Bug 1823541 - part2 : recreate the state machine if DRM playback is not allowed for the media engine playback. r=jolin

As we can't determine if the external state machine is going to be used
for DRM playback at the time we create it, we need to check that later
when the CDM proxy is assigned to the decoder.

So when detecting DRM playback on the media engine playback and the pref
is disabled, we would destroy the external state machine and then create
our normal state machine in order to run Gecko's media pipeline.

There is a race between shutting down the old format reader and the new
format reader. For the media source playback, we would reuse the
demuxer [1]. If the demuxer init hasn't finished when the new format
reader starts initializing the demuxer, we would end up chaining the
same init promise twice, which hit the assertion of exclusive promise.

Therefore, we change the init promise to non-exlusive, which won't hurt,
because in our case that means we don't need to re-init the demuxer
again. For other cases, it won't change any behavior because the
media format reader won't change its demuxer at the middle of playback,
and that promise actually isn't necessary to be an exclusive promise.


[1]
https://searchfox.org/mozilla-central/rev/137075514eddc08c68ff652e9899da82e8043574/dom/media/mediasource/MediaSourceDecoder.cpp#42-44

[2]
https://searchfox.org/mozilla-central/rev/137075514eddc08c68ff652e9899da82e8043574/dom/media/MediaFormatReader.cpp#782-788

Depends on D173205

Differential Revision: https://phabricator.services.mozilla.com/D173206
This commit is contained in:
alwu 2023-03-23 17:36:50 +00:00
parent 79a84f1d8d
commit fd3d570d36
3 changed files with 24 additions and 7 deletions

View File

@ -35,7 +35,7 @@ class MediaDataDemuxer : public DecoderDoctorLifeLogger<MediaDataDemuxer> {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDataDemuxer)
typedef MozPromise<MediaResult, MediaResult, /* IsExclusive = */ true>
typedef MozPromise<MediaResult, MediaResult, /* IsExclusive = */ false>
InitPromise;
// Initializes the demuxer. Other methods cannot be called unless

View File

@ -436,12 +436,13 @@ void MediaDecoder::OnPlaybackErrorEvent(const MediaResult& aError) {
return;
}
// External engine can't play the resource, try to use our own state machine
// again. Here we will create a new state machine immediately and asynchrously
// shutdown the old one because we don't want to dispatch any task to the old
// state machine. Therefore, we will disconnect anything related with the old
// state machine, create a new state machine and setup events/mirror/etc, then
// shutdown the old one and release its reference once it finishes shutdown.
// External engine can't play the resource or we intentionally disable it, try
// to use our own state machine again. Here we will create a new state machine
// immediately and asynchrously shutdown the old one because we don't want to
// dispatch any task to the old state machine. Therefore, we will disconnect
// anything related with the old state machine, create a new state machine and
// setup events/mirror/etc, then shutdown the old one and release its
// reference once it finishes shutdown.
MOZ_ASSERT(aError == NS_ERROR_DOM_MEDIA_EXTERNAL_ENGINE_NOT_SUPPORTED_ERR);
RefPtr<MediaDecoderStateMachineBase> discardStateMachine =
mDecoderStateMachine;
@ -1369,6 +1370,16 @@ bool MediaDecoder::CanPlayThrough() {
RefPtr<SetCDMPromise> MediaDecoder::SetCDMProxy(CDMProxy* aProxy) {
MOZ_ASSERT(NS_IsMainThread());
#ifdef MOZ_WMF_MEDIA_ENGINE
// DRM playback via the media engine is disabled, switch back to the state
// machine using Gecko's media pipeline.
if (GetStateMachine()->IsExternalStateMachine() &&
!StaticPrefs::media_wmf_media_engine_drm_playback()) {
LOG("Disable external state machine due to DRM playback not allowed");
OnPlaybackErrorEvent(
MediaResult{NS_ERROR_DOM_MEDIA_EXTERNAL_ENGINE_NOT_SUPPORTED_ERR});
}
#endif
return GetStateMachine()->SetCDMProxy(aProxy);
}

View File

@ -10212,6 +10212,12 @@
value: false
mirror: always
# This allows playing DRM video via the media engine pipeline.
- name: media.wmf.media-engine.drm-playback
type: RelaxedAtomicBool
value: false
mirror: always
# The amount of video raw data the engine stream will queue
- name: media.wmf.media-engine.raw-data-threshold.video
type: RelaxedAtomicInt32