1. 程式人生 > >最簡單的基於FFmpeg的移動端例子:IOS HelloWorld

最簡單的基於FFmpeg的移動端例子:IOS HelloWorld

=====================================================

最簡單的基於FFmpeg的移動端例子系列文章列表:

=====================================================


本文記錄IOS平臺下基於FFmpeg的HelloWorld程式。該示例C語言的原始碼來自於《最簡單的基於FFMPEG的Helloworld程式》。相關的概念就不再重複記錄了。


IOS程式使用FFmpeg類庫的說明

IOS應用程式使用FFmpeg類庫的流程如下所示。

1.編譯FFmpeg類庫

編譯IOS的FFmpeg類庫需要支援5種架構:armv7、armv7s、arm64、i386、x86_64。其中前面3個是給真機使用的,後面2個是給模擬器使用的。本文記錄的FFmpeg類庫還支援第三方類庫libx264和libfaac,所以在編譯之前還要先編譯libx264和libfaac的原始碼。總體說來,IOS下的類庫需要編譯成兩個版本:thin和fat。每種架構對應一個thin版本的類庫,將這些不同架構thin版本的類庫合成起來之後,就形成了fat版本的類庫。下面簡單記錄一下編譯步驟。編譯過程中IOS SDK版本為8.3,FFmpeg版本為2.7.1,faac和x264分別使用了最新版本的原始碼。

(1) 第三方庫libx264的編譯

這一步用於生成支援armv7、armv7s、arm64、i386、x86_64幾種架構的fat版本的libx264.a。下面這個指令碼可以首先編譯生成上面5種架構的thin版本的libx264.a,分成5個資料夾儲存於thin-x264資料夾中;然後將這些類庫合併成為1個fat版本的libx264.a,儲存於fat-x264資料夾中。

build_x264.sh
#!/bin/sh
# LXH,MXY
#
# directories
SOURCE="x264"
FAT="fat-x264"

SCRATCH="scratch-x264"
# must be an absolute path
THIN=`pwd`/"thin-x264"

#This is decided by your SDK version.
SDK_VERSION="8.3"

cd ./x264

#============== simulator ===============
PLATFORM="iPhoneSimulator"

#i386
ARCHS="i386"

export DEVROOT=/Applications/Xcode.app/Contents/Developer/Platforms/${PLATFORM}.platform/Developer
export SDKROOT=$DEVROOT/SDKs/${PLATFORM}${SDK_VERSION}.sdk
export CC=$DEVROOT/usr/bin/gcc
export LD=$DEVROOT/usr/bin/ld
export CXX=$DEVROOT/usr/bin/g++
export LIBTOOL=$DEVROOT/usr/bin/libtool
export HOST=i386-apple-darwin

COMMONFLAGS="-pipe -gdwarf-2 -no-cpp-precomp -isysroot ${SDKROOT} -fPIC"
export LDFLAGS="${COMMONFLAGS} -fPIC"
export CFLAGS="${COMMONFLAGS} -fvisibility=hidden"


for ARCH in $ARCHS; do

echo "Building $ARCH ......"

make clean
./configure \
--host=i386-apple-darwin \
--sysroot=$SDKROOT \
--prefix="$THIN/$ARCH" \
--extra-cflags="-arch $ARCH -miphoneos-version-min=6.0" \
--extra-ldflags="-L$SDKROOT/usr/lib/system -arch $ARCH -miphoneos-version-min=6.0" \
--enable-pic \
--enable-static \
--disable-asm \
make && make install && make clean

echo "Installed: $DEST/$ARCH"
done

#x86_64

ARCHS="x86_64"

unset DEVROOT
unset SDKROOT
unset CC
unset LD
unset CXX
unset LIBTOOL
unset HOST
unset LDFLAGS
unset CFLAGS

make clean
for ARCH in $ARCHS; do

echo "Building $ARCH ......"

./configure \
--prefix="$THIN/$ARCH" \
--enable-pic \
--enable-static \
--disable-asm \
make && make install && make clean

echo "Installed: $DEST/$ARCH"
done

#================ iphone ==================

export PLATFORM="iPhoneOS"

ARCHS="arm64 armv7 armv7s "

export DEVROOT=/Applications/Xcode.app/Contents/Developer
export SDKROOT=$DEVROOT/Platforms/${PLATFORM}.platform/Developer/SDKs/${PLATFORM}${SDK_VERSION}.sdk
#DEVPATH=/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS${SDK_VERSION}.sdk
export CC=$DEVROOT/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang
export AS=$DEVROOT/Toolchains/XcodeDefault.xctoolchain/usr/bin/as
COMMONFLAGS="-pipe -gdwarf-2 -no-cpp-precomp -isysroot ${SDKROOT} -marm -fPIC"
export LDFLAGS="${COMMONFLAGS} -fPIC"
export CFLAGS="${COMMONFLAGS} -fvisibility=hidden"
export CXXFLAGS="${COMMONFLAGS} -fvisibility=hidden -fvisibility-inlines-hidden"


