зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1194606 - Make MediaDecoderStateMachine capable of requesting different kind (decoded/raw) of media data. r=jya
This commit is contained in:
Родитель
abeada522e
Коммит
f01266ed3f
|
@ -153,6 +153,14 @@ public:
|
|||
virtual bool IsWaitForDataSupported() { return false; }
|
||||
virtual RefPtr<WaitForDataPromise> WaitForData(MediaData::Type aType) { MOZ_CRASH(); }
|
||||
|
||||
// By default, the reader return the decoded data. Some readers support
|
||||
// retuning demuxed data.
|
||||
virtual bool IsDemuxOnlySupported() const { return false; }
|
||||
|
||||
// Configure the reader to return demuxed or decoded data
|
||||
// upon calls to Request{Audio,Video}Data.
|
||||
virtual void SetDemuxOnly(bool /*aDemuxedOnly*/) {}
|
||||
|
||||
virtual bool HasAudio() = 0;
|
||||
virtual bool HasVideo() = 0;
|
||||
|
||||
|
|
|
@ -354,6 +354,8 @@ private:
|
|||
// be held.
|
||||
bool IsPlaying() const;
|
||||
|
||||
// TODO: Those callback function may receive demuxed-only data.
|
||||
// Need to figure out a suitable API name for this case.
|
||||
void OnAudioDecoded(MediaData* aAudioSample);
|
||||
void OnVideoDecoded(MediaData* aVideoSample);
|
||||
void OnNotDecoded(MediaData::Type aType, MediaDecoderReader::NotDecodedReason aReason);
|
||||
|
|
|
@ -74,6 +74,7 @@ MediaFormatReader::MediaFormatReader(AbstractMediaDecoder* aDecoder,
|
|||
, mIsEncrypted(false)
|
||||
, mTrackDemuxersMayBlock(false)
|
||||
, mHardwareAccelerationDisabled(false)
|
||||
, mDemuxOnly(false)
|
||||
, mVideoFrameContainer(aVideoFrameContainer)
|
||||
{
|
||||
MOZ_ASSERT(aDemuxer);
|
||||
|
@ -570,7 +571,7 @@ MediaFormatReader::ShouldSkip(bool aSkipToNextKeyframe, media::TimeUnit aTimeThr
|
|||
|
||||
RefPtr<MediaDecoderReader::VideoDataPromise>
|
||||
MediaFormatReader::RequestVideoData(bool aSkipToNextKeyframe,
|
||||
int64_t aTimeThreshold)
|
||||
int64_t aTimeThreshold)
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
MOZ_DIAGNOSTIC_ASSERT(mSeekPromise.IsEmpty(), "No sample requests allowed while seeking");
|
||||
|
@ -901,8 +902,21 @@ MediaFormatReader::RequestDemuxSamples(TrackType aTrack)
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
MediaFormatReader::DecodeDemuxedSamples(TrackType aTrack,
|
||||
MediaRawData* aSample)
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
auto& decoder = GetDecoderData(aTrack);
|
||||
if (NS_FAILED(decoder.mDecoder->Input(aSample))) {
|
||||
LOG("Unable to pass frame to decoder");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
MediaFormatReader::HandleDemuxedSamples(TrackType aTrack,
|
||||
AbstractMediaDecoder::AutoNotifyDecoded& aA)
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
|
@ -1005,12 +1019,20 @@ MediaFormatReader::DecodeDemuxedSamples(TrackType aTrack,
|
|||
if (aTrack == TrackInfo::kVideoTrack) {
|
||||
aA.mParsed++;
|
||||
}
|
||||
if (NS_FAILED(decoder.mDecoder->Input(sample))) {
|
||||
LOG("Unable to pass frame to decoder");
|
||||
|
||||
if (mDemuxOnly) {
|
||||
ReturnOutput(sample, aTrack);
|
||||
} else if (!DecodeDemuxedSamples(aTrack, sample)) {
|
||||
NotifyError(aTrack);
|
||||
return;
|
||||
}
|
||||
|
||||
decoder.mQueuedSamples.RemoveElementAt(0);
|
||||
if (mDemuxOnly) {
|
||||
// If demuxed-only case, ReturnOutput will resolve with one demuxed data.
|
||||
// Then we should stop doing the iteration.
|
||||
return;
|
||||
}
|
||||
samplesPending = true;
|
||||
}
|
||||
|
||||
|
@ -1150,8 +1172,8 @@ MediaFormatReader::Update(TrackType aTrack)
|
|||
|
||||
// Demux samples if we don't have some.
|
||||
RequestDemuxSamples(aTrack);
|
||||
// Decode all pending demuxed samples.
|
||||
DecodeDemuxedSamples(aTrack, a);
|
||||
|
||||
HandleDemuxedSamples(aTrack, a);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1166,19 +1188,21 @@ MediaFormatReader::ReturnOutput(MediaData* aData, TrackType aTrack)
|
|||
}
|
||||
|
||||
if (aTrack == TrackInfo::kAudioTrack) {
|
||||
AudioData* audioData = static_cast<AudioData*>(aData);
|
||||
if (aData->mType != MediaData::RAW_DATA) {
|
||||
AudioData* audioData = static_cast<AudioData*>(aData);
|
||||
|
||||
if (audioData->mChannels != mInfo.mAudio.mChannels ||
|
||||
audioData->mRate != mInfo.mAudio.mRate) {
|
||||
LOG("change of audio format (rate:%d->%d). "
|
||||
"This is an unsupported configuration",
|
||||
mInfo.mAudio.mRate, audioData->mRate);
|
||||
mInfo.mAudio.mRate = audioData->mRate;
|
||||
mInfo.mAudio.mChannels = audioData->mChannels;
|
||||
if (audioData->mChannels != mInfo.mAudio.mChannels ||
|
||||
audioData->mRate != mInfo.mAudio.mRate) {
|
||||
LOG("change of audio format (rate:%d->%d). "
|
||||
"This is an unsupported configuration",
|
||||
mInfo.mAudio.mRate, audioData->mRate);
|
||||
mInfo.mAudio.mRate = audioData->mRate;
|
||||
mInfo.mAudio.mChannels = audioData->mChannels;
|
||||
}
|
||||
}
|
||||
mAudio.mPromise.Resolve(audioData, __func__);
|
||||
mAudio.mPromise.Resolve(aData, __func__);
|
||||
} else if (aTrack == TrackInfo::kVideoTrack) {
|
||||
mVideo.mPromise.Resolve(static_cast<VideoData*>(aData), __func__);
|
||||
mVideo.mPromise.Resolve(aData, __func__);
|
||||
}
|
||||
LOG("Resolved data promise for %s", TrackTypeToStr(aTrack));
|
||||
}
|
||||
|
|
|
@ -89,6 +89,20 @@ public:
|
|||
bool IsWaitForDataSupported() override { return true; }
|
||||
RefPtr<WaitForDataPromise> WaitForData(MediaData::Type aType) override;
|
||||
|
||||
// MediaFormatReader supports demuxed-only mode.
|
||||
bool IsDemuxOnlySupported() const override { return true; }
|
||||
|
||||
void SetDemuxOnly(bool aDemuxedOnly) override
|
||||
{
|
||||
if (OnTaskQueue()) {
|
||||
mDemuxOnly = aDemuxedOnly;
|
||||
return;
|
||||
}
|
||||
nsCOMPtr<nsIRunnable> r = NS_NewRunnableMethodWithArg<bool>(
|
||||
this, &MediaDecoderReader::SetDemuxOnly, aDemuxedOnly);
|
||||
OwnerThread()->Dispatch(r.forget());
|
||||
}
|
||||
|
||||
bool UseBufferingHeuristics() override
|
||||
{
|
||||
return mTrackDemuxersMayBlock;
|
||||
|
@ -123,9 +137,12 @@ private:
|
|||
bool UpdateReceivedNewData(TrackType aTrack);
|
||||
// Called when new samples need to be demuxed.
|
||||
void RequestDemuxSamples(TrackType aTrack);
|
||||
// Decode any pending already demuxed samples.
|
||||
void DecodeDemuxedSamples(TrackType aTrack,
|
||||
// Handle demuxed samples by the input behavior.
|
||||
void HandleDemuxedSamples(TrackType aTrack,
|
||||
AbstractMediaDecoder::AutoNotifyDecoded& aA);
|
||||
// Decode any pending already demuxed samples.
|
||||
bool DecodeDemuxedSamples(TrackType aTrack,
|
||||
MediaRawData* aSample);
|
||||
// Drain the current decoder.
|
||||
void DrainDecoder(TrackType aTrack);
|
||||
void NotifyNewOutput(TrackType aTrack, MediaData* aSample);
|
||||
|
@ -407,6 +424,9 @@ private:
|
|||
|
||||
bool mHardwareAccelerationDisabled;
|
||||
|
||||
// Set the demuxed-only flag.
|
||||
Atomic<bool> mDemuxOnly;
|
||||
|
||||
// Seeking objects.
|
||||
bool IsSeeking() const { return mPendingSeekTime.isSome(); }
|
||||
void AttemptSeek();
|
||||
|
|
Загрузка…
Ссылка в новой задаче