Bug 1003712: Use Media Resource Manager to reserve OMX Codecs r=jhlin
authorRandell Jesup <rjesup@jesup.org>
Wed, 04 Jun 2014 14:52:31 -0400
changeset 206974 eb336259b85f050b59a5cd516bdfa28cb2a8f65e
parent 206973 52f23831adbc4d6442a485014797e5b312ea9e74
child 206975 9e0dfff3fdb2803515c5fdf5591ccc412f2ac89f
push id494
push userraliiev@mozilla.com
push dateMon, 25 Aug 2014 18:42:16 +0000
treeherdermozilla-release@a3cc3e46b571 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjhlin
bugs1003712
milestone32.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 1003712: Use Media Resource Manager to reserve OMX Codecs r=jhlin
content/media/omx/OMXCodecWrapper.cpp
content/media/omx/OMXCodecWrapper.h
content/media/omx/mediaresourcemanager/moz.build
media/webrtc/signaling/src/media-conduit/WebrtcOMXH264VideoCodec.cpp
media/webrtc/signaling/src/media-conduit/WebrtcOMXH264VideoCodec.h
--- a/content/media/omx/OMXCodecWrapper.cpp
+++ b/content/media/omx/OMXCodecWrapper.cpp
@@ -29,16 +29,42 @@ using namespace mozilla::layers;
 
 #define CODEC_ERROR(args...)                                                   \
   do {                                                                         \
     __android_log_print(ANDROID_LOG_ERROR, "OMXCodecWrapper", ##args);         \
   } while (0)
 
 namespace android {
 
+bool
+OMXCodecReservation::ReserveOMXCodec()
+{
+  if (!mManagerService.get()) {
+    sp<MediaResourceManagerClient::EventListener> listener = this;
+    mClient = new MediaResourceManagerClient(listener);
+
+    mManagerService = mClient->getMediaResourceManagerService();
+    if (!mManagerService.get()) {
+      mClient = nullptr;
+      return true; // not really in use, but not usable
+    }
+  }
+  return (mManagerService->requestMediaResource(mClient, mType, false) == OK); // don't wait
+}
+
+void
+OMXCodecReservation::ReleaseOMXCodec()
+{
+  if (!mManagerService.get() || !mClient.get()) {
+    return;
+  }
+
+  mManagerService->cancelClient(mClient, mType);
+}
+
 OMXAudioEncoder*
 OMXCodecWrapper::CreateAACEncoder()
 {
   nsAutoPtr<OMXAudioEncoder> aac(new OMXAudioEncoder(CodecType::AAC_ENC));
   // Return the object only when media codec is valid.
   NS_ENSURE_TRUE(aac->IsValid(), nullptr);
 
   return aac.forget();
--- a/content/media/omx/OMXCodecWrapper.h
+++ b/content/media/omx/OMXCodecWrapper.h
@@ -10,20 +10,55 @@
 #include <stagefright/foundation/ABuffer.h>
 #include <stagefright/foundation/AMessage.h>
 #include <stagefright/MediaCodec.h>
 
 #include "AudioSegment.h"
 #include "GonkNativeWindow.h"
 #include "GonkNativeWindowClient.h"
 
+#include "IMediaResourceManagerService.h"
+#include "MediaResourceManagerClient.h"
+
 #include <speex/speex_resampler.h>
 
 namespace android {
 
+// Wrapper class for managing HW codec reservations
+class OMXCodecReservation : public MediaResourceManagerClient::EventListener
+{
+public:
+  OMXCodecReservation(bool aEncoder)
+  {
+    mType = aEncoder ? IMediaResourceManagerService::HW_VIDEO_ENCODER :
+            IMediaResourceManagerService::HW_VIDEO_DECODER;
+  }
+
+  virtual ~OMXCodecReservation()
+  {
+    ReleaseOMXCodec();
+  }
+
+  /** Reserve the Encode or Decode resource for this instance */
+  virtual bool ReserveOMXCodec();
+
+  /** Release the Encode or Decode resource for this instance */
+  virtual void ReleaseOMXCodec();
+
+  // MediaResourceManagerClient::EventListener
+  virtual void statusChanged(int event) {}
+
+private:
+  IMediaResourceManagerService::ResourceType mType;
+
+  sp<MediaResourceManagerClient> mClient;
+  sp<IMediaResourceManagerService> mManagerService;
+};
+
+
 class OMXAudioEncoder;
 class OMXVideoEncoder;
 
 /**
  * This class (and its subclasses) wraps the video and audio codec from
  * MediaCodec API in libstagefright. Currently only AVC/H.264 video encoder and
  * AAC audio encoder are supported.
  *
--- a/content/media/omx/mediaresourcemanager/moz.build
+++ b/content/media/omx/mediaresourcemanager/moz.build
@@ -1,14 +1,22 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+EXPORTS += [
+    'IMediaResourceManagerClient.h',
+    'IMediaResourceManagerDeathNotifier.h',
+    'IMediaResourceManagerService.h',
+    'MediaResourceManagerClient.h',
+    'MediaResourceManagerService.h',
+]
+
 SOURCES += [
     'IMediaResourceManagerClient.cpp',
     'IMediaResourceManagerDeathNotifier.cpp',
     'IMediaResourceManagerService.cpp',
     'MediaResourceManagerClient.cpp',
     'MediaResourceManagerService.cpp',
 ]
 
--- a/media/webrtc/signaling/src/media-conduit/WebrtcOMXH264VideoCodec.cpp
+++ b/media/webrtc/signaling/src/media-conduit/WebrtcOMXH264VideoCodec.cpp
@@ -709,16 +709,17 @@ WebrtcOMXH264VideoEncoder::WebrtcOMXH264
   , mWidth(0)
   , mHeight(0)
   , mFrameRate(0)
   , mBitRateKbps(0)
   , mBitRateAtLastIDR(0)
   , mOMXConfigured(false)
   , mOMXReconfigure(false)
 {
+  mReservation = new OMXCodecReservation(true);
   CODEC_LOGD("WebrtcOMXH264VideoEncoder:%p constructed", this);
 }
 
 int32_t
 WebrtcOMXH264VideoEncoder::InitEncode(const webrtc::VideoCodec* aCodecSettings,
                                       int32_t aNumOfCores,
                                       uint32_t aMaxPayloadSize)
 {
@@ -728,25 +729,32 @@ WebrtcOMXH264VideoEncoder::InitEncode(co
     nsAutoPtr<OMXVideoEncoder> omx(OMXCodecWrapper::CreateAVCEncoder());
     if (NS_WARN_IF(omx == nullptr)) {
       return WEBRTC_VIDEO_CODEC_ERROR;
     }
     mOMX = omx.forget();
     CODEC_LOGD("WebrtcOMXH264VideoEncoder:%p OMX created", this);
   }
 
+  if (!mReservation->ReserveOMXCodec()) {
+    CODEC_LOGD("WebrtcOMXH264VideoEncoder:%p Encoder in use", this);
+    mOMX = nullptr;
+    return WEBRTC_VIDEO_CODEC_ERROR;
+  }
+
   // Defer configuration until 1st frame is received because this function will
   // be called more than once, and unfortunately with incorrect setting values
   // at first.
   mWidth = aCodecSettings->width;
   mHeight = aCodecSettings->height;
   mFrameRate = aCodecSettings->maxFramerate;
   mBitRateKbps = aCodecSettings->startBitrate;
   // XXX handle maxpayloadsize (aka mode 0/1)
 
+  CODEC_LOGD("WebrtcOMXH264VideoEncoder:%p OMX Encoder reserved", this);
   return WEBRTC_VIDEO_CODEC_OK;
 }
 
 int32_t
 WebrtcOMXH264VideoEncoder::Encode(const webrtc::I420VideoFrame& aInputImage,
                                   const webrtc::CodecSpecificInfo* aCodecSpecificInfo,
                                   const std::vector<webrtc::VideoFrameType>* aFrameTypes)
 {
@@ -916,17 +924,21 @@ WebrtcOMXH264VideoEncoder::Release()
 {
   CODEC_LOGD("WebrtcOMXH264VideoEncoder:%p will be released", this);
 
   if (mOutputDrain != nullptr) {
     mOutputDrain->Stop();
     mOutputDrain = nullptr;
   }
   mOMXConfigured = false;
+  bool hadOMX = !!mOMX;
   mOMX = nullptr;
+  if (hadOMX) {
+    mReservation->ReleaseOMXCodec();
+  }
   CODEC_LOGD("WebrtcOMXH264VideoEncoder:%p released", this);
 
   return WEBRTC_VIDEO_CODEC_OK;
 }
 
 WebrtcOMXH264VideoEncoder::~WebrtcOMXH264VideoEncoder()
 {
   CODEC_LOGD("WebrtcOMXH264VideoEncoder:%p will be destructed", this);
@@ -1008,28 +1020,35 @@ WebrtcOMXH264VideoEncoder::SetRates(uint
   return NS_FAILED(rv) ? WEBRTC_VIDEO_CODEC_OK : WEBRTC_VIDEO_CODEC_ERROR;
 }
 
 // Decoder.
 WebrtcOMXH264VideoDecoder::WebrtcOMXH264VideoDecoder()
   : mCallback(nullptr)
   , mOMX(nullptr)
 {
+  mReservation = new OMXCodecReservation(false);
   CODEC_LOGD("WebrtcOMXH264VideoDecoder:%p will be constructed", this);
 }
 
 int32_t
 WebrtcOMXH264VideoDecoder::InitDecode(const webrtc::VideoCodec* aCodecSettings,
                                       int32_t aNumOfCores)
 {
   CODEC_LOGD("WebrtcOMXH264VideoDecoder:%p init OMX:%p", this, mOMX.get());
 
+  if (!mReservation->ReserveOMXCodec()) {
+    CODEC_LOGD("WebrtcOMXH264VideoDecoder:%p Decoder in use", this);
+    return WEBRTC_VIDEO_CODEC_ERROR;
+  }
+
   // Defer configuration until SPS/PPS NALUs (where actual decoder config
   // values can be extracted) are received.
 
+  CODEC_LOGD("WebrtcOMXH264VideoDecoder:%p OMX Decoder reserved", this);
   return WEBRTC_VIDEO_CODEC_OK;
 }
 
 int32_t
 WebrtcOMXH264VideoDecoder::Decode(const webrtc::EncodedImage& aInputImage,
                                   bool aMissingFrames,
                                   const webrtc::RTPFragmentationHeader* aFragmentation,
                                   const webrtc::CodecSpecificInfo* aCodecSpecificInfo,
@@ -1084,16 +1103,17 @@ WebrtcOMXH264VideoDecoder::RegisterDecod
 }
 
 int32_t
 WebrtcOMXH264VideoDecoder::Release()
 {
   CODEC_LOGD("WebrtcOMXH264VideoDecoder:%p will be released", this);
 
   mOMX = nullptr;
+  mReservation->ReleaseOMXCodec();
 
   return WEBRTC_VIDEO_CODEC_OK;
 }
 
 WebrtcOMXH264VideoDecoder::~WebrtcOMXH264VideoDecoder()
 {
   CODEC_LOGD("WebrtcOMXH264VideoDecoder:%p will be destructed", this);
   Release();
--- a/media/webrtc/signaling/src/media-conduit/WebrtcOMXH264VideoCodec.h
+++ b/media/webrtc/signaling/src/media-conduit/WebrtcOMXH264VideoCodec.h
@@ -6,16 +6,19 @@
 #pragma error WebrtcOMXH264VideoCodec works only on B2G.
 #endif
 
 #ifndef WEBRTC_OMX_H264_CODEC_H_
 #define WEBRTC_OMX_H264_CODEC_H_
 
 #include "AudioConduit.h"
 #include "VideoConduit.h"
+#include <foundation/ABase.h>
+#include <utils/RefBase.h>
+#include "OMXCodecWrapper.h"
 
 namespace android {
   class OMXVideoEncoder;
 }
 
 namespace mozilla {
 
 class WebrtcOMXDecoder;
@@ -43,16 +46,18 @@ public:
 
   virtual int32_t SetChannelParameters(uint32_t aPacketLossRate,
                                        int aRoundTripTimeMs) MOZ_OVERRIDE;
 
   virtual int32_t SetRates(uint32_t aBitRate, uint32_t aFrameRate) MOZ_OVERRIDE;
 
 private:
   RefPtr<android::OMXVideoEncoder> mOMX;
+  android::sp<android::OMXCodecReservation> mReservation;
+
   webrtc::EncodedImageCallback* mCallback;
   RefPtr<OMXOutputDrain> mOutputDrain;
   uint32_t mWidth;
   uint32_t mHeight;
   uint32_t mFrameRate;
   uint32_t mBitRateKbps;
   uint32_t mBitRateAtLastIDR;
   TimeStamp mLastIDRTime;
@@ -80,13 +85,14 @@ public:
 
   virtual int32_t Release() MOZ_OVERRIDE;
 
   virtual int32_t Reset() MOZ_OVERRIDE;
 
 private:
   webrtc::DecodedImageCallback* mCallback;
   RefPtr<WebrtcOMXDecoder> mOMX;
+  android::sp<android::OMXCodecReservation> mReservation;
 };
 
 }
 
 #endif // WEBRTC_OMX_H264_CODEC_H_