зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset 1704ea727e81 (bug 1163486) for at least b2g bustage
This commit is contained in:
Родитель
79fe86d82b
Коммит
de3872af29
|
@ -66,6 +66,7 @@
|
||||||
#include "AppleMP3Reader.h"
|
#include "AppleMP3Reader.h"
|
||||||
#endif
|
#endif
|
||||||
#ifdef MOZ_FMP4
|
#ifdef MOZ_FMP4
|
||||||
|
#include "MP4Reader.h"
|
||||||
#include "MP4Decoder.h"
|
#include "MP4Decoder.h"
|
||||||
#include "MP4Demuxer.h"
|
#include "MP4Demuxer.h"
|
||||||
#endif
|
#endif
|
||||||
|
@ -653,7 +654,9 @@ MediaDecoderReader* DecoderTraits::CreateReader(const nsACString& aType, Abstrac
|
||||||
}
|
}
|
||||||
#ifdef MOZ_FMP4
|
#ifdef MOZ_FMP4
|
||||||
if (IsMP4SupportedType(aType)) {
|
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
|
} else
|
||||||
#endif
|
#endif
|
||||||
if (IsMP3SupportedType(aType)) {
|
if (IsMP3SupportedType(aType)) {
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "MP4Decoder.h"
|
#include "MP4Decoder.h"
|
||||||
|
#include "MP4Reader.h"
|
||||||
#include "MediaDecoderStateMachine.h"
|
#include "MediaDecoderStateMachine.h"
|
||||||
#include "MediaFormatReader.h"
|
#include "MediaFormatReader.h"
|
||||||
#include "MP4Demuxer.h"
|
#include "MP4Demuxer.h"
|
||||||
|
@ -41,7 +42,11 @@ MP4Decoder::MP4Decoder()
|
||||||
|
|
||||||
MediaDecoderStateMachine* MP4Decoder::CreateStateMachine()
|
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);
|
return new MediaDecoderStateMachine(this, reader);
|
||||||
}
|
}
|
||||||
|
@ -53,8 +58,8 @@ MP4Decoder::SetCDMProxy(CDMProxy* aProxy)
|
||||||
nsresult rv = MediaDecoder::SetCDMProxy(aProxy);
|
nsresult rv = MediaDecoder::SetCDMProxy(aProxy);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
if (aProxy) {
|
if (aProxy) {
|
||||||
// The MediaFormatReader can't decrypt EME content until it has a CDMProxy,
|
// The MP4Reader can't decrypt EME content until it has a CDMProxy,
|
||||||
// and the CDMProxy knows the capabilities of the CDM. The MediaFormatReader
|
// and the CDMProxy knows the capabilities of the CDM. The MP4Reader
|
||||||
// remains in "waiting for resources" state until then.
|
// remains in "waiting for resources" state until then.
|
||||||
CDMCaps::AutoLock caps(aProxy->Capabilites());
|
CDMCaps::AutoLock caps(aProxy->Capabilites());
|
||||||
nsCOMPtr<nsIRunnable> task(
|
nsCOMPtr<nsIRunnable> task(
|
||||||
|
|
|
@ -20,14 +20,6 @@
|
||||||
#include "mp4_demuxer/AnnexB.h"
|
#include "mp4_demuxer/AnnexB.h"
|
||||||
#include "mp4_demuxer/H264.h"
|
#include "mp4_demuxer/H264.h"
|
||||||
|
|
||||||
PRLogModuleInfo* GetDemuxerLog() {
|
|
||||||
static PRLogModuleInfo* log = nullptr;
|
|
||||||
if (!log) {
|
|
||||||
log = PR_NewLogModule("MP4Demuxer");
|
|
||||||
}
|
|
||||||
return log;
|
|
||||||
}
|
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
// Returns true if no SPS was found and search for it should continue.
|
// Returns true if no SPS was found and search for it should continue.
|
||||||
|
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -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_
|
#ifndef MP4_STREAM_H_
|
||||||
#define MP4_STREAM_H_
|
#define MP4_STREAM_H_
|
||||||
|
|
||||||
#include "mp4_demuxer/Stream.h"
|
#include "mp4_demuxer/mp4_demuxer.h"
|
||||||
|
|
||||||
#include "MediaResource.h"
|
#include "MediaResource.h"
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
EXPORTS += [
|
EXPORTS += [
|
||||||
'MP4Decoder.h',
|
'MP4Decoder.h',
|
||||||
'MP4Demuxer.h',
|
'MP4Demuxer.h',
|
||||||
|
'MP4Reader.h',
|
||||||
'MP4Stream.h',
|
'MP4Stream.h',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -17,6 +18,7 @@ UNIFIED_SOURCES += [
|
||||||
|
|
||||||
SOURCES += [
|
SOURCES += [
|
||||||
'MP4Demuxer.cpp',
|
'MP4Demuxer.cpp',
|
||||||
|
'MP4Reader.cpp',
|
||||||
]
|
]
|
||||||
|
|
||||||
FINAL_LIBRARY = 'xul'
|
FINAL_LIBRARY = 'xul'
|
||||||
|
|
|
@ -12,6 +12,7 @@ UNIFIED_SOURCES += [
|
||||||
'TestIntervalSet.cpp',
|
'TestIntervalSet.cpp',
|
||||||
'TestMozPromise.cpp',
|
'TestMozPromise.cpp',
|
||||||
'TestMP3Demuxer.cpp',
|
'TestMP3Demuxer.cpp',
|
||||||
|
'TestMP4Demuxer.cpp',
|
||||||
# 'TestMP4Reader.cpp', disabled so we can turn check tests back on (bug 1175752)
|
# 'TestMP4Reader.cpp', disabled so we can turn check tests back on (bug 1175752)
|
||||||
'TestTrackEncoder.cpp',
|
'TestTrackEncoder.cpp',
|
||||||
'TestVideoSegment.cpp',
|
'TestVideoSegment.cpp',
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "SharedDecoderManager.h"
|
#include "SharedDecoderManager.h"
|
||||||
#include "MP4Decoder.h"
|
#include "MP4Decoder.h"
|
||||||
#include "MP4Demuxer.h"
|
#include "MP4Demuxer.h"
|
||||||
|
#include "MP4Reader.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef MOZ_WEBM
|
#ifdef MOZ_WEBM
|
||||||
|
@ -700,15 +701,18 @@ CreateReaderForType(const nsACString& aType, AbstractMediaDecoder* aDecoder,
|
||||||
TaskQueue* aBorrowedTaskQueue)
|
TaskQueue* aBorrowedTaskQueue)
|
||||||
{
|
{
|
||||||
#ifdef MOZ_FMP4
|
#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
|
// PlatformDecoderModules is hidden behind prefs for regular video
|
||||||
// elements, but we always want to use it for MSE, so instantiate it
|
// elements, but we always want to use it for MSE, so instantiate it
|
||||||
// directly here.
|
// directly here.
|
||||||
if ((aType.LowerCaseEqualsLiteral("video/mp4") ||
|
if ((aType.LowerCaseEqualsLiteral("video/mp4") ||
|
||||||
aType.LowerCaseEqualsLiteral("audio/mp4")) &&
|
aType.LowerCaseEqualsLiteral("audio/mp4")) &&
|
||||||
MP4Decoder::IsEnabled() && aDecoder) {
|
MP4Decoder::IsEnabled() && aDecoder) {
|
||||||
MediaDecoderReader* reader =
|
bool useFormatDecoder =
|
||||||
new MediaFormatReader(aDecoder, new MP4Demuxer(aDecoder->GetResource()), aBorrowedTaskQueue);
|
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;
|
return reader;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "AppleUtils.h"
|
#include "AppleUtils.h"
|
||||||
|
#include "MP4Reader.h"
|
||||||
#include "MP4Decoder.h"
|
#include "MP4Decoder.h"
|
||||||
#include "mp4_demuxer/Adts.h"
|
#include "mp4_demuxer/Adts.h"
|
||||||
#include "MediaInfo.h"
|
#include "MediaInfo.h"
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
|
|
||||||
#include "PlatformDecoderModule.h"
|
#include "PlatformDecoderModule.h"
|
||||||
#include "mozilla/ReentrantMonitor.h"
|
#include "mozilla/ReentrantMonitor.h"
|
||||||
|
#include "MP4Reader.h"
|
||||||
#include "MP4Decoder.h"
|
#include "MP4Decoder.h"
|
||||||
#include "nsIThread.h"
|
#include "nsIThread.h"
|
||||||
#include "ReorderQueue.h"
|
#include "ReorderQueue.h"
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "PlatformDecoderModule.h"
|
#include "PlatformDecoderModule.h"
|
||||||
#include "FFmpegLibs.h"
|
#include "FFmpegLibs.h"
|
||||||
#include "mozilla/StaticMutex.h"
|
#include "mozilla/StaticMutex.h"
|
||||||
|
#include "mp4_demuxer/mp4_demuxer.h"
|
||||||
|
|
||||||
namespace mozilla
|
namespace mozilla
|
||||||
{
|
{
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#define WMFAudioOutputSource_h_
|
#define WMFAudioOutputSource_h_
|
||||||
|
|
||||||
#include "WMF.h"
|
#include "WMF.h"
|
||||||
|
#include "MP4Reader.h"
|
||||||
#include "MFTDecoder.h"
|
#include "MFTDecoder.h"
|
||||||
#include "mozilla/RefPtr.h"
|
#include "mozilla/RefPtr.h"
|
||||||
#include "WMFMediaDataDecoder.h"
|
#include "WMFMediaDataDecoder.h"
|
||||||
|
|
|
@ -9,9 +9,9 @@
|
||||||
|
|
||||||
|
|
||||||
#include "WMF.h"
|
#include "WMF.h"
|
||||||
|
#include "MP4Reader.h"
|
||||||
#include "MFTDecoder.h"
|
#include "MFTDecoder.h"
|
||||||
#include "mozilla/RefPtr.h"
|
#include "mozilla/RefPtr.h"
|
||||||
#include "PlatformDecoderModule.h"
|
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#define WMFVideoMFTManager_h_
|
#define WMFVideoMFTManager_h_
|
||||||
|
|
||||||
#include "WMF.h"
|
#include "WMF.h"
|
||||||
|
#include "MP4Reader.h"
|
||||||
#include "MFTDecoder.h"
|
#include "MFTDecoder.h"
|
||||||
#include "nsRect.h"
|
#include "nsRect.h"
|
||||||
#include "WMFMediaDataDecoder.h"
|
#include "WMFMediaDataDecoder.h"
|
||||||
|
|
|
@ -24,6 +24,8 @@
|
||||||
PRLogModuleInfo* GetDemuxerLog();
|
PRLogModuleInfo* GetDemuxerLog();
|
||||||
#define LOG(...) MOZ_LOG(GetDemuxerLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
|
#define LOG(...) MOZ_LOG(GetDemuxerLog(), mozilla::LogLevel::Debug, (__VA_ARGS__))
|
||||||
|
|
||||||
|
using namespace mp4_demuxer;
|
||||||
|
|
||||||
namespace mozilla {
|
namespace mozilla {
|
||||||
|
|
||||||
using layers::Image;
|
using layers::Image;
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "PlatformDecoderModule.h"
|
#include "PlatformDecoderModule.h"
|
||||||
#include "mozilla/Monitor.h"
|
#include "mozilla/Monitor.h"
|
||||||
|
|
||||||
|
#include "mp4_demuxer/mp4_demuxer.h"
|
||||||
#include "MediaInfo.h"
|
#include "MediaInfo.h"
|
||||||
#include "MediaData.h"
|
#include "MediaData.h"
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
#include "mp4_demuxer/Box.h"
|
#include "mp4_demuxer/Box.h"
|
||||||
#include "mp4_demuxer/Stream.h"
|
#include "mp4_demuxer/mp4_demuxer.h"
|
||||||
#include "mozilla/Endian.h"
|
#include "mozilla/Endian.h"
|
||||||
#include <algorithm>
|
#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_
|
#ifndef MOOF_PARSER_H_
|
||||||
#define MOOF_PARSER_H_
|
#define MOOF_PARSER_H_
|
||||||
|
|
||||||
#include "mozilla/Monitor.h"
|
|
||||||
#include "mp4_demuxer/Atom.h"
|
#include "mp4_demuxer/Atom.h"
|
||||||
#include "mp4_demuxer/AtomType.h"
|
#include "mp4_demuxer/AtomType.h"
|
||||||
|
#include "mp4_demuxer/mp4_demuxer.h"
|
||||||
#include "mp4_demuxer/SinfParser.h"
|
#include "mp4_demuxer/SinfParser.h"
|
||||||
#include "mp4_demuxer/Interval.h"
|
|
||||||
#include "MediaResource.h"
|
#include "MediaResource.h"
|
||||||
|
|
||||||
namespace mp4_demuxer {
|
namespace mp4_demuxer {
|
||||||
using mozilla::Monitor;
|
|
||||||
typedef int64_t Microseconds;
|
|
||||||
|
|
||||||
class Stream;
|
class Stream;
|
||||||
class Box;
|
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/Index.h',
|
||||||
'binding/include/mp4_demuxer/Interval.h',
|
'binding/include/mp4_demuxer/Interval.h',
|
||||||
'binding/include/mp4_demuxer/MoofParser.h',
|
'binding/include/mp4_demuxer/MoofParser.h',
|
||||||
|
'binding/include/mp4_demuxer/mp4_demuxer.h',
|
||||||
'binding/include/mp4_demuxer/MP4Metadata.h',
|
'binding/include/mp4_demuxer/MP4Metadata.h',
|
||||||
|
'binding/include/mp4_demuxer/MP4TrackDemuxer.h',
|
||||||
'binding/include/mp4_demuxer/ResourceStream.h',
|
'binding/include/mp4_demuxer/ResourceStream.h',
|
||||||
'binding/include/mp4_demuxer/SinfParser.h',
|
'binding/include/mp4_demuxer/SinfParser.h',
|
||||||
'binding/include/mp4_demuxer/Stream.h',
|
'binding/include/mp4_demuxer/Stream.h',
|
||||||
|
@ -93,7 +95,9 @@ UNIFIED_SOURCES += [
|
||||||
'binding/H264.cpp',
|
'binding/H264.cpp',
|
||||||
'binding/Index.cpp',
|
'binding/Index.cpp',
|
||||||
'binding/MoofParser.cpp',
|
'binding/MoofParser.cpp',
|
||||||
|
'binding/mp4_demuxer.cpp',
|
||||||
'binding/MP4Metadata.cpp',
|
'binding/MP4Metadata.cpp',
|
||||||
|
'binding/MP4TrackDemuxer.cpp',
|
||||||
'binding/ResourceStream.cpp',
|
'binding/ResourceStream.cpp',
|
||||||
'binding/SinfParser.cpp',
|
'binding/SinfParser.cpp',
|
||||||
'frameworks/av/media/libstagefright/DataSource.cpp',
|
'frameworks/av/media/libstagefright/DataSource.cpp',
|
||||||
|
|
|
@ -474,6 +474,11 @@ pref("media.mediasource.webm.enabled", false);
|
||||||
// Enable new MediaSource architecture.
|
// Enable new MediaSource architecture.
|
||||||
pref("media.mediasource.format-reader", false);
|
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
|
// Enable new MediaFormatReader architecture for webm in MSE
|
||||||
pref("media.mediasource.format-reader.webm", false);
|
pref("media.mediasource.format-reader.webm", false);
|
||||||
// Enable new MediaFormatReader architecture for plain webm.
|
// Enable new MediaFormatReader architecture for plain webm.
|
||||||
|
|
Загрузка…
Ссылка в новой задаче