Bug 789307 - Unlock() the graphics buffer if we're not going to consume it. r=kchen
authorMike Habicher <mikeh@mozilla.com>
Fri, 07 Sep 2012 16:23:01 -0400
changeset 104613 f0161019458aaf099c2e8e4834cdce137fec0a42
parent 104612 f298ffd6a36d9a956e3cc751322d97008c8ec8ed
child 104614 b5289c1f03c01c3c1f5128e73dd78ca05bb7bab2
push id23433
push userryanvm@gmail.com
push dateSat, 08 Sep 2012 04:11:45 +0000
treeherdermozilla-central@1d4fc0c60063 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskchen
bugs789307
milestone18.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 789307 - Unlock() the graphics buffer if we're not going to consume it. r=kchen
dom/camera/CameraControlImpl.cpp
dom/camera/CameraControlImpl.h
dom/camera/DOMCameraPreview.cpp
dom/camera/DOMCameraPreview.h
dom/camera/GonkCameraControl.cpp
dom/camera/GonkNativeWindow.cpp
dom/camera/GonkNativeWindow.h
--- a/dom/camera/CameraControlImpl.cpp
+++ b/dom/camera/CameraControlImpl.cpp
@@ -218,22 +218,24 @@ CameraControlImpl::StartPreview(DOMCamer
 
 void
 CameraControlImpl::StopPreview()
 {
   nsCOMPtr<nsIRunnable> stopPreviewTask = new StopPreviewTask(this);
   mCameraThread->Dispatch(stopPreviewTask, NS_DISPATCH_NORMAL);
 }
 
-void
+bool
 CameraControlImpl::ReceiveFrame(void* aBuffer, ImageFormat aFormat, FrameBuilder aBuilder)
 {
-  if (mDOMPreview) {
-    mDOMPreview->ReceiveFrame(aBuffer, aFormat, aBuilder);
+  if (!mDOMPreview) {
+    return false;
   }
+
+  return mDOMPreview->ReceiveFrame(aBuffer, aFormat, aBuilder);
 }
 
 NS_IMETHODIMP
 GetPreviewStreamResult::Run()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   if (mOnSuccessCb) {
--- a/dom/camera/CameraControlImpl.h
+++ b/dom/camera/CameraControlImpl.h
@@ -89,17 +89,17 @@ public:
   virtual double GetParameterDouble(uint32_t aKey) = 0;
   virtual void GetParameter(uint32_t aKey, nsTArray<CameraRegion>& aRegions) = 0;
   virtual void SetParameter(const char* aKey, const char* aValue) = 0;
   virtual void SetParameter(uint32_t aKey, const char* aValue) = 0;
   virtual void SetParameter(uint32_t aKey, double aValue) = 0;
   virtual void SetParameter(uint32_t aKey, const nsTArray<CameraRegion>& aRegions) = 0;
   virtual nsresult PushParameters() = 0;
 
-  void ReceiveFrame(void* aBuffer, ImageFormat aFormat, FrameBuilder aBuilder);
+  bool ReceiveFrame(void* aBuffer, ImageFormat aFormat, FrameBuilder aBuilder);
 
 protected:
   virtual ~CameraControlImpl()
   {
     DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
   }
 
   virtual nsresult GetPreviewStreamImpl(GetPreviewStreamTask* aGetPreviewStream) = 0;
--- a/dom/camera/DOMCameraPreview.cpp
+++ b/dom/camera/DOMCameraPreview.cpp
@@ -165,34 +165,35 @@ DOMCameraPreview::~DOMCameraPreview()
 }
 
 bool
 DOMCameraPreview::HaveEnoughBuffered()
 {
   return mInput->HaveEnoughBuffered(TRACK_VIDEO);
 }
 
-void
+bool
 DOMCameraPreview::ReceiveFrame(void* aBuffer, ImageFormat aFormat, FrameBuilder aBuilder)
 {
   DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
   if (!aBuffer || !aBuilder) {
-    return;
+    return false;
   }
   if (mState != STARTED) {
-    return;
+    return false;
   }
 
   ImageFormat format = aFormat;
   nsRefPtr<Image> image = mImageContainer->CreateImage(&format, 1);
   aBuilder(image, aBuffer, mWidth, mHeight);
 
   // AppendFrame() takes over image's reference
   mVideoSegment.AppendFrame(image.forget(), 1, gfxIntSize(mWidth, mHeight));
   mInput->AppendToTrack(TRACK_VIDEO, &mVideoSegment);
+  return true;
 }
 
 void
 DOMCameraPreview::Start()
 {
   NS_ASSERTION(NS_IsMainThread(), "Start() not called from main thread");
   if (mState != STOPPED) {
     return;
--- a/dom/camera/DOMCameraPreview.h
+++ b/dom/camera/DOMCameraPreview.h
@@ -25,17 +25,17 @@ typedef void (*FrameBuilder)(Image* aIma
  */
 class DOMCameraPreview : public nsDOMMediaStream
 {
 protected:
   enum { TRACK_VIDEO = 1 };
 
 public:
   DOMCameraPreview(ICameraControl* aCameraControl, uint32_t aWidth, uint32_t aHeight, uint32_t aFramesPerSecond = 30);
-  void ReceiveFrame(void* aBuffer, ImageFormat aFormat, FrameBuilder aBuilder);
+  bool ReceiveFrame(void* aBuffer, ImageFormat aFormat, FrameBuilder aBuilder);
   bool HaveEnoughBuffered();
 
   NS_IMETHODIMP
   GetCurrentTime(double* aCurrentTime) {
     return nsDOMMediaStream::GetCurrentTime(aCurrentTime);
   }
 
   void Start();   // called by the MediaStreamListener to start preview
--- a/dom/camera/GonkCameraControl.cpp
+++ b/dom/camera/GonkCameraControl.cpp
@@ -836,12 +836,14 @@ GonkFrameBuilder(Image* aImage, void* aB
   data.mGraphicBuffer = static_cast<layers::GraphicBufferLocked*>(aBuffer);
   data.mPicSize = gfxIntSize(aWidth, aHeight);
   videoImage->SetData(data);
 }
 
 void
 ReceiveFrame(nsGonkCameraControl* gc, layers::GraphicBufferLocked* aBuffer)
 {
-  gc->ReceiveFrame(aBuffer, ImageFormat::GONK_IO_SURFACE, GonkFrameBuilder);
+  if (!gc->ReceiveFrame(aBuffer, ImageFormat::GONK_IO_SURFACE, GonkFrameBuilder)) {
+    aBuffer->Unlock();
+  }
 }
 
 } // namespace mozilla
--- a/dom/camera/GonkNativeWindow.cpp
+++ b/dom/camera/GonkNativeWindow.cpp
@@ -19,25 +19,24 @@
 
 #include "base/basictypes.h"
 #include "GonkCameraHwMgr.h"
 #include "mozilla/layers/ShadowLayerUtilsGralloc.h"
 #include "mozilla/layers/ImageBridgeChild.h"
 #include "GonkNativeWindow.h"
 #include "nsDebug.h"
 
-// enable debug logging by setting to 1
-#define CNW_DEBUG 0
-#if CNW_DEBUG
-#define CNW_LOGD(...) {(void)printf_stderr(__VA_ARGS__);}
-#else
-#define CNW_LOGD(...) ((void)0)
-#endif
-
-#define CNW_LOGE(...) {(void)printf_stderr(__VA_ARGS__);}
+/**
+ * DOM_CAMERA_LOGI() is enabled in debug builds, and turned on by setting
+ * NSPR_LOG_MODULES=Camera:N environment variable, where N >= 3.
+ *
+ * CNW_LOGE() is always enabled.
+ */
+#define CNW_LOGD(...)   DOM_CAMERA_LOGI(__VA_ARGS__)
+#define CNW_LOGE(...)   {(void)printf_stderr(__VA_ARGS__);}
 
 using namespace android;
 using namespace mozilla::layers;
 
 GonkNativeWindow::GonkNativeWindow(GonkNativeWindowNewFrameCallback* aCallback)
   : mNewFrameCallback(aCallback)
 {
     GonkNativeWindow::init();
--- a/dom/camera/GonkNativeWindow.h
+++ b/dom/camera/GonkNativeWindow.h
@@ -31,29 +31,31 @@
 #include <ui/GraphicBuffer.h>
 #include <ui/Rect.h>
 #include <utils/String8.h>
 #include <utils/threads.h>
 
 #include "mozilla/layers/LayersSurfaces.h"
 #include "mozilla/layers/ImageBridgeChild.h"
 #include "GonkIOSurfaceImage.h"
+#include "CameraCommon.h"
 
 namespace android {
 
 // The user of GonkNativeWindow who wants to receive notification of
 // new frames should implement this interface.
 class GonkNativeWindowNewFrameCallback {
 public:
     virtual void OnNewFrame() = 0;
 };
 
 class GonkNativeWindow : public EGLNativeBase<ANativeWindow, GonkNativeWindow, RefBase>
 {
     typedef mozilla::layers::SurfaceDescriptor SurfaceDescriptor;
+
 public:
     enum { MIN_UNDEQUEUED_BUFFERS = 2 };
     enum { MIN_BUFFER_SLOTS = MIN_UNDEQUEUED_BUFFERS };
     enum { NUM_BUFFER_SLOTS = 32 };
 
     GonkNativeWindow();
     GonkNativeWindow(GonkNativeWindowNewFrameCallback* aCallback);
     ~GonkNativeWindow(); // this class cannot be overloaded
@@ -224,45 +226,52 @@ private:
     // mGeneration is the current generation of buffer slots
     uint32_t mGeneration;
 
     GonkNativeWindowNewFrameCallback* mNewFrameCallback;
 };
 
 
 // CameraGraphicBuffer maintains the buffer returned from GonkNativeWindow
-class CameraGraphicBuffer : public mozilla::layers::GraphicBufferLocked {
+class CameraGraphicBuffer : public mozilla::layers::GraphicBufferLocked
+{
     typedef mozilla::layers::SurfaceDescriptor SurfaceDescriptor;
+
 public:
     CameraGraphicBuffer(GonkNativeWindow* aNativeWindow,
                         uint32_t aIndex,
                         uint32_t aGeneration,
                         SurfaceDescriptor aBuffer)
         : GraphicBufferLocked(aBuffer)
-          , mNativeWindow(aNativeWindow)
-          , mIndex(aIndex)
-          , mGeneration(aGeneration)
-          , mLocked(true)
-    {}
+        , mNativeWindow(aNativeWindow)
+        , mIndex(aIndex)
+        , mGeneration(aGeneration)
+        , mLocked(true)
+    {
+        DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
+    }
 
-    virtual ~CameraGraphicBuffer() {}
+    virtual ~CameraGraphicBuffer()
+    {
+        DOM_CAMERA_LOGT("%s:%d : this=%p\n", __func__, __LINE__, this);
+    }
 
     // Unlock either returns the buffer to the native window or
     // destroys the buffer if the window is already released.
-    virtual void Unlock()  MOZ_OVERRIDE
+    virtual void Unlock() MOZ_OVERRIDE
     {
         if (mLocked) {
-            // The window might has been destroyed. The buffer is no longer
+            // The window might have been destroyed. The buffer is no longer
             // valid at that point.
             sp<GonkNativeWindow> window = mNativeWindow.promote();
             if (window.get() && window->returnBuffer(mIndex, mGeneration)) {
                 mLocked = false;
             } else {
                 // If the window doesn't exist any more, release the buffer
-                // by ourself.
+                // directly.
                 ImageBridgeChild *ibc = ImageBridgeChild::GetSingleton();
                 ibc->DeallocSurfaceDescriptorGralloc(mSurfaceDescriptor);
             }
         }
     }
 
 protected:
     wp<GonkNativeWindow> mNativeWindow;