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/
9 comments on “Effective Color Conversion (YUV->RGB) for Android in Assembly”
Leave a Reply Cancel reply
40% Discount on My Book — Android NDK Cookbook
Android NDK Cookbook ebook 40% discount with promotion code MREANC40 at Packt Publishing The promotion code is valid until 15th June.Categories
- Android Apps (18)
- Android Audio Editor (1)
- TS 2 (3)
- Video Converter Android (8)
- Video2Gif (1)
- Android Tutorial (26)
- Android Dev Tools (1)
- API illustrated (8)
- Multimedia API (3)
- ffmpeg on Android (4)
- NDK (6)
- UI (5)
- Animation (1)
- Code Snippet (2)
- Coding Beyond Technique (18)
- a word, a world (4)
- Bug Rectified (4)
- Programming Habit (1)
- Software as a Career (1)
- Software as User Experience (1)
- Compilers and Related (2)
- ELF (2)
- Computer Languages (31)
- C/C++ (13)
- Java (9)
- JavaScript (2)
- PHP (1)
- Python (8)
- Data Structure & Algorithms (29)
- Bits (1)
- Data Structure (5)
- Integers (10)
- BigInteger (1)
- Prime (4)
- Search (3)
- Sorting (5)
- Strings (5)
- Database (1)
- SQLite (1)
- Digital Signal Processing (33)
- Distributed Systems (17)
- Apache Cassandra (6)
- Apache Hadoop (8)
- Apache Avro (3)
- Apache Nutch (3)
- Apache Solr (1)
- Linux Study Notes (40)
- crontab (1)
- Linux Kernel Programming (8)
- Linux Programming (12)
- IPC (2)
- Linux Network Programming (5)
- Linux Signals (2)
- Linux Shell Scripting (1)
- ssh (3)
- Machinery (30)
- misc (1)
- My Ideas (1)
- My Project (3)
- Mobile Caching (1)
- Selective Decoding (2)
- My Publication (1)
- My Readings (1)
- Networking (15)
- Program for Performance (8)
- Uncategorized (1)
- Virtual Machine (2)
- Web Dev (8)
- web components (3)
- Android Apps (18)
Recent Comments
Archives
- May 2013 (1)
- April 2013 (1)
- March 2013 (4)
- December 2012 (2)
- November 2012 (6)
- October 2012 (6)
- September 2012 (3)
- August 2012 (13)
- July 2012 (15)
- June 2012 (3)
- May 2012 (8)
- April 2012 (4)
- March 2012 (13)
- February 2012 (19)
- January 2012 (9)
- December 2011 (11)
- November 2011 (12)
- October 2011 (4)
- September 2011 (12)
- August 2011 (16)
- July 2011 (15)
- June 2011 (6)
- May 2011 (10)
- April 2011 (13)
- March 2011 (20)
- February 2011 (4)
- November 2010 (2)
- May 2010 (1)
- April 2010 (1)
- February 2010 (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.
=)
Thank you! I’ll write more about ffmpeg and video apps from time to time.
Hey! is there a conversion code to get scaled RGB image.
There’s a code for scaling at YUV space at libyuv. You can search google code for it.
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!
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
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?
If you call ASM function from a C++ file, remember to declare ASM function inside extern “C” {};
Thanks for sharing this, i wish you have mentioned the performance gain when you use the assembly code.