Skip to content

tvos: Implement UrlPlayer for native HLS playback - #10698

Open
abhijeetk wants to merge 1 commit into
youtube:mainfrom
abhijeetk:URLPlayer-Phase-01-v3
Open

tvos: Implement UrlPlayer for native HLS playback#10698
abhijeetk wants to merge 1 commit into
youtube:mainfrom
abhijeetk:URLPlayer-Phase-01-v3

Conversation

@abhijeetk

@abhijeetk abhijeetk commented May 29, 2026

Copy link
Copy Markdown
Collaborator

Introduce native HLS support for tvOS by integrating the platform's
AVPlayer into the media pipeline. This allows Cobalt to leverage
native hardware acceleration and platform-specific HLS features
while maintaining the standard Chromium control interface.

A UrlPlayerDemuxer is injected via the demuxer_override mechanism
and exposes placeholder streams to satisfy Chromium's stream-based
initialization. Actual playback is delegated to the platform player.

The HLS URL is carried from the demuxer through
MediaResource::GetMediaUrl() in the renderer process, then bridged
to the GPU process via the StarboardRendererExtension Mojo interface.

Bug: 512045535

@abhijeetk abhijeetk self-assigned this May 29, 2026
@github-actions

Copy link
Copy Markdown
Contributor

🤖 Gemini Suggested Commit Message


media: Implement UrlPlayer for native HLS playback

Introduce UrlPlayerDemuxer to support native URL-based media players,
primarily for HLS on tvOS using AVPlayer. The demuxer carries the media
URL through the pipeline and exposes placeholder streams to satisfy
Chromium's MojoRenderer initialization requirements.

StarboardRenderer detects the URL player path via the source URL and
calls SbUrlPlayerCreate instead of the standard stream-based player.
This design keeps URL player logic isolated from upstream code paths,
simplifying future rebases. HLS detection is centralized to skip
DataSource creation when native playback is preferred.

Bug: 512045535

💡 Pro Tips for a Better Commit Message:

  1. Influence the Result: Want to change the output? You can write custom prompts or instructions directly in the Pull Request description. The model uses that text to generate the message.
  2. Re-run the Generator: Post a comment with: /generate-commit-message

@abhijeetk
abhijeetk force-pushed the URLPlayer-Phase-01-v3 branch 3 times, most recently from bdfff13 to 63765d6 Compare May 30, 2026 14:57
@abhijeetk
abhijeetk force-pushed the URLPlayer-Phase-01-v3 branch 3 times, most recently from 2735b1c to e8b32c7 Compare June 10, 2026 12:20
@abhijeetk abhijeetk changed the title media: Basic URLPlayer implementation media: Implement UrlPlayer for native HLS on tvOS Jun 10, 2026
@abhijeetk
abhijeetk marked this pull request as ready for review June 10, 2026 18:53
@abhijeetk
abhijeetk requested review from a team as code owners June 10, 2026 18:53

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request introduces support for URL-based native media playback (such as HLS on tvOS) by implementing a placeholder UrlPlayerDemuxer and updating the Starboard renderer components to delegate demuxing, buffering, and playback to the platform player. The code review feedback identifies critical preprocessor guard mismatches that could cause compilation failures when USE_STARBOARD_MEDIA is disabled, and suggests adding a defensive fallback for video resolution rather than relying solely on a DCHECK. Additionally, the newly introduced classes lack required documentation on lifetime, ownership, and threading models as specified by the style guide, and a missing header include for raw_ptr was noted.

Comment thread media/mojo/clients/starboard/starboard_renderer_client.cc
Comment thread media/starboard/starboard_renderer.cc Outdated
Comment thread media/starboard/url_player_demuxer.h Outdated
Comment thread media/starboard/url_player_demuxer.h Outdated
Comment thread media/starboard/url_player_demuxer.h
Comment thread media/mojo/clients/starboard/starboard_renderer_client.cc
@abhijeetk
abhijeetk force-pushed the URLPlayer-Phase-01-v3 branch from e8b32c7 to 46b0401 Compare June 11, 2026 11:01
@abhijeetk

Copy link
Copy Markdown
Collaborator Author

cc : @Gyuyoung @jkim-julie @rakuco

@rakuco
rakuco requested review from borongc and removed request for oxve June 11, 2026 11:17
@borongc

borongc commented Jun 11, 2026

Copy link
Copy Markdown
Member

@jasonzhangxx is out, this PR needs his review.

@abhijeetk abhijeetk closed this Jun 25, 2026
@abhijeetk
abhijeetk deleted the URLPlayer-Phase-01-v3 branch June 25, 2026 16:56
@abhijeetk
abhijeetk restored the URLPlayer-Phase-01-v3 branch June 25, 2026 17:07
@abhijeetk

