转载: 音视频交流群  发的一个总结。  原作者 请查看相关博客作者 http://blog.51cto.com/fengyuzaitu/2061036

场景要求
项目要求点播速度是300到500毫秒之间,现在最长的点播延时是1300毫秒(有的时候甚至无法播放视频),生产环境是RTSP传输h264裸流数据,
研究在接收到I帧的时候,开始出来图像,简化FFmpeg的调用逻辑(SPS/PPS已经预先知道,并且分辨率也是固定为1920*1080)

最终的解决方案:核心是要求发送端发送的第一帧:强制I帧,根据如下的其他的方案指定码流的格式

问题点
1)avformat_open_input取消问题的优化
在代码中指定如下:
AVInputFormat* pAVInputFormat = av_find_input_format("h264");
pAVFormatContext->iformat = pAVInputFormat;
//if (avformat_open_input(&pAVFormatContext, "", pAVInputFormat, NULL) < 0)
如果不调用avformat_open_input函数实际上,影响到的是av_read_frame(pVideo->m_pAVFormatContext, packet)
出错提示:
No start code is found
Error splitting the input into NAL units
实际上av_read_frame关键作用是从缓冲中拆分出一个个NAL单元(每一个NAL单元都是从00 00 00 01作为开始码,开始的),
目前的解决方案是手动自己进行NAL单元的拆分,然后送到av_send_packet进行分帧解码(从而也取消了
av_read_frame函数的调用),手动拆分出NAL,有点麻烦

正在研究的是avformat_open_input可能会填充pAVFormatContext的URLProtocol协议字段,不过这已经是FFmpeg底层函数,
可能不可访问,正在分析源码

2)non-existing PPS 0 referenced问题
在调用av_read_frame函数的时候,会提示如上错误
non-existing PPS 0 referenced
decode_slice_header error
no frame!

但是实际上,手动添加SPS/PPS的内容到extradata字符串中,
unsigned char sps_pps[] = { 0x00 ,0x00 ,0x01,0x67,0x42,0x00 ,0x2a ,0x96 ,0x35 ,0x40 ,0xf0 ,0x04 ,0x4f ,0xcb ,0x37 ,0x01 ,0x01 ,0x01 ,0x40 ,0x00 ,0x01 ,0xc2 ,0x00 ,0x00 ,0x57 ,0xe4 ,0x01 ,0x00 ,0x00 ,0x00 ,0x01 ,0x68 ,0xce ,0x3c ,0x80, 0x00 };
pAVFormatContext->streams[0]->codecpar->extradata_size = sizeof(sps_pps);
pAVFormatContext->streams[0]->codecpar->extradata = (uint8_t*)av_mallocz(pAVFormatContext->streams[0]->codecpar->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
memset(pAVFormatContext->streams[0]->codecpar->extradata, 0, sizeof(sps_pps) + FF_INPUT_BUFFER_PADDING_SIZE);
memcpy(pAVFormatContext->streams[0]->codecpar->extradata, sps_pps, sizeof(sps_pps));

FFmpeg需要通过分析数据来确定输入格式,所有程序启动时,ffmpeg收到的数据最先应该是SPS与PPS的nalu单元,然后是具体的视频数据

相关博客
http://blog.51cto.com/fengyuzaitu/2058138
http://blog.51cto.com/fengyuzaitu/2057885

3)如果知道了码流格式,实际上不需要调用什么探测码流格式的函数,直接调用AVCodecContext解码,就可以
目前在网上没有相关的资料

FFmpeg日志定向输出到文件
http://blog.51cto.com/fengyuzaitu/2053210
avcodec_send_packet函数错误定位
http://blog.51cto.com/fengyuzaitu/2046171

相关资料
1)http://www.yidianzixun.com/news_1eff46dc583b688d33a557b5582745dc
MP4的H264视频数据保存在名为mdata的box当中,MediaRecorder通过socket发送出来的MP4数据包含四部分:填充符、ftyp、mdat、slice。
其中slice就是我们要找的视频数据,slice是mdata的一部分,slice与mdata之间可能存在填充符,而slice与slice之间是连在一起的。
slice由视频数据长度(4字节,前两个字节通常为0)和视频数据组成,其中视频数据是不带起始码的H264 Nalu单元,
不难看出其第一个字节为0x65(关键帧)、0x41等。数据长度描述的是 H264 Nalu单元的长度,这样我们已经找到一帧完成的H264码流数据了,
接下来我们只需将 Nalu单元提取出来前面加上0x00 00 00 01的4字节起始码我们就得到了H264裸数据,这样的数据在播放器上还不能播放,
需在H264裸数据文件的最前端加上SPS与PPS信息(他们也是有起始码的哦),至此,播放器能够正常播放文件了

优化FFmpeg点播慢的问题经验总结:
主要是通过指定解码格式H264来减少探测码流格式的时间
http://blog.51cto.com/fengyuzaitu/1573766
http://blog.51cto.com/fengyuzaitu/1982996

有什么纰漏,请不吝赐教

目前遇到如下两个问题
1)第一次点播视频的时候,还是会慢些,然后其他路播放视频就快很多
2)C#调用C++播放视频,比较慢

有这方面的大牛,希望给点建议,谢谢

