stereoplay

annotate src/vid.c @ 0:265a24704ff2

stereoplay
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 06 Mar 2011 20:31:18 +0200
parents
children fd671d488cfd
rev   line source
nuclear@0 1 #include <stdio.h>
nuclear@0 2 #include <libavcodec/avcodec.h>
nuclear@0 3 #include <libavformat/avformat.h>
nuclear@0 4 #include <libswscale/swscale.h>
nuclear@0 5 #include "vid.h"
nuclear@0 6
nuclear@0 7 struct video_file {
nuclear@0 8 AVFormatContext *avctx;
nuclear@0 9 AVCodecContext *cctx;
nuclear@0 10 AVCodec *codec;
nuclear@0 11 int vstream, audio_stream;
nuclear@0 12 struct SwsContext *sws;
nuclear@0 13
nuclear@0 14 AVFrame *frm, *rgbfrm;
nuclear@0 15 };
nuclear@0 16
nuclear@0 17 struct video_file *vid_open(const char *fname)
nuclear@0 18 {
nuclear@0 19 static int initialized;
nuclear@0 20 struct video_file *vf;
nuclear@0 21 int i;
nuclear@0 22
nuclear@0 23 if(!initialized) {
nuclear@0 24 av_register_all();
nuclear@0 25 initialized = 1;
nuclear@0 26 }
nuclear@0 27
nuclear@0 28 if(!(vf = malloc(sizeof *vf))) {
nuclear@0 29 fprintf(stderr, "open_video(%s): failed to allocate memory: %s\n", fname, strerror(errno));
nuclear@0 30 return 0;
nuclear@0 31 }
nuclear@0 32 memset(vf, 0, sizeof *vf);
nuclear@0 33
nuclear@0 34 if(av_open_input_file(&vf->avctx, fname, 0, 0, 0) != 0) {
nuclear@0 35 fprintf(stderr, "open_video(%s): failed to open file\n", fname);
nuclear@0 36 vid_close(vf);
nuclear@0 37 return 0;
nuclear@0 38 }
nuclear@0 39
nuclear@0 40 if(av_find_stream_info(vf->avctx) < 0) {
nuclear@0 41 fprintf(stderr, "open_video(%s): failed to find stream info\n", fname);
nuclear@0 42 vid_close(vf);
nuclear@0 43 return 0;
nuclear@0 44 }
nuclear@0 45
nuclear@0 46 vf->vstream = -1;
nuclear@0 47 for(i=0; i<vf->avctx->nb_streams; i++) {
nuclear@0 48 if(vf->avctx->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO) {
nuclear@0 49 vf->vstream = i;
nuclear@0 50 break;
nuclear@0 51 }
nuclear@0 52 }
nuclear@0 53 if(vf->vstream == -1) {
nuclear@0 54 fprintf(stderr, "open_video(%s): didn't find a video stream\n", fname);
nuclear@0 55 vid_close(vf);
nuclear@0 56 return 0;
nuclear@0 57 }
nuclear@0 58 vf->cctx = vf->avctx->streams[vf->vstream]->codec;
nuclear@0 59
nuclear@0 60 if(!(vf->codec = avcodec_find_decoder(vf->cctx->codec_id))) {
nuclear@0 61 fprintf(stderr, "open_video(%s): unsupported codec\n", fname);
nuclear@0 62 vid_close(vf);
nuclear@0 63 return 0;
nuclear@0 64 }
nuclear@0 65
nuclear@0 66 if(avcodec_open(vf->cctx, vf->codec) < 0) {
nuclear@0 67 fprintf(stderr, "open_video(%s): failed to open codec\n", fname);
nuclear@0 68 vid_close(vf);
nuclear@0 69 return 0;
nuclear@0 70 }
nuclear@0 71
nuclear@0 72 if(!(vf->frm = avcodec_alloc_frame()) || !(vf->rgbfrm = avcodec_alloc_frame())) {
nuclear@0 73 fprintf(stderr, "open_video(%s): failed to allocate frame\n", fname);
nuclear@0 74 vid_close(vf);
nuclear@0 75 return 0;
nuclear@0 76 }
nuclear@0 77
nuclear@0 78 vf->sws = sws_getContext(vf->cctx->width, vf->cctx->height, vf->cctx->pix_fmt,
nuclear@0 79 vf->cctx->width, vf->cctx->height, PIX_FMT_RGB32, SWS_POINT, 0, 0, 0);
nuclear@0 80 if(!vf->sws) {
nuclear@0 81 fprintf(stderr, "open_video(%s): failed to allocate sws context\n", fname);
nuclear@0 82 vid_close(vf);
nuclear@0 83 return 0;
nuclear@0 84 }
nuclear@0 85
nuclear@0 86
nuclear@0 87 printf("using codec: %s\n", vf->codec->name);
nuclear@0 88 printf("fps: %f (%u usec frame interval)\n", vid_fps(vf), vid_frame_interval(vf));
nuclear@0 89 printf("size: %dx%d\n", vid_frame_width(vf), vid_frame_height(vf));
nuclear@0 90
nuclear@0 91 return vf;
nuclear@0 92 }
nuclear@0 93
nuclear@0 94 void vid_close(struct video_file *vf)
nuclear@0 95 {
nuclear@0 96 if(!vf) return;
nuclear@0 97
nuclear@0 98 /* TODO how do we deallocate sws contexts? */
nuclear@0 99 if(vf->rgbfrm) av_free(vf->rgbfrm);
nuclear@0 100 if(vf->frm) av_free(vf->frm);
nuclear@0 101 if(vf->cctx) avcodec_close(vf->cctx);
nuclear@0 102 if(vf->avctx) av_close_input_file(vf->avctx);
nuclear@0 103 free(vf);
nuclear@0 104 }
nuclear@0 105
nuclear@0 106
nuclear@0 107 float vid_fps(struct video_file *vf)
nuclear@0 108 {
nuclear@0 109 float inv_tb = (float)vf->cctx->time_base.den / (float)vf->cctx->time_base.num;
nuclear@0 110 return inv_tb / (float)vf->cctx->ticks_per_frame;
nuclear@0 111 }
nuclear@0 112
nuclear@0 113 unsigned int vid_frame_interval(struct video_file *vf)
nuclear@0 114 {
nuclear@0 115 float fps = vid_fps(vf);
nuclear@0 116 return 1000000 / fps;
nuclear@0 117 }
nuclear@0 118
nuclear@0 119 int vid_frame_width(struct video_file *vf)
nuclear@0 120 {
nuclear@0 121 return vf->cctx->width;
nuclear@0 122 }
nuclear@0 123
nuclear@0 124 int vid_frame_height(struct video_file *vf)
nuclear@0 125 {
nuclear@0 126 return vf->cctx->height;
nuclear@0 127 }
nuclear@0 128
nuclear@0 129 size_t vid_frame_size(struct video_file *vf)
nuclear@0 130 {
nuclear@0 131 return vf->cctx->width * vf->cctx->height * 4;
nuclear@0 132 }
nuclear@0 133
nuclear@0 134 int vid_get_frame(struct video_file *vf, uint32_t *img)
nuclear@0 135 {
nuclear@0 136 AVPacket packet;
nuclear@0 137 int frame_done = 0;
nuclear@0 138 AVPicture *rgbfrm = (AVPicture*)vf->rgbfrm;
nuclear@0 139 AVPicture *frm = (AVPicture*)vf->frm;
nuclear@0 140
nuclear@0 141 avpicture_fill((AVPicture*)vf->rgbfrm, (uint8_t*)img, PIX_FMT_RGB32, vf->cctx->width, vf->cctx->height);
nuclear@0 142
nuclear@0 143 while(av_read_frame(vf->avctx, &packet) >= 0) {
nuclear@0 144 if(packet.stream_index == vf->vstream) {
nuclear@0 145 avcodec_decode_video2(vf->cctx, vf->frm, &frame_done, &packet);
nuclear@0 146
nuclear@0 147 if(frame_done) {
nuclear@0 148 sws_scale(vf->sws, frm->data, frm->linesize, 0, vf->cctx->height, rgbfrm->data, rgbfrm->linesize);
nuclear@0 149 av_free_packet(&packet);
nuclear@0 150 return 0;
nuclear@0 151 }
nuclear@0 152 }
nuclear@0 153 av_free_packet(&packet);
nuclear@0 154 }
nuclear@0 155
nuclear@0 156 return -1;
nuclear@0 157 }