Merge m-c to inbound.
authorRyan VanderMeulen <ryanvm@gmail.com>
Fri, 17 May 2013 09:08:44 -0400
changeset 143724 32191193cbb220fa548723633375f61deb61c3f9
parent 143723 a7bd66bbb68b7da84a71cd3c8dacf30573b718ac (current diff)
parent 143669 cb242a1cccb23effd29535aaca919ecd4ad4c05c (diff)
child 143725 c66d8ea1b2f195ddb9c7810e15f073eea98dc78e
push id2697
push userbbajaj@mozilla.com
push dateMon, 05 Aug 2013 18:49:53 +0000
treeherdermozilla-beta@dfec938c7b63 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone24.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
Merge m-c to inbound.
--- a/content/media/omx/OmxDecoder.cpp
+++ b/content/media/omx/OmxDecoder.cpp
@@ -3,16 +3,17 @@
 /* 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 <unistd.h>
 #include <fcntl.h>
 
 #include "base/basictypes.h"
 #include <cutils/properties.h>
+#include <stagefright/foundation/AMessage.h>
 #include <stagefright/MediaExtractor.h>
 #include <stagefright/MetaData.h>
 #include <stagefright/OMXClient.h>
 #include <stagefright/OMXCodec.h>
 #include <OMX.h>
 
 #include "mozilla/Preferences.h"
 #include "mozilla/Types.h"
@@ -53,17 +54,21 @@ VideoGraphicBuffer::~VideoGraphicBuffer(
   }
 }
 
 void
 VideoGraphicBuffer::Unlock()
 {
   android::sp<android::OmxDecoder> omxDecoder = mOmxDecoder.promote();
   if (omxDecoder.get()) {
-    omxDecoder->ReleaseVideoBuffer(mMediaBuffer);
+    // Post kNotifyPostReleaseVideoBuffer message to OmxDecoder via ALooper.
+    // The message is delivered to OmxDecoder on ALooper thread.
+    // MediaBuffer::release() could take a very long time.
+    // PostReleaseVideoBuffer() prevents long time locking.
+    omxDecoder->PostReleaseVideoBuffer(mMediaBuffer);
   } else {
     NS_WARNING("OmxDecoder is not present");
     if (mMediaBuffer) {
       mMediaBuffer->release();
     }
   }
   mMediaBuffer = nullptr;
 }
@@ -140,30 +145,49 @@ OmxDecoder::OmxDecoder(MediaResource *aR
   mAudioSampleRate(-1),
   mDurationUs(-1),
   mVideoBuffer(nullptr),
   mAudioBuffer(nullptr),
   mIsVideoSeeking(false),
   mAudioMetadataRead(false),
   mPaused(false)
 {
+  mLooper = new ALooper;
+  mLooper->setName("OmxDecoder");
+
+  mReflector = new AHandlerReflector<OmxDecoder>(this);
+  // Register AMessage handler to ALooper.
+  mLooper->registerHandler(mReflector);
+  // Start ALooper thread.
+  mLooper->start();
 }
 
 OmxDecoder::~OmxDecoder()
 {
+  {
+    // Free all pending video buffers.
+    Mutex::Autolock autoLock(mSeekLock);
+    ReleaseAllPendingVideoBuffersLocked();
+  }
+
   ReleaseVideoBuffer();
   ReleaseAudioBuffer();
 
   if (mVideoSource.get()) {
     mVideoSource->stop();
   }
 
   if (mAudioSource.get()) {
     mAudioSource->stop();
   }
+
+  // unregister AMessage handler from ALooper.
+  mLooper->unregisterHandler(mReflector->id());
+  // Stop ALooper thread.
+  mLooper->stop();
 }
 
 class AutoStopMediaSource {
   sp<MediaSource> mMediaSource;
 public:
   AutoStopMediaSource(const sp<MediaSource>& aMediaSource) : mMediaSource(aMediaSource) {
   }
 
@@ -669,42 +693,16 @@ bool OmxDecoder::ReadAudio(AudioFrame *a
   }
   else if (err != OK && err != -ETIMEDOUT) {
     return false;
   }
 
   return true;
 }
 
-bool OmxDecoder::ReleaseVideoBuffer(MediaBuffer *aBuffer)
-{
-  Mutex::Autolock autoLock(mSeekLock);
-
-  if (!aBuffer) {
-    return false;
-  }
-
-  if (mIsVideoSeeking == true) {
-    mPendingVideoBuffers.push(aBuffer);
-  } else {
-    aBuffer->release();
-  }
-  return true;
-}
-
-void OmxDecoder::ReleaseAllPendingVideoBuffersLocked()
-{
-  int size = mPendingVideoBuffers.size();
-  for (int i = 0; i < size; i++) {
-    MediaBuffer *buffer = mPendingVideoBuffers[i];
-    buffer->release();
-  }
-  mPendingVideoBuffers.clear();
-}
-
 nsresult OmxDecoder::Play() {
   if (!mPaused) {
     return NS_OK;
   }
   if (mVideoSource.get() && mVideoSource->start() != OK) {
     return NS_ERROR_UNEXPECTED;
   }
 
@@ -724,8 +722,56 @@ void OmxDecoder::Pause() {
   }
 
   if (mAudioSource.get()) {
     mAudioSource->pause();
   }
   mPaused = true;
 }
 
+// Called on ALooper thread.
+void OmxDecoder::onMessageReceived(const sp<AMessage> &msg)
+{
+  Mutex::Autolock autoLock(mSeekLock);
+
+  // Free pending video buffers when OmxDecoder is not seeking video.
+  // If OmxDecoder is in seeking video, the buffers are freed on seek exit. 
+  if (mIsVideoSeeking != true) {
+    ReleaseAllPendingVideoBuffersLocked();
+  }
+}
+
+void OmxDecoder::PostReleaseVideoBuffer(MediaBuffer *aBuffer)
+{
+  {
+    Mutex::Autolock autoLock(mPendingVideoBuffersLock);
+    mPendingVideoBuffers.push(aBuffer);
+  }
+
+  sp<AMessage> notify =
+            new AMessage(kNotifyPostReleaseVideoBuffer, mReflector->id());
+  // post AMessage to OmxDecoder via ALooper.
+  notify->post();
+}
+
+void OmxDecoder::ReleaseAllPendingVideoBuffersLocked()
+{
+  Vector<MediaBuffer *> releasingVideoBuffers;
+  {
+    Mutex::Autolock autoLock(mPendingVideoBuffersLock);
+
+    int size = mPendingVideoBuffers.size();
+    for (int i = 0; i < size; i++) {
+      MediaBuffer *buffer = mPendingVideoBuffers[i];
+      releasingVideoBuffers.push(buffer);
+    }
+    mPendingVideoBuffers.clear();
+  }
+  // Free all pending video buffers without holding mPendingVideoBuffersLock.
+  int size = releasingVideoBuffers.size();
+  for (int i = 0; i < size; i++) {
+    MediaBuffer *buffer;
+    buffer = releasingVideoBuffers[i];
+    buffer->release();
+  }
+  releasingVideoBuffers.clear();
+}
+
--- a/content/media/omx/OmxDecoder.h
+++ b/content/media/omx/OmxDecoder.h
@@ -1,8 +1,12 @@
+#include <stagefright/foundation/ABase.h>
+#include <stagefright/foundation/AHandlerReflector.h>
+#include <stagefright/foundation/ALooper.h>
+#include <stagefright/MediaSource.h>
 #include <stagefright/DataSource.h>
 #include <stagefright/MediaSource.h>
 #include <utils/RefBase.h>
 
 #include "GonkNativeWindow.h"
 #include "GonkNativeWindowClient.h"
 #include "GonkIOSurfaceImage.h"
 #include "MPAPI.h"
@@ -74,16 +78,20 @@ class OmxDecoder : public RefBase {
   typedef mozilla::AbstractMediaDecoder AbstractMediaDecoder;
 
   enum {
     kPreferSoftwareCodecs = 1,
     kSoftwareCodecsOnly = 8,
     kHardwareCodecsOnly = 16,
   };
 
+  enum {
+    kNotifyPostReleaseVideoBuffer = 'noti'
+  };
+
   AbstractMediaDecoder *mDecoder;
   nsRefPtr<MediaResource> mResource;
   sp<GonkNativeWindow> mNativeWindow;
   sp<GonkNativeWindowClient> mNativeWindowClient;
   sp<MediaSource> mVideoTrack;
   sp<MediaSource> mVideoSource;
   sp<MediaSource> mAudioTrack;
   sp<MediaSource> mAudioSource;
@@ -104,24 +112,37 @@ class OmxDecoder : public RefBase {
   MediaBuffer *mVideoBuffer;
   MediaBuffer *mAudioBuffer;
 
   // Hold video's MediaBuffers that are released during video seeking.
   // The holded MediaBuffers are released soon after seek completion.
   // OMXCodec does not accept MediaBuffer during seeking. If MediaBuffer is
   //  returned to OMXCodec during seeking, OMXCodec calls assert.
   Vector<MediaBuffer *> mPendingVideoBuffers;
+  // The lock protects mPendingVideoBuffers.
+  Mutex mPendingVideoBuffersLock;
+
   // Show if OMXCodec is seeking.
   bool mIsVideoSeeking;
   // The lock protects video MediaBuffer release()'s pending operations called
   //  from multiple threads. The pending operations happen only during video
   //  seeking. Holding mSeekLock long time could affect to video rendering.
   // Holding time should be minimum.
   Mutex mSeekLock;
 
+  // ALooper is a message loop used in stagefright.
+  // It creates a thread for messages and handles messages in the thread.
+  // ALooper is a clone of Looper in android Java.
+  // http://developer.android.com/reference/android/os/Looper.html
+  sp<ALooper> mLooper;
+  // deliver a message to a wrapped object(OmxDecoder).
+  // AHandlerReflector is similar to Handler in android Java.
+  // http://developer.android.com/reference/android/os/Handler.html
+  sp<AHandlerReflector<OmxDecoder> > mReflector;
+
   // 'true' if a read from the audio stream was done while reading the metadata
   bool mAudioMetadataRead;
 
   void ReleaseVideoBuffer();
   void ReleaseAudioBuffer();
   // Call with mSeekLock held.
   void ReleaseAllPendingVideoBuffersLocked();
 
@@ -170,19 +191,24 @@ public:
                  bool aKeyframeSkip = false,
                  bool aDoSeek = false);
   bool ReadAudio(AudioFrame *aFrame, int64_t aSeekTimeUs);
 
   MediaResource *GetResource() {
     return mResource;
   }
 
-  bool ReleaseVideoBuffer(MediaBuffer *aBuffer);
-
   //Change decoder into a playing state
   nsresult Play();
 
   //Change decoder into a paused state
   void Pause();
+
+  // Post kNotifyPostReleaseVideoBuffer message to OmxDecoder via ALooper.
+  void PostReleaseVideoBuffer(MediaBuffer *aBuffer);
+  // Receive a message from AHandlerReflector.
+  // Called on ALooper thread.
+  void onMessageReceived(const sp<AMessage> &msg);
+
 };
 
 }
 
--- a/security/manager/ssl/src/JARSignatureVerification.cpp
+++ b/security/manager/ssl/src/JARSignatureVerification.cpp
@@ -196,24 +196,41 @@ VerifyEntryContentDigest(nsIZipReader * 
 
 // On input, nextLineStart is the start of the current line. On output,
 // nextLineStart is the start of the next line.
 nsresult
 ReadLine(/*in/out*/ const char* & nextLineStart, /*out*/ nsCString & line,
          bool allowContinuations = true)
 {
   line.Truncate();
+  size_t previousLength = 0;
+  size_t currentLength = 0;
   for (;;) {
     const char* eol = PL_strpbrk(nextLineStart, "\r\n");
 
     if (!eol) { // Reached end of file before newline
       eol = nextLineStart + strlen(nextLineStart);
     }
 
+    previousLength = currentLength;
     line.Append(nextLineStart, eol - nextLineStart);
+    currentLength = line.Length();
+
+    // The spec says "No line may be longer than 72 bytes (not characters)"
+    // in its UTF8-encoded form.
+    static const size_t lineLimit = 72;
+    if (currentLength - previousLength > lineLimit) {
+      return NS_ERROR_SIGNED_JAR_MANIFEST_INVALID;
+    }
+
+    // The spec says: "Implementations should support 65535-byte
+    // (not character) header values..."
+    if (currentLength > 65535) {
+      return NS_ERROR_SIGNED_JAR_MANIFEST_INVALID;
+    }
 
     if (*eol == '\r') {
       ++eol;
     }
     if (*eol == '\n') {
       ++eol;
     }
 
@@ -240,24 +257,16 @@ ReadLine(/*in/out*/ const char* & nextLi
 #define JAR_MF_HEADER (const char*)"Manifest-Version: 1.0"
 #define JAR_SF_HEADER (const char*)"Signature-Version: 1.0"
 
 nsresult
 ParseAttribute(const nsAutoCString & curLine,
                /*out*/ nsAutoCString & attrName,
                /*out*/ nsAutoCString & attrValue)
 {
-  nsAutoCString::size_type len = curLine.Length();
-  if (len > 72) {
-    // The spec says "No line may be longer than 72 bytes (not characters)"
-    // in its UTF8-encoded form. This check also ensures that len < INT32_MAX,
-    // which is required below.
-    return NS_ERROR_SIGNED_JAR_MANIFEST_INVALID;
-  }
-
   // Find the colon that separates the name from the value.
   int32_t colonPos = curLine.FindChar(':');
   if (colonPos == kNotFound) {
     return NS_ERROR_SIGNED_JAR_MANIFEST_INVALID;
   }
 
   // set attrName to the name, skipping spaces between the name and colon
   int32_t nameEnd = colonPos;
--- a/toolkit/library/Makefile.in
+++ b/toolkit/library/Makefile.in
@@ -482,16 +482,17 @@ OS_LIBS += \
   -lhardware \
   -lutils \
   -lcutils \
   -lsysutils \
   -lcamera_client \
   -lsensorservice \
   -ldbus \
   -lstagefright \
+  -lstagefright_foundation \
   -lstagefright_omx \
   -lbinder \
   -lgui \
   $(NULL)
 endif
 
 ifdef MOZ_WMF
 OS_LIBS += $(call EXPAND_LIBNAME,mfuuid wmcodecdspuuid strmiids)