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.
--- 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