Backed out 11 changesets (bug 1297265) for gtest timeouts during MediaDataDecoder.H264

Backed out changeset 04d9b7160ac9 (bug 1297265)
Backed out changeset c7bffd1ba7fd (bug 1297265)
Backed out changeset ad1915ff688b (bug 1297265)
Backed out changeset 67a97304d44d (bug 1297265)
Backed out changeset e6b9e6184457 (bug 1297265)
Backed out changeset 30636ac0790f (bug 1297265)
Backed out changeset cc70d3a139bc (bug 1297265)
Backed out changeset 345a577c92a1 (bug 1297265)
Backed out changeset ec1f3ac8751c (bug 1297265)
Backed out changeset da9117375d2e (bug 1297265)
Backed out changeset dd4c7aafcc3d (bug 1297265)
This commit is contained in:
Phil Ringnalda 2016-08-31 19:49:28 -07:00
Родитель 73811a0f67
Коммит 9f470c98e5
14 изменённых файлов: 118 добавлений и 69 удалений

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

@ -62,9 +62,9 @@ MediaFormatReader::MediaFormatReader(AbstractMediaDecoder* aDecoder,
VideoFrameContainer* aVideoFrameContainer,
layers::LayersBackend aLayersBackend)
: MediaDecoderReader(aDecoder)
, mAudio(this, MediaData::AUDIO_DATA,
, mAudio(this, MediaData::AUDIO_DATA, Preferences::GetUint("media.audio-decode-ahead", 2),
Preferences::GetUint("media.audio-max-decode-error", 3))
, mVideo(this, MediaData::VIDEO_DATA,
, mVideo(this, MediaData::VIDEO_DATA, Preferences::GetUint("media.video-decode-ahead", 2),
Preferences::GetUint("media.video-max-decode-error", 2))
, mDemuxer(aDemuxer)
, mDemuxerInitDone(false)
@ -562,7 +562,7 @@ MediaFormatReader::RequestVideoData(bool aSkipToNextKeyframe,
}
RefPtr<MediaDataPromise> p = mVideo.EnsurePromise(__func__);
ScheduleUpdate(TrackInfo::kVideoTrack);
NotifyDecodingRequested(TrackInfo::kVideoTrack);
return p;
}
@ -606,6 +606,7 @@ MediaFormatReader::OnDemuxFailed(TrackType aTrack, DemuxerFailureReason aFailure
void
MediaFormatReader::DoDemuxVideo()
{
// TODO Use DecodeAhead value rather than 1.
mVideo.mDemuxRequest.Begin(mVideo.mTrackDemuxer->GetSamples(1)
->Then(OwnerThread(), __func__, this,
&MediaFormatReader::OnVideoDemuxCompleted,
@ -656,7 +657,7 @@ MediaFormatReader::RequestAudioData()
}
RefPtr<MediaDataPromise> p = mAudio.EnsurePromise(__func__);
ScheduleUpdate(TrackInfo::kAudioTrack);
NotifyDecodingRequested(TrackInfo::kAudioTrack);
return p;
}
@ -664,6 +665,7 @@ MediaFormatReader::RequestAudioData()
void
MediaFormatReader::DoDemuxAudio()
{
// TODO Use DecodeAhead value rather than 1.
mAudio.mDemuxRequest.Begin(mAudio.mTrackDemuxer->GetSamples(1)
->Then(OwnerThread(), __func__, this,
&MediaFormatReader::OnAudioDemuxCompleted,
@ -695,7 +697,6 @@ MediaFormatReader::NotifyNewOutput(TrackType aTrack, MediaData* aSample)
decoder.mOutput.AppendElement(aSample);
decoder.mNumSamplesOutput++;
decoder.mNumOfConsecutiveError = 0;
decoder.mDecodePending = false;
ScheduleUpdate(aTrack);
}
@ -705,7 +706,7 @@ MediaFormatReader::NotifyInputExhausted(TrackType aTrack)
MOZ_ASSERT(OnTaskQueue());
LOGV("Decoder has requested more %s data", TrackTypeToStr(aTrack));
auto& decoder = GetDecoderData(aTrack);
decoder.mDecodePending = false;
decoder.mInputExhausted = true;
ScheduleUpdate(aTrack);
}
@ -754,21 +755,33 @@ MediaFormatReader::NotifyEndOfStream(TrackType aTrack)
ScheduleUpdate(aTrack);
}
void
MediaFormatReader::NotifyDecodingRequested(TrackType aTrack)
{
MOZ_ASSERT(OnTaskQueue());
auto& decoder = GetDecoderData(aTrack);
decoder.mDecodingRequested = true;
ScheduleUpdate(aTrack);
}
bool
MediaFormatReader::NeedInput(DecoderData& aDecoder)
{
// To account for H.264 streams which may require a longer
// run of input than we input, decoders fire an "input exhausted" callback.
// The decoder will not be fed a new raw sample until either Output callback
// has been called, or InputExhausted was called.
// We try to keep a few more compressed samples input than decoded samples
// have been output, provided the state machine has requested we send it a
// decoded sample. To account for H.264 streams which may require a longer
// run of input than we input, decoders fire an "input exhausted" callback,
// which overrides our "few more samples" threshold.
return
(aDecoder.HasPromise() || aDecoder.mTimeThreshold.isSome()) &&
!aDecoder.HasPendingDrain() &&
!aDecoder.HasFatalError() &&
aDecoder.mDecodingRequested &&
!aDecoder.mDemuxRequest.Exists() &&
!aDecoder.mOutput.Length() &&
!aDecoder.HasInternalSeekPending() &&
!aDecoder.mDecodePending;
aDecoder.mOutput.Length() <= aDecoder.mDecodeAhead &&
(aDecoder.mInputExhausted || !aDecoder.mQueuedSamples.IsEmpty() ||
aDecoder.mTimeThreshold.isSome() ||
aDecoder.mNumSamplesInput - aDecoder.mNumSamplesOutput <= aDecoder.mDecodeAhead);
}
void
@ -919,7 +932,6 @@ MediaFormatReader::DecodeDemuxedSamples(TrackType aTrack,
LOG("Unable to pass frame to decoder");
return false;
}
decoder.mDecodePending = true;
return true;
}
@ -995,7 +1007,7 @@ MediaFormatReader::HandleDemuxedSamples(TrackType aTrack,
decoder.ShutdownDecoder();
if (sample->mKeyframe) {
decoder.mQueuedSamples.AppendElements(Move(samples));
ScheduleUpdate(aTrack);
NotifyDecodingRequested(aTrack);
} else {
TimeInterval time =
TimeInterval(TimeUnit::FromMicroseconds(sample->mTime),
@ -1033,6 +1045,9 @@ MediaFormatReader::HandleDemuxedSamples(TrackType aTrack,
}
samplesPending = true;
}
// We have serviced the decoder's request for more data.
decoder.mInputExhausted = false;
}
void
@ -1056,7 +1071,7 @@ MediaFormatReader::InternalSeek(TrackType aTrack, const InternalSeekTarget& aTar
"Seek promise must be disconnected when timethreshold is reset");
decoder.mTimeThreshold.ref().mHasSeeked = true;
self->SetVideoDecodeThreshold();
self->ScheduleUpdate(aTrack);
self->NotifyDecodingRequested(aTrack);
},
[self, aTrack] (DemuxerFailureReason aResult) {
auto& decoder = self->GetDecoderData(aTrack);
@ -1260,7 +1275,6 @@ MediaFormatReader::Update(TrackType aTrack)
if (decoder.mError &&
decoder.mError.ref() == MediaDataDecoderError::DECODE_ERROR) {
decoder.mDecodePending = false;
decoder.mError.reset();
if (++decoder.mNumOfConsecutiveError > decoder.mMaxConsecutiveError) {
NotifyError(aTrack);
@ -1278,11 +1292,11 @@ MediaFormatReader::Update(TrackType aTrack)
bool needInput = NeedInput(decoder);
LOGV("Update(%s) ni=%d no=%d ie=%d, in:%llu out:%llu qs=%u pending:%u waiting:%d promise:%d sid:%u",
TrackTypeToStr(aTrack), needInput, needOutput, decoder.mDecodePending,
LOGV("Update(%s) ni=%d no=%d ie=%d, in:%llu out:%llu qs=%u pending:%u waiting:%d ahead:%d sid:%u",
TrackTypeToStr(aTrack), needInput, needOutput, decoder.mInputExhausted,
decoder.mNumSamplesInput, decoder.mNumSamplesOutput,
uint32_t(size_t(decoder.mSizeOfQueue)), uint32_t(decoder.mOutput.Length()),
decoder.mWaitingForData, decoder.HasPromise(), decoder.mLastStreamSourceID);
decoder.mWaitingForData, !decoder.HasPromise(), decoder.mLastStreamSourceID);
if (decoder.mWaitingForData &&
(!decoder.mTimeThreshold || decoder.mTimeThreshold.ref().mWaiting)) {
@ -1563,7 +1577,7 @@ MediaFormatReader::OnVideoSkipCompleted(uint32_t aSkipped)
VideoSkipReset(aSkipped);
ScheduleUpdate(TrackInfo::kVideoTrack);
NotifyDecodingRequested(TrackInfo::kVideoTrack);
}
void
@ -1581,7 +1595,7 @@ MediaFormatReader::OnVideoSkipFailed(MediaTrackDemuxer::SkipFailureHolder aFailu
DropDecodedSamples(TrackInfo::kVideoTrack);
// We can't complete the skip operation, will just service a video frame
// normally.
ScheduleUpdate(TrackInfo::kVideoTrack);
NotifyDecodingRequested(TrackInfo::kVideoTrack);
break;
case DemuxerFailureReason::CANCELED: MOZ_FALLTHROUGH;
case DemuxerFailureReason::SHUTDOWN:
@ -1999,11 +2013,12 @@ MediaFormatReader::GetMozDebugReaderData(nsAString& aString)
result += nsPrintfCString("audio frames decoded: %lld\n",
mAudio.mNumSamplesOutputTotal);
if (HasAudio()) {
result += nsPrintfCString("audio state: ni=%d no=%d ie=%d demuxr:%d demuxq:%d tt:%f tths:%d in:%llu out:%llu qs=%u pending:%u waiting:%d sid:%u\n",
result += nsPrintfCString("audio state: ni=%d no=%d ie=%d demuxr:%d demuxq:%d decoder:%d tt:%f tths:%d in:%llu out:%llu qs=%u pending:%u waiting:%d sid:%u\n",
NeedInput(mAudio), mAudio.HasPromise(),
mAudio.mDecodePending,
mAudio.mInputExhausted,
mAudio.mDemuxRequest.Exists(),
int(mAudio.mQueuedSamples.Length()),
mAudio.mDecodingRequested,
mAudio.mTimeThreshold
? mAudio.mTimeThreshold.ref().Time().ToSeconds()
: -1.0,
@ -2022,11 +2037,12 @@ MediaFormatReader::GetMozDebugReaderData(nsAString& aString)
mVideo.mNumSamplesOutputTotal,
mVideo.mNumSamplesSkippedTotal);
if (HasVideo()) {
result += nsPrintfCString("video state: ni=%d no=%d ie=%d demuxr:%d demuxq:%d tt:%f tths:%d in:%llu out:%llu qs=%u pending:%u waiting:%d sid:%u\n",
result += nsPrintfCString("video state: ni=%d no=%d ie=%d demuxr:%d demuxq:%d decoder:%d tt:%f tths:%d in:%llu out:%llu qs=%u pending:%u waiting:%d sid:%u\n",
NeedInput(mVideo), mVideo.HasPromise(),
mVideo.mDecodePending,
mVideo.mInputExhausted,
mVideo.mDemuxRequest.Exists(),
int(mVideo.mQueuedSamples.Length()),
mVideo.mDecodingRequested,
mVideo.mTimeThreshold
? mVideo.mTimeThreshold.ref().Time().ToSeconds()
: -1.0,
@ -2064,7 +2080,7 @@ MediaFormatReader::SetBlankDecode(TrackType aTrack, bool aIsBlankDecode)
decoder.mIsBlankDecode = aIsBlankDecode;
decoder.Flush();
decoder.ShutdownDecoder();
ScheduleUpdate(TrackInfo::kVideoTrack);
NotifyDecodingRequested(TrackInfo::kVideoTrack); // Calls ScheduleUpdate().
return;
}

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

@ -169,6 +169,7 @@ private:
void NotifyError(TrackType aTrack, MediaDataDecoderError aError = MediaDataDecoderError::FATAL_ERROR);
void NotifyWaitingForData(TrackType aTrack);
void NotifyEndOfStream(TrackType aTrack);
void NotifyDecodingRequested(TrackType aTrack);
void ExtractCryptoInitData(nsTArray<uint8_t>& aInitData);
@ -230,18 +231,21 @@ private:
struct DecoderData {
DecoderData(MediaFormatReader* aOwner,
MediaData::Type aType,
uint32_t aDecodeAhead,
uint32_t aNumOfMaxError)
: mOwner(aOwner)
, mType(aType)
, mMonitor("DecoderData")
, mDescription("shutdown")
, mDecodeAhead(aDecodeAhead)
, mUpdateScheduled(false)
, mDemuxEOS(false)
, mWaitingForData(false)
, mReceivedNewData(false)
, mDecoderInitialized(false)
, mDecodingRequested(false)
, mOutputRequested(false)
, mDecodePending(false)
, mInputExhausted(false)
, mNeedDraining(false)
, mDraining(false)
, mDrainComplete(false)
@ -284,6 +288,7 @@ private:
}
// Only accessed from reader's task queue.
uint32_t mDecodeAhead;
bool mUpdateScheduled;
bool mDemuxEOS;
bool mWaitingForData;
@ -307,14 +312,11 @@ private:
MozPromiseRequestHolder<MediaDataDecoder::InitPromise> mInitPromise;
// False when decoder is created. True when decoder Init() promise is resolved.
bool mDecoderInitialized;
// Set when decoding can proceed. It is reset when a decoding promise is
// rejected or prior a seek operation.
bool mDecodingRequested;
bool mOutputRequested;
// Set to true once the MediaDataDecoder has been fed a compressed sample.
// No more sample will be passed to the decoder while true.
// mDecodePending is reset when:
// 1- The decoder returns a sample
// 2- The decoder calls InputExhausted
// 3- The decoder is Flushed or Reset.
bool mDecodePending;
bool mInputExhausted;
bool mNeedDraining;
bool mDraining;
bool mDrainComplete;
@ -374,8 +376,9 @@ private:
if (mDecoder) {
mDecoder->Flush();
}
mDecodingRequested = false;
mOutputRequested = false;
mDecodePending = false;
mInputExhausted = false;
mOutput.Clear();
mNumSamplesInput = 0;
mNumSamplesOutput = 0;
@ -394,9 +397,10 @@ private:
mDemuxEOS = false;
mWaitingForData = false;
mQueuedSamples.Clear();
mDecodingRequested = false;
mOutputRequested = false;
mInputExhausted = false;
mNeedDraining = false;
mDecodePending = false;
mDraining = false;
mDrainComplete = false;
mTimeThreshold.reset();
@ -437,8 +441,9 @@ private:
public:
DecoderDataWithPromise(MediaFormatReader* aOwner,
MediaData::Type aType,
uint32_t aDecodeAhead,
uint32_t aNumOfMaxError)
: DecoderData(aOwner, aType, aNumOfMaxError)
: DecoderData(aOwner, aType, aDecodeAhead, aNumOfMaxError)
, mHasPromise(false)
{}
@ -467,6 +472,7 @@ private:
{
MOZ_ASSERT(mOwner->OnTaskQueue());
mPromise.Reject(aReason, aMethodName);
mDecodingRequested = false;
mHasPromise = false;
}

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

@ -175,8 +175,6 @@ public:
// Denotes that the last input sample has been inserted into the decoder,
// and no more output can be produced unless more input is sent.
// InputExhausted should only be called if no decoded samples were returned
// from the last input.
virtual void InputExhausted() = 0;
virtual void DrainComplete() = 0;

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

@ -93,13 +93,14 @@ private:
// Frames come out in DTS order but we need to output them in PTS order.
mReorderQueue.Push(aData);
while (mReorderQueue.Length() > mMaxRefFrames) {
mCallback->Output(mReorderQueue.Pop().get());
}
if (mReorderQueue.Length() <= mMaxRefFrames) {
mCallback->InputExhausted();
} else {
while (mReorderQueue.Length() > mMaxRefFrames) {
mCallback->Output(mReorderQueue.Pop().get());
}
}
}
private:

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

@ -165,6 +165,10 @@ OpusDataDecoder::ProcessDecode(MediaRawData* aSample)
case DecodeError::DECODE_SUCCESS:
break;
}
if (mTaskQueue->IsEmpty()) {
mCallback->InputExhausted();
}
}
OpusDataDecoder::DecodeError

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

@ -202,6 +202,8 @@ TheoraDecoder::ProcessDecode(MediaRawData* aSample)
}
if (DoDecode(aSample) == -1) {
mCallback->Error(MediaDataDecoderError::DECODE_ERROR);
} else if (mTaskQueue->IsEmpty()) {
mCallback->InputExhausted();
}
}

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

@ -121,7 +121,6 @@ VPXDecoder::DoDecode(MediaRawData* aSample)
vpx_codec_iter_t iter = nullptr;
vpx_image_t *img;
bool didOutput = false;
while ((img = vpx_codec_get_frame(&mVPX, &iter))) {
NS_ASSERTION(img->fmt == VPX_IMG_FMT_I420 ||
@ -180,10 +179,6 @@ VPXDecoder::DoDecode(MediaRawData* aSample)
return -1;
}
mCallback->Output(v);
didOutput = true;
}
if (!didOutput) {
mCallback->InputExhausted();
}
return 0;
}
@ -197,6 +192,8 @@ VPXDecoder::ProcessDecode(MediaRawData* aSample)
}
if (DoDecode(aSample) == -1) {
mCallback->Error(MediaDataDecoderError::DECODE_ERROR);
} else if (mTaskQueue->IsEmpty()) {
mCallback->InputExhausted();
}
}

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

@ -143,6 +143,8 @@ VorbisDataDecoder::ProcessDecode(MediaRawData* aSample)
}
if (DoDecode(aSample) == -1) {
mCallback->Error(MediaDataDecoderError::DECODE_ERROR);
} else if (mTaskQueue->IsEmpty()) {
mCallback->InputExhausted();
}
}

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

