How to build ffmpeg with hardware accelerated codecs for Android x86
in order to build a complete ffmpeg with hardware acceleration for intel platform (xxx lake + atom), we need a complete android x86 build, the cross-compilation doesn't work well with ndk or anything else.
steps are below.
install ubuntu 16.04 lts x86-64, install the all ubuntu dependencies as here.
sudo apt-get install git-core gnupg flex bison gperf build-essential zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 lib32ncurses5-dev x11proto-core-dev libx11-dev lib32z-dev libgl1-mesa-dev libxml2-utils xsltproc unzip
install python mako by pip, which the build system uses to generate the i18n files during compilation.
sudo apt-get install python-pip pip install mako
get the source code of android x86, here make sure you have large enough space.
mkdir android-x86 cd android-x86 repo init -u git://git.osdn.net/gitroot/android-x86/manifest -b $branch repo sync --no-tags --no-clone-bundle
the variable $branch is the name of specific android branch.
- oreo-x86
- android 8.0
- nougat-x86
- android 7.1
- marshmallow-x86
- android 6.0
- lollipop-x86
- android 5.1
- kitkat-x86
- android 4.4
- jb-x86
- android 4.3
- ics-x86
- android 4.0
- honeycomb-x86
- android 3.2
- gingerbread-x86
- android 2.3
- froyo-x86
- android 2.2
- eclair-x86
- android 2.1
- donut-x86
- android 1.6
- cupcake-x86 (aka android-x86-v0.9)
- android 1.5
once the code base was checked out, use lunch command to build the system for once.
enter the folder of checked out folder.
source the build environement setup.
. build/envsetup.sh
select the build target and type of build
lunch $target_product-$target_build_variant
the $target_product could be one of android_x86 android_x86_64 .
the $target_build_variant could be one of eng user userdebug .
so if we want to make a debug version of android x86-64, we type
lunch android_x86_64-userdebug
now type
m -jx iso_img
to make the system image.
when there is the error about org.android.analytics, open the file
./build/core/tasks/check_boot_jars/package_whitelist.txt
and append a line
org\.android_x86\.analytics
to it.
if everything goes okay, the android system image would be build.
now we start to build a better ffmpeg with hardware acceleration api, vaapi, cuvid etc. the system already offer the possibilty but didn't supply the correct configuration as the default.
copy the file
external/ffmpeg/libavformat/android.mk
to
external/ffmpeg/libavfilter
if you want to build the command line of ffmpeg, create a new android.mk file under external/tools folder, fill it with content
local_path:= $(call my-dir) include $(clear_vars) local_cflags += \ -dandroid \ -dtarget_config=\"config-x86_64-x86_64.h\" \ local_src_files := \ ../ffmpeg.c \ ../ffmpeg_filter.c \ ../ffmpeg_opt.c \ ../ffmpeg_cuvid.c \ ../ffmpeg_vaapi.c \ ../cmdutils.c \ local_c_includes += \ $(local_path)/android/include \ $(local_path)/.. \ local_shared_libraries := libavutil libavcodec libswscale libswresample libswscale libavformat libavfilter local_module_tags := optional local_module := ffmpeg include $(build_executable)
then that's it, you would have the ffmpeg command line under /system/bin/ffmpeg !
do not touch the script gen-android-configs and configure with ffmpeg.
now let's add more dependency to the system, such as libva-utils for the intel platform to detect the video codec capability of the system.
under the folder external, clone the repository at branch 1.8.3
git clone -b 1.8.3 https://github.com/intel/libva-utils.git
enter the libva-utils folder, change a bit the source code. the system's libva under driver is 1.1.0, it's not very compatible with the libva-utils, which is a new program.
diff --git a/vainfo/vainfo.c b/vainfo/vainfo.c index 4405073..5d9f055 100644 --- a/vainfo/vainfo.c +++ b/vainfo/vainfo.c @@ -97,7 +97,8 @@ int main(int argc, const char* argv[]) const char *name = strrchr(argv[0], '/'); vaprofile profile, *profile_list = null; int num_profiles, max_num_profiles, i; - vaentrypoint entrypoint, entrypoints[10]; + vaentrypoint entrypoints[10]; + int entrypoint_index; int num_entrypoint; int ret_val = 0; @@ -118,8 +119,8 @@ int main(int argc, const char* argv[]) va_status = vainitialize(va_dpy, &major_version, &minor_version); check_vastatus(va_status, "vainitialize", 3); - printf("%s: va-api version: %d.%d (libva %s)\n", - name, major_version, minor_version, libva_version_s); + printf("%s: va-api version: %d.%d\n", + name, major_version, minor_version); driver = vaqueryvendorstring(va_dpy); printf("%s: driver version: %s\n", name, driver ? driver : "<unknown>"); @@ -149,8 +150,8 @@ int main(int argc, const char* argv[]) check_vastatus(va_status, "vaqueryconfigentrypoints", 4); profile_str = profile_string(profile); - for (entrypoint = 0; entrypoint < num_entrypoint; entrypoint++) - printf(" %-32s: %s\n", profile_str, entrypoint_string(entrypoints[entrypoint])); + for (entrypoint_index = 0; entrypoint_index < num_entrypoint; entrypoint_index++) + printf(" %-32s: %s\n", profile_str, entrypoint_string(entrypoints[entrypoint_index]));
just make the vainfo.c is able to be compiled with system libva.
back to the folder android-x86, type
mmm external/libva-utils
to just build the specific module. that's it, now the /system/bin/vainfo would be there !
references
- http://www.android-x86.org/getsourcecode
- https://github.com/cyanogenmod/android_external_ffmpeg
- https://github.com/intel/libva
- https://github.com/intel/libva-utils