ffmpeg tutorial 创建线程

在手册中,这部分有的没有翻译。

流程大致是这样的:

main-->定时器产生FF_REFRESH_EVENT事件-->产生decode_thread线程-->进入SDL事件循环

 

decode_thread-->初始化操作(很简单的找到解码库等)-->read包-->将包放入相应的队列中-->如果是视频流调用video_thread -->如果是音频流则设置audio_callback

 

video_thread-->取包-->解码-->解码后的AVFrame送去PictQ等待事件触发去读取它

 

audio_callback-->取包-->解码

 

video_refresh_timer(响应FF_REFRESH_EVENT)-->设置80毫秒之后的定时-->video_display显示

 

代码如下。在看手册的过程中发现很多问题 大家可以一起交流

 

  1. int main()  
  2. {  
  3.     file=fopen("123.txt","wb");  
  4.     av_register_all();  
  5.     //初始化ffmpeg库  
  6.     SDL_Event  event;  
  7.     VideoState *is;  
  8.     is= (VideoState*)av_mallocz(sizeof(VideoState));  
  9.     strncpy(is->filename,FILENAME, sizeof(is->filename));  
  10.     // 初始化显示互斥  
  11.     is->pictq_mutex=SDL_CreateMutex();  
  12.     is->pictq_cond=SDL_CreateCond();  
  13.     //初始化SDL库  
  14.     SDL_Init(SDL_INIT_AUDIO|SDL_INIT_TIMER|SDL_INIT_VIDEO);  
  15.     SDL_EventState(SDL_ACTIVEEVENT, SDL_IGNORE);  
  16.     SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);  
  17.     SDL_EventState(SDL_SYSWMEVENT, SDL_IGNORE);  
  18.     SDL_EventState(SDL_USEREVENT, SDL_IGNORE);  
  19.      
  20.     //添加定时器  
  21.     schedule_refresh(is,40);  
  22.     is->parse_tid=SDL_CreateThread(decode_thread,is);  
  23.     if (!is->parse_tid)  
  24.     {  
  25.         av_free(is);  
  26.         return -1;  
  27.     }  
  28.     event_loop();  
  29. return 0;  
  30. }  

 

以上是main函数。

下面贴出音频部分代码:

  1. void audio_callback(void *userdata, Uint8 *stream, int len)  
  2. {  
  3.     VideoState* is=(VideoState*) userdata;  
  4.     int len1;  
  5.     int audio_size;  
  6.     static uint8_t audio_buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE*3)/2];  
  7.     static unsigned int audio_buf_size=0;  
  8.     static unsigned int audio_buf_index=0;  
  9.     while (len>0)  
  10.     {  
  11.         if (audio_buf_index>=audio_buf_size)  
  12.         {  
  13.             audio_size= audio_decode_frame(is,audio_buf,  
  14.                 sizeof(audio_buf));  
  15.             if (audio_size<0)  
  16.             {  
  17.                 audio_buf_size=1024;  
  18.                 memset(audio_buf,0,audio_buf_size);  
  19.             }  
  20.             else  
  21.             {  
  22.                 audio_buf_size=audio_size;  
  23.             }  
  24.             audio_buf_index=0;  
  25.         }  
  26.         len1=audio_buf_size-audio_buf_index;  
  27.         if (len1>len)  
  28.         {  
  29.             len1=len;  
  30.         }  
  31.         memcpy(stream,(uint8_t*)audio_buf+audio_buf_index,len1);  
  32.         len-=len1;  
  33.         stream+=len1;  
  34.         audio_buf_index+=len1;  
  35.   
  36.     }  
  37. }  
  38. int audio_decode_frame(VideoState* is, uint8_t*  audio_buf, int buf_size)  
  39. {  
  40.     AVCodecContext* paCodecCtx=is->audio_st->codec;  
  41. //  puts("yanxinmeng ' thread");  
  42.     static AVPacket pkt;  
  43.     static uint8_t * audio_pkt_data =NULL;  
  44.     static int audio_pkt_size=0;  
  45.     int len1, data_size;  
  46.     for (;;)  
  47.     {  
  48.         while(audio_pkt_size>0)  
  49.         {  
  50.             data_size=buf_size;  
  51.             len1= avcodec_decode_audio2(paCodecCtx, (int16_t*) audio_buf,  
  52.                 &data_size, audio_pkt_data,audio_pkt_size);  
  53.             if (len1<0)  
  54.             {  
  55.                 audio_pkt_size=0;  
  56.                 break;  
  57.             }  
  58.             audio_pkt_data+=len1;  
  59.             audio_pkt_size-=len1;  
  60.             if (data_size<=0)  
  61.             {  
  62.                 continue;  
  63.             }  
  64.             return data_size;  
  65.         }  
  66.         if(pkt.data)  
  67.             av_free_packet(&pkt);  
  68.         if (quit)  
  69.         {  
  70.             return -1;  
  71.         }  
  72.         if (packet_queue_get(&(is->audioq),&pkt,1)<0)  
  73.         {  
  74.             return -1;  
  75.         }  
  76.         audio_pkt_data= pkt.data;  
  77.         audio_pkt_size=pkt.size;  
  78.     }  
  79. }  

