Bug 1200326 - p5: Moved fallible code from MP4TrackDemuxer constructor to caller - r=jya, a=sylvestre
authorGerald Squelart <gsquelart@mozilla.com>
Tue, 29 Sep 2015 12:24:16 +0200
changeset 289409 ea98b3ea55a4e308da82644fe00ed21026851a22
parent 289408 5da94c05c7a97d4251cc96ea41dc83b1d4abb1ea
child 289410 9ac72490a8cc3c9b8da291740be69bb7777d4746
push id5111
push usercbook@mozilla.com
push dateTue, 29 Sep 2015 10:26:44 +0000
treeherdermozilla-beta@ea98b3ea55a4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjya, sylvestre
bugs1200326
milestone42.0
Bug 1200326 - p5: Moved fallible code from MP4TrackDemuxer constructor to caller - r=jya, a=sylvestre In MP4TrackDemuxer constructor, getting the track info and indices could potentially fail, triggering crashing assertions. The fallible work is now done before calling the constructor, and if it fails a nullptr is returned, which is correctly handled in MediaFormatReader. Also reordered some MP4TrackDemuxer members for more natural construction.
dom/media/fmp4/MP4Demuxer.cpp
dom/media/fmp4/MP4Demuxer.h
--- a/dom/media/fmp4/MP4Demuxer.cpp
+++ b/dom/media/fmp4/MP4Demuxer.cpp
@@ -4,37 +4,84 @@
  * 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 <algorithm>
 #include <limits>
 #include <stdint.h>
 
 #include "MP4Demuxer.h"
-#include "mp4_demuxer/Index.h"
 #include "mp4_demuxer/MoofParser.h"
 #include "mp4_demuxer/MP4Metadata.h"
 #include "mp4_demuxer/ResourceStream.h"
 #include "mp4_demuxer/BufferStream.h"
