Bug 1243538: P6. Adjust gonk decoder to allow different decoding size from metadata. r?alfredo draft
authorJean-Yves Avenard <jyavenard@mozilla.com>
Fri, 15 Apr 2016 17:08:17 +1000
changeset 352922 30a877c912fe60853f5b84f40d132d2f5c0fb718
parent 352921 57f4a05a6d799d3e2111db14246ab212bbf7392c
child 352923 571faee00b1add3351cf8f863edf9a7d4f4faf0e
push id15841
push userbmo:jyavenard@mozilla.com
push dateTue, 19 Apr 2016 00:09:30 +0000
reviewersalfredo
bugs1243538, 1154162
milestone48.0a1
Bug 1243538: P6. Adjust gonk decoder to allow different decoding size from metadata. r?alfredo Additionally handle bug 1154162, and fix aspect ratio. The display size were used for the picture size which would be wrong if any aspect ratio was set. MozReview-Commit-ID: LCbvfdvAsN3
dom/media/platforms/gonk/GonkVideoDecoderManager.cpp
dom/media/platforms/gonk/GonkVideoDecoderManager.h
--- a/dom/media/platforms/gonk/GonkVideoDecoderManager.cpp
+++ b/dom/media/platforms/gonk/GonkVideoDecoderManager.cpp
@@ -91,34 +91,23 @@ public:
 
 private:
   uint32_t mGrallocFormat;
 };
 
 GonkVideoDecoderManager::GonkVideoDecoderManager(
   mozilla::layers::ImageContainer* aImageContainer,
   const VideoInfo& aConfig)
-  : mImageContainer(aImageContainer)
+  : mConfig(aConfig)
+  , mImageContainer(aImageContainer)
   , mColorConverterBufferSize(0)
   , mPendingReleaseItemsLock("GonkVideoDecoderManager::mPendingReleaseItemsLock")
   , mNeedsCopyBuffer(false)
 {
   MOZ_COUNT_CTOR(GonkVideoDecoderManager);
-  mMimeType = aConfig.mMimeType;
-  mVideoWidth  = aConfig.mDisplay.width;
-  mVideoHeight = aConfig.mDisplay.height;
-  mDisplayWidth = aConfig.mDisplay.width;
-  mDisplayHeight = aConfig.mDisplay.height;
-  mInfo.mVideo = aConfig;
-
-  mCodecSpecificData = aConfig.mCodecSpecificConfig;
-  nsIntRect pictureRect(0, 0, mVideoWidth, mVideoHeight);
-  nsIntSize frameSize(mVideoWidth, mVideoHeight);
-  mPicture = pictureRect;
-  mInitialFrame = frameSize;
 }
 
 GonkVideoDecoderManager::~GonkVideoDecoderManager()
 {
   MOZ_COUNT_DTOR(GonkVideoDecoderManager);
 }
 
 nsresult