FFmpeg点播慢的最终方案的更多相关文章

  1. 微软云平台媒体服务实践系列 1- 使用静态封装为iOS, Android 设备实现点播(VoD)方案

    微软的云平台媒体服务为流媒体服务提供了多种选择,在使用流媒体服务为企业做流媒体方案时,首先需要确认要流媒体接收目标,如针对广大iOS, Android移动设备,由于它们都支持HLS 格式的流媒体,基于 ...

  2. 利用QT、QWebview、ffmpeg实现的屏幕录制方案

    .katex { display: block; text-align: center; white-space: nowrap; } .katex-display > .katex > ...

  3. sql server 2008数据库 降为 sql server 2005数据库 最终方案总结

    由于xx原因,sql server 要降级,所以有了下文.... 一 直接 通过sql server 自带工具 生成脚本即可,具体操作方法如下: 1.打开 Microsoft Sql Server M ...

  4. Frida Android hook native层__system_property_get的最终方案

    记录这个问题的起因是,在hook时遇到了修改内容长度,超过原长度时,会出现显示不全的问题. 比如把nexus 5改成nexus 100,只会显示nexus 1. 所以去读了下源码 int __syst ...

  5. 微软云平台媒体服务实践系列 2- 使用动态封装为iOS, Android , Windows 等多平台提供视频点播(VoD)方案

    文章微软云平台媒体服务实践系列 1- 使用静态封装为iOS, Android 设备实现点播(VoD)方案  介绍了如何针对少数iOS, Android 客户端的场景,出于节约成本的目的使用媒体服务的静 ...

  6. FFmpeg在Android上的移植优化步骤

    http://blog.csdn.net/feixiang_john/article/details/7894188 从事多媒体软件开发的人几乎没有不知道FFmpeg的,很多视频播放器都是基于FFmp ...

  7. 【C++】从零开始,只使用FFmpeg,Win32 API,实现一个播放器(一)

    前言 起初只是想做一个直接读取视频文件然后播放字符动画的程序.我的设想很简单,只要有现成的库,帮我把视频文件解析成一帧一帧的原始画面信息,那么我只需要读取里面的每一个像素的RGB数值,计算出亮度,然后 ...

  8. 再谈C#采集,一个绕过高强度安全验证的采集方案?方案很Low,慎入

    说起采集,其实我是个外行,以前拔过阿里巴巴的客户数据,在我博客的文章:C#+HtmlAgilityPack+XPath带你采集数据(以采集天气数据为例子) 中,介绍过采集用的工具,其实很Low的,分析 ...

  9. Android 进程常驻----native保活5.0以下方案推演过程以及代码

    正文: 今天继续昨天,一鼓作气,争取这个礼拜全部写完. 上一篇文章留了一个别人的github链接,他里面的native保活实现方案也是大多数公司采用的方案. 我们先来讲一下他的方案. 他是首先开启一个 ...

随机推荐

  1. jvm到底是什么?有什么作用?工作机制如何?

    1.jvm定义 JVM就是java虚拟机,它是一个虚构出来的计算机,可在实际的计算机上模拟各种计算机的功能.JVM有自己完善的硬件结构,例如处理器.堆栈和寄存器等,还具有相应的指令系统. 2.jvm作 ...

  2. js代码点击触发事件

    js触发按钮点击事件 function load(){ //下面两种方法效果是一样的 document.getElementById("target").onclick(); do ...

  3. Windows下Oracle创建数据库的3种方式

    1.   Creating a Database with DBCA DatabaseConfiguration Assistant (DBCA) is the preferred way to cr ...

  4. leecode第一百二十二题(买卖股票的最佳时机II)

    class Solution { public: int maxProfit(vector<int>& prices) { int len=prices.size(); ) ; , ...

  5. leecode第八题(字符串转换整数 (atoi))

    ;//判断返回0是因为错误还是真的是0 class Solution { public: int myAtoi(string str) {//写的很丑 if (str=="") ; ...

  6. vuex学习与实践——mapState、getter、mapGetters

    1.mapState辅助函数 当一个组件需要获取多个状态时候,将这些状态都声明为计算属性会有些重复和冗余.为了解决这个问题,我们可以使用 mapState 辅助函数帮助我们生成计算属性,让你少按几次键 ...

  7. 用友软件系统管理员账号admin密码忘记了,如何解决?

    1.打开数据库. 2.点开  数据库-UFSystem. 3.找到dbo.UA_user表,鼠标右键,点打开表. 4.打开后,找到admin,cPassword列即可找到系统管理员密码.

  8. RedHat/CentOS根目录扩容

    下面以redhat为例,介绍如何扩容系统根目录,CentOS也是一样的. 1. 登录到系统中,查看硬盘情况. /dev/sdb就是增加的硬盘. [root@test ~]# fdisk -l 2. 操 ...

  9. <%@page contentType="text/html;charset=gbk"%> 与 <meta http-equiv="Content-Type" content="text/html; charset=GBK">区别

    前一个是在服务端起作用,是告诉应用服务器采用何种编码输出JSP文件流, 后一个是在客户端起作用,是告诉浏览器是采用何种编码方式显示HTML页面

  10. Spring Boot设置值:分别用@ConfigurationProperties和@Value给属性设值及其区别

    @ConfigurationProperties给属性映射值编写JavaBean/** 将配置文件application.properties中配置的每一个属性值映射到当前类的属性中:* @Confi ...