Bug 1139779: Part2. Use display dimension from SPS NAL. r=rillian a=lsblakk
authorJean-Yves Avenard <jyavenard@mozilla.com>
Tue, 10 Mar 2015 21:19:41 +1100
changeset 248170 8d8cd865b4d074d7b8ba8b4d97778faa1c88b32e
parent 248169 2802cf435885526ed59b1dc5bcc7222ce5a43285
child 248171 20b06ff42ed20303b113094ec95cd87a0f61f9e8
push id7776
push usercpearce@mozilla.com
push dateWed, 18 Mar 2015 03:12:44 +0000
treeherdermozilla-aurora@4acd7286be9e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrillian, lsblakk
bugs1139779
milestone38.0a2
Bug 1139779: Part2. Use display dimension from SPS NAL. r=rillian a=lsblakk
dom/media/fmp4/apple/AppleVDADecoder.cpp
dom/media/fmp4/apple/AppleVDADecoder.h
dom/media/fmp4/apple/AppleVTDecoder.cpp
--- a/dom/media/fmp4/apple/AppleVDADecoder.cpp
+++ b/dom/media/fmp4/apple/AppleVDADecoder.cpp
@@ -15,62 +15,68 @@
 #include "MediaData.h"
 #include "MacIOSurfaceImage.h"
 #include "mozilla/ArrayUtils.h"
 #include "nsAutoPtr.h"
 #include "nsCocoaFeatures.h"
 #include "nsThreadUtils.h"
 #include "prlog.h"
 #include "VideoUtils.h"
