Bug 904177 - Add I420ColorConverterHelper. r=sotaro, r=cpearce
authorBruce Sun <brsun@mozilla.com>
Wed, 16 Jul 2014 15:32:21 +0800
changeset 215370 b26a1d2a1b0c7ca27f09ddf3bf25ec6cc2855564
parent 215369 100732a8c93e05a90094f8b890d8d6baea5602a2
child 215371 a60ff172ed7d781209faeb50797110024267f7d6
push id3857
push userraliiev@mozilla.com
push dateTue, 02 Sep 2014 16:39:23 +0000
treeherdermozilla-beta@5638b907b505 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerssotaro, cpearce
bugs904177
milestone33.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 904177 - Add I420ColorConverterHelper. r=sotaro, r=cpearce
content/media/omx/I420ColorConverterHelper.cpp
content/media/omx/I420ColorConverterHelper.h
content/media/omx/moz.build
new file mode 100644
--- /dev/null
+++ b/content/media/omx/I420ColorConverterHelper.cpp
@@ -0,0 +1,229 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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 "I420ColorConverterHelper.h"
+
+#include <dlfcn.h>
+
+#include "prlog.h"
+
+#ifdef PR_LOGGING
+PRLogModuleInfo *gI420ColorConverterHelperLog;
+#define LOG(msg...) PR_LOG(gI420ColorConverterHelperLog, PR_LOG_WARNING, (msg))
+#else
+#define LOG(x...)
+#endif
+
+namespace android {
+
+I420ColorConverterHelper::I420ColorConverterHelper()
+  : mHandle(nullptr)
+  , mConverter({nullptr, nullptr, nullptr, nullptr, nullptr})
+{
+#ifdef PR_LOGGING
+  if (!gI420ColorConverterHelperLog) {
+    gI420ColorConverterHelperLog = PR_NewLogModule("I420ColorConverterHelper");
+  }
+#endif
+}
+
+I420ColorConverterHelper::~I420ColorConverterHelper()
+{
+  RWLock::AutoWLock awl(mLock);
+  unloadLocked();
+}
+
+// Prerequisite: a writer-lock should be held
+bool
+I420ColorConverterHelper::loadLocked()
+{
+  if (loadedLocked()) {
+    return true;
+  }
+  unloadLocked();
+
+  // Open the shared library
+  mHandle = dlopen("libI420colorconvert.so", RTLD_NOW);
+  if (mHandle == nullptr) {
+    LOG("libI420colorconvert.so not found");
+    return false;
+  }
+
+  // Find the entry point
+  // Pointer to function with signature
+  // void getI420ColorConverter(II420ColorConverter *converter)
+  typedef int (* getConverterFn)(II420ColorConverter *converter);
+  getConverterFn getI420ColorConverter =
+      (getConverterFn) dlsym(mHandle, "getI420ColorConverter");
+  if (getI420ColorConverter == nullptr) {
+    LOG("Cannot load getI420ColorConverter from libI420colorconvert.so");
+    unloadLocked();
+    return false;
+  }
+
+  // Fill the function pointers.
+  getI420ColorConverter(&mConverter);
+  if (mConverter.getDecoderOutputFormat == nullptr ||
+      mConverter.convertDecoderOutputToI420 == nullptr ||
+      mConverter.getEncoderInputFormat == nullptr ||
+      mConverter.convertI420ToEncoderInput == nullptr ||
+      mConverter.getEncoderInputBufferInfo == nullptr) {
+    LOG("Failed to initialize I420 color converter");
+    unloadLocked();
+    return false;
+  }
+
+  return true;
+}
+
+// Prerequisite: a reader-lock or a writer-lock should be held
+bool
+I420ColorConverterHelper::loadedLocked() const
+{
+  if (mHandle == nullptr ||
+      mConverter.getDecoderOutputFormat == nullptr ||
+      mConverter.convertDecoderOutputToI420 == nullptr ||
+      mConverter.getEncoderInputFormat == nullptr ||
+      mConverter.convertI420ToEncoderInput == nullptr ||
+      mConverter.getEncoderInputBufferInfo == nullptr) {
+    return false;
+  }
+  return true;
+}
+
+// Prerequisite: a writer-lock should be held
+void
+I420ColorConverterHelper::unloadLocked()
+{
+  if (mHandle != nullptr) {
+    dlclose(mHandle);
+  }
+  mHandle = nullptr;
+  mConverter.getDecoderOutputFormat = nullptr;
+  mConverter.convertDecoderOutputToI420 = nullptr;
+  mConverter.getEncoderInputFormat = nullptr;
+  mConverter.convertI420ToEncoderInput = nullptr;
+  mConverter.getEncoderInputBufferInfo = nullptr;
+}
+
+bool
+I420ColorConverterHelper::ensureLoaded()
+{
+  {
+    RWLock::AutoRLock arl(mLock);
+    // Check whether the library has been loaded or not.
+    if (loadedLocked()) {
+      return true;
+    }
+  }
+
+  {
+    RWLock::AutoWLock awl(mLock);
+    // Check whether the library has been loaded or not on other threads.
+    if (loadedLocked()) {
+      return true;
+    }
+
+    // Reload the library
+    unloadLocked();
+    if (loadLocked()) {
+      return true;
+    }
+
+    // Reset the library
+    unloadLocked();
+  }
+
+  return false;
+}
+
+int
+I420ColorConverterHelper::getDecoderOutputFormat()
+{
+  if (!ensureLoaded()) {
+    return -1;
+  }
+
+  RWLock::AutoRLock arl(mLock);
+  if (mConverter.getDecoderOutputFormat != nullptr) {
+    return mConverter.getDecoderOutputFormat();
+  }
+  return -1;
+}
+
+int
+I420ColorConverterHelper::convertDecoderOutputToI420(
+    void* decoderBits, int decoderWidth, int decoderHeight,
+    ARect decoderRect, void* dstBits)
+{
+  if (!ensureLoaded()) {
+    return -1;
+  }
+
+  RWLock::AutoRLock arl(mLock);
+  if (mConverter.convertDecoderOutputToI420 != nullptr) {
+    return mConverter.convertDecoderOutputToI420(decoderBits,
+        decoderWidth, decoderHeight, decoderRect, dstBits);
+  }
+  return -1;
+}
+
+int
+I420ColorConverterHelper::getEncoderInputFormat()
+{
+  if (!ensureLoaded()) {
+    return -1;
+  }
+
+  RWLock::AutoRLock arl(mLock);
+  if (mConverter.getEncoderInputFormat != nullptr) {
+    return mConverter.getEncoderInputFormat();
+  }
+  return -1;
+}
+
+int
+I420ColorConverterHelper::convertI420ToEncoderInput(void* aSrcBits,
+                                                    int aSrcWidth,
+                                                    int aSrcHeight,
+                                                    int aEncoderWidth,
+                                                    int aEncoderHeight,
+                                                    ARect aEncoderRect,
+                                                    void* aEncoderBits)
+{
+  if (!ensureLoaded()) {
+    return -1;
+  }
+
+  RWLock::AutoRLock arl(mLock);
+  if (mConverter.convertI420ToEncoderInput != nullptr) {
+    return mConverter.convertI420ToEncoderInput(aSrcBits, aSrcWidth, aSrcHeight,
+        aEncoderWidth, aEncoderHeight, aEncoderRect, aEncoderBits);
+  }
+  return -1;
+}
+
+int
+I420ColorConverterHelper::getEncoderInputBufferInfo(int aSrcWidth,
+                                                    int aSrcHeight,
+                                                    int* aEncoderWidth,
+                                                    int* aEncoderHeight,
+                                                    ARect* aEncoderRect,
+                                                    int* aEncoderBufferSize)
+{
+  if (!ensureLoaded()) {
+    return -1;
+  }
+
+  RWLock::AutoRLock arl(mLock);
+  if (mConverter.getEncoderInputBufferInfo != nullptr) {
+    return mConverter.getEncoderInputBufferInfo(aSrcWidth, aSrcHeight,
+        aEncoderWidth, aEncoderHeight, aEncoderRect, aEncoderBufferSize);
+  }
+  return -1;
+}
+
+} // namespace android
new file mode 100644
--- /dev/null
+++ b/content/media/omx/I420ColorConverterHelper.h
@@ -0,0 +1,64 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim:set ts=2 sw=2 sts=2 et cindent: */
+/* 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/. */
+
+#ifndef I420_COLOR_CONVERTER_HELPER_H
+#define I420_COLOR_CONVERTER_HELPER_H
+
+#include <utils/RWLock.h>
+#include <media/editor/II420ColorConverter.h>
+
+#include <mozilla/Attributes.h>
+
+namespace android {
+
+class I420ColorConverterHelper {
+public:
+  I420ColorConverterHelper();
+  ~I420ColorConverterHelper();
+
+  int getDecoderOutputFormat();
+
+  int convertDecoderOutputToI420(void* aDecoderBits,
+                                 int aDecoderWidth,
+                                 int aDecoderHeight,
+                                 ARect aDecoderRect,
+                                 void* aDstBits);
+
+  int getEncoderInputFormat();
+
+  int convertI420ToEncoderInput(void* aSrcBits,
+                                int aSrcWidth,
+                                int aSrcHeight,
+                                int aEncoderWidth,
+                                int aEncoderHeight,
+                                ARect aEncoderRect,
+                                void* aEncoderBits);
+
+  int getEncoderInputBufferInfo(int aSrcWidth,
+                                int aSrcHeight,
+                                int* aEncoderWidth,
+                                int* aEncoderHeight,
+                                ARect* aEncoderRect,
+                                int* aEncoderBufferSize);
+
+private:
+  mutable RWLock mLock;
+  void *mHandle;
+  II420ColorConverter mConverter;
+
+  bool loadLocked();
+  bool loadedLocked() const;
+  void unloadLocked();
+
+  bool ensureLoaded();
+
+  I420ColorConverterHelper(const I420ColorConverterHelper &) MOZ_DELETE;
+  const I420ColorConverterHelper &operator=(const I420ColorConverterHelper &) MOZ_DELETE;
+};
+
+} // namespace android
+
+#endif // I420_COLOR_CONVERTER_HELPER_H
old mode 100755
new mode 100644
--- a/content/media/omx/moz.build
+++ b/content/media/omx/moz.build
@@ -47,16 +47,17 @@ if 'rtsp' in CONFIG['NECKO_PROTOCOLS']:
         'RtspOmxReader.cpp',
     ]
 
 if int(CONFIG['ANDROID_VERSION']) >= 16:
     EXPORTS += [
         'MediaCodecProxy.h',
     ]
     SOURCES += [
+        'I420ColorConverterHelper.cpp',
         'MediaCodecProxy.cpp',
     ]
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'gklayout'
 LOCAL_INCLUDES += [
     '/content/base/src',