[Webkit-unassigned] [Bug 194747] New: [MSE] SourceBuffer sample time increment vs. last frame duration check is broken

bugzilla-daemon at webkit.org bugzilla-daemon at webkit.org
Sat Feb 16 09:06:35 PST 2019


https://bugs.webkit.org/show_bug.cgi?id=194747

            Bug ID: 194747
           Summary: [MSE] SourceBuffer sample time increment vs. last
                    frame duration check is broken
           Product: WebKit
           Version: Safari Technology Preview
          Hardware: Unspecified
                OS: All
            Status: NEW
          Severity: Blocker
          Priority: P2
         Component: Media
          Assignee: webkit-unassigned at lists.webkit.org
          Reporter: up at nanocosmos.de

Technical Severity 

This issue is breaking MSE playback for totally MSE compliant streams, 
in our case fMP4/H.264/AAC, but not limited to this container or codecs. 
Effects are playback not starting at all or significantly delayed and  
massive amount of frame/sample drop mid stream forced by a 
wrong a MSE compliance check.  

Business Severity 

If the issue will make it into Safari 12.2, 
MSE playback will be broken in Safari for our cdn,  
business leading customers of ours and 
other MSE applications and users. 
We would like to offer assistance and developer time 
to prevent this. 

Code Location and Context 

Location of the issue is SourceBuffer::sourceBufferPrivateDidReceiveSample 
in WebCore/Modules/mediasource/SourceBuffer.cpp, 
in the second part of this conditional statement related to trackBuffer.greatestDecodeDuration. 
The problem is how trackBuffer.greatestDecodeDuration is set/calculated. 
It is mainly a logical issue. Please find more in the details section. 

// 1.6 ↳ If last decode timestamp for track buffer is set and decode timestamp is less than last
// decode timestamp:
// OR
// ↳ If last decode timestamp for track buffer is set and the difference between decode timestamp and
// last decode timestamp is greater than 2 times last frame duration:
if (trackBuffer.lastDecodeTimestamp.isValid() && (decodeTimestamp < trackBuffer.lastDecodeTimestamp
   || (trackBuffer.greatestDecodeDuration.isValid() && abs(decodeTimestamp - trackBuffer.lastDecodeTimestamp) > (trackBuffer.greatestDecodeDuration * 2)))) 

Bug history 

We have first discovered the issue in Safari Technology preview 75. 
We have been able to verify that it exists already in STP 72, 
and that it did NOT exist in STP 61. Further it does not exist in 
the current Safari 12.1 release. 

Checking out WebKit itself we have been able to recreate the issue 
in WebKit nightly 2019 Feb. 14th. 

We have checked in between [MEDIA] commits and found this one: 
https://trac.webkit.org/changeset/236314/webkit/

According to the description the trackBuffer.greatestDecodeDuration check 
has been hidden behind a smaller bug related to the assignment. 
By fixing this the major issue with trackBuffer.greatestDecodeDuration 
became active. 

Details 

Here is how we understand the timestamp increment vs last frame duration check 
in the MSE spec and how it is done in the current implementation. 

Example frame/sample sequence that should not fail (but currently does): 

Frame A) dts:0, duration 10 
Frame B) dts:10, duration 90 
Frame C) dts:100, duration 10 
Timestamp increase and previous frame duration are perfectly aligned. 

Example frame/sample sequence that should fail: 

Frame A) dts:0, duration 10 
Frame B) dts:10, duration 10 
Frame C) dts:100, duration 10 
Discontinuity due to mismatch from B to C. 

What should be compared is (C.dts - B.dts) vs. B.duration .

Current impl. is comparing (C.dts - B.dts) vs. (B.dts - A.dts) . 
(involving a maximum value storage but that does not matter here) 

Instead of comparing current timestamp increment vs. last frame duration 
it's comparing current timestamp increment vs. previous timestamp increment, 
which makes a huge difference, because the target here is not to check 
how constant the frame rate is, but to detect discontinuities. 
Not sure about other containers, but in fMP4 the timestamp and duration 
of a frame are stored separately and explicitely. 

Implications seem to be even stranger for audio in fMP4, 
where one sample can hold multiple audio frames. 
In this case the current check will apply constraints to 
how many audio frames one sample contains and how it 
compares to the number of audio frames in the previous sample, 
which is obviously not what this check should be about. 

Proposal for a 'simple' fix 

Logically the solution would be to compare against trackBuffer.lastFrameDuration 
if valid instead of trackBuffer.greatestDecodeDuration. 

Technically both approaches could be combined to keep changes at a minimum, 
but no sample should be rejected if trackBuffer.lastFrameDuration is not valid. 
It must be ensured that, if valid, trackBuffer.lastFrameDuration holds the duration 
of the last frame/sample, not of any previous ones. 

Thanks in advance!

-- 
You are receiving this mail because:
You are the assignee for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.webkit.org/pipermail/webkit-unassigned/attachments/20190216/d1d3713c/attachment.html>


More information about the webkit-unassigned mailing list