您的位置:首页 > 移动开发 > IOS开发

Mp4V2库编译及使用

2015-04-09 12:07 274 查看
需求:想用Mp4V2 库将H264流录成MP4文件

反复折腾了好一下子,才整出来,再次纪录下。

具体实现:

1、下载Mp4v2源码

google code下载地址:http://code.google.com/p/mp4v2/downloads/list,若打不开链接,可以去github里搜索,本人也将其打包全部上传到github。

2、编译IOS上平台上合并库。

编译脚本如下(忘记出处了,不好意思):

#!/bin/sh

IOS_BASE_SDK=8.2
SOURCE="mp4v2-2.0.0"

ROOT=`pwd`
FAT="$ROOT/fat"
THIN="$ROOT/thin"

ARCHS="i386 x86_64 armv7 armv7s arm64 "
#ARCHS="i386 x86_64"
CONFIGURE_FLAGS="--disable-gch --disable-debug --disable-util \
--enable-shared=no"

clean()
{
rm -rf $THIN
rm -rf $FAT
}

clean

for ARCH in $ARCHS
do
echo "building $ARCH .."

if [ "$ARCH" = "i386" -o "$ARCH" = "x86_64" ]
then
PLATFORM="iPhoneSimulator"
CPU=
if [ "$ARCH" = "x86_64" ]
then
SIMULATOR="-mios-simulator-version-min=7.0"
HOST=
else
SIMULATOR="-mios-simulator-version-min=5.0"
HOST="--host=i386-apple-darwin"
fi
else
PLATFORM="iPhoneOS"
if [ $ARCH = "armv7s" ]
then
CPU="--cpu=swift"
else
CPU=
fi
SIMULATOR=
HOST="--host=arm-apple-darwin"
fi

DEVROOT=`xcode-select -p`/"Platforms/$PLATFORM.platform/Developer"
SDKROOT=$DEVROOT/SDKs/$PLATFORM$IOS_BASE_SDK.sdk
CFLAGS="-arch $ARCH $SIMULATOR -pipe -no-cpp-precomp -isysroot $SDKROOT -I$SDKROOT/usr/include/"

export CFLAGS="$CFLAGS"

export CXX="llvm-g++"
export CC="llvm-gcc"

if [ "$ARCH" = "i386" -o "$ARCH" = "x86_64" ]
then
export LD=$DEVROOT/usr/bin/ld
export LDFLAGS="-L$SDKROOT/usr/lib/"
else
export LD=$DEVROOT/usr/bin/ld
export AR=$DEVROOT/usr/bin/ar
export AS=$DEVROOT/usr/bin/as
export NM=$DEVROOT/usr/bin/nm
export RANLIB=$DEVROOT/usr/bin/ranlib
export LDFLAGS="-L$SDKROOT/usr/lib/"
export LIBTOOL=$DEVROOT/usr/bin/libtool
export LIPO=$DEVROOT/usr/bin/lipo
export OTOOL=$DEVROOT/usr/bin/otool
export NMEDIT=$DEVROOT/usr/bin/nmedit
export DSYMUTIL=$DEVROOT/usr/bin/dsymutil
export STRIP=$DEVROOT/usr/bin/strip
fi

export CPPFLAGS=$CFLAGS
export CXXFLAGS=$CFLAGS

make distclean
$ROOT/$SOURCE/configure $CONFIGURE_FLAGS $HOST --prefix="$THIN/$ARCH"
make
make install

echo "build $ARCH done.."
done

echo "building fat .."

mkdir -p "${FAT}/lib"

set - $ARCHS
CWD=`pwd`

cd ${THIN}/$1/lib
for LIB in `ls *.a`
do
echo $LIB
cd $CWD
xcrun -sdk iphoneos lipo -create `find $THIN -name $LIB` -output $FAT/lib/$LIB
done

cd $CWD
cp -rf $THIN/$1/include $FAT

echo "build fat done.."


3、使用:在写入文件时,需要先写入SPS帧和PPS帧,然后再写入I,B,P帧,不然录像文件播放不了。

#include "mp4record.h"
#include <stdlib.h>

typedef struct MP4V2_CONTEXT{

int m_vWidth,m_vHeight,m_vFrateR,m_vTimeScale;
MP4FileHandle m_mp4FHandle;
MP4TrackId m_vTrackId,m_aTrackId;
double m_vFrameDur;
} MP4V2_CONTEXT;

struct MP4V2_CONTEXT * recordCtx = NULL;

