stereoplay
diff 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 diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/vid.c Sun Mar 06 20:31:18 2011 +0200 1.3 @@ -0,0 +1,157 @@ 1.4 +#include <stdio.h> 1.5 +#include <libavcodec/avcodec.h> 1.6 +#include <libavformat/avformat.h> 1.7 +#include <libswscale/swscale.h> 1.8 +#include "vid.h" 1.9 + 1.10 +struct video_file { 1.11 + AVFormatContext *avctx; 1.12 + AVCodecContext *cctx; 1.13 + AVCodec *codec; 1.14 + int vstream, audio_stream; 1.15 + struct SwsContext *sws; 1.16 + 1.17 + AVFrame *frm, *rgbfrm; 1.18 +}; 1.19 + 1.20 +struct video_file *vid_open(const char *fname) 1.21 +{ 1.22 + static int initialized; 1.23 + struct video_file *vf; 1.24 + int i; 1.25 + 1.26 + if(!initialized) { 1.27 + av_register_all(); 1.28 + initialized = 1; 1.29 + } 1.30 + 1.31 + if(!(vf = malloc(sizeof *vf))) { 1.32 + fprintf(stderr, "open_video(%s): failed to allocate memory: %s\n", fname, strerror(errno)); 1.33 + return 0; 1.34 + } 1.35 + memset(vf, 0, sizeof *vf); 1.36 + 1.37 + if(av_open_input_file(&vf->avctx, fname, 0, 0, 0) != 0) { 1.38 + fprintf(stderr, "open_video(%s): failed to open file\n", fname); 1.39 + vid_close(vf); 1.40 + return 0; 1.41 + } 1.42 + 1.43 + if(av_find_stream_info(vf->avctx) < 0) { 1.44 + fprintf(stderr, "open_video(%s): failed to find stream info\n", fname); 1.45 + vid_close(vf); 1.46 + return 0; 1.47 + } 1.48 + 1.49 + vf->vstream = -1; 1.50 + for(i=0; i<vf->avctx->nb_streams; i++) { 1.51 + if(vf->avctx->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO) { 1.52 + vf->vstream = i; 1.53 + break; 1.54 + } 1.55 + } 1.56 + if(vf->vstream == -1) { 1.57 + fprintf(stderr, "open_video(%s): didn't find a video stream\n", fname); 1.58 + vid_close(vf); 1.59 + return 0; 1.60 + } 1.61 + vf->cctx = vf->avctx->streams[vf->vstream]->codec; 1.62 + 1.63 + if(!(vf->codec = avcodec_find_decoder(vf->cctx->codec_id))) { 1.64 + fprintf(stderr, "open_video(%s): unsupported codec\n", fname); 1.65 + vid_close(vf); 1.66 + return 0; 1.67 + } 1.68 + 1.69 + if(avcodec_open(vf->cctx, vf->codec) < 0) { 1.70 + fprintf(stderr, "open_video(%s): failed to open codec\n", fname); 1.71 + vid_close(vf); 1.72 + return 0; 1.73 + } 1.74 + 1.75 + if(!(vf->frm = avcodec_alloc_frame()) || !(vf->rgbfrm = avcodec_alloc_frame())) { 1.76 + fprintf(stderr, "open_video(%s): failed to allocate frame\n", fname); 1.77 + vid_close(vf); 1.78 + return 0; 1.79 + } 1.80 + 1.81 + vf->sws = sws_getContext(vf->cctx->width, vf->cctx->height, vf->cctx->pix_fmt, 1.82 + vf->cctx->width, vf->cctx->height, PIX_FMT_RGB32, SWS_POINT, 0, 0, 0); 1.83 + if(!vf->sws) { 1.84 + fprintf(stderr, "open_video(%s): failed to allocate sws context\n", fname); 1.85 + vid_close(vf); 1.86 + return 0; 1.87 + } 1.88 + 1.89 + 1.90 + printf("using codec: %s\n", vf->codec->name); 1.91 + printf("fps: %f (%u usec frame interval)\n", vid_fps(vf), vid_frame_interval(vf)); 1.92 + printf("size: %dx%d\n", vid_frame_width(vf), vid_frame_height(vf)); 1.93 + 1.94 + return vf; 1.95 +} 1.96 + 1.97 +void vid_close(struct video_file *vf) 1.98 +{ 1.99 + if(!vf) return; 1.100 + 1.101 + /* TODO how do we deallocate sws contexts? */ 1.102 + if(vf->rgbfrm) av_free(vf->rgbfrm); 1.103 + if(vf->frm) av_free(vf->frm); 1.104 + if(vf->cctx) avcodec_close(vf->cctx); 1.105 + if(vf->avctx) av_close_input_file(vf->avctx); 1.106 + free(vf); 1.107 +} 1.108 + 1.109 + 1.110 +float vid_fps(struct video_file *vf) 1.111 +{ 1.112 + float inv_tb = (float)vf->cctx->time_base.den / (float)vf->cctx->time_base.num; 1.113 + return inv_tb / (float)vf->cctx->ticks_per_frame; 1.114 +} 1.115 + 1.116 +unsigned int vid_frame_interval(struct video_file *vf) 1.117 +{ 1.118 + float fps = vid_fps(vf); 1.119 + return 1000000 / fps; 1.120 +} 1.121 + 1.122 +int vid_frame_width(struct video_file *vf) 1.123 +{ 1.124 + return vf->cctx->width; 1.125 +} 1.126 + 1.127 +int vid_frame_height(struct video_file *vf) 1.128 +{ 1.129 + return vf->cctx->height; 1.130 +} 1.131 + 1.132 +size_t vid_frame_size(struct video_file *vf) 1.133 +{ 1.134 + return vf->cctx->width * vf->cctx->height * 4; 1.135 +} 1.136 + 1.137 +int vid_get_frame(struct video_file *vf, uint32_t *img) 1.138 +{ 1.139 + AVPacket packet; 1.140 + int frame_done = 0; 1.141 + AVPicture *rgbfrm = (AVPicture*)vf->rgbfrm; 1.142 + AVPicture *frm = (AVPicture*)vf->frm; 1.143 + 1.144 + avpicture_fill((AVPicture*)vf->rgbfrm, (uint8_t*)img, PIX_FMT_RGB32, vf->cctx->width, vf->cctx->height); 1.145 + 1.146 + while(av_read_frame(vf->avctx, &packet) >= 0) { 1.147 + if(packet.stream_index == vf->vstream) { 1.148 + avcodec_decode_video2(vf->cctx, vf->frm, &frame_done, &packet); 1.149 + 1.150 + if(frame_done) { 1.151 + sws_scale(vf->sws, frm->data, frm->linesize, 0, vf->cctx->height, rgbfrm->data, rgbfrm->linesize); 1.152 + av_free_packet(&packet); 1.153 + return 0; 1.154 + } 1.155 + } 1.156 + av_free_packet(&packet); 1.157 + } 1.158 + 1.159 + return -1; 1.160 +}