ubuntu10.4下编译ffmpeg教程---tutorial05.c

首先需要ubuntu下编译ffmpeg0.8. ffmpeg0.8是当下最新的版本.(如何编译网上很多资料哈)
对于 http://dranger.com/ffmpeg/ffmpeg.html教程的ffmpeg,tutorial05.c就需要修改

这里做个记录:
1, 方法img_convert不再使用, sws_scale代替之
需要新增加#include <ffmpeg/swscale.h>.编译时增加编译条件  -lswscale
需要在struct VideoState中新增加struct SwsContext *img_convert_ctx,并初始化此参数
2, avcodec_decode_video方法过时,修改为avcodec_decode_video2, avcodec_decode_audio2方法过时,修改为avcodec_decode_audio3
注意更改后的参数变化
3, dump_format方法过时,更改为 av_dump_format. 不更改不会编译报错,程序能够正常运行.但是会告警
4, av_open_input_file此方法过时,但是不可更改,仅仅编译告警. 如根据ffmpeg源代码,修改为新方法后, 则编译无告警且正常通过后.但是运行时会莫名报段错误(Segmentation fault)


以下代码在ubuntu10.4下编译通过,并正常运行

gcc -o tutorial05 tutorial05.c -lavformat -lavcodec -lswscale -lz -lm `sdl-config --cflags --libs`

