移植mp4v2开源库,h264+g711a/g711u编码mp4
1、mp4v2移植
step1、下载:https://launchpad.net/ubuntu/+source/mp4v2
step2、编译
简单配置参数:
./configure --host=arm-linux CXX=arm-hisiv100nptl-linux-g++ CC=arm-hisiv100nptl-linux-gcc --prefix=/home/mp4v2-2.0.0/Demo --enable-shared
减少库大小配置参数:
./configure --host=arm-linux CXX=arm-hisiv100nptl-linux-g++ CC=arm-hisiv100nptl-linux-gcc --prefix=/home/mp4v2-2.0.0/Demo --enable-shared --disable-option-checking --disable-debug --disable-fvisibility --disable-largefile --disable-util --disable-dependency-tracking --disable-libtool-lock
如果编译出来的库在调用 MP4AddH264VideoTrack 函数时发生崩溃现象,加上以下选项可以解决,具体原因我也不清楚。
--disable-optimize
make
make install
2、mp4v2 API简介
MP4FileHandle MP4Create (const char* fileName,uint32_t flags)
功能:创建MP4文件句柄。
返回:MP4文件句柄。
参数:fileName 要录制的MP4文件名;flags 创建文件类型,如果要创建普通文件用默认值0就可以,如要录制大于4G的MP4文件此处要设置MP4_CREATE_64BIT_DATA。
bool MP4SetTimeScale( MP4FileHandle hFile, uint32_t value )
功能:设置时间标度。
返回:成功返回true,失败返回false。
参数:hFile MP4文件句柄,value 要设置的值(每秒的时钟ticks数)。
MP4TrackId MP4AddH264VideoTrack(MP4FileHandle hFile,
uint32_t timeScale,
MP4Duration sampleDuration,
uint16_t width,
uint16_t height,
uint8_t AVCProfileIndication,
uint8_t profile_compat,
uint8_t AVCLevelIndication,
uint8_t sampleLenFieldSizeMinusOne)
功能:添加h264视频track。
返回:返回track id号。
参数:hFile MP4文件句柄,timeScale 视频每秒的ticks数(如90000),sampleDuration 设置为 MP4_INVALID_DURATION,width height 视频的宽高,AVCProfileIndication profile (baseline profile, main profile, etc. see),profile_compat compatible profile,AVCLevelIndication levels,sampleLenFieldSizeMinusOne 设置为3.
注意: AVCProfileIndication,profile_compat, AVCLevelIndication,这三个参数值是在h264流中得到的。
MP4TrackId MP4AddAudioTrack(
MP4FileHandle hFile,
uint32_t timeScale,
MP4Duration sampleDuration,
uint8_t audioType)
功能:添加音频(aac)track。
返回:返回track id号。
参数:hFile MP4句柄,timeScale音频每秒的ticks数,默认使用采样率(如16000),下面两参数设置为MP4_INVALID_DURATION和MP4_MPEG4_AUDIO_TYPE。
sampleDuration[翻译:样例持续时长]:音频这中这个参数是指每一帧音频的专多少个采样点
MP4TrackId MP4AddALawAudioTrack(
MP4FileHandle hFile,
uint32_t timeScale)
这个接口是初始化添加音频为APCM(G711_A)的接口,接口的问题是其中默认一帧的持续时间是20ms,见下面的源码。我们可以根据自己的实际情况来更改这个值。
MP4TrackId MP4File::AddALawAudioTrack( uint32_t timeScale )
{
uint32_t fixedSampleDuration = (timeScale * 20)/1000; // 20mSec/Sample
MP4TrackId trackId = AddTrack(MP4_AUDIO_TRACK_TYPE, timeScale);
m_pTracks[FindTrackIndex(trackId)]->SetFixedSampleDuration(fixedSampleDuration);
return trackId;
}
所以建议修改库源码为以下接口:
MP4TrackId MP4AddALawAudioTrack(
MP4FileHandle hFile,
uint32_t timeScale, uint32_t pointPerFrame)
视频或者音画同步的主要参数是:SampleDuration。
G711_U的方式和G711_A做同样修改。
bool MP4SetTrackESConfiguration(
MP4FileHandle hFile,
MP4TrackId trackId,
const uint8_t* pConfig,
uint32_t configSize );
功能:设置音频解码信息(如果设置错误会导致没有声音)。
返回:成功返回true,失败返回false。
参数:hFile 文件句柄,trackId 音频的track id,pConfig 记录解码信息的二进制流,configSize 解码串的长度。
注意:mpeg4ip 使用faac进行aac音频编码的,在编码时可以调用相应的函数得到二进制串pConfig和长度configSize,但是如果aac不是用faac编码的,这是需要自己填充pConfig,可以参考faac的实现,下面是一个填充结构例子:
前五个字节为 AAC object types LOW 2
接着4个字节为 码率index 16000 8
接着4个字节为 channels 个数 1
应打印出的正确2进制形式为 00010 | 1000 | 0001 | 000
2 8 1
bool MP4WriteSample(
MP4FileHandle hFile,
MP4TrackId trackId,
const uint8_t* pBytes,
uint32_t numBytes,
MP4Duration duration DEFAULT(MP4_INVALID_DURATION),
MP4Duration renderingOffset DEFAULT(0),
bool isSyncSample DEFAULT(true) );
功能:写一帧视频数据或写一段音频数据。
返回:成功返回true,失败返回false。
参数:hFile 文件句柄,trackId 音频或视频的track id,pBytes为要写的数据流指针,numBytes为数据字节长度,duration为前一视频帧与当前视频帧之间的ticks数,或这是前一段音频数据和当前音频数据之间的ticks。isSyncSample 对视频来说是否为关键帧。
注意:1,duration这个参数是用来实现音视频同步用的,如果设置错了会造成音视频不同步,甚至会出现crash现象(一般出现在调用MP4Close是crash)。 2,对于视频流MP4WriteSample函数每次调用是录制前一帧数据,用当前帧的时间戳和前一帧的时间戳计算duration值,然后把当前帧保存下来用做下次调用MP4WriteSample时用,写音频数据一样。
void MP4AddH264SequenceParameterSet(
MP4FileHandle hFile,
MP4TrackId trackId,
const uint8_t* pSequence,
uint16_t sequenceLen );
和
void MP4AddH264PictureParameterSet(
MP4FileHandle hFile,
MP4TrackId trackId,
const uint8_t* pPict,
uint16_t pictLen );
功能:添加序列参数集,添加图像参数集。
参数:hFile 文件句柄,trackId 视频track id,pSequence和pPict为要写入的序列图像参数集的数据指针,sequenceLen和pictLen为串长度。
注意:当检测到序列参数集或图像参数集更新时要调用MP4AddH264SequenceParameterSet或MP4AddH264PictureParameterSet进行更新。
void MP4Close(
MP4FileHandle hFile,
uint32_t flags DEFAULT(0) );
功能:关闭以打开的MP4文件。
参数:hFile 文件句柄,flags 是否允许在关闭MP4文件前做一些额外的优化处理。
注意:在录制较小的MP4文件时可以把flags设置为默认值,如果录制较大的文件最好把flags设置为MP4_CLOSE_DO_NOT_COMPUTE_BITRATE否则调用MP4Close函数会用掉很长的时间。
3、h264编码mp4文件伪代码
- {
- rtp_s* p_rtp = (rtp_s*) arg;
- if (p_rtp == NULL)
- {
- printf("ERROR!\n");
- return;
- }
- MP4FileHandle file = MP4Create("test.mp4", 0);
- if (file == MP4_INVALID_FILE_HANDLE)
- {
- printf("open file fialed.\n");
- return;
- }
- MP4SetTimeScale(file, 90000);
- //添加h264 track
- MP4TrackId video = MP4AddH264VideoTrack(file, 90000, 90000 / video rate(25), width, height,
- sps[1], //sps[1] AVCProfileIndication
- sps[1], //sps[2] profile_compat
- sps[3]f, //sps[3] AVCLevelIndication
- 3); // 4 bytes length before each NAL unit
- if (video == MP4_INVALID_TRACK_ID)
- {
- printf("add video track failed.\n");
- return;
- }
- MP4SetVideoProfileLevel(file, 0x7F);
- //添加aac音频
- MP4TrackId audio = MP4AddAudioTrack(file, 48000, 1024, MP4_MPEG4_AUDIO_TYPE);
- if (video == MP4_INVALID_TRACK_ID)
- {
- printf("add audio track failed.\n");
- return;
- }
- MP4SetAudioProfileLevel(file, 0x2);
- //添加g711-u
- m_audioId = MP4AddULawAudioTrack(hMp4File, 8000, 320); //8K采用率
- if(m_audioId == MP4_INVALID_TRACK_ID)
- {
- return 0;
- }
- bool a = MP4SetTrackIntegerProperty( hMp4File, m_audioId,"mdia.minf.stbl.stsd.ulaw.channels", 1); //单通道
- MP4SetAudioProfileLevel(hMp4File, 0x02);
- //添加g711-a
- m_audioId = MP4AddALawAudioTrack(hMp4File, 8000, 320); //8K采用率
- if(m_audioId == MP4_INVALID_TRACK_ID)
- {
- return 0;
- }
- bool a = MP4SetTrackIntegerProperty( hMp4File, m_audioId,"mdia.minf.stbl.stsd.alaw.channels", 1); //单通道
- MP4SetAudioProfileLevel(hMp4File, 0x02);
- int ncount = 0;
- while (1)
- {
- frame_t* pf = NULL; //frame
- pthread_mutex_lock(&p_rtp->mutex);
- pf = p_rtp->p_frame_header;
- if (pf != NULL)
- {
- if (pf->i_type == 1)//video
- {
- MP4WriteSample(file, video, pf->p_frame, pf->i_frame_size, MP4_INVALID_DURATION, 0, 1);
- }
- else if (pf->i_type == 2)//audio
- {
- MP4WriteSample(file, audio, pf->p_frame, pf->i_frame_size , MP4_INVALID_DURATION, 0, 1);
- }
- ncount++;
- //clear frame.
- p_rtp->i_buf_num--;
- p_rtp->p_frame_header = pf->p_next;
- if (p_rtp->i_buf_num <= 0)
- {
- p_rtp->p_frame_buf = p_rtp->p_frame_header;
- }
- free_frame(&pf);
- pf = NULL;
- if (ncount >= 1000)
- {
- break;
- }
- }
- else
- {
- //printf("BUFF EMPTY, p_rtp->i_buf_num:%d\n", p_rtp->i_buf_num);
- }
- pthread_mutex_unlock(&p_rtp->mutex);
- usleep(10000);
- }
- MP4Close(file);
- }
移植mp4v2开源库,h264+g711a/g711u编码mp4相关推荐
- STM32HAL库-移植mbedtls开源库示例(一)
目录 概述 一.使用方法 二.STM32CubeMx配置 三.Examples 四.运行结果 五.总结 概述 本篇文章介绍如何使用STM32HAL库,移植mbedtls开源库支持mqtt证书加密示例. ...
- STM32HAL 移植 cJSON开源库 (裸机开发神器)
目录 概述 一.使用方法 二.STM32CubeMx配置 三.Examples 四.运行结果 五.总结 概述 本篇文章介绍如何使用STM32引用 cJSON开源库,JSON格式在互联网数据交互时常用的 ...
- Linux下ffmpeg开源库移植到ARM开发板。
Linux下移植ffmpeg开源库. Make install 成功后,用户安装目录下出现bin,include,lib,share目录. 进入bin目录执行file ffmpeg 查看编译出的执行程 ...
- mp4v2再学习 -- H264视频编码成MP4文件
一.H264视频编码成MP4文件 参看:H264视频编码成MP4文件 参看:mp4v2在VS2010下的编译与在项目中的使用 最近做项目需要将H264文件封装为mp4文件,从网上找到了MP4V2库,下 ...
- 开源库的使用方法以及libjpeg的移植详解
一.开源库的使用方法 (1)移植(×××.解压.配置.修改Makefile.编译或交叉编译).移植的目的是由源码得到三个东西:动态库.so,静态库.a,头文件.h (2)部署(部署动态库so.部署静态 ...
- 使用mp4v2将aac音频h264视频数据封装成mp4开发心得
这阵子在捣鼓一个将游戏视频打包成本地可播放文件的模块.开始使用avi作为容器,弄了半天无奈avi对aac的支持实在有限,在播放时音视频时无法完美同步. 关于这点avi文档中有提到: For AAC, ...
- 基于live555的rtsp播放器之十八:G711a/G711u/G726转AAC
封装格式的主要作用是把视频码流和音频码流按照一定的格式存储在一个文件中.现如今流行的封装格式如下表所示: 此表来自雷神:[总结]视音频编解码技术零基础学习方法,由表可见: 1.除了AVI之外,其他封装 ...
- 常用C/C++开源库
1. 框架 Apache C++ Standard Library : 是一系列算法,容器,迭代器和其他基本组件的集合 ASL : Adobe源代码库提供了同行的评审和可移植的C++源代码库. Boo ...
- C++开源库大全(转)
http://blog.csdn.net/chen19870707/article/details/40427645 程序员要站在巨人的肩膀上,C++拥有丰富的开源库,这里包括:标准库.Web应用框架 ...
最新文章
- 谷歌又放大招:视觉效果完胜其他SOTA的风格迁移网络,手机端可达实时4K
- 有小数点是什么类型_为什么0.1+0.2不等于0.3?原来编程语言是这么算的……
- jpa 默认生成sql语句_springboot-jpa自动创建数据库表
- asp.net core webapi Session 内存缓存
- 混合云备份服务 > 产品简介 > 什么是混合云备份
- 0基础python入门书籍 excel_零基础学Python3(23):Excel 基础操作(上)
- (8)Python_分割numpy数组
- Java——实现100以内奇数的和
- Android性能测试工具(一) 之Emmagee[转载]
- java dom4j解析复杂xml成json
- ppt太大怎么压缩变小一点?
- Python批量剪切mp3音乐
- 掉入黑洞会怎样?被拉成面条,还是前往另一个宇宙?
- 什么是数字孪生专用引擎技术
- CSS3边框、颜色、伪选择器
- mysql association_Mybatis的一对多(collection)和一对一(association)查询
- GameofMir引擎架设传奇服务器【2:登录器配置】
- 怎么用视频转换器把mp4转换成mp3
- 贴几张Google Earth的图
- shell小工具-检查日志目录下log文件中err信息
热门文章
- 雷蛇电脑原厂预装出厂系统恢复镜像
- Leetcode——953.验证外星语词典——题解+代码实现
- 弘玑Cyclone RPA为无锡农商行提供数字化路径,每月节省300小时人力成本
- nats需要消息服务器吗,浅谈NATS消息系统
- 即构微信小程序直播组件是什么?有哪些功能?哪些小程序类目可以使用?
- Mybatis源码学习第六课---核心层源码分析--binding模块
- [隐私安全]PC端网页版百度地图是如何定位你的真实地址的
- 【FXCG】美联储加息在即,10年期国债收益率创近两年新高
- VCU整车控制器开发 VCU开发设计策略 整车控制器设计方案
- 如何随意截断ggplot2图像的y轴?