Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(cast): Use cast platform APIs in MediaCapabilties polyfill #4727

Conversation

JulianDomingo
Copy link
Contributor

@JulianDomingo JulianDomingo commented Nov 17, 2022

See #4726 for more context.

This allows Cast devices to properly filter stream variants with a resolution surpassing that of the device's capabilities.

We place the fix in the MediaCapabilities polyfill since it's intended to be the right way to check for anything related to platform support.


HDR support checks will require eotf=smpte2048, as indicated in #2813 (comment). Specifically, a {hev|hvc}1.2 profile is only an indication of an HDR transfer function, but may be a non-HDR 10-bit color stream. Take for instance this publicly available hls.js HEVC stream (https://devstreaming-cdn.apple.com/videos/streaming/examples/bipbop_adv_example_hevc/master.m3u8) which contains stream variants with the hvc1.2.4.L123.B0 codecs, but with a resolution < 4K:

#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=1996813,BANDWIDTH=2194827,CODECS="hvc1.2.4.L123.B0,ec-3",RESOLUTION=960x540,FRAME-RATE=60.000,CLOSED-CAPTIONS="cc",AUDIO="a3",SUBTITLES="sub1"
v14/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=6135662,BANDWIDTH=6694727,CODECS="hvc1.2.4.L123.B0,ec-3",RESOLUTION=1920x1080,FRAME-RATE=60.000,CLOSED-CAPTIONS="cc",AUDIO="a3",SUBTITLES="sub1"
v18/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=4831572,BANDWIDTH=5458398,CODECS="hvc1.2.4.L123.B0,ec-3",RESOLUTION=1920x1080,FRAME-RATE=60.000,CLOSED-CAPTIONS="cc",AUDIO="a3",SUBTITLES="sub1"
v17/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=3471811,BANDWIDTH=4110269,CODECS="hvc1.2.4.L123.B0,ec-3",RESOLUTION=1920x1080,FRAME-RATE=60.000,CLOSED-CAPTIONS="cc",AUDIO="a3",SUBTITLES="sub1"
v16/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=2666432,BANDWIDTH=2795200,CODECS="hvc1.2.4.L123.B0,ec-3",RESOLUTION=1280x720,FRAME-RATE=60.000,CLOSED-CAPTIONS="cc",AUDIO="a3",SUBTITLES="sub1"
v15/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=1169111,BANDWIDTH=1256754,CODECS="hvc1.2.4.L123.B0,ec-3",RESOLUTION=768x432,FRAME-RATE=30.000,CLOSED-CAPTIONS="cc",AUDIO="a3",SUBTITLES="sub1"
v13/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=859838,BANDWIDTH=932269,CODECS="hvc1.2.4.L123.B0,ec-3",RESOLUTION=640x360,FRAME-RATE=30.000,CLOSED-CAPTIONS="cc",AUDIO="a3",SUBTITLES="sub1"
v12/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=552728,BANDWIDTH=579426,CODECS="hvc1.2.4.L123.B0,ec-3",RESOLUTION=480x270,FRAME-RATE=30.000,CLOSED-CAPTIONS="cc",AUDIO="a3",SUBTITLES="sub1"
v11/prog_index.m3u8
#EXT-X-STREAM-INF:AVERAGE-BANDWIDTH=345440,BANDWIDTH=371212,CODECS="hvc1.2.4.L123.B0,ec-3",RESOLUTION=416x234,FRAME-RATE=30.000,CLOSED-CAPTIONS="cc",AUDIO="a3",SUBTITLES="sub1"
v10/prog_index.m3u8

