Thursday, 7 June 2012

Slow queues and big maths

After a couple of days poking at my android video player - mostly just to test jjmpeg really - and getting it to mostly work, I thought i'd have a look at some performance tuning. It even does network streaming now.

Fired up the profiler and had a poke ...

Found out it was spending 10% of it's time in the starSlash implementation I was using - I hadn't upgraded the multi-thread player to use the libavutil rescale function and it was still using the java BigInteger class. Easy fix.

And then I checked the queue stuff it's using for sending around asynchronous data. I changed from using the LinkedBlockingQueue to a lighter weight and simpler blocking queue I had tested with the simpler player code. Nearly another 10% cpu time there as well.

So with those small changes my test video went from about 30% cpu time (if i'm reading the cpu usage debug option properly) to well under 10% most of the time. It's only a fairly low-bitrate 656x400@25fps source.

The next biggest thing is the texture loading which can be a bit slow (actually depending on the video size, it's easily the single biggest overhead). I kinda mucked around with that a lot trying to debug `the crash', so that could probably do with a revisit. Right now i'm updating it on the GL thread - but synchronously with the video decoding thread, so any delay is costly (I wasn't sure if decode_video could reference an AVFrame at the next call). From memory doing it this was was quicker than using a shared gl context too. Actually whilst writing this i had a closer look and a bit of a poke - the texture loading is still really slow but i removed more overhead with a few tweaks.

The main problem with the player itself is that it still just vanishes sometimes with a SIGBUS. Android displays nothing about it apart from that the signal was '7', so i guess it's in some native thread. I thought I had gdb running a few weeks ago but i can't seem to get it to run now - although back then it didn't help much anyway. It also doesn't even try to cope well with not being able to keep up with decoding and ugly stuff happens.

Ahh well, if it was done I'd have nothing to do ...


Andrei Buneyeu said...

I had very similar issue - ffmpeg caused crash of my app by signal 7 (SIGBUS) after decoding several hundreds of frames.

It was very incomprehensible issue for me cause it could happen at any time of video encoding/decoding and I couldn't find any conditions that causes failures.
But I recompiled ffmpeg with `-malign-double` flag according to this useful article: And it helped! So my full "configure" line is (of course not all of these flags are useful for you):

> ./configure --target-os=linux --cross-prefix=arm-linux-androideabi-
> --disable-asm --arch=arm --cpu=cortex-a9 --sysroot=${SYSROOT} --enable-neon --disable-avdevice --enable-decoder=mjpeg --enable-demuxer=mjpeg --enable-parser=mjpeg --enable-demuxer=image2 --enable-muxer=mp4 --prefix=build/armeabi-v7a --extra-cflags='-DANDROID -I${NDK_ROOT}/sources/cxx-stl/system/include -mtune=cortex-a9 -mfpu=neon -mfloat-abi=softfp' --extra-ldflags='-Wl,--fix-cortex-a8 -malign-double -L../android-libs -Wl,-rpath-link,../android-libs' --extra-cxxflags='-Wno-multichar -malign-double -fno-exceptions -fno-rtti'

Hope it'll help you.

NotZed said...

Hi Andrei,

On the update over here I found a solution for my crash:

That intel article is talking about making x86 align the same as arm, not the other way around, I suspect your fix of using -malign-double is just a coincidence - the backtrace of my crash was with an indexed array access where the index was non-aligned and -malign-double shouldn't affect that.

If I used --disable-asm it also worked for me, as that was also required for HAVE_FAST_UNALIGNED to add the buggy code. But it made the code much slower so wasn't desirable.

Scrawler said...

Have you found anything that could cause the SIGBUS error or any workaround? I have a pure Java Android app which just disappears at random times with a SIGBUS error at random times on Tegra 3 machines (eg, Transformer Infinity) and I'm pulling my hair out. Thank you.

NotZed said...

I only know of the mis-aligned memory access for ARM instructions, although I don't know if that's the only hardware exception that will cause that particular signal. It's strange they force this on.

If you have root access you could try turning off the exception-on-misaligned access stuff in the kernel (sorry i can't recall where it is, something in /sys).

Android has a lot of stuff implemented in C++ and accessed by JNI - so it's pretty easy to hit bugs in the non-java code.

It's possible, but probably not likely to be davlik bugs.

Another possibility is a hardware fault.