Add YV12 color converter interface for VideoEditor.

The original assumption in VideoEditor is that the decoder output
and encoder input are in YV12 format. However on different
hardware platform the actual formats may be different. So now we
load a platform-specific YV12 color conversion module which
knows the actual format and can convert to/from YV12, which is
the format used in VideoEditor internally for processing.

Bug: 5061733
Change-Id: I852f85efd30c05cf6c42810059ee4d2ef37ee3da
diff --git a/libvideoeditor/lvpp/PreviewPlayerBase.cpp b/libvideoeditor/lvpp/PreviewPlayerBase.cpp
index 62b8a72..8e27a27 100644
--- a/libvideoeditor/lvpp/PreviewPlayerBase.cpp
+++ b/libvideoeditor/lvpp/PreviewPlayerBase.cpp
@@ -204,6 +204,13 @@
 
     mAudioStatusEventPending = false;
 
+    mYV12ColorConverter = new YV12ColorConverter();
+    if (!mYV12ColorConverter->isLoaded() ||
+        mYV12ColorConverter->getDecoderOutputFormat() == OMX_COLOR_FormatYUV420Planar) {
+        delete mYV12ColorConverter;
+        mYV12ColorConverter = NULL;
+    }
+
     reset();
 }
 
@@ -212,6 +219,8 @@
         mQueue.stop();
     }
 
+    delete mYV12ColorConverter;
+
     reset();
 
     mClient.disconnect();
@@ -849,23 +858,33 @@
 void PreviewPlayerBase::notifyVideoSize_l() {
     sp<MetaData> meta = mVideoSource->getFormat();
 
+    int32_t vWidth, vHeight;
     int32_t cropLeft, cropTop, cropRight, cropBottom;
+
+    CHECK(meta->findInt32(kKeyWidth, &vWidth));
+    CHECK(meta->findInt32(kKeyHeight, &vHeight));
+
+    mGivenWidth = vWidth;
+    mGivenHeight = vHeight;
+
     if (!meta->findRect(
                 kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom)) {
-        int32_t width, height;
-        CHECK(meta->findInt32(kKeyWidth, &width));
-        CHECK(meta->findInt32(kKeyHeight, &height));
 
         cropLeft = cropTop = 0;
-        cropRight = width - 1;
-        cropBottom = height - 1;
+        cropRight = vWidth - 1;
+        cropBottom = vHeight - 1;
 
-        LOGV("got dimensions only %d x %d", width, height);
+        LOGD("got dimensions only %d x %d", vWidth, vHeight);
     } else {
-        LOGV("got crop rect %d, %d, %d, %d",
+        LOGD("got crop rect %d, %d, %d, %d",
              cropLeft, cropTop, cropRight, cropBottom);
     }
 
+    mCropRect.left = cropLeft;
+    mCropRect.right = cropRight;
+    mCropRect.top = cropTop;
+    mCropRect.bottom = cropBottom;
+
     int32_t displayWidth;
     if (meta->findInt32(kKeyDisplayWidth, &displayWidth)) {
         LOGV("Display width changed (%d=>%d)", mDisplayWidth, displayWidth);
@@ -910,11 +929,8 @@
 
     int32_t format;
     const char *component;
-    int32_t decodedWidth, decodedHeight;
     CHECK(meta->findInt32(kKeyColorFormat, &format));
     CHECK(meta->findCString(kKeyDecoderComponent, &component));
-    CHECK(meta->findInt32(kKeyWidth, &decodedWidth));
-    CHECK(meta->findInt32(kKeyHeight, &decodedHeight));
 
     int32_t rotationDegrees;
     if (!mVideoTrack->getFormat()->findInt32(
@@ -1395,7 +1411,7 @@
                         : MediaSource::ReadOptions::SEEK_CLOSEST_SYNC);
         }
         for (;;) {
-            status_t err = mVideoSource->read(&mVideoBuffer, &options);
+            status_t err = readYV12Buffer(mVideoSource, &mVideoBuffer, &options);
             options.clearSeekTo();
 
             if (err != OK) {
@@ -1912,4 +1928,59 @@
 status_t PreviewPlayerBase::getParameter(int key, Parcel *reply) {
     return OK;
 }
+
+status_t PreviewPlayerBase::readYV12Buffer(sp<MediaSource> source, MediaBuffer **buffer,
+    const MediaSource::ReadOptions *options) {
+    status_t result = source->read(buffer, options);
+    if (mYV12ColorConverter == NULL || *buffer == NULL) {
+        return result;
+    }
+
+    int width = mCropRect.right - mCropRect.left + 1;
+    int height = mCropRect.bottom - mCropRect.top + 1;
+
+    MediaBuffer *origBuffer = *buffer;
+    MediaBuffer *newBuffer = new MediaBuffer(width * height * 3 / 2);
+
+    LOGD("convertDecoderOutputToYV12: mGivenWidth = %d, mGivenHeight = %d",
+        mGivenWidth, mGivenHeight);
+    LOGD("width = %d, height = %d", width, height);
+
+    if (mYV12ColorConverter->convertDecoderOutputToYV12(
+        (uint8_t *)origBuffer->data(), // ?? + origBuffer->range_offset(), // decoderBits
+        mGivenWidth,  // decoderWidth
+        mGivenHeight,  // decoderHeight
+        mCropRect, // decoderRect
+        (uint8_t *)newBuffer->data() + newBuffer->range_offset() /* dstBits */) < 0) {
+        LOGE("convertDecoderOutputToYV12 failed");
+    }
+
+    // Copy the timestamp
+    int64_t timeUs;
+    CHECK(origBuffer->meta_data()->findInt64(kKeyTime, &timeUs));
+    newBuffer->meta_data()->setInt64(kKeyTime, timeUs);
+
+    origBuffer->release();
+    *buffer = newBuffer;
+
+    return result;
+}
+
+void PreviewPlayerBase::getVideoBufferSize(sp<MetaData> meta, int* width, int* height) {
+    if (mYV12ColorConverter) {
+        int32_t cropLeft, cropTop, cropRight, cropBottom;
+        if (meta->findRect(
+                kKeyCropRect, &cropLeft, &cropTop, &cropRight, &cropBottom)) {
+            *width = cropRight - cropLeft + 1;
+            *height = cropBottom - cropTop + 1;
+        } else {
+            CHECK(meta->findInt32(kKeyWidth, width));
+            CHECK(meta->findInt32(kKeyHeight, height));
+        }
+    } else {
+        CHECK(meta->findInt32(kKeyWidth, width));
+        CHECK(meta->findInt32(kKeyHeight, height));
+    }
+}
+
 }  // namespace android