使用mp4v2将H264+AAC合成mp4文件
|
录制程序要添加新功能:录制CMMB电视节目,我们的板卡发送出来的是RTP流(H264视频和AAC音频),录制程序要做的工作是: (1)接收并解析RTP包,分离出H264和AAC数据流; (2)将H264视频和AAC音频以某种格式封装,最后存成文件,供用户查看。 第一步已经有部分代码可供参考,因此很快就完成了。 第二步,我们决定封装成mp4,查找了一些资料后,决定使用开源库mp4v2来合成mp4文件。 技术路线已确定,就开工干活。 (一)mp4格式的基础知识。 关于mp4格式,网上介绍的不少,有以下内容可供参考: (1)两个ISO标准: [ISO/IEC 14496-12]:ISO base media file format --”is a general format forming the basis for a number of other more specific file formats. This format contains the timing, structure, and media information for timed sequences of media data, such as audio-visual presentations ” [ISO/IEC 14496-14]:MP4 file format --”This specification defines MP4 as an instance of the ISO Media File format [ISO/IEC 14496-12 and ISO/IEC 定义了mp4文件格式标准。 (2)http://wenku.baidu.com/view/673482284b73f242336c5f4c.html 是上面两个标准的解释,建议先看这个,了解大概,具体细节再看ISO标准文件。 (二)技术验证。主要就是写验证代码,验证技术可行性。 去官网下载mp4v2源码、编译、安装过程略过不提。所有资料可以在http://code.google.com/p/mp4v2/找到。 先写部分验证代码,很快完成了,但封装出来的文件有问题,无法播放。 合成部分,代码如下:
现象:没有图像,也没有声音,根本无法播放。 于是,艰苦的工作开始了:跟踪查找原因。 (1)使用 vlc播放合成的mp4文件,查看详细输出:
可以看到vlc(实际上是调用libmp4库)解析box都正确的,mdat的大小也是正确的。 (2)既然找到疑点,继续跟踪。 查看vlc的源代码,在文件modules/demux/mp4/libmp4.c中发现:skip信息是由MP4_ReadBoxSkip()函数打印的,而调用的地方在libmp4.c中2641行:
从代码看,vlc调用libmp4解析文件时,主动忽略了mdat,skip,free,wide这四种类型的box。 (3)继续查看modules/demux/mp4/mp4.c中的Open()函数(解析模块的入口函数),可以看到本模块的主要工作是初始化一个demux_sys_t结构体,该结构体定义如下:
似乎只是为了获取mp4的tracks,moov,duration, timescale等基本信息,实际上并不解码数据,因此就不需要关注mdat这个box了。 综上:vlc的输出是正常的,libmp4忽略了mdat这个box也不是造成mp4文件无法播放的原因,只是因为libmp4这个模块并不真正解码数据,所以不需要关注这个box。 (4)继续看vlc的输出: 不管那么多,先看看代码再说。 vlc是以lib的形式使用ffmpeg的,所以我们必须看ffmpeg的代码:
可以看到,正是这里报错的。 (5)在mp4v2的论坛上找到一个帖子,与我的情况非常类似: 内容如下: Jeremy Noring ...so each sample you and to mp4v2 should be prefixed with a size code Ottavio Campana Ottavio Campana 从中得到如下关键信息: 那好说,我将每个sample(也就是NAL)的头四个字节内容改成NAL的长度,且试试看:
测试下来,果然OK了! (6)视频已经解决了,音频还有问题:播放的声音太快。 尝试调整参数: MP4TrackId audio = MP4AddAudioTrack(file, 48000, 1024, MP4_MPEG4_AUDIO_TYPE); 第三个参数sampleDuration,表示每个sample持续多少个duration,网上看到的都是1024。 我尝试了几个不同的值:128,256,512,4096都不行,最后发现设为2048就正常了。 (为什么是2048??????我不清楚,也许是因为我们的音频是双声道?有时间再研究。。。) 正确代码如下:
至此,已经成功的将rtp流合成了mp4文件,证明了技术上是可行的。 关于该demo,可以在这里 http://bbs.rosoo.net/thread-15165-1-1.html 看到。 注意:很多参数都是针对我们的具体应用写死的,仅供参考。 (三)将功能合并到录制程序中。 略。 from:http://www.rosoo.net/a/201305/16631.html
|
使用mp4v2将H264+AAC合成mp4文件的更多相关文章
- 嵌入式 使用mp4v2将H264+AAC合成mp4文件
录制程序要添加新功能:录制CMMB电视节目,我们的板卡发送出来的是RTP流(H264视频和AAC音频),录制程序要做的工作是: (1)接收并解析RTP包,分离出H264和AAC数据流: (2)将H26 ...
- H264视频编码成MP4文件
firehood的专栏 Wince嵌入式开发 目录视图 摘要视图 订阅 赠书 | AI专栏(AI圣经!<深度学习>中文版) 每周荐书:Kotlin.分布式.Keras ...
- 嵌入式 H264—MP4格式及在MP4文件中提取H264的SPS、PPS及码流
一.MP4格式基本概念 MP4格式对应标准MPEG-4标准(ISO/IEC14496) 二.MP4封装格式核心概念 1 MP4封装格式对应标准为 ISO/IEC 14496-12(信息技术 视听对象 ...
- 使用ffmpeg从mp4文件中提取视频流到h264文件中
ffmpeg -i 2018.mp4 -codec copy -bsf: h264_mp4toannexb -f h264 tmp. 注释: -i 2018.mp4: 是输入的MP4文件 -code ...
- (转)MP4文件两种格式AVC1和H264的区别及利用FFMPEG demux为h264码流事项
出自:http://www.mworkbox.com/wp/work/314.html 2013-05-04 MP4的视频H264封装有2种格式:h264和avc1,对于这个细节,很容易被忽略.笔者也 ...
- [转]【流媒體】H264—MP4格式及在MP4文件中提取H264的SPS、PPS及码流
[流媒體]H264—MP4格式及在MP4文件中提取H264的SPS.PPS及码流 SkySeraph Apr 1st 2012 Email:skyseraph00@163.com 一.MP4格式基本 ...
- ffmpeg学习(二) 通过rtsp获取H264裸流并保存到mp4文件
本篇将使用上节http://www.cnblogs.com/wenjingu/p/3977015.html中编译好的库文件通过rtsp获取网络上的h264裸流并保存到mp4文件中. 1.VS2010建 ...
- 多媒体开发之---H264—MP4格式及在MP4文件中提取H264的SPS、PPS及码流
一.MP4格式基本概念 MP4格式对应标准MPEG-4标准(ISO/IEC14496) 二.MP4封装格式核心概念 1 MP4封装格式对应标准为 ISO/IEC 14496-12(信息技术 视听对象 ...
- 嵌入式 hi3518x平台h264+g711a封装mp4代码demo
先看代码吧,有代码有真相,具体代码的demo(下载demo的朋友请勿在网上上传我的demo,谢谢)下载连接为: http://download.csdn.net/detail/skdkjxy/8071 ...
随机推荐
- NYOJ-456 邮票分你一半 AC 分类: NYOJ 2014-01-02 14:33 152人阅读 评论(0) 收藏
#include<stdio.h> #define max(x,y) x>y?x:y int main(){ int n,x,y; scanf("%d",& ...
- [错误]试图加载格式不正确的程序。 (异常来自 HRESULT:0x8007000B)
错误原因: dll文件是在64位机下编译的,而服务器是32位机,所以无法调用 或者dll文件是在64位开发环境下下编译的,而现在的调用程序是的32位,所以无法调用 注意项目属性:
- OpenResty 反向代理的用法与技巧
Nginx最开始是作为反向代理被熟知的,基于它的OpenResty的自然也是支持反向代理的,下面我们就来看看它的一些基本用法以及在使用过程中的一些技巧. 一.基本用法 在业务环境中,可能会将OpenR ...
- Selenium网址
Selenium官网:http://www.seleniumhq.org/ Selenium火狐插件地址:http://release.seleniumhq.org/selenium-ide/ 浏览器 ...
- gcc / g++ 编译选项
g++ -Wall -m64 -W -O2 a.cpp b.cpp -o a 用下面的命令编译,生成libtriangle.so 先生成动态库 g++ -g -fpic -shared -o lib ...
- java基础知识回顾之---java String final类普通方法的应用之“子串在整串中出现的次数”
/* * 2 一个子串在整串中出现的次数. * "loveerlovetyloveuiloveoplove" * 思路: * 1,要找的子串是否存在,如果存在获取其出现的位置.这个 ...
- Unrecognized Windows Sockets error: 0: JVM_Bind异常
根据端口查看 根据PID查看具体的进程 任务管理器->查看-选择列,选中PID 然后查看任务管理器.
- POJ1118 Lining Up
快弄死我了 最后的原因是abs和fabs的区别... 说点收获:1.cmp函数返回的是int,所以不要直接返回double相减的结果2.define inf 1e9和eps 1e-93.在整数相除得到 ...
- 【Linux高频命令专题(21)】df
概述 linux中df命令的功能是用来检查linux服务器的文件系统的磁盘空间占用情况.可以利用该命令来获取硬盘被占用了多少空间,目前还剩下多少空间等信息. 显示指定磁盘文件的可用空间.如果没有文件名 ...
- Qt 自定义model实现文件系统的文件名排序(重定义sort函数即可。忽然开窍了:其实捕捉点击Header事件,内部重排序,全部刷新显示即可)
前段时间,需要做一个功能是要做文件系统的排序的功能.由于是自己写的model, 自己定义的数据结构.最初的想法只有一个自己去实现文件夹跟文件名的排序算法,不过感觉比较费时间.后来想到的是QFileSy ...