Jordan
Jordan

Reputation: 4212

Invalid character linking FFmpeg 3.4.2 built with NDK r16

I'm in the process of updating my applications FFmpeg version from 2.8.6 to 3.4.2. I've managed to get FFmpeg built, but when I build my native library I'm getting a linker error:

  /usr/local/android-sdk/ndk-bundle/toolchains/x86-4.9/prebuilt/darwin-x86_64/lib/gcc/i686-linux-android/4.9.x/../../../../i686-linux-android/bin/ld: error: /shared/dev/libs/ffmpeg/3.4.2/lib/android-x86/libswresample.so:1:1: invalid character
  /usr/local/android-sdk/ndk-bundle/toolchains/x86-4.9/prebuilt/darwin-x86_64/lib/gcc/i686-linux-android/4.9.x/../../../../i686-linux-android/bin/ld: error: /shared/dev/libs/ffmpeg/3.4.2/lib/android-x86/libavcodec.so:1:1: invalid character
  /usr/local/android-sdk/ndk-bundle/toolchains/x86-4.9/prebuilt/darwin-x86_64/lib/gcc/i686-linux-android/4.9.x/../../../../i686-linux-android/bin/ld: error: /shared/dev/libs/ffmpeg/3.4.2/lib/android-x86/libavfilter.so:1:1: invalid character
  /usr/local/android-sdk/ndk-bundle/toolchains/x86-4.9/prebuilt/darwin-x86_64/lib/gcc/i686-linux-android/4.9.x/../../../../i686-linux-android/bin/ld: error: /shared/dev/libs/ffmpeg/3.4.2/lib/android-x86/libavutil.so:1:1: invalid character

The libraries are correct, but I don't understand where the :1:1: is coming from (assuming the trailing : is probably a delineator between the command and the error message). The path to the library is correct, but the filename definitely does not have a :1:1 in it.

I'm building on a Mac, so the first thing I do is:

sed -i ".orig" "s/SHFLAGS='-shared -Wl,-soname,\$(SLIBNAME)'/SHFLAGS='-shared -Wl,-install_name,\$(SLIBNAME)'/g" configure

so that ld uses the -install_name flag, rather than -soname. I used to have to do some other configure manipulation to strip the library naming out, but that doesn't seem to be necessary anymore (even if I do it I still get the same error).

FFmpeg was built using the following options:

./configure --prefix=output --enable-shared --disable-everything 
    --disable-iconv --disable-zlib --disable-bzlib 
    --enable-encoder=aac --enable-decoder=aac --enable-encoder=pcm_alaw 
    --enable-decoder=pcm_alaw --enable-encoder=pcm_mulaw
    --enable-decoder=pcm_mulaw --enable-encoder=adpcm_g726
    --enable-decoder=adpcm_g726 --enable-encoder=adpcm_ima_wav
    --enable-decoder=adpcm_ima_wav --enable-encoder=mjpeg
    --enable-decoder=mjpeg --enable-encoder=wmav1
    --enable-decoder=wmav1 --enable-encoder=wmav2
    --enable-decoder=wmav2 --enable-encoder=wmv1 --enable-decoder=wmv1 
    --enable-encoder=wmv2 --enable-decoder=wmv2 
    --enable-encoder=h264_vaapi --enable-encoder=hevc_vaapi 
    --enable-encoder=h264_nvenc --enable-encoder=hevc_nvenc 
    --enable-encoder=h264_omx --enable-encoder=h264_qsv 
    --enable-encoder=hevc_qsv --enable-decoder=aac_fixed 
    --enable-decoder=aac_latm --enable-decoder=adpcm_g726le 
    --enable-decoder=h263 --enable-decoder=h264 --enable-decoder=hevc 
    --enable-decoder=mjpegb --enable-decoder=mpeg4 
    --enable-decoder=h264_qsv --enable-decoder=h264_vdpau 
    --enable-decoder=hevc_qsv --enable-decoder=hevc_qsv 
    --enable-filter=scale --enable-filter=scale_vaapi 
    --enable-filter=scale_cuda --enable-filter=scale_npp
    --enable-filter=scale_qsv --enable-parser=aac --enable-parser=h263
    --enable-parser=h264 --enable-parser=hevc --enable-parser=mjpeg
    --enable-muxer=asf --enable-demuxer=asf --enable-muxer=avi
    --enable-demuxer=avi --enable-muxer=h263 --enable-demuxer=h263
    --enable-muxer=h264 --enable-demuxer=h264 --enable-muxer=hevc
    --enable-demuxer=hevc --enable-muxer=mjpeg --enable-demuxer=mjpeg
    --enable-muxer=pcm_alaw --enable-demuxer=pcm_alaw 
    --enable-muxer=pcm_mulaw --enable-demuxer=pcm_mulaw --enable-muxer=wav
    --enable-demuxer=wav --enable-demuxer=aac --enable-hwaccel=h264_d3d11va
    --enable-hwaccel=hevc_d3d11va --enable-hwaccel=h264_d3d11va2 
    --enable-hwaccel=hevc_d3d11va2 --enable-hwaccel=h264_dxva2 
    --enable-hwaccel=hevc_dxva2 --enable-hwaccel=h264_vaapi
    --enable-hwaccel=hevc_vaapi --enable-hwaccel=h264_vdpau 
    --enable-hwaccel=hevc_vdpau --enable-hwaccel=h264_nvenc
    --enable-hwaccel=hevc_nvenc --enable-hwaccel=h264_qsv
    --enable-hwaccel=hevc_qsv --enable-hwaccel=h264_vdpau
    --enable-hwaccel=hevc_vdpau --disable-programs --enable-cross-compile
    --cross-prefix=/shared/dev/toolchain/android/darwin-x86_64/ndk-r16/android-19/arm/bin/arm-linux-androideabi-
    --arch=arm --target-os=android --disable-asm --disable-stripping
    --disable-static --cc=clang --enable-pic

NDK toolchain is a standalone x86 toolchain built using NDK r16's make_standalone_toolchain.py tool.

The native project is built using CMake and using the clang android toolchain.

I've also got an arm version that gives the same linker error.

I'm not sure where exactly to start looking. Did this come from the build config options? I had to do quite a bit of tweaking to get it to build using NDK r16, but it was mostly stuff like adding --disable-stripping and changing --target-os from linux to android. Is it something with the NDK r16 toolchain?

Does anyone have any idea what the problem might be, or where I might start looking?

Upvotes: 0

Views: 541

Answers (1)

Jordan
Jordan

Reputation: 4212

Ok, I figured this out.

It turns out that passing --cc=clang will configure the makefiles to use the system clang, not the clang available in the provided --cross-prefix. This was resulting in a binary built for the Darwin-x86_64 architecture, and NOT the Android x86 or Android ARM architectures.

Fix was to pass the complete path to the clang compiler with the --cc configure option.

I've made my build script available on GitHub for anyone else having trouble building FFmpeg for Android using NDK r16b:

android-ffmpeg-buildscript

Upvotes: 2

Related Questions