xiph / opus

Modern audio compression for the internet.
https://opus-codec.org/
Other
2.25k stars 601 forks source link

Question - how to build for Android arm64-v8 #281

Open kvasilye opened 1 year ago

kvasilye commented 1 year ago

Hello,

I'm trying to compile Opus for Android arm64 (and ultimately other arch's) using the CMakeLists.txt file available in the repository.

My cmake commands are like this:

https://gist.github.com/kvasilye/9004332a5f3f90f2a6e868090d004d7b

This produces an error:

ld: error: undefined symbol: celt_pitch_xcorr_neon
>>> referenced by pitch.c:347 (/home/[ANT.AMAZON.COM/kvasilye/opus/celt/pitch.c:347](http://ant.amazon.com/kvasilye/opus/celt/pitch.c:347))
>>>               CMakeFiles/opus.dir/celt/pitch.c.o:(pitch_search)
>>> referenced by celt_lpc.c:314 (/home/[ANT.AMAZON.COM/kvasilye/opus/celt/celt_lpc.c:314](http://ant.amazon.com/kvasilye/opus/celt/celt_lpc.c:314))
>>>               CMakeFiles/opus.dir/celt/celt_lpc.c.o:(_celt_autocorr)
>>> referenced by burg_modified_FIX.c:98 (/home/[ANT.AMAZON.COM/kvasilye/opus/silk/fixed/burg_modified_FIX.c:98](http://ant.amazon.com/kvasilye/opus/silk/fixed/burg_modified_FIX.c:98))
>>>               CMakeFiles/opus.dir/silk/fixed/burg_modified_FIX.c.o:(silk_burg_modified_c)
>>> referenced 2 more times

Next, I tried to write my own CMakeLists.txt and got stuck too - the undefined symbol above is defined in celt_pitch_xcorr_arm.s which as I understand uses ARM assembler syntax.

I converted the file to GNU syntax using the provided Perl script.

Trying to compile the output with aarch64-linux-gnu-as gives a whole bunch of errors like:

third_party/cmake-build-opus-android-arm64-v8a-Debug/celt_pitch_xcorr_arm_gnu.S: Assembler messages:
third_party/cmake-build-opus-android-arm64-v8a-Debug/celt_pitch_xcorr_arm_gnu.S:1: Error: unknown pseudo-op: `.syntax'
third_party/cmake-build-opus-android-arm64-v8a-Debug/celt_pitch_xcorr_arm_gnu.S:2: Error: junk at end of line, first unrecognized character is `@'
third_party/cmake-build-opus-android-arm64-v8a-Debug/celt_pitch_xcorr_arm_gnu.S:3: Error: junk at end of line, first unrecognized character is `@'
third_party/cmake-build-opus-android-arm64-v8a-Debug/celt_pitch_xcorr_arm_gnu.S:4: Error: junk at end of line, first unrecognized character is `@'
third_party/cmake-build-opus-android-arm64-v8a-Debug/celt_pitch_xcorr_arm_gnu.S:5: Error: junk at end of line, first unrecognized character is `@'

So it looks unhappy with the syntax.

Questions:

1 - What is the right way to compile Opus for Android on arm64-v8a?

2 - If I wanted to compile the asm file, how can I do that?

3 - Is this asm file for both armeabi-v7a and arm64-v8a or just for armeabi-v7a? The symbol is required for arm64-v8a, but there is a directive ".arch armv7-a" at the top of the file so I'm confused.

I really don't know anything about arm assembly to figure these out on my own, any help would be appreciated!

PS - I am able to compile the generated GNU .S file using arm-linux-gnueabi-as on Linux or armv7a-linux-androideabi21-clang which is included in the Android SDK. But that again is for arm7 - and the symbol is missing for arm64-v8a.

xnorpx commented 1 year ago

Hi, can you try to reproduce what I have in my CI build?

https://github.com/xnorpx/opus/blob/master/.github/workflows/build.yml

https://github.com/xnorpx/opus/actions/runs/5050652420

There might be bugs regarding the neon detection, so please feel free to file specific bugs if you find them for specific configs that I can reproduce.

kvasilye commented 1 year ago

Thanks for the link. I don't see an arm64 build variant - much less one for Android - in your build action script.

I ended up configuring for arm64 like this: 1) enable fixed point 2) did not enable any neon defines - and it built and linked.

I wonder if that's a good configuration?

For x86 I used floating point with SSE and it compiled and linked just fine.

xnorpx commented 1 year ago
xnorpx commented 1 year ago

Regarding performance I would start with everything plain float and maybe even no optimization, then you can start adding optimization and measure on your target device and see what gives the best performance.

If some specific configuration doesn't build, then file a issue per config that doesn't build.

kvasilye commented 1 year ago

How did I miss it! Thanks!

Looks like it doesn't pass any special parameters for Neon - so your build for arm64 (or any other platform) doesn't use Neon, correct?

xnorpx commented 1 year ago

if(CMAKE_SYSTEM_PROCESSOR MATCHES "aarch64") set(OPUS_PRESUME_NEON ON) elseif(CMAKE_SYSTEM_NAME MATCHES "iOS") set(OPUS_PRESUME_NEON ON) endif()

But as stated, possible with bugs there so feel free to verify.

kvasilye commented 1 year ago

Think I figured it out. Your build scripts don't use fixed point when building for aarch64.

If I remove OPUS_FIXED_POINT from my CMake config then aarch64 builds fine.

Question is - does that use neon then at all? Or is neon only for fixed point?

kvasilye commented 1 year ago

To summarize for anyone else who might run into this:

aarch64 with Neon and fixed point is broken - the unresolved symbol issue - where the celt_pitch_xcorr_neon function is only defined in the arm7 specific .S file.

aarch64 with Neon and floating point does work - the defines should be like this:

"OPUS_ARM_MAY_HAVE_NEON=1"
"OPUS_ARM_MAY_HAVE_NEON_INTR=1"
"OPUS_ARM_PRESUME_NEON=1"
"OPUS_ARM_PRESUME_NEON_INTR=1"
SineVector241 commented 7 months ago

For those wanting an easy instruction including arm64-v8 and more. I've pretty much figured out how to do it here https://github.com/SineVector241/OpusSharp/tree/master/OpusLibs/Android Read the README.md and either download the exact same folder setup or download the makefile and make sure to include the opus library in the same directory as the makefile.