@@ -128,35 +117,31 @@ GonkVideoDecoderManager::Shutdown()
   return GonkDecoderManager::Shutdown();
 }
 
 RefPtr<MediaDataDecoder::InitPromise>
 GonkVideoDecoderManager::Init()
 {
   mNeedsCopyBuffer = false;
 
-  nsIntSize displaySize(mDisplayWidth, mDisplayHeight);
-  nsIntRect pictureRect(0, 0, mVideoWidth, mVideoHeight);
-
   uint32_t maxWidth, maxHeight;
   char propValue[PROPERTY_VALUE_MAX];
   property_get("ro.moz.omx.hw.max_width", propValue, "-1");
   maxWidth = -1 == atoi(propValue) ? MAX_VIDEO_WIDTH : atoi(propValue);
   property_get("ro.moz.omx.hw.max_height", propValue, "-1");
   maxHeight = -1 == atoi(propValue) ? MAX_VIDEO_HEIGHT : atoi(propValue) ;
 
-  if (mVideoWidth * mVideoHeight > maxWidth * maxHeight) {
+  if (mConfig.mImage.width * mConfig.mImage.height > maxWidth * maxHeight) {
     GVDM_LOG("Video resolution exceeds hw codec capability");
     return InitPromise::CreateAndReject(DecoderFailureReason::INIT_ERROR, __func__);
   }
 
   // Validate the container-reported frame and pictureRect sizes. This ensures
   // that our video frame creation code doesn't overflow.
-  nsIntSize frameSize(mVideoWidth, mVideoHeight);
-  if (!IsValidVideoRegion(frameSize, pictureRect, displaySize)) {
+  if (!IsValidVideoRegion(mConfig.mImage, mConfig.ImageRect(), mConfig.mDisplay)) {
     GVDM_LOG("It is not a valid region");
     return InitPromise::CreateAndReject(DecoderFailureReason::INIT_ERROR, __func__);
   }
 
   mReaderTaskQueue = AbstractThread::GetCurrent()->AsTaskQueue();
   MOZ_ASSERT(mReaderTaskQueue);
 
   if (mDecodeLooper.get() != nullptr) {
@@ -164,17 +149,19 @@ GonkVideoDecoderManager::Init()
   }
 
   if (!InitLoopers(MediaData::VIDEO_DATA)) {
     return InitPromise::CreateAndReject(DecoderFailureReason::INIT_ERROR, __func__);
   }
 
   RefPtr<InitPromise> p = mInitPromise.Ensure(__func__);
   android::sp<GonkVideoDecoderManager> self = this;
-  mDecoder = MediaCodecProxy::CreateByType(mDecodeLooper, mMimeType.get(), false);
+  mDecoder = MediaCodecProxy::CreateByType(mDecodeLooper,
+                                           mConfig.mMimeType.get(),
+                                           false);
 
   uint32_t capability = MediaCodecProxy::kEmptyCapability;
   if (mDecoder->getCapability(&capability) == OK && (capability &
       MediaCodecProxy::kCanExposeGraphicBuffer)) {
 #if ANDROID_VERSION >= 21
     sp<IGonkGraphicBufferConsumer> consumer;
     GonkBufferQueue::createBufferQueue(&mGraphicBufferProducer, &consumer);
     mNativeWindow = new GonkNativeWindow(consumer);
@@ -229,38 +216,28 @@ GonkVideoDecoderManager::CreateVideoData
     // quoted from Android's AwesomePlayer.cpp
     return NS_ERROR_NOT_AVAILABLE;
   }
 
   if (!aBuffer->meta_data()->findInt32(kKeyIsSyncFrame, &keyFrame)) {
     keyFrame = 0;
   }
 
-  gfx::IntRect picture = mPicture;
-  if (mFrameInfo.mWidth != mInitialFrame.width ||
-      mFrameInfo.mHeight != mInitialFrame.height) {
-
-    // Frame size is different from what the container reports. This is legal,
-    // and we will preserve the ratio of the crop rectangle as it
-    // was reported relative to the picture size reported by the container.
-    picture.x = (mPicture.x * mFrameInfo.mWidth) / mInitialFrame.width;
-    picture.y = (mPicture.y * mFrameInfo.mHeight) / mInitialFrame.height;
-    picture.width = (mFrameInfo.mWidth * mPicture.width) / mInitialFrame.width;
-    picture.height = (mFrameInfo.mHeight * mPicture.height) / mInitialFrame.height;
-  }
-
   if (aBuffer->graphicBuffer().get()) {
     data = CreateVideoDataFromGraphicBuffer(aBuffer, picture);
     if (data && !mNeedsCopyBuffer) {
       // RecycleCallback() will be responsible for release the buffer.
       autoRelease.forget();
     }
     mNeedsCopyBuffer = false;
   } else {
-    data = CreateVideoDataFromDataBuffer(aBuffer, picture);
+    data =
+      CreateVideoDataFromDataBuffer(aBuffer,
+                                    mConfig.ScaledImageRect(mFrameInfo.mWidth,
+                                                            mFrameInfo.mHeight));
   }
 
   if (!data) {
     return NS_ERROR_UNEXPECTED;
   }
   // Fill necessary info.
   data->mOffset = aStreamOffset;
   data->mTime = timeUs;
@@ -560,17 +537,19 @@ GonkVideoDecoderManager::SetVideoFormat(
     }
     mFrameInfo.mWidth = width;
     mFrameInfo.mHeight = height;
     mFrameInfo.mStride = stride;
     mFrameInfo.mSliceHeight = slice_height;
     mFrameInfo.mColorFormat = color_format;
 
     nsIntSize displaySize(width, height);
-    if (!IsValidVideoRegion(mInitialFrame, mPicture, displaySize)) {
+    if (!IsValidVideoRegion(mConfig.mDisplay,
+                            mConfig.ScaledImageRect(width, height),
+                            displaySize)) {
       GVDM_LOG("It is not a valid region");
       return false;
     }
     return true;
   }
   GVDM_LOG("Fail to get output format");
   return false;
 }
@@ -663,36 +642,36 @@ GonkVideoDecoderManager::codecReserved()
   if (mInitPromise.IsEmpty()) {
     return;
   }
   GVDM_LOG("codecReserved");
   sp<AMessage> format = new AMessage;
   sp<Surface> surface;
   status_t rv = OK;
   // Fixed values
-  GVDM_LOG("Configure video mime type: %s, width:%d, height:%d", mMimeType.get(), mVideoWidth, mVideoHeight);
-  format->setString("mime", mMimeType.get());
-  format->setInt32("width", mVideoWidth);
-  format->setInt32("height", mVideoHeight);
+  GVDM_LOG("Configure video mime type: %s, width:%d, height:%d", mConfig.mMimeType.get(), mConfig.mImage.width, mConfig.mImage.height);
+  format->setString("mime", mConfig.mMimeType.get());
+  format->setInt32("width", mConfig.mImage.width);
+  format->setInt32("height", mConfig.mImage.height);
   // Set the "moz-use-undequeued-bufs" to use the undeque buffers to accelerate
   // the video decoding.
   format->setInt32("moz-use-undequeued-bufs", 1);
   if (mNativeWindow != nullptr) {
 #if ANDROID_VERSION >= 21
     surface = new Surface(mGraphicBufferProducer);
 #else
     surface = new Surface(mNativeWindow->getBufferQueue());
 #endif
   }
   mDecoder->configure(format, surface, nullptr, 0);
   mDecoder->Prepare();
 
-  if (mMimeType.EqualsLiteral("video/mp4v-es")) {
-    rv = mDecoder->Input(mCodecSpecificData->Elements(),
-                         mCodecSpecificData->Length(), 0,
+  if (mConfig.mMimeType.EqualsLiteral("video/mp4v-es")) {
+    rv = mDecoder->Input(mConfig.mCodecSpecificData->Elements(),
+                         mConfig.mCodecSpecificData->Length(), 0,
                          android::MediaCodec::BUFFER_FLAG_CODECCONFIG,
                          CODECCONFIG_TIMEOUT_US);
   }
 
   if (rv != OK) {
     GVDM_LOG("Failed to configure codec!!!!");
     mInitPromise.Reject(DecoderFailureReason::INIT_ERROR, __func__);
     return;
--- a/dom/media/platforms/gonk/GonkVideoDecoderManager.h
+++ b/dom/media/platforms/gonk/GonkVideoDecoderManager.h
@@ -96,27 +96,21 @@ private:
   // For codec resource management
   void codecReserved();
   void codecCanceled();
 
   void ReleaseAllPendingVideoBuffers();
   void PostReleaseVideoBuffer(android::MediaBuffer *aBuffer,
                               layers::FenceHandle mReleaseFence);
 
-  uint32_t mVideoWidth;
-  uint32_t mVideoHeight;
-  uint32_t mDisplayWidth;
-  uint32_t mDisplayHeight;
-  nsIntRect mPicture;
-  nsIntSize mInitialFrame;
+  VideoInfo mConfig;
 
   RefPtr<layers::ImageContainer> mImageContainer;
   RefPtr<layers::TextureClientRecycleAllocator> mCopyAllocator;
 
-  MediaInfo mInfo;
   MozPromiseRequestHolder<android::MediaCodecProxy::CodecPromise> mVideoCodecRequest;
   FrameInfo mFrameInfo;
 
   // color converter
   android::I420ColorConverterHelper mColorConverter;
   UniquePtr<uint8_t[]> mColorConverterBuffer;
   size_t mColorConverterBufferSize;