+#include <algorithm>
 
 #ifdef PR_LOGGING
 PRLogModuleInfo* GetAppleMediaLog();
 #define LOG(...) PR_LOG(GetAppleMediaLog(), PR_LOG_DEBUG, (__VA_ARGS__))
 //#define LOG_MEDIA_SHA1
 #else
 #define LOG(...)
 #endif
 
 namespace mozilla {
 
 AppleVDADecoder::AppleVDADecoder(const mp4_demuxer::VideoDecoderConfig& aConfig,
                                FlushableMediaTaskQueue* aVideoTaskQueue,
                                MediaDataDecoderCallback* aCallback,
                                layers::ImageContainer* aImageContainer)
-  : mConfig(aConfig)
-  , mTaskQueue(aVideoTaskQueue)
+  : mTaskQueue(aVideoTaskQueue)
   , mCallback(aCallback)
   , mImageContainer(aImageContainer)
   , mDecoder(nullptr)
   , mIs106(!nsCocoaFeatures::OnLionOrLater())
 {
   MOZ_COUNT_CTOR(AppleVDADecoder);
   // TODO: Verify aConfig.mime_type.
 
   // Retrieve video dimensions from H264 SPS NAL.
-  mPictureWidth = mConfig.image_width;
-  mPictureHeight = mConfig.image_height;
+  mPictureWidth = aConfig.image_width;
+  mPictureHeight = aConfig.image_height;
+  mDisplayWidth = aConfig.display_width;
+  mDisplayHeight = aConfig.display_height;
+  mExtraData = aConfig.extra_data;
   mMaxRefFrames = 4;
   mp4_demuxer::SPSData spsdata;
-  if (mp4_demuxer::H264::DecodeSPSFromExtraData(mConfig.extra_data, spsdata) &&
+  if (mp4_demuxer::H264::DecodeSPSFromExtraData(mExtraData, spsdata) &&
       spsdata.pic_width && spsdata.pic_height) {
     mPictureWidth = spsdata.pic_width;
     mPictureHeight = spsdata.pic_height;
+    mDisplayWidth = spsdata.display_width;
+    mDisplayHeight = spsdata.display_height;
     // max_num_ref_frames determines the size of the sliding window
     // we need to queue that many frames in order to guarantee proper
     // pts frames ordering. Use a minimum of 4 to ensure proper playback of
     // non compliant videos.
     mMaxRefFrames =
-      (spsdata.max_num_ref_frames + 1) > mMaxRefFrames ?
-        spsdata.max_num_ref_frames + 1 : mMaxRefFrames;
+      std::min(std::max(mMaxRefFrames, spsdata.max_num_ref_frames + 1), 16u);
   }
 
-  LOG("Creating AppleVDADecoder for %dx%d h.264 video",
+  LOG("Creating AppleVDADecoder for %dx%d (%dx%d) h.264 video",
       mPictureWidth,
-      mPictureHeight
+      mPictureHeight,
+      mDisplayWidth,
+      mDisplayHeight
      );
 }
 
 AppleVDADecoder::~AppleVDADecoder()
 {
   MOZ_COUNT_DTOR(AppleVDADecoder);
 }
 
@@ -252,22 +258,22 @@ AppleVDADecoder::OutputFrame(CVPixelBuff
     aFrameRef->composition_timestamp,
     aFrameRef->duration,
     aFrameRef->is_sync_point ? " keyframe" : ""
   );
 
   nsRefPtr<MacIOSurface> macSurface = new MacIOSurface(surface);
   // Bounds.
   VideoInfo info;
-  info.mDisplay = nsIntSize(mConfig.display_width, mConfig.display_height);
+  info.mDisplay = nsIntSize(mDisplayWidth, mDisplayHeight);
   info.mHasVideo = true;
   gfx::IntRect visible = gfx::IntRect(0,
                                       0,
-                                      mConfig.display_width,
-                                      mConfig.display_height);
+                                      mPictureWidth,
+                                      mPictureHeight);
 
   nsRefPtr<layers::Image> image =
     mImageContainer->CreateImage(ImageFormat::MAC_IOSURFACE);
   layers::MacIOSurfaceImage* videoImage =
     static_cast<layers::MacIOSurfaceImage*>(image.get());
   videoImage->SetSurface(macSurface);
 
   nsRefPtr<VideoData> data;
@@ -405,18 +411,18 @@ AppleVDADecoder::InitializeSession()
   }
 
   return NS_OK;
 }
 
 CFDictionaryRef
 AppleVDADecoder::CreateDecoderSpecification()
 {
-  const uint8_t* extradata = mConfig.extra_data->Elements();
-  int extrasize = mConfig.extra_data->Length();
+  const uint8_t* extradata = mExtraData->Elements();
+  int extrasize = mExtraData->Length();
 
   OSType format = 'avc1';
   AutoCFRelease<CFNumberRef> avc_width  =
     CFNumberCreate(kCFAllocatorDefault,
                    kCFNumberSInt32Type,
                    &mPictureWidth);
   AutoCFRelease<CFNumberRef> avc_height =
     CFNumberCreate(kCFAllocatorDefault,
--- a/dom/media/fmp4/apple/AppleVDADecoder.h
+++ b/dom/media/fmp4/apple/AppleVDADecoder.h
@@ -80,23 +80,25 @@ public:
                        nsAutoPtr<AppleFrameRef> aFrameRef);
 
  protected:
   AppleFrameRef* CreateAppleFrameRef(const mp4_demuxer::MP4Sample* aSample);
   void DrainReorderedFrames();
   void ClearReorderedFrames();
   CFDictionaryRef CreateOutputConfiguration();
 
-  const mp4_demuxer::VideoDecoderConfig& mConfig;
+  nsRefPtr<mp4_demuxer::ByteBuffer> mExtraData;
   nsRefPtr<FlushableMediaTaskQueue> mTaskQueue;
   MediaDataDecoderCallback* mCallback;
   nsRefPtr<layers::ImageContainer> mImageContainer;
   ReorderQueue mReorderQueue;
   uint32_t mPictureWidth;
   uint32_t mPictureHeight;
+  uint32_t mDisplayWidth;
+  uint32_t mDisplayHeight;
   uint32_t mMaxRefFrames;
 
 private:
   VDADecoder mDecoder;
   bool mIs106;
 
   // Method to pass a frame to VideoToolbox for decoding.
   nsresult SubmitFrame(mp4_demuxer::MP4Sample* aSample);
--- a/dom/media/fmp4/apple/AppleVTDecoder.cpp
+++ b/dom/media/fmp4/apple/AppleVTDecoder.cpp
@@ -40,18 +40,18 @@ AppleVTDecoder::AppleVTDecoder(const mp4
                                layers::ImageContainer* aImageContainer)
   : AppleVDADecoder(aConfig, aVideoTaskQueue, aCallback, aImageContainer)
   , mFormat(nullptr)
   , mSession(nullptr)
 {
   MOZ_COUNT_CTOR(AppleVTDecoder);
   // TODO: Verify aConfig.mime_type.
   LOG("Creating AppleVTDecoder for %dx%d h.264 video",
-      mConfig.image_width,
-      mConfig.image_height
+      mDisplayWidth,
+      mDisplayHeight
      );
 }
 
 AppleVTDecoder::~AppleVTDecoder()
 {
   MOZ_COUNT_DTOR(AppleVTDecoder);
 }
 
@@ -256,25 +256,25 @@ AppleVTDecoder::SubmitFrame(mp4_demuxer:
 
 nsresult
 AppleVTDecoder::InitializeSession()
 {
   OSStatus rv;
 
 #ifdef LOG_MEDIA_SHA1
   SHA1Sum avc_hash;
-  avc_hash.update(mConfig.extra_data->Elements(), mConfig.extra_data->Length());
+  avc_hash.update(mExtraData->Elements(),mExtraData->Length());
   uint8_t digest_buf[SHA1Sum::kHashSize];
   avc_hash.finish(digest_buf);
   nsAutoCString avc_digest;
   for (size_t i = 0; i < sizeof(digest_buf); i++) {
     avc_digest.AppendPrintf("%02x", digest_buf[i]);
   }
   LOG("AVCDecoderConfig %ld bytes sha1 %s",
-      mConfig.extra_data->Length(), avc_digest.get());
+      mExtraData->Length(), avc_digest.get());
 #endif // LOG_MEDIA_SHA1
 
   AutoCFRelease<CFDictionaryRef> extensions = CreateDecoderExtensions();
 
   rv = CMVideoFormatDescriptionCreate(kCFAllocatorDefault,
                                       kCMVideoCodecType_H264,
                                       mPictureWidth,
                                       mPictureHeight,
@@ -322,18 +322,18 @@ AppleVTDecoder::InitializeSession()
   return NS_OK;
 }
 
 CFDictionaryRef
 AppleVTDecoder::CreateDecoderExtensions()
 {
   AutoCFRelease<CFDataRef> avc_data =
     CFDataCreate(kCFAllocatorDefault,
-                 mConfig.extra_data->Elements(),
-                 mConfig.extra_data->Length());
+                 mExtraData->Elements(),
+                 mExtraData->Length());
 
   const void* atomsKey[] = { CFSTR("avcC") };
   const void* atomsValue[] = { avc_data };
   static_assert(ArrayLength(atomsKey) == ArrayLength(atomsValue),
                 "Non matching keys/values array size");
 
   AutoCFRelease<CFDictionaryRef> atoms =
     CFDictionaryCreate(kCFAllocatorDefault,