当前位置: 首页 > news >正文

ffmpeg学习(二) 通过rtsp获取H264裸流并保存到mp4文件

本篇将使用上节http://www.cnblogs.com/wenjingu/p/3977015.html中编译好的库文件通过rtsp获取网络上的h264裸流并保存到mp4文件中。

1、VS2010建立VC++  win32控制台项目

2、在工程目录下建立lib目录和include目录,将已编译好的lib拷打lib下,include拷到include下,dll拷到Debug目录下

3、工程属性--配置属性--VC++目录--包含目录,添加ffmpeg头文件目录及其他第三方头文件目录

                                             链接器--常规--附加库目录,添加lib目录

                                             链接器--输入--附加依赖项,添加各个lib名

4、设计和实现:

4.1 设计思路:

       组件和网络初始化——>打开网络流——>获取网络流信息——>根据网络流信息初始化输出流信息——>创建并打开mp4文件——>写mp4文件头

                    ——>循环读取输入流并写入mp4文件——>写文件尾——>关闭流,关闭文件

4.2 关键数据结构:

       AVFormatContext,AVStream,AVCodecContext,AVPacket,AVFrame等,它们的关系解释如下:

       一个AVFormatContext包含多个AVStream,每个码流包含了AVCodec和AVCodecContext,AVPicture是AVFrame的一个子集,

他们都是数据流在编解过程中用来保存数据缓存的对像,从数据流读出的数据首先是保存在AVPacket里,也可以理解为一个AVPacket最多只包含一个AVFrame,

而一个AVFrame可能包含好几个AVPacket,AVPacket是种数据流分包的概念。

4.3 关键函数:

int avformat_open_input(AVFormatContext **ps, const char *filename, AVInputFormat *fmt, AVDictionary **options); //打开网络流或文件流

int avformat_write_header(AVFormatContext *s, AVDictionary **options);//根据文件名的后缀写相应格式的文件头

int av_read_frame(AVFormatContext *s, AVPacket *pkt);//从输入流中读取一个分包

int av_interleaved_write_frame(AVFormatContext *s, AVPacket *pkt);//往输出流中写一个分包

int av_write_trailer(AVFormatContext *s);//写输出流(文件)的文件尾

4.4 代码:

#include "stdafx.h"

