最好经手一个小的功能将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