1. 程式人生 > >ffmpeg學習---7.音視訊同步之視訊同步音訊

ffmpeg學習---7.音視訊同步之視訊同步音訊

  1. #include <libavcodec/avcodec.h>
  2. #include <libavformat/avformat.h>
  3. #include <libswscale/swscale.h>
  4. #include <libswresample/swresample.h>
  5. #include <libavutil/avstring.h>
  6. #include <libavutil/pixfmt.h>
  7. #include <libavutil/log.h>
  8. #include <libavutil/
    time.h>              //要使用函式av_gettime
  9. #include <SDL/SDL.h>
  10. #include <SDL/SDL_thread.h>
  11. #include <stdio.h>
  12. #include <math.h>
  13. #define SDL_AUDIO_BUFFER_SIZE 4096
  14. #define AVCODEC_MAX_AUDIO_FRAME_SIZE 192000
  15. #define MAX_AUDIOQ_SIZE (* 16 * 1024)
  16. #define MAX_VIDEOQ_SIZE (
    * 256 * 1024)
  17. #define AV_SYNC_THRESHOLD 0.01
  18. #define AV_NOSYNC_THRESHOLD 10.0
  19. #define FF_REFRESH_EVENT (SDL_USEREVENT)
  20. #define FF_QUIT_EVENT (SDL_USEREVENT + 1)
  21. typedef struct PacketQueue
  22. {
  23.     AVPacketList * first_pkt, *last_pkt;
  24.     int nb_packets;
  25.     int size;
  26.     SDL_mutex *
    mutex;
  27.     SDL_cond * cond;
  28. }PacketQueue;
  29. static int signal_quit = 0;
  30. SDL_mutex *affmutex;
  31. SDL_Event sdlevent;
  32. #define VIDEO_PICTURE_QUEUE_SIZE 1
  33. typedef struct VideoState {
  34.     int videoindex;
  35.     int sndindex;
  36.     int frameFinished;
  37.     int wanted_freq;
  38.     int wanted_samples;
  39.     int wanted_channels;
  40.     int pictq_size, pictq_rindex, pictq_windex;
  41. unsigned int audio_buf_size;
  42.     unsigned int audio_buf_index;
  43.     double frame_timer;
  44.     double frame_last_pts;
  45.     double now_video_pts;
  46.     double frame_last_delay;
  47.     double video_clock;
  48.     double              audio_clock;
  49.     SDL_Thread* video_tid;
  50.     AVFormatContext* pFormatCtx;
  51.     AVCodecContext* vdoCodecCtx;
  52.     AVCodecContext* sndCodecCtx;
  53.     AVCodec* vdoCodec;
  54.     AVCodec* sndCodec;
  55.     AVStream* vdoStream;
  56.     AVStream* sndStream;
  57.     AVFrame* pFrameYUV;
  58.     AVPacket* packet;
  59.     struct SwsContext *img_convert_ctx;
  60.     struct SwrContext *swr_ctx;
  61.     SDL_mutex *pictq_mutex;
  62.     SDL_cond *pictq_cond;
  63.     SDL_Surface* psscreen;
  64.     SDL_Overlay* overlay;
  65.     SDL_Rect rect;
  66.     SDL_mutex *screen_mutex;
  67.     enum AVSampleFormat wanted_fmt;
  68.     int64_t wanted_channel_layout;
  69.     PacketQueue audioq;
  70.     PacketQueue videoq;
  71.     DECLARE_ALIGNED(16,uint8_t,audio_buf2) [AVCODEC_MAX_AUDIO_FRAME_SIZE * 4];
  72. }VideoState;
  73. static void video_refresh_timer(void* arg);
  74. double synchronize_video(VideoState *is, AVFrame *src_frame, double pts) ;  //這兩個函式是新加的
  75. double get_audio_clock(VideoState *is);
  76. static int sdl_event_thread(void* data)
  77. {
  78.     while((0==signal_quit))
  79.     {
  80.         SDL_LockMutex(affmutex);
  81.         while(SDL_PollEvent(&sdlevent))
  82.         {
  83.             switch(sdlevent.type)
  84.             {
  85.                 case FF_QUIT_EVENT:
  86.                 case SDL_QUIT:
  87.                     {
  88.                         signal_quit = 1;
  89.                         SDL_Quit();
  90.                         exit(0);
  91.                     }
  92.                     break;
  93.                 case FF_REFRESH_EVENT:
  94.                   video_refresh_timer(sdlevent.user.data1);
  95.                   break;
  96.                 default:
  97.                     break;
  98.             }
  99.         }
  100.         SDL_UnlockMutex(affmutex);
  101.     }
  102.     return 0;
  103. }
  104. static void packet_queue_init(PacketQueue *q)
  105. {
  106.     memset(q, 0, sizeof(PacketQueue));
  107.     q->mutex = SDL_CreateMutex();
  108.     q->cond = SDL_CreateCond();
  109. }
  110. static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
  111. {
  112.     AVPacketList *pkt1;
  113.     pkt1 = av_malloc(sizeof(AVPacketList));
  114.     if (!pkt1)
  115.         return -1;
  116.     pkt1->pkt = *pkt;
  117.     pkt1->next = NULL;
  118.     SDL_LockMutex(q->mutex);
  119.     if (!q->last_pkt)
  120.         q->first_pkt = pkt1;
  121.     else
  122.         q->last_pkt->next = pkt1;
  123.     q->last_pkt = pkt1;
  124.     q->nb_packets++;
  125.     q->size += pkt1->pkt.size;
  126.     //dbmsg("put_queue and send singal");
  127.     SDL_CondSignal(q->cond);
  128.     SDL_UnlockMutex(q->mutex);
  129.     return 0;
  130. }
  131. static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block)
  132. {
  133.     AVPacketList *pkt1;
  134.     int ret;
  135.     SDL_LockMutex(q->mutex);
  136.     for(;;)
  137.     {
  138.         pkt1 = q->first_pkt;
  139.         if (pkt1)
  140.         {
  141.             q->first_pkt = pkt1->next;
  142.             if (!q->first_pkt)
  143.                 q->last_pkt = NULL;
  144.             q->nb_packets--;
  145.             q->size -= pkt1->pkt.size;
  146.             *pkt = pkt1->pkt;
  147.             av_free(pkt1);
  148.             ret = 1;
  149.             break;
  150.         } else if (!block) {
  151.             ret = 0;
  152.             break;
  153.         } else {
  154.             SDL_CondWait(q->cond, q->mutex);
  155.          }
  156.     }
  157.     SDL_UnlockMutex(q->mutex);
  158.     return ret;
  159. }
  160. double get_audio_clock(VideoState *is) {
  161.     double pts;
  162. int hw_buf_size, bytes_per_sec, n;
  163.     pts = is->audio_clock; /* maintained in the audio thread */
  164.     hw_buf_size = is-