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