以下是视频处理部分

  1. int video_thread(void* arg)  
  2. {  
  3.     VideoState * is=(VideoState*) arg;  
  4.     AVPacket pkt1;  
  5.     AVPacket* packet = & pkt1;  
  6.     int len1, frameFinished;  
  7.     AVFrame *pFrame;  
  8.     //分配好解码后的frame   
  9.     pFrame = avcodec_alloc_frame();  
  10.       
  11.     screen =SDL_SetVideoMode(is->video_st->codec->width,  
  12.             is->video_st->codec->height,0,0);  
  13.     for (;;)  
  14.     {  
  15.         if (packet_queue_get(&is->videoq,packet,1)<0)  
  16.         {  
  17.             break;  
  18.         }  
  19.         len1 = avcodec_decode_video(is->video_st->codec, pFrame,&frameFinished,  
  20.             packet->data,packet->size);  
  21.         if (frameFinished)  
  22.         {  
  23.             //解码完成将帧队列化  
  24.             if (queue_picture(is,pFrame)<0)  
  25.             {  
  26.                 break;  
  27.             }  
  28.         }  
  29.         av_free_packet(packet);  
  30.     }  
  31.     av_free(pFrame);  
  32.     return 0;  
  33. }  
  34. //把帧队列化  
  35. int queue_picture(VideoState* is, AVFrame* pFrame)  
  36. {  
  37.     VideoPicture * vp;  
  38.     int dst_pix_mt;  
  39.     AVPicture pict;  
  40.       
  41.     SDL_LockMutex(is->pictq_mutex);  
  42.     while (is->pictq_size>= VIDEO_PICTURE_QUEUE_SIZE&& !is->quit)  
  43.     {  
  44.         SDL_CondWait(is->pictq_cond, is->pictq_mutex);  
  45.     }  
  46.     SDL_UnlockMutex(is->pictq_mutex);  
  47.     if(is->quit)  return -1;  
  48.     vp= &is->pictq[is->pictq_windex];//写指针  
  49.     if (!vp->bmp||vp->width!= is->video_st->codec->width  
  50.         || vp->height!= is->video_st->codec->height)  
  51.     {  
  52.         SDL_Event  event;  
  53.         vp->allocated=0;  
  54.         event.type =FF_ALLOC_EVENT;  
  55.         event.user.data1=is;  
  56.         SDL_PushEvent(&event);  
  57.         SDL_LockMutex(is->pictq_mutex);  
  58.         while (!vp->allocated&&!is->quit)  
  59.         {  
  60.             SDL_CondWait(is->pictq_cond,is->pictq_mutex);  
  61.         }  
  62.         SDL_UnlockMutex(is->pictq_mutex);  
  63.         if (is->quit)  
  64.         {  
  65.             return -1;  
  66.         }  
  67.     }  
  68.     if ( vp->bmp)  
  69.     {  
  70.     SDL_LockYUVOverlay(vp->bmp);  
  71.     dst_pix_mt= PIX_FMT_YUV420P;  
  72.     pict.data[0]= vp->bmp->pixels[0];  
  73.     pict.data[1]= vp->bmp->pixels[2];  
  74.     pict.data[2]= vp->bmp->pixels[1];  
  75.     pict.linesize[0]= vp->bmp->pitches[0];  
  76.     pict.linesize[1]= vp->bmp->pitches[2];  
  77.     pict.linesize[2]= vp->bmp->pitches[1];  
  78.     static SwsContext* img_convert_ctx;  
  79.     img_convert_ctx=sws_getCachedContext(img_convert_ctx,vp->width,vp->height,is->video_st->codec->pix_fmt,  
  80.         vp->width,vp->height,PIX_FMT_YUV420P,SWS_BICUBIC,NULL,NULL,NULL);  
  81.                   
  82.       
  83.     sws_scale(img_convert_ctx,pFrame->data,pFrame->linesize,0,  
  84.         vp->height,pict.data,pict.linesize);  
  85.   
  86.     SDL_LockYUVOverlay(vp->bmp);  
  87.     if (++is->pictq_windex == VIDEO_PICTURE_QUEUE_SIZE)  
  88.     {  
  89.         is->pictq_windex=0;  
  90.     }  
  91.     SDL_LockMutex(is->pictq_mutex);  
  92.     is->pictq_size++;  
  93.     SDL_UnlockMutex(is->pictq_mutex);  
  94.                
  95.     }  
  96.     return 0;  
  97. }  

 

基本结构是这样 事件循环就不贴了。很简单的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值