Make creation of decoder an asynchronous API
Categories
(Core :: Audio/Video: Playback, enhancement)
Tracking
()
Tracking | Status | |
---|---|---|
firefox84 | --- | fixed |
People
(Reporter: jya, Assigned: jya)
References
(Blocks 1 open bug, Regressed 1 open bug)
Details
Attachments
(13 files, 10 obsolete files)
47 bytes,
text/x-phabricator-request
|
Details | Review | |
47 bytes,
text/x-phabricator-request
|
Details | Review | |
47 bytes,
text/x-phabricator-request
|
Details | Review | |
47 bytes,
text/x-phabricator-request
|
Details | Review | |
47 bytes,
text/x-phabricator-request
|
Details | Review | |
47 bytes,
text/x-phabricator-request
|
Details | Review | |
47 bytes,
text/x-phabricator-request
|
Details | Review | |
47 bytes,
text/x-phabricator-request
|
Details | Review | |
47 bytes,
text/x-phabricator-request
|
Details | Review | |
47 bytes,
text/x-phabricator-request
|
Details | Review | |
47 bytes,
text/x-phabricator-request
|
Details | Review | |
47 bytes,
text/x-phabricator-request
|
Details | Review | |
47 bytes,
text/x-phabricator-request
|
Details | Review |
Currently, to create a decoder we call the PDMFactory::CreateDecoder and this is a synchronous call.
The PDMFactory will sequentially queries all registered PDM to determine which one supports the type we need.
For this the PDMFactory will call PlatformDecoderModule::Supports on each PDM.
The forces Supports to be a sync API and the RemoteDecoderModule will need a Supports sync IPC which isn't very desirable and has negative performance impact.
The primary aim is to make the RemoteDecoderManagerChild::Supports be asynchronous ; and to achieve this we need each potential caller to also be asynchronous, starting with PDMFactory::CreateDecoder.
This bug will track that progress.
Assignee | ||
Comment 1•4 years ago
|
||
This method will become the main entry point of a PDM and allow to create a decoder asynchronously for PDM not supporting that interface.
Updated•4 years ago
|
Assignee | ||
Comment 2•4 years ago
|
||
The DecoderDoctorDiagnostic is only ever used with PDM::Supports; when creating a decoder this object would always be nullptr.
Attempting to set it would have resulted in UAF as a DiagnosticDecoderDecoder is typically an object allocated on the stack and most of the code creating the decoders is async.
Depends on D96347
Assignee | ||
Comment 3•4 years ago
|
||
There's no longer have a GpuDecoderModule and RemoteGpuDecoder.
So we no longer need the IRemoteDecoderChild abstraction layer.
Depends on D96348
Assignee | ||
Comment 4•4 years ago
|
||
Passing a pointer to an object across several thread was dubious at best to ensure a use after free was never in place.
This complexity becomes even greater should we want to create the decoder asynchronously.
So we pass instead a lambda that holds a strong reference to the object that holds the event producer.
Depends on D96349
Assignee | ||
Comment 5•4 years ago
|
||
This method will become the main entry point of a PDM and allow to create a decoder asynchronously for PDM not supporting that interface.
Assignee | ||
Comment 6•4 years ago
|
||
The DecoderDoctorDiagnostic is only ever used with PDM::Supports; when creating a decoder this object would always be nullptr.
Attempting to set it would have resulted in UAF as a DiagnosticDecoderDecoder is typically an object allocated on the stack and most of the code creating the decoders is async.
Depends on D96351
Assignee | ||
Comment 7•4 years ago
|
||
There's no longer have a GpuDecoderModule and RemoteGpuDecoder.
So we no longer need the IRemoteDecoderChild abstraction layer.
Depends on D96352
Assignee | ||
Comment 8•4 years ago
|
||
Passing a pointer to an object across several thread was dubious at best to ensure a use after free was never in place.
This complexity becomes even greater should we want to create the decoder asynchronously.
So we pass instead a lambda that holds a strong reference to the object that holds the event producer.
Depends on D96353
Assignee | ||
Comment 9•4 years ago
|
||
Updated•4 years ago
|
Updated•4 years ago
|
Updated•4 years ago
|
Updated•4 years ago
|
Updated•4 years ago
|
Updated•4 years ago
|
Updated•4 years ago
|
Updated•4 years ago
|
Updated•4 years ago
|
Assignee | ||
Comment 10•4 years ago
|
||
This method will become the main entry point of a PDM and allow to create a decoder asynchronously for PDM not supporting that interface.
Assignee | ||
Comment 11•4 years ago
|
||
The DecoderDoctorDiagnostic is only ever used with PDM::Supports; when creating a decoder this object would always be nullptr.
Attempting to set it would have resulted in UAF as a DiagnosticDecoderDecoder is typically an object allocated on the stack and most of the code creating the decoders is async.
Assignee | ||
Comment 12•4 years ago
|
||
There's no longer have a GpuDecoderModule and RemoteGpuDecoder.
So we no longer need the IRemoteDecoderChild abstraction layer.
Assignee | ||
Comment 13•4 years ago
|
||
Passing a pointer to an object across several thread was dubious at best to ensure a use after free was never in place.
This complexity becomes even greater should we want to create the decoder asynchronously.
So we pass instead a lambda that holds a strong reference to the object that holds the event producer.
Assignee | ||
Comment 14•4 years ago
|
||
For now, creation of the decoders is a synchronous operation, so we can deal with a convenience, stack-only structure to pass all the parameters required.
This will change once creation becomes asynchronous and we must ensure that the parameters lifetime will overlap the entire process.
It also allows to simplify the few areas that did have to manually copy all those parameters and save them individually.
Assignee | ||
Comment 15•4 years ago
|
||
Assignee | ||
Comment 16•4 years ago
|
||
Until now, it was up to the caller to ensure that the VideoInfo or AudioInfo passed to the PlatformDecoderModule would remain alive until the created decoder was shut down.
This was achieved by the MediaFormatReader through great care and complexity and ensuring that the MediaFormatReader would never complete its own shutdown unless the decoder did the same.
Asynchronously creating the decoder add an even greater of complexity. We have to ensure that should the caller shut down while the decoder creation promise hasn't been resolved ; that it stays alive the entire time.
It could be achieved by making the TrackInfo object refcounted, or creating a cycle between the caller and the PDM/decoder.
Each of those options have their own downsides.
Either of those options add an unwarranted level of complexity, when we can just have each decoder copy the arguments it receives. This is simpler and more straightforward and the required copy isn't expensive.
Depends on D96362
Assignee | ||
Comment 17•4 years ago
|
||
PDMFactory::CreateDecoder is changed to return a MozPromise that will contain the MediaDataDecoder once created.
This will allow to later make RemoteDecoderManager fully asynchronous and no longer require an IPC sync call to start the RDD process.
We also modify the WebrtcMediaDataDecoderCodec to never create a decoder on the main thread, which could cause deadlocks under some circumstances.
Depends on D96363
Assignee | ||
Comment 18•4 years ago
|
||
We can now chaincreation of the decoder to the launch of the RDD process as needed and setting up the PRemoteDecoderManager
Depends on D96364
Assignee | ||
Comment 19•4 years ago
|
||
Depends on D96365
Assignee | ||
Comment 20•4 years ago
|
||
P4 introduced a cycle between the MediaFormatReader and the onWaitingForKeyEvent lambda.
Normally, this cycle would be broken by a call to Shutdown.
However, should the MediaFormatReader shuts down before the CreateDecoderPromise be resolved, it would have no way of shutting down the decoder keeping the cycle alive.
Theoretically, keeping a plain pointer to the MFR::mOnTrackWaitingForKey like we did before P4 is safe, as the EME code making use of it, only does so while we are decoding data and the MFR has the ability to properly shutdown the decoder.
However, for the sake of clarity and simplification, we introduce an easier way to check of the MFR has been deleted already by making it support SafeThreadWeakPtr; and the OnWaitingForKey keep a weak pointer to it and checking the value before calling it.
Depends on D96366
Assignee | ||
Comment 21•4 years ago
|
||
This allows for nice template type deducation.
Assignee | ||
Comment 22•4 years ago
|
||
We also ensure that the MediaFormatReader will only shutdown once the CreateDecoderPromise has been resolved (or rejected)
This makes a few of the earlier changes redundant; as we can now guarantee all the objects provided to the PDMFactory will stay valid for the entire lifetime of the decoder. So we could do away with P4 and P7.
It's better that we keep those however, as it greatly simplify other usage of the PDMFactory. Ensuring that the user of the PDMFactory survives any decoder isn't a trivial affair.
Depends on D96368
Assignee | ||
Comment 23•4 years ago
|
||
This allows for nice template argument deducation.
Updated•4 years ago
|
Comment 24•4 years ago
|
||
Comment 25•4 years ago
|
||
Backed out 13 changesets (bug 1672072) for short.mp4.firstframe.html.
Backout link: https://hg.mozilla.org/integration/autoland/rev/23b8e2facfb9860427b51b8fbad686def2d2ac29
Failure log: https://treeherder.mozilla.org/logviewer?job_id=321661300&repo=autoland&lineNumber=7781
[task 2020-11-13T03:59:07.474Z] 03:59:07 INFO - REFTEST TEST-LOAD | http://localhost:51404/1605239947464/1/reftest/short.mp4.firstframe.html | 0 / 8 (0%)
[task 2020-11-13T03:59:07.591Z] 03:59:07 INFO - REFTEST INFO | drawWindow flags = DRAWWINDOW_DRAW_CARET | DRAWWINDOW_DRAW_VIEW | DRAWWINDOW_USE_WIDGET_LAYERS; window size = 800,1000; test browser size = 800,1000
[task 2020-11-13T03:59:07.674Z] 03:59:07 INFO - _RegisterApplication(), FAILED TO establish the default connection to the WindowServer, _CGSDefaultConnection() is NULL.
[task 2020-11-13T03:59:08.139Z] 03:59:08 INFO - REFTEST TEST-LOAD | http://localhost:51404/1605239947464/1/reftest/short.mp4.firstframe-ref.html | 0 / 8 (0%)
[task 2020-11-13T03:59:08.139Z] 03:59:08 INFO - JavaScript error: resource://gre/actors/PictureInPictureChild.jsm, line 452: TypeError: can't access property "requestIdleCallback", this.contentWindow is null
[task 2020-11-13T03:59:08.139Z] 03:59:08 INFO - REFTEST INFO | REFTEST fuzzy test (0, 0) <= (80, 76800) <= (68, 76800)
[task 2020-11-13T03:59:08.232Z] 03:59:08 INFO - REFTEST TEST-UNEXPECTED-FAIL | dom/media/test/reftest/short.mp4.firstframe.html == dom/media/test/reftest/short.mp4.firstframe-ref.html | image comparison, max difference: 80, number of differing pixels: 76800
[task 2020-11-13T03:59:08.232Z] 03:59:08 INFO - REFTEST IMAGE 1 (TEST): data:image/png;base64,iVBORw0K...
[task 2020-11-13T03:59:08.232Z] 03:59:08 INFO - REFTEST IMAGE 2 (REFERENCE): data:image/png;base64,iVBORw0K...
[task 2020-11-13T03:59:08.233Z] 03:59:08 INFO - REFTEST TEST-END | dom/media/test/reftest/short.mp4.firstframe.html == dom/media/test/reftest/short.mp4.firstframe-ref.html
[task 2020-11-13T03:59:08.233Z] 03:59:08 INFO - REFTEST TEST-START | dom/media/test/reftest/short.mp4.lastframe.html == dom/media/test/reftest/short.mp4.lastframe-ref.html
[task 2020-11-13T03:59:08.233Z] 03:59:08 INFO - REFTEST TEST-LOAD | http://localhost:51404/1605239947464/2/reftest/short.mp4.lastframe.html | 1 / 8 (12%)
[task 2020-11-13T03:59:08.593Z] 03:59:08 INFO - REFTEST TEST-LOAD | http://localhost:51404/1605239947464/2/reftest/short.mp4.lastframe-ref.html | 1 / 8 (12%)
[task 2020-11-13T03:59:08.596Z] 03:59:08 INFO - JavaScript error: resource://gre/actors/PictureInPictureChild.jsm, line 568: TypeError: can't access property "removeEventListener", this.contentWindow is null
[task 2020-11-13T03:59:08.641Z] 03:59:08 INFO - REFTEST INFO | REFTEST fuzzy test (0, 0) <= (87, 76795) <= (60, 76797)
[task 2020-11-13T03:59:08.801Z] 03:59:08 INFO - REFTEST TEST-UNEXPECTED-FAIL | dom/media/test/reftest/short.mp4.lastframe.html == dom/media/test/reftest/short.mp4.lastframe-ref.html | image comparison, max difference: 87, number of differing pixels: 76795
[task 2020-11-13T03:59:08.801Z] 03:59:08 INFO - REFTEST IMAGE 1 (TEST): data:image/png;base64,iVBORw0KGgoAAAANSUhE...
[task 2020-11-13T03:59:08.801Z] 03:59:08 INFO - REFTEST IMAGE 2 (REFERENCE): data:image/png;base64,iVBORw0KG...
[task 2020-11-13T03:59:08.802Z] 03:59:08 INFO - REFTEST TEST-END | dom/media/test/reftest/short.mp4.lastframe.html == dom/media/test/reftest/short.mp4.lastframe-ref.html
Comment 26•4 years ago
|
||
The following seems to start perma failing with the backed out changes: https://treeherder.mozilla.org/logviewer?job_id=321656073&repo=autoland&lineNumber=1793
Assignee | ||
Comment 27•4 years ago
|
||
(In reply to Bogdan Tara[:bogdan_tara | bogdant] from comment #26)
The following seems to start perma failing with the backed out changes: https://treeherder.mozilla.org/logviewer?job_id=321656073&repo=autoland&lineNumber=1793
doesn't seem so, on that same push there's two run of that job, and the 2nd one is green
Comment 28•4 years ago
|
||
Comment 29•4 years ago
|
||
bugherder |
https://hg.mozilla.org/mozilla-central/rev/781cbe96daef
https://hg.mozilla.org/mozilla-central/rev/df40384bc11a
https://hg.mozilla.org/mozilla-central/rev/070e63e03b0d
https://hg.mozilla.org/mozilla-central/rev/1ebf3b578f0e
https://hg.mozilla.org/mozilla-central/rev/5f32a75ad1be
https://hg.mozilla.org/mozilla-central/rev/b014e619965f
https://hg.mozilla.org/mozilla-central/rev/17a5d812f4cb
https://hg.mozilla.org/mozilla-central/rev/2ad5d48f1452
https://hg.mozilla.org/mozilla-central/rev/134879789eca
https://hg.mozilla.org/mozilla-central/rev/d6c6d6fc3918
https://hg.mozilla.org/mozilla-central/rev/3bad20fc960d
https://hg.mozilla.org/mozilla-central/rev/e938ec569adb
https://hg.mozilla.org/mozilla-central/rev/7c39a1568c5e
Comment 30•4 years ago
|
||
This seems like a lot to land during a soft freeze. Was there a reason it couldn't wait until after the 85 version bump?
Assignee | ||
Comment 31•4 years ago
|
||
(In reply to Ryan VanderMeulen [:RyanVM] from comment #30)
This seems like a lot to land during a soft freeze. Was there a reason it couldn't wait until after the 85 version bump?
Either we landed this or we would have to backout all the work done on RDD in 84. In particular bug 1595994.
I felt this was the safest approach.
Description
•