Bug 1269408: P6. Add debugging information, useful when a mochitest timeout. r=gerald

Access to some members is not thread-safe; but the typical use of those informations is when a mochitest has timed out, and by that time the MFR will have been idled for over 5 minutes.

MozReview-Commit-ID: 21BxrSZXVVJ
This commit is contained in:
Jean-Yves Avenard 2016-05-05 15:11:21 +10:00
Родитель 420e17dd76
Коммит ffcc71c256
2 изменённых файлов: 70 добавлений и 14 удалений

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

@ -114,7 +114,7 @@ MediaFormatReader::Shutdown()
mAudio.mTaskQueue->AwaitShutdownAndIdle();
mAudio.mTaskQueue = nullptr;
}
MOZ_ASSERT(mAudio.mPromise.IsEmpty());
MOZ_ASSERT(!mAudio.HasPromise());
if (mVideo.mDecoder) {
Reset(TrackInfo::kVideoTrack);
@ -134,7 +134,7 @@ MediaFormatReader::Shutdown()
mVideo.mTaskQueue->AwaitShutdownAndIdle();
mVideo.mTaskQueue = nullptr;
}
MOZ_ASSERT(mVideo.mPromise.IsEmpty());
MOZ_ASSERT(!mVideo.HasPromise());
mDemuxer = nullptr;
@ -541,7 +541,7 @@ MediaFormatReader::RequestVideoData(bool aSkipToNextKeyframe,
return p;
}
RefPtr<MediaDataPromise> p = mVideo.mPromise.Ensure(__func__);
RefPtr<MediaDataPromise> p = mVideo.EnsurePromise(__func__);
NotifyDecodingRequested(TrackInfo::kVideoTrack);
return p;
@ -627,7 +627,7 @@ MediaFormatReader::RequestAudioData()
return MediaDataPromise::CreateAndReject(CANCELED, __func__);
}
RefPtr<MediaDataPromise> p = mAudio.mPromise.Ensure(__func__);
RefPtr<MediaDataPromise> p = mAudio.EnsurePromise(__func__);
NotifyDecodingRequested(TrackInfo::kAudioTrack);
return p;
@ -740,7 +740,6 @@ MediaFormatReader::NotifyDecodingRequested(TrackType aTrack)
bool
MediaFormatReader::NeedInput(DecoderData& aDecoder)
{
MOZ_ASSERT(OnTaskQueue());
// 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
@ -1237,7 +1236,7 @@ MediaFormatReader::ReturnOutput(MediaData* aData, TrackType aTrack)
mInfo.mAudio.mChannels = audioData->mChannels;
}
}
mAudio.mPromise.Resolve(aData, __func__);
mAudio.ResolvePromise(aData, __func__);
} else if (aTrack == TrackInfo::kVideoTrack) {
if (aData->mType != MediaData::RAW_DATA) {
VideoData* videoData = static_cast<VideoData*>(aData);
@ -1249,7 +1248,7 @@ MediaFormatReader::ReturnOutput(MediaData* aData, TrackType aTrack)
mInfo.mVideo.mDisplay = videoData->mDisplay;
}
}
mVideo.mPromise.Resolve(aData, __func__);
mVideo.ResolvePromise(aData, __func__);
}
LOG("Resolved data promise for %s", TrackTypeToStr(aTrack));
}
@ -1770,12 +1769,48 @@ MediaFormatReader::GetMozDebugReaderData(nsAString& aString)
result += nsPrintfCString("audio decoder: %s\n", audioName);
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 decoder:%d tt:%f tths:%d in:%llu out:%llu qs=%u pending:%u waiting:%d sid:%u\n",
NeedInput(mAudio), mAudio.HasPromise(),
mAudio.mInputExhausted,
mAudio.mDemuxRequest.Exists(),
int(mAudio.mQueuedSamples.Length()),
mAudio.mDecodingRequested,
mAudio.mTimeThreshold
? mAudio.mTimeThreshold.ref().mTime.ToSeconds()
: -1.0,
mAudio.mTimeThreshold
? mAudio.mTimeThreshold.ref().mHasSeeked
: -1,
mAudio.mNumSamplesInput, mAudio.mNumSamplesOutput,
unsigned(size_t(mAudio.mSizeOfQueue)),
unsigned(mAudio.mOutput.Length()),
mAudio.mWaitingForData, mAudio.mLastStreamSourceID);
}
result += nsPrintfCString("video decoder: %s\n", videoName);
result += nsPrintfCString("hardware video decoding: %s\n",
VideoIsHardwareAccelerated() ? "enabled" : "disabled");
result += nsPrintfCString("video frames decoded: %lld (skipped:%lld)\n",
mVideo.mNumSamplesOutputTotal,
mVideo.mNumSamplesSkippedTotal);
if (HasVideo()) {
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.mInputExhausted,
mVideo.mDemuxRequest.Exists(),
int(mVideo.mQueuedSamples.Length()),
mVideo.mDecodingRequested,
mVideo.mTimeThreshold
? mVideo.mTimeThreshold.ref().mTime.ToSeconds()
: -1.0,
mVideo.mTimeThreshold
? mVideo.mTimeThreshold.ref().mHasSeeked
: -1,
mVideo.mNumSamplesInput, mVideo.mNumSamplesOutput,
unsigned(size_t(mVideo.mSizeOfQueue)),
unsigned(mVideo.mOutput.Length()),
mVideo.mWaitingForData, mVideo.mLastStreamSourceID);
}
aString += NS_ConvertUTF8toUTF16(result);
}

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

