ffmpeg+sdl教程----编写一个简单的播放器7(处理快进快退命令)

这篇教程例子中的程序,让右方向按键为快进10秒,上方向按键为快进60秒,左方向按键为快退10秒,上方向按键为快退60秒,程序中的av_seek_frame函数可能是用错了,或者函数本身的问题导致按上和右都没反应;按左和下让画面暂停,声音在很短区间内不停播放,这时再按右和下才正常。

 

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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值