Effective Color Conversion (YUV->RGB) for Android in Assembly

Please jump to “0. Android NDK” if you want pure technical stuff; please jump to end of the post to download the sample code if you want to figure out everything yourself.

Recently I am doing a project that decodes a video using ffmpeg and render it on Android using Bitmap. At first, I tried to using sws_scale to do color conversion and scaling, it’s very slow (100~300ms).

Then I found from reference 1 that there’s ARM assembly code available to do YUV to RGB/RGBA color conversion. The code downloaded from the website doesn’t compile for Android, so I changed the code a little bit and made it work on Android.

The code also contains C equivalent  procedures to do the conversion. It also runs faster than sws_scale. In case the assembly code doesn’t work for your processor, you can use the C equivalent methods.

0. Android NDK

In order to do yuv to rgb color conversion in assembly code, you’ll need to have Android NDK set up. I’m testing using NDK r5b, but other NDK versions should also work.
Note that you’ll need basic NDK knowledge in order to understand the example given. This includes how to pass bitmap, string, and primitive data from Java and C, how to manipulate bitmap object in C and basic JNI stuff.

1. How the Sample Program Work
The sample program consists of both Java and native C code. The java code will copy the test.yuv file from assets folder to /sdcard/test.yuv (main.java), create a bitmap object (RenderView.java), call the native code (also RenderView.java, native method defined in jni/test.c file) to do conversion and render the converted bitmap on screen.

The native code (jni/test.c) will manipulate the bitmap buffer, open the test.yuv file to get the YUV bytes and call the assembly procedure to do yuv2rgb8888 (defined in jni/yuv2rgb/yuv4202rgb8888.s file) conversion.

The assembly procedure is modified based on the code from reference 1. I don’t understand it fully yet.  🙁

2. How to Compile
I’ve created the Android.mk file. So you just go the jni folder, and type “ndk-build” will build the native library for you.

3. Who might Need this Code
The code basically contains the color conversion and also rendering on Android. If you’re developing a video player using ffmpeg, or a video game, you might want to handle color conversion and rendering yourself, then you might find this code useful.

4. Final Note
The sample code only test on yuv420 to rgb8888, but the code actually contains a lot other assembly code. You’ll need to modify the assembly procedure yourself and add them to Android.mk. But it should be straightforward and you can refer the yuv4202rgb8888.s file for reference.

When you call the assembly procedure, you might need to switch the order of u and v if you find the color is wired after conversion.

Note that it is the users’ responsibility to ensure that they are patent free before using the code.

5. Download
You can download the entire source code package here or from github here.

References:
1. YUV2RGB: http://wss.co.uk/pinknoise/yuv2rgb/

0 thoughts on “Effective Color Conversion (YUV->RGB) for Android in Assembly”

  1. Roman i’m very impressed by your work!!
    Thanks alot for the great tutorials on ffmpeg.
    It would be great if u add more tutorials on ffmpeg converting video to bitmaps and back.
    =)

  2. Hi! Thanks for the code, I’m trying to implement it but I get only a dotted grayscale image as output, with some random red and blue patches… I want to convert the camera preview frame, maybe they are in a wrong format? I’m forcing them to NV21… Do you have some suggestions? I can share my modified code if you need to see it…
    Thanks a lot!

  3. Hi,

    Your code is working fast for android.
    Is it possible to convert from YUV to RGB with a different destination width and height.

    thanks,
    Aatral

  4. Tremendous work. Do you have an estimate of the speedup this gives over the trivial ‘C’ Code?

    I need the reciprocal functions – I am trying to encode video from Android Bitmaps and thus need to convert RGB888->YUV420. Any leads?

  5. Hi Roman,

    Thank you so much for the post. I was trying to deploy this on my device using Android Studio but I wasn’t able to compile it. Could you please help me with this?

Leave a Reply

Your email address will not be published. Required fields are marked *