Closed
Bug 1184429
Opened 9 years ago
Closed 9 years ago
WebM playback performance issue.
Categories
(Core :: Audio/Video: Playback, defect)
Core
Audio/Video: Playback
Tracking
()
RESOLVED
FIXED
mozilla42
Tracking | Status | |
---|---|---|
firefox42 | --- | fixed |
People
(Reporter: bechen, Assigned: jya)
References
(Blocks 1 open bug)
Details
Attachments
(2 files, 1 obsolete file)
1.01 KB,
patch
|
jwwang
:
review+
|
Details | Diff | Splinter Review |
2.26 KB,
patch
|
jwwang
:
review+
|
Details | Diff | Splinter Review |
Reporter | ||
Comment 1•9 years ago
|
||
There is another weird behavior from the log I saw.
During the seeking,
|MediaDecoderReader::DispatchNotifyDataArrived| is invoked with the same arguments repeatedly. Then I saw many
|ThrottledNotifyDataArrived| were executed with the same argument.
For example: The DispatchNotifyDataArrived notify the WebMReader with argument offset 0, length 8192, 3 times. So the WebMReader read the same offset 3 times then send the data into WebMBufferParser.
Comment 2•9 years ago
|
||
Can you check if data is evicted from MediaCache so that the http channel is closed and opened again to download the data that was already downloaded before?
Reporter | ||
Comment 3•9 years ago
|
||
(In reply to JW Wang [:jwwang] from comment #2)
> Can you check if data is evicted from MediaCache so that the http channel is
> closed and opened again to download the data that was already downloaded
> before?
Yes, I will check it later.
Now I'm going to write a patch in WebMBufferedParser for reducing the |SilentReadAt| if the data chunk had already sent into WebMBufferedParser.
Assignee | ||
Comment 4•9 years ago
|
||
(In reply to Benjamin Chen [:bechen] from comment #3)
> (In reply to JW Wang [:jwwang] from comment #2)
> > Can you check if data is evicted from MediaCache so that the http channel is
> > closed and opened again to download the data that was already downloaded
> > before?
>
> Yes, I will check it later.
> Now I'm going to write a patch in WebMBufferedParser for reducing the
> |SilentReadAt| if the data chunk had already sent into WebMBufferedParser.
It would be much better to find out the *why* those are happening rather than just getting around the problem in the WebMReader
There are several readers using NotifyDataArrived mechanism to find out what is available for playback.
WebMReader is also going away very soon (bug 1148102)
Comment 5•9 years ago
|
||
For WebMReader will go away soon, I don't think it is worth the effort to find a workaround for it.
Reporter | ||
Comment 6•9 years ago
|
||
(In reply to Jean-Yves Avenard [:jya] from comment #4)
> (In reply to Benjamin Chen [:bechen] from comment #3)
> > (In reply to JW Wang [:jwwang] from comment #2)
> > > Can you check if data is evicted from MediaCache so that the http channel is
> > > closed and opened again to download the data that was already downloaded
> > > before?
I enable the MediaCache's NSPR log to see the detail in MediaCache.
The root cause is that: there are 2 seek operations in the funcion |SilentReadAt|.
For example: test_played.html + seek.webm (duration is 4s)
1. The data is dowloaded from offset 0 because we need metadata.
2. After metadataloaded, the testcase trigger a "seek to 2.6s"
3. Since the |SEEK_VS_READ_THRESHOLD| is 32k, the "seek to 2.6s" correspond to offset 131072 => trigger RecreateChannel
4. The |NotifyDataArrivedInternal| on the other thread from step 1 be executed for offset 8192
=> call SilentReadAt => "seek to 0" => "seek to 131072"
The "seek to 0" and "seek to 131072" also trigger ReCreateChannel and also dispatch another |NotifyDataArrivedInternal| tasks that are redundant for the WebMBufferedParser
Assignee | ||
Comment 7•9 years ago
|
||
That could be easily fixed in MediaDecoderReader::ThrottledNotifyDataArrived
if the new range isn't contiguous with the previous one, it does:
} else if (!mThrottledInterval.ref().Contiguous(aInterval)) {
DoThrottledNotify();
mThrottledInterval.emplace(aInterval);
} else {
We simply need to add before, something like
mThrottledInterval.Contains(aInterval) and do nothing then...
That should do the trick.
Assignee | ||
Comment 8•9 years ago
|
||
Assignee | ||
Comment 9•9 years ago
|
||
Please try the attached patch... let me know if that does it.
Comment 10•9 years ago
|
||
I wonder why don't we call MediaResource::GetCachedRanges to determine the buffer range which has no side effect like re-creating http channels?
Assignee | ||
Comment 11•9 years ago
|
||
it already does...
It's SilentReadAt which appear to not be very silent after all :)
Assignee | ||
Comment 12•9 years ago
|
||
What SilentReadAt could do instead is attempt to use ReadFromCache first, and only if it couldn't read all the data would it default to MediaResource::Read
Assignee | ||
Comment 13•9 years ago
|
||
Benjamin, do you mind if I take this bug?
I'm going to rework MediaReadAt/SilentReadAt so it first attempt to only read from the cache
Reporter | ||
Updated•9 years ago
|
Assignee: bechen → jyavenard
Reporter | ||
Comment 14•9 years ago
|
||
(In reply to Jean-Yves Avenard [:jya] from comment #9)
> Please try the attached patch... let me know if that does it.
I'll try it tomorrow, but I guess the patch doesn't work.
Consider the seek case:
When we press seek generate the task1, but the task2 is dispatched by http channel.
task 1: seek to offset 102400 => ReCreatechannel to offset 102400
task 2: DoThrottledNotify for offset 8192 => ReCreatechannel to offset 8192, ReCreatechannel to offset 102400
comment 12 may be the solution.
Or can we generate a nsRefPtr<MediaByteBuffer> here https://dxr.mozilla.org/mozilla-central/source/dom/media/MediaResource.cpp#466, then send it to reader?
Reporter | ||
Comment 15•9 years ago
|
||
Comment on attachment 8634662 [details] [diff] [review]
Don't dispatch NotifyDataArrived if previously dispatched with same range.
>+ } else if (mThrottledInterval.ref().Contains(aInterval)) {
>+ return;
I have tried the patch, it doesn't work.
During the testcase, there is no chance to go into this code block.
Attachment #8634662 -
Flags: feedback-
Comment 16•9 years ago
|
||
(In reply to Benjamin Chen [:bechen] from comment #6)
> For example: test_played.html + seek.webm (duration is 4s)
> 1. The data is dowloaded from offset 0 because we need metadata.
> 2. After metadataloaded, the testcase trigger a "seek to 2.6s"
> 3. Since the |SEEK_VS_READ_THRESHOLD| is 32k, the "seek to 2.6s" correspond to offset 131072 => trigger RecreateChannel
> 4. The |NotifyDataArrivedInternal| on the other thread from step 1 be executed for offset 8192 => call SilentReadAt => "seek to 0" => "seek to 131072"
> The "seek to 0" and "seek to 131072" also trigger ReCreateChannel and also dispatch another |NotifyDataArrivedInternal| tasks that are redundant for the WebMBufferedParser
It makes sense to ReCreateChannel when seeking to offset 131072 since the data is not yet downloaded. However why did it ReCreateChannel when seeking to offset 0? Wasn't the data already downloaded when reading metadata?
Assignee | ||
Comment 17•9 years ago
|
||
Ben, would you have a particular video that exhibits that behaviour ?
is it just one of the mochitest?
Flags: needinfo?(bechen)
Assignee | ||
Comment 18•9 years ago
|
||
Attachment #8635114 -
Flags: review?(jwwang)
Assignee | ||
Comment 19•9 years ago
|
||
In practice, it will always read from the cache. This allows SilentReadAt to really be silent and prevent unecessary NotifyDataArrived callbacks.
Attachment #8635115 -
Flags: review?(jwwang)
Assignee | ||
Updated•9 years ago
|
Attachment #8634662 -
Attachment is obsolete: true
Updated•9 years ago
|
Attachment #8635115 -
Flags: review?(jwwang) → review+
Updated•9 years ago
|
Attachment #8635114 -
Flags: review?(jwwang) → review+
Assignee | ||
Comment 20•9 years ago
|
||
Comment 21•9 years ago
|
||
Hi Benjamin,
Do you have any idea about comment 16?
Reporter | ||
Comment 22•9 years ago
|
||
(In reply to Jean-Yves Avenard [:jya] from comment #17)
> Ben, would you have a particular video that exhibits that behaviour ?
>
> is it just one of the mochitest?
Just a mochitest.
dom/media/test/test_played.html (I run the "test 6" only) with seek.webm only (In manifest.js |gPlayedTests|)
> (In reply to JW Wang [:jwwang] from comment #16)
> It makes sense to ReCreateChannel when seeking to offset 131072 since the
> data is not yet downloaded. However why did it ReCreateChannel when seeking
> to offset 0? Wasn't the data already downloaded when reading metadata?
I'll check it.
Flags: needinfo?(bechen)
Comment 23•9 years ago
|
||
Reporter | ||
Comment 24•9 years ago
|
||
(In reply to JW Wang [:jwwang] from comment #16)
> (In reply to Benjamin Chen [:bechen] from comment #6)
> > For example: test_played.html + seek.webm (duration is 4s)
> > 1. The data is dowloaded from offset 0 because we need metadata.
> > 2. After metadataloaded, the testcase trigger a "seek to 2.6s"
> > 3. Since the |SEEK_VS_READ_THRESHOLD| is 32k, the "seek to 2.6s" correspond to offset 131072 => trigger RecreateChannel
> > 4. The |NotifyDataArrivedInternal| on the other thread from step 1 be executed for offset 8192 => call SilentReadAt => "seek to 0" => "seek to 131072"
> > The "seek to 0" and "seek to 131072" also trigger ReCreateChannel and also dispatch another |NotifyDataArrivedInternal| tasks that are redundant for the WebMBufferedParser
>
> It makes sense to ReCreateChannel when seeking to offset 131072 since the
> data is not yet downloaded. However why did it ReCreateChannel when seeking
> to offset 0? Wasn't the data already downloaded when reading metadata?
https://dxr.mozilla.org/mozilla-central/source/dom/media/MediaCache.cpp?from=MediaCache.cpp#1178
Because the |GetCachedDataEndInternal| only check the "seek offset (stream->mStreamOffset)" is at the end of block(mChannelOffset) or not. If the "seek offset" is located at the end of block means that the data will arrive soon or had been store in the end block.
Now the code logic doesn't check the whole cache.
Comment 25•9 years ago
|
||
https://hg.mozilla.org/mozilla-central/rev/a438f0060869
https://hg.mozilla.org/mozilla-central/rev/00008b664c22
Status: NEW → RESOLVED
Closed: 9 years ago
Resolution: --- → FIXED
Target Milestone: --- → mozilla42
Comment 26•9 years ago
|
||
(In reply to Benjamin Chen [:bechen] from comment #24)
> (In reply to JW Wang [:jwwang] from comment #16)
> > (In reply to Benjamin Chen [:bechen] from comment #6)
> > > For example: test_played.html + seek.webm (duration is 4s)
> > > 1. The data is dowloaded from offset 0 because we need metadata.
> > > 2. After metadataloaded, the testcase trigger a "seek to 2.6s"
> > > 3. Since the |SEEK_VS_READ_THRESHOLD| is 32k, the "seek to 2.6s" correspond to offset 131072 => trigger RecreateChannel
> > > 4. The |NotifyDataArrivedInternal| on the other thread from step 1 be executed for offset 8192 => call SilentReadAt => "seek to 0" => "seek to 131072"
> > > The "seek to 0" and "seek to 131072" also trigger ReCreateChannel and also dispatch another |NotifyDataArrivedInternal| tasks that are redundant for the WebMBufferedParser
> >
> > It makes sense to ReCreateChannel when seeking to offset 131072 since the
> > data is not yet downloaded. However why did it ReCreateChannel when seeking
> > to offset 0? Wasn't the data already downloaded when reading metadata?
>
> https://dxr.mozilla.org/mozilla-central/source/dom/media/MediaCache.
> cpp?from=MediaCache.cpp#1178
>
> Because the |GetCachedDataEndInternal| only check the "seek offset
> (stream->mStreamOffset)" is at the end of block(mChannelOffset) or not. If
> the "seek offset" is located at the end of block means that the data will
> arrive soon or had been store in the end block.
> Now the code logic doesn't check the whole cache.
I see why. 8192 bytes do not make a full block and a partial block won't go into the cache. That is why bytes downloaded for metadata are discarded when seeking.
You need to log in
before you can comment on or make changes to this bug.
Description
•