Closed
Bug 1168008
Opened 10 years ago
Closed 10 years ago
Implement Completion MediaPromises
Categories
(Core :: Audio/Video, defect)
Core
Audio/Video
Tracking
()
RESOLVED
FIXED
mozilla41
Tracking | Status | |
---|---|---|
firefox41 | --- | fixed |
People
(Reporter: bholley, Assigned: bholley)
References
Details
Attachments
(12 files, 1 obsolete file)
1.06 KB,
patch
|
jwwang
:
review+
|
Details | Diff | Splinter Review |
1.72 KB,
patch
|
jwwang
:
review+
|
Details | Diff | Splinter Review |
34.30 KB,
patch
|
jwwang
:
review+
|
Details | Diff | Splinter Review |
3.25 KB,
patch
|
jwwang
:
review+
|
Details | Diff | Splinter Review |
1.57 KB,
patch
|
jwwang
:
review+
|
Details | Diff | Splinter Review |
8.15 KB,
patch
|
jwwang
:
review+
|
Details | Diff | Splinter Review |
23.95 KB,
patch
|
jwwang
:
review+
|
Details | Diff | Splinter Review |
3.23 KB,
patch
|
jwwang
:
review+
|
Details | Diff | Splinter Review |
6.29 KB,
patch
|
jwwang
:
review+
|
Details | Diff | Splinter Review |
1.06 KB,
patch
|
mozbugz
:
review+
|
Details | Diff | Splinter Review |
7.02 KB,
patch
|
mozbugz
:
review+
|
Details | Diff | Splinter Review |
2.30 KB,
patch
|
jya
:
review+
|
Details | Diff | Splinter Review |
At present, one of the biggest conceptual differences between MediaPromises and JS promises is that JS promises can be chained (|foo()->then(bar)->then(baz)|), whereas MediaPromises can't.
This chaining gives JS promises a huge amount of power - the promise that bar() returns can hook into an arbitrarily complex network of asynchronous work, all of which is elegantly abstracted away. I initially avoided implementing this behavior for MediaPromises because I couldn't figure out how to make it work with the type system, and because I didn't have a use case. But I've figured out a way to make it work, and have a use case in bug 1163223.
In that bug, I ran into the situation where we want to quarantine the first sample from one channel (audio or video) until we have the first sample from the other channel, so that we can compute the min of the two start times and adjust the samples (and all subsequent samples) by this offset. This is kind of an icky thing to handle in either the demuxer or the MDSM, but it can be very elegantly handled somewhere in between. ;-)
I have patches to do this, which also unify Then() and RefableThen(). Here's what usage of this looks like (from my patches in bug 1163223).
Before:
mAudioDataRequest.Begin(
ProxyMediaCall(DecodeTaskQueue(), mReader.get(),
__func__, &MediaDecoderReader::RequestAudioData)
->RefableThen(TaskQueue(), __func__, this,
&MediaDecoderStateMachine::OnAudioDecoded,
&MediaDecoderStateMachine::OnAudioNotDecoded)
);
After:
mAudioDataRequest.Begin(
ProxyMediaCall(DecodeTaskQueue(), mReader.get(),
__func__, &MediaDecoderReader::RequestAudioData)
->Then(TaskQueue(), __func__, mStartTimeAdjuster.get(),
&StartTimeAdjuster::AdjustSample<AudioDataPromise>,
&StartTimeAdjuster::Pass)
->CompletionPromise()
->Then(TaskQueue(), __func__, this,
&MediaDecoderStateMachine::OnAudioDecoded,
&MediaDecoderStateMachine::OnAudioNotDecoded)
);
Assignee | ||
Comment 1•10 years ago
|
||
Comment 2•10 years ago
|
||
What happens if one of the chained promises rejects? Does the rest of the chain still get called like JS promises?
Assignee | ||
Comment 3•10 years ago
|
||
(In reply to Chris Pearce (:cpearce) from comment #2)
> What happens if one of the chained promises rejects? Does the rest of the
> chain still get called like JS promises?
Yep. If the resolve or reject callback returns a promise, that promise is chained to the completion promise, so that its result gets propagated through. If the callback doesn't return a promise, the completion promise is immediately resolved or reject with the ResolveOrRejectValue. This allows the use of ::Pass in comment 0 - rejections just propagate through the intermediate processing step.
I'll write a comment explaining how this all works.
Comment 4•10 years ago
|
||
Can this replace the use of the ProxyMediaCall?
Assignee | ||
Comment 5•10 years ago
|
||
(In reply to Jean-Yves Avenard [:jya] from comment #4)
> Can this replace the use of the ProxyMediaCall?
Hm, how? The point of ProxyMediaCall is to dispatch a task to another thread - I'm not sure how completion promises would help with that.
Assignee | ||
Comment 6•10 years ago
|
||
Attachment #8611563 -
Flags: review?(jwwang)
Assignee | ||
Comment 7•10 years ago
|
||
Attachment #8611564 -
Flags: review?(jwwang)
Assignee | ||
Comment 8•10 years ago
|
||
This incurs an extra addref here and there, but I think it makes the API simpler
to use and understand.
Attachment #8611565 -
Flags: review?(jwwang)
Assignee | ||
Comment 9•10 years ago
|
||
The hard-coded specificity here is a barrier towards various bits of
generalization in the ensuing patches.
Attachment #8611566 -
Flags: review?(jwwang)
Assignee | ||
Comment 10•10 years ago
|
||
Attachment #8611567 -
Flags: review?(jwwang)
Assignee | ||
Comment 11•10 years ago
|
||
I'm open to suggestions on how to do this more elegantly.
Attachment #8611568 -
Flags: review?(jwwang)
Assignee | ||
Comment 12•10 years ago
|
||
Attachment #8611569 -
Flags: review?(jwwang)
Assignee | ||
Comment 13•10 years ago
|
||
I think this makes more sense, and it matches the naming convention that all
of the consumers of this stuff are actually using.
Attachment #8611570 -
Flags: review?(jwwang)
Assignee | ||
Comment 14•10 years ago
|
||
Suggestions of other topics to describe are welcome.
Attachment #8611571 -
Flags: review?(jwwang)
Assignee | ||
Comment 15•10 years ago
|
||
Attachment #8611572 -
Flags: review?(jwwang)
Comment on attachment 8611568 [details] [diff] [review]
Part 6 - Do the template munging to allow promise callbacks to optionally return a promise, and surface that from InvokeCallbackMethod. v1
Review of attachment 8611568 [details] [diff] [review]:
-----------------------------------------------------------------
Drive-by micro comment (didn't review the full file)
::: dom/media/MediaPromise.h
@@ +58,5 @@
> +};
> +
> +/*
> + * Work around the fact that IsConvertible doesn't support void. It would be nice
> + * to fix this in TypeTraits.h but we're not supposed to touch it. :-(.
stl::is_convertible supports void, so mozilla::IsConvertible should probably be fixed.
iso cpp 20.9.6: "template <class From, class To> struct is_convertible; -- From and To shall be complete types, arrays of unknown bound, or (possibly cv-qualified) void types."
Updated•10 years ago
|
Attachment #8611563 -
Flags: review?(jwwang) → review+
Comment 17•10 years ago
|
||
Comment on attachment 8611565 [details] [diff] [review]
Part 3 - Get rid of RefableThen and make Then return an nsRefPtr<Consumer>. v1
Review of attachment 8611565 [details] [diff] [review]:
-----------------------------------------------------------------
::: dom/media/MediaPromise.h
@@ +392,5 @@
> nsRefPtr<ThenValueBase> thenValue = new FunctionThenValue<ResolveFunction, RejectFunction>(aResponseThread,
> Move(aResolveFunction), Move(aRejectFunction), aCallSite);
> ThenInternal(aResponseThread, thenValue, aCallSite);
> + nsRefPtr<Consumer> c = thenValue.forget();
> + return c;
Can't we just return thenValue.forget() for already_AddRefed is implicitly convertible to nsRefPtr?
Attachment #8611565 -
Flags: review?(jwwang) → review+
Updated•10 years ago
|
Attachment #8611566 -
Flags: review?(jwwang) → review+
Comment 18•10 years ago
|
||
Comment on attachment 8611567 [details] [diff] [review]
Part 5 - Make FunctionThenValue dispatch via InvokeCallbackMethod. v1
Review of attachment 8611567 [details] [diff] [review]:
-----------------------------------------------------------------
What is the benefit of using InvokeCallbackMethod instead of direct calls to mResolveFunction/mRejectFunction?
Attachment #8611567 -
Flags: review?(jwwang) → review+
Assignee | ||
Comment 19•10 years ago
|
||
(In reply to JW Wang [:jwwang] from comment #18)
> What is the benefit of using InvokeCallbackMethod instead of direct calls to
> mResolveFunction/mRejectFunction?
It lets us share all the complicated templated invoke overloads in the next method.
Assignee | ||
Comment 20•10 years ago
|
||
(In reply to Bobby Holley (:bholley) from comment #19)
> It lets us share all the complicated templated invoke overloads in the next
> method.
*next patch.
Comment 21•10 years ago
|
||
Comment on attachment 8611568 [details] [diff] [review]
Part 6 - Do the template munging to allow promise callbacks to optionally return a promise, and surface that from InvokeCallbackMethod. v1
Review of attachment 8611568 [details] [diff] [review]:
-----------------------------------------------------------------
Looks fine to me. However, I am not a c++ guru. MFBT guys should have better suggestions.
::: dom/media/MediaPromise.h
@@ +303,5 @@
> */
>
> template<typename ThisType, typename MethodType, typename ValueType>
> + static typename EnableIf<ReturnTypeIs<MethodType, nsRefPtr<MediaPromise>>::value,
> + typename EnableIf<TakesArgument<MethodType>::value, already_AddRefed<MediaPromise>>::Type>::Type
Can we just say:
EnableIf<
ReturnTypeIs<MethodType, nsRefPtr<MediaPromise>>::value && TakesArgument<MethodType>::value,
already_AddRefed<MediaPromise>
>::Type
to have one EnableIf only?
Attachment #8611568 -
Flags: review?(jwwang) → feedback+
Updated•10 years ago
|
Attachment #8611569 -
Flags: review?(jwwang) → review+
Updated•10 years ago
|
Attachment #8611570 -
Flags: review?(jwwang) → review+
Updated•10 years ago
|
Attachment #8611571 -
Flags: review?(jwwang) → review+
Comment 22•10 years ago
|
||
Comment on attachment 8611564 [details] [diff] [review]
Part 2 - Improve MediaPromise::ResolveOrRejectValue. v1
Review of attachment 8611564 [details] [diff] [review]:
-----------------------------------------------------------------
::: dom/media/MediaPromise.h
@@ +72,5 @@
> MOZ_ASSERT(IsNothing());
> mRejectValue.emplace(aRejectValue);
> }
>
> + static ResolveOrRejectValue MakeResolve(const ResolveValueType aResolveValue)
Where is this function used?
Attachment #8611564 -
Flags: review?(jwwang) → review+
Assignee | ||
Comment 23•10 years ago
|
||
(In reply to JW Wang [:jwwang] from comment #22)
> Where is this function used?
In the tests.
Updated•10 years ago
|
Attachment #8611572 -
Flags: review?(jwwang) → review+
Assignee | ||
Comment 24•10 years ago
|
||
(In reply to JW Wang [:jwwang] from comment #17)
> Can't we just return thenValue.forget() for already_AddRefed is implicitly
> convertible to nsRefPtr?
Hm, that's slightly more confusing, but definitely more compact. I'll switch to it.
Thanks for the reviews!
Assignee | ||
Comment 25•10 years ago
|
||
Attachment #8612094 -
Flags: review?(gsquelart)
Assignee | ||
Comment 26•10 years ago
|
||
Attachment #8611568 -
Attachment is obsolete: true
Attachment #8612095 -
Flags: review?(gsquelart)
Assignee | ||
Comment 27•10 years ago
|
||
Comment on attachment 8612094 [details] [diff] [review]
Part 5.5 - Make IsConvertible handle void. v1
Review of attachment 8612094 [details] [diff] [review]:
-----------------------------------------------------------------
r+ as it works and it's probably all you need for your use, which I don't want to delay.
If possible I would suggest the following small changes.
And/or just file a separate bug to get IsConvertible fully STL-compliant.
Also some unit tests, e.g.:
static_assert(IsConvertible<void, void>::value, "void is void");
static_assert(!IsConvertible<A, void>::value, "A shouldn't convert to void");
static_assert(!IsConvertible<void, B>::value, "void shouldn't convert to B");
::: mfbt/TypeTraits.h
@@ +655,5 @@
> +
> +template<>
> +struct IsConvertible<void, void> {
> + static const bool value = true;
> +};
These do not have a 'Type' member type. You may just follow the same style as the initial template to get all that's needed, e.g.:
"""
template<typename B>
struct IsConvertible<void, B>
: IntegralConstant<bool, IsVoid<B>::value>
{};
template<typename A>
struct IsConvertible<A, void>
: IntegralConstant<bool, IsVoid<A>::value>
{};
template<>
struct IsConvertible<void, void>
: TrueType
{};
"""
Also, these won't handle const/volatile void properly, probably rare but it should probably be documented above.
Attachment #8612094 -
Flags: review?(gsquelart) → review+
Attachment #8612095 -
Flags: review?(gsquelart) → review+
Assignee | ||
Comment 29•10 years ago
|
||
It looks like the subsequent rename to "Request" causes trouble with the
leak log tables.
Attachment #8612430 -
Flags: review?(jyavenard)
Assignee | ||
Comment 30•10 years ago
|
||
Assignee | ||
Comment 31•10 years ago
|
||
Comment 32•10 years ago
|
||
Comment on attachment 8612430 [details] [diff] [review]
Part 7.5 - Use a base class for refcounting MediaPromise::Consumer as well. v1
Review of attachment 8612430 [details] [diff] [review]:
-----------------------------------------------------------------
No fan of the name MediaPromiseRefcountable...
Attachment #8612430 -
Flags: review?(jyavenard) → review+
Comment 33•10 years ago
|
||
https://hg.mozilla.org/integration/mozilla-inbound/rev/831c5d95d197
https://hg.mozilla.org/integration/mozilla-inbound/rev/4b6b0af6e032
https://hg.mozilla.org/integration/mozilla-inbound/rev/b4f5c50385af
https://hg.mozilla.org/integration/mozilla-inbound/rev/e6ad9ecaaefc
https://hg.mozilla.org/integration/mozilla-inbound/rev/743cd6e023c5
https://hg.mozilla.org/integration/mozilla-inbound/rev/be83609966a1
https://hg.mozilla.org/integration/mozilla-inbound/rev/ec08b62b49f4
https://hg.mozilla.org/integration/mozilla-inbound/rev/e3d613bbf185
https://hg.mozilla.org/integration/mozilla-inbound/rev/7bea013b498a
https://hg.mozilla.org/integration/mozilla-inbound/rev/eb72777f68d3
https://hg.mozilla.org/integration/mozilla-inbound/rev/a0593eed31d4
https://hg.mozilla.org/integration/mozilla-inbound/rev/d29db7f0d3f0
Blocks: 1169495
Comment 34•10 years ago
|
||
https://hg.mozilla.org/mozilla-central/rev/831c5d95d197
https://hg.mozilla.org/mozilla-central/rev/4b6b0af6e032
https://hg.mozilla.org/mozilla-central/rev/b4f5c50385af
https://hg.mozilla.org/mozilla-central/rev/e6ad9ecaaefc
https://hg.mozilla.org/mozilla-central/rev/743cd6e023c5
https://hg.mozilla.org/mozilla-central/rev/be83609966a1
https://hg.mozilla.org/mozilla-central/rev/ec08b62b49f4
https://hg.mozilla.org/mozilla-central/rev/e3d613bbf185
https://hg.mozilla.org/mozilla-central/rev/7bea013b498a
https://hg.mozilla.org/mozilla-central/rev/eb72777f68d3
https://hg.mozilla.org/mozilla-central/rev/a0593eed31d4
https://hg.mozilla.org/mozilla-central/rev/d29db7f0d3f0
Status: NEW → RESOLVED
Closed: 10 years ago
status-firefox41:
--- → fixed
Flags: in-testsuite+
Resolution: --- → FIXED
Target Milestone: --- → mozilla41
You need to log in
before you can comment on or make changes to this bug.
Description
•