弱龄寄事外,委怀在琴书。这篇文章主要讲述Android 音视频深入 十七 FFmpeg 获取RTMP流保存为flv (附源码下载)相关的知识,希望能为你提供帮助。
项目地址
https://github.com/979451341/RtmpSave
这个项目主要代码我是从雷神那弄过来的,不愧是雷神,我就配个环境搞个界面就可以用代码了。
这一次说的是将RTMP流媒体保存成为一个本地的FLV文件。因为播放视频本身占有很多技术难点,我先不做边获取RTMP流边播放了,这一次主要说如何获取RTMP流。
说说代码
初始化组件和网络环境
av_register_all();
//Network
avformat_network_init();
打开RTMP流,获取RTMP流的信息,并搜索到其中视频流的位置
//Input
if ((ret = avformat_open_input(&
ifmt_ctx, in_filename, 0, 0)) <
0) {
printf( "Could not open input file.");
goto end;
}
if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) <
0) {
printf( "Failed to retrieve input stream information");
goto end;
}for(i=0;
i<
ifmt_ctx->
nb_streams;
i++)
if(ifmt_ctx->
streams[i]->
codec->
codec_type==AVMEDIA_TYPE_VIDEO){
videoindex=i;
break;
}
将RTMP流的一些配置信息保存在输入环境信息
av_dump_format(ifmt_ctx, 0, in_filename, 0);
根据输出flv文件名称和路径得到输出环境信息
avformat_alloc_output_context2(&
ofmt_ctx, NULL, NULL, out_filename);
//RTMPif (!ofmt_ctx) {
printf( "Could not create output context\n");
ret = AVERROR_UNKNOWN;
goto end;
}
把输出环境信息的输出格式信息保存在ofmt
ofmt = ofmt_ctx-> oformat;
创建一条输出环境信息的流,就将输如环境信息里一条流复制到其中,并对每一条流的编码做出配置
for (i = 0;
i <
ifmt_ctx->
nb_streams;
i++) {
//Create output AVStream according to input AVStream
AVStream *in_stream = ifmt_ctx->
streams[i];
AVStream *out_stream = avformat_new_stream(ofmt_ctx, in_stream->
codec->
codec);
if (!out_stream) {
printf( "Failed allocating output stream\n");
ret = AVERROR_UNKNOWN;
goto end;
}
//Copy the settings of AVCodecContext
ret = avcodec_copy_context(out_stream->
codec, in_stream->
codec);
if (ret <
0) {
printf( "Failed to copy context from input to output stream codec context\n");
goto end;
}
out_stream->
codec->
codec_tag = 0;
if (ofmt_ctx->
oformat->
flags &
AVFMT_GLOBALHEADER)
out_stream->
codec->
flags |= CODEC_FLAG_GLOBAL_HEADER;
}
调试函数
av_dump_format(ofmt_ctx, 0, out_filename, 1);
打开输出url路径
if (!(ofmt->
flags &
AVFMT_NOFILE)) {
ret = avio_open(&
ofmt_ctx->
pb, out_filename, AVIO_FLAG_WRITE);
if (ret <
0) {
printf( "Could not open output URL ‘%s‘", out_filename);
goto end;
}
}
向输出环境写入文件头部
//Write file header
ret = avformat_write_header(ofmt_ctx, NULL);
if (ret <
0) {
printf( "Error occurred when opening output URL\n");
goto end;
}
配置H264编码器
#if USE_H264BSF
AVBitStreamFilterContext* h264bsfc =av_bitstream_filter_init(" h264_mp4toannexb" );
#endif
开始循环读帧写入flv文件
读取一帧RTMP流的视屏流数据
ret = av_read_frame(ifmt_ctx, &
pkt);
if (ret <
0)
break;
计算对应这一帧输入RTMP流数据的一帧输出数据的相关显示帧时间pts,解码帧时间dts,距离上一帧到下一帧的播放时间差距duration
pkt.pts = av_rescale_q_rnd(pkt.pts, in_stream->
time_base, out_stream->
time_base, (AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));
pkt.dts = av_rescale_q_rnd(pkt.dts, in_stream->
time_base, out_stream->
time_base, (AVRounding)(AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX));
pkt.duration = av_rescale_q(pkt.duration, in_stream->
time_base, out_stream->
time_base);
根据H264编码格式转换一帧输出数据
#if USE_H264BSF
av_bitstream_filter_filter(h264bsfc, in_stream-> codec, NULL, & pkt.data, & pkt.size, pkt.data, pkt.size, 0);
#endif
将这一帧输出数据写入flv文件,然后释放这一帧数据
ret = av_interleaved_write_frame(ofmt_ctx, &
pkt);
if (ret <
0) {
printf( "Error muxing packet\n");
break;
}av_free_packet(&
pkt);
关闭H264编码器
#if USE_H264BSF
av_bitstream_filter_close(h264bsfc);
#endif
释放输入、输出环境
av_write_trailer(ofmt_ctx);
end:
avformat_close_input(&
ifmt_ctx);
/* close output */
if (ofmt_ctx &
&
!(ofmt->
flags &
AVFMT_NOFILE))
avio_close(ofmt_ctx->
pb);
avformat_free_context(ofmt_ctx);
if (ret <
0 &
&
ret != AVERROR_EOF) {
printf( "Error occurred.\n");
return -1;
}
说说app的使用
【Android 音视频深入 十七 FFmpeg 获取RTMP流保存为flv (附源码下载)】那个点击button就可以了,点击后它会字样会变成started,这样他就在保存RTMP流文件了,过一两分钟就相应路径去看就可以了
推荐阅读
- App 区别
- Appium Desired Capabilities信息配置
- NetApp7mode环境下配置VSCAN
- MATLAB高斯和高斯-乔丹消除
- Win10 Windows无法访问局域网共享电脑的处理办法
- Win10易升一直删除不掉,删除后又出现怎样办?
- Win10系统打开添加删除程序的办法
- Win10系统桌面安装天气插件的办法
- Win10运行origin闪退的处理办法