FFmpeg实现录屏+录音

原文地址:https://blog.csdn.net/dancing_night/article/details/46698853

1、概述

最简单的基于FFmpeg的AVDevice例子(屏幕录制+声音采集),视频采用mpeg4编码,音频采用aac编码,并生成mp4文件,其中fifo是此程序的关键,此程序只是一个demo很多优化都没做,仅供参考。

2、代码

[cpp]  view plain  copy
  1. <pre name="code" class="cpp">/** 
  2.  *最简单的基于FFmpeg的AVDevice例子(屏幕录制+声音采集),视频采用mpeg4编码,音频采用aac编码,并生成mp4文件 
  3.  *缪国凯 MK 
  4.  *[email protected] 
  5.  */  
  6.   
  7. #include "stdafx.h"  
  8.   
  9. #ifdef  __cplusplus  
  10. extern "C"  
  11. {  
  12. #endif  
  13. #include "libavcodec/avcodec.h"  
  14. #include "libavformat/avformat.h"  
  15. #include "libswscale/swscale.h"  
  16. #include "libavdevice/avdevice.h"  
  17. #include "libavutil/audio_fifo.h"  
  18.   
  19. #pragma comment(lib, "avcodec.lib")  
  20. #pragma comment(lib, "avformat.lib")  
  21. #pragma comment(lib, "avutil.lib")  
  22. #pragma comment(lib, "avdevice.lib")  
  23. #pragma comment(lib, "avfilter.lib")  
  24.   
  25. //#pragma comment(lib, "avfilter.lib")  
  26. //#pragma comment(lib, "postproc.lib")  
  27. //#pragma comment(lib, "swresample.lib")  
  28. #pragma comment(lib, "swscale.lib")  
  29. #ifdef __cplusplus  
  30. };  
  31. #endif  
  32.   
  33. AVFormatContext *pFormatCtx_Video = NULL, *pFormatCtx_Audio = NULL, *pFormatCtx_Out = NULL;  
  34. AVCodecContext  *pCodecCtx_Video;  
  35. AVCodec         *pCodec_Video;  
  36. AVFifoBuffer    *fifo_video = NULL;  
  37. AVAudioFifo     *fifo_audio = NULL;  
  38. int VideoIndex, AudioIndex;  
  39.   
  40. CRITICAL_SECTION AudioSection, VideoSection;  
  41.   
  42.   
  43.   
  44. SwsContext *img_convert_ctx;  
  45. int frame_size = 0;  
  46.   
  47. uint8_t *picture_buf = NULL, *frame_buf = NULL;  
  48.   
  49. bool bCap = true;  
  50.   
  51. DWORD WINAPI ScreenCapThreadProc( LPVOID lpParam );  
  52. DWORD WINAPI AudioCapThreadProc( LPVOID lpParam );  
  53.   
  54. int OpenVideoCapture()  
  55. {  
  56.     AVInputFormat *ifmt=av_find_input_format("gdigrab");  
  57.     //这里可以加参数打开,例如可以指定采集帧率  
  58.     AVDictionary *options = NULL;  
  59.     av_dict_set(&options, "framerate""15", NULL);  
  60.     //av_dict_set(&options,"offset_x","20",0);  
  61.     //The distance from the top edge of the screen or desktop  
  62.     //av_dict_set(&options,"offset_y","40",0);  
  63.     //Video frame size. The default is to capture the full screen  
  64.     //av_dict_set(&options,"video_size","320x240",0);  
  65.     if(avformat_open_input(&pFormatCtx_Video, "desktop", ifmt, &options)!=0)  
  66.     {  
  67.         printf("Couldn't open input stream.(无法打开视频输入流)\n");  
  68.         return -1;  
  69.     }  
  70.     if(avformat_find_stream_info(pFormatCtx_Video,NULL)<0)  
  71.     {  
  72.         printf("Couldn't find stream information.(无法获取视频流信息)\n");  
  73.         return -1;  
  74.     }  
  75.     if (pFormatCtx_Video->streams[0]->codec->codec_type != AVMEDIA_TYPE_VIDEO)  
  76.     {  
  77.         printf("Couldn't find video stream information.(无法获取视频流信息)\n");  
  78.         return -1;  
  79.     }  
  80.     pCodecCtx_Video = pFormatCtx_Video->streams[0]->codec;  
  81.     pCodec_Video = avcodec_find_decoder(pCodecCtx_Video->codec_id);  
  82.     if(pCodec_Video == NULL)  
  83.     {  
  84.         printf("Codec not found.(没有找到解码器)\n");  
  85.         return -1;  
  86.     }  
  87.     if(avcodec_open2(pCodecCtx_Video, pCodec_Video, NULL) < 0)  
  88.     {  
  89.         printf("Could not open codec.(无法打开解码器)\n");  
  90.         return -1;  
  91.     }  
  92.   
  93.       
  94.   
  95.     img_convert_ctx = sws_getContext(pCodecCtx_Video->width, pCodecCtx_Video->height, pCodecCtx_Video->pix_fmt,   
  96.         pCodecCtx_Video->width, pCodecCtx_Video->height, PIX_FMT_YUV420P, SWS_BICUBIC, NULL, NULL, NULL);   
  97.   
  98.     frame_size = avpicture_get_size(pCodecCtx_Video->pix_fmt, pCodecCtx_Video->width, pCodecCtx_Video->height);  
  99.     //申请30帧缓存  
  100.     fifo_video = av_fifo_alloc(30 * avpicture_get_size(AV_PIX_FMT_YUV420P, pCodecCtx_Video->width, pCodecCtx_Video->height));  
  101.   
  102.     return 0;  
  103. }  
  104.   
  105. static char *dup_wchar_to_utf8(wchar_t *w)  
  106. {  
  107.     char *s = NULL;  
  108.     int l = WideCharToMultiByte(CP_UTF8, 0, w, -1, 0, 0, 0, 0);  
  109.     s = (char *) av_malloc(l);  
  110.     if (s)  
  111.         WideCharToMultiByte(CP_UTF8, 0, w, -1, s, l, 0, 0);  
  112.     return s;  
  113. }  
  114.   
  115. int OpenAudioCapture()  
  116. {  
  117.     //查找输入方式  
  118.     AVInputFormat *pAudioInputFmt = av_find_input_format("dshow");  
  119.       
  120.     //以Direct Show的方式打开设备,并将 输入方式 关联到格式上下文  
  121.     char * psDevName = dup_wchar_to_utf8(L"audio=麦克风 (Realtek High Definition Au");  
  122.   
  123.     if (avformat_open_input(&pFormatCtx_Audio, psDevName, pAudioInputFmt,NULL) < 0)  
  124.     {  
  125.         printf("Couldn't open input stream.(无法打开音频输入流)\n");  
  126.         return -1;  
  127.     }  
  128.   
  129.     if(avformat_find_stream_info(pFormatCtx_Audio,NULL)<0)    
  130.         return -1;   
  131.       
  132.     if(pFormatCtx_Audio->streams[0]->codec->codec_type != AVMEDIA_TYPE_AUDIO)  
  133.     {  
  134.         printf("Couldn't find video stream information.(无法获取音频流信息)\n");  
  135.         return -1;  
  136.     }  
  137.   
  138.     AVCodec *tmpCodec = avcodec_find_decoder(pFormatCtx_Audio->streams[0]->codec->codec_id);  
  139.     if(0 > avcodec_open2(pFormatCtx_Audio->streams[0]->codec, tmpCodec, NULL))  
  140.     {  
  141.         printf("can not find or open audio decoder!\n");  
  142.     }  
  143.   
  144.       
  145.   
  146.     return 0;  
  147. }  
  148.   
  149. int OpenOutPut()  
  150. {  
  151.     AVStream *pVideoStream = NULL, *pAudioStream = NULL;  
  152.     const char *outFileName = "test.mp4";  
  153.     avformat_alloc_output_context2(&pFormatCtx_Out, NULL, NULL, outFileName);  
  154.   
  155.     if (pFormatCtx_Video->streams[0]->codec->codec_type == AVMEDIA_TYPE_VIDEO)  
  156.     {  
  157.         AVCodecContext *videoCodecCtx;  
  158.         VideoIndex = 0;  
  159.         pVideoStream = avformat_new_stream(pFormatCtx_Out, NULL);  
  160.   
  161.         if (!pVideoStream)  
  162.         {  
  163.             printf("can not new stream for output!\n");  
  164.             return -1;  
  165.         }  
  166.   
  167.         //set codec context param  
  168.         pVideoStream->codec->codec = avcodec_find_encoder(AV_CODEC_ID_MPEG4);  
  169.         pVideoStream->codec->height = pFormatCtx_Video->streams[0]->codec->height;  
  170.         pVideoStream->codec->width = pFormatCtx_Video->streams[0]->codec->width;  
  171.           
  172.         pVideoStream->codec->time_base = pFormatCtx_Video->streams[0]->codec->time_base;  
  173.         pVideoStream->codec->sample_aspect_ratio = pFormatCtx_Video->streams[0]->codec->sample_aspect_ratio;  
  174.         // take first format from list of supported formats  
  175.         pVideoStream->codec->pix_fmt = pFormatCtx_Out->streams[VideoIndex]->codec->codec->pix_fmts[0];  
  176.   
  177.         //open encoder  
  178.         if (!pVideoStream->codec->codec)  
  179.         {  
  180.             printf("can not find the encoder!\n");  
  181.             return -1;  
  182.         }  
  183.   
  184.         if (pFormatCtx_Out->oformat->flags & AVFMT_GLOBALHEADER)  
  185.             pVideoStream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;  
  186.   
  187.         if ((avcodec_open2(pVideoStream->codec, pVideoStream->codec->codec, NULL)) < 0)  
  188.         {  
  189.             printf("can not open the encoder\n");  
  190.             return -1;  
  191.         }  
  192.     }  
  193.   
  194.     if(pFormatCtx_Audio->streams[0]->codec->codec_type == AVMEDIA_TYPE_AUDIO)  
  195.     {  
  196.         AVCodecContext *pOutputCodecCtx;  
  197.         AudioIndex = 1;  
  198.         pAudioStream = avformat_new_stream(pFormatCtx_Out, NULL);  
  199.   
  200.         pAudioStream->codec->codec = avcodec_find_encoder(pFormatCtx_Out->oformat->audio_codec);  
  201.   
  202.         pOutputCodecCtx = pAudioStream->codec;  
  203.   
  204.         pOutputCodecCtx->sample_rate = pFormatCtx_Audio->streams[0]->codec->sample_rate;  
  205.         pOutputCodecCtx->channel_layout = pFormatCtx_Out->streams[0]->codec->channel_layout;  
  206.         pOutputCodecCtx->channels = av_get_channel_layout_nb_channels(pAudioStream->codec->channel_layout);  
  207.         if(pOutputCodecCtx->channel_layout == 0)  
  208.         {  
  209.             pOutputCodecCtx->channel_layout = AV_CH_LAYOUT_STEREO;  
  210.             pOutputCodecCtx->channels = av_get_channel_layout_nb_channels(pOutputCodecCtx->channel_layout);  
  211.   
  212.         }  
  213.         pOutputCodecCtx->sample_fmt = pAudioStream->codec->codec->sample_fmts[0];  
  214.         AVRational time_base={1, pAudioStream->codec->sample_rate};  
  215.         pAudioStream->time_base = time_base;  
  216.         //audioCodecCtx->time_base = time_base;  
  217.   
  218.         pOutputCodecCtx->codec_tag = 0;    
  219.         if (pFormatCtx_Out->oformat->flags & AVFMT_GLOBALHEADER)    
  220.             pOutputCodecCtx->flags |= CODEC_FLAG_GLOBAL_HEADER;  
  221.   
  222.         if (avcodec_open2(pOutputCodecCtx, pOutputCodecCtx->codec, 0) < 0)  
  223.         {  
  224.             //编码器打开失败,退出程序  
  225.             return -1;  
  226.         }  
  227.     }  
  228.   
  229.     if (!(pFormatCtx_Out->oformat->flags & AVFMT_NOFILE))  
  230.     {  
  231.         if(avio_open(&pFormatCtx_Out->pb, outFileName, AVIO_FLAG_WRITE) < 0)  
  232.         {  
  233.             printf("can not open output file handle!\n");  
  234.             return -1;  
  235.         }  
  236.     }  
  237.   
  238.     if(avformat_write_header(pFormatCtx_Out, NULL) < 0)  
  239.     {  
  240.         printf("can not write the header of the output file!\n");  
  241.         return -1;  
  242.     }  
  243.   
  244.     return 0;  
  245. }  
  246.   
  247. int _tmain(int argc, _TCHAR* argv[])  
  248. {  
  249.     av_register_all();  
  250.     avdevice_register_all();  
  251.     if (OpenVideoCapture() < 0)  
  252.     {  
  253.         return -1;  
  254.     }  
  255.     if (OpenAudioCapture() < 0)  
  256.     {  
  257.         return -1;  
  258.     }  
  259.     if (OpenOutPut() < 0)  
  260.     {  
  261.         return -1;  
  262.     }  
  263.       
  264.     InitializeCriticalSection(&VideoSection);  
  265.     InitializeCriticalSection(&AudioSection);  
  266.   
  267.     AVFrame *picture = av_frame_alloc();  
  268.     int size = avpicture_get_size(pFormatCtx_Out->streams[VideoIndex]->codec->pix_fmt,   
  269.         pFormatCtx_Out->streams[VideoIndex]->codec->width, pFormatCtx_Out->streams[VideoIndex]->codec->height);  
  270.     picture_buf = new uint8_t[size];  
  271.   
  272.     avpicture_fill((AVPicture *)picture, picture_buf,   
  273.         pFormatCtx_Out->streams[VideoIndex]->codec->pix_fmt,   
  274.         pFormatCtx_Out->streams[VideoIndex]->codec->width,   
  275.         pFormatCtx_Out->streams[VideoIndex]->codec->height);  
  276.   
  277.   
  278.   
  279.     //star cap screen thread  
  280.     CreateThread( NULL, 0, ScreenCapThreadProc, 0, 0, NULL);  
  281.     //star cap audio thread  
  282.     CreateThread( NULL, 0, AudioCapThreadProc, 0, 0, NULL);  
  283.     int64_t cur_pts_v=0,cur_pts_a=0;  
  284.     int VideoFrameIndex = 0, AudioFrameIndex = 0;  
  285.   
  286.     while(1)  
  287.     {  
  288.         if (_kbhit() != 0 && bCap)  
  289.         {  
  290.             bCap = false;  
  291.             Sleep(2000);//简单的用sleep等待采集线程关闭  
  292.         }  
  293.         if (fifo_audio && fifo_video)  
  294.         {  
  295.             int sizeAudio = av_audio_fifo_size(fifo_audio);  
  296.             int sizeVideo = av_fifo_size(fifo_video);  
  297.             //缓存数据写完就结束循环  
  298.             if (av_audio_fifo_size(fifo_audio) <= pFormatCtx_Out->streams[AudioIndex]->codec->frame_size &&   
  299.                 av_fifo_size(fifo_video) <= frame_size && !bCap)  
  300.             {  
  301.                 break;  
  302.             }  
  303.         }  
  304.   
  305.         if(av_compare_ts(cur_pts_v, pFormatCtx_Out->streams[VideoIndex]->time_base,   
  306.             cur_pts_a,pFormatCtx_Out->streams[AudioIndex]->time_base) <= 0)  
  307.         {  
  308.             //read data from fifo  
  309.             if (av_fifo_size(fifo_video) < frame_size && !bCap)  
  310.             {  
  311.                 cur_pts_v = 0x7fffffffffffffff;  
  312.             }  
  313.             if(av_fifo_size(fifo_video) >= size)  
  314.             {  
  315.                 EnterCriticalSection(&VideoSection);  
  316.                 av_fifo_generic_read(fifo_video, picture_buf, size, NULL);  
  317.                 LeaveCriticalSection(&VideoSection);  
  318.                   
  319.                 avpicture_fill((AVPicture *)picture, picture_buf,   
  320.                     pFormatCtx_Out->streams[VideoIndex]->codec->pix_fmt,   
  321.                     pFormatCtx_Out->streams[VideoIndex]->codec->width,   
  322.                     pFormatCtx_Out->streams[VideoIndex]->codec->height);  
  323.                   
  324.                 //pts = n * ((1 / timbase)/ fps);  
  325.                 picture->pts = VideoFrameIndex * ((pFormatCtx_Video->streams[0]->time_base.den / pFormatCtx_Video->streams[0]->time_base.num) / 15);  
  326.   
  327.                 int got_picture = 0;  
  328.                 AVPacket pkt;  
  329.                 av_init_packet(&pkt);  
  330.                   
  331.                 pkt.data = NULL;  
  332.                 pkt.size = 0;  
  333.                 int ret = avcodec_encode_video2(pFormatCtx_Out->streams[VideoIndex]->codec, &pkt, picture, &got_picture);  
  334.                 if(ret < 0)  
  335.                 {  
  336.                     //编码错误,不理会此帧  
  337.                     continue;  
  338.                 }  
  339.                   
  340.                 if (got_picture==1)  
  341.                 {  
  342.                     pkt.stream_index = VideoIndex;  
  343.                     pkt.pts = av_rescale_q_rnd(pkt.pts, pFormatCtx_Video->streams[0]->time_base,   
  344.                         pFormatCtx_Out->streams[VideoIndex]->time_base, (AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));    
  345.                     pkt.dts = av_rescale_q_rnd(pkt.dts,  pFormatCtx_Video->streams[0]->time_base,   
  346.                         pFormatCtx_Out->streams[VideoIndex]->time_base, (AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));    
  347.   
  348.                     pkt.duration = ((pFormatCtx_Out->streams[0]->time_base.den / pFormatCtx_Out->streams[0]->time_base.num) / 15);  
  349.   
  350.                     cur_pts_v = pkt.pts;  
  351.   
  352.                     ret = av_interleaved_write_frame(pFormatCtx_Out, &pkt);  
  353.                     //delete[] pkt.data;  
  354.                     av_free_packet(&pkt);  
  355.                 }  
  356.                 VideoFrameIndex++;  
  357.             }  
  358.         }  
  359.         else  
  360.         {  
  361.             if (NULL == fifo_audio)  
  362.             {  
  363.                 continue;//还未初始化fifo  
  364.             }  
  365.             if (av_audio_fifo_size(fifo_audio) < pFormatCtx_Out->streams[AudioIndex]->codec->frame_size && !bCap)  
  366.             {  
  367.                 cur_pts_a = 0x7fffffffffffffff;  
  368.             }  
  369.             if(av_audio_fifo_size(fifo_audio) >=   
  370.                 (pFormatCtx_Out->streams[AudioIndex]->codec->frame_size > 0 ? pFormatCtx_Out->streams[AudioIndex]->codec->frame_size : 1024))  
  371.             {  
  372.                 AVFrame *frame;  
  373.                 frame = av_frame_alloc();  
  374.                 frame->nb_samples = pFormatCtx_Out->streams[AudioIndex]->codec->frame_size>0 ? pFormatCtx_Out->streams[AudioIndex]->codec->frame_size: 1024;  
  375.                 frame->channel_layout = pFormatCtx_Out->streams[AudioIndex]->codec->channel_layout;  
  376.                 frame->format = pFormatCtx_Out->streams[AudioIndex]->codec->sample_fmt;  
  377.                 frame->sample_rate = pFormatCtx_Out->streams[AudioIndex]->codec->sample_rate;  
  378.                 av_frame_get_buffer(frame, 0);  
  379.   
  380.                 EnterCriticalSection(&AudioSection);  
  381.                 av_audio_fifo_read(fifo_audio, (void **)frame->data,   
  382.                     (pFormatCtx_Out->streams[AudioIndex]->codec->frame_size > 0 ? pFormatCtx_Out->streams[AudioIndex]->codec->frame_size : 1024));  
  383.                 LeaveCriticalSection(&AudioSection);  
  384.   
  385.                 if (pFormatCtx_Out->streams[0]->codec->sample_fmt != pFormatCtx_Audio->streams[AudioIndex]->codec->sample_fmt   
  386.                     || pFormatCtx_Out->streams[0]->codec->channels != pFormatCtx_Audio->streams[AudioIndex]->codec->channels   
  387.                     || pFormatCtx_Out->streams[0]->codec->sample_rate != pFormatCtx_Audio->streams[AudioIndex]->codec->sample_rate)  
  388.                 {  
  389.                     //如果输入和输出的音频格式不一样 需要重采样,这里是一样的就没做  
  390.                 }  
  391.   
  392.                 AVPacket pkt_out;  
  393.                 av_init_packet(&pkt_out);  
  394.                 int got_picture = -1;  
  395.                 pkt_out.data = NULL;  
  396.                 pkt_out.size = 0;  
  397.   
  398.                 frame->pts = AudioFrameIndex * pFormatCtx_Out->streams[AudioIndex]->codec->frame_size;  
  399.                 if (avcodec_encode_audio2(pFormatCtx_Out->streams[AudioIndex]->codec, &pkt_out, frame, &got_picture) < 0)  
  400.                 {  
  401.                     printf("can not decoder a frame");  
  402.                 }  
  403.                 av_frame_free(&frame);  
  404.                 if (got_picture)   
  405.                 {  
  406.                     pkt_out.stream_index = AudioIndex;  
  407.                     pkt_out.pts = AudioFrameIndex * pFormatCtx_Out->streams[AudioIndex]->codec->frame_size;  
  408.                     pkt_out.dts = AudioFrameIndex * pFormatCtx_Out->streams[AudioIndex]->codec->frame_size;  
  409.                     pkt_out.duration = pFormatCtx_Out->streams[AudioIndex]->codec->frame_size;  
  410.   
  411.                     cur_pts_a = pkt_out.pts;  
  412.                       
  413.                     int ret = av_interleaved_write_frame(pFormatCtx_Out, &pkt_out);  
  414.                     av_free_packet(&pkt_out);  
  415.                 }  
  416.                 AudioFrameIndex++;  
  417.             }  
  418.         }  
  419.     }  
  420.   
  421.     delete[] picture_buf;  
  422.   
  423.     av_fifo_free(fifo_video);  
  424.     av_audio_fifo_free(fifo_audio);  
  425.   
  426.     av_write_trailer(pFormatCtx_Out);  
  427.   
  428.     avio_close(pFormatCtx_Out->pb);  
  429.     avformat_free_context(pFormatCtx_Out);  
  430.   
  431.     if (pFormatCtx_Video != NULL)  
  432.     {  
  433.         avformat_close_input(&pFormatCtx_Video);  
  434.         pFormatCtx_Video = NULL;  
  435.     }  
  436.     if (pFormatCtx_Audio != NULL)  
  437.     {  
  438.         avformat_close_input(&pFormatCtx_Audio);  
  439.         pFormatCtx_Audio = NULL;  
  440.     }  
  441.   
  442.     return 0;  
  443. }  
  444.   
  445. DWORD WINAPI ScreenCapThreadProc( LPVOID lpParam )  
  446. {  
  447.     AVPacket packet;/* = (AVPacket *)av_malloc(sizeof(AVPacket))*/;  
  448.     int got_picture;  
  449.     AVFrame *pFrame;  
  450.     pFrame=avcodec_alloc_frame();  
  451.   
  452.     AVFrame *picture = avcodec_alloc_frame();  
  453.     int size = avpicture_get_size(pFormatCtx_Out->streams[VideoIndex]->codec->pix_fmt,   
  454.         pFormatCtx_Out->streams[VideoIndex]->codec->width, pFormatCtx_Out->streams[VideoIndex]->codec->height);  
  455.     //picture_buf = new uint8_t[size];  
  456.   
  457.     avpicture_fill((AVPicture *)picture, picture_buf,   
  458.         pFormatCtx_Out->streams[VideoIndex]->codec->pix_fmt,   
  459.         pFormatCtx_Out->streams[VideoIndex]->codec->width,   
  460.         pFormatCtx_Out->streams[VideoIndex]->codec->height);  
  461.   
  462.     FILE *p = NULL;  
  463.     p = fopen("proc_test.yuv""wb+");  
  464.     av_init_packet(&packet);  
  465.     int height = pFormatCtx_Out->streams[VideoIndex]->codec->height;  
  466.     int width = pFormatCtx_Out->streams[VideoIndex]->codec->width;  
  467.     int y_size=height*width;  
  468.     while(bCap)  
  469.     {  
  470.         packet.data = NULL;  
  471.         packet.size = 0;  
  472.         if (av_read_frame(pFormatCtx_Video, &packet) < 0)  
  473.         {  
  474.             continue;  
  475.         }  
  476.         if(packet.stream_index == 0)  
  477.         {  
  478.             if (avcodec_decode_video2(pCodecCtx_Video, pFrame, &got_picture, &packet) < 0)  
  479.             {  
  480.                 printf("Decode Error.(解码错误)\n");  
  481.                 continue;  
  482.             }  
  483.             if (got_picture)  
  484.             {  
  485.                 sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data, pFrame->linesize, 0,   
  486.                     pFormatCtx_Out->streams[VideoIndex]->codec->height, picture->data, picture->linesize);  
  487.                   
  488.                 if (av_fifo_space(fifo_video) >= size)  
  489.                 {  
  490.                     EnterCriticalSection(&VideoSection);                      
  491.                     av_fifo_generic_write(fifo_video, picture->data[0], y_size, NULL);  
  492.                     av_fifo_generic_write(fifo_video, picture->data[1], y_size/4, NULL);  
  493.                     av_fifo_generic_write(fifo_video, picture->data[2], y_size/4, NULL);  
  494.                     LeaveCriticalSection(&VideoSection);  
  495.                 }  
  496.             }  
  497.         }  
  498.         av_free_packet(&packet);  
  499.         //Sleep(50);  
  500.     }  
  501.     av_frame_free(&pFrame);  
  502.     av_frame_free(&picture);  
  503.     //delete[] picture_buf;  
  504.     return 0;  
  505. }  
  506.   
  507. DWORD WINAPI AudioCapThreadProc( LPVOID lpParam )  
  508. {  
  509.     AVPacket pkt;  
  510.     AVFrame *frame;  
  511.     frame = av_frame_alloc();  
  512.     int gotframe;  
  513.     while(bCap)  
  514.     {  
  515.         pkt.data = NULL;  
  516.         pkt.size = 0;  
  517.         if(av_read_frame(pFormatCtx_Audio,&pkt) < 0)  
  518.         {  
  519.             continue;  
  520.         }  
  521.           
  522.         if (avcodec_decode_audio4(pFormatCtx_Audio->streams[0]->codec, frame, &gotframe, &pkt) < 0)  
  523.         {  
  524.             av_frame_free(&frame);  
  525.             printf("can not decoder a frame");  
  526.             break;  
  527.         }  
  528.         av_free_packet(&pkt);  
  529.   
  530.         if (!gotframe)  
  531.         {  
  532.             continue;//没有获取到数据,继续下一次  
  533.         }  
  534.   
  535.         if (NULL == fifo_audio)  
  536.         {  
  537.             fifo_audio = av_audio_fifo_alloc(pFormatCtx_Audio->streams[0]->codec->sample_fmt,   
  538.                 pFormatCtx_Audio->streams[0]->codec->channels, 30 * frame->nb_samples);  
  539.         }  
  540.   
  541.         int buf_space = av_audio_fifo_space(fifo_audio);  
  542.         if (av_audio_fifo_space(fifo_audio) >= frame->nb_samples)  
  543.         {  
  544.             EnterCriticalSection(&AudioSection);  
  545.             av_audio_fifo_write(fifo_audio, (void **)frame->data, frame->nb_samples);  
  546.             LeaveCriticalSection(&AudioSection);  
  547.         }  
  548.     }  
  549.     av_frame_free(&frame);  
  550.     return 0;  
  551. }  


 注:上面的代码已经过修改,请重新下载工程(或者用代码覆盖以前的版本)。//8-25-15

3、工程地址

http://download.csdn.net/detail/dancing_night/9044441



猜你喜欢

转载自blog.csdn.net/boonya/article/details/80649018
今日推荐