+#include "mp4_demuxer/Index.h"
 
 // Used for telemetry
 #include "mozilla/Telemetry.h"
 #include "mp4_demuxer/AnnexB.h"
 #include "mp4_demuxer/H264.h"
 
 PRLogModuleInfo* GetDemuxerLog() {
   static PRLogModuleInfo* log = nullptr;
   if (!log) {
     log = PR_NewLogModule("MP4Demuxer");
   }
   return log;
 }
 
 namespace mozilla {
 
+class MP4TrackDemuxer : public MediaTrackDemuxer
+{
+public:
+  MP4TrackDemuxer(MP4Demuxer* aParent,
+                  UniquePtr<TrackInfo>&& aInfo,
+                  const nsTArray<mp4_demuxer::Index::Indice>& indices);
+
+  virtual UniquePtr<TrackInfo> GetInfo() const override;
+
+  virtual nsRefPtr<SeekPromise> Seek(media::TimeUnit aTime) override;
+
+  virtual nsRefPtr<SamplesPromise> GetSamples(int32_t aNumSamples = 1) override;
+
+  virtual void Reset() override;
+
+  virtual nsresult GetNextRandomAccessPoint(media::TimeUnit* aTime) override;
+
+  nsRefPtr<SkipAccessPointPromise> SkipToNextRandomAccessPoint(media::TimeUnit aTimeThreshold) override;
+
+  virtual media::TimeIntervals GetBuffered() override;
+
+  virtual int64_t GetEvictionOffset(media::TimeUnit aTime) override;
+
+  virtual void BreakCycles() override;
+
+private:
+  friend class MP4Demuxer;
+  void NotifyDataArrived();
+  void UpdateSamples(nsTArray<nsRefPtr<MediaRawData>>& aSamples);
+  void EnsureUpToDateIndex();
+  void SetNextKeyFrameTime();
+  nsRefPtr<MP4Demuxer> mParent;
+  nsRefPtr<mp4_demuxer::ResourceStream> mStream;
+  UniquePtr<TrackInfo> mInfo;
+  // We do not actually need a monitor, however MoofParser (in mIndex) will
+  // assert if a monitor isn't held.
+  Monitor mMonitor;
+  nsRefPtr<mp4_demuxer::Index> mIndex;
+  UniquePtr<mp4_demuxer::SampleIterator> mIterator;
+  Maybe<media::TimeUnit> mNextKeyframeTime;
+  // Queued samples extracted by the demuxer, but not yet returned.
+  nsRefPtr<MediaRawData> mQueuedSample;
+  bool mNeedReIndex;
+  bool mNeedSPSForTelemetry;
+};
+
+
 // Returns true if no SPS was found and search for it should continue.
 bool
 AccumulateSPSTelemetry(const MediaByteBuffer* aExtradata)
 {
   mp4_demuxer::SPSData spsdata;
   if (mp4_demuxer::H264::DecodeSPSFromExtraData(aExtradata, spsdata)) {
     uint8_t constraints = (spsdata.constraint_set0_flag ? (1 << 0) : 0) |
                           (spsdata.constraint_set1_flag ? (1 << 1) : 0) |
@@ -131,18 +178,25 @@ MP4Demuxer::GetNumberTracks(TrackInfo::T
 }
 
 already_AddRefed<MediaTrackDemuxer>
 MP4Demuxer::GetTrackDemuxer(TrackInfo::TrackType aType, uint32_t aTrackNumber)
 {
   if (mMetadata->GetNumberTracks(aType) <= aTrackNumber) {
     return nullptr;
   }
-  nsRefPtr<MP4TrackDemuxer> e =
-    new MP4TrackDemuxer(this, aType, aTrackNumber);
+  UniquePtr<TrackInfo> info = mMetadata->GetTrackInfo(aType, aTrackNumber);
+  if (!info) {
+    return nullptr;
+  }
+  FallibleTArray<mp4_demuxer::Index::Indice> indices;
+  if (!mMetadata->ReadTrackIndex(indices, info->mTrackId)) {
+    return nullptr;
+  }
+  nsRefPtr<MP4TrackDemuxer> e = new MP4TrackDemuxer(this, Move(info), indices);
   mDemuxers.AppendElement(e);
 
   return e.forget();
 }
 
 bool
 MP4Demuxer::IsSeekable() const
 {
@@ -185,37 +239,30 @@ MP4Demuxer::GetCrypto()
 
   auto crypto = MakeUnique<EncryptionInfo>();
   crypto->AddInitData(NS_LITERAL_STRING("cenc"), Move(initData));
 
   return crypto;
 }
 
 MP4TrackDemuxer::MP4TrackDemuxer(MP4Demuxer* aParent,
-                                 TrackInfo::TrackType aType,
-                                 uint32_t aTrackNumber)
+                                 UniquePtr<TrackInfo>&& aInfo,
+                                 const nsTArray<mp4_demuxer::Index::Indice>& indices)
   : mParent(aParent)
   , mStream(new mp4_demuxer::ResourceStream(mParent->mResource))
-  , mNeedReIndex(true)
+  , mInfo(Move(aInfo))
   , mMonitor("MP4TrackDemuxer")
-{
-  mInfo = mParent->mMetadata->GetTrackInfo(aType, aTrackNumber);
-
-  MOZ_ASSERT(mInfo);
-
-  FallibleTArray<mp4_demuxer::Index::Indice> indices;
-  if (!mParent->mMetadata->ReadTrackIndex(indices, mInfo->mTrackId)) {
-    MOZ_ASSERT(false);
-  }
-  mIndex = new mp4_demuxer::Index(indices,
+  , mIndex(new mp4_demuxer::Index(indices,
                                   mStream,
                                   mInfo->mTrackId,
                                   mInfo->IsAudio(),
-                                  &mMonitor);
-  mIterator = MakeUnique<mp4_demuxer::SampleIterator>(mIndex);
+                                  &mMonitor))
+  , mIterator(MakeUnique<mp4_demuxer::SampleIterator>(mIndex))
+  , mNeedReIndex(true)
+{
   EnsureUpToDateIndex(); // Force update of index
 
   // Collect telemetry from h264 AVCC SPS.
   if (mInfo->GetAsVideoInfo() &&
       (mInfo->mMimeType.EqualsLiteral("video/mp4") ||
        mInfo->mMimeType.EqualsLiteral("video/avc"))) {
     mNeedSPSForTelemetry =
       AccumulateSPSTelemetry(mInfo->GetAsVideoInfo()->mExtraData);
--- a/dom/media/fmp4/MP4Demuxer.h
+++ b/dom/media/fmp4/MP4Demuxer.h
@@ -8,17 +8,16 @@
 #define MP4Demuxer_h_
 
 #include "mozilla/Maybe.h"
 #include "mozilla/Monitor.h"
 #include "MediaDataDemuxer.h"
 #include "MediaResource.h"
 
 namespace mp4_demuxer {
-class Index;
 class MP4Metadata;
 class ResourceStream;
 class SampleIterator;
 } // namespace mp4_demuxer
 
 namespace mozilla {
 
 class MP4TrackDemuxer;
@@ -51,58 +50,11 @@ private:
   friend class MP4TrackDemuxer;
   nsRefPtr<MediaResource> mResource;
   nsRefPtr<mp4_demuxer::ResourceStream> mStream;
   nsRefPtr<MediaByteBuffer> mInitData;
   UniquePtr<mp4_demuxer::MP4Metadata> mMetadata;
   nsTArray<nsRefPtr<MP4TrackDemuxer>> mDemuxers;
 };
 
-class MP4TrackDemuxer : public MediaTrackDemuxer
-{
-public:
-  MP4TrackDemuxer(MP4Demuxer* aParent,
-                  TrackInfo::TrackType aType,
-                  uint32_t aTrackNumber);
-
-  virtual UniquePtr<TrackInfo> GetInfo() const override;
-
-  virtual nsRefPtr<SeekPromise> Seek(media::TimeUnit aTime) override;
-
-  virtual nsRefPtr<SamplesPromise> GetSamples(int32_t aNumSamples = 1) override;
-
-  virtual void Reset() override;
-
-  virtual nsresult GetNextRandomAccessPoint(media::TimeUnit* aTime) override;
-
-  nsRefPtr<SkipAccessPointPromise> SkipToNextRandomAccessPoint(media::TimeUnit aTimeThreshold) override;
-
-  virtual media::TimeIntervals GetBuffered() override;
-
-  virtual int64_t GetEvictionOffset(media::TimeUnit aTime) override;
-
-  virtual void BreakCycles() override;
-
-private:
-  friend class MP4Demuxer;
-  void NotifyDataArrived();
-  void UpdateSamples(nsTArray<nsRefPtr<MediaRawData>>& aSamples);
-  void EnsureUpToDateIndex();
-  void SetNextKeyFrameTime();
-  nsRefPtr<MP4Demuxer> mParent;
-  nsRefPtr<mp4_demuxer::Index> mIndex;
-  UniquePtr<mp4_demuxer::SampleIterator> mIterator;
-  UniquePtr<TrackInfo> mInfo;
-  nsRefPtr<mp4_demuxer::ResourceStream> mStream;
-  Maybe<media::TimeUnit> mNextKeyframeTime;
-  // Queued samples extracted by the demuxer, but not yet returned.
-  nsRefPtr<MediaRawData> mQueuedSample;
-  bool mNeedReIndex;
-  bool mNeedSPSForTelemetry;
-
-  // We do not actually need a monitor, however MoofParser will assert
-  // if a monitor isn't held.
-  Monitor mMonitor;
-};
-
 } // namespace mozilla
 
 #endif