Copy link
Copy Markdown
Collaborator Author

I wanted to share an update on the URL player (AVPlayer/HLS) work for tvOS.

I've closed this PR #10698 ("media: Implement UrlPlayer for native HLS on tvOS"). This PR added URL player support by extending the existing Starboard renderer and wrapper classes inline. The new approach introduces dedicated renderer, client, and factory classes (UrlPlayerRenderer UrlPlayerRendererClient, UrlPlayerRendererWrapper) with a clean factory-level split, rather than piggybacking on the Starboard code path. This gives us better separation of concerns and makes the code easier to review and maintain.

Here is the new PR stack. Please review in order, as each PR builds on the previous one:

  1. media: Add RendererType::kUrlPlayer and buildflag #10979 - media: Add RendererType::kUrlPlayer and buildflag
  2. media: Add InitializeWithUrl transport and URL player renderer #10989 - media: Add InitializeWithUrl transport and URL player renderer
  3. media: Add URL-player renderer client and GetMediaUrl #10998 - media: Add URL-player renderer client and GetMediaUrl
  4. media: Wire URL-player renderer factory plumbing #11056 - media: Wire URL-player renderer factory plumbing
  5. media: Add URL-player demuxer and HLS URL predicate #11067 - media: Add URL-player demuxer and HLS URL predicate
  6. media: Route HLS URLs to URL-player renderer #11066 - media: Route HLS URLs to URL-player Renderer

All PRs have been build-verified and tested on tvOS simulator.

@github-actions

Copy link
Copy Markdown
Contributor

🤖 Gemini Suggested Commit Message


media: Implement native HLS support for tvOS

Integrate the tvOS native AVPlayer into the Cobalt media pipeline to
provide native HLS support. This allows Cobalt to leverage hardware
acceleration and platform-specific HLS features while maintaining the
standard Chromium control interface.

The implementation uses a UrlPlayerDemuxer to provide placeholder
streams for Chromium's initialization, then bridges the actual media
URL from the renderer process to the GPU process using the
StarboardRendererExtension Mojo interface.

Bug: 512045535

💡 Pro Tips for a Better Commit Message:

  1. Influence the Result: Want to change the output? You can write custom prompts or instructions directly in the Pull Request description. The model uses that text to generate the message.
  2. Re-run the Generator: Post a comment with: /generate-commit-message

Add URL player support to StarboardRenderer for native HLS playback.
UrlPlayerDemuxer provides placeholder streams for pipeline init while
the platform player handles actual playback via SetSourceUrl.

Bug: 512045535
@abhijeetk
abhijeetk force-pushed the URLPlayer-Phase-01-v3 branch from af7c613 to c280e82 Compare July 28, 2026 18:34
abhijeetk added a commit to abhijeetk/cobalt that referenced this pull request Jul 28, 2026
through StarboardRenderer, StarboardRendererWrapper, Mojo IPC, and
UrlPlayerDemuxer. This ensures that the JavaScript video.duration and
video.buffered APIs correctly reflect the underlying platform player
state on tvOS.

Duration is reported once when the player reaches the presenting state.
Buffered ranges are polled via GetMediaTime on each timer tick to
provide continuous updates to the web application.

Blocked by youtube#10698

Bug: 512045535
@jasonzhangxx

Copy link
Copy Markdown
Contributor

Let's change the to "tvos: Implement UrlPlayer for native HLS playback", as the change is specifically to tvos.

@borongc

borongc commented Jul 28, 2026

Copy link
Copy Markdown
Member

Left some comments in #11548, which should be addressed in this PR.

@jasonzhangxx jasonzhangxx left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Let's change the title to start with "tvos:" as it's specifically for tvos.

// AVSBVideoRenderer::SetBounds() when necessary.
UIView* playerContainerView = [[UIView alloc] init];
UIView* playerContainerView =
[[UIView alloc] initWithFrame:[UIScreen mainScreen].bounds];

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@abhijeetk, could you help me understand this change? I'm curious why we need it, and if it could have problem when player is non full screen.

@abhijeetk abhijeetk Jul 30, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I checked this against C25. In C25, SBDApplicationView was initialized with UIScreen.mainScreen.bounds in application_window.mm, and the player
container was initialized with that application view frame in application_view.mm. So using [UIScreen mainScreen].bounds here keeps the new chrobalt shell path closer to the old C25 behavior.

That said, I also verified that reverting this to [[UIView alloc] init] does not break playback. The URL player view (SBDPlayerView) is created with its own fullscreen frame in
application_player.mm. It is later resized via setBoundsX:y:width:height: in application_player.mm.

So the initial frame of the chrobalt shell playerContainerView is not what determines the final video size. Initializing it with [UIScreen mainScreen].bounds is mainly for C25 layout parity and not because final video bounds depend on it.

