Bug 794061 - Let OMX hardware decoded video frames be copied to canvas. r=kanru, a=blocking-basecamp
authorEdwin Flores <eflores@mozilla.com>
Tue, 09 Oct 2012 17:06:35 +1300
changeset 113336 adfd438b56ffd83ce7af0c1eff560ee495b4cdd2
parent 113335 90a5685dc1be98a1314cc6a4129083b22eed2142
child 113337 0e355208adffa4c255a2dd3c2a7251a8960434af
push id2292
push userryanvm@gmail.com
push dateSat, 13 Oct 2012 19:19:53 +0000
treeherdermozilla-aurora@c0b49817915d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskanru, blocking-basecamp
bugs794061
milestone18.0a2
Bug 794061 - Let OMX hardware decoded video frames be copied to canvas. r=kanru, a=blocking-basecamp
gfx/layers/GonkIOSurfaceImage.cpp
gfx/layers/GonkIOSurfaceImage.h
gfx/layers/Makefile.in
new file mode 100644
--- /dev/null
+++ b/gfx/layers/GonkIOSurfaceImage.cpp
@@ -0,0 +1,104 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "GonkIOSurfaceImage.h"
+
+#include <OMX_IVCommon.h>
+#include <ColorConverter.h>
+#include <utils/RefBase.h>
+#include <utils/Errors.h>
+
+#define ALIGN(x, align) ((x + align - 1) & ~(align - 1))
+
+typedef android::GraphicBuffer GraphicBuffer;
+
+namespace mozilla {
+namespace layers {
+
+uint32_t GonkIOSurfaceImage::sColorIdMap[] = {
+    HAL_PIXEL_FORMAT_YCbCr_420_P, OMX_COLOR_FormatYUV420Planar,
+    HAL_PIXEL_FORMAT_YCbCr_422_P, OMX_COLOR_FormatYUV422Planar,
+    HAL_PIXEL_FORMAT_YCbCr_420_SP, OMX_COLOR_FormatYUV420SemiPlanar,
+    HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO, OMX_QCOM_COLOR_FormatYVU420SemiPlanar,
+    0, 0
+};
+
+struct GraphicBufferAutoUnlock {
+  android::sp<GraphicBuffer> mGraphicBuffer;
+
+  GraphicBufferAutoUnlock(android::sp<GraphicBuffer>& aGraphicBuffer)
+    : mGraphicBuffer(aGraphicBuffer) { }
+
+  ~GraphicBufferAutoUnlock() { mGraphicBuffer->unlock(); }
+};
+
+already_AddRefed<gfxASurface>
+GonkIOSurfaceImage::GetAsSurface()
+{
+  android::sp<GraphicBuffer> graphicBuffer =
+    GrallocBufferActor::GetFrom(GetSurfaceDescriptor());
+
+  void *buffer;
+  int32_t rv =
+    graphicBuffer->lock(android::GraphicBuffer::USAGE_SW_READ_OFTEN, &buffer);
+
+  if (rv) {
+    NS_WARNING("Couldn't lock graphic buffer");
+    return nullptr;
+  }
+
+  GraphicBufferAutoUnlock unlock(graphicBuffer);
+
+  uint32_t format = graphicBuffer->getPixelFormat();
+  uint32_t omxFormat = 0;
+
+  for (int i = 0; sColorIdMap[i]; i += 2) {
+    if (sColorIdMap[i] == format) {
+      omxFormat = sColorIdMap[i + 1];
+      break;
+    }
+  }
+
+  if (!omxFormat) {
+    NS_WARNING("Unknown color format");
+    return nullptr;
+  }
+
+  nsRefPtr<gfxImageSurface> imageSurface =
+    new gfxImageSurface(GetSize(), gfxASurface::ImageFormatRGB16_565);
+
+  android::ColorConverter *colorConverter =
+    new android::ColorConverter((OMX_COLOR_FORMATTYPE)omxFormat,
+                                OMX_COLOR_Format16bitRGB565);
+
+  if (!colorConverter->isValid()) {
+    NS_WARNING("Invalid color conversion");
+    return nullptr;
+  }
+
+  uint32_t width = GetSize().width;
+  uint32_t height = GetSize().height;
+
+  if (omxFormat == OMX_QCOM_COLOR_FormatYVU420SemiPlanar) {
+    // The Adreno hardware decoder aligns image dimensions to a multiple of 32,
+    //  so we have to account for that here
+    width = ALIGN(width, 32);
+    height = ALIGN(height, 32);
+  }
+
+  rv = colorConverter->convert(buffer, width, height,
+                               0, 0, width - 1, height - 1 /* source crop */,
+                               imageSurface->Data(), width, height,
+                               0, 0, width - 1, height - 1 /* dest crop */);
+
+  if (rv) {
+    NS_WARNING("OMX color conversion failed");
+    return nullptr;
+  }
+
+  return imageSurface.forget();
+}
+
+} // namespace layers
+} // namespace mozilla
--- a/gfx/layers/GonkIOSurfaceImage.h
+++ b/gfx/layers/GonkIOSurfaceImage.h
@@ -42,16 +42,18 @@ public:
     return mSurfaceDescriptor;
   }
 
 protected:
   SurfaceDescriptor mSurfaceDescriptor;
 };
 
 class THEBES_API GonkIOSurfaceImage : public Image {
+  typedef android::GraphicBuffer GraphicBuffer;
+  static uint32_t sColorIdMap[];
 public:
   struct Data {
     nsRefPtr<GraphicBufferLocked> mGraphicBuffer;
     gfxIntSize mPicSize;
   };
   GonkIOSurfaceImage()
     : Image(NULL, GONK_IO_SURFACE)
     , mSize(0, 0)
@@ -68,21 +70,30 @@ public:
     mSize = aData.mPicSize;
   }
 
   virtual gfxIntSize GetSize()
   {
     return mSize;
   }
 