@ -325,7 +325,9 @@ private:
// These get overriden in the templated concrete class.
// Indicate if we have a pending promise for decoded frame.
// Rejecting the promise will stop the reader from decoding ahead.
virtual bool HasPromise() = 0;
virtual bool HasPromise() const = 0;
virtual RefPtr<MediaDataPromise> EnsurePromise(const char* aMethodName) = 0;
virtual void ResolvePromise(MediaData* aData, const char* aMethodName) = 0;
virtual void RejectPromise(MediaDecoderReader::NotDecodedReason aReason,
const char* aMethodName) = 0;
@ -402,19 +404,33 @@ private:
RefPtr<SharedTrackInfo> mInfo;
};
struct DecoderDataWithPromise : public DecoderData {
class DecoderDataWithPromise : public DecoderData {
public:
DecoderDataWithPromise(MediaFormatReader* aOwner,
MediaData::Type aType,
uint32_t aDecodeAhead) :
DecoderData(aOwner, aType, aDecodeAhead)
uint32_t aDecodeAhead)
: DecoderData(aOwner, aType, aDecodeAhead)
, mHasPromise(false)
{}
MozPromiseHolder<MediaDataPromise> mPromise;
bool HasPromise() const override
{
return mHasPromise;
}
bool HasPromise() override
RefPtr<MediaDataPromise> EnsurePromise(const char* aMethodName) override
{
MOZ_ASSERT(mOwner->OnTaskQueue());
return !mPromise.IsEmpty();
mHasPromise = true;
return mPromise.Ensure(aMethodName);
}
void ResolvePromise(MediaData* aData, const char* aMethodName) override
{
MOZ_ASSERT(mOwner->OnTaskQueue());
mPromise.Resolve(aData, aMethodName);
mHasPromise = false;
}
void RejectPromise(MediaDecoderReader::NotDecodedReason aReason,
@ -423,7 +439,12 @@ private:
MOZ_ASSERT(mOwner->OnTaskQueue());
mPromise.Reject(aReason, aMethodName);
mDecodingRequested = false;
mHasPromise = false;
}
private:
MozPromiseHolder<MediaDataPromise> mPromise;
Atomic<bool> mHasPromise;
};
DecoderDataWithPromise mAudio;