织梦CMS - 轻松建站从此开始!

罗索

利用ffmpeg的filter混音

jackyhwei 发布于 2020-08-05 13:11 点击:次 
一个简单的混音demo,把文件a和文件b的音频混为一个音频流输出并存为文件,只处理每个文件的第一个音频流 注:源代码是网友Larry_Liang(1085803139)写的,我帮其调试通过,存在这里以免备忘
TAG: filter  混音  

概述

一个简单的混音demo,把文件a和文件b的音频混为一个音频流输出并存为文件,只处理每个文件的第一个音频流
注:源代码是网友Larry_Liang(1085803139)写的,我帮其调试通过,存在这里以免备忘

流程介绍

流程如下:

打开输入1->打开输入2->打开输出->初始化混音filter->开启采集线程和编码写文件循环

线程之间数据走向如下:

采集线程1采集到数据->解码->写入fifo1 |
采集线程2采集到数据->解码->写入fifo2 | ->主线程编码循环读取2个fifo->把数据压人filter->从filter中读取混音后数据->编码->写入文件

代码

  1. /* 
  2. *一个简单的混音demo,把文件a和文件b的音频混为一个音频流输出并存为文件,只处理每个文件的第一个音频流 
  3. *源代码是网友Larry_Liang(1085803139)写的,我帮其调试通过 
  4. *MK(821486004@qq.com) 
  5. */ 
  6.  
  7.  
  8. extern "C" 
  9. #include "libavcodec/avcodec.h" 
  10. #include "libavformat/avformat.h" 
  11. #include "libavdevice/avdevice.h" 
  12. #include "libavfilter/avfilter.h" 
  13. #include "libavfilter/avfiltergraph.h" 
  14. #include "libavfilter/buffersink.h" 
  15. #include "libavfilter/buffersrc.h" 
  16. #include "libavutil/audio_fifo.h" 
  17. #include "libavutil/avutil.h" 
  18. #include "libavutil/fifo.h" 
  19.  
  20. #pragma comment(lib, "avcodec.lib") 
  21. #pragma comment(lib, "avformat.lib") 
  22. #pragma comment(lib, "avutil.lib") 
  23. #pragma comment(lib, "avdevice.lib") 
  24. #pragma comment(lib, "avfilter.lib") 
  25.  
  26. //#pragma comment(lib, "avfilter.lib") 
  27. //#pragma comment(lib, "postproc.lib") 
  28. //#pragma comment(lib, "swresample.lib") 
  29. #pragma comment(lib, "swscale.lib") 
  30.  
  31. #include <windows.h> 
  32. #include <conio.h> 
  33. #include <time.h> 
  34.  
  35. enum CaptureState 
  36.     PREPARED, 
  37.     RUNNING, 
  38.     STOPPED, 
  39.     FINISHED 
  40. }; 
  41.  
  42.  typedef struct BufferSourceContext { 
  43.     const AVClass    *bscclass; 
  44.     AVFifoBuffer     *fifo; 
  45.     AVRational        time_base;     ///< time_base to set in the output link 
  46.     AVRational        frame_rate;    ///< frame_rate to set in the output link 
  47.     unsigned          nb_failed_requests; 
  48.     unsigned          warning_limit; 
  49.  
  50.     /* video only */ 
  51.     int               w, h; 
  52.     enum AVPixelFormat  pix_fmt; 
  53.     AVRational        pixel_aspect; 
  54.     char              *sws_param; 
  55.  
  56.     AVBufferRef *hw_frames_ctx; 
  57.  
  58.     /* audio only */ 
  59.     int sample_rate; 
  60.     enum AVSampleFormat sample_fmt; 
  61.     int channels; 
  62.     uint64_t channel_layout; 
  63.     char    *channel_layout_str; 
  64.  
  65.     int got_format_from_params; 
  66.     int eof; 
  67.  } BufferSourceContext; 
  68.  
  69. AVFormatContext* _fmt_ctx_spk = NULL; 
  70. AVFormatContext* _fmt_ctx_mic = NULL; 
  71. AVFormatContext* _fmt_ctx_out = NULL; 
  72. int _index_spk = -1; 
  73. int _index_mic = -1; 
  74. int _index_a_out = -1; 
  75.  
  76. AVFilterGraph* _filter_graph = NULL; 
  77. AVFilterContext* _filter_ctx_src_spk = NULL; 
  78. AVFilterContext* _filter_ctx_src_mic = NULL; 
  79. AVFilterContext* _filter_ctx_sink = NULL; 
  80.  
  81. CaptureState _state = CaptureState::PREPARED; 
  82.  
  83. CRITICAL_SECTION _section_spk; 
  84. CRITICAL_SECTION _section_mic; 
  85. AVAudioFifo* _fifo_spk = NULL; 
  86. AVAudioFifo* _fifo_mic = NULL; 
  87.  
  88. void InitRecorder() 
  89.     av_register_all(); 
  90.     avdevice_register_all(); 
  91.     avfilter_register_all(); 
  92.  
  93. int OpenSpeakerInput(char* inputForamt, char* url) 
  94.     AVInputFormat* ifmt = av_find_input_format(inputForamt); 
  95.     AVDictionary* opt1 = NULL; 
  96.     av_dict_set(&opt1, "rtbufsize""10M", 0); 
  97.  
  98.     int ret = 0; 
  99.     ret = avformat_open_input(&_fmt_ctx_spk, url, ifmt, &opt1); 
  100.     if (ret < 0) 
  101.     { 
  102.         printf("Speaker: failed to call avformat_open_input\n"); 
  103.         return -1; 
  104.     } 
  105.     ret = avformat_find_stream_info(_fmt_ctx_spk, NULL); 
  106.     if (ret < 0) 
  107.     { 
  108.         printf("Speaker: failed to call avformat_find_stream_info\n"); 
  109.         return -1; 
  110.     } 
  111.     for (int i = 0; i < _fmt_ctx_spk->nb_streams; i++) 
  112.     { 
  113.         if (_fmt_ctx_spk->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) 
  114.         { 
  115.             _index_spk = i; 
  116.             break
  117.         } 
  118.     } 
  119.     if (_index_spk < 0) 
  120.     { 
  121.         printf("Speaker: negative audio index\n"); 
  122.         return -1; 
  123.     } 
  124.     AVCodecContext* codec_ctx = _fmt_ctx_spk->streams[_index_spk]->codec; 
  125.     AVCodec* codec = avcodec_find_decoder(codec_ctx->codec_id); 
  126.     if (codec == NULL) 
  127.     { 
  128.         printf("Speaker: null audio decoder\n"); 
  129.         return -1; 
  130.     } 
  131.     ret = avcodec_open2(codec_ctx, codec, NULL); 
  132.     if (ret < 0) 
  133.     { 
  134.         printf("Speaker: failed to call avcodec_open2\n"); 
  135.         return -1; 
  136.     } 
  137.     av_dump_format(_fmt_ctx_spk, _index_spk, url, 0); 
  138.  
  139.     return 0; 
  140.  
  141. int OpenMicrophoneInput(char* inputForamt, char* url) 
  142.     AVInputFormat* ifmt = av_find_input_format(inputForamt); 
  143.     AVDictionary* opt1 = NULL; 
  144.     av_dict_set(&opt1, "rtbufsize""10M", 0); 
  145.  
  146.     int ret = 0; 
  147.     ret = avformat_open_input(&_fmt_ctx_mic, url, ifmt, &opt1); 
  148.     if (ret < 0) 
  149.     { 
  150.         printf("Microphone: failed to call avformat_open_input\n"); 
  151.         return -1; 
  152.     } 
  153.     ret = avformat_find_stream_info(_fmt_ctx_mic, NULL); 
  154.     if (ret < 0) 
  155.     { 
  156.         printf("Microphone: failed to call avformat_find_stream_info\n"); 
  157.         return -1; 
  158.     } 
  159.     for (int i = 0; i < _fmt_ctx_mic->nb_streams; i++) 
  160.     { 
  161.         if (_fmt_ctx_mic->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) 
  162.         { 
  163.             _index_mic = i; 
  164.             break
  165.         } 
  166.     } 
  167.     if (_index_mic < 0) 
  168.     { 
  169.         printf("Microphone: negative audio index\n"); 
  170.         return -1; 
  171.     } 
  172.     AVCodecContext* codec_ctx = _fmt_ctx_mic->streams[_index_mic]->codec; 
  173.     AVCodec* codec = avcodec_find_decoder(codec_ctx->codec_id); 
  174.     if (codec == NULL) 
  175.     { 
  176.         printf("Microphone: null audio decoder\n"); 
  177.         return -1; 
  178.     } 
  179.     ret = avcodec_open2(codec_ctx, codec, NULL); 
  180.     if (ret < 0) 
  181.     { 
  182.         printf("Microphone: failed to call avcodec_open2\n"); 
  183.         return -1; 
  184.     } 
  185.  
  186.     av_dump_format(_fmt_ctx_mic, _index_mic, url, 0); 
  187.  
  188.     return 0; 
  189.  
  190. int OpenFileOutput(char* fileName) 
  191.     int ret = 0; 
  192.     ret = avformat_alloc_output_context2(&_fmt_ctx_out, NULL, NULL, fileName); 
  193.     if (ret < 0) 
  194.     { 
  195.         printf("Mixer: failed to call avformat_alloc_output_context2\n"); 
  196.         return -1; 
  197.     } 
  198.     AVStream* stream_a = NULL; 
  199.     stream_a = avformat_new_stream(_fmt_ctx_out, NULL); 
  200.     if (stream_a == NULL) 
  201.     { 
  202.         printf("Mixer: failed to call avformat_new_stream\n"); 
  203.         return -1; 
  204.     } 
  205.     _index_a_out = 0; 
  206.  
  207.     stream_a->codec->codec_type = AVMEDIA_TYPE_AUDIO; 
  208.     AVCodec* codec_mp3 = avcodec_find_encoder(AV_CODEC_ID_MP3); 
  209.     stream_a->codec->codec = codec_mp3; 
  210.     stream_a->codec->sample_rate = 44100; 
  211.     stream_a->codec->channels = 2; 
  212.     stream_a->codec->channel_layout = av_get_default_channel_layout(2); 
  213.     stream_a->codec->sample_fmt = codec_mp3->sample_fmts[0]; 
  214.     stream_a->codec->bit_rate = 320000; 
  215.     stream_a->codec->time_base.num = 1; 
  216.     stream_a->codec->time_base.den = stream_a->codec->sample_rate; 
  217.     stream_a->codec->codec_tag = 0; 
  218.  
  219.  
  220.     if (_fmt_ctx_out->oformat->flags & AVFMT_GLOBALHEADER) 
  221.         stream_a->codec->flags |= CODEC_FLAG_GLOBAL_HEADER; 
  222.  
  223.     if (avcodec_open2(stream_a->codec, stream_a->codec->codec, NULL) < 0) 
  224.     { 
  225.         printf("Mixer: failed to call avcodec_open2\n"); 
  226.         return -1;  
  227.     } 
  228.     if (!(_fmt_ctx_out->oformat->flags & AVFMT_NOFILE)) 
  229.     { 
  230.         if (avio_open(&_fmt_ctx_out->pb, fileName, AVIO_FLAG_WRITE) < 0) 
  231.         { 
  232.             printf("Mixer: failed to call avio_open\n"); 
  233.             return -1; 
  234.         } 
  235.     } 
  236.  
  237.     if (avformat_write_header(_fmt_ctx_out, NULL) < 0) 
  238.     { 
  239.         printf("Mixer: failed to call avformat_write_header\n"); 
  240.         return -1; 
  241.     } 
  242.  
  243.     bool b = (!_fmt_ctx_out->streams[0]->time_base.num && _fmt_ctx_out->streams[0]->codec->time_base.num); 
  244.  
  245.     av_dump_format(_fmt_ctx_out, _index_a_out, fileName, 1); 
  246.  
  247.     _fifo_spk = av_audio_fifo_alloc(_fmt_ctx_spk->streams[_index_spk]->codec->sample_fmt, _fmt_ctx_spk->streams[_index_spk]->codec->channels, 30*_fmt_ctx_spk->streams[_index_spk]->codec->frame_size); 
  248.     _fifo_mic = av_audio_fifo_alloc(_fmt_ctx_mic->streams[_index_mic]->codec->sample_fmt, _fmt_ctx_mic->streams[_index_mic]->codec->channels, 30*_fmt_ctx_mic->streams[_index_spk]->codec->frame_size); 
  249.  
  250.     return 0; 
  251.  
  252. int InitFilter(char* filter_desc) 
  253.     char args_spk[512]; 
  254.     char* pad_name_spk = "in0"
  255.     char args_mic[512]; 
  256.     char* pad_name_mic = "in1"
  257.  
  258.     AVFilter* filter_src_spk = avfilter_get_by_name("abuffer"); 
  259.     AVFilter* filter_src_mic = avfilter_get_by_name("abuffer"); 
  260.     AVFilter* filter_sink = avfilter_get_by_name("abuffersink"); 
  261.     AVFilterInOut* filter_output_spk = avfilter_inout_alloc(); 
  262.     AVFilterInOut* filter_output_mic = avfilter_inout_alloc(); 
  263.     AVFilterInOut* filter_input = avfilter_inout_alloc(); 
  264.     _filter_graph = avfilter_graph_alloc(); 
  265.  
  266.     sprintf_s(args_spk, sizeof(args_spk), "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=0x%I64x",  
  267.         _fmt_ctx_spk->streams[_index_spk]->codec->time_base.num,  
  268.         _fmt_ctx_spk->streams[_index_spk]->codec->time_base.den,  
  269.         _fmt_ctx_spk->streams[_index_spk]->codec->sample_rate,  
  270.         av_get_sample_fmt_name(_fmt_ctx_spk->streams[_index_spk]->codec->sample_fmt),  
  271.         _fmt_ctx_spk->streams[_index_spk]->codec->channel_layout); 
  272.     sprintf_s(args_mic, sizeof(args_mic), "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=0x%I64x",  
  273.         _fmt_ctx_mic->streams[_index_mic]->codec->time_base.num,  
  274.         _fmt_ctx_mic->streams[_index_mic]->codec->time_base.den,  
  275.         _fmt_ctx_mic->streams[_index_mic]->codec->sample_rate,  
  276.         av_get_sample_fmt_name(_fmt_ctx_mic->streams[_index_mic]->codec->sample_fmt),  
  277.         _fmt_ctx_mic->streams[_index_mic]->codec->channel_layout); 
  278.  
  279.     //sprintf_s(args_spk, sizeof(args_spk), "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=0x%I64x", _fmt_ctx_out->streams[_index_a_out]->codec->time_base.num, _fmt_ctx_out->streams[_index_a_out]->codec->time_base.den, _fmt_ctx_out->streams[_index_a_out]->codec->sample_rate, av_get_sample_fmt_name(_fmt_ctx_out->streams[_index_a_out]->codec->sample_fmt), _fmt_ctx_out->streams[_index_a_out]->codec->channel_layout); 
  280.     //sprintf_s(args_mic, sizeof(args_mic), "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=0x%I64x", _fmt_ctx_out->streams[_index_a_out]->codec->time_base.num, _fmt_ctx_out->streams[_index_a_out]->codec->time_base.den, _fmt_ctx_out->streams[_index_a_out]->codec->sample_rate, av_get_sample_fmt_name(_fmt_ctx_out->streams[_index_a_out]->codec->sample_fmt), _fmt_ctx_out->streams[_index_a_out]->codec->channel_layout); 
  281.  
  282.  
  283.     int ret = 0; 
  284.     ret = avfilter_graph_create_filter(&_filter_ctx_src_spk, filter_src_spk, pad_name_spk, args_spk, NULL, _filter_graph); 
  285.     if (ret < 0) 
  286.     { 
  287.         printf("Filter: failed to call avfilter_graph_create_filter -- src spk\n"); 
  288.         return -1; 
  289.     } 
  290.     ret = avfilter_graph_create_filter(&_filter_ctx_src_mic, filter_src_mic, pad_name_mic, args_mic, NULL, _filter_graph); 
  291.     if (ret < 0) 
  292.     { 
  293.         printf("Filter: failed to call avfilter_graph_create_filter -- src mic\n"); 
  294.         return -1; 
  295.     } 
  296.  
  297.     ret = avfilter_graph_create_filter(&_filter_ctx_sink, filter_sink, "out", NULL, NULL, _filter_graph); 
  298.     if (ret < 0) 
  299.     { 
  300.         printf("Filter: failed to call avfilter_graph_create_filter -- sink\n"); 
  301.         return -1; 
  302.     } 
  303.     AVCodecContext* encodec_ctx = _fmt_ctx_out->streams[_index_a_out]->codec; 
  304.     ret = av_opt_set_bin(_filter_ctx_sink, "sample_fmts", (uint8_t*)&encodec_ctx->sample_fmt, sizeof(encodec_ctx->sample_fmt), AV_OPT_SEARCH_CHILDREN); 
  305.     if (ret < 0) 
  306.     { 
  307.         printf("Filter: failed to call av_opt_set_bin -- sample_fmts\n"); 
  308.         return -1; 
  309.     } 
  310.     ret = av_opt_set_bin(_filter_ctx_sink, "channel_layouts", (uint8_t*)&encodec_ctx->channel_layout, sizeof(encodec_ctx->channel_layout), AV_OPT_SEARCH_CHILDREN); 
  311.     if (ret < 0) 
  312.     { 
  313.         printf("Filter: failed to call av_opt_set_bin -- channel_layouts\n"); 
  314.         return -1; 
  315.     } 
  316.     ret = av_opt_set_bin(_filter_ctx_sink, "sample_rates", (uint8_t*)&encodec_ctx->sample_rate, sizeof(encodec_ctx->sample_rate), AV_OPT_SEARCH_CHILDREN); 
  317.     if (ret < 0) 
  318.     { 
  319.         printf("Filter: failed to call av_opt_set_bin -- sample_rates\n"); 
  320.         return -1; 
  321.     } 
  322.  
  323.     filter_output_spk->name = av_strdup(pad_name_spk); 
  324.     filter_output_spk->filter_ctx = _filter_ctx_src_spk; 
  325.     filter_output_spk->pad_idx = 0; 
  326.     filter_output_spk->next = filter_output_mic; 
  327.  
  328.     filter_output_mic->name = av_strdup(pad_name_mic); 
  329.     filter_output_mic->filter_ctx = _filter_ctx_src_mic; 
  330.     filter_output_mic->pad_idx = 0; 
  331.     filter_output_mic->next = NULL; 
  332.  
  333.     filter_input->name = av_strdup("out"); 
  334.     filter_input->filter_ctx = _filter_ctx_sink; 
  335.     filter_input->pad_idx = 0; 
  336.     filter_input->next = NULL; 
  337.  
  338.     AVFilterInOut* filter_outputs[2]; 
  339.     filter_outputs[0] = filter_output_spk; 
  340.     filter_outputs[1] = filter_output_mic; 
  341.  
  342.     ret = avfilter_graph_parse_ptr(_filter_graph, filter_desc, &filter_input, filter_outputs, NULL); 
  343.     if (ret < 0) 
  344.     { 
  345.         printf("Filter: failed to call avfilter_graph_parse_ptr\n"); 
  346.         return -1; 
  347.     } 
  348.  
  349.     ret = avfilter_graph_config(_filter_graph, NULL); 
  350.     if (ret < 0) 
  351.     { 
  352.         printf("Filter: failed to call avfilter_graph_config\n"); 
  353.         return -1; 
  354.     } 
  355.  
  356.     avfilter_inout_free(&filter_input); 
  357.     av_free(filter_src_spk); 
  358.     av_free(filter_src_mic); 
  359.     avfilter_inout_free(filter_outputs); 
  360.     //av_free(filter_outputs); 
  361.  
  362.     char* temp = avfilter_graph_dump(_filter_graph, NULL); 
  363.     printf("%s\n", temp); 
  364.  
  365.     return 0; 
  366.  
  367. DWORD WINAPI SpeakerCapThreadProc(LPVOID lpParam) 
  368.     AVFrame* pFrame = av_frame_alloc(); 
  369.     AVPacket packet; 
  370.     av_init_packet(&packet); 
  371.  
  372.     int got_sound; 
  373.  
  374.     while (_state == CaptureState::RUNNING) 
  375.     { 
  376.         packet.data = NULL; 
  377.         packet.size = 0; 
  378.  
  379.         if (av_read_frame(_fmt_ctx_spk, &packet) < 0) 
  380.         { 
  381.             continue
  382.         } 
  383.         if (packet.stream_index == _index_spk) 
  384.         { 
  385.             if (avcodec_decode_audio4(_fmt_ctx_spk->streams[_index_spk]->codec, pFrame, &got_sound, &packet) < 0) 
  386.             { 
  387.                 break
  388.             } 
  389.             av_free_packet(&packet); 
  390.  
  391.             if (!got_sound) 
  392.             { 
  393.                 continue
  394.             } 
  395.  
  396.             int fifo_spk_space = av_audio_fifo_space(_fifo_spk); 
  397.             while(fifo_spk_space < pFrame->nb_samples && _state == CaptureState::RUNNING) 
  398.             { 
  399.                 Sleep(10); 
  400.                 printf("_fifo_spk full !\n"); 
  401.                 fifo_spk_space = av_audio_fifo_space(_fifo_spk); 
  402.             } 
  403.  
  404.             if (fifo_spk_space >= pFrame->nb_samples) 
  405.             { 
  406.                 EnterCriticalSection(&_section_spk); 
  407.                 int nWritten = av_audio_fifo_write(_fifo_spk, (void**)pFrame->data, pFrame->nb_samples); 
  408.                 LeaveCriticalSection(&_section_spk); 
  409.             } 
  410.         } 
  411.     } 
  412.     av_frame_free(&pFrame); 
  413.  
  414.     return 0; 
  415.  
  416. DWORD WINAPI MicrophoneCapThreadProc(LPVOID lpParam) 
  417.     AVFrame* pFrame = av_frame_alloc(); 
  418.     AVPacket packet; 
  419.     av_init_packet(&packet); 
  420.  
  421.     int got_sound; 
  422.  
  423.     while (_state == CaptureState::PREPARED) 
  424.     { 
  425.  
  426.     } 
  427.  
  428.     while (_state == CaptureState::RUNNING) 
  429.     { 
  430.         packet.data = NULL; 
  431.         packet.size = 0; 
  432.  
  433.         if (av_read_frame(_fmt_ctx_mic, &packet) < 0) 
  434.         { 
  435.             continue
  436.         } 
  437.         if (packet.stream_index == _index_mic) 
  438.         { 
  439.             if (avcodec_decode_audio4(_fmt_ctx_mic->streams[_index_mic]->codec, pFrame, &got_sound, &packet) < 0) 
  440.             { 
  441.                 break
  442.             } 
  443.             av_free_packet(&packet); 
  444.  
  445.             if (!got_sound) 
  446.             { 
  447.                 continue
  448.             } 
  449.  
  450.             int fifo_mic_space = av_audio_fifo_space(_fifo_mic); 
  451.             while(fifo_mic_space < pFrame->nb_samples && _state == CaptureState::RUNNING) 
  452.             { 
  453.                 Sleep(10); 
  454.                 printf("_fifo_mic full !\n"); 
  455.                 fifo_mic_space = av_audio_fifo_space(_fifo_mic); 
  456.             } 
  457.  
  458.             if (fifo_mic_space >= pFrame->nb_samples) 
  459.             { 
  460.                 EnterCriticalSection(&_section_mic); 
  461.                 int temp = av_audio_fifo_space(_fifo_mic); 
  462.                 int temp2 = pFrame->nb_samples; 
  463.                 int nWritten = av_audio_fifo_write(_fifo_mic, (void**)pFrame->data, pFrame->nb_samples); 
  464.                 LeaveCriticalSection(&_section_mic); 
  465.             } 
  466.         } 
  467.     } 
  468.     av_frame_free(&pFrame); 
  469.  
  470.     return 0; 
  471.  
  472. int main() 
  473.     int ret = 0; 
  474.  
  475.     InitRecorder(); 
  476.  
  477.     char fileName[128]; 
  478.     char* outFileType = ".mp3"
  479.  
  480.     time_t rawtime; 
  481.     tm* timeInfo; 
  482.     time(&rawtime); 
  483.     timeInfo = localtime(&rawtime); 
  484.     sprintf_s(fileName, sizeof(fileName), "%d_%d_%d_%d_%d_%d%s"
  485.         timeInfo->tm_year + 1900, timeInfo->tm_mon + 1, timeInfo->tm_mday, 
  486.         timeInfo->tm_hour, timeInfo->tm_min, timeInfo->tm_sec, outFileType); 
  487.  
  488.     char* filter_desc = "[in0][in1]amix=inputs=2[out]"
  489.  
  490.     //ret = OpenSpeakerInput("dshow", "audio=virtual-audio-capturer"); 
  491.     ret = OpenSpeakerInput(NULL, "故乡.mp3"); 
  492.     if (ret < 0) 
  493.     { 
  494.         goto Release; 
  495.     } 
  496.     //ret = OpenMicrophoneInput("dshow", "audio=External Microphone (Conexant S"); 
  497.     ret = OpenMicrophoneInput(NULL, "旅行.mp3"); 
  498.     if (ret < 0) 
  499.     { 
  500.         goto Release; 
  501.     } 
  502.     ret = OpenFileOutput(fileName); 
  503.     if (ret < 0) 
  504.     { 
  505.         goto Release; 
  506.     } 
  507.     ret = InitFilter(filter_desc); 
  508.     if (ret < 0) 
  509.     { 
  510.         goto Release; 
  511.     } 
  512.  
  513.     _state = CaptureState::RUNNING; 
  514.  
  515.     InitializeCriticalSection(&_section_spk); 
  516.     InitializeCriticalSection(&_section_mic); 
  517.  
  518.     CreateThread(NULL, 0, SpeakerCapThreadProc, 0, 0, NULL); 
  519.     CreateThread(NULL, 0, MicrophoneCapThreadProc, 0, 0, NULL); 
  520.  
  521.     int tmpFifoFailed = 0; 
  522.     int64_t frame_count = 0; 
  523.  
  524.     while (_state != CaptureState::FINISHED) 
  525.     { 
  526.         if (_kbhit()) 
  527.         { 
  528.             _state = CaptureState::STOPPED; 
  529.             break
  530.         } 
  531.         else 
  532.         { 
  533.             int ret = 0; 
  534.             AVFrame* pFrame_spk = av_frame_alloc(); 
  535.             AVFrame* pFrame_mic = av_frame_alloc(); 
  536.  
  537.  
  538.             AVPacket packet_out; 
  539.  
  540.             int got_packet_ptr = 0; 
  541.  
  542.             int fifo_spk_size = av_audio_fifo_size(_fifo_spk); 
  543.             int fifo_mic_size = av_audio_fifo_size(_fifo_mic); 
  544.             int frame_spk_min_size = _fmt_ctx_spk->streams[_index_spk]->codec->frame_size; 
  545.             int frame_mic_min_size = _fmt_ctx_mic->streams[_index_mic]->codec->frame_size; 
  546.             if (fifo_spk_size >= frame_spk_min_size && fifo_mic_size >= frame_mic_min_size) 
  547.             { 
  548.                 tmpFifoFailed = 0; 
  549.  
  550.                 pFrame_spk->nb_samples = frame_spk_min_size; 
  551.                 pFrame_spk->channel_layout = _fmt_ctx_spk->streams[_index_spk]->codec->channel_layout; 
  552.                 pFrame_spk->format = _fmt_ctx_spk->streams[_index_spk]->codec->sample_fmt; 
  553.                 pFrame_spk->sample_rate = _fmt_ctx_spk->streams[_index_spk]->codec->sample_rate; 
  554.                 av_frame_get_buffer(pFrame_spk, 0); 
  555.  
  556.                 pFrame_mic->nb_samples = frame_mic_min_size; 
  557.                 pFrame_mic->channel_layout = _fmt_ctx_mic->streams[_index_mic]->codec->channel_layout; 
  558.                 pFrame_mic->format = _fmt_ctx_mic->streams[_index_mic]->codec->sample_fmt; 
  559.                 pFrame_mic->sample_rate = _fmt_ctx_mic->streams[_index_mic]->codec->sample_rate; 
  560.                 av_frame_get_buffer(pFrame_mic, 0); 
  561.  
  562.                 EnterCriticalSection(&_section_spk); 
  563.                 ret = av_audio_fifo_read(_fifo_spk, (void**)pFrame_spk->data, frame_spk_min_size); 
  564.                 LeaveCriticalSection(&_section_spk); 
  565.  
  566.                 EnterCriticalSection(&_section_mic); 
  567.                 ret = av_audio_fifo_read(_fifo_mic, (void**)pFrame_mic->data, frame_mic_min_size); 
  568.                 LeaveCriticalSection(&_section_mic); 
  569.  
  570.                 pFrame_spk->pts = av_frame_get_best_effort_timestamp(pFrame_spk); 
  571.                 pFrame_mic->pts = av_frame_get_best_effort_timestamp(pFrame_mic); 
  572.  
  573.                 BufferSourceContext* s = (BufferSourceContext*)_filter_ctx_src_spk->priv; 
  574.                 bool b1 = (s->sample_fmt != pFrame_spk->format); 
  575.                 bool b2 = (s->sample_rate != pFrame_spk->sample_rate); 
  576.                 bool b3 = (s->channel_layout != pFrame_spk->channel_layout); 
  577.                 bool b4 = (s->channels != pFrame_spk->channels); 
  578.  
  579.                 ret = av_buffersrc_add_frame(_filter_ctx_src_spk, pFrame_spk); 
  580.                 if (ret < 0) 
  581.                 { 
  582.                     printf("Mixer: failed to call av_buffersrc_add_frame (speaker)\n"); 
  583.                     break
  584.                 } 
  585.  
  586.                 ret = av_buffersrc_add_frame(_filter_ctx_src_mic, pFrame_mic); 
  587.                 if (ret < 0) 
  588.                 { 
  589.                     printf("Mixer: failed to call av_buffersrc_add_frame (microphone)\n"); 
  590.                     break
  591.                 } 
  592.  
  593.                 while (1) 
  594.                 { 
  595.                     AVFrame* pFrame_out = av_frame_alloc(); 
  596.  
  597.                     ret = av_buffersink_get_frame_flags(_filter_ctx_sink, pFrame_out, 0); 
  598.                     if (ret < 0) 
  599.                     { 
  600.                         printf("Mixer: failed to call av_buffersink_get_frame_flags\n"); 
  601.                         break
  602.                     } 
  603.                     if (pFrame_out->data[0] != NULL) 
  604.                     { 
  605.                         av_init_packet(&packet_out); 
  606.                         packet_out.data = NULL; 
  607.                         packet_out.size = 0; 
  608.  
  609.                         ret = avcodec_encode_audio2(_fmt_ctx_out->streams[_index_a_out]->codec, &packet_out, pFrame_out, &got_packet_ptr); 
  610.                         if (ret < 0) 
  611.                         { 
  612.                             printf("Mixer: failed to call avcodec_decode_audio4\n"); 
  613.                             break
  614.                         } 
  615.                         if (got_packet_ptr) 
  616.                         { 
  617.                             packet_out.stream_index = _index_a_out; 
  618.                             packet_out.pts = frame_count * _fmt_ctx_out->streams[_index_a_out]->codec->frame_size; 
  619.                             packet_out.dts = packet_out.pts; 
  620.                             packet_out.duration = _fmt_ctx_out->streams[_index_a_out]->codec->frame_size; 
  621.  
  622.                             packet_out.pts = av_rescale_q_rnd(packet_out.pts,  
  623.                                 _fmt_ctx_out->streams[_index_a_out]->codec->time_base, 
  624.                                 _fmt_ctx_out->streams[_index_a_out]->time_base, 
  625.                                 (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX)); 
  626.                             packet_out.dts = packet_out.pts; 
  627.                             packet_out.duration = av_rescale_q_rnd(packet_out.duration, 
  628.                                 _fmt_ctx_out->streams[_index_a_out]->codec->time_base, 
  629.                                 _fmt_ctx_out->streams[_index_a_out]->time_base, 
  630.                                 (AVRounding)(AV_ROUND_NEAR_INF | AV_ROUND_PASS_MINMAX)); 
  631.  
  632.                             frame_count++; 
  633.  
  634.                             ret = av_interleaved_write_frame(_fmt_ctx_out, &packet_out); 
  635.                             if (ret < 0) 
  636.                             { 
  637.                                 printf("Mixer: failed to call av_interleaved_write_frame\n"); 
  638.                             } 
  639.                             printf("Mixer: write frame to file\n"); 
  640.                         } 
  641.                         av_free_packet(&packet_out);                     
  642.                     } 
  643.                     av_frame_free(&pFrame_out); 
  644.                 } 
  645.             } 
  646.             else 
  647.             { 
  648.                 tmpFifoFailed++; 
  649.                 Sleep(20); 
  650.                 if (tmpFifoFailed > 300) 
  651.                 { 
  652.                     _state = CaptureState::STOPPED; 
  653.                     Sleep(30); 
  654.                     break
  655.                 } 
  656.             } 
  657.             av_frame_free(&pFrame_spk); 
  658.             av_frame_free(&pFrame_mic); 
  659.         } 
  660.     } 
  661.  
  662.     av_write_trailer(_fmt_ctx_out); 
  663.  
  664. Release: 
  665.     av_audio_fifo_free(_fifo_spk); 
  666.     av_audio_fifo_free(_fifo_mic); 
  667.  
  668.     avfilter_free(_filter_ctx_src_spk); 
  669.     avfilter_free(_filter_ctx_src_mic); 
  670.     avfilter_free(_filter_ctx_sink); 
  671.  
  672.     avfilter_graph_free(&_filter_graph); 
  673.  
  674.  
  675.     if (_fmt_ctx_out) 
  676.     { 
  677.         avio_close(_fmt_ctx_out->pb); 
  678.     } 
  679.  
  680.     avformat_close_input(&_fmt_ctx_spk); 
  681.     avformat_close_input(&_fmt_ctx_mic); 
  682.     avformat_free_context(_fmt_ctx_out); 
  683.  
  684.     return ret; 
(dancing_night)
本站文章除注明转载外,均为本站原创或编译欢迎任何形式的转载,但请务必注明出处,尊重他人劳动,同学习共成长。转载请注明:文章转载自:罗索实验室 [http://www.rosoo.net/a/202008/17718.html]
本文出处:CSDN博客 作者:dancing_night 原文
顶一下
(0)
0%
踩一下
(0)
0%
------分隔线----------------------------
相关文章
发表评论
请自觉遵守互联网相关的政策法规,严禁发布色情、暴力、反动的言论。
评价:
表情:
用户名: 验证码:点击我更换图片
栏目列表
将本文分享到微信
织梦二维码生成器
推荐内容