How to convert YUV420SP to RGB and display it?

981 Views Asked by At

Im trying to render a video frame using android NDK.

Im using this sample of google Native-Codec NDK sample code and modified it so I can manually display each video frame (non-tunneled).

so I added this code to get the output buffer which is in YUV.

  ANativeWindow_setBuffersGeometry(mWindow, bufferWidth, bufferHeight,
                                     WINDOW_FORMAT_RGBA_8888
  uint8_t *decodedBuff = AMediaCodec_getOutputBuffer(d->codec, status, &bufSize);
  auto format = AMediaCodec_getOutputFormat(d->codec);
  LOGV("VOUT: format %s", AMediaFormat_toString(format));
  AMediaFormat *myFormat = format;
  int32_t w,h;
  AMediaFormat_getInt32(myFormat, AMEDIAFORMAT_KEY_HEIGHT, &h);
  AMediaFormat_getInt32(myFormat, AMEDIAFORMAT_KEY_WIDTH, &w);
  err = ANativeWindow_lock(mWindow, &buffer, nullptr);

and these codes to convert the YUV to RGB and display it using native window.

  if (err == 0) {
            LOGV("ANativeWindow_lock()");
            int width =w;
            int height=h;
            int const frameSize = width * height;
            int *line = reinterpret_cast<int *>(buffer.bits);
            for (int y= 0; y < height; y++) {
                for (int x = 0; x < width; x++) {
                /*accessing YUV420SP elements*/
                int indexY = y * width + x;
                int indexU = (size + (y / 2) * (width ) + (x / 2) *2);
                int indexV = (int) (size + (y / 2) * (width) + (x / 2) * 2 + 1);

                /*todo; this conversion to int and then later back to int really isn't required.
                There's room for better work here.*/
                int Y = 0xFF & decodedBuff[indexY];
                int U = 0xFF & decodedBuff[indexU];
                int V = 0xFF & decodedBuff[indexV];

                /*constants picked up from http://www.fourcc.org/fccyvrgb.php*/
                    int R = (int) (Y + 1.402f * (V - 128));
                    int G = (int) (Y - 0.344f * (U - 128) - 0.714f * (V - 128));
                    int B = (int) (Y + 1.772f * (U - 128));

                /*clamping values*/
                R = R < 0 ? 0 : R;
                G = G < 0 ? 0 : G;
                B = B < 0 ? 0 : B;
                R = R > 255 ? 255 : R;
                G = G > 255 ? 255 : G;
                B = B > 255 ? 255 : B;

                line[buffer.stride * y + x] = 0xff000000 + (B << 16) + (G << 8) + R;
            }
        }
ANativeWindow_unlockAndPost(mWindow);

Finally I was able to display a video on my device. Now my problem is the video does not scale to fit the surface view :(

enter image description here

Your thoughts are very much appreciated.

0

There are 0 best solutions below