author | Bobby Holley <bobbyholley@gmail.com> |
Mon, 08 Jun 2015 17:16:42 -0700 | |
changeset 248173 | e7b684137f229a40241bb0f2ad2c834103a2166a |
parent 248172 | 6289cdbce7b7b3950706d5e5bef4daf29c604f55 |
child 248174 | 0e722555cc6dcb49b6b833419f9670b99207c311 |
push id | 28893 |
push user | kwierso@gmail.com |
push date | Fri, 12 Jun 2015 00:02:58 +0000 |
treeherder | mozilla-central@8cf9d3e497f9 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jww |
bugs | 1173001 |
milestone | 41.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/media/MediaDecoderReader.cpp +++ b/dom/media/MediaDecoderReader.cpp @@ -55,24 +55,26 @@ public: const AudioData* audioData = static_cast<const AudioData*>(aObject); mSize += audioData->SizeOfIncludingThis(MallocSizeOf); return nullptr; } size_t mSize; }; -MediaDecoderReader::MediaDecoderReader(AbstractMediaDecoder* aDecoder) +MediaDecoderReader::MediaDecoderReader(AbstractMediaDecoder* aDecoder, + MediaTaskQueue* aBorrowedTaskQueue) : mAudioCompactor(mAudioQueue) , mDecoder(aDecoder) + , mTaskQueue(aBorrowedTaskQueue ? aBorrowedTaskQueue : new MediaTaskQueue(GetMediaThreadPool(MediaThreadType::PLAYBACK))) , mIgnoreAudioOutputFormat(false) , mStartTime(-1) , mHitAudioDecodeError(false) , mShutdown(false) - , mTaskQueueIsBorrowed(false) + , mTaskQueueIsBorrowed(!!aBorrowedTaskQueue) , mAudioDiscontinuity(false) , mVideoDiscontinuity(false) { MOZ_COUNT_CTOR(MediaDecoderReader); } MediaDecoderReader::~MediaDecoderReader() { @@ -326,29 +328,16 @@ MediaDecoderReader::RequestAudioData() mHitAudioDecodeError = false; } else { MOZ_ASSERT(false, "Dropping this promise on the floor"); } return p; } -MediaTaskQueue* -MediaDecoderReader::EnsureTaskQueue() -{ - if (!mTaskQueue) { - MOZ_ASSERT(!mTaskQueueIsBorrowed); - RefPtr<SharedThreadPool> pool(GetMediaThreadPool(MediaThreadType::PLAYBACK)); - MOZ_DIAGNOSTIC_ASSERT(pool); - mTaskQueue = new MediaTaskQueue(pool.forget()); - } - - return mTaskQueue; -} - void MediaDecoderReader::BreakCycles() { mTaskQueue = nullptr; } nsRefPtr<ShutdownPromise> MediaDecoderReader::Shutdown()
--- a/dom/media/MediaDecoderReader.h +++ b/dom/media/MediaDecoderReader.h @@ -74,17 +74,17 @@ public: // so we mark it that way to verify our assumptions. If you have a use-case // for multiple WaitForData consumers, feel free to flip the exclusivity here. typedef MediaPromise<MediaData::Type, WaitForDataRejectValue, /* IsExclusive = */ true> WaitForDataPromise; NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDecoderReader) // The caller must ensure that Shutdown() is called before aDecoder is // destroyed. - explicit MediaDecoderReader(AbstractMediaDecoder* aDecoder); + explicit MediaDecoderReader(AbstractMediaDecoder* aDecoder, MediaTaskQueue* aBorrowedTaskQueue = nullptr); // Initializes the reader, returns NS_OK on success, or NS_ERROR_FAILURE // on failure. virtual nsresult Init(MediaDecoderReader* aCloneDonor) = 0; // True if this reader is waiting media resource allocation virtual bool IsWaitingMediaResources() { return false; } // True if this reader is waiting for a Content Decryption Module to become @@ -102,28 +102,19 @@ public: virtual void BreakCycles(); // Destroys the decoding state. The reader cannot be made usable again. // This is different from ReleaseMediaResources() as it is irreversable, // whereas ReleaseMediaResources() is. Must be called on the decode // thread. virtual nsRefPtr<ShutdownPromise> Shutdown(); - MediaTaskQueue* EnsureTaskQueue(); - virtual bool OnTaskQueue() { - return !GetTaskQueue() || GetTaskQueue()->IsCurrentThreadIn(); - } - - void SetBorrowedTaskQueue(MediaTaskQueue* aTaskQueue) - { - MOZ_ASSERT(!mTaskQueue && aTaskQueue); - mTaskQueue = aTaskQueue; - mTaskQueueIsBorrowed = true; + return GetTaskQueue()->IsCurrentThreadIn(); } // Resets all state related to decoding, emptying all buffers etc. // Cancels all pending Request*Data() request callbacks, rejects any // outstanding seek promises, and flushes the decode pipeline. The // decoder must not call any of the callbacks for outstanding // Request*Data() calls after this is called. Calls to Request*Data() // made after this should be processed as usual. @@ -315,16 +306,19 @@ protected: // minimal allocation slop and then pushes them to the queue. This is // useful for decoders working with formats that give awkward numbers of // frames such as mp3. AudioCompactor mAudioCompactor; // Reference to the owning decoder object. AbstractMediaDecoder* mDecoder; + // Decode task queue. + nsRefPtr<MediaTaskQueue> mTaskQueue; + // Stores presentation info required for playback. MediaInfo mInfo; // Whether we should accept media that we know we can't play // directly, because they have a number of channel higher than // what we support. bool mIgnoreAudioOutputFormat; @@ -342,17 +336,16 @@ protected: bool mShutdown; private: // Promises used only for the base-class (sync->async adapter) implementation // of Request{Audio,Video}Data. MediaPromiseHolder<AudioDataPromise> mBaseAudioPromise; MediaPromiseHolder<VideoDataPromise> mBaseVideoPromise; - nsRefPtr<MediaTaskQueue> mTaskQueue; bool mTaskQueueIsBorrowed; // Flags whether a the next audio/video sample comes after a "gap" or // "discontinuity" in the stream. For example after a seek. bool mAudioDiscontinuity; bool mVideoDiscontinuity; };
--- a/dom/media/MediaDecoderStateMachine.cpp +++ b/dom/media/MediaDecoderStateMachine.cpp @@ -1253,20 +1253,16 @@ bool MediaDecoderStateMachine::IsPlaying AssertCurrentThreadInMonitor(); return !mPlayStartTime.IsNull(); } nsresult MediaDecoderStateMachine::Init(MediaDecoderStateMachine* aCloneDonor) { MOZ_ASSERT(NS_IsMainThread()); - if (NS_WARN_IF(!mReader->EnsureTaskQueue())) { - return NS_ERROR_FAILURE; - } - MediaDecoderReader* cloneReader = nullptr; if (aCloneDonor) { cloneReader = aCloneDonor->mReader; } nsresult rv = mReader->Init(cloneReader); NS_ENSURE_SUCCESS(rv, rv);
--- a/dom/media/MediaFormatReader.cpp +++ b/dom/media/MediaFormatReader.cpp @@ -56,18 +56,19 @@ TrackTypeToStr(TrackInfo::TrackType aTra case TrackInfo::kTextTrack: return "Text"; default: return "Unknown"; } } MediaFormatReader::MediaFormatReader(AbstractMediaDecoder* aDecoder, - MediaDataDemuxer* aDemuxer) - : MediaDecoderReader(aDecoder) + MediaDataDemuxer* aDemuxer, + MediaTaskQueue* aBorrowedTaskQueue) + : MediaDecoderReader(aDecoder, aBorrowedTaskQueue) , mDemuxer(aDemuxer) , mAudio(this, MediaData::AUDIO_DATA, Preferences::GetUint("media.audio-decode-ahead", 2)) , mVideo(this, MediaData::VIDEO_DATA, Preferences::GetUint("media.video-decode-ahead", 2)) , mLastReportedNumDecodedFrames(0) , mLayersBackendType(layers::LayersBackend::LAYERS_NONE) , mInitDone(false) , mSeekable(false) , mIsEncrypted(false)
--- a/dom/media/MediaFormatReader.h +++ b/dom/media/MediaFormatReader.h @@ -25,17 +25,18 @@ namespace mozilla { class MediaFormatReader final : public MediaDecoderReader { typedef TrackInfo::TrackType TrackType; typedef media::Interval<int64_t> ByteInterval; public: explicit MediaFormatReader(AbstractMediaDecoder* aDecoder, - MediaDataDemuxer* aDemuxer); + MediaDataDemuxer* aDemuxer, + MediaTaskQueue* aBorrowedTaskQueue = nullptr); virtual ~MediaFormatReader(); virtual nsresult Init(MediaDecoderReader* aCloneDonor) override; virtual size_t SizeOfVideoQueueInFrames() override; virtual size_t SizeOfAudioQueueInFrames() override;
--- a/dom/media/fmp4/MP4Reader.cpp +++ b/dom/media/fmp4/MP4Reader.cpp @@ -139,18 +139,18 @@ InvokeAndRetry(ThisType* aThisVal, Retur prevFailure = failure; if (NS_WARN_IF(!stream->BlockingReadIntoCache(failure.mOffset, failure.mCount, aMonitor))) { return result; } } } -MP4Reader::MP4Reader(AbstractMediaDecoder* aDecoder) - : MediaDecoderReader(aDecoder) +MP4Reader::MP4Reader(AbstractMediaDecoder* aDecoder, MediaTaskQueue* aBorrowedTaskQueue) + : MediaDecoderReader(aDecoder, aBorrowedTaskQueue) , mAudio(MediaData::AUDIO_DATA, Preferences::GetUint("media.mp4-audio-decode-ahead", 2)) , mVideo(MediaData::VIDEO_DATA, Preferences::GetUint("media.mp4-video-decode-ahead", 2)) , mLastReportedNumDecodedFrames(0) , mLayersBackendType(layers::LayersBackend::LAYERS_NONE) , mDemuxerInitialized(false) , mFoundSPSForTelemetry(false) , mIsEncrypted(false) , mIndexReady(false)
--- a/dom/media/fmp4/MP4Reader.h +++ b/dom/media/fmp4/MP4Reader.h @@ -29,17 +29,17 @@ class MP4Stream; #undef MP4_READER_DORMANT_HEURISTIC #endif class MP4Reader final : public MediaDecoderReader { typedef TrackInfo::TrackType TrackType; public: - explicit MP4Reader(AbstractMediaDecoder* aDecoder); + explicit MP4Reader(AbstractMediaDecoder* aDecoder, MediaTaskQueue* aBorrowedTaskQueue = nullptr); virtual ~MP4Reader(); virtual nsresult Init(MediaDecoderReader* aCloneDonor) override; virtual size_t SizeOfVideoQueueInFrames() override; virtual size_t SizeOfAudioQueueInFrames() override;
--- a/dom/media/gtest/TestMP4Reader.cpp +++ b/dom/media/gtest/TestMP4Reader.cpp @@ -31,17 +31,16 @@ public: { EXPECT_EQ(NS_OK, Preferences::SetBool( "media.fragmented-mp4.use-blank-decoder", true)); EXPECT_EQ(NS_OK, resource->Open(nullptr)); decoder->SetResource(resource); reader->Init(nullptr); - reader->EnsureTaskQueue(); { // This needs to be done before invoking GetBuffered. This is normally // done by MediaDecoderStateMachine. ReentrantMonitorAutoEnter mon(decoder->GetReentrantMonitor()); reader->SetStartTime(0); } }
--- a/dom/media/mediasource/MediaSourceReader.cpp +++ b/dom/media/mediasource/MediaSourceReader.cpp @@ -673,75 +673,74 @@ MediaSourceReader::ReleaseMediaResources { ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); if (GetVideoReader()) { GetVideoReader()->ReleaseMediaResources(); } } MediaDecoderReader* -CreateReaderForType(const nsACString& aType, AbstractMediaDecoder* aDecoder) +CreateReaderForType(const nsACString& aType, AbstractMediaDecoder* aDecoder, + MediaTaskQueue* aBorrowedTaskQueue) { #ifdef MOZ_FMP4 // 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) { bool useFormatDecoder = Preferences::GetBool("media.mediasource.format-reader.mp4", true); MediaDecoderReader* reader = useFormatDecoder ? - static_cast<MediaDecoderReader*>(new MediaFormatReader(aDecoder, new MP4Demuxer(aDecoder->GetResource()))) : - static_cast<MediaDecoderReader*>(new MP4Reader(aDecoder)); + static_cast<MediaDecoderReader*>(new MediaFormatReader(aDecoder, new MP4Demuxer(aDecoder->GetResource()), aBorrowedTaskQueue)) : + static_cast<MediaDecoderReader*>(new MP4Reader(aDecoder, aBorrowedTaskQueue)); return reader; } #endif #ifdef MOZ_WEBM if (DecoderTraits::IsWebMType(aType)) { - return new WebMReader(aDecoder); + return new WebMReader(aDecoder, aBorrowedTaskQueue); } #endif return nullptr; } already_AddRefed<SourceBufferDecoder> MediaSourceReader::CreateSubDecoder(const nsACString& aType, int64_t aTimestampOffset) { if (IsShutdown()) { return nullptr; } - MOZ_ASSERT(GetTaskQueue()); + + // The task queue borrowing is icky. It would be nicer to just give each subreader + // its own task queue. Unfortunately though, Request{Audio,Video}Data implementations + // currently assert that they're on "the decode thread", and so having + // separate task queues makes MediaSource stuff unnecessarily cumbersome. We + // should remove the need for these assertions (which probably involves making + // all Request*Data implementations fully async), and then get rid of the + // borrowing. nsRefPtr<SourceBufferDecoder> decoder = new SourceBufferDecoder(new SourceBufferResource(aType), mDecoder, aTimestampOffset); - nsRefPtr<MediaDecoderReader> reader(CreateReaderForType(aType, decoder)); + nsRefPtr<MediaDecoderReader> reader(CreateReaderForType(aType, decoder, GetTaskQueue())); if (!reader) { return nullptr; } // MSE uses a start time of 0 everywhere. Set that immediately on the // subreader to make sure that it's always in a state where we can invoke // GetBuffered on it. { ReentrantMonitorAutoEnter mon(decoder->GetReentrantMonitor()); reader->SetStartTime(0); } - // This part is icky. It would be nicer to just give each subreader its own - // task queue. Unfortunately though, Request{Audio,Video}Data implementations - // currently assert that they're on "the decode thread", and so having - // separate task queues makes MediaSource stuff unnecessarily cumbersome. We - // should remove the need for these assertions (which probably involves making - // all Request*Data implementations fully async), and then get rid of the - // borrowing. - reader->SetBorrowedTaskQueue(GetTaskQueue()); - #ifdef MOZ_FMP4 reader->SetSharedDecoderManager(mSharedDecoderManager); #endif reader->Init(nullptr); MSE_DEBUG("subdecoder %p subreader %p", decoder.get(), reader.get()); decoder->SetReader(reader);
--- a/dom/media/webaudio/MediaBufferDecoder.cpp +++ b/dom/media/webaudio/MediaBufferDecoder.cpp @@ -206,20 +206,16 @@ MediaDecodeTask::CreateReader() return false; } nsresult rv = mDecoderReader->Init(nullptr); if (NS_FAILED(rv)) { return false; } - if (!mDecoderReader->EnsureTaskQueue()) { - return false; - } - return true; } class AutoResampler final { public: AutoResampler() : mResampler(nullptr)
--- a/dom/media/webm/WebMReader.cpp +++ b/dom/media/webm/WebMReader.cpp @@ -156,18 +156,18 @@ ogg_packet InitOggPacket(const unsigned packet.packetno = aPacketNo; return packet; } #if defined(MOZ_PDM_VPX) static bool sIsIntelDecoderEnabled = false; #endif -WebMReader::WebMReader(AbstractMediaDecoder* aDecoder) - : MediaDecoderReader(aDecoder) +WebMReader::WebMReader(AbstractMediaDecoder* aDecoder, MediaTaskQueue* aBorrowedTaskQueue) + : MediaDecoderReader(aDecoder, aBorrowedTaskQueue) , mContext(nullptr) , mPacketCount(0) , mOpusDecoder(nullptr) , mSkip(0) , mSeekPreroll(0) , mVideoTrack(0) , mAudioTrack(0) , mAudioStartUsec(-1)
--- a/dom/media/webm/WebMReader.h +++ b/dom/media/webm/WebMReader.h @@ -136,17 +136,17 @@ public: int64_t aTimeThreshold) = 0; WebMVideoDecoder() {} virtual ~WebMVideoDecoder() {} }; class WebMReader : public MediaDecoderReader { public: - explicit WebMReader(AbstractMediaDecoder* aDecoder); + explicit WebMReader(AbstractMediaDecoder* aDecoder, MediaTaskQueue* aBorrowedTaskQueue = nullptr); protected: ~WebMReader(); public: virtual nsRefPtr<ShutdownPromise> Shutdown() override; virtual nsresult Init(MediaDecoderReader* aCloneDonor) override; virtual nsresult ResetDecode() override;