for ARCH in $ARCHS; do

echo "Building $ARCH ......"

./configure \
--host=arm-apple-darwin \
--sysroot=$DEVPATH \
--prefix="$THIN/$ARCH" \
--extra-cflags="-arch $ARCH" \
--extra-ldflags="-L$DEVPATH/usr/lib/system -arch $ARCH" \
--enable-pic \
--enable-static \
--disable-asm

make && make install && make clean

echo "Installed: $DEST/$ARCH"

done

cd ..

#================ fat lib ===================

ARCHS="armv7 armv7s i386 x86_64 arm64"

echo "building fat binaries..."
mkdir -p $FAT/lib
set - $ARCHS
CWD=`pwd`
cd $THIN/$1/lib
for LIB in *.a
do
cd $CWD
lipo -create `find $THIN -name $LIB` -output $FAT/lib/$LIB
done

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

(2) 第三方庫libfaac的編譯

這一步用於生成支援armv7、armv7s、arm64、i386、x86_64幾種架構的fat版本的libfaac.a。下面這個指令碼可以首先編譯生成上面5種架構的thin版本的libfaac.a,分成5個資料夾儲存於fat-faac中;然後將這些類庫合併成為1個fat版本的libfaac.a,儲存於fat-faac中。

build_faac.sh
#!/bin/sh
cd ./faac
make distclean
cd ..

CONFIGURE_FLAGS="--enable-static --with-pic"

ARCHS="arm64 armv7s x86_64 i386 armv7"

# directories
SOURCE="faac"
FAT="fat-faac"

SCRATCH="scratch-faac"
# must be an absolute path
THIN=`pwd`/"thin-faac"

COMPILE="y"
LIPO="y"

if [ "$*" ]
then
if [ "$*" = "lipo" ]
then
# skip compile
COMPILE=
else
ARCHS="$*"
if [ $# -eq 1 ]
then
# skip lipo
LIPO=
fi
fi
fi

if [ "$COMPILE" ]
then
CWD=`pwd`
for ARCH in $ARCHS
do
echo "building $ARCH..."
mkdir -p "$SCRATCH/$ARCH"
cd "$SCRATCH/$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

XCRUN_SDK=`echo $PLATFORM | tr '[:upper:]' '[:lower:]'`
CC="xcrun -sdk $XCRUN_SDK clang -Wno-error=unused-command-line-argument-hard-error-in-future"
AS="/usr/local/bin/gas-preprocessor.pl $CC"
CFLAGS="-arch $ARCH $SIMULATOR"
CXXFLAGS="$CFLAGS"
LDFLAGS="$CFLAGS"

CC=$CC CFLAGS=$CXXFLAGS LDFLAGS=$LDFLAGS CPPFLAGS=$CXXFLAGS CXX=$CC CXXFLAGS=$CXXFLAGS  $CWD/$SOURCE/configure \
$CONFIGURE_FLAGS \
$HOST \
--prefix="$THIN/$ARCH" \
--disable-shared \
--without-mp4v2

make clean && make && make install-strip
cd $CWD
done
fi

#================ fat lib ===================

echo "building fat binaries..."
mkdir -p $FAT/lib
set - $ARCHS
CWD=`pwd`
cd $THIN/$1/lib
for LIB in *.a
do
cd $CWD
lipo -create `find $THIN -name $LIB` -output $FAT/lib/$LIB
done

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

(3) 編譯armv7版本FFmpeg類庫

這一步用於生成支援armv7架構的thin版本的FFmpeg類庫,儲存於thin-ffmpeg/armv7資料夾中。指令碼如下所示。

build_ffmpeg_demo_armv7.sh
#!/bin/sh
# LXH,MXY modified

cd ffmpeg

PLATFORM="iPhoneOS"
INSTALL="thin-ffmpeg"
SDK_VERSION="8.3"

# libx264
export X264ROOT=../thin-x264/armv7
export X264LIB=$X264ROOT/lib
export X264INCLUDE=$X264ROOT/include
# libfaac
export FAACROOT=../thin-faac/armv7
export FAACLIB=$FAACROOT/lib
export FAACINCLUDE=$FAACROOT/include

export DEVROOT=/Applications/Xcode.app/Contents/Developer

export SDKROOT=$DEVROOT/Platforms/${PLATFORM}.platform/Developer/SDKs/${PLATFORM}${SDK_VERSION}.sdk
export CC=$DEVROOT/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang
export AS=$DEVROOT/Toolchains/XcodeDefault.xctoolchain/usr/bin/as

COMMONFLAGS="-pipe -gdwarf-2 -no-cpp-precomp -isysroot ${SDKROOT} -marm -fPIC"
export LDFLAGS="${COMMONFLAGS} -fPIC"
export CFLAGS="${COMMONFLAGS} -fvisibility=hidden"
export CXXFLAGS="${COMMONFLAGS} -fvisibility=hidden -fvisibility-inlines-hidden"


echo "Building armv7..."

make clean
./configure \
    --cpu=cortex-a9 \
    --extra-cflags='-I$X264INCLUDE -I$FAACINCLUDE -arch armv7 -miphoneos-version-min=5.0 -mthumb' \
    --extra-ldflags='-L$X264LIB -L$FAACLIB -arch armv7 -miphoneos-version-min=5.0' \
    --enable-cross-compile \
    --arch=arm --disable-iconv\
    --target-os=darwin \
    --cc=${CC} --disable-asm\
    --sysroot=${SDKROOT} \
    --prefix=../${INSTALL}/armv7 \
--enable-gpl --enable-nonfree --enable-version3 --disable-bzlib --enable-small --disable-vda \
--disable-encoders --enable-libx264 --enable-libfaac --enable-encoder=libx264 --enable-encoder=libfaac \
--disable-muxers --enable-muxer=flv --enable-muxer=mov --enable-muxer=ipod --enable-muxer=mpegts --enable-muxer=psp --enable-muxer=mp4 --enable-muxer=avi \
--disable-decoders --enable-decoder=aac --enable-decoder=aac_latm --enable-decoder=h264 --enable-decoder=mpeg4 \
--disable-demuxers --enable-demuxer=flv --enable-demuxer=h264 --enable-demuxer=mpegts --enable-demuxer=avi --enable-demuxer=mpc --enable-demuxer=mov \
--disable-parsers --enable-parser=aac --enable-parser=ac3 --enable-parser=h264 \
--disable-protocols --enable-protocol=file --enable-protocol=rtmp --enable-protocol=rtp --enable-protocol=udp \
--disable-bsfs --enable-bsf=aac_adtstoasc --enable-bsf=h264_mp4toannexb \
--disable-devices --disable-debug --disable-ffmpeg --disable-ffprobe --disable-ffplay --disable-ffserver --disable-debug

make
make install

cd ..

(4) 編譯armv7s版本FFmpeg類庫

這一步用於生成支援armv7s架構的thin版本的FFmpeg類庫,儲存於thin-ffmpeg/armv7s資料夾中。指令碼如下所示。

build_ffmpeg_demo_armv7s.sh
#!/bin/sh
# LXH,MXY modified

cd ffmpeg

PLATFORM="iPhoneOS"
INSTALL="thin-ffmpeg"
SDK_VERSION="8.3"

# libx264
export X264ROOT=../thin-x264/armv7s
export X264LIB=$X264ROOT/lib
export X264INCLUDE=$X264ROOT/include
# libfaac
export FAACROOT=../thin-faac/armv7s
export FAACLIB=$FAACROOT/lib
export FAACINCLUDE=$FAACROOT/include

export DEVROOT=/Applications/Xcode.app/Contents/Developer

export SDKROOT=$DEVROOT/Platforms/${PLATFORM}.platform/Developer/SDKs/${PLATFORM}${SDK_VERSION}.sdk
export CC=$DEVROOT/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang
export AS=$DEVROOT/Toolchains/XcodeDefault.xctoolchain/usr/bin/as

COMMONFLAGS="-pipe -gdwarf-2 -no-cpp-precomp -isysroot ${SDKROOT} -marm -fPIC"
export LDFLAGS="${COMMONFLAGS} -fPIC"
export CFLAGS="${COMMONFLAGS} -fvisibility=hidden"
export CXXFLAGS="${COMMONFLAGS} -fvisibility=hidden -fvisibility-inlines-hidden"


echo "Building armv7s..."

make clean
./configure \
    --cpu=cortex-a9 \
    --extra-cflags='-I$X264INCLUDE -I$FAACINCLUDE -arch armv7s -miphoneos-version-min=5.0 -mthumb' \
    --extra-ldflags='-L$X264LIB -L$FAACLIB -arch armv7s -miphoneos-version-min=5.0' \
    --enable-cross-compile \
    --arch=arm --disable-iconv\
    --target-os=darwin \
    --cc=${CC} --disable-asm \
    --sysroot=${SDKROOT} \
    --prefix=../${INSTALL}/armv7s \
--enable-gpl --enable-nonfree --enable-version3 --disable-bzlib --enable-small --disable-vda \
 --disable-encoders --enable-libx264 --enable-libfaac --enable-encoder=libx264 --enable-encoder=libfaac \
 --disable-muxers --enable-muxer=flv --enable-muxer=mov --enable-muxer=ipod --enable-muxer=mpegts --enable-muxer=psp --enable-muxer=mp4 --enable-muxer=avi \
 --disable-decoders --enable-decoder=aac --enable-decoder=aac_latm --enable-decoder=h264 --enable-decoder=mpeg4 \
 --disable-demuxers --enable-demuxer=flv --enable-demuxer=h264 --enable-demuxer=avi --enable-demuxer=mpegts --enable-demuxer=mpc --enable-demuxer=mov \
 --disable-parsers --enable-parser=aac --enable-parser=ac3 --enable-parser=h264 \
 --disable-protocols --enable-protocol=file --enable-protocol=rtmp --enable-protocol=rtp --enable-protocol=udp \
 --disable-bsfs --enable-bsf=aac_adtstoasc --enable-bsf=h264_mp4toannexb \
 --disable-devices --disable-debug --disable-ffmpeg --disable-ffprobe --disable-ffplay --disable-ffserver --disable-debug

make
make install

cd ..

(5) 編譯arm64版本FFmpeg類庫

這一步用於生成支援arm64架構的thin版本的FFmpeg類庫,儲存於thin-ffmpeg/arm64資料夾中。指令碼如下所示。

build_ffmpeg_demo_arm64.sh
#!/bin/sh
# LXH,MXY modified
	
cd ffmpeg

PLATFORM="iPhoneOS"
INSTALL="thin-ffmpeg"
SDK_VERSION="8.3"

# libx264
export X264ROOT=../thin-x264/arm64
export X264LIB=$X264ROOT/lib
export X264INCLUDE=$X264ROOT/include
# libfaac
export FAACROOT=../thin-faac/arm64
export FAACLIB=$FAACROOT/lib
export FAACINCLUDE=$FAACROOT/include

export DEVROOT=/Applications/Xcode.app/Contents/Developer

export SDKROOT=$DEVROOT/Platforms/${PLATFORM}.platform/Developer/SDKs/${PLATFORM}${SDK_VERSION}.sdk
export CC=$DEVROOT/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang
export AS=$DEVROOT/Toolchains/XcodeDefault.xctoolchain/usr/bin/as

COMMONFLAGS="-pipe -gdwarf-2 -no-cpp-precomp -isysroot ${SDKROOT} -marm -fPIC"
export LDFLAGS="${COMMONFLAGS} -fPIC"
export CFLAGS="${COMMONFLAGS} -fvisibility=hidden"
export CXXFLAGS="${COMMONFLAGS} -fvisibility=hidden -fvisibility-inlines-hidden"


echo "Building arm64..."

make clean
./configure \
    --extra-cflags='-I$X264INCLUDE -I$FAACINCLUDE -arch arm64 -miphoneos-version-min=5.0 -mthumb' \
    --extra-ldflags='-L$X264LIB -L$FAACLIB -arch arm64 -miphoneos-version-min=5.0' \
    --enable-cross-compile \
    --arch=arm --disable-iconv \
    --target-os=darwin \
    --cc=${CC} --disable-asm \
    --sysroot=${SDKROOT} \
    --prefix=../${INSTALL}/arm64 \
--enable-gpl --enable-nonfree --enable-version3 --disable-bzlib --enable-small --disable-vda \
--disable-encoders --enable-libx264 --enable-libfaac --enable-encoder=libx264 --enable-encoder=libfaac \
--disable-muxers --enable-muxer=flv --enable-muxer=mov --enable-muxer=ipod --enable-muxer=mpegts --enable-muxer=psp --enable-muxer=mp4 --enable-muxer=avi \
--disable-decoders --enable-decoder=aac --enable-decoder=aac_latm --enable-decoder=h264 --enable-decoder=mpeg4 \
--disable-demuxers --enable-demuxer=flv --enable-demuxer=h264 --enable-demuxer=avi --enable-demuxer=mpegts --enable-demuxer=mpc --enable-demuxer=mov \
--disable-parsers --enable-parser=aac --enable-parser=ac3 --enable-parser=h264 \
--disable-protocols --enable-protocol=file --enable-protocol=rtmp --enable-protocol=rtp --enable-protocol=udp \
--disable-bsfs --enable-bsf=aac_adtstoasc --enable-bsf=h264_mp4toannexb \
--disable-devices --disable-debug --disable-ffmpeg --disable-ffprobe --disable-ffplay --disable-ffserver --disable-debug

make
make install

cd ..

(6) 編譯i386版本FFmpeg類庫

這一步用於生成支援i386架構的thin版本的FFmpeg類庫,儲存於thin-ffmpeg/i386資料夾中。指令碼如下所示。

build_ffmpeg_demo_i386.sh
#!/bin/sh
# LXH,MXY modified

cd ffmpeg

PLATFORM="iPhoneSimulator"
INSTALL="thin-ffmpeg"
SDK_VERSION="8.3"

# libx264
export X264ROOT=../thin-x264/i386
export X264LIB=$X264ROOT/lib
export X264INCLUDE=$X264ROOT/include
# libfaac
export FAACROOT=../thin-faac/i386
export FAACLIB=$FAACROOT/lib
export FAACINCLUDE=$FAACROOT/include

export DEVROOT=/Applications/Xcode.app/Contents/Developer/Platforms/${PLATFORM}.platform/Developer
export SDKROOT=$DEVROOT/SDKs/${PLATFORM}${SDK_VERSION}.sdk
export CC=$DEVROOT/usr/bin/gcc
export LD=$DEVROOT/usr/bin/ld

export CXX=$DEVROOT/usr/bin/g++

export LIBTOOL=$DEVROOT/usr/bin/libtool

COMMONFLAGS="-pipe -gdwarf-2 -no-cpp-precomp -isysroot ${SDKROOT} -fPIC"
export LDFLAGS="${COMMONFLAGS} -fPIC"
export CFLAGS="${COMMONFLAGS} -fvisibility=hidden"


echo "Building i386..."
make clean
./configure \
    --cpu=i386 \
    --extra-cflags='-I$X264INCLUDE -I$FAACINCLUDE -arch i386 -miphoneos-version-min=5.0' \
    --extra-ldflags='-L$X264LIB -L$FAACLIB -arch i386 -miphoneos-version-min=5.0' \
    --enable-cross-compile \
    --arch=i386 --disable-iconv \
    --target-os=darwin \
    --cc=${CC} \
    --sysroot=${SDKROOT} \
--prefix=../${INSTALL}/i386 \
--enable-gpl --enable-nonfree --enable-version3 --disable-bzlib --enable-small --disable-vda \
--disable-encoders --enable-libx264 --enable-libfaac --enable-encoder=libx264 --enable-encoder=libfaac \
--disable-muxers --enable-muxer=flv --enable-muxer=mov --enable-muxer=mpegts --enable-muxer=ipod --enable-muxer=psp --enable-muxer=mp4 --enable-muxer=avi \
--disable-decoders --enable-decoder=aac --enable-decoder=aac_latm --enable-decoder=h264 --enable-decoder=mpeg4 \
--disable-demuxers --enable-demuxer=flv --enable-demuxer=h264 --enable-demuxer=mpegts --enable-demuxer=avi --enable-demuxer=mpc --enable-demuxer=mov \
--disable-parsers --enable-parser=aac --enable-parser=ac3 --enable-parser=h264 \
--disable-protocols --enable-protocol=file --enable-protocol=rtmp --enable-protocol=rtp --enable-protocol=udp \
--disable-bsfs --enable-bsf=aac_adtstoasc --enable-bsf=h264_mp4toannexb \
--disable-devices --disable-debug --disable-ffmpeg --disable-ffprobe --disable-ffplay --disable-ffserver --disable-debug

make
make install

cd ..

(7) 編譯x86_64版本FFmpeg類庫

這一步用於生成支援x86_64架構的thin版本的FFmpeg類庫,儲存於thin-ffmpeg/x86_64資料夾中。指令碼如下所示。

build_ffmpeg_demo_x86_64.sh
#!/bin/sh
# LXH,MXY modified

cd ./ffmpeg

INSTALL="thin-ffmpeg"

# libx264
export X264ROOT=../thin-x264/x86_64
export X264LIB=$X264ROOT/lib
export X264INCLUDE=$X264ROOT/include
# libfaac
export FAACROOT=../thin-faac/x86_64
export FAACLIB=$FAACROOT/lib
export FAACINCLUDE=$FAACROOT/include

unset DEVROOT
unset SDKROOT
unset CC
unset LD
unset CXX
unset LIBTOOL
unset HOST
unset LDFLAGS
unset CFLAGS

echo "Building x86_64..."

make clean
./configure \
    --extra-cflags='-I$X264INCLUDE -I$FAACINCLUDE' \
    --extra-ldflags='-L$X264LIB -L$FAACLIB' \
    --disable-iconv \
    --disable-asm \
--prefix=../${INSTALL}/x86_64 \
--enable-gpl --enable-nonfree --enable-version3 --disable-bzlib --enable-small --disable-vda \
--disable-encoders --enable-libx264 --enable-libfaac --enable-encoder=libx264 --enable-encoder=mpeg2video --enable-encoder=libfaac \
--disable-muxers --enable-muxer=flv --enable-muxer=mov --enable-muxer=ipod --enable-muxer=mpegts --enable-muxer=psp --enable-muxer=mp4 --enable-muxer=avi \
--disable-decoders --enable-decoder=aac --enable-decoder=mpeg2video --enable-decoder=aac_latm --enable-decoder=h264 --enable-decoder=mpeg4 \
--disable-demuxers --enable-demuxer=flv --enable-demuxer=h264 --enable-demuxer=avi --enable-demuxer=mpegts --enable-demuxer=mpc --enable-demuxer=mov \
--disable-parsers --enable-parser=aac --enable-parser=ac3 --enable-parser=h264 \
--disable-protocols --enable-protocol=file --enable-protocol=rtmp --enable-protocol=rtp --enable-protocol=udp \
--enable-bsf=aac_adtstoasc --enable-bsf=h264_mp4toannexb \
--disable-devices --disable-debug --disable-ffmpeg --disable-ffprobe --disable-ffplay --disable-ffserver --disable-debug

make
make install
cd ..

(8) 打包類庫

這一步用於將上述步驟中生成的5個版本的FFmpeg打包生成fat版本的FFmpeg類庫。這一步驟執行完畢後,將thin-ffmpeg中幾個thin版本的類庫合併為一個fat版本的類庫,並存儲於fat-ffmpeg資料夾中。指令碼如下所示。

build_ffmpeg_fat.sh
#!/bin/sh


# directories
THIN=`pwd`/"thin-ffmpeg"
FAT=`pwd`/"fat-ffmpeg"
CWD=`pwd`
# must be an absolute path


ARCHS="armv7s i386 armv7 arm64 x86_64"


echo "building fat binaries..."

mkdir -p $FAT/lib
set - $ARCHS
cd thin-ffmpeg/$1/lib
for LIB in *.a
do
cd $CWD
lipo -create `find $THIN -name $LIB` -output $FAT/lib/$LIB
done

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

生成完fat版本的類庫後,可以在命令列使用lipo命令檢視類庫的架構,如下所示。
lipo -info libavcodec.a

2.編寫IOS程式

編寫包含FFmpeg類庫支援的IOS程式分成兩步:配置Xcode環境,編寫C語言程式碼。

(1) 配置Xcode環境

下面以Xcode的IOS中的Single View Application為例,記錄一下配置步驟:

(a)拷貝標頭檔案所在的include資料夾和fat版本的FFmpeg類庫(包括libavformat.a, libavcodec.a, libavutil.a, libavdevice.a, libavfilter.a, libpostproc.a, libswresample.a, libswscale.a;以及第三方fat版本類庫libx264.a, libfaac.a)至專案資料夾。並將它們新增至專案中。

(b)專案屬性->Build Settings中配置以下3個選項。
Linking->Other Linker Flags中新增下面內容:
-lavformat
-lavcodec
-lavutil
-lavdevice
-lavfilter
-lpostproc
-lswresample
-lswscale
-lx264
-lfaac
Search Paths->Header Search Paths新增下面內容
$(PROJECT_DIR)/include
Search Paths->Library Search Paths新增下面內容
$(PROJECT_DIR)
其它的一些配置。這些配置隨著FFmpeg版本的不同而有略微的不同(在某些情況下也可能不需要配置)。我目前使用的2.7.1版本的FFmpeg需要配置下面的選項。
專案屬性->General->Linked Frameworks and Libraries中新增兩個類庫:AVFoundation.framework和libz.dylib。

(2) 編寫C語言程式碼

做好上面配置後,就可以在專案中編寫程式碼測試一下FFmpeg是否正確配置了。由於IOS使用的Objective-C是相容C語言的,所以可以直接寫C語言程式碼呼叫FFmpeg。可以在ViewController.m中的viewDidLoad()函式中新增一行printf()程式碼列印FFmpeg類庫的版本資訊,如下所示。
#import "ViewController.h"
#include <libavcodec/avcodec.h>

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    printf("%s",avcodec_configuration());
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

如果類庫編譯無誤,啟動IOS程式的時候會在控制檯列印版本資訊。

原始碼

專案的目錄結構如圖所示。

C程式碼位於ViewController.m檔案中,內容如下所示。
/**
 * 最簡單的基於FFmpeg的HelloWorld程式 - IOS
 * Simplest FFmpeg Helloworld - IOS
 *
 * 雷霄驊 Lei Xiaohua
 * [email protected]
 * 中國傳媒大學/數字電視技術
 * Communication University of China / Digital TV Technology
 * http://blog.csdn.net/leixiaohua1020
 *
 * 本程式可以獲得FFmpeg類庫相關的資訊。
 * This software can get information about FFmpeg libraries.
 *
 */

#import "ViewController.h"
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavfilter/avfilter.h>

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    av_register_all();
    char info[10000] = { 0 };
    printf("%s\n", avcodec_configuration());
    sprintf(info, "%s\n", avcodec_configuration());
    NSString * info_ns = [NSString stringWithFormat:@"%s", info];
    self.content.text=info_ns;
}


- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

- (IBAction)clickProtocolButton:(id)sender {
    //Alert
    /*
    UIAlertView *alter = [[UIAlertView alloc] initWithTitle:@"Title" message:@"This is content" delegate:nil cancelButtonTitle:@"Close" otherButtonTitles:nil];
    [alter show];
     */
    char info[40000]={0};
    av_register_all();
    
    struct URLProtocol *pup = NULL;
    //Input
    struct URLProtocol **p_temp = &pup;
    avio_enum_protocols((void **)p_temp, 0);
    while ((*p_temp) != NULL){
        sprintf(info, "%s[In ][%10s]\n", info, avio_enum_protocols((void **)p_temp, 0));
    }
    pup = NULL;
    //Output
    avio_enum_protocols((void **)p_temp, 1);
    while ((*p_temp) != NULL){
        sprintf(info, "%s[Out][%10s]\n", info, avio_enum_protocols((void **)p_temp, 1));
    }
    //printf("%s", info);
    NSString * info_ns = [NSString stringWithFormat:@"%s", info];
    self.content.text=info_ns;
}

- (IBAction)clickAVFormatButton:(id)sender {
    char info[40000] = { 0 };
    
    av_register_all();
    
    AVInputFormat *if_temp = av_iformat_next(NULL);
    AVOutputFormat *of_temp = av_oformat_next(NULL);
    //Input
    while(if_temp!=NULL){
        sprintf(info, "%s[In ]%10s\n", info, if_temp->name);
        if_temp=if_temp->next;
    }
    //Output
    while (of_temp != NULL){
        sprintf(info, "%s[Out]%10s\n", info, of_temp->name);
        of_temp = of_temp->next;
    }
    //printf("%s", info);
    NSString * info_ns = [NSString stringWithFormat:@"%s", info];
    self.content.text=info_ns;
}


- (IBAction)clickAVCodecButton:(id)sender {
    
    char info[40000] = { 0 };
    
    av_register_all();
    
    AVCodec *c_temp = av_codec_next(NULL);
    
    while(c_temp!=NULL){
        if (c_temp->decode!=NULL){
            sprintf(info, "%s[Dec]", info);
        }
        else{
            sprintf(info, "%s[Enc]", info);
        }
        switch (c_temp->type){
            case AVMEDIA_TYPE_VIDEO:
                sprintf(info, "%s[Video]", info);
                break;
            case AVMEDIA_TYPE_AUDIO:
                sprintf(info, "%s[Audio]", info);
                break;
            default:
                sprintf(info, "%s[Other]", info);
                break;
        }
        sprintf(info, "%s%10s\n", info, c_temp->name);
        
        
        c_temp=c_temp->next;
    }
    //printf("%s", info);
    NSString * info_ns = [NSString stringWithFormat:@"%s", info];
    self.content.text=info_ns;
}

- (IBAction)clickAVFilterButton:(id)sender {
    char info[40000] = { 0 };
    avfilter_register_all();
    AVFilter *f_temp = (AVFilter *)avfilter_next(NULL);
    while (f_temp != NULL){
        sprintf(info, "%s[%10s]\n", info, f_temp->name);
    }
    //printf("%s", info);
    NSString * info_ns = [NSString stringWithFormat:@"%s", info];
    self.content.text=info_ns;
}

- (IBAction)clickConfigurationButton:(id)sender {
    char info[10000] = { 0 };
    av_register_all();
    
    sprintf(info, "%s\n", avcodec_configuration());
    
    //printf("%s", info);
    //[email protected]"Lei Xiaohua";
    NSString * info_ns = [NSString stringWithFormat:@"%s", info];
    self.content.text=info_ns;
}


@end

執行結果

App在手機上執行後的結果如下圖所示。

單擊不同的按鈕,可以得到類庫不同方面的資訊。單擊“Protocol”按鈕內容如下所示。

單擊“AVFormat”按鈕內容如下所示。
 單擊“AVCodec”按鈕內容如下所示。
 單擊“Configure”按鈕即為程式開始執行時候的內容。


下載


simplest ffmpeg mobile

專案主頁

CSDN工程下載地址:http://download.csdn.net/detail/leixiaohua1020/8924391

本解決方案包含了使用FFmpeg在移動端處理多媒體的各種例子:
[Android]
simplest_android_player: 基於安卓介面的視訊播放器
simplest_ffmpeg_android_helloworld: 安卓平臺下基於FFmpeg的HelloWorld程式
simplest_ffmpeg_android_decoder: 安卓平臺下最簡單的基於FFmpeg的視訊解碼器
simplest_ffmpeg_android_decoder_onelib: 安卓平臺下最簡單的基於FFmpeg的視訊解碼器-單庫版
simplest_ffmpeg_android_streamer: 安卓平臺下最簡單的基於FFmpeg的推流器
simplest_ffmpeg_android_transcoder: 安卓平臺下移植的FFmpeg命令列工具
simplest_sdl_android_helloworld: 移植SDL到安卓平臺的最簡單程式
[IOS]
simplest_ios_player: 基於IOS介面的視訊播放器
simplest_ffmpeg_ios_helloworld: IOS平臺下基於FFmpeg的HelloWorld程式
simplest_ffmpeg_ios_decoder: IOS平臺下最簡單的基於FFmpeg的視訊解碼器
simplest_ffmpeg_ios_streamer: IOS平臺下最簡單的基於FFmpeg的推流器
simplest_ffmpeg_ios_transcoder: IOS平臺下移植的ffmpeg.c命令列工具
simplest_sdl_ios_helloworld: 移植SDL到IOS平臺的最簡單程式

相關推薦

簡單基於FFmpeg移動例子IOS HelloWorld

=====================================================最簡單的基於FFmpeg的移動端例子系列文章列表:=====================================================本文記錄IOS

簡單基於FFmpeg移動例子Android 視訊轉碼器

=====================================================最簡單的基於FFmpeg的移動端例子系列文章列表:=====================================================本文記錄一個安

簡單基於FFmpeg移動例子附件SDL Android HelloWorld

=====================================================最簡單的基於FFmpeg的移動端例子系列文章列表:=====================================================本文記錄一個安

簡單基於FFmpeg移動例子附件Android 自帶播放器

=====================================================最簡單的基於FFmpeg的移動端例子系列文章列表:=====================================================前幾篇文章記錄

簡單基於FFmpeg移動樣例IOS HelloWorld

目的 mes 真機 roo mux 能夠 ted 配置 details =====================================================最簡單的基於FFmpeg的移動端樣例系列文章列表:最簡單的基於FFmpeg的移動端樣例:An

簡單基於FFmpeg的AVfilter例子(水印疊加

                =====================================================最簡單的基於FFmpeg的AVfilter例子系列文章:=====================================================FFMPE

簡單基於FFmpeg的AVDevice例子 讀取攝像頭

                =====================================================最簡單的基於FFmpeg的AVDevice例子文章列表:最簡單的基於FFmpeg的AVDevice例子(螢幕錄製)=============================

簡單基於FFmpeg的AVDevice例子(讀取攝像頭)解讀

本文轉載自最簡單的基於FFmpeg的AVDevice例子(讀取攝像頭) 在此基礎上對程式的流程進行解讀,閱讀前請先閱讀原文。 ============================= /** * 最簡單的基於FFmpeg的AVDevice例子(讀取攝像頭) * Simplest F

移動頁面viewport與分辨率的坑

效果 span idt 分辨 name col 移動端 use init <meta name="viewport" content="width=device-width, user-scalable=no"> <meta name=‘

[轉]Netty入門(簡單的Netty客戶/服務器程序)

serve exc new final 綁定 title graceful 關閉連接 listener  Java中的NIO是一種解決阻塞式IO問題的基本技術,但是NIO的編寫對java程序員是有比較高的要求的。那麽Netty就是一種簡化操作的一個成熟的網絡IO編程框架。這

vue2 + iview-admin 1.3 + django 2.0 一個簡單的增刪改查例子

iview-admin axios django 前後端分離 api 以下為利用iview-admin + django 做的一個最基本的增刪改查例子。 前端iview-admin git clone https://github.com/iview/iview-admin.git cd

基於VUE移動UI好用框架

1. vonic 一個基於 vue.js 和 ionic 樣式的 UI 框架,用於快速構建移動端單頁應用,很簡約,是我喜歡的風格 star 2.3k 中文文件 線上預覽 2.vux 基於WeUI和Vue(2.x)開發的移動端UI元件庫 star 10k 基於webpack+vue-loader+v

分享幾個簡單的bat指令碼的例子

兩個小時後自動關機 echo off shutdown /s /t 7200 進入C盤一個資料夾執行一個程式,接收使用者兩個輸入,一個是百度文庫某一個文件的連結,一個是該文件的型別,然後根據該程式執行的規則:FreeForWenku.exe + URL + 型

MongoDB簡單的入門教程之四使用Spring Boot操作MongoDB

Spring Boot 是一個輕量級框架,可以完成基於 Spring 的應用程式的大部分配置工作。Spring Boot的目的是提供一組工具,以便快速構建容易配置的Spring應用程式,省去大量傳統Spring專案的繁瑣配置。 MongoDB是一個基於分散式檔

基於vue移動UI框架

1.vux 基於WeUI和Vue(2.x)開發的移動端UI元件庫 基於webpack+vue-loader+vux可以快速開發移動端頁面,配合vux-loader方便你在WeUI的基礎上定製需要的樣式。 中文文件 線上預覽 特性 star數最多 這可能跟

移動網頁給body設定 overflowhidden 無效的解決辦法

做移動端網頁的時候,總會遇到一些奇葩的問題,在PC端瀏覽器做模擬除錯時,都是完美顯示的,但是一到真機除錯就是各種坑; 我在做移動端網頁時的需求是這樣的: 頁面背景圖片是自適應螢幕大小的,頁面上有輸入框和按鈕,當點選輸入框時,移動端的軟鍵盤彈出,但是背景圖片不能受影響而被壓縮,且頁面不能應為軟

史上簡單的 SpringCloud 教程 | 第一篇 服務的註冊與發現(Eureka)

一、spring cloud簡介 spring cloud 為開發人員提供了快速構建分散式系統的一些工具,包括配置管理、服務發現、斷路器、路由、微代理

移動border1px 解決辦法

sass寫法 @mixin border-1px ($color) { position:relative; &::after{ diplay:block; position:ab

WebRTC中簡單loopback攝像頭&麥克風的例子【轉】

peerconnection_client本地回放原理 預設的client已經集成了本地回放程式碼,但是要想實現該功能,需要做少許修改。預設的點選介面上的"connect"按鈕是連線到另一臺peer,其最終執行的函式為Conductor::StartLogin。現在我們想

簡單寫一個移動touch事件

var mybody = document.getElementsByTagName('body')[0];         //滑動處理     var startX, startY, moveEndX, mov