2012-06-06 17:24 mpeg4ip的Mp4v2库移植到android系统上,实现h264封装到mp4的容器内
第一步: 首选从官网上下载mpeg4ip源代码,只要其中的lib/mp4v2目录下cpp源文件和.h头文件,和include目录下的mpeg4ip.h和mpeg4ip_version.h头文件。(我下的版本是1.6)。我这里处理了下,把源文件放到src目录下,头文件放到include目录下。 第二步,源文件做少量修改。 1、mpeg4ip.h文件中注释掉 #incl
第二步,源文件做少量修改。
1、mpeg4ip.h文件中注释掉 #include <mpeg4ip_config.h>
2、mp4file.cpp文件中的GetNumberOfTracks函数中修改。
修改前:
u_int32_t MP4File::GetNumberOfTracks(const char* type, u_int8_t subType)
{
if (type == NULL) {
return m_pTracks.Size();
}
u_int32_t typeSeen = 0;
const char* normType = MP4NormalizeTrackType(type, m_verbosity);
for (u_int32_t i = 0; i < m_pTracks.Size(); i++) {
if (!strcmp(normType, m_pTracks[i]->GetType())) {
if (subType) {
if (normType == MP4_AUDIO_TRACK_TYPE) {
if (subType != GetTrackEsdsObjectTypeId(m_pTracks[i]->GetId())) {
continue;
}
} else if (normType == MP4_VIDEO_TRACK_TYPE) {
if (subType != GetTrackEsdsObjectTypeId(m_pTracks[i]->GetId())) {
continue;
}
}
// else unknown subtype, ignore it
}
typeSeen++;
}
}
return typeSeen;
}
修改后:
u_int32_t MP4File::GetNumberOfTracks(const char* type, u_int8_t subType)
{
if (type == NULL) {
return m_pTracks.Size();
}
u_int32_t typeSeen = 0;
const char* normType = MP4NormalizeTrackType(type, m_verbosity);
for (u_int32_t i = 0; i < m_pTracks.Size(); i++) {
if (!strcmp(normType, m_pTracks[i]->GetType())) {
if (subType) {
if ( !strcmp(normType, MP4_AUDIO_TRACK_TYPE)) {
if (subType != GetTrackEsdsObjectTypeId(m_pTracks[i]->GetId())) {
continue;
}
} else if ( !strcmp(normType, MP4_VIDEO_TRACK_TYPE) ) {
if (subType != GetTrackEsdsObjectTypeId(m_pTracks[i]->GetId())) {
continue;
}
}
// else unknown subtype, ignore it
}
typeSeen++;
}
}
return typeSeen;
}
MP4TrackId MP4File::FindTrackId(u_int16_t trackIndex, const char* type, u_int8_t subType)函数中字符串比较处做同样的修改。
第三步:编写android.mk文件,这里要注意,因为android中默认的c++不支持异常处理,所以找到一个完整支持c++的标准c++静态库libstdc++.a,把libstdc++.a放到src目录下,且加上
LOCAL_SRC_FILES += libstdc++.a
LOCAL_LDFLAGS := $(LOCAL_PATH)/src/libstdc++.a
还要加上
LOCAL_CPPFLAGS := -O2 -fexceptions -DHAVE_SOCKLEN_T -DHAVE_STRUCT_IOVEC
第四步:源码状态下,mm编译。或者用ndk进行编译。
第五步:调用库,进行封装。
测试源代码(经过测试,封装的文件vlc能正常播放)
#include "mp4.h"
int main()
{
unsigned char sps_pps[24] = {'\0'}; //存储sps和pps
unsigned char buf[1024*100] = {'\0'}; //存储video数据
int frameSize = 0; //取过来的数据长度
int ret;
int sps_ppsLen = 0; //sps和pps的总长度
int id = start(); //打开数据流
if(id <0 )
{
printf("open video fail %d\n",id);
return -1;
}
ret = getsps(sps_pps,&sps_ppsLen);//取得sps和pps
if(ret != 0)
{
printf("get sps and pps fail %d\n",ret);
stop(id);
return -1;
}
//创建mp4文件
MP4FileHandle fileHandle = MP4CreateEx("/data/test.mp4",MP4_DETAILS_ALL,0,1,1,0,0,0,0);
if(fileHandle == MP4_INVALID_FILE_HANDLE)
{
printf("creat mp4 file fail\n");
stop(id);
return -1;
}
//设置mp4文件的时间单位
MP4SetTimeScale(fileHandle,90000);
//创建视频track
//根据ISO/IEC 14496-10 可知sps的第二个,第三个,第三个字节分别是 AVCProfileIndication,profile_compat,AVCLevelIndication
MP4TrackId video = MP4AddH264VideoTrack(fileHandle,90000,90000/12,320,240,sps_pps[1],sps_pps[2],sps_pps[3],3);
if(video == MP4_INVALID_TRACK_ID)
{
printf("creat video track fail\n");
stop(id);
MP4Close(fileHandle);
return -1;
}
//设置sps和pps
MP4AddH264SequenceParameterSet(fileHandle,video,sps_pps,sps_ppsLen-5);
MP4AddH264PictureParameterSet(fileHandle,video,sps_pps+sps_ppsLen-5,5);
int count = 0;
int num = 0;
while(count < 5000)
{
while(ret = thakral_getframe(id,buf+4,&frameSize,&num))
{
printf("get frame fail %d\n",ret);
usleep(90*1000);
}
//由于传过来的数据没有0x00000001这样的头,都是纯数据,而mp4中的nal结构是 nal长度+nal数据
int nalsize = frameSize;
buf[0] = (nalsize&0xff000000)>>24;
buf[1] = (nalsize&0x00ff0000)>>16;
buf[2] = (nalsize&0x0000ff00)>>8;
buf[3] = nalsize&0x000000ff;
MP4WriteSample(fileHandle,video,buf,frameSize+4,MP4_INVALID_DURATION,0,true);
count++;
usleep(85*1000);
}
stop(id);
MP4Close(fileHandle);
return 0;
}
更多推荐
所有评论(0)