最好經手一個小的功能將mp2實時流轉成AAC併發布成rtmp音頻流,自己不是很難的一個需求,php
一個晚上就能將功能開發好。功能開發完畢後,找來一音頻文件利用Ffmpeg命令將音視頻文件推成併發
實時udp格式音頻流,具體的推送命令是:測試
ffmpeg.exe -r -i F:\test.mp2 -acodec copy -f mp2 udp://127.0.0.1:1234
測試程序以udp://127.0.0.1:1234爲輸入源,rtmp://127.0.0.1/live/stream爲輸出流。從輸入到輸出編碼
通過解碼、過濾器、編碼最後封裝,這些基本的原理及代碼以前的博文已經寫過,也有相關的視頻進行spa
講述,本文再也不贅述。線程
測試程序運行後,經過ffplay播放輸出音頻流地址rtmp://127.0.0.1/live/stream,開始一分鐘左右能夠code
音頻播放正常,過了一分鐘後聲音出現卡頓。開始覺得是推送的速度問題,對原有的程序作了些改進:將視頻
讀包一單獨線程,編解碼及發送單獨一線程。修改程序後,卡頓的現象還在,顯然沒有找到問題。接下來blog
考慮多是讀udp數據出了問題,增長各類UDP參數設置從新再測試,卡頓的現象依然在。通過多番折騰教程
發現問題出在filter上:filter SRC端每Push一次,SINK端須要一直讀取Frame直到讀取方法返回負值。源
代碼也是這麼寫的,不當心埋了Bug,實際執行的狀況是每次SINK端只讀一次即返回。正常的代碼片斷以下
void Transcode(std::shared_ptr<AVPacket> packet) { int gotOutput = 0; AVFrame *pSrcAudioFrame = av_frame_alloc(); bool decodeResult = decodeAudio(packet.get(),pSrcAudioFrame); if(decodeResult) { while (true) { AVFrame *filtFrame = av_frame_alloc(); int ret = av_buffersink_get_frame_flags(buffersinkCtx, filtFrame, 0); if(ret < 0) { av_frame_free(&filtFrame); break; } std::shared_ptr<AVPacket> pkt(static_cast<AVPacket*>(av_malloc(sizeof(AVPacket))), [&](AVPacket *p) { av_packet_free(&p); av_freep(&p); }); av_init_packet(pkt.get()); pkt->data = NULL; pkt->size = 0; ret = avcodec_encode_audio2(encodeContext, pkt.get(), filtFrame, &gotOutput); if (ret >= 0 && gotOutput) { WritePacket(pkt); } av_frame_free(&filtFrame); } } av_frame_free(&pSrcAudioFrame); }
如需交流可加QQ羣766718184 或者QQ3501870
博主提供Ffmpeg、GB28181視頻教程
播放地址: http://www.iqiyi.com/u/1426749687
源碼及Demo下載地址:http://www.chungen90.com/index.php?m=text&a=index&classify_id=207視頻下載地址: http://www.chungen90.com/index.php?m=text&a=index&classify_id=208