1

Hi my task is to display a set of decoded frames in android. In my native code i have a character(char ) pointer which holds the address of the decoded frame. I want to display this frame on my device so i got a hint from: Displaying YUV Image in Android hence in my activity class i wrote the following function:

public void displayFrame(byte[] data, int fwidth,int fheight){

    ImageView frameImgView=(ImageView) findViewById(R.id.imageView2);

    ByteArrayOutputStream out=new ByteArrayOutputStream();
    YuvImage yuvimg=new YuvImage(data, ImageFormat.NV21, fwidth, fheight, null);
    yuvimg.compressToJpeg(new Rect(0, 0, fwidth, fheight), 100, out);
    byte[] imageBytes = out.toByteArray();
    Bitmap image = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.length);
    frameImgView.setImageBitmap(image);
    return;
}

Hence from my native code i need to call this function in java. From the link: http://www.altdevblogaday.com/2011/12/09/running-native-code-on-android-part-1/ i got to know how to call a java function from native c. However to call a java function we need an environment variable to do that. Im my java class i hav declared the main function as native and generated a header for that main function:

JNIEXPORT jint JNICALL Java_com_example_decoder_Decoder_mainFunction(JNIEnv *env, jclass jobj, jint argc, jstring argv1, jstring argv2);

however my mainFunction calls a function "fwriter(some pointer, some pointer)" which has a pointers as parameters. How do i get environment variable for the same. I know that in java class i need to declare "fwriter" function as native but what do i represent pointers as??

eg: my c function is:

void fwriter(int *ptr, char *ptr)
{
  ....
}

In my java class how do i declare this function as native?? Please help. Any other methods to diaplay YUV in java/Android will also be appreciated. Thank you.

Community
  • 1
  • 1
Zax
  • 2,870
  • 7
  • 52
  • 76

2 Answers2

1

Whilst JPEG encoding and decoding may be hardware accelerated on most phones, I would expect a simple RGB->YUV conversion for-loop you wrote yourself to be much faster (fast enough even in Java without using a native library) and simpler.

Here is the formula. If you are using OpenGLES to display, consider using a fragment shader to do the conversion on-the-fly.

Finally, here's the integer-only code you can use on the CPU:

Ytmp =      4768 * (Y - 16);
R = (Ytmp + 6537 * (V - 128)) >> 12;
G = (Ytmp - 3330 * (V - 128) - 1602 * (U - 128)) >> 12;
B = (Ytmp + 8266 * (U - 128)) >> 12;
Will
  • 73,905
  • 40
  • 169
  • 246
  • Thanks for the reply.... +1 for ur effort... But i think using openGLES will slower the process too. So i need to do things in c code itself. I mean the conversion from yuv to rgb. However if my yuv was yuv 4:4:4 i could have directly applied the formulae and converted to the corresponding rgb. But mine is YUV 4:2:0 so can u please suggest how do i convert this to rgb format. Will wait for the reply. Thanks in advance... – Zax Feb 07 '13 at 05:59
  • 1
    @Zax 1) using the GPU will be fastest of all, if your purpose is to display it; 2) I've written the code myself for commercial projects and you can directly apply the formula even in 4:2:0 its just you increment some pointers every other frame; 3) I'll paste in the classic integer-math yuv conversion – Will Feb 07 '13 at 06:32
  • Thanks for the fast reply. Yes my main purpose is to display it. In my native code i'm decoding a video and the decoded buffer is in yuv format. So my main work is to display this yuv frame. Each iteration a frame is decoded i hav to display it so that it loks like a video. So please help regarding the same. Also do you hav code for converting 420 to RGB?? if so please mail me. I also have tried some code but the output is a set of colourful lines :( – Zax Feb 07 '13 at 06:46
1

You can use RenderScript intrinsic to convert YUV image to bitmap.

You can prepare these objects once:

RenderScript rs = RenderScript.create(getContext());
ScriptIntrinsicYuvToRGB yuvToRgb = ScriptIntrinsicYuvToRGB.create(rs, Element.U8_4(rs));

Type.Builder yuvType = new Type.Builder(rs, Element.U8(rs)).setX(data.length);
Allocation in = Allocation.createTyped(rs, yuvType.create(), Allocation.USAGE_SCRIPT);

Type.Builder rgbaType = new Type.Builder(rs, Element.RGBA_8888(rs)).setX(fwidth).setY(fheight);
Allocation out = Allocation.createTyped(rs, rgbaType.create(), Allocation.USAGE_SCRIPT);

Bitmap image = Bitmap.createBitmap(fwidth, fheight, Bitmap.Config.ARGB_8888);

and for every frame you perform the conversion:

in.copyFrom(data);

yuvToRgb.setInput(in);
yuvToRgb.forEach(out);

out.copyTo(image);
Alex Cohn
  • 56,089
  • 9
  • 113
  • 307