Bug 1194606 - Make MediaDecoderStateMachine capable of requesting different kind (decoded/raw) of media data. r=jya

This commit is contained in:
James Cheng 2015-10-20 05:33:00 -04:00
Родитель abeada522e
Коммит f01266ed3f
4 изменённых файлов: 72 добавлений и 18 удалений

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

@ -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();