#ifdef __cplusplus 
extern "C" { #endif #include <libavcodec/avcodec.h> #include <libavdevice/avdevice.h> #include <libavformat/avformat.h> #include <libavfilter/avfilter.h> #include <libavutil/avutil.h> #include <libswscale/swscale.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <math.h> #ifdef __cplusplus } #endif AVFormatContext *i_fmt_ctx; AVStream *i_video_stream; AVFormatContext *o_fmt_ctx; AVStream *o_video_stream; int _tmain(int argc, char **argv) { avcodec_register_all(); av_register_all(); avformat_network_init(); /* should set to NULL so that avformat_open_input() allocate a new one */ i_fmt_ctx = NULL; char rtspUrl[] = "rtsp://admin:12345@192.168.10.76:554"; const char *filename = "1.mp4"; if (avformat_open_input(&i_fmt_ctx, rtspUrl, NULL, NULL)!=0) { fprintf(stderr, "could not open input file\n"); return -1; } if (avformat_find_stream_info(i_fmt_ctx, NULL)<0) { fprintf(stderr, "could not find stream info\n"); return -1; } //av_dump_format(i_fmt_ctx, 0, argv[1], 0); /* find first video stream */ for (unsigned i=0; i<i_fmt_ctx->nb_streams; i++) { if (i_fmt_ctx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { i_video_stream = i_fmt_ctx->streams[i]; break; } } if (i_video_stream == NULL) { fprintf(stderr, "didn't find any video stream\n"); return -1; } avformat_alloc_output_context2(&o_fmt_ctx, NULL, NULL, filename); /* * since all input files are supposed to be identical (framerate, dimension, color format, ...) * we can safely set output codec values from first input file */ o_video_stream = avformat_new_stream(o_fmt_ctx, NULL); { AVCodecContext *c; c = o_video_stream->codec; c->bit_rate = 400000; c->codec_id = i_video_stream->codec->codec_id; c->codec_type = i_video_stream->codec->codec_type; c->time_base.num = i_video_stream->time_base.num; c->time_base.den = i_video_stream->time_base.den; fprintf(stderr, "time_base.num = %d time_base.den = %d\n", c->time_base.num, c->time_base.den); c->width = i_video_stream->codec->width; c->height = i_video_stream->codec->height; c->pix_fmt = i_video_stream->codec->pix_fmt; printf("%d %d %d", c->width, c->height, c->pix_fmt); c->flags = i_video_stream->codec->flags; c->flags |= CODEC_FLAG_GLOBAL_HEADER; c->me_range = i_video_stream->codec->me_range; c->max_qdiff = i_video_stream->codec->max_qdiff; c->qmin = i_video_stream->codec->qmin; c->qmax = i_video_stream->codec->qmax; c->qcompress = i_video_stream->codec->qcompress; } avio_open(&o_fmt_ctx->pb, filename, AVIO_FLAG_WRITE); avformat_write_header(o_fmt_ctx, NULL); int last_pts = 0; int last_dts = 0; int64_t pts, dts; while (1) { AVPacket i_pkt; av_init_packet(&i_pkt); i_pkt.size = 0; i_pkt.data = NULL; if (av_read_frame(i_fmt_ctx, &i_pkt) <0 ) break; /* * pts and dts should increase monotonically * pts should be >= dts */ i_pkt.flags |= AV_PKT_FLAG_KEY; pts = i_pkt.pts; i_pkt.pts += last_pts; dts = i_pkt.dts; i_pkt.dts += last_dts; i_pkt.stream_index = 0; //printf("%lld %lld\n", i_pkt.pts, i_pkt.dts); static int num = 1; printf("frame %d\n", num++); av_interleaved_write_frame(o_fmt_ctx, &i_pkt); //av_free_packet(&i_pkt); //av_init_packet(&i_pkt);  } last_dts += dts; last_pts += pts; avformat_close_input(&i_fmt_ctx); av_write_trailer(o_fmt_ctx); avcodec_close(o_fmt_ctx->streams[0]->codec); av_freep(&o_fmt_ctx->streams[0]->codec); av_freep(&o_fmt_ctx->streams[0]); avio_close(o_fmt_ctx->pb); av_free(o_fmt_ctx); return 0; }

 

5、测试

如上图为存储过程中程序的打印结果。生成的mp4文件可以用任意支持该格式的播放器播放。

原文链接: http://www.cnblogs.com/wenjingu/p/3990071.html

转载于:https://www.cnblogs.com/lifan3a/articles/7325912.html

相关文章:

  • 安装node.js和npm
  • 推荐几款谷歌浏览器的使用插件
  • webservcie学习之webservice是什么
  • Win10《芒果TV》更新v3.6.0秋收版:新增追剧磁贴、记忆续播、跳转列表
  • Centos7安装TensorFlow
  • 没有绝对的cc.ResolutionPolicy.FIXED_WIDTH或cc.ResolutionPolicy.FIXED_HEIGHT
  • Spring 定时任务之 @Scheduled cron表达式
  • Java内存知识整理
  • 嵌入式GPIO接口及操作(一)
  • Redis源代码剖析--对象object
  • JavaScript 基本语法
  • 四轴遥控器ADC部分
  • 代码备忘, TODO宏实现
  • html2canvas页面截图图片不显示
  • 4.5 以卫语句取代嵌套条件式
  • 【Amaple教程】5. 插件
  • 【vuex入门系列02】mutation接收单个参数和多个参数
  • Angular2开发踩坑系列-生产环境编译
  • C++类的相互关联
  • Flex布局到底解决了什么问题
  • js继承的实现方法
  • October CMS - 快速入门 9 Images And Galleries
  • Spring-boot 启动时碰到的错误
  • SQLServer插入数据
  • Stream流与Lambda表达式(三) 静态工厂类Collectors
  • Swoft 源码剖析 - 代码自动更新机制
  • TypeScript迭代器
  • ⭐ Unity 开发bug —— 打包后shader失效或者bug (我这里用Shader做两张图片的合并发现了问题)
  • vue-loader 源码解析系列之 selector
  • WePY 在小程序性能调优上做出的探究
  • Yeoman_Bower_Grunt
  • 道格拉斯-普克 抽稀算法 附javascript实现
  • 多线程事务回滚
  • 使用 Docker 部署 Spring Boot项目
  • 使用common-codec进行md5加密
  • 微服务核心架构梳理
  • 微信小程序--------语音识别(前端自己也能玩)
  • 远离DoS攻击 Windows Server 2016发布DNS政策
  • 正则与JS中的正则
  • ​批处理文件中的errorlevel用法
  • ![CDATA[ ]] 是什么东东
  • #Linux(Source Insight安装及工程建立)
  • #考研#计算机文化知识1(局域网及网络互联)
  • (2)(2.4) TerraRanger Tower/Tower EVO(360度)
  • (Matlab)遗传算法优化的BP神经网络实现回归预测
  • (二) Windows 下 Sublime Text 3 安装离线插件 Anaconda
  • (附源码)ssm码农论坛 毕业设计 231126
  • (论文阅读40-45)图像描述1
  • (四)Controller接口控制器详解(三)
  • (转)一些感悟
  • **CI中自动类加载的用法总结
  • *Algs4-1.5.25随机网格的倍率测试-(未读懂题)
  • .bat批处理(一):@echo off
  • .Net Redis的秒杀Dome和异步执行
  • .NET 常见的偏门问题