码迷,mamicode.com
首页 > 其他好文 > 详细

ffmpeg+sdl教程----编写一个简单的播放器6(其他的时钟同步方式)

时间:2014-12-30 14:45:48      阅读:348      评论:0      收藏:0      [点我收藏+]

标签:

来源:http://blog.csdn.net/mu399/article/details/5818384

在理解上一个教程的基础上,这篇教程就稍微容易理解些了,不外乎多加了两种同步方式,同步音频到视频,同步音频视频到外部时钟。

这篇教程主要是新增了不少新变量,is->video_current_pts用于保存当前视频帧的时间戳(以秒为单位),只在 video_refresh_timer函数中播放一帧视频前改变,is->video_current_pts_time单位为毫秒,在 stream_component_open中初始化,也在video_refresh_timer函数中初始化。

   这篇教程的难点是对synchronize_audio函数的理解,它的功能是测量声音的位置,把它与参考时间进行比较,然后算出我们需要修正多少的样本 数,也就是说:我们是否需要通过丢弃样本的方式来加速播放还是需要通过插值样本的方式来放慢播放,这个函数在教程中有详细的说明。

  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 -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 "libavformat/avformat.h"  
  19. #include "libswscale/swscale.h"  
  20.   
  21. #include <SDL/SDL.h>  
  22. #include <SDL/SDL_thread.h>  
  23.   
  24. #ifdef main  
  25. #undef main /* Prevents SDL from overriding main() */  
  26. #endif  
  27.   
  28. #include <stdio.h>  
  29. #include <math.h>  
  30.   
  31. #define SDL_AUDIO_BUFFER_SIZE 1024  
  32.   
  33. #define MAX_AUDIOQ_SIZE (5 * 16 * 1024)  
  34. #define MAX_VIDEOQ_SIZE (5 * 256 * 1024)  
  35.   
  36. #define AV_SYNC_THRESHOLD 0.01  
  37. #define AV_NOSYNC_THRESHOLD 10.0  
  38.   
  39. #define SAMPLE_CORRECTION_PERCENT_MAX 10  
  40. #define AUDIO_DIFF_AVG_NB 20  
  41.   
  42. #define FF_ALLOC_EVENT   (SDL_USEREVENT)  
  43. #define FF_REFRESH_EVENT (SDL_USEREVENT + 1)  
  44. #define FF_QUIT_EVENT (SDL_USEREVENT + 2)  
  45.   
  46. #define VIDEO_PICTURE_QUEUE_SIZE 1  
  47.   
  48. #define DEFAULT_AV_SYNC_TYPE AV_SYNC_EXTERNAL_MASTER  
  49. enum  
  50. {  
  51.     AV_SYNC_AUDIO_MASTER,  
  52.     AV_SYNC_VIDEO_MASTER,  
  53.     AV_SYNC_EXTERNAL_MASTER,  
  54. };  
  55.   
  56. typedef struct PacketQueue  
  57. {  
  58.     AVPacketList *first_pkt, *last_pkt;  
  59.     int nb_packets;  
  60.     int size;  
  61.     SDL_mutex *mutex;  
  62.     SDL_cond *cond;  
  63. } PacketQueue;  
  64.   
  65.   
  66. typedef struct VideoPicture  
  67. {  
  68.     SDL_Overlay *bmp;  
  69.     int width, height; /* source height & width */  
  70.     int allocated;  
  71.     double pts;  
  72. } VideoPicture;  
  73.   
  74. typedef struct VideoState  
  75. {  
  76.     AVFormatContext *pFormatCtx;  
  77.     int             videoStream, audioStream;  
  78.   
  79.     int             av_sync_type;  
  80.     double          audio_clock;  
  81.     AVStream        *audio_st;  
  82.     PacketQueue     audioq;  
  83.     uint8_t         audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2];  
  84.     unsigned int    audio_buf_size;  
  85.     unsigned int    audio_buf_index;  
  86.     AVPacket        audio_pkt;  
  87.     uint8_t         *audio_pkt_data;  
  88.     int             audio_pkt_size;  
  89.     int             audio_hw_buf_size;  
  90.   
  91.     double          audio_diff_cum; /* used for AV difference average computation */  
  92.     double          audio_diff_avg_coef;  
  93.     double          audio_diff_threshold;  
  94.     int             audio_diff_avg_count;  
  95.   
  96.     double          frame_timer;  
  97.     double          frame_last_pts;  
  98.     double          frame_last_delay;  
  99.     double          video_clock; ///<pts of last decoded frame / predicted pts of next decoded frame  
  100.   
  101.     double          video_current_pts; ///<current displayed pts (different from video_clock if frame fifos are used)  
  102.     int64_t         video_current_pts_time;  ///<time (av_gettime) at which we updated video_current_pts - used to have running video pts  
  103.   
  104.     AVStream        *video_st;  
  105.     PacketQueue     videoq;  
  106.   
  107.     VideoPicture    pictq[VIDEO_PICTURE_QUEUE_SIZE];  
  108.     int             pictq_size, pictq_rindex, pictq_windex;  
  109.     SDL_mutex       *pictq_mutex;  
  110.     SDL_cond        *pictq_cond;  
  111.     SDL_Thread      *parse_tid;  
  112.     SDL_Thread      *video_tid;  
  113.   
  114.     char            filename[1024];  
  115.     int             quit;  
  116. } VideoState;  
  117.   
  118. SDL_Surface     *screen;  
  119.   
  120. /* Since we only have one decoding thread, the Big Struct 
  121. can be global in case we need it. */  
  122. VideoState *global_video_state;  
  123.   
  124. void packet_queue_init(PacketQueue *q)  
  125. {  
  126.     memset(q, 0, sizeof(PacketQueue));  
  127.     q->mutex = SDL_CreateMutex();  
  128.     q->cond = SDL_CreateCond();  
  129. }  
  130. int packet_queue_put(PacketQueue *q, AVPacket *pkt)  
  131. {  
  132.     AVPacketList *pkt1;  
  133.     if(av_dup_packet(pkt) < 0)  
  134.     {  
  135.         return -1;  
  136.     }  
  137.     pkt1 = (AVPacketList *)av_malloc(sizeof(AVPacketList));  
  138.     if (!pkt1)  
  139.         return -1;  
  140.     pkt1->pkt = *pkt;  
  141.     pkt1->next = NULL;  
  142.   
  143.     SDL_LockMutex(q->mutex);  
  144.   
  145.     if (!q->last_pkt)  
  146.         q->first_pkt = pkt1;  
  147.     else  
  148.         q->last_pkt->next = pkt1;  
  149.     q->last_pkt = pkt1;  
  150.     q->nb_packets++;  
  151.     q->size += pkt1->pkt.size;  
  152.     SDL_CondSignal(q->cond);  
  153.   
  154.     SDL_UnlockMutex(q->mutex);  
  155.     return 0;  
  156. }  
  157.   
  158. static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)  
  159. {  
  160.     AVPacketList *pkt1;  
  161.     int ret;  
  162.     SDL_LockMutex(q->mutex);  
  163.   
  164.     for(;;)  
  165.     {  
  166.         if(global_video_state->quit)  
  167.         {  
  168.             ret = -1;  
  169.             break;  
  170.         }  
  171.   
  172.         pkt1 = q->first_pkt;  
  173.         if (pkt1)  
  174.         {  
  175.             q->first_pkt = pkt1->next;  
  176.             if (!q->first_pkt)  
  177.                 q->last_pkt = NULL;  
  178.             q->nb_packets--;  
  179.             q->size -= pkt1->pkt.size;  
  180.             *pkt = pkt1->pkt;  
  181.             av_free(pkt1);  
  182.             ret = 1;  
  183.             break;  
  184.         }  
  185.         else if (!block)  
  186.         {  
  187.             ret = 0;  
  188.             break;  
  189.         }  
  190.         else  
  191.         {  
  192.             SDL_CondWait(q->cond, q->mutex);  
  193.         }  
  194.     }  
  195.     SDL_UnlockMutex(q->mutex);  
  196.     return ret;  
  197. }  
  198. double get_audio_clock(VideoState *is)  
  199. {  
  200.     double pts;  
  201.     int hw_buf_size, bytes_per_sec, n;  
  202.   
  203.     pts = is->audio_clock; /* maintained in the audio thread */  
  204.     hw_buf_size = is->audio_buf_size - is->audio_buf_index;  
  205.     bytes_per_sec = 0;  
  206.     n = is->audio_st->codec->channels * 2;  
  207.     if(is->audio_st)  
  208.     {  
  209.         bytes_per_sec = is->audio_st->codec->sample_rate * n;  
  210.     }  
  211.     if(bytes_per_sec)  
  212.     {  
  213.         pts -= (double)hw_buf_size / bytes_per_sec;  
  214.     }  
  215.     return pts;  
  216. }  
  217.   
  218. double get_video_clock(VideoState *is)  
  219. {  
  220.     double delta;  
  221.   
  222.     delta = (av_gettime() - is->video_current_pts_time) / 1000000.0;  
  223.     return is->video_current_pts + delta;  
  224. }  
  225.   
  226. double get_external_clock(VideoState *is)  
  227. {  
  228.     return av_gettime() / 1000000.0;  
  229. }  
  230.   
  231. double get_master_clock(VideoState *is)  
  232. {  
  233.     if(is->av_sync_type == AV_SYNC_VIDEO_MASTER)  
  234.     {  
  235.         return get_video_clock(is);  
  236.     }  
  237.     else if(is->av_sync_type == AV_SYNC_AUDIO_MASTER)  
  238.     {  
  239.         return get_audio_clock(is);  
  240.     }  
  241.     else  
  242.     {  
  243.         return get_external_clock(is);  
  244.     }  
  245. }  
  246.   
  247. /* Add or subtract samples to get a better sync, return new 
  248.    audio buffer size */  
  249. int synchronize_audio(VideoState *is, short *samples,int samples_size, double pts)  
  250. {  
  251.     int n;  
  252.     double ref_clock;  
  253.   
  254.     n = 2 * is->audio_st->codec->channels;  
  255.   
  256.     if(is->av_sync_type != AV_SYNC_AUDIO_MASTER)  
  257.     {  
  258.         double diff, avg_diff;  
  259.         int wanted_size, min_size, max_size, nb_samples;  
  260.   
  261.         ref_clock = get_master_clock(is);  
  262.         diff = get_audio_clock(is) - ref_clock;  
  263.   
  264.         if(diff < AV_NOSYNC_THRESHOLD)  
  265.         {  
  266.             // accumulate the diffs  
  267.             is->audio_diff_cum = diff + is->audio_diff_avg_coef  
  268.                                  * is->audio_diff_cum;  
  269.             if(is->audio_diff_avg_count < AUDIO_DIFF_AVG_NB)  
  270.             {  
  271.                 is->audio_diff_avg_count++;  
  272.             }  
  273.             else  
  274.             {  
  275.                 avg_diff = is->audio_diff_cum * (1.0 - is->audio_diff_avg_coef);  
  276.                 if(fabs(avg_diff) >= is->audio_diff_threshold)  
  277.                 {  
  278.                     wanted_size = samples_size + ((int)(diff * is->audio_st->codec->sample_rate) * n);  
  279.                     min_size = samples_size * ((100 - SAMPLE_CORRECTION_PERCENT_MAX) / 100);  
  280.                     max_size = samples_size * ((100 + SAMPLE_CORRECTION_PERCENT_MAX) / 100);  
  281.                     if(wanted_size < min_size)  
  282.                     {  
  283.                         wanted_size = min_size;  
  284.                     }  
  285.                     else if (wanted_size > max_size)  
  286.                     {  
  287.                         wanted_size = max_size;  
  288.                     }  
  289.                     if(wanted_size < samples_size)  
  290.                     {  
  291.                         /* remove samples */  
  292.                         samples_size = wanted_size;  
  293.                     }  
  294.                     else if(wanted_size > samples_size)  
  295.                     {  
  296.                         uint8_t *samples_end, *q;  
  297.                         int nb;  
  298.   
  299.                         /* add samples by copying final sample*/  
  300.                         nb = (samples_size - wanted_size);  
  301.                         samples_end = (uint8_t *)samples + samples_size - n;  
  302.                         q = samples_end + n;  
  303.                         while(nb > 0)  
  304.                         {  
  305.                             memcpy(q, samples_end, n);  
  306.                             q += n;  
  307.                             nb -= n;  
  308.                         }  
  309.                         samples_size = wanted_size;  
  310.                     }  
  311.                 }  
  312.             }  
  313.         }  
  314.         else  
  315.         {  
  316.             /* difference is TOO big; reset diff stuff */  
  317.             is->audio_diff_avg_count = 0;  
  318.             is->audio_diff_cum = 0;  
  319.         }  
  320.     }  
  321.     return samples_size;  
  322. }  
  323.   
  324. int audio_decode_frame(VideoState *is, uint8_t *audio_buf, int buf_size, double *pts_ptr)  
  325. {  
  326.     int len1, data_size, n;  
  327.     AVPacket *pkt = &is->audio_pkt;  
  328.     double pts;  
  329.   
  330.     for(;;)  
  331.     {  
  332.         while(is->audio_pkt_size > 0)  
  333.         {  
  334.             data_size = buf_size;  
  335.             len1 = avcodec_decode_audio2(is->audio_st->codec,  
  336.                                          (int16_t *)audio_buf, &data_size,  
  337.                                          is->audio_pkt_data, is->audio_pkt_size);  
  338.             if(len1 < 0)  
  339.             {  
  340.                 /* if error, skip frame */  
  341.                 is->audio_pkt_size = 0;  
  342.                 break;  
  343.             }  
  344.             is->audio_pkt_data += len1;  
  345.             is->audio_pkt_size -= len1;  
  346.             if(data_size <= 0)  
  347.             {  
  348.                 /* No data yet, get more frames */  
  349.                 continue;  
  350.             }  
  351.             pts = is->audio_clock;  
  352.             *pts_ptr = pts;  
  353.             n = 2 * is->audio_st->codec->channels;  
  354.             is->audio_clock += (double)data_size /  
  355.                                (double)(n * is->audio_st->codec->sample_rate);  
  356.   
  357.             /* We have data, return it and come back for more later */  
  358.             return data_size;  
  359.         }  
  360.         if(pkt->data)  
  361.             av_free_packet(pkt);  
  362.   
  363.         if(is->quit)  
  364.         {  
  365.             return -1;  
  366.         }  
  367.         /* next packet */  
  368.         if(packet_queue_get(&is->audioq, pkt, 1) < 0)  
  369.         {  
  370.             return -1;  
  371.         }  
  372.         is->audio_pkt_data = pkt->data;  
  373.         is->audio_pkt_size = pkt->size;  
  374.         /* if update, update the audio clock w/pts */  
  375.         if(pkt->pts != AV_NOPTS_VALUE)  
  376.         {  
  377.             is->audio_clock = av_q2d(is->audio_st->time_base)*pkt->pts;  
  378.         }  
  379.     }  
  380. }  
  381.   
  382. void audio_callback(void *userdata, Uint8 *stream, int len)  
  383. {  
  384.     VideoState *is = (VideoState *)userdata;  
  385.     int len1, audio_size;  
  386.     double pts;  
  387.   
  388.     while(len > 0)  
  389.     {  
  390.         if(is->audio_buf_index >= is->audio_buf_size)  
  391.         {  
  392.             /* We have already sent all our data; get more */  
  393.             audio_size = audio_decode_frame(is, is->audio_buf, sizeof(is->audio_buf), &pts);  
  394.             if(audio_size < 0)  
  395.             {  
  396.                 /* If error, output silence */  
  397.                 is->audio_buf_size = 1024;  
  398.                 memset(is->audio_buf, 0, is->audio_buf_size);  
  399.             }  
  400.             else  
  401.             {  
  402.                 audio_size = synchronize_audio(is, (int16_t *)is->audio_buf,audio_size, pts);  
  403.   
  404.                 is->audio_buf_size = audio_size;  
  405.             }  
  406.             is->audio_buf_index = 0;  
  407.         }  
  408.         len1 = is->audio_buf_size - is->audio_buf_index;  
  409.         if(len1 > len)  
  410.             len1 = len;  
  411.         memcpy(stream, (uint8_t *)is->audio_buf + is->audio_buf_index, len1);  
  412.         len -= len1;  
  413.         stream += len1;  
  414.         is->audio_buf_index += len1;  
  415.     }  
  416. }  
  417.   
  418. static Uint32 sdl_refresh_timer_cb(Uint32 interval, void *opaque)  
  419. {  
  420.     SDL_Event event;  
  421.     event.type = FF_REFRESH_EVENT;  
  422.     event.user.data1 = opaque;  
  423.     SDL_PushEvent(&event);  
  424.     return 0; /* 0 means stop timer */  
  425. }  
  426.   
  427. /* schedule a video refresh in ‘delay‘ ms */  
  428. static void schedule_refresh(VideoState *is, int delay)  
  429. {  
  430.     SDL_AddTimer(delay, sdl_refresh_timer_cb, is);  
  431. }  
  432.   
  433. void video_display(VideoState *is)  
  434. {  
  435.     SDL_Rect rect;  
  436.     VideoPicture *vp;  
  437.     AVPicture pict;  
  438.     float aspect_ratio;  
  439.     int w, h, x, y;  
  440.     int i;  
  441.   
  442.     vp = &is->pictq[is->pictq_rindex];  
  443.     if(vp->bmp)  
  444.     {  
  445.         if(is->video_st->codec->sample_aspect_ratio.num == 0)  
  446.         {  
  447.             aspect_ratio = 0;  
  448.         }  
  449.         else  
  450.         {  
  451.             aspect_ratio = av_q2d(is->video_st->codec->sample_aspect_ratio) *  
  452.                            is->video_st->codec->width / is->video_st->codec->height;  
  453.         }  
  454.         if(aspect_ratio <= 0.0)  
  455.         {  
  456.             aspect_ratio = (float)is->video_st->codec->width /  
  457.                            (float)is->video_st->codec->height;  
  458.         }  
  459.         h = screen->h;  
  460.         w = ((int)(h * aspect_ratio)) & -3;  
  461.         if(w > screen->w)  
  462.         {  
  463.             w = screen->w;  
  464.             h = ((int)(w / aspect_ratio)) & -3;  
  465.         }  
  466.         x = (screen->w - w) / 2;  
  467.         y = (screen->h - h) / 2;  
  468.   
  469.         rect.x = x;  
  470.         rect.y = y;  
  471.         rect.w = w;  
  472.         rect.h = h;  
  473.         SDL_DisplayYUVOverlay(vp->bmp, &rect);  
  474.     }  
  475. }  
  476.   
  477. void video_refresh_timer(void *userdata)  
  478. {  
  479.     VideoState *is = (VideoState *)userdata;  
  480.     VideoPicture *vp;  
  481.     double actual_delay, delay, sync_threshold, ref_clock, diff;  
  482.   
  483.     if(is->video_st)  
  484.     {  
  485.         if(is->pictq_size == 0)  
  486.         {  
  487.             schedule_refresh(is, 1);  
  488.         }  
  489.         else  
  490.         {  
  491.             vp = &is->pictq[is->pictq_rindex];  
  492.             is->video_current_pts = vp->pts;  
  493.             is->video_current_pts_time = av_gettime();  
  494.   
  495.             delay = vp->pts - is->frame_last_pts; /* the pts from last time */  
  496.             if(delay <= 0 || delay >= 1.0)  
  497.             {  
  498.                 /* if incorrect delay, use previous one */  
  499.                 delay = is->frame_last_delay;  
  500.             }  
  501.             /* save for next time */  
  502.             is->frame_last_delay = delay;  
  503.             is->frame_last_pts = vp->pts;  
  504.   
  505.             /* update delay to sync to audio */  
  506.             ref_clock = get_master_clock(is);  
  507.             diff = vp->pts - ref_clock;  
  508.   
  509.             /* Skip or repeat the frame. Take delay into account 
  510.             FFPlay still doesn‘t "know if this is the best guess." */  
  511.             if(is->av_sync_type != AV_SYNC_VIDEO_MASTER)  
  512.             {  
  513.                 sync_threshold = (delay > AV_SYNC_THRESHOLD) ? delay : AV_SYNC_THRESHOLD;  
  514.                 if(fabs(diff) < AV_NOSYNC_THRESHOLD)  
  515.                 {  
  516.                     if(diff <= -sync_threshold)  
  517.                     {  
  518.                         delay = 0;  
  519.                     }  
  520.                     else if(diff >= sync_threshold)  
  521.                     {  
  522.                         delay = 2 * delay;  
  523.                     }  
  524.                 }  
  525.             }  
  526.             is->frame_timer += delay;  
  527.             /* computer the REAL delay */  
  528.             actual_delay = is->frame_timer - (av_gettime() / 1000000.0);  
  529.             if(actual_delay < 0.010)  
  530.             {  
  531.                 /* Really it should skip the picture instead */  
  532.                 actual_delay = 0.010;  
  533.             }  
  534.             schedule_refresh(is, (int)(actual_delay * 1000 + 0.5));  
  535.             /* show the picture! */  
  536.             video_display(is);  
  537.   
  538.             /* update queue for next picture! */  
  539.             if(++is->pictq_rindex == VIDEO_PICTURE_QUEUE_SIZE)  
  540.             {  
  541.                 is->pictq_rindex = 0;  
  542.             }  
  543.             SDL_LockMutex(is->pictq_mutex);  
  544.             is->pictq_size--;  
  545.             SDL_CondSignal(is->pictq_cond);  
  546.             SDL_UnlockMutex(is->pictq_mutex);  
  547.         }  
  548.     }  
  549.     else  
  550.     {  
  551.         schedule_refresh(is, 100);  
  552.     }  
  553. }  
  554.   
  555. void alloc_picture(void *userdata)  
  556. {  
  557.     VideoState *is = (VideoState *)userdata;  
  558.     VideoPicture *vp;  
  559.   
  560.     vp = &is->pictq[is->pictq_windex];  
  561.     if(vp->bmp)  
  562.     {  
  563.         // we already have one make another, bigger/smaller  
  564.         SDL_FreeYUVOverlay(vp->bmp);  
  565.     }  
  566.     // Allocate a place to put our YUV image on that screen  
  567.     vp->bmp = SDL_CreateYUVOverlay(is->video_st->codec->width,  
  568.                                    is->video_st->codec->height,  
  569.                                    SDL_YV12_OVERLAY,  
  570.                                    screen);  
  571.     vp->width = is->video_st->codec->width;  
  572.     vp->height = is->video_st->codec->height;  
  573.   
  574.     SDL_LockMutex(is->pictq_mutex);  
  575.     vp->allocated = 1;  
  576.     SDL_CondSignal(is->pictq_cond);  
  577.     SDL_UnlockMutex(is->pictq_mutex);  
  578.   
  579. }  
  580.   
  581. int queue_picture(VideoState *is, AVFrame *pFrame, double pts)  
  582. {  
  583.     VideoPicture *vp;  
  584.     //int dst_pix_fmt;  
  585.     AVPicture pict;  
  586.   
  587.     /* wait until we have space for a new pic */  
  588.     SDL_LockMutex(is->pictq_mutex);  
  589.     while(is->pictq_size >= VIDEO_PICTURE_QUEUE_SIZE &&  
  590.             !is->quit)  
  591.     {  
  592.         SDL_CondWait(is->pictq_cond, is->pictq_mutex);  
  593.     }  
  594.     SDL_UnlockMutex(is->pictq_mutex);  
  595.   
  596.     if(is->quit)  
  597.         return -1;  
  598.   
  599.     // windex is set to 0 initially  
  600.     vp = &is->pictq[is->pictq_windex];  
  601.   
  602.     /* allocate or resize the buffer! */  
  603.     if(!vp->bmp ||  
  604.             vp->width != is->video_st->codec->width ||  
  605.             vp->height != is->video_st->codec->height)  
  606.     {  
  607.         SDL_Event event;  
  608.   
  609.         vp->allocated = 0;  
  610.         /* we have to do it in the main thread */  
  611.         event.type = FF_ALLOC_EVENT;  
  612.         event.user.data1 = is;  
  613.         SDL_PushEvent(&event);  
  614.   
  615.         /* wait until we have a picture allocated */  
  616.         SDL_LockMutex(is->pictq_mutex);  
  617.         while(!vp->allocated && !is->quit)  
  618.         {  
  619.             SDL_CondWait(is->pictq_cond, is->pictq_mutex);  
  620.         }  
  621.         SDL_UnlockMutex(is->pictq_mutex);  
  622.         if(is->quit)  
  623.         {  
  624.             return -1;  
  625.         }  
  626.     }  
  627.     /* We have a place to put our picture on the queue */  
  628.     /* If we are skipping a frame, do we set this to null 
  629.     but still return vp->allocated = 1? */  
  630.     static struct SwsContext *img_convert_ctx;  
  631.     if (img_convert_ctx == NULL)  
  632.     {  
  633.         img_convert_ctx = sws_getContext(is->video_st->codec->width, is->video_st->codec->height,  
  634.                                          is->video_st->codec->pix_fmt,  
  635.                                          is->video_st->codec->width, is->video_st->codec->height,  
  636.                                          PIX_FMT_YUV420P,  
  637.                                          SWS_BICUBIC, NULL, NULL, NULL);  
  638.         if (img_convert_ctx == NULL)  
  639.         {  
  640.             fprintf(stderr, "Cannot initialize the conversion context/n");  
  641.             exit(1);  
  642.         }  
  643.     }  
  644.   
  645.     if(vp->bmp)  
  646.     {  
  647.         SDL_LockYUVOverlay(vp->bmp);  
  648.   
  649.         //dst_pix_fmt = PIX_FMT_YUV420P;  
  650.         /* point pict at the queue */  
  651.   
  652.         pict.data[0] = vp->bmp->pixels[0];  
  653.         pict.data[1] = vp->bmp->pixels[2];  
  654.         pict.data[2] = vp->bmp->pixels[1];  
  655.   
  656.         pict.linesize[0] = vp->bmp->pitches[0];  
  657.         pict.linesize[1] = vp->bmp->pitches[2];  
  658.         pict.linesize[2] = vp->bmp->pitches[1];  
  659.   
  660.         // Convert the image into YUV format that SDL uses  
  661.         /*img_convert(&pict, dst_pix_fmt, 
  662.                     (AVPicture *)pFrame, is->video_st->codec->pix_fmt, 
  663.                     is->video_st->codec->width, is->video_st->codec->height);*/  
  664.         sws_scale(img_convert_ctx, pFrame->data, pFrame->linesize,  
  665.                   0, is->video_st->codec->height, pict.data, pict.linesize);  
  666.         SDL_UnlockYUVOverlay(vp->bmp);  
  667.         vp->pts = pts;  
  668.   
  669.         /* now we inform our display thread that we have a pic ready */  
  670.         if(++is->pictq_windex == VIDEO_PICTURE_QUEUE_SIZE)  
  671.         {  
  672.             is->pictq_windex = 0;  
  673.         }  
  674.         SDL_LockMutex(is->pictq_mutex);  
  675.         is->pictq_size++;  
  676.         SDL_UnlockMutex(is->pictq_mutex);  
  677.     }  
  678.     return 0;  
  679. }  
  680.   
  681. double synchronize_video(VideoState *is, AVFrame *src_frame, double pts)  
  682. {  
  683.     double frame_delay;  
  684.   
  685.     if(pts != 0)  
  686.     {  
  687.         /* if we have pts, set video clock to it */  
  688.         is->video_clock = pts;  
  689.     }  
  690.     else  
  691.     {  
  692.         /* if we aren‘t given a pts, set it to the clock */  
  693.         pts = is->video_clock;  
  694.     }  
  695.     /* update the video clock */  
  696.     frame_delay = av_q2d(is->video_st->codec->time_base);  
  697.     /* if we are repeating a frame, adjust clock accordingly */  
  698.     frame_delay += src_frame->repeat_pict * (frame_delay * 0.5);  
  699.     is->video_clock += frame_delay;  
  700.     return pts;  
  701. }  
  702. uint64_t global_video_pkt_pts = AV_NOPTS_VALUE;  
  703.   
  704. /* These are called whenever we allocate a frame 
  705. * buffer. We use this to store the global_pts in 
  706. * a frame at the time it is allocated. 
  707. */  
  708. int our_get_buffer(struct AVCodecContext *c, AVFrame *pic)  
  709. {  
  710.     int ret = avcodec_default_get_buffer(c, pic);  
  711.     uint64_t *pts = (uint64_t *)av_malloc(sizeof(uint64_t));  
  712.     *pts = global_video_pkt_pts;  
  713.     pic->opaque = pts;  
  714.     return ret;  
  715. }  
  716. void our_release_buffer(struct AVCodecContext *c, AVFrame *pic)  
  717. {  
  718.     if(pic) av_freep(&pic->opaque);  
  719.     avcodec_default_release_buffer(c, pic);  
  720. }  
  721.   
  722. int video_thread(void *arg)  
  723. {  
  724.     VideoState *is = (VideoState *)arg;  
  725.     AVPacket pkt1, *packet = &pkt1;  
  726.     int len1, frameFinished;  
  727.     AVFrame *pFrame;  
  728.     double pts;  
  729.   
  730.     pFrame = avcodec_alloc_frame();  
  731.   
  732.     for(;;)  
  733.     {  
  734.         if(packet_queue_get(&is->videoq, packet, 1) < 0)  
  735.         {  
  736.             // means we quit getting packets  
  737.             break;  
  738.         }  
  739.         pts = 0;  
  740.   
  741.         // Save global pts to be stored in pFrame in first call  
  742.         global_video_pkt_pts = packet->pts;  
  743.         // Decode video frame  
  744.         len1 = avcodec_decode_video(is->video_st->codec, pFrame, &frameFinished,  
  745.                                     packet->data, packet->size);  
  746.         if(packet->dts == AV_NOPTS_VALUE  
  747.                 && pFrame->opaque && *(uint64_t*)pFrame->opaque != AV_NOPTS_VALUE)  
  748.         {  
  749.             pts = *(uint64_t *)pFrame->opaque;  
  750.         }  
  751.         else if(packet->dts != AV_NOPTS_VALUE)  
  752.         {  
  753.             pts = packet->dts;  
  754.         }  
  755.         else  
  756.         {  
  757.             pts = 0;  
  758.         }  
  759.         pts *= av_q2d(is->video_st->time_base);  
  760.   
  761.         // Did we get a video frame?  
  762.         if(frameFinished)  
  763.         {  
  764.             pts = synchronize_video(is, pFrame, pts);  
  765.             if(queue_picture(is, pFrame, pts) < 0)  
  766.             {  
  767.                 break;  
  768.             }  
  769.         }  
  770.         av_free_packet(packet);  
  771.     }  
  772.     av_free(pFrame);  
  773.     return 0;  
  774. }  
  775.   
  776. int stream_component_open(VideoState *is, int stream_index)  
  777. {  
  778.     AVFormatContext *pFormatCtx = is->pFormatCtx;  
  779.     AVCodecContext *codecCtx;  
  780.     AVCodec *codec;  
  781.     SDL_AudioSpec wanted_spec, spec;  
  782.   
  783.     if(stream_index < 0 || stream_index >= pFormatCtx->nb_streams)  
  784.     {  
  785.         return -1;  
  786.     }  
  787.   
  788.     // Get a pointer to the codec context for the video stream  
  789.     codecCtx = pFormatCtx->streams[stream_index]->codec;  
  790.   
  791.     if(codecCtx->codec_type == CODEC_TYPE_AUDIO)  
  792.     {  
  793.         // Set audio settings from codec info  
  794.         wanted_spec.freq = codecCtx->sample_rate;  
  795.         wanted_spec.format = AUDIO_S16SYS;  
  796.         wanted_spec.channels = codecCtx->channels;  
  797.         wanted_spec.silence = 0;  
  798.         wanted_spec.samples = SDL_AUDIO_BUFFER_SIZE;  
  799.         wanted_spec.callback = audio_callback;  
  800.         wanted_spec.userdata = is;  
  801.   
  802.         if(SDL_OpenAudio(&wanted_spec, &spec) < 0)  
  803.         {  
  804.             fprintf(stderr, "SDL_OpenAudio: %s/n", SDL_GetError());  
  805.             return -1;  
  806.         }  
  807.         is->audio_hw_buf_size = spec.size;  
  808.     }  
  809.     codec = avcodec_find_decoder(codecCtx->codec_id);  
  810.   
  811.     if(!codec || (avcodec_open(codecCtx, codec) < 0))  
  812.     {  
  813.         fprintf(stderr, "Unsupported codec!/n");  
  814.         return -1;  
  815.     }  
  816.   
  817.     switch(codecCtx->codec_type)  
  818.     {  
  819.     case CODEC_TYPE_AUDIO:  
  820.         is->audioStream = stream_index;  
  821.         is->audio_st = pFormatCtx->streams[stream_index];  
  822.         is->audio_buf_size = 0;  
  823.         is->audio_buf_index = 0;  
  824.   
  825.         /* averaging filter for audio sync */  
  826.         is->audio_diff_avg_coef = exp(log(0.01 / AUDIO_DIFF_AVG_NB));  
  827.         is->audio_diff_avg_count = 0;  
  828.         /* Correct audio only if larger error than this */  
  829.         is->audio_diff_threshold = 2.0 * SDL_AUDIO_BUFFER_SIZE / codecCtx->sample_rate;  
  830.   
  831.   
  832.         memset(&is->audio_pkt, 0, sizeof(is->audio_pkt));  
  833.         packet_queue_init(&is->audioq);  
  834.         SDL_PauseAudio(0);  
  835.         break;  
  836.     case CODEC_TYPE_VIDEO:  
  837.         is->videoStream = stream_index;  
  838.         is->video_st = pFormatCtx->streams[stream_index];  
  839.   
  840.         is->frame_timer = (double)av_gettime() / 1000000.0;  
  841.         is->frame_last_delay = 40e-3;  
  842.         is->video_current_pts_time = av_gettime();  
  843.   
  844.         packet_queue_init(&is->videoq);  
  845.         is->video_tid = SDL_CreateThread(video_thread, is);  
  846.         codecCtx->get_buffer = our_get_buffer;  
  847.         codecCtx->release_buffer = our_release_buffer;  
  848.         break;  
  849.     default:  
  850.         break;  
  851.     }  
  852.     return 0;  
  853. }  
  854.   
  855. int decode_interrupt_cb(void)  
  856. {  
  857.     return (global_video_state && global_video_state->quit);  
  858. }  
  859.   
  860. int decode_thread(void *arg)  
  861. {  
  862.     VideoState *is = (VideoState *)arg;  
  863.     AVFormatContext *pFormatCtx;  
  864.     AVPacket pkt1, *packet = &pkt1;  
  865.   
  866.     int video_index = -1;  
  867.     int audio_index = -1;  
  868.     int i;  
  869.   
  870.     is->videoStream=-1;  
  871.     is->audioStream=-1;  
  872.   
  873.     global_video_state = is;  
  874.     // will interrupt blocking functions if we quit!  
  875.     url_set_interrupt_cb(decode_interrupt_cb);  
  876.   
  877.     // Open video file  
  878.     if(av_open_input_file(&pFormatCtx, is->filename, NULL, 0, NULL)!=0)  
  879.         return -1; // Couldn‘t open file  
  880.   
  881.     is->pFormatCtx = pFormatCtx;  
  882.   
  883.     // Retrieve stream information  
  884.     if(av_find_stream_info(pFormatCtx)<0)  
  885.         return -1; // Couldn‘t find stream information  
  886.   
  887.     // Dump information about file onto standard error  
  888.     dump_format(pFormatCtx, 0, is->filename, 0);  
  889.   
  890.     // Find the first video stream  
  891.   
  892.     for(i=0; i<pFormatCtx->nb_streams; i++)  
  893.     {  
  894.         if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_VIDEO &&  
  895.                 video_index < 0)  
  896.         {  
  897.             video_index=i;  
  898.         }  
  899.         if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_AUDIO &&  
  900.                 audio_index < 0)  
  901.         {  
  902.             audio_index=i;  
  903.         }  
  904.     }  
  905.     if(audio_index >= 0)  
  906.     {  
  907.         stream_component_open(is, audio_index);  
  908.     }  
  909.     if(video_index >= 0)  
  910.     {  
  911.         stream_component_open(is, video_index);  
  912.     }  
  913.   
  914.     if(is->videoStream < 0 || is->audioStream < 0)  
  915.     {  
  916.         fprintf(stderr, "%s: could not open codecs/n", is->filename);  
  917.         goto fail;  
  918.     }  
  919.   
  920.     // main decode loop  
  921.   
  922.     for(;;)  
  923.     {  
  924.         if(is->quit)  
  925.         {  
  926.             break;  
  927.         }  
  928.         // seek stuff goes here  
  929.         if(is->audioq.size > MAX_AUDIOQ_SIZE ||  
  930.                 is->videoq.size > MAX_VIDEOQ_SIZE)  
  931.         {  
  932.             SDL_Delay(10);  
  933.             continue;  
  934.         }  
  935.         if(av_read_frame(is->pFormatCtx, packet) < 0)  
  936.         {  
  937.             if(url_ferror(pFormatCtx->pb) == 0)  
  938.             {  
  939.                 SDL_Delay(100); /* no error; wait for user input */  
  940.                 continue;  
  941.             }  
  942.             else  
  943.             {  
  944.                 break;  
  945.             }  
  946.         }  
  947.         // Is this a packet from the video stream?  
  948.         if(packet->stream_index == is->videoStream)  
  949.         {  
  950.             packet_queue_put(&is->videoq, packet);  
  951.         }  
  952.         else if(packet->stream_index == is->audioStream)  
  953.         {  
  954.             packet_queue_put(&is->audioq, packet);  
  955.         }  
  956.         else  
  957.         {  
  958.             av_free_packet(packet);  
  959.         }  
  960.     }  
  961.     /* all done - wait for it */  
  962.     while(!is->quit)  
  963.     {  
  964.         SDL_Delay(100);  
  965.     }  
  966.   
  967. fail:  
  968.     {  
  969.         SDL_Event event;  
  970.         event.type = FF_QUIT_EVENT;  
  971.         event.user.data1 = is;  
  972.         SDL_PushEvent(&event);  
  973.     }  
  974.     return 0;  
  975. }  
  976.   
  977. int main(int argc, char *argv[])  
  978. {  
  979.     SDL_Event       event;  
  980.     VideoState      *is;  
  981.     is = (VideoState *)av_mallocz(sizeof(VideoState));  
  982.     if(argc < 2)  
  983.     {  
  984.         fprintf(stderr, "Usage: test <file>/n");  
  985.         exit(1);  
  986.     }  
  987.     // Register all formats and codecs  
  988.     av_register_all();  
  989.     if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER))  
  990.     {  
  991.         fprintf(stderr, "Could not initialize SDL - %s/n", SDL_GetError());  
  992.         exit(1);  
  993.     }  
  994.   
  995.     // Make a screen to put our video  
  996. #ifndef __DARWIN__  
  997.     screen = SDL_SetVideoMode(640, 480, 0, 0);  
  998. #else  
  999.     screen = SDL_SetVideoMode(640, 480, 24, 0);  
  1000. #endif  
  1001.     if(!screen)  
  1002.     {  
  1003.         fprintf(stderr, "SDL: could not set video mode - exiting/n");  
  1004.         exit(1);  
  1005.     }  
  1006.   
  1007.     //pstrcpy(is->filename, sizeof(is->filename), argv[1]);  
  1008.     strcpy(is->filename,argv[1]);  
  1009.     is->pictq_mutex = SDL_CreateMutex();  
  1010.     is->pictq_cond = SDL_CreateCond();  
  1011.   
  1012.     schedule_refresh(is, 40);  
  1013.     is->av_sync_type = DEFAULT_AV_SYNC_TYPE;  
  1014.   
  1015.     is->parse_tid = SDL_CreateThread(decode_thread, is);  
  1016.     if(!is->parse_tid)  
  1017.     {  
  1018.         av_free(is);  
  1019.         return -1;  
  1020.     }  
  1021.     for(;;)  
  1022.     {  
  1023.         SDL_WaitEvent(&event);  
  1024.         switch(event.type)  
  1025.         {  
  1026.         case FF_QUIT_EVENT:  
  1027.         case SDL_QUIT:  
  1028.             is->quit = 1;  
  1029.             SDL_Quit();  
  1030.             exit(0);  
  1031.             break;  
  1032.         case FF_ALLOC_EVENT:  
  1033.             alloc_picture(event.user.data1);  
  1034.             break;  
  1035.         case FF_REFRESH_EVENT:  
  1036.             video_refresh_timer(event.user.data1);  
  1037.             break;  
  1038.         default:  
  1039.             break;  
  1040.         }  
  1041.     }  
  1042.     return 0;  

ffmpeg+sdl教程----编写一个简单的播放器6(其他的时钟同步方式)

标签:

原文地址:http://www.cnblogs.com/sunminmin/p/4193420.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!