Backed out changeset 1704ea727e81 (bug 1163486) for at least b2g bustage

This commit is contained in:
Carsten "Tomcat" Book 2015-07-21 08:42:54 +02:00
Родитель 79fe86d82b
Коммит de3872af29
25 изменённых файлов: 1877 добавлений и 22 удалений

Просмотреть файл

@ -66,6 +66,7 @@
#include "AppleMP3Reader.h"
#endif
#ifdef MOZ_FMP4
#include "MP4Reader.h"
#include "MP4Decoder.h"
#include "MP4Demuxer.h"
#endif
@ -653,7 +654,9 @@ MediaDecoderReader* DecoderTraits::CreateReader(const nsACString& aType, Abstrac
}
#ifdef MOZ_FMP4
if (IsMP4SupportedType(aType)) {
decoderReader = new MediaFormatReader(aDecoder, new MP4Demuxer(aDecoder->GetResource()));
decoderReader = Preferences::GetBool("media.format-reader.mp4", true) ?
static_cast<MediaDecoderReader*>(new MediaFormatReader(aDecoder, new MP4Demuxer(aDecoder->GetResource()))) :
static_cast<MediaDecoderReader*>(new MP4Reader(aDecoder));
} else
#endif
if (IsMP3SupportedType(aType)) {

Просмотреть файл

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "MP4Decoder.h"
#include "MP4Reader.h"
#include "MediaDecoderStateMachine.h"
#include "MediaFormatReader.h"
#include "MP4Demuxer.h"
@ -41,7 +42,11 @@ MP4Decoder::MP4Decoder()
MediaDecoderStateMachine* MP4Decoder::CreateStateMachine()
{
MediaDecoderReader* reader = new MediaFormatReader(this, new MP4Demuxer(GetResource()));
bool useFormatDecoder =
Preferences::GetBool("media.format-reader.mp4", true);
nsRefPtr<MediaDecoderReader> reader = useFormatDecoder ?
static_cast<MediaDecoderReader*>(new MediaFormatReader(this, new MP4Demuxer(GetResource()))) :
static_cast<MediaDecoderReader*>(new MP4Reader(this));
return new MediaDecoderStateMachine(this, reader);
}
@ -53,8 +58,8 @@ MP4Decoder::SetCDMProxy(CDMProxy* aProxy)
nsresult rv = MediaDecoder::SetCDMProxy(aProxy);
NS_ENSURE_SUCCESS(rv, rv);
if (aProxy) {
// The MediaFormatReader can't decrypt EME content until it has a CDMProxy,
// and the CDMProxy knows the capabilities of the CDM. The MediaFormatReader
// The MP4Reader can't decrypt EME content until it has a CDMProxy,
// and the CDMProxy knows the capabilities of the CDM. The MP4Reader
// remains in "waiting for resources" state until then.
CDMCaps::AutoLock caps(aProxy->Capabilites());
nsCOMPtr<nsIRunnable> task(

Просмотреть файл

@ -20,14 +20,6 @@
#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 {
// Returns true if no SPS was found and search for it should continue.

1136
dom/media/fmp4/MP4Reader.cpp Normal file

Разница между файлами не показана из-за своего большого размера Загрузить разницу

280
dom/media/fmp4/MP4Reader.h Normal file
Просмотреть файл

@ -0,0 +1,280 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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/. */
#if !defined(MP4Reader_h_)
#define MP4Reader_h_
#include "mozilla/Monitor.h"
#include "mozilla/TaskQueue.h"
#include "MediaDecoderReader.h"
#include "nsAutoPtr.h"
#include "PlatformDecoderModule.h"
#include "mp4_demuxer/mp4_demuxer.h"
#include "demuxer/TrackDemuxer.h"
#include <deque>
namespace mozilla {
typedef std::deque<nsRefPtr<MediaRawData>> MediaSampleQueue;
class MP4Stream;
class MP4Reader final : public MediaDecoderReader
{
typedef TrackInfo::TrackType TrackType;
public:
explicit MP4Reader(AbstractMediaDecoder* aDecoder, TaskQueue* aBorrowedTaskQueue = nullptr);
virtual ~MP4Reader();
virtual nsresult Init(MediaDecoderReader* aCloneDonor) override;
virtual size_t SizeOfVideoQueueInFrames() override;
virtual size_t SizeOfAudioQueueInFrames() override;
virtual nsRefPtr<VideoDataPromise>
RequestVideoData(bool aSkipToNextKeyframe, int64_t aTimeThreshold, bool aForceDecodeAhead) override;
virtual nsRefPtr<AudioDataPromise> RequestAudioData() override;
virtual bool HasAudio() override;
virtual bool HasVideo() override;
virtual nsresult ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags) override;
virtual void ReadUpdatedMetadata(MediaInfo* aInfo) override;
virtual nsRefPtr<SeekPromise>
Seek(int64_t aTime, int64_t aEndTime) override;
virtual bool IsMediaSeekable() override;
virtual int64_t GetEvictionOffset(double aTime) override;
protected:
virtual void NotifyDataArrivedInternal(uint32_t aLength, int64_t aOffset) override;
public:
virtual media::TimeIntervals GetBuffered() override;
// For Media Resource Management
virtual void SetIdle() override;
virtual void ReleaseMediaResources() override;
virtual void SetSharedDecoderManager(SharedDecoderManager* aManager)
override;
virtual nsresult ResetDecode() override;
virtual nsRefPtr<ShutdownPromise> Shutdown() override;
virtual bool IsAsync() const override { return true; }
virtual bool VideoIsHardwareAccelerated() const override;
virtual void DisableHardwareAcceleration() override;
private:
bool InitDemuxer();
void ReturnOutput(MediaData* aData, TrackType aTrack);
bool EnsureDecodersSetup();
// Sends input to decoder for aTrack, and output to the state machine,
// if necessary.
void Update(TrackType aTrack);
// Enqueues a task to call Update(aTrack) on the decoder task queue.
// Lock for corresponding track must be held.
void ScheduleUpdate(TrackType aTrack);
void ExtractCryptoInitData(nsTArray<uint8_t>& aInitData);
// Initializes mLayersBackendType if possible.
void InitLayersBackendType();
// Blocks until the demuxer produces an sample of specified type.
// Returns nullptr on error on EOS. Caller must delete sample.
already_AddRefed<MediaRawData> PopSample(TrackType aTrack);
already_AddRefed<MediaRawData> PopSampleLocked(TrackType aTrack);
bool SkipVideoDemuxToNextKeyFrame(int64_t aTimeThreshold, uint32_t& parsed);
// DecoderCallback proxies the MediaDataDecoderCallback calls to these
// functions.
void Output(TrackType aType, MediaData* aSample);
void InputExhausted(TrackType aTrack);
void Error(TrackType aTrack);
void Flush(TrackType aTrack);
void DrainComplete(TrackType aTrack);
void UpdateIndex();
bool IsSupportedAudioMimeType(const nsACString& aMimeType);
bool IsSupportedVideoMimeType(const nsACString& aMimeType);
virtual bool IsWaitingOnCDMResource() override;
mp4_demuxer::Microseconds GetNextKeyframeTime();
bool ShouldSkip(bool aSkipToNextKeyframe, int64_t aTimeThreshold);
size_t SizeOfQueue(TrackType aTrack);
nsRefPtr<MP4Stream> mStream;
nsRefPtr<mp4_demuxer::MP4Demuxer> mDemuxer;
nsRefPtr<PlatformDecoderModule> mPlatform;
mp4_demuxer::CryptoFile mCrypto;
class DecoderCallback : public MediaDataDecoderCallback {
public:
DecoderCallback(MP4Reader* aReader, TrackType aType)
: mReader(aReader)
, mType(aType)
{
}
virtual void Output(MediaData* aSample) override {
mReader->Output(mType, aSample);
}
virtual void InputExhausted() override {
mReader->InputExhausted(mType);
}
virtual void Error() override {
mReader->Error(mType);
}
virtual void DrainComplete() override {
mReader->DrainComplete(mType);
}
virtual void ReleaseMediaResources() override {
mReader->ReleaseMediaResources();
}
virtual bool OnReaderTaskQueue() override {
return mReader->OnTaskQueue();
}
private:
MP4Reader* mReader;
TrackType mType;
};
struct DecoderData {
DecoderData(MediaData::Type aType,
uint32_t aDecodeAhead)
: mType(aType)
, mMonitor(aType == MediaData::AUDIO_DATA ? "MP4 audio decoder data"
: "MP4 video decoder data")
, mNumSamplesInput(0)
, mNumSamplesOutput(0)
, mDecodeAhead(aDecodeAhead)
, mForceDecodeAhead(false)
, mActive(false)
, mInputExhausted(false)
, mError(false)
, mIsFlushing(false)
, mUpdateScheduled(false)
, mDemuxEOS(false)
, mDrainComplete(false)
, mDiscontinuity(false)
{
}
nsAutoPtr<TrackDemuxer> mTrackDemuxer;
// The platform decoder.
nsRefPtr<MediaDataDecoder> mDecoder;
// TaskQueue on which decoder can choose to decode.
// Only non-null up until the decoder is created.
nsRefPtr<FlushableTaskQueue> mTaskQueue;
// Callback that receives output and error notifications from the decoder.
nsAutoPtr<DecoderCallback> mCallback;
// Decoded samples returned my mDecoder awaiting being returned to
// state machine upon request.
nsTArray<nsRefPtr<MediaData> > mOutput;
// Disambiguate Audio vs Video.
MediaData::Type mType;
// These get overriden in the templated concrete class.
virtual bool HasPromise() = 0;
virtual void RejectPromise(MediaDecoderReader::NotDecodedReason aReason,
const char* aMethodName) = 0;
// Monitor that protects all non-threadsafe state; the primitives
// that follow.
Monitor mMonitor;
uint64_t mNumSamplesInput;
uint64_t mNumSamplesOutput;
uint32_t mDecodeAhead;
bool mForceDecodeAhead;
// Whether this stream exists in the media.
bool mActive;
bool mInputExhausted;
bool mError;
bool mIsFlushing;
bool mUpdateScheduled;
bool mDemuxEOS;
bool mDrainComplete;
bool mDiscontinuity;
};
template<typename PromiseType>
struct DecoderDataWithPromise : public DecoderData {
DecoderDataWithPromise(MediaData::Type aType, uint32_t aDecodeAhead) :
DecoderData(aType, aDecodeAhead)
{
mPromise.SetMonitor(&mMonitor);
}
MozPromiseHolder<PromiseType> mPromise;
bool HasPromise() override { return !mPromise.IsEmpty(); }
void RejectPromise(MediaDecoderReader::NotDecodedReason aReason,
const char* aMethodName) override
{
mPromise.Reject(aReason, aMethodName);
}
};
DecoderDataWithPromise<AudioDataPromise> mAudio;
DecoderDataWithPromise<VideoDataPromise> mVideo;
// Queued samples extracted by the demuxer, but not yet sent to the platform
// decoder.
nsRefPtr<MediaRawData> mQueuedVideoSample;
// Returns true when the decoder for this track needs input.
// aDecoder.mMonitor must be locked.
bool NeedInput(DecoderData& aDecoder);
// The last number of decoded output frames that we've reported to
// MediaDecoder::NotifyDecoded(). We diff the number of output video
// frames every time that DecodeVideoData() is called, and report the
// delta there.
uint64_t mLastReportedNumDecodedFrames;
DecoderData& GetDecoderData(TrackType aTrack);
layers::LayersBackend mLayersBackendType;
// For use with InvokeAndRetry as an already_refed can't be converted to bool
nsRefPtr<MediaRawData> DemuxVideoSample();
nsRefPtr<MediaRawData> DemuxAudioSample();
// True if we've read the streams' metadata.
bool mDemuxerInitialized;
// True if we've gathered telemetry from an SPS.
bool mFoundSPSForTelemetry;
// Synchronized by decoder monitor.
bool mIsEncrypted;
bool mIndexReady;
int64_t mLastSeenEnd;
Monitor mDemuxerMonitor;
nsRefPtr<SharedDecoderManager> mSharedDecoderManager;
};
} // namespace mozilla
#endif

Просмотреть файл

@ -7,7 +7,7 @@
#ifndef MP4_STREAM_H_
#define MP4_STREAM_H_
#include "mp4_demuxer/Stream.h"
#include "mp4_demuxer/mp4_demuxer.h"
#include "MediaResource.h"

Просмотреть файл

@ -7,6 +7,7 @@
EXPORTS += [
'MP4Decoder.h',
'MP4Demuxer.h',
'MP4Reader.h',
'MP4Stream.h',
]
@ -17,6 +18,7 @@ UNIFIED_SOURCES += [
SOURCES += [
'MP4Demuxer.cpp',
'MP4Reader.cpp',
]
FINAL_LIBRARY = 'xul'

Просмотреть файл

@ -12,6 +12,7 @@ UNIFIED_SOURCES += [
'TestIntervalSet.cpp',
'TestMozPromise.cpp',
'TestMP3Demuxer.cpp',
'TestMP4Demuxer.cpp',
# 'TestMP4Reader.cpp', disabled so we can turn check tests back on (bug 1175752)
'TestTrackEncoder.cpp',
'TestVideoSegment.cpp',

Просмотреть файл

@ -20,6 +20,7 @@
#include "SharedDecoderManager.h"
#include "MP4Decoder.h"
#include "MP4Demuxer.h"
#include "MP4Reader.h"
#endif
#ifdef MOZ_WEBM
@ -700,15 +701,18 @@ CreateReaderForType(const nsACString& aType, AbstractMediaDecoder* aDecoder,
TaskQueue* aBorrowedTaskQueue)
{
#ifdef MOZ_FMP4
// The MediaFormatReader that supports fragmented MP4 and uses
// The MP4Reader that supports fragmented MP4 and uses
// PlatformDecoderModules is hidden behind prefs for regular video
// elements, but we always want to use it for MSE, so instantiate it
// directly here.
if ((aType.LowerCaseEqualsLiteral("video/mp4") ||
aType.LowerCaseEqualsLiteral("audio/mp4")) &&
MP4Decoder::IsEnabled() && aDecoder) {
MediaDecoderReader* reader =
new MediaFormatReader(aDecoder, new MP4Demuxer(aDecoder->GetResource()), aBorrowedTaskQueue);
bool useFormatDecoder =
Preferences::GetBool("media.mediasource.format-reader.mp4", true);
MediaDecoderReader* reader = useFormatDecoder ?
static_cast<MediaDecoderReader*>(new MediaFormatReader(aDecoder, new MP4Demuxer(aDecoder->GetResource()), aBorrowedTaskQueue)) :
static_cast<MediaDecoderReader*>(new MP4Reader(aDecoder, aBorrowedTaskQueue));
return reader;
}
#endif

Просмотреть файл

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "AppleUtils.h"
#include "MP4Reader.h"
#include "MP4Decoder.h"
#include "mp4_demuxer/Adts.h"
#include "MediaInfo.h"

Просмотреть файл

@ -9,6 +9,7 @@
#include "PlatformDecoderModule.h"
#include "mozilla/ReentrantMonitor.h"
#include "MP4Reader.h"
#include "MP4Decoder.h"
#include "nsIThread.h"
#include "ReorderQueue.h"

Просмотреть файл

@ -10,6 +10,7 @@
#include "PlatformDecoderModule.h"
#include "FFmpegLibs.h"
#include "mozilla/StaticMutex.h"
#include "mp4_demuxer/mp4_demuxer.h"
namespace mozilla
{

Просмотреть файл

@ -8,6 +8,7 @@
#define WMFAudioOutputSource_h_
#include "WMF.h"
#include "MP4Reader.h"
#include "MFTDecoder.h"
#include "mozilla/RefPtr.h"
#include "WMFMediaDataDecoder.h"

Просмотреть файл

@ -9,9 +9,9 @@
#include "WMF.h"
#include "MP4Reader.h"
#include "MFTDecoder.h"
#include "mozilla/RefPtr.h"
#include "PlatformDecoderModule.h"
namespace mozilla {

Просмотреть файл

@ -8,6 +8,7 @@
#define WMFVideoMFTManager_h_
#include "WMF.h"
#include "MP4Reader.h"
#include "MFTDecoder.h"
#include "nsRect.h"
#include "WMFMediaDataDecoder.h"

Просмотреть файл

@ -24,6 +24,8 @@
PRLogModuleInfo* GetDemuxerLog();
#define LOG(...) MOZ_LOG(GetDemuxerLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
using namespace mp4_demuxer;
namespace mozilla {
using layers::Image;

Просмотреть файл

@ -13,6 +13,7 @@
#include "PlatformDecoderModule.h"
#include "mozilla/Monitor.h"
#include "mp4_demuxer/mp4_demuxer.h"
#include "MediaInfo.h"
#include "MediaData.h"

Просмотреть файл

@ -5,7 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mp4_demuxer/Box.h"
#include "mp4_demuxer/Stream.h"
#include "mp4_demuxer/mp4_demuxer.h"
#include "mozilla/Endian.h"
#include <algorithm>

Просмотреть файл

@ -0,0 +1,51 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim:set ts=2 sw=2 sts=2 et cindent: */
/* 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 "mp4_demuxer/MP4TrackDemuxer.h"
using namespace mozilla;
namespace mp4_demuxer {
void
MP4AudioDemuxer::Seek(Microseconds aTime)
{
mDemuxer->SeekAudio(aTime);
}
already_AddRefed<MediaRawData>
MP4AudioDemuxer::DemuxSample()
{
nsRefPtr<MediaRawData> sample(mDemuxer->DemuxAudioSample());
return sample.forget();
}
Microseconds
MP4AudioDemuxer::GetNextKeyframeTime()
{
return -1;
}
void
MP4VideoDemuxer::Seek(Microseconds aTime)
{
mDemuxer->SeekVideo(aTime);
}
already_AddRefed<MediaRawData>
MP4VideoDemuxer::DemuxSample()
{
nsRefPtr<MediaRawData> sample(mDemuxer->DemuxVideoSample());
return sample.forget();
}
Microseconds
MP4VideoDemuxer::GetNextKeyframeTime()
{
return mDemuxer->GetNextKeyframeTime();
}
}

Просмотреть файл

@ -0,0 +1,38 @@
/* 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/. */
#ifndef MP4_TRACK_DEMUXER_H_
#define MP4_TRACK_DEMUXER_H_
#include "mozilla/Attributes.h"
#include "demuxer/TrackDemuxer.h"
namespace mp4_demuxer
{
class MP4AudioDemuxer : public mozilla::TrackDemuxer {
public:
explicit MP4AudioDemuxer(MP4Demuxer* aDemuxer) : mDemuxer(aDemuxer) {}
virtual void Seek(Microseconds aTime) override;
virtual already_AddRefed<mozilla::MediaRawData> DemuxSample() override;
virtual Microseconds GetNextKeyframeTime() override;
private:
nsRefPtr<MP4Demuxer> mDemuxer;
};
class MP4VideoDemuxer : public mozilla::TrackDemuxer {
public:
explicit MP4VideoDemuxer(MP4Demuxer* aDemuxer) : mDemuxer(aDemuxer) {}
virtual void Seek(Microseconds aTime) override;
virtual already_AddRefed<mozilla::MediaRawData> DemuxSample() override;
virtual Microseconds GetNextKeyframeTime() override;
private:
nsRefPtr<MP4Demuxer> mDemuxer;
};
}
#endif

Просмотреть файл

@ -5,16 +5,13 @@
#ifndef MOOF_PARSER_H_
#define MOOF_PARSER_H_
#include "mozilla/Monitor.h"
#include "mp4_demuxer/Atom.h"
#include "mp4_demuxer/AtomType.h"
#include "mp4_demuxer/mp4_demuxer.h"
#include "mp4_demuxer/SinfParser.h"
#include "mp4_demuxer/Interval.h"
#include "MediaResource.h"
namespace mp4_demuxer {
using mozilla::Monitor;
typedef int64_t Microseconds;
class Stream;
class Box;

Просмотреть файл

@ -0,0 +1,84 @@
/* 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/. */
#ifndef MP4_DEMUXER_H_
#define MP4_DEMUXER_H_
#include "MediaInfo.h"
#include "MediaResource.h"
#include "mozilla/Monitor.h"
#include "mozilla/UniquePtr.h"
#include "mp4_demuxer/DecoderData.h"
#include "mp4_demuxer/Interval.h"
#include "mp4_demuxer/Stream.h"
#include "nsISupportsImpl.h"
#include "nsTArray.h"
namespace mp4_demuxer
{
class Index;
class MP4Metadata;
class SampleIterator;
using mozilla::Monitor;
typedef int64_t Microseconds;
class MP4Demuxer
{
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MP4Demuxer)
explicit MP4Demuxer(Stream* aSource, Monitor* aMonitor);
bool Init();
Microseconds Duration();
bool CanSeek();
bool HasValidAudio();
bool HasValidVideo();
void SeekAudio(Microseconds aTime);
void SeekVideo(Microseconds aTime);
// DemuxAudioSample and DemuxVideoSample functions
// return nullptr on end of stream or error.
already_AddRefed<mozilla::MediaRawData> DemuxAudioSample();
already_AddRefed<mozilla::MediaRawData> DemuxVideoSample();
const CryptoFile& Crypto() const;
const mozilla::AudioInfo& AudioConfig() const { return *mAudioConfig->GetAsAudioInfo(); }
const mozilla::VideoInfo& VideoConfig() const { return *mVideoConfig->GetAsVideoInfo(); }
void UpdateIndex(const nsTArray<mozilla::MediaByteRange>& aByteRanges);
void ConvertByteRangesToTime(
const nsTArray<mozilla::MediaByteRange>& aByteRanges,
nsTArray<Interval<Microseconds>>* aIntervals);
int64_t GetEvictionOffset(Microseconds aTime);
// Returns timestamp of next keyframe, or -1 if demuxer can't
// report this.
Microseconds GetNextKeyframeTime();
protected:
~MP4Demuxer();
private:
mozilla::UniquePtr<mozilla::TrackInfo> mAudioConfig;
mozilla::UniquePtr<mozilla::TrackInfo> mVideoConfig;
nsRefPtr<Stream> mSource;
nsTArray<mozilla::MediaByteRange> mCachedByteRanges;
nsTArray<Interval<Microseconds>> mCachedTimeRanges;
Monitor* mMonitor;
Microseconds mNextKeyframeTime;
mozilla::UniquePtr<MP4Metadata> mMetadata;
mozilla::UniquePtr<SampleIterator> mAudioIterator;
mozilla::UniquePtr<SampleIterator> mVideoIterator;
nsTArray<nsRefPtr<Index>> mIndexes;
};
} // namespace mp4_demuxer
#endif // MP4_DEMUXER_H_

Просмотреть файл

@ -0,0 +1,245 @@
/* 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 "mp4_demuxer/Index.h"
#include "mp4_demuxer/MP4Metadata.h"
#include "mp4_demuxer/mp4_demuxer.h"
#include <stdint.h>
#include <algorithm>
#include <limits>
namespace mp4_demuxer
{
MP4Demuxer::MP4Demuxer(Stream* source, Monitor* aMonitor)
: mSource(source)
, mMonitor(aMonitor)
, mNextKeyframeTime(-1)
{
}
MP4Demuxer::~MP4Demuxer()
{
}
bool
MP4Demuxer::Init()
{
mMonitor->AssertCurrentThreadOwns();
// Check that we have an entire moov before attempting any new reads to make
// the retry system work.
if (!MP4Metadata::HasCompleteMetadata(mSource)) {
return false;
}
mMetadata = mozilla::MakeUnique<MP4Metadata>(mSource);
if (!mMetadata->GetNumberTracks(mozilla::TrackInfo::kAudioTrack) &&
!mMetadata->GetNumberTracks(mozilla::TrackInfo::kVideoTrack)) {
return false;
}
auto audioInfo = mMetadata->GetTrackInfo(mozilla::TrackInfo::kAudioTrack, 0);
if (audioInfo) {
mAudioConfig = mozilla::Move(audioInfo);
FallibleTArray<Index::Indice> indices;
if (!mMetadata->ReadTrackIndex(indices, mAudioConfig->mTrackId)) {
return false;
}
nsRefPtr<Index> index =
new Index(indices,
mSource,
mAudioConfig->mTrackId,
/* aIsAudio = */ true,
mMonitor);
mIndexes.AppendElement(index);
mAudioIterator = mozilla::MakeUnique<SampleIterator>(index);
}
auto videoInfo = mMetadata->GetTrackInfo(mozilla::TrackInfo::kVideoTrack, 0);
if (videoInfo) {
mVideoConfig = mozilla::Move(videoInfo);
FallibleTArray<Index::Indice> indices;
if (!mMetadata->ReadTrackIndex(indices, mVideoConfig->mTrackId)) {
return false;
}
nsRefPtr<Index> index =
new Index(indices,
mSource,
mVideoConfig->mTrackId,
/* aIsAudio = */ false,
mMonitor);
mIndexes.AppendElement(index);
mVideoIterator = mozilla::MakeUnique<SampleIterator>(index);
}
return mAudioIterator || mVideoIterator;
}
bool
MP4Demuxer::HasValidAudio()
{
mMonitor->AssertCurrentThreadOwns();
return mAudioIterator && mAudioConfig && mAudioConfig->IsValid();
}
bool
MP4Demuxer::HasValidVideo()
{
mMonitor->AssertCurrentThreadOwns();
return mVideoIterator && mVideoConfig && mVideoConfig->IsValid();
}
Microseconds
MP4Demuxer::Duration()
{
mMonitor->AssertCurrentThreadOwns();
int64_t videoDuration = mVideoConfig ? mVideoConfig->mDuration : 0;
int64_t audioDuration = mAudioConfig ? mAudioConfig->mDuration : 0;
return std::max(videoDuration, audioDuration);
}
bool
MP4Demuxer::CanSeek()
{
mMonitor->AssertCurrentThreadOwns();
return mMetadata->CanSeek();
}
void
MP4Demuxer::SeekAudio(Microseconds aTime)
{
mMonitor->AssertCurrentThreadOwns();
MOZ_ASSERT(mAudioIterator);
mAudioIterator->Seek(aTime);
}
void
MP4Demuxer::SeekVideo(Microseconds aTime)
{
mMonitor->AssertCurrentThreadOwns();
MOZ_ASSERT(mVideoIterator);
mVideoIterator->Seek(aTime);
}
already_AddRefed<mozilla::MediaRawData>
MP4Demuxer::DemuxAudioSample()
{
mMonitor->AssertCurrentThreadOwns();
MOZ_ASSERT(mAudioIterator);
nsRefPtr<mozilla::MediaRawData> sample(mAudioIterator->GetNext());
if (sample) {
if (sample->mCrypto.mValid) {
nsAutoPtr<MediaRawDataWriter> writer(sample->CreateWriter());
writer->mCrypto.mMode = mAudioConfig->mCrypto.mMode;
writer->mCrypto.mIVSize = mAudioConfig->mCrypto.mIVSize;
writer->mCrypto.mKeyId.AppendElements(mAudioConfig->mCrypto.mKeyId);
}
}
return sample.forget();
}
already_AddRefed<MediaRawData>
MP4Demuxer::DemuxVideoSample()
{
mMonitor->AssertCurrentThreadOwns();
MOZ_ASSERT(mVideoIterator);
nsRefPtr<mozilla::MediaRawData> sample(mVideoIterator->GetNext());
if (sample) {
sample->mExtraData = mVideoConfig->GetAsVideoInfo()->mExtraData;
if (sample->mCrypto.mValid) {
nsAutoPtr<MediaRawDataWriter> writer(sample->CreateWriter());
writer->mCrypto.mMode = mVideoConfig->mCrypto.mMode;
writer->mCrypto.mKeyId.AppendElements(mVideoConfig->mCrypto.mKeyId);
}
if (sample->mTime >= mNextKeyframeTime) {
mNextKeyframeTime = mVideoIterator->GetNextKeyframeTime();
}
}
return sample.forget();
}
void
MP4Demuxer::UpdateIndex(const nsTArray<mozilla::MediaByteRange>& aByteRanges)
{
mMonitor->AssertCurrentThreadOwns();
for (int i = 0; i < mIndexes.Length(); i++) {
mIndexes[i]->UpdateMoofIndex(aByteRanges);
}
}
void
MP4Demuxer::ConvertByteRangesToTime(
const nsTArray<mozilla::MediaByteRange>& aByteRanges,
nsTArray<Interval<Microseconds>>* aIntervals)
{
mMonitor->AssertCurrentThreadOwns();
if (mIndexes.IsEmpty()) {
return;
}
Microseconds lastComposition = 0;
nsTArray<Microseconds> endCompositions;
for (int i = 0; i < mIndexes.Length(); i++) {
Microseconds endComposition =
mIndexes[i]->GetEndCompositionIfBuffered(aByteRanges);
endCompositions.AppendElement(endComposition);
lastComposition = std::max(lastComposition, endComposition);
}
if (aByteRanges != mCachedByteRanges) {
mCachedByteRanges = aByteRanges;
mCachedTimeRanges.Clear();
for (int i = 0; i < mIndexes.Length(); i++) {
nsTArray<Interval<Microseconds>> ranges;
mIndexes[i]->ConvertByteRangesToTimeRanges(aByteRanges, &ranges);
if (lastComposition && endCompositions[i]) {
Interval<Microseconds>::SemiNormalAppend(
ranges, Interval<Microseconds>(endCompositions[i], lastComposition));
}
if (i) {
nsTArray<Interval<Microseconds>> intersection;
Interval<Microseconds>::Intersection(mCachedTimeRanges, ranges, &intersection);
mCachedTimeRanges = intersection;
} else {
mCachedTimeRanges = ranges;
}
}
}
aIntervals->AppendElements(mCachedTimeRanges);
}
int64_t
MP4Demuxer::GetEvictionOffset(Microseconds aTime)
{
mMonitor->AssertCurrentThreadOwns();
if (mIndexes.IsEmpty()) {
return 0;
}
uint64_t offset = std::numeric_limits<uint64_t>::max();
for (int i = 0; i < mIndexes.Length(); i++) {
offset = std::min(offset, mIndexes[i]->GetEvictionOffset(aTime));
}
return offset == std::numeric_limits<uint64_t>::max() ? 0 : offset;
}
Microseconds
MP4Demuxer::GetNextKeyframeTime()
{
mMonitor->AssertCurrentThreadOwns();
return mNextKeyframeTime;
}
const CryptoFile&
MP4Demuxer::Crypto() const
{
return mMetadata->Crypto();
}
} // namespace mp4_demuxer

Просмотреть файл

@ -60,7 +60,9 @@ EXPORTS.mp4_demuxer += [
'binding/include/mp4_demuxer/Index.h',
'binding/include/mp4_demuxer/Interval.h',
'binding/include/mp4_demuxer/MoofParser.h',
'binding/include/mp4_demuxer/mp4_demuxer.h',
'binding/include/mp4_demuxer/MP4Metadata.h',
'binding/include/mp4_demuxer/MP4TrackDemuxer.h',
'binding/include/mp4_demuxer/ResourceStream.h',
'binding/include/mp4_demuxer/SinfParser.h',
'binding/include/mp4_demuxer/Stream.h',
@ -93,7 +95,9 @@ UNIFIED_SOURCES += [
'binding/H264.cpp',
'binding/Index.cpp',
'binding/MoofParser.cpp',
'binding/mp4_demuxer.cpp',
'binding/MP4Metadata.cpp',
'binding/MP4TrackDemuxer.cpp',
'binding/ResourceStream.cpp',
'binding/SinfParser.cpp',
'frameworks/av/media/libstagefright/DataSource.cpp',

Просмотреть файл

@ -474,6 +474,11 @@ pref("media.mediasource.webm.enabled", false);
// Enable new MediaSource architecture.
pref("media.mediasource.format-reader", false);
// Enable new MediaFormatReader architecture for mp4 in MSE
pref("media.mediasource.format-reader.mp4", true);
// Enable new MediaFormatReader architecture for plain mp4.
pref("media.format-reader.mp4", true);
// Enable new MediaFormatReader architecture for webm in MSE
pref("media.mediasource.format-reader.webm", false);
// Enable new MediaFormatReader architecture for plain webm.