@ -214,7 +214,9 @@ AppleATDecoder::SubmitSample(MediaRawData* aSample)
}
}
mQueuedSamples.Clear();
} else {
}
if (mTaskQueue->IsEmpty()) {
mCallback->InputExhausted();
}
}
@ -280,9 +282,6 @@ AppleATDecoder::DecodeSample(MediaRawData* aSample)
} while (true);
if (outputData.IsEmpty()) {
// We aren't going to output anything, inform the reader that we need more
// data.
mCallback->InputExhausted();
return NS_OK;
}

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

@ -34,9 +34,11 @@ AppleVTDecoder::AppleVTDecoder(const VideoInfo& aConfig,
, mPictureHeight(aConfig.mImage.height)
, mDisplayWidth(aConfig.mDisplay.width)
, mDisplayHeight(aConfig.mDisplay.height)
, mQueuedSamples(0)
, mTaskQueue(aTaskQueue)
, mMaxRefFrames(mp4_demuxer::H264::ComputeMaxRefFrames(aConfig.mExtraData))
, mImageContainer(aImageContainer)
, mInputIncoming(0)
, mIsShutDown(false)
#ifdef MOZ_WIDGET_UIKIT
, mUseSoftwareImages(true)
@ -86,6 +88,8 @@ AppleVTDecoder::Input(MediaRawData* aSample)
aSample->mKeyframe ? " keyframe" : "",
aSample->Size());
mInputIncoming++;
mTaskQueue->Dispatch(NewRunnableMethod<RefPtr<MediaRawData>>(
this, &AppleVTDecoder::ProcessDecode, aSample));
return NS_OK;
@ -100,6 +104,8 @@ AppleVTDecoder::Flush()
NewRunnableMethod(this, &AppleVTDecoder::ProcessFlush);
SyncRunnable::DispatchToThread(mTaskQueue, runnable);
mIsFlushing = false;
// All ProcessDecode() tasks should be done.
MOZ_ASSERT(mInputIncoming == 0);
mSeekTargetThreshold.reset();
@ -136,11 +142,18 @@ AppleVTDecoder::ProcessDecode(MediaRawData* aSample)
{
AssertOnTaskQueueThread();
mInputIncoming--;
if (mIsFlushing) {
return NS_OK;
}
auto rv = DoDecode(aSample);
// Ask for more data.
if (NS_SUCCEEDED(rv) && !mInputIncoming && mQueuedSamples <= mMaxRefFrames) {
LOG("%s task queue empty; requesting more data", GetDescriptionName());
mCallback->InputExhausted();
}
return rv;
}
@ -200,6 +213,7 @@ AppleVTDecoder::DrainReorderedFrames()
while (!mReorderQueue.IsEmpty()) {
mCallback->Output(mReorderQueue.Pop().get());
}
mQueuedSamples = 0;
}
void
@ -209,6 +223,7 @@ AppleVTDecoder::ClearReorderedFrames()
while (!mReorderQueue.IsEmpty()) {
mReorderQueue.Pop();
}
mQueuedSamples = 0;
}
void
@ -273,10 +288,16 @@ AppleVTDecoder::OutputFrame(CVPixelBufferRef aImage,
aFrameRef.is_sync_point ? " keyframe" : ""
);
if (!aImage) {
// Image was dropped by decoder or none return yet.
// We need more input to continue.
if (mQueuedSamples > mMaxRefFrames) {
// We had stopped requesting more input because we had received too much at
// the time. We can ask for more once again.
mCallback->InputExhausted();
}
MOZ_ASSERT(mQueuedSamples);
mQueuedSamples--;
if (!aImage) {
// Image was dropped by decoder.
return NS_OK;
}
@ -389,10 +410,8 @@ AppleVTDecoder::OutputFrame(CVPixelBufferRef aImage,
// in composition order.
MonitorAutoLock mon(mMonitor);
mReorderQueue.Push(data);
if (mReorderQueue.Length() > mMaxRefFrames) {
while (mReorderQueue.Length() > mMaxRefFrames) {
mCallback->Output(mReorderQueue.Pop().get());
} else {
mCallback->InputExhausted();
}
LOG("%llu decoded frames queued",
static_cast<unsigned long long>(mReorderQueue.Length()));
@ -461,6 +480,8 @@ AppleVTDecoder::DoDecode(MediaRawData* aSample)
return NS_ERROR_FAILURE;
}
mQueuedSamples++;
VTDecodeFrameFlags decodeFlags =
kVTDecodeFrame_EnableAsynchronousDecompression;
rv = VTDecompressionSessionDecodeFrame(mSession,

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

@ -90,6 +90,11 @@ private:
const uint32_t mDisplayWidth;
const uint32_t mDisplayHeight;
// Number of times a sample was queued via Input(). Will be decreased upon
// the decoder's callback being invoked.
// This is used to calculate how many frames has been buffered by the decoder.
Atomic<uint32_t> mQueuedSamples;
// Method to set up the decompression session.
nsresult InitializeSession();
nsresult WaitForAsynchronousFrames();
@ -101,6 +106,9 @@ private:
const RefPtr<TaskQueue> mTaskQueue;
const uint32_t mMaxRefFrames;
const RefPtr<layers::ImageContainer> mImageContainer;
// Increased when Input is called, and decreased when ProcessFrame runs.
// Reaching 0 indicates that there's no pending Input.
Atomic<uint32_t> mInputIncoming;
Atomic<bool> mIsShutDown;
const bool mUseSoftwareImages;

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

@ -133,7 +133,6 @@ FFmpegAudioDecoder<LIBAV_VER>::DoDecode(MediaRawData* aSample)
int64_t samplePosition = aSample->mOffset;
media::TimeUnit pts = media::TimeUnit::FromMicroseconds(aSample->mTime);
bool didOutput = false;
while (packet.size > 0) {
int decoded;
@ -182,7 +181,6 @@ FFmpegAudioDecoder<LIBAV_VER>::DoDecode(MediaRawData* aSample)
numChannels,
samplingRate);
mCallback->Output(data);
didOutput = true;
pts += duration;
if (!pts.IsValid()) {
NS_WARNING("Invalid count of accumulated audio samples");
@ -194,7 +192,7 @@ FFmpegAudioDecoder<LIBAV_VER>::DoDecode(MediaRawData* aSample)
samplePosition += bytesConsumed;
}
return didOutput ? DecodeResult::DECODE_FRAME : DecodeResult::DECODE_NO_FRAME;
return DecodeResult::DECODE_FRAME;
}
void

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

@ -117,11 +117,10 @@ FFmpegDataDecoder<LIBAV_VER>::ProcessDecode(MediaRawData* aSample)
case DecodeResult::FATAL_ERROR:
mCallback->Error(MediaDataDecoderError::FATAL_ERROR);
break;
case DecodeResult::DECODE_NO_FRAME:
mCallback->InputExhausted();
break;
default:
break;
if (mTaskQueue->IsEmpty()) {
mCallback->InputExhausted();
}
}
}

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

@ -143,15 +143,13 @@ WMFMediaDataDecoder::ProcessOutput()
{
RefPtr<MediaData> output;
HRESULT hr = S_OK;
bool didOutput = false;
while (SUCCEEDED(hr = mMFTManager->Output(mLastStreamOffset, output)) &&
output) {
mHasSuccessfulOutput = true;
mCallback->Output(output);
didOutput = true;
}
if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) {
if (!didOutput) {
if (mTaskQueue->IsEmpty()) {
mCallback->InputExhausted();
}
} else if (FAILED(hr)) {