int initMp4Encoder(const char * filename,int width,int height){

int ret = -1;
recordCtx = malloc(sizeof(struct MP4V2_CONTEXT));
if (!recordCtx) {
printf("error : malloc context \n");
return ret;
}

recordCtx->m_vWidth = width;
recordCtx->m_vHeight = height;
recordCtx->m_vFrateR = 25;
recordCtx->m_vTimeScale = 90000;
recordCtx->m_vFrameDur = 300;
recordCtx->m_vTrackId = 0;
recordCtx->m_aTrackId = 0;

recordCtx->m_mp4FHandle = MP4Create(filename,0);
if (recordCtx->m_mp4FHandle == MP4_INVALID_FILE_HANDLE) {
printf("error : MP4Create  \n");
return ret;
}
MP4SetTimeScale(recordCtx->m_mp4FHandle, recordCtx->m_vTimeScale);
//------------------------------------------------------------------------------------- audio track
//    recordCtx->m_aTrackId = MP4AddAudioTrack(recordCtx->m_mp4FHandle, 44100, 1024, MP4_MPEG4_AUDIO_TYPE);
//    if (recordCtx->m_aTrackId == MP4_INVALID_TRACK_ID){
//        printf("error : MP4AddAudioTrack  \n");
//        return ret;
//    }
//
//    MP4SetAudioProfileLevel(recordCtx->m_mp4FHandle, 0x2);
//    uint8_t aacConfig[2] = {18,16};
//    MP4SetTrackESConfiguration(recordCtx->m_mp4FHandle,recordCtx->m_aTrackId,aacConfig,2);
//    printf("ok  : initMp4Encoder file=%s  \n",filename);

return 0;
}
int mp4VEncode(uint8_t * _naluData ,int _naluSize){

int index = -1;

if(_naluData[0]==0 && _naluData[1]==0 && _naluData[2]==0 && _naluData[3]==1 && _naluData[4]==0x67){
index = _NALU_SPS_;
}

if(index!=_NALU_SPS_ && recordCtx->m_vTrackId == MP4_INVALID_TRACK_ID){
return index;
}
if(_naluData[0]==0 && _naluData[1]==0 && _naluData[2]==0 && _naluData[3]==1 && _naluData[4]==0x68){
index = _NALU_PPS_;
}
if(_naluData[0]==0 && _naluData[1]==0 && _naluData[2]==0 && _naluData[3]==1 && _naluData[4]==0x65){
index = _NALU_I_;
}
if(_naluData[0]==0 && _naluData[1]==0 && _naluData[2]==0 && _naluData[3]==1 && _naluData[4]==0x41){
index = _NALU_P_;
}
//
switch(index){
case _NALU_SPS_:
if(recordCtx->m_vTrackId == MP4_INVALID_TRACK_ID){
recordCtx->m_vTrackId = MP4AddH264VideoTrack
(recordCtx->m_mp4FHandle,
recordCtx->m_vTimeScale,
recordCtx->m_vTimeScale / recordCtx->m_vFrateR,
recordCtx->m_vWidth,     // width
recordCtx->m_vHeight,    // height
_naluData[5], // sps[1] AVCProfileIndication
_naluData[6], // sps[2] profile_compat
_naluData[7], // sps[3] AVCLevelIndication
3);           // 4 bytes length before each NAL unit
if (recordCtx->m_vTrackId == MP4_INVALID_TRACK_ID)  {
return -1;
}
MP4SetVideoProfileLevel(recordCtx->m_mp4FHandle, 0x7F); //  Simple Profile @ Level 3
}
MP4AddH264SequenceParameterSet(recordCtx->m_mp4FHandle,recordCtx->m_vTrackId,_naluData+4,_naluSize-4);
//
break;
case _NALU_PPS_:
MP4AddH264PictureParameterSet(recordCtx->m_mp4FHandle,recordCtx->m_vTrackId,_naluData+4,_naluSize-4);
break;
case _NALU_I_:
{
uint8_t * IFrameData = malloc(_naluSize+1);
//
IFrameData[0] = (_naluSize-3) >>24;
IFrameData[1] = (_naluSize-3) >>16;
IFrameData[2] = (_naluSize-3) >>8;
IFrameData[3] = (_naluSize-3) &0xff;

memcpy(IFrameData+4,_naluData+3,_naluSize-3);
//            if(!MP4WriteSample(recordCtx->m_mp4FHandle, recordCtx->m_vTrackId, IFrameData, _naluSize+1, recordCtx->m_vFrameDur/44100*90000, 0, 1)){
//                return -1;
//            }
//            recordCtx->m_vFrameDur = 0;
if(!MP4WriteSample(recordCtx->m_mp4FHandle, recordCtx->m_vTrackId, IFrameData, _naluSize+1, MP4_INVALID_DURATION, 0, 1)){
return -1;
}
free(IFrameData);
//
break;
}
case _NALU_P_:
{
_naluData[0] = (_naluSize-4) >>24;
_naluData[1] = (_naluSize-4) >>16;
_naluData[2] = (_naluSize-4) >>8;
_naluData[3] = (_naluSize-4) &0xff;

//            if(!MP4WriteSample(recordCtx->m_mp4FHandle, recordCtx->m_vTrackId, _naluData, _naluSize, recordCtx->m_vFrameDur/44100*90000, 0, 1)){
//                return -1;
//            }
//            recordCtx->m_vFrameDur = 0;
if(!MP4WriteSample(recordCtx->m_mp4FHandle, recordCtx->m_vTrackId, _naluData, _naluSize, MP4_INVALID_DURATION, 0, 1)){
return -1;
}
break;
}
}
return 0;
}

int mp4AEncode(uint8_t * data ,int len){
if(recordCtx->m_vTrackId == MP4_INVALID_TRACK_ID){
return -1;
}
MP4WriteSample(recordCtx->m_mp4FHandle, recordCtx->m_aTrackId, data, len , MP4_INVALID_DURATION, 0, 1);
recordCtx->m_vFrameDur += 1024;
return 0;
}

void closeMp4Encoder(){
if(recordCtx){
if (recordCtx->m_mp4FHandle != MP4_INVALID_FILE_HANDLE) {
MP4Close(recordCtx->m_mp4FHandle,0);
recordCtx->m_mp4FHandle = NULL;
}

free(recordCtx);
recordCtx = NULL;
}

printf("ok  : closeMp4Encoder  \n");

}


附:有网友提出编译不过,报错。

原因:需要添加系统库libc++.dylib,添加即可。

参考网址:

http://blog.csdn.net/skdkjzz/article/details/40506473

https://github.com/Thinkerfans/lib-mp4v2
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  mp4v2 mp4 ios