Bug 1724106 - Clarify threading usage when getting media debug info. r=alwu
Differential Revision: https://phabricator.services.mozilla.com/D124104
This commit is contained in:
@@ -7385,6 +7385,8 @@ void HTMLMediaElement::AsyncRejectPendingPlayPromises(nsresult aError) {
|
||||
}
|
||||
|
||||
void HTMLMediaElement::GetEMEInfo(dom::EMEDebugInfo& aInfo) {
|
||||
MOZ_ASSERT(NS_IsMainThread(),
|
||||
"MediaKeys expects to be interacted with on main thread!");
|
||||
if (!mMediaKeys) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1376,6 +1376,7 @@ MediaDecoderOwner::NextFrameStatus MediaDecoder::NextFrameBufferedStatus() {
|
||||
}
|
||||
|
||||
void MediaDecoder::GetDebugInfo(dom::MediaDecoderDebugInfo& aInfo) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
CopyUTF8toUTF16(nsPrintfCString("%p", this), aInfo.mInstance);
|
||||
aInfo.mChannels = mInfo ? mInfo->mAudio.mChannels : 0;
|
||||
aInfo.mRate = mInfo ? mInfo->mAudio.mRate : 0;
|
||||
@@ -1384,26 +1385,27 @@ void MediaDecoder::GetDebugInfo(dom::MediaDecoderDebugInfo& aInfo) {
|
||||
CopyUTF8toUTF16(MakeStringSpan(PlayStateStr()), aInfo.mPlayState);
|
||||
aInfo.mContainerType =
|
||||
NS_ConvertUTF8toUTF16(ContainerType().Type().AsString());
|
||||
mReader->GetDebugInfo(aInfo.mReader);
|
||||
}
|
||||
|
||||
RefPtr<GenericPromise> MediaDecoder::RequestDebugInfo(
|
||||
MediaDecoderDebugInfo& aInfo) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(!IsShutdown());
|
||||
if (!NS_IsMainThread()) {
|
||||
// Run the request on the main thread if it's not already.
|
||||
return InvokeAsync(AbstractThread::MainThread(), __func__,
|
||||
[this, self = RefPtr{this}, &aInfo]() {
|
||||
return RequestDebugInfo(aInfo);
|
||||
});
|
||||
}
|
||||
GetDebugInfo(aInfo);
|
||||
|
||||
return mReader->RequestDebugInfo(aInfo.mReader)
|
||||
->Then(AbstractThread::MainThread(), __func__,
|
||||
[this, self = RefPtr{this}, &aInfo] {
|
||||
if (!GetStateMachine()) {
|
||||
return GenericPromise::CreateAndResolve(true, __func__);
|
||||
}
|
||||
|
||||
return GetStateMachine()
|
||||
->RequestDebugInfo(aInfo.mStateMachine)
|
||||
->Then(
|
||||
AbstractThread::MainThread(), __func__,
|
||||
[]() { return GenericPromise::CreateAndResolve(true, __func__); },
|
||||
[]() {
|
||||
MOZ_ASSERT_UNREACHABLE("Unexpected RequestDebugInfo() rejection");
|
||||
return GenericPromise::CreateAndResolve(false, __func__);
|
||||
return GetStateMachine()->RequestDebugInfo(aInfo.mStateMachine);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -3096,7 +3096,23 @@ layers::ImageContainer* MediaFormatReader::GetImageContainer() {
|
||||
: nullptr;
|
||||
}
|
||||
|
||||
RefPtr<GenericPromise> MediaFormatReader::RequestDebugInfo(
|
||||
dom::MediaFormatReaderDebugInfo& aInfo) {
|
||||
if (!OnTaskQueue()) {
|
||||
// Run the request on the task queue if it's not already.
|
||||
return InvokeAsync(mTaskQueue, __func__,
|
||||
[this, self = RefPtr{this}, &aInfo] {
|
||||
return RequestDebugInfo(aInfo);
|
||||
});
|
||||
}
|
||||
GetDebugInfo(aInfo);
|
||||
return GenericPromise::CreateAndResolve(true, __func__);
|
||||
}
|
||||
|
||||
void MediaFormatReader::GetDebugInfo(dom::MediaFormatReaderDebugInfo& aInfo) {
|
||||
MOZ_ASSERT(OnTaskQueue(),
|
||||
"Don't call this off the task queue, it's going to touch a lot of "
|
||||
"data members");
|
||||
nsCString result;
|
||||
nsAutoCString audioDecoderName("unavailable");
|
||||
nsAutoCString videoDecoderName = audioDecoderName;
|
||||
@@ -3104,34 +3120,11 @@ void MediaFormatReader::GetDebugInfo(dom::MediaFormatReaderDebugInfo& aInfo) {
|
||||
nsAutoCString videoType("none");
|
||||
|
||||
AudioInfo audioInfo;
|
||||
{
|
||||
MutexAutoLock lock(mAudio.mMutex);
|
||||
if (HasAudio()) {
|
||||
audioInfo = *mAudio.GetWorkingInfo()->GetAsAudioInfo();
|
||||
audioDecoderName = mAudio.mDecoder ? mAudio.mDecoder->GetDescriptionName()
|
||||
: mAudio.mDescription;
|
||||
audioType = audioInfo.mMimeType;
|
||||
}
|
||||
}
|
||||
|
||||
VideoInfo videoInfo;
|
||||
{
|
||||
MutexAutoLock lock(mVideo.mMutex);
|
||||
if (HasVideo()) {
|
||||
videoInfo = *mVideo.GetWorkingInfo()->GetAsVideoInfo();
|
||||
videoDecoderName = mVideo.mDecoder ? mVideo.mDecoder->GetDescriptionName()
|
||||
: mVideo.mDescription;
|
||||
videoType = videoInfo.mMimeType;
|
||||
}
|
||||
}
|
||||
|
||||
CopyUTF8toUTF16(audioDecoderName, aInfo.mAudioDecoderName);
|
||||
CopyUTF8toUTF16(audioType, aInfo.mAudioType);
|
||||
aInfo.mAudioChannels = audioInfo.mChannels;
|
||||
aInfo.mAudioRate = audioInfo.mRate / 1000.0f;
|
||||
aInfo.mAudioFramesDecoded = mAudio.mNumSamplesOutputTotal;
|
||||
|
||||
if (HasAudio()) {
|
||||
aInfo.mAudioState.mNeedInput = NeedInput(mAudio);
|
||||
aInfo.mAudioState.mHasPromise = mAudio.HasPromise();
|
||||
aInfo.mAudioState.mWaitingPromise = !mAudio.mWaitingPromise.IsEmpty();
|
||||
@@ -3155,18 +3148,18 @@ void MediaFormatReader::GetDebugInfo(dom::MediaFormatReaderDebugInfo& aInfo) {
|
||||
aInfo.mAudioState.mLastStreamSourceID = mAudio.mLastStreamSourceID;
|
||||
}
|
||||
|
||||
CopyUTF8toUTF16(videoDecoderName, aInfo.mVideoDecoderName);
|
||||
CopyUTF8toUTF16(videoType, aInfo.mVideoType);
|
||||
aInfo.mVideoWidth =
|
||||
videoInfo.mDisplay.width < 0 ? 0 : videoInfo.mDisplay.width;
|
||||
aInfo.mVideoHeight =
|
||||
videoInfo.mDisplay.height < 0 ? 0 : videoInfo.mDisplay.height;
|
||||
aInfo.mVideoRate = mVideo.mMeanRate.Mean();
|
||||
aInfo.mVideoHardwareAccelerated = VideoIsHardwareAccelerated();
|
||||
aInfo.mVideoNumSamplesOutputTotal = mVideo.mNumSamplesOutputTotal;
|
||||
aInfo.mVideoNumSamplesSkippedTotal = mVideo.mNumSamplesSkippedTotal;
|
||||
CopyUTF8toUTF16(audioDecoderName, aInfo.mAudioDecoderName);
|
||||
CopyUTF8toUTF16(audioType, aInfo.mAudioType);
|
||||
aInfo.mAudioChannels = audioInfo.mChannels;
|
||||
aInfo.mAudioRate = audioInfo.mRate / 1000.0f;
|
||||
aInfo.mAudioFramesDecoded = mAudio.mNumSamplesOutputTotal;
|
||||
|
||||
VideoInfo videoInfo;
|
||||
if (HasVideo()) {
|
||||
videoInfo = *mVideo.GetWorkingInfo()->GetAsVideoInfo();
|
||||
videoDecoderName = mVideo.mDecoder ? mVideo.mDecoder->GetDescriptionName()
|
||||
: mVideo.mDescription;
|
||||
videoType = videoInfo.mMimeType;
|
||||
aInfo.mVideoState.mNeedInput = NeedInput(mVideo);
|
||||
aInfo.mVideoState.mHasPromise = mVideo.HasPromise();
|
||||
aInfo.mVideoState.mWaitingPromise = !mVideo.mWaitingPromise.IsEmpty();
|
||||
@@ -3190,6 +3183,17 @@ void MediaFormatReader::GetDebugInfo(dom::MediaFormatReaderDebugInfo& aInfo) {
|
||||
aInfo.mVideoState.mLastStreamSourceID = mVideo.mLastStreamSourceID;
|
||||
}
|
||||
|
||||
CopyUTF8toUTF16(videoDecoderName, aInfo.mVideoDecoderName);
|
||||
CopyUTF8toUTF16(videoType, aInfo.mVideoType);
|
||||
aInfo.mVideoWidth =
|
||||
videoInfo.mDisplay.width < 0 ? 0 : videoInfo.mDisplay.width;
|
||||
aInfo.mVideoHeight =
|
||||
videoInfo.mDisplay.height < 0 ? 0 : videoInfo.mDisplay.height;
|
||||
aInfo.mVideoRate = mVideo.mMeanRate.Mean();
|
||||
aInfo.mVideoHardwareAccelerated = VideoIsHardwareAccelerated();
|
||||
aInfo.mVideoNumSamplesOutputTotal = mVideo.mNumSamplesOutputTotal;
|
||||
aInfo.mVideoNumSamplesSkippedTotal = mVideo.mNumSamplesSkippedTotal;
|
||||
|
||||
// Looking at dropped frames
|
||||
FrameStatisticsData stats = mFrameStats->GetFrameStatisticsData();
|
||||
aInfo.mFrameStats.mDroppedDecodedFrames = stats.mDroppedDecodedFrames;
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
# include "SeekTarget.h"
|
||||
# include "mozilla/Atomics.h"
|
||||
# include "mozilla/Maybe.h"
|
||||
# include "mozilla/MozPromise.h"
|
||||
# include "mozilla/Mutex.h"
|
||||
# include "mozilla/StateMirroring.h"
|
||||
# include "mozilla/StaticPrefs_media.h"
|
||||
@@ -182,9 +183,11 @@ class MediaFormatReader final
|
||||
|
||||
RefPtr<SetCDMPromise> SetCDMProxy(CDMProxy* aProxy);
|
||||
|
||||
// Returns a MediaDebugInfo structure
|
||||
// Used for debugging purposes.
|
||||
void GetDebugInfo(dom::MediaFormatReaderDebugInfo& aInfo);
|
||||
// Requests that the MediaFormatReader populates aInfo with debug information.
|
||||
// This may be done asynchronously, and aInfo should *not* be accessed by the
|
||||
// caller until the returned promise is resolved or rejected.
|
||||
RefPtr<GenericPromise> RequestDebugInfo(
|
||||
dom::MediaFormatReaderDebugInfo& aInfo);
|
||||
|
||||
// Switch the video decoder to NullDecoderModule. It might takes effective
|
||||
// since a few samples later depends on how much demuxed samples are already
|
||||
@@ -813,6 +816,8 @@ class MediaFormatReader final
|
||||
MozPromiseHolder<SetCDMPromise> mSetCDMPromise;
|
||||
TrackSet mSetCDMForTracks{};
|
||||
bool IsDecoderWaitingForCDM(TrackType aTrack);
|
||||
|
||||
void GetDebugInfo(dom::MediaFormatReaderDebugInfo& aInfo);
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
||||
@@ -629,9 +629,17 @@ already_AddRefed<Promise> MediaSource::MozDebugReaderData(ErrorResult& aRv) {
|
||||
return nullptr;
|
||||
}
|
||||
MOZ_ASSERT(domPromise);
|
||||
MediaSourceDecoderDebugInfo info;
|
||||
mDecoder->GetDebugInfo(info);
|
||||
domPromise->MaybeResolve(info);
|
||||
UniquePtr<MediaSourceDecoderDebugInfo> info =
|
||||
MakeUnique<MediaSourceDecoderDebugInfo>();
|
||||
mDecoder->RequestDebugInfo(*info)->Then(
|
||||
mAbstractMainThread, __func__,
|
||||
[domPromise, infoPtr = std::move(info)] {
|
||||
domPromise->MaybeResolve(infoPtr.get());
|
||||
},
|
||||
[] {
|
||||
MOZ_ASSERT_UNREACHABLE("Unexpected rejection while getting debug data");
|
||||
});
|
||||
|
||||
return domPromise.forget();
|
||||
}
|
||||
|
||||
|
||||
@@ -223,11 +223,22 @@ void MediaSourceDecoder::SetMediaSourceDuration(double aDuration) {
|
||||
}
|
||||
}
|
||||
|
||||
void MediaSourceDecoder::GetDebugInfo(dom::MediaSourceDecoderDebugInfo& aInfo) {
|
||||
if (mReader && mDemuxer) {
|
||||
mReader->GetDebugInfo(aInfo.mReader);
|
||||
RefPtr<GenericPromise> MediaSourceDecoder::RequestDebugInfo(
|
||||
dom::MediaSourceDecoderDebugInfo& aInfo) {
|
||||
// This should be safe to call off main thead, but there's no such usage at
|
||||
// time of writing. Can be carefully relaxed if needed.
|
||||
MOZ_ASSERT(NS_IsMainThread(), "Expects to be called on main thread.");
|
||||
if (mReader) {
|
||||
return mReader->RequestDebugInfo(aInfo.mReader)
|
||||
->Then(GetCurrentSerialEventTarget(), __func__,
|
||||
[this, self = RefPtr<MediaSourceDecoder>{this}, &aInfo] {
|
||||
if (mDemuxer) {
|
||||
mDemuxer->GetDebugInfo(aInfo.mDemuxer);
|
||||
}
|
||||
return GenericPromise::CreateAndResolve(true, __func__);
|
||||
});
|
||||
}
|
||||
return GenericPromise::CreateAndResolve(true, __func__);
|
||||
}
|
||||
|
||||
double MediaSourceDecoder::GetDuration() {
|
||||
|
||||
@@ -54,9 +54,11 @@ class MediaSourceDecoder : public MediaDecoder,
|
||||
|
||||
bool IsTransportSeekable() override { return true; }
|
||||
|
||||
// Returns a structure describing the state of the MediaSource internal
|
||||
// buffered data. Used for debugging purposes.
|
||||
void GetDebugInfo(dom::MediaSourceDecoderDebugInfo& aInfo);
|
||||
// Requests that the MediaSourceDecoder populates aInfo with debug
|
||||
// information. This may be done asynchronously, and aInfo should *not* be
|
||||
// accessed by the caller until the returned promise is resolved or rejected.
|
||||
RefPtr<GenericPromise> RequestDebugInfo(
|
||||
dom::MediaSourceDecoderDebugInfo& aInfo);
|
||||
|
||||
void AddSizeOfResources(ResourceSizes* aSizes) override;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user