1

EDIT : I came across this libyuv that does the NV21 to I420 conversion, but i don't really understand how to call it.

// Convert NV21 to I420.  Same as NV12 but u and v pointers swapped.
LIBYUV_API
int NV21ToI420(const uint8* src_y, int src_stride_y,
           const uint8* src_vu, int src_stride_vu,
           uint8* dst_y, int dst_stride_y,
           uint8* dst_u, int dst_stride_u,
           uint8* dst_v, int dst_stride_v,
           int width, int height) 

I am passing the NV21 byte[] obtained from camera callback to the jni layer and converting it to unsigned char* as below

int yuvBufLen = env->GetArrayLength(yuvNV21);
unsigned char* yuvNV21Buf = new unsigned char[yuvBufLen];
env->GetByteArrayRegion(yuvNV21, 0, yuvBufLen,reinterpret_cast<jbyte*>(yuvNV21Buf));

Now it is not clear to me how do i get the different parameters required to call the libyuv function NV21ToI420. What does each of the following parameters represent and how to obtain them from the unsigned char* yuvNV21Buf I have ??

const uint8* src_y,
int src_stride_y,
const uint8* src_vu,
int src_stride_vu,
uint8* dst_y,
int dst_stride_y,
uint8* dst_u,
int dst_stride_u,
uint8* dst_v,
int dst_stride_v

I have checked this obtain yuv420 in ios which explains how to get all the required parameters to call libyuv::NV12ToI420.

Can someone please explain me how to achieve this??

I am capturing frame byte[] from camera through the preview callback below

@Override
        public void onPreviewFrame(byte[] frameData, Camera camera) {

The frameData am getting is in NV21 format and I am trying to convert NV21 to I420.

Community
  • 1
  • 1
zenith
  • 55
  • 3
  • 12
  • Why do you need to convert to I420? What are you trying to do? – fadden Nov 03 '14 at 16:19
  • working on video conferencing app, and server needs I420 format. When I transmit NV21 from Android it looks distorted on server. – zenith Nov 04 '14 at 05:27
  • Like this? http://stackoverflow.com/questions/13703596/mediacodec-and-camera-colorspaces-dont-match – fadden Nov 04 '14 at 06:04
  • Exactly same..my image looks distorted like the one shown in the above link (2nd image)... it happens because my server treats it as I420, so I have to convert it to I420 to make it work..any ideas how to convert NV21 to I420?? – zenith Nov 04 '14 at 13:24
  • If I've got my formats straight, NV21 is semi-planar, while I420 is planar. So it's not a simple matter of swapping U and V. You have to convert from "all U values, then all V values" to "alternating U and V values". – fadden Nov 04 '14 at 14:55
  • so isn't there any means by which i can achieve the desired I420?? – zenith Nov 06 '14 at 07:10
  • You have the frame data. Modify your code to shuffle the color bytes around. It's more involved than a simple U/V swap, but you're just changing it from YYYYYYYYUUUUVVVV to YYYYYYYYVUVUVUVU. – fadden Nov 06 '14 at 17:19

2 Answers2

0

I could not get to work the method I posted in the question, it kept crashing.

But thanks to Peter I found this NV21ToI420 conversion and it worked perfect for me.

Simply it needs the NV21 and the I420 pointer.

unsigned char* yuvPtr; //NV21 data
unsigned char* I420 = new unsigned char[sourceWidth*sourceHeight*1.5]; //destination I420 pointer where the converted yuv will be stored 
NV21toI420(yuvPtr, I420, sourceWidth, sourceHeight);

Thats all....

zenith
  • 55
  • 3
  • 12
0

adding to this (since the link in the answer seems to be expired). One can use this code to convert YUV format into NV21.

So I modified the code like this to convert it to I420. Code here. Now it's working fine for mediaEncoder generated video.

Monster Brain
  • 1,950
  • 18
  • 28