辽宁住房和城乡建设厅网站首页,广告设计哪里可以学,网站的icp 备案信息,3d建模工资一般多少本课对应源文件下载链接#xff1a;
https://download.csdn.net/download/XiBuQiuChong/88801992 通过前面的学习#xff0c;我们已经可以正常播放网络rtmp流及本地mp4文件。这节课#xff0c;我们将在前面的基础上实现一个常用的转推功能#xff1a;读取rtmp流或mp4文件并…本课对应源文件下载链接
https://download.csdn.net/download/XiBuQiuChong/88801992 通过前面的学习我们已经可以正常播放网络rtmp流及本地mp4文件。这节课我们将在前面的基础上实现一个常用的转推功能读取rtmp流或mp4文件并转推到rtmp服务器上实现直播转发功能。
一、最终实现的效果 上面左图为播放的rtmp流并将该流转推到另一台rtmp服务器右图为用vlc播放的另一台rtmp服务器上被转发的流。
二、使用FFmpeg将rtmp流转推到另一台rtmp服务器的原理
使用FFmpeg API 转码推流的一般过程如下
1.引入ffmpeg库在代码中引入ffmpeg库以便使用其提供的功能。
2.打开输入文件使用avformat_open_input()函数打开输入文件并获取输入文件的相关信息。
3.查找流信息使用avformat_find_stream_info()函数查找输入文件中的流信息并将其存储在AVFormatContext结构体中。
4.创建输出上下文使用avformat_alloc_output_context2()函数创建输出上下文并设置输出格式。
5.添加输出流根据输入文件的流信息使用avformat_new_stream()函数创建输出流并将其添加到输出上下文中。
6.设置编码参数为输出流设置编码参数包括编码器、编码器参数等。
7.输出文件使用avio_open()函数打开输出文件并将输出文件的相关信息存储在输出上下文中。
8.写入文件头使用avformat_write_header()函数写入输出文件的文件头。
9.转码推流循环读取输入文件的数据包使用av_read_frame()函数读取数据包然后使用avcodec_send_frame()函数发送数据包给编码器进行编码再使用avcodec_receive_packet()函数接收编码后的数据包最后使用av_interleaved_write_frame()函数将编码后的数据包写入输出流。
10.写入文件尾使用av_write_trailer()函数写入输出文件的文件尾。
11.释放资源释放所有的上下文、流和其他资源使用avformat_close_input()函数关闭输入文件。
三、转推功能的具体实现
与rtmp流或mp4文件播放功能相比转推功能只是在原来的基础上又增加了编码功能和向rtmp服务器的推送功能。为了降低难度这节课的转推功能不涉及编码部分只实现将拉取来的rtmp流直接进行转推。
1.为了与上节课的播放功能区分新建或直接复制fmlpFlash Media Live Player类为一个新的fmltFlash Media Live Transcoder类并修改主对话框相应代码使fmlt能正常工作并实现正常的播放功能。
修改如下
//#include fmlp.h
#include fmlt.h
………………
//fmlp *myFmlp new fmlp();
fmlt *myFmlt new fmlt();2.与mp4文件相比rtmp流转推实现起来相对容易因此我们先在原来的基础上实现rtmp流的转推功能。
1直接拷贝原fmlp.cpp的代码到fmt.cpp中并定义转推到另一台rtmp服务器的流地址等变量
//转码输出初始化 const char *outFileName rtmp://192.168.0.101/hk/cctv; AVOutputFormat *outFormat NULL;AVFormatContext *outFormatCtx NULL;//定义输出音视频流AVStream *videoStream NULL;AVStream *audioStream NULL;2打开输出流
avformat_alloc_output_context2(outFormatCtx, NULL, flv, outFileName);………………videoStream avformat_new_stream(outFormatCtx, vDecodec);videoStream-id outFormatCtx-nb_streams - 1;videoStream-codecpar-codec_tag 0;avcodec_parameters_from_context(videoStream-codecpar, vDecodeCtx);audioStream avformat_new_stream(outFormatCtx, aDecodec);audioStream-codecpar-codec_tag 0;audioStream-id outFormatCtx-nb_streams - 1;avcodec_parameters_from_context(audioStream-codecpar, aDecodeCtx);av_dump_format(outFormatCtx, 0, outFileName, 1);ret avio_open2(outFormatCtx-pb, outFileName, AVIO_FLAG_READ_WRITE, nullptr, nullptr);if (ret 0){return -1;}ret avformat_write_header(outFormatCtx, NULL);if (ret 0){TRACE(ret:%d\n, ret);return -1;}
3获取到原rtmp流并正常播放音视频后将音视频包直接写入输出流
if (normalPkt.stream_index videoIndex) {//原视频播放代码normalPkt.stream_index videoStream-index;normalPkt.pts currentTime;normalPkt.dts currentTime;normalPkt.duration currentTime;normalPkt.pos -1;//enVideoPacket.flags AV_PKT_FLAG_KEY;if (normalPkt.size 0){ret av_interleaved_write_frame(outFormatCtx, normalPkt);}av_packet_unref(normalPkt);}else if (normalPkt.stream_index audioIndex){ //原音频播放代码normalPkt.stream_index audioStream-index;normalPkt.pts currentTime;normalPkt.dts currentTime;normalPkt.duration currentTime;normalPkt.pos -1;//enVideoPacket.flags AV_PKT_FLAG_KEY;if (normalPkt.size 0){ret av_interleaved_write_frame(outFormatCtx, normalPkt);}av_packet_unref(normalPkt);}
这样就实现了在播放音视频的同时又能将该流转推到另一台服务器的功能。