-  virtual already_AddRefed<gfxASurface> GetAsSurface()
-  {
-    // We need to fix this and return a ASurface at some point.
-    return nullptr;
-  }
+  // From [android 4.0.4]/hardware/msm7k/libgralloc-qsd8k/gralloc_priv.h
+  enum {
+    /* OEM specific HAL formats */
+    HAL_PIXEL_FORMAT_YCbCr_422_P            = 0x102,
+    HAL_PIXEL_FORMAT_YCbCr_420_P            = 0x103,
+    HAL_PIXEL_FORMAT_YCbCr_420_SP           = 0x109,
+    HAL_PIXEL_FORMAT_YCrCb_420_SP_ADRENO    = 0x10A,
+  };
+
+  enum {
+    OMX_QCOM_COLOR_FormatYVU420SemiPlanar   = 0x7FA30C00,
+  };
+
+  virtual already_AddRefed<gfxASurface> GetAsSurface();
 
   void* GetNativeBuffer()
   {
     return GrallocBufferActor::GetFrom(GetSurfaceDescriptor())->getNativeBuffer();
   }
 
   SurfaceDescriptor GetSurfaceDescriptor()
   {
--- a/gfx/layers/Makefile.in
+++ b/gfx/layers/Makefile.in
@@ -175,20 +175,23 @@ endif
 # NB: Gralloc is available on other platforms that use the android GL
 # libraries, but only Gonk is able to use it reliably because Gecko
 # has full system permissions there.
 ifeq ($(MOZ_WIDGET_TOOLKIT),gonk)
 EXPORTS_mozilla/layers += ShadowLayerUtilsGralloc.h
 CPPSRCS += \
         ShadowLayerUtilsGralloc.cpp \
         GrallocImages.cpp \
+        GonkIOSurfaceImage.cpp \
         $(NULL)
 endif
 
 include $(topsrcdir)/config/rules.mk
 
 include $(topsrcdir)/ipc/chromium/chromium-config.mk
 
 LOCAL_INCLUDES += \
         -I$(topsrcdir)/content/events/src \
+        -I$(ANDROID_SOURCE)/frameworks/base/include/media/stagefright \
+        -I$(ANDROID_SOURCE)/frameworks/base/include/media/stagefright/openmax \
         $(NULL)
 
 CXXFLAGS += $(MOZ_CAIRO_CFLAGS) $(MOZ_PIXMAN_CFLAGS) $(TK_CFLAGS)