already_AddRefed<SourceBufferDecoder> MediaSourceReader::CreateSubDecoder(const nsACString& aType) { if (IsShutdown()) { return nullptr; } MOZ_ASSERT(GetTaskQueue()); nsRefPtr<SourceBufferDecoder> decoder = new SourceBufferDecoder(new SourceBufferResource(aType), mDecoder); nsRefPtr<MediaDecoderReader> reader(CreateReaderForType(aType, decoder)); if (!reader) { return nullptr; } // Set a callback on the subreader that forwards calls to this reader. // This reader will then forward them onto the state machine via this // reader's callback. RefPtr<MediaDataDecodedListener<MediaSourceReader>> callback = new MediaDataDecodedListener<MediaSourceReader>(this, GetTaskQueue()); reader->SetCallback(callback); reader->SetTaskQueue(GetTaskQueue()); reader->Init(nullptr); MSE_DEBUG("MediaSourceReader(%p)::CreateSubDecoder subdecoder %p subreader %p", this, decoder.get(), reader.get()); decoder->SetReader(reader); return decoder.forget(); }
already_AddRefed<SourceBufferDecoder> MediaSourceReader::CreateSubDecoder(const nsACString& aType, int64_t aTimestampOffset) { if (IsShutdown()) { return nullptr; } MOZ_ASSERT(GetTaskQueue()); nsRefPtr<SourceBufferDecoder> decoder = new SourceBufferDecoder(new SourceBufferResource(aType), mDecoder, aTimestampOffset); nsRefPtr<MediaDecoderReader> reader(CreateReaderForType(aType, decoder)); 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); #ifdef MOZ_EME decoder->SetCDMProxy(mCDMProxy); #endif return decoder.forget(); }
already_AddRefed<SourceBufferDecoder> MediaSourceReader::CreateSubDecoder(const nsACString& aType) { if (IsShutdown()) { return nullptr; } MOZ_ASSERT(GetTaskQueue()); nsRefPtr<SourceBufferDecoder> decoder = new SourceBufferDecoder(new SourceBufferResource(aType), mDecoder); nsRefPtr<MediaDecoderReader> reader(CreateReaderForType(aType, decoder)); 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); } // Set a callback on the subreader that forwards calls to this reader. // This reader will then forward them onto the state machine via this // reader's callback. RefPtr<MediaDataDecodedListener<MediaSourceReader>> callback = new MediaDataDecodedListener<MediaSourceReader>(this, GetTaskQueue()); reader->SetCallback(callback); reader->SetTaskQueue(GetTaskQueue()); reader->Init(nullptr); MSE_DEBUG("MediaSourceReader(%p)::CreateSubDecoder subdecoder %p subreader %p", this, decoder.get(), reader.get()); decoder->SetReader(reader); #ifdef MOZ_EME decoder->SetCDMProxy(mCDMProxy); #endif return decoder.forget(); }