项目地址
https://github.com/979451341/RtmpSave

这个项目主要代码我是从雷神那弄过来的,不愧是雷神,我就配个环境搞个界面就可以用代码了。

这一次说的是将RTMP流媒体保存成为一个本地的FLV文件。因为播放视频本身占有很多技术难点,我先不做边获取RTMP流边播放了,这一次主要说如何获取RTMP流。

说说代码

初始化组件和网络环境

  1. av_register_all();
  2. //Network
  3. avformat_network_init();

打开RTMP流,获取RTMP流的信息,并搜索到其中视频流的位置

  1. //Input
  2. if ((ret = avformat_open_input(&ifmt_ctx, in_filename, 0, 0)) < 0) {
  3. printf( "Could not open input file.");
  4. goto end;
  5. }
  6. if ((ret = avformat_find_stream_info(ifmt_ctx, 0)) < 0) {
  7. printf( "Failed to retrieve input stream information");
  8. goto end;
  9. }
  10.  
  11. for(i=0; i<ifmt_ctx->nb_streams; i++)
  12. if(ifmt_ctx->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO){
  13. videoindex=i;
  14. break;
  15. }

将RTMP流的一些配置信息保存在输入环境信息

  1. av_dump_format(ifmt_ctx, 0, in_filename, 0);

根据输出flv文件名称和路径得到输出环境信息

  1. avformat_alloc_output_context2(&ofmt_ctx, NULL, NULL, out_filename); //RTMP
  2.  
  3. if (!ofmt_ctx) {
  4. printf( "Could not create output context\n");
  5. ret = AVERROR_UNKNOWN;
  6. goto end;
  7. }

把输出环境信息的输出格式信息保存在ofmt

  1. ofmt = ofmt_ctx->oformat;

创建一条输出环境信息的流,就将输如环境信息里一条流复制到其中,并对每一条流的编码做出配置

  1. for (i = 0; i < ifmt_ctx->nb_streams; i++) {
  2. //Create output AVStream according to input AVStream
  3. AVStream *in_stream = ifmt_ctx->streams[i];
  4. AVStream *out_stream = avformat_new_stream(ofmt_ctx, in_stream->codec->codec);
  5. if (!out_stream) {
  6. printf( "Failed allocating output stream\n");
  7. ret = AVERROR_UNKNOWN;
  8. goto end;
  9. }
  10. //Copy the settings of AVCodecContext
  11. ret = avcodec_copy_context(out_stream->codec, in_stream->codec);
  12. if (ret < 0) {
  13. printf( "Failed to copy context from input to output stream codec context\n");
  14. goto end;
  15. }
  16. out_stream->codec->codec_tag = 0;
  17. if (ofmt_ctx->oformat->flags & AVFMT_GLOBALHEADER)
  18. out_stream->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;
  19. }

调试函数

  1. av_dump_format(ofmt_ctx, 0, out_filename, 1);

打开输出url路径

  1. if (!(ofmt->flags & AVFMT_NOFILE)) {
  2. ret = avio_open(&ofmt_ctx->pb, out_filename, AVIO_FLAG_WRITE);
  3. if (ret < 0) {
  4. printf( "Could not open output URL '%s'", out_filename);
  5. goto end;
  6. }
  7. }

向输出环境写入文件头部

  1. //Write file header
  2. ret = avformat_write_header(ofmt_ctx, NULL);
  3. if (ret < 0) {
  4. printf( "Error occurred when opening output URL\n");
  5. goto end;
  6. }

配置H264编码器

  1. #if USE_H264BSF
  2. AVBitStreamFilterContext* h264bsfc = av_bitstream_filter_init("h264_mp4toannexb");
  3. #endif

开始循环读帧写入flv文件

读取一帧RTMP流的视屏流数据

  1. ret = av_read_frame(ifmt_ctx, &pkt);
  2. if (ret < 0)
  3. break;

计算对应这一帧输入RTMP流数据的一帧输出数据的相关显示帧时间pts,解码帧时间dts,距离上一帧到下一帧的播放时间差距duration

  1. 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));
  2. 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));
  3. pkt.duration = av_rescale_q(pkt.duration, in_stream->time_base, out_stream->time_base);

根据H264编码格式转换一帧输出数据

  1. #if USE_H264BSF
  2. av_bitstream_filter_filter(h264bsfc, in_stream->codec, NULL, &pkt.data, &pkt.size, pkt.data, pkt.size, 0);
  3. #endif

将这一帧输出数据写入flv文件,然后释放这一帧数据

  1. ret = av_interleaved_write_frame(ofmt_ctx, &pkt);
  2.  
  3. if (ret < 0) {
  4. printf( "Error muxing packet\n");
  5. break;
  6. }
  7.  
  8. av_free_packet(&pkt);

关闭H264编码器

  1. #if USE_H264BSF
  2. av_bitstream_filter_close(h264bsfc);
  3. #endif

