New issue
Advanced search Search tips

Issue 776704 link

Starred by 2 users

Issue metadata

Status: Assigned
Owner:
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: Linux
Pri: 2
Type: Bug



Sign in to add a comment

durationchange event is not fired during some MSE calls (e.g. appendBuffer())

Reported by ddy...@vewd.com, Oct 20 2017

Issue description

UserAgent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.62 Safari/537.36

Example URL:
https://yt-dash-mse-test.commondatastorage.googleapis.com/unit-tests/2018.html?test_type=conformance-test&command=run&tests=31

Steps to reproduce the problem:
Version using attached simplified TC

1. Host attached test case on any web server (it's stripped down version of 2018's QUAL MSE-conformance, mainly test `31. DurationAfterAppendOpusAudio`)
2. Run in Chrome/Chromium link: http://localhost/path/to/attached/qual/test/2018.html?test_type=conformance-test&command=run&tests=31
3. Observe printed logs
3.1. There are some extra logs added which will print fired events (they start with `###`)
4. Note that there is only one `durationchange` event which is sent after log `Remove() complete` which is when JS code directly assigns new duration value to `MediaSource.duration` in js/lib/mse/2018/msutil-20171005191104.js` in `SetDuration()` function.

Version with plan QUAL 2018 (MSE-conformance test) using built-in DevTools:

1. Run: https://yt-dash-mse-test.commondatastorage.googleapis.com/unit-tests/2018.html?test_type=conformance-test&command=run&tests=31
2. Open DevTools -> Sources tab
3. Open file from unit-tests/js/tests/2018/conformanceTest-$ver$.js
4. Find `createDurationAfterAppendTest()` function
5. Add some extra logs in there on `media` variable for `durationchange` event.

What is the expected behavior?
According to MSE specification (https://www.w3.org/TR/media-source/), when JS code executes `appendBuffer()` method on SourceBuffer object (https://www.w3.org/TR/media-source/#dom-sourcebuffer-appendbuffer) and asynchronous append buffer algorithm (https://www.w3.org/TR/media-source/#sourcebuffer-buffer-append) is run, browser should:

1. Run the segment parser loop algorithm.
...
4. Queue a task to fire a simple event named update at this SourceBuffer object.
5. Queue a task to fire a simple event named updateend at this SourceBuffer object.

If you inspect segment parser loop algorithm (https://www.w3.org/TR/media-source/#sourcebuffer-segment-parser-loop) then there are two cases:

(a) for initialization segments, initialization segment received algorithm (https://www.w3.org/TR/media-source/#sourcebuffer-init-segment-received) mandates in first step, that duration should be updated (either to known value or positive infinity) and *duration change algorithm* should be run.

(b) for media segments, coded frame processing algorithm (https://www.w3.org/TR/media-source/#sourcebuffer-coded-frame-processing) mandates in step 5 that duration can be updated if frames are beyond current duration. Again - *duration change algorithm* should be run.

Now, the duration change algorithm (https://www.w3.org/TR/media-source/#duration-change-algorithm) mandates in step 6 that we should run HTMLMediaElement duration change algorithm (unless some corner cases like the same duration or error states). This algorithm (https://www.w3.org/TR/html51/semantics-embedded-content.html#durationChange) issues that the browser should send `durationchange` event. Only exception is specified as: 

  "The event is not fired when the duration is reset as part of loading a new media resource"

but I don't believe that this is the case here, as below that there is:

"Similarly, if the user agent initially estimated the media resource’s duration instead of determining it precisely, and later revises the estimate based on new information, then the duration would change and the durationchange event would be fired."

This is exactly the case when ChunkDemuxer finds duration in initialization segments, but then data exceeds this duration and has to be updated.

What went wrong?
Chrome (/Chromium) will send `durationchange` events only for direct assignment of MediaSource's `duration` field (a) or when ready state is at least HAVE_METADATA. In some corner cases when using MSE, ready state is still in HAVE_NOTHING state and `durationchange` events are not fired.

Did this work before? N/A 

Is it a problem with Flash or HTML5? HTML5

Does this work in other browsers? N/A

Chrome version: 62.0.3202.62  Channel: stable
OS Version: 
Flash Version: 

Contents of chrome://gpu: 
Note: To properly save this page, select the "Webpage, Complete" option in the Save File dialog.
Graphics Feature Status
Canvas: Software only, hardware acceleration unavailable
CheckerImaging: Disabled
Flash: Software only, hardware acceleration unavailable
Flash Stage3D: Software only, hardware acceleration unavailable
Flash Stage3D Baseline profile: Software only, hardware acceleration unavailable
Compositing: Software only, hardware acceleration unavailable
Multiple Raster Threads: Enabled
Native GpuMemoryBuffers: Software only. Hardware acceleration disabled
Rasterization: Software only, hardware acceleration unavailable
Video Decode: Software only, hardware acceleration unavailable
Video Encode: Software only, hardware acceleration unavailable
WebGL: Hardware accelerated but at reduced performance
WebGL2: Unavailable
Problems Detected
ATI/AMD cards with older drivers in Linux are crash-prone: 71381, 76428, 73910, 101225, 136240, 357314
Disabled Features: flash_stage3d, gpu_compositing, panel_fitting, flash3d, gpu_rasterization, accelerated_2d_canvas, accelerated_video_decode, webgl2, accelerated_webgl, flash_stage3d_baseline, accelerated_video_encode
Accelerated video decode is unavailable on Linux: 137247
Disabled Features: accelerated_video_decode
Accelerated video encode is unavailable on Linux
Disabled Features: accelerated_video_encode
Native GpuMemoryBuffers have been disabled, either via about:flags or command line.
Disabled Features: native_gpu_memory_buffers
Checker-imaging has been disabled via finch trial or the command line.
Disabled Features: checker_imaging
Version Information
Data exported	10/20/2017, 1:23:30 PM
Chrome version	Chrome/62.0.3202.62
Operating system	Linux 4.10.0-37-generic
Software rendering list version	13.12
Driver bug list version	10.30
ANGLE commit id	e8ef2bc4bd01
2D graphics backend	Skia/62 e74b41c6c84638d5a9ee6d254a715bcd9e17c603-
Command Line	/usr/bin/google-chrome-stable --enable-blink-features=MediaSourceNewAbortAndDuration --flag-switches-begin --flag-switches-end
Driver Information
Initialization time	0
In-process GPU	true
Passthrough Command Decoder	false
Supports overlays	false
Sandboxed	false
GPU0	VENDOR = 0x1002, DEVICE= 0x6610
Optimus	false
Optimus	false
AMD switchable	false
Driver vendor	Google Inc.
Driver version	3.3.0.2
Driver date	2017/04/07
Pixel shader version	3.0
Vertex shader version	3.0
Max. MSAA samples	4
Machine model name	
Machine model version	
GL_VENDOR	Google Inc.
GL_RENDERER	Google SwiftShader
GL_VERSION	OpenGL ES 2.0 SwiftShader
GL_EXTENSIONS	
Disabled Extensions	
Window system binding vendor	
Window system binding version	
Window system binding extensions	
Window manager	Compiz
XDG_CURRENT_DESKTOP	Unity
GDMSESSION	ubuntu
Compositing manager	Yes
Direct rendering	Yes
Reset notification strategy	0x0000
GPU process crash count	0
System visual ID	0
RGBA visual ID	0
Compositor Information
Tile Update Mode	One-copy
Partial Raster	Enabled
GpuMemoryBuffers Status
ATC	Software only
ATCIA	Software only
DXT1	Software only
DXT5	Software only
ETC1	Software only
R_8	Software only
R_16	Software only
RG_88	Software only
BGR_565	Software only
RGBA_4444	Software only
RGBX_8888	Software only
RGBA_8888	Software only
BGRX_8888	Software only
BGRA_8888	Software only
RGBA_F16	Software only
YVU_420	Software only
YUV_420_BIPLANAR	Software only
UYVY_422	Software only

Note that this makes Chrome/Chromium behavior inconsistent, as it will fire `durationchange` event from MSE if MediaSource.duration is asasigned directly (even in HAVE_NOTHING ready state, but won't fire it from other "sources").

This is due to the fact that MediaSource.duration assignment is done in `MediaSource::setDuration(double, ExceptionState&)`  (https://cs.chromium.org/chromium/src/third_party/WebKit/Source/modules/mediasource/MediaSource.cpp?sq=package:chromium&l=485) and this goes directly to `HTMLMediaElement::DurationChanged(double, bool)`, but other ways goes from `ChunkDemuxer::UpdateDuration(TimeDelta)` (https://cs.chromium.org/chromium/src/media/filters/chunk_demuxer.cc?dr=CSs&l=1313) through `WebMediaPlayerImpl::OnDurationChange()` (https://cs.chromium.org/chromium/src/media/blink/webmediaplayer_impl.cc?dr=CSs&l=1622) which has something like this:

```
  if (ready_state_ == WebMediaPlayer::kReadyStateHaveNothing)
    return;
```

This will quietly kill any duration-changed notifications.
 
minified_qual_2018_mse.zip
1.2 MB Download
Labels: Needs-Triage-M62
Labels: TE-NeedsTriageHelp
The issue seems to be out of TE-scope as it is related to unit test. Hence, adding TE-NeedsTriageHelp for further investigation from dev team.

Thanks...!!
Components: -Internals>Media Internals>Media>Source
Owner: wolenetz@chromium.org
Status: Assigned (was: Unconfirmed)
this is source API related. give to matt to start investigating.

Sign in to add a comment