In Cast, the platform can distinguish between the two by explicitly providing the transfer function; it uses smpte2048 ("PQ") because this is the "basis of HDR video formats..." (https://en.wikipedia.org/wiki/Perceptual_quantizer). Below you can see the platform correctly distinguishing between an HDR-capable and non-HDR capable HDMI sink device (using a 4K-capable Chromecast):

canDisplayType() results on a 1920x1080 ASUS monitor:

[JULIAN]: canDisplayType(video/mp4; codecs="hev1.2.4.L153.B0"; width=1920; height=1080; eotf="smpte2084"') => false
[JULIAN]: canDisplayType(video/mp4; codecs="hev1.2.4.L153.B0"; width=3840; height=2160; eotf="smpte2084"') => false
VM10:1 New style VP9 codec string must start with vp09. codecId:hev1.2.4.L153.B0
[JULIAN]: canDisplayType(video/mp4; codecs="hev1.2.4.L153.B0"; width=1920; height=1080') => true
[JULIAN]: canDisplayType(video/mp4; codecs="hev1.2.4.L153.B0"; width=3840; height=2160') => false
VM10:1 New style VP9 codec string must start with vp09. codecId:hev1.2.4.L153.B0
[JULIAN]: canDisplayType(video/mp4; codecs="hev1.2.4.L153.B0"') => true
[JULIAN]: canDisplayType(video/mp4; codecs="hev1.2.4.L153.B0; eotf="smpte2084"') => false
[JULIAN]: canDisplayType(video/mp4; codecs="hvc1.2.4.L153.B0"; width=1920; height=1080; eotf="smpte2084"') => false
[JULIAN]: canDisplayType(video/mp4; codecs="hvc1.2.4.L153.B0"; width=3840; height=2160; eotf="smpte2084"') => false
VM10:1 New style VP9 codec string must start with vp09. codecId:hvc1.2.4.L153.B0
[JULIAN]: canDisplayType(video/mp4; codecs="hvc1.2.4.L153.B0"; width=1920; height=1080') => true
[JULIAN]: canDisplayType(video/mp4; codecs="hvc1.2.4.L153.B0"; width=3840; height=2160') => false
VM10:1 New style VP9 codec string must start with vp09. codecId:hvc1.2.4.L153.B0
[JULIAN]: canDisplayType(video/mp4; codecs="hvc1.2.4.L153.B0"') => true
[JULIAN]: canDisplayType(video/mp4; codecs="hvc1.2.4.L153.B0; eotf="smpte2084"') => false

canDisplayType() results on a 4K HDR TCL 2017 Roku TV (43"):

New style VP9 codec string must start with vp09. codecId:hev1.2.4.L153.B0
[JULIAN]: canDisplayType(video/mp4; codecs="hev1.2.4.L153.B0"; width=1920; height=1080; eotf="smpte2084"') => true
VM10:1 New style VP9 codec string must start with vp09. codecId:hev1.2.4.L153.B0
[JULIAN]: canDisplayType(video/mp4; codecs="hev1.2.4.L153.B0"; width=3840; height=2160; eotf="smpte2084"') => true
VM10:1 New style VP9 codec string must start with vp09. codecId:hev1.2.4.L153.B0
[JULIAN]: canDisplayType(video/mp4; codecs="hev1.2.4.L153.B0"; width=1920; height=1080') => true
VM10:1 New style VP9 codec string must start with vp09. codecId:hev1.2.4.L153.B0
[JULIAN]: canDisplayType(video/mp4; codecs="hev1.2.4.L153.B0"; width=3840; height=2160') => true
VM10:1 New style VP9 codec string must start with vp09. codecId:hev1.2.4.L153.B0
[JULIAN]: canDisplayType(video/mp4; codecs="hev1.2.4.L153.B0"') => true
VM10:1 New style VP9 codec string must start with vp09. codecId:hev1.2.4.L153.B0
[JULIAN]: canDisplayType(video/mp4; codecs="hev1.2.4.L153.B0; eotf="smpte2084"') => true
VM10:1 New style VP9 codec string must start with vp09. codecId:hvc1.2.4.L153.B0
[JULIAN]: canDisplayType(video/mp4; codecs="hvc1.2.4.L153.B0"; width=1920; height=1080; eotf="smpte2084"') => true
VM10:1 New style VP9 codec string must start with vp09. codecId:hvc1.2.4.L153.B0
[JULIAN]: canDisplayType(video/mp4; codecs="hvc1.2.4.L153.B0"; width=3840; height=2160; eotf="smpte2084"') => true
VM10:1 New style VP9 codec string must start with vp09. codecId:hvc1.2.4.L153.B0
[JULIAN]: canDisplayType(video/mp4; codecs="hvc1.2.4.L153.B0"; width=1920; height=1080') => true
VM10:1 New style VP9 codec string must start with vp09. codecId:hvc1.2.4.L153.B0
[JULIAN]: canDisplayType(video/mp4; codecs="hvc1.2.4.L153.B0"; width=3840; height=2160') => true
VM10:1 New style VP9 codec string must start with vp09. codecId:hvc1.2.4.L153.B0
[JULIAN]: canDisplayType(video/mp4; codecs="hvc1.2.4.L153.B0"') => true
VM10:1 New style VP9 codec string must start with vp09. codecId:hvc1.2.4.L153.B0
[JULIAN]: canDisplayType(video/mp4; codecs="hvc1.2.4.L153.B0; eotf="smpte2084"') => true

@JulianDomingo JulianDomingo added component: HLS The issue involves Apple's HLS manifest format priority: P1 Big impact or workaround impractical; resolve before feature release platform: Cast Issues affecting Cast devices labels Nov 17, 2022
@JulianDomingo JulianDomingo self-assigned this Nov 17, 2022
@JulianDomingo JulianDomingo changed the title Initial fix with temp debug logs. fix(polyfill): Call cast.__platform__.canDisplayType() to determine supported for MediaCapabilties.decodingInfo() polyfill in Cast devices. Nov 17, 2022
@github-actions
Copy link
Contributor

github-actions bot commented Nov 17, 2022

Incremental code coverage: 100.00%

@avelad avelad added this to the v4.4 milestone Nov 18, 2022
@avelad avelad added type: bug Something isn't working correctly and removed component: HLS The issue involves Apple's HLS manifest format labels Nov 18, 2022
lib/polyfill/media_capabilities.js Outdated Show resolved Hide resolved
lib/polyfill/media_capabilities.js Outdated Show resolved Hide resolved
@avelad
Copy link
Member

avelad commented Nov 21, 2022

@JulianDomingo There seems to be a lot of bugs in the tests when running on Chromecast, can you review it? Thanks!

@JulianDomingo
Copy link
Contributor Author

Sure thing, it looks like canDisplayType() is returning false for basic video stream configs, surprisingly. So there's no stream variants to test on - looking into it.

joeyparrish
joeyparrish previously approved these changes Nov 22, 2022
Copy link
Member

@joeyparrish joeyparrish left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM if spyOn doesn't need cleanup

test/polyfill/media_capabilities_unit.js Show resolved Hide resolved
@JulianDomingo JulianDomingo force-pushed the 4726-account-for-extended-mime-type-parameters-in-mediacapabilitiesdecodinginfo-polyfill-for-cast-platform branch 4 times, most recently from f625b35 to 2b8ecf9 Compare November 23, 2022 07:27
…ble. Only throw an error if the entire cast namespace is unavailable.
@JulianDomingo JulianDomingo force-pushed the 4726-account-for-extended-mime-type-parameters-in-mediacapabilitiesdecodinginfo-polyfill-for-cast-platform branch from 2b8ecf9 to 6a8cf51 Compare November 23, 2022 09:16
@JulianDomingo
Copy link
Contributor Author

@avelad @joeyparrish Based on my findings with the Chromecast lab failures, the tests were failing due to cast.__platform__ && cast.__platform__.canDisplayType being unavailable (but cast is available). My solution is to fall back to the original MediaSource.isTypeSupported(contentType) if the full cast API set isn't available.

  • In this commit which removes the cast.__platform__ && cast.__platform__.canDisplayType check (720fe11), you can see Chromecast lab tests fail.
  • The subsequent commit re-instates the above check (8465a99) and the Chromecast lab tests succeed.

This obviously contradicts with my manual tests on my Chromecast devices. Maybe this has something to do with the canDisplayType binding not being "applied" yet when the tests are ran? I'm not as knowledgeable on how the unit tests / integration tests are "hooked" to the platform when lab tests are ran.

avelad
avelad previously approved these changes Nov 24, 2022
frameRate = undefined,
transferFunction = undefined,
}) {
if (!(window.cast && cast)) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: I don't believe you need both of these checks. I would just say if (!window.cast).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, removed.

Comment on lines 249 to 253
* width: Describes the stream horizontal resolution in pixels.
* height: Describes the stream vertical resolution in pixels.
* frameRate: Describes the frame rate of the stream.
* transferFunction: Describes the video transfer function supported by
* the rendering capabilities of the user agent.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since all of these come from videoConfig, I feel like you should just pass that instead of creating a new record type.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, thanks

shaka.util.Error.Category.CAST,
shaka.util.Error.Code.CAST_API_UNAVAILABLE);
} else if (!(cast.__platform__ && cast.__platform__.canDisplayType)) {
shaka.log.warning('Expected cast APIs to be available! Falling back to ' +
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is very strange. I'd like to help you look into that, but I don't want to hold up the PR for it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, was held up on this for a while - the lab tests were failing without this check.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I spent a solid day on this, and it's time for me to give up for now. I managed to forward the Cast platform APIs through an iframe boundary, but not in a way that is compatible with Karma's websocket usage. :-(

test/polyfill/media_capabilities_unit.js Show resolved Hide resolved
'codecs="hev1.2.4.L153.B0"; ' +
'width=512; ' +
'height=288; ' +
'framerate=23.976023976023978; ' +
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks brittle. I don't know if we can rely on this exact amount of detail in converting a number to a string on all devices. Can you make the framerate 24 for this test instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, forgot to consider precision here.

Comment on lines 249 to 253
* width: Describes the stream horizontal resolution in pixels.
* height: Describes the stream vertical resolution in pixels.
* frameRate: Describes the frame rate of the stream.
* transferFunction: Describes the video transfer function supported by
* the rendering capabilities of the user agent.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

+1

@joeyparrish joeyparrish changed the title fix(polyfill): Call cast.__platform__.canDisplayType() to determine supported for MediaCapabilties.decodingInfo() polyfill in Cast devices. fix(cast): Use cast platform APIs in MediaCapabilties polyfill Dec 1, 2022
@joeyparrish joeyparrish merged commit 5d6f56a into shaka-project:main Dec 1, 2022
joeyparrish pushed a commit that referenced this pull request Dec 8, 2022
See #4726 for more
context.

This allows Cast devices to properly filter stream variants with a
resolution surpassing that of the device's capabilities.

We place the fix in the `MediaCapabilities` polyfill since it's intended
to be the right way to check for anything related to platform support.

HDR support checks will require `eotf=smpte2048`, as indicated in
#2813 (comment).
Specifically, a `{hev|hvc}1.2` profile is only an *indication* of an HDR
transfer function, but *may* be a non-HDR 10-bit color stream.

In Cast, the platform can distinguish between the two by explicitly
providing the transfer function; it uses `smpte2048` (`"PQ"`) because
this is the "basis of HDR video formats..."
(https://en.wikipedia.org/wiki/Perceptual_quantizer).
joeyparrish pushed a commit that referenced this pull request Dec 8, 2022
See #4726 for more
context.

This allows Cast devices to properly filter stream variants with a
resolution surpassing that of the device's capabilities.

We place the fix in the `MediaCapabilities` polyfill since it's intended
to be the right way to check for anything related to platform support.

HDR support checks will require `eotf=smpte2048`, as indicated in
#2813 (comment).
Specifically, a `{hev|hvc}1.2` profile is only an *indication* of an HDR
transfer function, but *may* be a non-HDR 10-bit color stream.

In Cast, the platform can distinguish between the two by explicitly
providing the transfer function; it uses `smpte2048` (`"PQ"`) because
this is the "basis of HDR video formats..."
(https://en.wikipedia.org/wiki/Perceptual_quantizer).
joeyparrish pushed a commit that referenced this pull request Dec 8, 2022
See #4726 for more
context.

This allows Cast devices to properly filter stream variants with a
resolution surpassing that of the device's capabilities.

We place the fix in the `MediaCapabilities` polyfill since it's intended
to be the right way to check for anything related to platform support.

HDR support checks will require `eotf=smpte2048`, as indicated in
#2813 (comment).
Specifically, a `{hev|hvc}1.2` profile is only an *indication* of an HDR
transfer function, but *may* be a non-HDR 10-bit color stream.

In Cast, the platform can distinguish between the two by explicitly
providing the transfer function; it uses `smpte2048` (`"PQ"`) because
this is the "basis of HDR video formats..."
(https://en.wikipedia.org/wiki/Perceptual_quantizer).
joeyparrish pushed a commit that referenced this pull request Dec 8, 2022
See #4726 for more
context.

This allows Cast devices to properly filter stream variants with a
resolution surpassing that of the device's capabilities.

We place the fix in the `MediaCapabilities` polyfill since it's intended
to be the right way to check for anything related to platform support.

HDR support checks will require `eotf=smpte2048`, as indicated in
#2813 (comment).
Specifically, a `{hev|hvc}1.2` profile is only an *indication* of an HDR
transfer function, but *may* be a non-HDR 10-bit color stream.

In Cast, the platform can distinguish between the two by explicitly
providing the transfer function; it uses `smpte2048` (`"PQ"`) because
this is the "basis of HDR video formats..."
(https://en.wikipedia.org/wiki/Perceptual_quantizer).
@github-actions github-actions bot added the status: archived Archived and locked; will not be updated label Jul 25, 2023
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jul 25, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
platform: Cast Issues affecting Cast devices priority: P1 Big impact or workaround impractical; resolve before feature release status: archived Archived and locked; will not be updated type: bug Something isn't working correctly
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Account for extended MIME type parameters in MediaCapabilities.decodingInfo() polyfill for Cast platform
4 participants