释放输入、输出环境

  1. av_write_trailer(ofmt_ctx);
  2. end:
  3. avformat_close_input(&ifmt_ctx);
  4. /* close output */
  5. if (ofmt_ctx && !(ofmt->flags & AVFMT_NOFILE))
  6. avio_close(ofmt_ctx->pb);
  7. avformat_free_context(ofmt_ctx);
  8. if (ret < 0 && ret != AVERROR_EOF) {
  9. printf( "Error occurred.\n");
  10. return -1;
  11. }

说说app的使用

那个点击button就可以了,点击后它会字样会变成started,这样他就在保存RTMP流文件了,过一两分钟就相应路径去看就可以了

Android 音视频深入 十七 FFmpeg 获取RTMP流保存为flv (附源码下载)的更多相关文章

  1. Android 音视频深入 十九 使用ijkplayer做个视频播放器(附源码下载)

    项目地址https://github.com/979451341/Myijkplayer 前段时候我觉得FFmpeg做个视频播放器好难,虽然播放上没问题,但暂停还有通过拖动进度条来设置播放进度,这些都 ...

  2. Android 音视频深入 一 AudioRecord录音生成pcm转换为wav(附源码下载)

    本篇项目地址,名字是AudioRecord录音(能暂停,将pch转换为wav),求starhttps://github.com/979451341/Audio-and-video-learning-m ...

  3. Android中Canvas绘图基础详解(附源码下载) (转)

    Android中Canvas绘图基础详解(附源码下载) 原文链接  http://blog.csdn.net/iispring/article/details/49770651   AndroidCa ...

  4. Android 音视频深入 二十 FFmpeg视频压缩(附源码下载)

    项目源码https://github.com/979451341/FFmpegCompress 这个视频压缩是通过类似在mac终端上输入FFmpeg命令来完成,意思是我们需要在Android上达到能够 ...

  5. Android 音视频深入 十六 FFmpeg 推流手机摄像头,实现直播 (附源码下载)

    源码地址https://github.com/979451341/RtmpCamera/tree/master 配置RMTP服务器,虽然之前说了,这里就直接粘贴过来吧 1.配置RTMP服务器 这个我不 ...

  6. Android 音视频深入 十五 FFmpeg 推流mp4文件(附源码下载)

    源码地址https://github.com/979451341/Rtmp 1.配置RTMP服务器 这个我不多说贴两个博客分别是在mac和windows环境上的,大家跟着弄 MAC搭建RTMP服务器h ...

  7. Android 音视频深入 十一 FFmpeg和AudioTrack播放声音(附源码下载)

    项目地址,求starhttps://github.com/979451341/AudioVideoStudyCodeTwo/tree/master/FFmpeg%E6%92%AD%E6%94%BE%E ...

  8. Android 音视频深入 六 使用FFmpeg播放视频(附源码下载)

    本篇项目地址,求starhttps://github.com/979451341/Audio-and-video-learning-materials/tree/master/FFmpeg%E6%92 ...

  9. Android 音视频技术之录音获取实时音量

    一.实时音量相关基础知识 说到获取音量,大家首先想到的应该就是分贝(dB),分贝是一个相对单位(是一个比值,是一个数值,是一个纯计数方法). 在音频领域dB度量的是声音的强度,其计算的公式如下: 在上 ...

随机推荐

  1. jmeter接口/性能压测入门

    1.相关知识 https://www.cnblogs.com/star91/p/5059222.html http://www.51testing.com/zhuanti/jmeter.html 测试 ...

  2. fork项目适合全局替换注释说明

    sublimeText 正则替换 (@date) (\d+-\d+-\d+)$1 2016-11-17 (@author) (\w+)$1 youName

  3. java0429 wen 数据库

  4. 组装一台PRUSA I3打印机

    闲来无事,又搞了台机.这样下去顶不住了.草. 还是咸鱼购买,但是这台收到的时候比我以前任何一台都要散,几乎重新装了一台. 此处省略收到货时候的零件图,省略装机图. 不得不提的是,原机用的山寨melzi ...

  5. linux install Openvino

    recommend centos7 github Openvino tooltiks 1. download openvino addational installation for ncs2 ncs ...

  6. Bootstrap3基础 栅格系统 col-lg/md/sm/xs-* 简单示例

      内容 参数   OS   Windows 10 x64   browser   Firefox 65.0.2   framework     Bootstrap 3.3.7   editor    ...

  7. luoguP1919 A*B Problem升级版 ntt

    luoguP1919 A*B Problem升级版 链接 luogu 思路 ntt模板题 代码 #include <bits/stdc++.h> #define ll long long ...

  8. js函数式编程curry与compose实现

    //自行实现以下curry函数和compose //curry function curry(fn) { return function aa (...arg) { if (arg.length &g ...

  9. 安装与配置apache WEB服务器(Linux环境)

    Linux环境下安装一个软件的方式多数为两种: 1.通过命令从远程源下载自动默认安装 2.编译安装 第一种较为简单,直接通过 yum 或者 apt-get 直接安装即可,但是对我来说,编译安装可能更加 ...

  10. .net 去除特殊字符

    str = Regex.Replace(str, @"<script[^>]*?>.*?</script>", "", Regex ...