Bug 812881 - Ensure OMX plugins instantiate only one OMXClient instance. r=sotaro, a=sledru
authorEdwin Flores <eflores@mozilla.com>
Thu, 03 Apr 2014 09:53:38 +1300
changeset 183688 14b8222e1a24
parent 183687 b39c5ca49785
child 183689 afdcb5d5d7cc
push id3447
push userryanvm@gmail.com
push date2014-04-09 18:07 +0000
Treeherderresults
reviewerssotaro, sledru
bugs812881
milestone29.0
Bug 812881 - Ensure OMX plugins instantiate only one OMXClient instance. r=sotaro, a=sledru

Samsung's OMX IL doesn't like being instantiated more than once, often leading
to crashes. This patch changes the OMX plugin so that we statically instantiate
one OMXClient to be shared between decoder instances.
media/omx-plugin/OmxPlugin.cpp
--- a/media/omx-plugin/OmxPlugin.cpp
+++ b/media/omx-plugin/OmxPlugin.cpp
@@ -60,19 +60,16 @@ namespace OmxPlugin {
 
 const int OMX_QCOM_COLOR_FormatYVU420PackedSemiPlanar32m4ka = 0x7FA30C01;
 const int OMX_QCOM_COLOR_FormatYVU420SemiPlanar = 0x7FA30C00;
 const int OMX_TI_COLOR_FormatYUV420PackedSemiPlanar = 0x7F000100;
 
 class OmxDecoder {
   PluginHost *mPluginHost;
   Decoder *mDecoder;
-#ifndef MOZ_WIDGET_GONK
-  OMXClient mClient;
-#endif
   sp<MediaSource> mVideoTrack;
   sp<MediaSource> mVideoSource;
   sp<MediaSource> mAudioTrack;
   sp<MediaSource> mAudioSource;
   int32_t mVideoWidth;
   int32_t mVideoHeight;
   int32_t mVideoColorFormat;
   int32_t mVideoStride;
@@ -138,16 +135,49 @@ public:
   bool HasAudio() {
     return mAudioSource != nullptr;
   }
 
   bool ReadVideo(VideoFrame *aFrame, int64_t aSeekTimeUs, BufferCallback *aBufferCallback);
   bool ReadAudio(AudioFrame *aFrame, int64_t aSeekTimeUs);
 };
 
+#if !defined(MOZ_WIDGET_GONK)
+static class OmxClientInstance {
+public:
+  OmxClientInstance()
+    : mClient(new OMXClient())
+    , mStatus(mClient->connect())
+  {
+  }
+
+  status_t IsValid()
+  {
+    return mStatus == OK;
+  }
+
+  OMXClient *get()
+  {
+    return mClient;
+  }
+
+  ~OmxClientInstance()
+  {
+    if (mStatus == OK) {
+      mClient->disconnect();
+    }
+    delete mClient;
+  }
+
+private:
+  OMXClient *mClient;
+  status_t mStatus;
+} sClientInstance;
+#endif
+
 OmxDecoder::OmxDecoder(PluginHost *aPluginHost, Decoder *aDecoder) :
   mPluginHost(aPluginHost),
   mDecoder(aDecoder),
   mVideoWidth(0),
   mVideoHeight(0),
   mVideoColorFormat(0),
   mVideoStride(0),
   mVideoSliceHeight(0),
@@ -179,19 +209,16 @@ OmxDecoder::~OmxDecoder()
     mAudioSource->stop();
   }
 
 #ifndef MOZ_ANDROID_HC
   if (mColorConverter) {
     delete mColorConverter;
   }
 #endif
-#ifndef MOZ_WIDGET_GONK
-  mClient.disconnect();
-#endif
 }
 
 class AutoStopMediaSource {
   sp<MediaSource> mMediaSource;
 public:
   AutoStopMediaSource(sp<MediaSource> aMediaSource) : mMediaSource(aMediaSource) {
   }
 
@@ -424,17 +451,28 @@ static sp<MediaSource> CreateVideoSource
 #endif
   }
 
   MOZ_ASSERT(flags != DEFAULT_STAGEFRIGHT_FLAGS);
   return OMXCodec::Create(aOmx, aVideoTrack->getFormat(), false, aVideoTrack,
                           nullptr, flags);
 }
 
-bool OmxDecoder::Init() {
+bool OmxDecoder::Init()
+{
+#if defined(MOZ_WIDGET_ANDROID)
+  // OMXClient::connect() always returns OK and aborts fatally if
+  // it can't connect. We may need to implement the connect functionality
+  // ourselves if this proves to be an issue.
+  if (!sClientInstance.IsValid()) {
+    LOG("OMXClient failed to connect");
+    return false;
+  }
+#endif
+
   //register sniffers, if they are not registered in this process.
   DataSource::RegisterDefaultSniffers();
 
   sp<DataSource> dataSource =
     DataSource::CreateFromURI(static_cast<char*>(mDecoder->mResource));
   if (!dataSource.get() || dataSource->initCheck()) {
     return false;
   }
@@ -470,23 +508,17 @@ bool OmxDecoder::Init() {
     return false;
   }
 
   int64_t totalDurationUs = 0;
 
 #ifdef MOZ_WIDGET_GONK
   sp<IOMX> omx = GetOMX();
 #else
-  // OMXClient::connect() always returns OK and abort's fatally if
-  // it can't connect. We may need to implement the connect functionality
-  // ourselves if this proves to be an issue.
-  if (mClient.connect() != OK) {
-    LOG("OMXClient failed to connect");
-  }
-  sp<IOMX> omx = mClient.interface();
+  sp<IOMX> omx = sClientInstance.get()->interface();
 #endif
 
   sp<MediaSource> videoTrack;
   sp<MediaSource> videoSource;
   if (videoTrackIndex != -1 && (videoTrack = extractor->getTrack(videoTrackIndex)) != nullptr) {
 #if defined(MOZ_ANDROID_FROYO)
     // Allow up to 720P video.
     sp<MetaData> meta = extractor->getTrackMetaData(videoTrackIndex);