Java代码   收藏代码
  1. // tutorial05.c  
  2. // A pedagogical video player that really works!  
  3. //  
  4. // Code based on FFplay, Copyright (c) 2003 Fabrice Bellard,   
  5. // and a tutorial by Martin Bohme (boehme@inb.uni-luebeckREMOVETHIS.de)  
  6. // Tested on Gentoo, CVS version 5/01/07 compiled with GCC 4.1.1  
  7. // Use  
  8. //  
  9. // gcc -o tutorial05 tutorial05.c -lavformat -lavcodec -lswscale -lz -lm `sdl-config --cflags --libs`  
  10. // to build (assuming libavformat and libavcodec are correctly installed,   
  11. // and assuming you have sdl-config. Please refer to SDL docs for your installation.)  
  12. //  
  13. // Run using  
  14. // tutorial05 myvideofile.mpg  
  15. //  
  16. // to play the video.  
  17.   
  18. #include <ffmpeg/avcodec.h>  
  19. #include <ffmpeg/avformat.h>  
  20. #include <ffmpeg/swscale.h>  
  21.   
  22. #include <SDL.h>  
  23. #include <SDL_thread.h>  
  24.   
  25. #ifdef __MINGW32__  
  26. #undef main /* Prevents SDL from overriding main() */  
  27. #endif  
  28.   
  29. #include <stdio.h>  
  30. #include <math.h>  
  31.   
  32. #define SDL_AUDIO_BUFFER_SIZE 1024  
  33.   
  34. #define MAX_AUDIOQ_SIZE (5 * 16 * 1024)  
  35. #define MAX_VIDEOQ_SIZE (5 * 256 * 1024)  
  36.   
  37. #define AV_SYNC_THRESHOLD 0.01  
  38. #define AV_NOSYNC_THRESHOLD 10.0  
  39.   
  40. #define FF_ALLOC_EVENT   (SDL_USEREVENT)  
  41. #define FF_REFRESH_EVENT (SDL_USEREVENT + 1)  
  42. #define FF_QUIT_EVENT (SDL_USEREVENT + 2)  
  43.   
  44. #define VIDEO_PICTURE_QUEUE_SIZE 1  
  45.   
  46. typedef struct PacketQueue {  
  47.   AVPacketList *first_pkt, *last_pkt;  
  48.   int nb_packets;  
  49.   int size;  
  50.   SDL_mutex *mutex;  
  51.   SDL_cond *cond;  
  52. } PacketQueue;  
  53.   
  54.   
  55. typedef struct VideoPicture {  
  56.   SDL_Overlay *bmp;  
  57.   int width, height; /* source height & width */  
  58.   int allocated;  
  59.   double pts;  
  60. } VideoPicture;  
  61.   
  62. typedef struct VideoState {  
  63.   
  64.   AVFormatContext *pFormatCtx;  
  65.   int             videoStream, audioStream;  
  66.   
  67.   double          audio_clock;  
  68.   AVStream        *audio_st;  
  69.   PacketQueue     audioq;  
  70.   uint8_t         audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];  
  71.   unsigned int    audio_buf_size;  
  72.   unsigned int    audio_buf_index;  
  73.   AVPacket        audio_pkt;  
  74.   uint8_t         *audio_pkt_data;  
  75.   int             audio_pkt_size;  
  76.   int             audio_hw_buf_size;    
  77.   double          frame_timer;  
  78.   double          frame_last_pts;  
  79.   double          frame_last_delay;  
  80.   double          video_clock; ///<pts of last decoded frame / predicted pts of next decoded frame  
  81.   AVStream        *video_st;  
  82.   PacketQueue     videoq;  
  83.   
  84.   VideoPicture    pictq[VIDEO_PICTURE_QUEUE_SIZE];  
  85.   int             pictq_size, pictq_rindex, pictq_windex;  
  86.   SDL_mutex       *pictq_mutex;  
  87.   SDL_cond        *pictq_cond;  
  88.     
  89.   SDL_Thread      *parse_tid;  
  90.   SDL_Thread      *video_tid;  
  91.   
  92.   char            filename[1024];  
  93.   int             quit;  
  94.   struct SwsContext *img_convert_ctx;  
  95.     
  96. } VideoState;  
  97.   
  98. SDL_Surface     *screen;  
  99.   
  100. /* Since we only have one decoding thread, the Big Struct 
  101.    can be global in case we need it. */  
  102. VideoState *global_video_state;  
  103.   
  104. void packet_queue_init(PacketQueue *q) {  
  105.   memset(q, 0, sizeof(PacketQueue));  
  106.   q->mutex = SDL_CreateMutex();  
  107.   q->cond = SDL_CreateCond();  
  108. }  
  109. int packet_queue_put(PacketQueue *q, AVPacket *pkt) {  
  110.   
  111.   AVPacketList *pkt1;  
  112.   if(av_dup_packet(pkt) < 0) {  
  113.     return -1;  
  114.   }  
  115.   pkt1 = av_malloc(sizeof(AVPacketList));  
  116.   if (!pkt1)  
  117.     return -1;  
  118.   pkt1->pkt = *pkt;  
  119.   pkt1->next = NULL;  
  120.     
  121.   SDL_LockMutex(q->mutex);  
  122.   
  123.   if (!q->last_pkt)  
  124.     q->first_pkt = pkt1;  
  125.   else  
  126.     q->last_pkt->next = pkt1;  
  127.   q->last_pkt = pkt1;  
  128.   q->nb_packets++;  
  129.   q->size += pkt1->pkt.size;  
  130.   SDL_CondSignal(q->cond);  
  131.     
  132.   SDL_UnlockMutex(q->mutex);  
  133.   return 0;  
  134. }  
  135. static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)  
  136. {  
  137.   AVPacketList *pkt1;  
  138.   int ret;  
  139.   
  140.   SDL_LockMutex(q->mutex);  
  141.     
  142.   for(;;) {  
  143.       
  144.     if(global_video_state->quit) {  
  145.       ret = -1;  
  146.       break;  
  147.     }  
  148.   
  149.     pkt1 = q->first_pkt;  
  150.     if (pkt1) {  
  151.       q->first_pkt = pkt1->next;  
  152.       if (!q->first_pkt)  
  153.     q->last_pkt = NULL;  
  154.       q->nb_packets--;  
  155.       q->size -= pkt1->pkt.size;  
  156.       *pkt = pkt1->pkt;  
  157.       av_free(pkt1);  
  158.       ret = 1;  
  159.       break;  
  160.     } else if (!block) {  
  161.       ret = 0;  
  162.       break;  
  163.     } else {  
  164.       SDL_CondWait(q->cond, q->mutex);  
  165.     }  
  166.   }  
  167.   SDL_UnlockMutex(q->mutex);  
  168.   return ret;  
  169. }  
  170. double get_audio_clock(VideoState *is) {  
  171.   double pts;  
  172.   int hw_buf_size, bytes_per_sec, n;  
  173.     
  174.   pts = is->audio_clock; /* maintained in the audio thread */  
  175.   hw_buf_size = is->audio_buf_size - is->audio_buf_index;  
  176.   bytes_per_sec = 0;  
  177.   n = is->audio_st->codec->channels * 2;  
  178.   if(is->audio_st) {  
  179.     bytes_per_sec = is->audio_st->codec->sample_rate * n;  
  180.   }  
  181.   if(bytes_per_sec) {  
  182.     pts -= (double)hw_buf_size / bytes_per_sec;  
  183.   }  
  184.   return pts;  
  185. }  
  186.   
  187. int audio_decode_frame(VideoState *is, uint8_t *audio_buf, int buf_size, double *pts_ptr) {  
  188.   
  189.   int len1, data_size, n;  
  190.   AVPacket *pkt = &is->audio_pkt;  
  191.   double pts;  
  192.   
  193.   for(;;) {  
  194.     while(is->audio_pkt_size > 0) {  
  195.       data_size = buf_size;  
  196.       len1 = avcodec_decode_audio3(is->audio_st->codec,   
  197.                   (int16_t *)audio_buf, &data_size,   
  198.                   pkt);  
  199.       if(len1 < 0) {  
  200.     /* if error, skip frame */  
  201.     is->audio_pkt_size = 0;  
  202.     break;  
  203.       }  
  204.       is->audio_pkt_data += len1;  
  205.       is->audio_pkt_size -= len1;  
  206.       if(data_size <= 0) {  
  207.     /* No data yet, get more frames */  
  208.     continue;  
  209.       }  
  210.       pts = is->audio_clock;  
  211.       *pts_ptr = pts;  
  212.       n = 2 * is->audio_st->codec->channels;  
  213.       is->audio_clock += (double)data_size /  
  214.     (double)(n * is->audio_st->codec->sample_rate);  
  215.   
  216.       /* We have data, return it and come back for more later */  
  217.       return data_size;  
  218.     }  
  219.     if(pkt->data)  
  220.       av_free_packet(pkt);  
  221.   
  222.     if(is->quit) {  
  223.       return -1;  
  224.     }  
  225.     /* next packet */  
  226.     if(packet_queue_get(&is->audioq, pkt, 1) < 0) {  
  227.       return -1;  
  228.     }  
  229.     is->audio_pkt_data = pkt->data;  
  230.     is->audio_pkt_size = pkt->size;  
  231.     /* if update, update the audio clock w/pts */  
  232.     if(pkt->pts != AV_NOPTS_VALUE) {  
  233.       is->audio_clock = av_q2d(is->audio_st->time_base)*pkt->pts;  
  234.     }  
  235.   
  236.   }  
  237. }  
  238.   
  239. void audio_callback(void *userdata, Uint8 *stream, int len) {  
  240.   
  241.   VideoState *is = (VideoState *)userdata;  
  242.   int len1, audio_size;  
  243.   double pts;  
  244.   
  245.   while(len > 0) {  
  246.     if(is->audio_buf_index >= is->audio_buf_size) {  
  247.       /* We have already sent all our data; get more */  
  248.       audio_size = audio_decode_frame(is, is->audio_buf, sizeof(is->audio_buf), &pts);  
  249.       if(audio_size < 0) {  
  250.     /* If error, output silence */  
  251.     is->audio_buf_size = 1024;  
  252.     memset(is->audio_buf, 0, is->audio_buf_size);  
  253.       } else {  
  254.     is->audio_buf_size = audio_size;  
  255.       }  
  256.       is->audio_buf_index = 0;  
  257.     }  
  258.     len1 = is->audio_buf_size - is->audio_buf_index;  
  259.     if(len1 > len)  
  260.       len1 = len;  
  261.     memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);  
  262.     len -= len1;  
  263.     stream += len1;  
  264.     is->audio_buf_index += len1;  
  265.   }  
  266. }  
  267.   
  268. static Uint32 sdl_refresh_timer_cb(Uint32 interval, void *opaque) {  
  269.   SDL_Event event;  
  270.   event.type = FF_REFRESH_EVENT;  
  271.   event.user.data1 = opaque;  
  272.   SDL_PushEvent(&event);  
  273.   return 0/* 0 means stop timer */  
  274. }  
  275.   
  276. /* schedule a video refresh in 'delay' ms */  
  277. static void schedule_refresh(VideoState *is, int delay) {  
  278.   SDL_AddTimer(delay, sdl_refresh_timer_cb, is);  
  279. }  
  280.   
  281. void video_display(VideoState *is) {  
  282.   
  283.   SDL_Rect rect;  
  284.   VideoPicture *vp;  
  285.   AVPicture pict;  
  286.   float aspect_ratio;  
  287.   int w, h, x, y;  
  288.   int i;  
  289.   
  290.   vp = &is->pictq[is->pictq_rindex];  
  291.   if(vp->bmp) {  
  292.     if(is->video_st->codec->sample_aspect_ratio.num == 0) {  
  293.       aspect_ratio = 0;  
  294.     } else {  
  295.       aspect_ratio = av_q2d(is->video_st->codec->sample_aspect_ratio) *  
  296.     is->video_st->codec->width / is->video_st->codec->height;  
  297.     }  
  298.     if(aspect_ratio <= 0.0) {  
  299.       aspect_ratio = (float)is->video_st->codec->width /  
  300.     (float)is->video_st->codec->height;  
  301.     }  
  302.     h = screen->h;  
  303.     w = ((int)rint(h * aspect_ratio)) & -3;  
  304.     if(w > screen->w) {  
  305.       w = screen->w;  
  306.       h = ((int)rint(w / aspect_ratio)) & -3;  
  307.     }  
  308.     x = (screen->w - w) / 2;  
  309.     y = (screen->h - h) / 2;  
  310.       
  311.     rect.x = x;  
  312.     rect.y = y;  
  313.     rect.w = w;  
  314.     rect.h = h;  
  315.     SDL_DisplayYUVOverlay(vp->bmp, &rect);  
  316.   }  
  317. }  
  318.   
  319. void video_refresh_timer(void *userdata) {  
  320.   
  321.   VideoState *is = (VideoState *)userdata;  
  322.   VideoPicture *vp;  
  323.   double actual_delay, delay, sync_threshold, ref_clock, diff;  
  324.     
  325.   if(is->video_st) {  
  326.     if(is->pictq_size == 0) {  
  327.       schedule_refresh(is, 1);  
  328.     } else {  
  329.       vp = &is->pictq[is->pictq_rindex];  
  330.   
  331.       delay = vp->pts - is->frame_last_pts; /* the pts from last time */  
  332.       if(delay <= 0 || delay >= 1.0) {  
  333.     /* if incorrect delay, use previous one */  
  334.     delay = is->frame_last_delay;  
  335.       }  
  336.       /* save for next time */  
  337.       is->frame_last_delay = delay;  
  338.       is->frame_last_pts = vp->pts;  
  339.   
  340.       /* update delay to sync to audio */  
  341.       ref_clock = get_audio_clock(is);  
  342.       diff = vp->pts - ref_clock;  
  343.   
  344.       /* Skip or repeat the frame. Take delay into account 
  345.      FFPlay still doesn't "know if this is the best guess." */  
  346.       sync_threshold = (delay > AV_SYNC_THRESHOLD) ? delay : AV_SYNC_THRESHOLD;  
  347.       if(fabs(diff) < AV_NOSYNC_THRESHOLD) {  
  348.     if(diff <= -sync_threshold) {  
  349.       delay = 0;  
  350.     } else if(diff >= sync_threshold) {  
  351.       delay = 2 * delay;  
  352.     }  
  353.       }  
  354.       is->frame_timer += delay;  
  355.       /* computer the REAL delay */  
  356.       actual_delay = is->frame_timer - (av_gettime() / 1000000.0);  
  357.       if(actual_delay < 0.010) {  
  358.     /* Really it should skip the picture instead */  
  359.     actual_delay = 0.010;  
  360.       }  
  361.       schedule_refresh(is, (int)(actual_delay * 1000 + 0.5));  
  362.       /* show the picture! */  
  363.       video_display(is);  
  364.         
  365.       /* update queue for next picture! */  
  366.       if(++is->pictq_rindex == VIDEO_PICTURE_QUEUE_SIZE) {  
  367.     is->pictq_rindex = 0;  
  368.       }  
  369.       SDL_LockMutex(is->pictq_mutex);  
  370.       is->pictq_size--;  
  371.       SDL_CondSignal(is->pictq_cond);  
  372.       SDL_UnlockMutex(is->pictq_mutex);  
  373.     }  
  374.   } else {  
  375.     schedule_refresh(is, 100);  
  376.   }  
  377. }  
  378.         
  379. void alloc_picture(void *userdata) {  
  380.   
  381.   VideoState *is = (VideoState *)userdata;  
  382.   VideoPicture *vp;  
  383.   
  384.   vp = &is->pictq[is->pictq_windex];  
  385.   if(vp->bmp) {  
  386.     // we already have one make another, bigger/smaller  
  387.     SDL_FreeYUVOverlay(vp->bmp);  
  388.   }  
  389.   // Allocate a place to put our YUV image on that screen  
  390.   vp->bmp = SDL_CreateYUVOverlay(is->video_st->codec->width,  
  391.                  is->video_st->codec->height,  
  392.                  SDL_YV12_OVERLAY,  
  393.                  screen);  
  394.   
  395.   vp->width = is->video_st->codec->width;  
  396.   vp->height = is->video_st->codec->height;  
  397.   
  398.   is->img_convert_ctx = sws_getContext(is->video_st->codec->width, is->video_st->codec->height,  
  399.         is->video_st->codec->pix_fmt, is->video_st->codec->width, is->video_st->codec->height,  
  400.         PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);  
  401.     
  402.   SDL_LockMutex(is->pictq_mutex);  
  403.   vp->allocated = 1;  
  404.   SDL_CondSignal(is->pictq_cond);  
  405.   SDL_UnlockMutex(is->pictq_mutex);  
  406.   
  407. }  
  408.   
  409. int queue_picture(VideoState *is, AVFrame *pFrame, double pts) {  
  410.   
  411.   VideoPicture *vp;  
  412.   int dst_pix_fmt;  
  413.   AVPicture pict;  
  414.   
  415.   /* wait until we have space for a new pic */  
  416.   SDL_LockMutex(is->pictq_mutex);  
  417.   while(is->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE &&  
  418.     !is->quit) {  
  419.     SDL_CondWait(is->pictq_cond, is->pictq_mutex);  
  420.   }  
  421.   SDL_UnlockMutex(is->pictq_mutex);  
  422.   
  423.   if(is->quit)  
  424.     return -1;  
  425.   
  426.   // windex is set to 0 initially  
  427.   vp = &is->pictq[is->pictq_windex];  
  428.   
  429.   /* allocate or resize the buffer! */  
  430.   if(!vp->bmp ||  
  431.      vp->width != is->video_st->codec->width ||  
  432.      vp->height != is->video_st->codec->height) {  
  433.     SDL_Event event;  
  434.   
  435.     vp->allocated = 0;  
  436.     /* we have to do it in the main thread */  
  437.     event.type = FF_ALLOC_EVENT;  
  438.     event.user.data1 = is;  
  439.     SDL_PushEvent(&event);  
  440.   
  441.     /* wait until we have a picture allocated */  
  442.     SDL_LockMutex(is->pictq_mutex);  
  443.     while(!vp->allocated && !is->quit) {  
  444.       SDL_CondWait(is->pictq_cond, is->pictq_mutex);  
  445.     }  
  446.     SDL_UnlockMutex(is->pictq_mutex);  
  447.     if(is->quit) {  
  448.       return -1;  
  449.     }  
  450.   }  
  451.   /* We have a place to put our picture on the queue */  
  452.   /* If we are skipping a frame, do we set this to null  
  453.      but still return vp->allocated = 1? */  
  454.   
  455.   
  456.   if(vp->bmp) {  
  457.   
  458.     SDL_LockYUVOverlay(vp->bmp);  
  459.       
  460.     dst_pix_fmt = PIX_FMT_YUV420P;  
  461.     /* point pict at the queue */  
  462.   
  463.     pict.data[0] = vp->bmp->pixels[0];  
  464.     pict.data[1] = vp->bmp->pixels[2];  
  465.     pict.data[2] = vp->bmp->pixels[1];  
  466.       
  467.     pict.linesize[0] = vp->bmp->pitches[0];  
  468.     pict.linesize[1] = vp->bmp->pitches[2];  
  469.     pict.linesize[2] = vp->bmp->pitches[1];  
  470.       
  471.     // Convert the image into YUV format that SDL uses  
  472.     //img_convert(&pict, dst_pix_fmt,  
  473.     //      (AVPicture *)pFrame, is->video_st->codec->pix_fmt,   
  474.     //      is->video_st->codec->width, is->video_st->codec->height);  
  475.   
  476.     sws_scale(is->img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize,  
  477.               0,is->video_st->codec->height, pict.data, pict.linesize);  
  478.       
  479.     SDL_UnlockYUVOverlay(vp->bmp);  
  480.     vp->pts = pts;  
  481.   
  482.     /* now we inform our display thread that we have a pic ready */  
  483.     if(++is->pictq_windex == VIDEO_PICTURE_QUEUE_SIZE) {  
  484.       is->pictq_windex = 0;  
  485.     }  
  486.     SDL_LockMutex(is->pictq_mutex);  
  487.     is->pictq_size++;  
  488.     SDL_UnlockMutex(is->pictq_mutex);  
  489.   }  
  490.   return 0;  
  491. }  
  492.   
  493. double synchronize_video(VideoState *is, AVFrame *src_frame, double pts) {  
  494.   
  495.   double frame_delay;  
  496.   
  497.   if(pts != 0) {  
  498.     /* if we have pts, set video clock to it */  
  499.     is->video_clock = pts;  
  500.   } else {  
  501.     /* if we aren't given a pts, set it to the clock */  
  502.     pts = is->video_clock;  
  503.   }  
  504.   /* update the video clock */  
  505.   frame_delay = av_q2d(is->video_st->codec->time_base);  
  506.   /* if we are repeating a frame, adjust clock accordingly */  
  507.   frame_delay += src_frame->repeat_pict * (frame_delay * 0.5);  
  508.   is->video_clock += frame_delay;  
  509.   return pts;  
  510. }  
  511. uint64_t global_video_pkt_pts = AV_NOPTS_VALUE;  
  512.   
  513. /* These are called whenever we allocate a frame 
  514.  * buffer. We use this to store the global_pts in 
  515.  * a frame at the time it is allocated. 
  516.  */  
  517. int our_get_buffer(struct AVCodecContext *c, AVFrame *pic) {  
  518.   int ret = avcodec_default_get_buffer(c, pic);  
  519.   uint64_t *pts = av_malloc(sizeof(uint64_t));  
  520.   *pts = global_video_pkt_pts;  
  521.   pic->opaque = pts;  
  522.   return ret;  
  523. }  
  524. void our_release_buffer(struct AVCodecContext *c, AVFrame *pic) {  
  525.   if(pic) av_freep(&pic->opaque);  
  526.   avcodec_default_release_buffer(c, pic);  
  527. }  
  528.   
  529. int video_thread(void *arg) {  
  530.   VideoState *is = (VideoState *)arg;  
  531.   AVPacket pkt1, *packet = &pkt1;  
  532.   int len1, frameFinished;  
  533.   AVFrame *pFrame;  
  534.   double pts;  
  535.   
  536.   pFrame = avcodec_alloc_frame();  
  537.   
  538.   for(;;) {  
  539.     if(packet_queue_get(&is->videoq, packet, 1) < 0) {  
  540.       // means we quit getting packets  
  541.       break;  
  542.     }  
  543.     pts = 0;  
  544.   
  545.     // Save global pts to be stored in pFrame in first call  
  546.     global_video_pkt_pts = packet->pts;  
  547.     // Decode video frame  
  548.     len1 = avcodec_decode_video2(is->video_st->codec, pFrame, &frameFinished,   
  549.                 packet);  
  550.     if(packet->dts == AV_NOPTS_VALUE   
  551.        && pFrame->opaque && *(uint64_t*)pFrame->opaque != AV_NOPTS_VALUE) {  
  552.       pts = *(uint64_t *)pFrame->opaque;  
  553.     } else if(packet->dts != AV_NOPTS_VALUE) {  
  554.       pts = packet->dts;  
  555.     } else {  
  556.       pts = 0;  
  557.     }  
  558.     pts *= av_q2d(is->video_st->time_base);  
  559.   
  560.     // Did we get a video frame?  
  561.     if(frameFinished) {  
  562.       pts = synchronize_video(is, pFrame, pts);  
  563.       if(queue_picture(is, pFrame, pts) < 0) {  
  564.     break;  
  565.       }  
  566.     }  
  567.     av_free_packet(packet);  
  568.   }  
  569.   av_free(pFrame);  
  570.   return 0;  
  571. }  
  572.   
  573. int stream_component_open(VideoState *is, int stream_index) {  
  574.   
  575.   AVFormatContext *pFormatCtx = is->pFormatCtx;  
  576.   AVCodecContext *codecCtx;  
  577.   AVCodec *codec;  
  578.   SDL_AudioSpec wanted_spec, spec;  
  579.   
  580.   if(stream_index < 0 || stream_index >= pFormatCtx->nb_streams) {  
  581.     return -1;  
  582.   }  
  583.   
  584.   // Get a pointer to the codec context for the video stream  
  585.   codecCtx = pFormatCtx->streams[stream_index]->codec;  
  586.   
  587.   if(codecCtx->codec_type == AVMEDIA_TYPE_AUDIO) {  
  588.     // Set audio settings from codec info  
  589.     wanted_spec.freq = codecCtx->sample_rate;  
  590.     wanted_spec.format = AUDIO_S16SYS;  
  591.     wanted_spec.channels = codecCtx->channels;  
  592.     wanted_spec.silence = 0;  
  593.     wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;  
  594.     wanted_spec.callback = audio_callback;  
  595.     wanted_spec.userdata = is;  
  596.       
  597.     if(SDL_OpenAudio(&wanted_spec, &spec) < 0) {  
  598.       fprintf(stderr, "SDL_OpenAudio: %s\n", SDL_GetError());  
  599.       return -1;  
  600.     }  
  601.     is->audio_hw_buf_size = spec.size;  
  602.   }  
  603.   codec = avcodec_find_decoder(codecCtx->codec_id);  
  604.   
  605.   if(!codec || (avcodec_open(codecCtx, codec) < 0)) {  
  606.     fprintf(stderr, "Unsupported codec!\n");  
  607.     return -1;  
  608.   }  
  609.   
  610.   switch(codecCtx->codec_type) {  
  611.   case AVMEDIA_TYPE_AUDIO:  
  612.     is->audioStream = stream_index;  
  613.     is->audio_st = pFormatCtx->streams[stream_index];  
  614.     is->audio_buf_size = 0;  
  615.     is->audio_buf_index = 0;  
  616.     memset(&is->audio_pkt, 0, sizeof(is->audio_pkt));  
  617.     packet_queue_init(&is->audioq);  
  618.     SDL_PauseAudio(0);  
  619.     break;  
  620.   case AVMEDIA_TYPE_VIDEO:  
  621.     is->videoStream = stream_index;  
  622.     is->video_st = pFormatCtx->streams[stream_index];  
  623.   
  624.     is->frame_timer = (double)av_gettime() / 1000000.0;  
  625.     is->frame_last_delay = 40e-3;  
  626.   
  627.     packet_queue_init(&is->videoq);  
  628.     is->video_tid = SDL_CreateThread(video_thread, is);  
  629.     codecCtx->get_buffer = our_get_buffer;  
  630.     codecCtx->release_buffer = our_release_buffer;  
  631.     break;  
  632.   default:  
  633.     break;  
  634.   }  
  635.   
  636.   
  637. }  
  638.   
  639. int decode_interrupt_cb(void) {  
  640.   return (global_video_state && global_video_state->quit);  
  641. }  
  642.   
  643. int decode_thread(void *arg) {  
  644.   
  645.   VideoState *is = (VideoState *)arg;  
  646.   AVFormatContext *pFormatCtx;  
  647.   AVPacket pkt1, *packet = &pkt1;  
  648.   
  649.   int video_index = -1;  
  650.   int audio_index = -1;  
  651.   int i;  
  652.   
  653.   is->videoStream=-1;  
  654.   is->audioStream=-1;  
  655.   
  656.   global_video_state = is;  
  657.   // will interrupt blocking functions if we quit!  
  658.   url_set_interrupt_cb(decode_interrupt_cb);  
  659.   
  660.   // Open video file  
  661.   if(av_open_input_file(&pFormatCtx, is->filename, NULL, 0, NULL)!=0)  
  662.     return -1// Couldn't open file  
  663.   
  664.   is->pFormatCtx = pFormatCtx;  
  665.     
  666.   // Retrieve stream information  
  667.   if(av_find_stream_info(pFormatCtx)<0)  
  668.     return -1// Couldn't find stream information  
  669.     
  670.   // Dump information about file onto standard error  
  671.   av_dump_format(pFormatCtx, 0, is->filename, 0);  
  672.     
  673.   // Find the first video stream  
  674.   
  675.   for(i=0; i<pFormatCtx->nb_streams; i++) {  
  676.     if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO &&  
  677.        video_index < 0) {  
  678.       video_index=i;  
  679.     }  
  680.     if(pFormatCtx->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO &&  
  681.        audio_index < 0) {  
  682.       audio_index=i;  
  683.     }  
  684.   }  
  685.   if(audio_index >= 0) {  
  686.     stream_component_open(is, audio_index);  
  687.   }  
  688.   if(video_index >= 0) {  
  689.     stream_component_open(is, video_index);  
  690.   }     
  691.   
  692.   if(is->videoStream < 0 || is->audioStream < 0) {  
  693.     fprintf(stderr, "%s: could not open codecs\n", is->filename);  
  694.     goto fail;  
  695.   }  
  696.   
  697.   // main decode loop  
  698.   
  699.   for(;;) {  
  700.     if(is->quit) {  
  701.       break;  
  702.     }  
  703.     // seek stuff goes here  
  704.     if(is->audioq.size > MAX_AUDIOQ_SIZE ||  
  705.        is->videoq.size > MAX_VIDEOQ_SIZE) {  
  706.       SDL_Delay(10);  
  707.       continue;  
  708.     }  
  709.     if(av_read_frame(is->pFormatCtx, packet) < 0) {  
  710.       if(url_ferror(&pFormatCtx->pb) == 0) {  
  711.     SDL_Delay(100); /* no error; wait for user input */  
  712.     continue;  
  713.       } else {  
  714.     break;  
  715.       }  
  716.     }  
  717.     // Is this a packet from the video stream?  
  718.     if(packet->stream_index == is->videoStream) {  
  719.       packet_queue_put(&is->videoq, packet);  
  720.     } else if(packet->stream_index == is->audioStream) {  
  721.       packet_queue_put(&is->audioq, packet);  
  722.     } else {  
  723.       av_free_packet(packet);  
  724.     }  
  725.   }  
  726.   /* all done - wait for it */  
  727.   while(!is->quit) {  
  728.     SDL_Delay(100);  
  729.   }  
  730.   
  731.  fail:  
  732.   {  
  733.     SDL_Event event;  
  734.     event.type = FF_QUIT_EVENT;  
  735.     event.user.data1 = is;  
  736.     SDL_PushEvent(&event);  
  737.   }  
  738.   return 0;  
  739. }  
  740.   
  741.   
  742.   
  743. int main(int argc, char *argv[]) {  
  744.   
  745.   SDL_Event       event;  
  746.   
  747.   VideoState      *is;  
  748.   
  749.   is = av_mallocz(sizeof(VideoState));  
  750.   
  751.   if(argc < 2) {  
  752.     fprintf(stderr, "Usage: test <file>\n");  
  753.     exit(1);  
  754.   }  
  755.   // Register all formats and codecs  
  756.   av_register_all();  
  757.     
  758.   if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {  
  759.     fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());  
  760.     exit(1);  
  761.   }  
  762.   
  763.   // Make a screen to put our video  
  764. #ifndef __DARWIN__  
  765.         screen = SDL_SetVideoMode(64048000);  
  766. #else  
  767.         screen = SDL_SetVideoMode(640480240);  
  768. #endif  
  769.   if(!screen) {  
  770.     fprintf(stderr, "SDL: could not set video mode - exiting\n");  
  771.     exit(1);  
  772.   }  
  773.   
  774.   //pstrcpy(is->filename, sizeof(is->filename), argv[1]);  
  775.   av_strlcpy(is->filename, argv[1], sizeof(is->filename));  
  776.   
  777.   is->pictq_mutex = SDL_CreateMutex();  
  778.   is->pictq_cond = SDL_CreateCond();  
  779.   
  780.   schedule_refresh(is, 40);  
  781.   
  782.   is->parse_tid = SDL_CreateThread(decode_thread, is);  
  783.   if(!is->parse_tid) {  
  784.     av_free(is);  
  785.     return -1;  
  786.   }  
  787.   for(;;) {  
  788.   
  789.     SDL_WaitEvent(&event);  
  790.     switch(event.type) {  
  791.     case FF_QUIT_EVENT:  
  792.     case SDL_QUIT:  
  793.       is->quit = 1;  
  794.       SDL_Quit();  
  795.       exit(0);  
  796.       break;  
  797.     case FF_ALLOC_EVENT:  
  798.       alloc_picture(event.user.data1);  
  799.       break;  
  800.     case FF_REFRESH_EVENT:  
  801.       video_refresh_timer(event.user.data1);  
  802.       break;  
  803.     default:  
  804.       break;  
  805.     }  
  806.   }  
  807.   return 0;  
  808.   
  809. }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值