is_url_player = url.is_valid();
#endif // BUILDFLAG(IS_IOS_TVOS)

if (!is_url_player &&

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@abhijeetk, can you help to confirm if url player and mojo bypass mechanisms mutually exclusive?

My understanding is we can still bypass mojo with url player. @borongc to review this piece of code.

@abhijeetk abhijeetk Jul 30, 2026

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Hi @jasonzhangxx , borong has reviewed same changes in PR : #11548

As per this comment, I can infer that bypass mojo is not applicable to tvOS.

Comment thread media/mojo/services/starboard/starboard_renderer_wrapper.cc
};

// Returns true when the renderer is operating in URL player mode.
bool IsUrlPlayer() const;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

IsUrlPlayer and OnUrlPlayerPresenting are for url player on tvos, we can guard them behind SB_HAS(PLAYER_WITH_URL) or BUILDFLAG(IS_IOS_TVOS).

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

IsUrlPlayer() is called unconditionally in Initialize(), CreatePlayerBridge(), OnNeedData() etc. Guarding the declaration would require wrapping every call site with #if BUILDFLAG(IS_IOS_TVOS), adding noise and making rebasing harder.

Currently it just returns false on non-tvOS via #if/#else in the body, keeping call sites clean. Happy to change if you prefer though.

if (width > 0 && height > 0) {
gfx::Size size(width, height);
client_->OnVideoNaturalSizeChange(size);
paint_video_hole_frame_cb_.Run(size);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The current implementation triggers the video natural size update and the paint_video_hole_frame_cb_ only once here. As hls content is adaptive, will this work properly if the video resolution changes mid-playback?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

You're right, OnUrlPlayerPresenting() is called once from OnPlayerStatus() when the player transitions to kSbPlayerStatePresenting. There's currently no mechanism to detect resolution changes mid-playback.

Will add this in a follow-up PR if preferred.

}

// URL player handles all buffering natively so ignore OnNeedData.
if (IsUrlPlayer()) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Will OnNeedData be called by url player?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

No, it should not be called for the URL-player path. OnNeedData() is reached through SbPlayerBridge::OnDecoderStatus(), which is wired from the decoder-status callback passed to normal SbPlayerCreate(). The URL-player path uses SbUrlPlayerCreate(), whose API does not take a decoder-status callback, so URL player should not request demuxed data through OnNeedData().

The early return in OnNeedData is just a defensive guard as this function deals with stream which we want to bypass for URL-Player. I’ll remove this guard unless we want to keep it only as defensive protection.

));
));
}
if (player_bridge_->IsValid()) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I made a cleanup pr go/cobalt-pr/11583 to simply the code. Please rebase the change after that pr is merged. That pr can help to simplify the code here.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Acknowledged.

}

AudioDecoderConfig UrlPlayerDemuxerStream::audio_decoder_config() {
return AudioDecoderConfig(AudioCodec::kAAC, kSampleFormatS16,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Will this function and video_decoder_config be actually used?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yes. These are placeholder configs, not configs used for URL-player decoding. These placeholder configs are required for media pipeline initialization, which is stream-based.

UrlPlayerDemuxer exposes audio/video DemuxerStreams via UrlPlayerDemuxer::GetAllStreams(), and the Mojo demuxer stream initialization reads the matching audio_decoder_config()/video_decoder_config() for initial stream metadata.

These configs need to be valid because they are sent over Mojo IPC during stream initialization, and the Mojo traits reject invalid configs via IsValidConfig() (media/mojo/mojom/audio_decoder_config_mojom_traits.cc, media/mojo/mojom/
video_decoder_config_mojom_traits.cc:73
). AAC/H264 are only valid placeholder configs for the stream-based pipeline handshake; the native URL player does not use them for actual decoding.

@abhijeetk abhijeetk changed the title media: Implement UrlPlayer for native HLS on tvOS tvos: Implement UrlPlayer for native HLS playback Jul 30, 2026
abhijeetk added a commit to abhijeetk/cobalt that referenced this pull request Jul 30, 2026
SB_HAS_PLAYER_WITH_URL is legacy Cobalt configuration that was only
defined for tvOS in configuration_public.h. In the Chromium
architecture, BUILDFLAG(IS_IOS_TVOS) is the standard way to gate
tvOS-specific code.

Replace all SB_HAS(PLAYER_WITH_URL) guards with BUILDFLAG(IS_IOS_TVOS)
across sbplayer_bridge, sbplayer_interface, starboard_renderer, and
url_player_create_test. Replace the indirect SB_URL_PLAYER_INCLUDE_PATH
include with the direct header path. Remove both definitions from
starboard/tvos/shared/configuration_public.h.

Required-For: youtube#10698

Bug: 512045535
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants