FFmpeg 支持 libstagefright 硬件解码

Posted

技术标签:

【中文标题】FFmpeg 支持 libstagefright 硬件解码【英文标题】:FFmpeg support for libstagefright hardware decoding 【发布时间】:2014-11-07 05:53:35 【问题描述】:

大家: 我是ffmpeg的新手。最近我正在研究将 ffmpeg 移植到 android 设备的项目。 一开始,我按照互联网上的一些指南以非常正常的方式将ffmpeg编译为共享库(.so文件),将它们加载到我的android应用程序中。效果很好。

现在我想让 ffmpeg 使用 libstagefright 来完成硬件解码。 问题是,我可以编译 .so 库,但是当我启动我的应用程序并加载这些 .so 库时,总是会出现 java.lang.UnsatisfiedLinkError: 无法加载库:reloc_library[1314]: 114 找不到'_ZN7android11MediaBufferC1Ej'

我在那里呆了几天。有没有人遇到过类似的问题?如果有人能给我一些关于这个错误的提示,那就太好了。

我的步骤: 1、编译ffmpeg-2.1.4源代码为.so共享库。我使用 build_libstagefright 脚本来执行此操作,并根据 Internet 的一些指南进行了一些修改。

#!/bin/bash
#export NDK=/home/mingzhang/android/android-ndk-r9c
export NDK=/home/mingzhang/android/android-ndk-r7
if [ "$NDK" = "" ]; then
    echo NDK variable not set, assuming $HOME/android-ndk
    export NDK=$HOME/android-ndk
fi

echo "Fetching Android system headers"
git clone --depth=1 --branch gingerbread-release git://github.com/CyanogenMod/android_frameworks_base.git ../android-source/frameworks/base
git clone --depth=1 --branch gingerbread-release git://github.com/CyanogenMod/android_frameworks_av.git ../android-source/frameworks/av
git clone --depth=1 --branch gingerbread-release git://github.com/CyanogenMod/android_frameworks_native.git ../android-source/frameworks/native
git clone --depth=1 --branch gingerbread-release git://github.com/CyanogenMod/android_hardware_libhardware.git ../android-source/hardware/libhardware
git clone --depth=1 --branch gingerbread-release git://github.com/CyanogenMod/android_system_core.git ../android-source/system/core

echo "Fetching Android libraries for linking"
# Libraries from any froyo/gingerbread device/emulator should work
# fine, since the symbols used should be available on most of them.
#if [ ! -d "../android-libs" ]; then
#    if [ ! -f "../update-cm-7.0.3-N1-signed.zip" ]; then
#        wget http://download.cyanogenmod.com/get/update-cm-7.0.3-N1-signed.zip -P../
#    fi
#    unzip ../update-cm-7.0.3-N1-signed.zip system/lib/* -d../
#    mv ../system/lib ../android-libs
#    rmdir ../system
#fi

SYSROOT=$NDK/platforms/android-9/arch-arm
# Expand the prebuilt/* path into the correct one
#TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86_64
TOOLCHAIN=/home/mingzhang/android/android-ndk-r7/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86
export PATH=$TOOLCHAIN/bin:$PATH
ANDROID_SOURCE=../android-source
ANDROID_LIBS=../android-libs
ABI="armeabi-v7a"
CC=$TOOLCHAIN/bin/arm-linux-androideabi-gcc
#CC=$TOOLCHAIN/bin/arm-eabi-gcc-4.4.3
NM=$TOOLCHAIN/bin/arm-linux-androideabi-nm
#NM=$TOOLCHAIN/bin/arm-eabi-nm

rm -rf ../build/stagefright
mkdir -p ../build/stagefright

ADDI_CFLAGS="-marm"
DEST=../build/stagefright
DEST="$DEST/$ABI"

FLAGS="--target-os=linux --arch=arm --cpu=armv7-a --cross-prefix=arm-linux-androideabi- --cc=$CC --nm=$NM"
#FLAGS="--target-os=linux --arch=arm --cpu=armv7-a --cross-prefix=arm-eabi- --cc=$CC --nm=$NM"
FLAGS="$FLAGS --sysroot=$SYSROOT"
#FLAGS="$FLAGS --disable-avdevice --disable-decoder=h264 --disable-decoder=h264_vdpau --enable-libstagefright-h264"
FLAGS="$FLAGS --enable-shared --disable-demuxers --disable-muxers --disable-parsers --disable-avdevice --disable-filters --disable-programs --disable-encoders --disable-decoders --disable-decoder=h264 --disable-decoder=h264_vdpau --enable-decoder=libstagefright_h264 --enable-libstagefright-h264 \
    --enable-asm \
    --enable-neon \
    --enable-cross-compile \
    --enable-gpl \
    --disable-static \
    --enable-memalign-hack"

EXTRA_CFLAGS="-I$DEST/include"
EXTRA_CFLAGS="$EXTRA_CFLAGS -I$ANDROID_SOURCE/frameworks/native/include"
EXTRA_CFLAGS="$EXTRA_CFLAGS -I$ANDROID_SOURCE/frameworks/native/include/media/openmax"
EXTRA_CFLAGS="$EXTRA_CFLAGS -I$ANDROID_SOURCE/frameworks/av/include"
EXTRA_CFLAGS="$EXTRA_CFLAGS -I$ANDROID_SOURCE/frameworks/base/include -I$ANDROID_SOURCE/system/core/include"
EXTRA_CFLAGS="$EXTRA_CFLAGS -I$ANDROID_SOURCE/hardware/libhardware/include"
EXTRA_CFLAGS="$EXTRA_CFLAGS -I$ANDROID_SOURCE/frameworks/base/media/libstagefright"
EXTRA_CFLAGS="$EXTRA_CFLAGS -I$ANDROID_SOURCE/frameworks/base/include/media/stagefright/openmax"
EXTRA_CFLAGS="$EXTRA_CFLAGS -I$NDK/sources/cxx-stl/gnu-libstdc++/4.6/include -I$NDK/sources/cxx-stl/gnu-libstdc++/4.6/libs/$ABI/include"
EXTRA_CFLAGS="$EXTRA_CFLAGS -I$NDK/sources/cxx-stl/stlport/stlport"
EXTRA_CFLAGS="$EXTRA_CFLAGS -march=armv7-a -mfloat-abi=softfp -mfpu=neon -marm -mtune=cortex-a8"
EXTRA_CFLAGS="$EXTRA_CFLAGS -O3 -fpic -DANDROID -DHAVE_SYS_UIO_H=1 -D_STLP_USE_NEWALLOC"

EXTRA_LDFLAGS="-Wl,--fix-cortex-a8 -L$ANDROID_LIBS -Wl,-rpath-link,$ANDROID_LIBS -L$NDK/sources/cxx-stl/gnu-libstdc++/4.6/libs/$ABI -static-libstdc++"
EXTRA_CXXFLAGS="-Wno-multichar -fno-exceptions -fno-rtti"
FLAGS="$FLAGS --prefix=$DEST"

mkdir -p $DEST

echo $FLAGS --extra-cflags="$EXTRA_CFLAGS" --extra-ldflags="$EXTRA_LDFLAGS" --extra-cxxflags="$EXTRA_CXXFLAGS" > $DEST/info.txt
./configure $FLAGS --extra-cflags="$EXTRA_CFLAGS" --extra-ldflags="$EXTRA_LDFLAGS" --extra-cxxflags="$EXTRA_CXXFLAGS" | tee $DEST/configuration.txt
[ $PIPESTATUS == 0 ] || exit 1
make clean
#make -j4 || exit 1
#make -j4
make install || exit 1

    将编译好的 include 和 lib 目录复制到我的 android-ndk-r7/sources/ffmpeg-2.1.4/android/arm 目录。该目录下的Android.mk文件是。

    LOCAL_PATH:= $(call my-dir)

    包括 $(CLEAR_VARS) LOCAL_MODULE:= libavcodec LOCAL_SRC_FILES:= lib/libavcodec-55.so LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include 包括 $(PREBUILT_SHARED_LIBRARY)

    包括 $(CLEAR_VARS) LOCAL_MODULE:= libavformat LOCAL_SRC_FILES:= lib/libavformat-55.so LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include 包括 $(PREBUILT_SHARED_LIBRARY)

    包括 $(CLEAR_VARS) LOCAL_MODULE:= libswscale LOCAL_SRC_FILES:= lib/libswscale-2.so LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include 包括 $(PREBUILT_SHARED_LIBRARY)

    包括 $(CLEAR_VARS) LOCAL_MODULE:= libavutil LOCAL_SRC_FILES:= lib/libavutil-52.so LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include 包括 $(PREBUILT_SHARED_LIBRARY)

    包括 $(CLEAR_VARS) LOCAL_MODULE:= libavfilter LOCAL_SRC_FILES:= lib/libavfilter-3.so LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include 包括 $(PREBUILT_SHARED_LIBRARY)

    包括 $(CLEAR_VARS) LOCAL_MODULE:= libwsresample LOCAL_SRC_FILES:= lib/libswresample-0.so LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include 包括 $(PREBUILT_SHARED_LIBRARY)

    在我的android应用的jni目录下,Android.mk是。

    LOCAL_PATH:= $(call my-dir)
    include $(CLEAR_VARS)
    
    LOCAL_MODULE    := libripple
    #LOCAL_CFLAGS    := -Werror
    LOCAL_SRC_FILES := entrypoint.cpp scene.cpp
    LOCAL_LDLIBS    := -llog -lGLESv2 -lm
    
    include $(BUILD_SHARED_LIBRARY)
    
    include $(CLEAR_VARS)
    
    LOCAL_MODULE    := myfflib
    LOCAL_SRC_FILES := fflib.c
    LOCAL_LDLIBS := -L/home/mingzhang/ffmpeg_android/android-libs -llog -ljnigraphics -lz -landroid -ldl -lm -llog -lgcc -lc -lstagefright -lmedia -lutils -lbinder #-lstdc++
    LOCAL_SHARED_LIBRARIES := libavformat libavcodec libswscale libavutil libutils libstagefright libbinder libmedia libstdc++-6
    
    include $(BUILD_SHARED_LIBRARY)
    $(call import-module,ffmpeg-2.1.4/android/arm)
    

    Application.mk 是:

    APP_ABI=armeabi-v7a
    #APP_STL=gnustl_static
    APP_STL=stlport_static
    

我不知道你还需要什么材料,如果缺少什么,请告诉我,我会上传。 非常感谢各位!!!

【问题讨论】:

【参考方案1】:

FFmpeg 已在 https://github.com/FFmpeg/FFmpeg/commit/72673ad7eae2d4f685f3c0a895558502bfe07c8e(包含在 n3.0 中)删除了对 libstagefright 的支持。提交信息:

avcodec: Remove libstagefright

It serves absolutely no purpose other than to confuse potentional
Android developers about how to use hardware acceleration properly
on the the platform. The stagefright "API" is not public, and the
MediaCodec API is the proper way to do this.

Furthermore, stagefright support in avcodec needs a series of
magic incantations and version-specific stuff, such that
using it actually provides downsides compared just using the actual
Android frameworks properly, in that it is a lot more work and confusion
to get it even running. It also leads to a lot of misinformation, like
these sorts of comments (in [1]) that are absolutely incorrect.

[1] http://***.com/a/29362353/3115956

所以也许已经不可能了。

使用AMediaCodec 和OpenMAX 可能会有更好的机会。

【讨论】:

该提交本身基本上是在问题发布后发生的,但提出的问题听起来确实与发帖者遇到的问题非常相似 - 链接到私有平台内部一直是有风险的,难以维护命题很少适用于即时实验。

以上是关于FFmpeg 支持 libstagefright 硬件解码的主要内容,如果未能解决你的问题,请参考以下文章

Linux下NDK编译FFMPEG包含neon参数

编译cm11出错

ffmpeg:哪些文件格式支持标准输入?

FFmpegffmpeg 命令查询三 ( 查询 ffmpeg 命令分类支持的参数 )

FFmpegffmpeg 命令查询三 ( 查询 ffmpeg 命令分类支持的参数 )

FFmpeg:创建支持FFmpeg的AS项目