Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions cobalt/renderer/cobalt_content_renderer_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

#include "base/task/bind_post_task.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "cobalt/media/service/mojom/platform_window_provider.mojom.h"
#include "cobalt/renderer/cobalt_render_frame_observer.h"
#include "cobalt/shell/common/url_constants.h"
Expand All @@ -46,6 +47,10 @@
#include "third_party/blink/public/web/web_view.h"
#include "ui/gfx/geometry/size_conversions.h"

#if BUILDFLAG(IS_IOS_TVOS)
#include "media/starboard/url_player_demuxer.h"
#endif // BUILDFLAG(IS_IOS_TVOS)

namespace cobalt {

namespace {
Expand Down Expand Up @@ -368,4 +373,18 @@ void CobaltContentRendererClient::PostSandboxInitialized() {
}
}

std::unique_ptr<::media::Demuxer>
CobaltContentRendererClient::OverrideDemuxerForUrl(
content::RenderFrame* render_frame,
const GURL& url,
scoped_refptr<base::SequencedTaskRunner> task_runner) {
#if BUILDFLAG(IS_IOS_TVOS)
if (::media::IsHlsUrl(url)) {
return std::make_unique<::media::UrlPlayerDemuxer>(std::move(task_runner),
url);
}
#endif // BUILDFLAG(IS_IOS_TVOS)
return nullptr;
}

} // namespace cobalt
6 changes: 6 additions & 0 deletions cobalt/renderer/cobalt_content_renderer_client.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#define COBALT_RENDERER_COBALT_CONTENT_RENDERER_CLIENT_H_

#include <atomic>
#include <memory>

#include "base/functional/callback.h"
#include "base/memory/weak_ptr.h"
Expand All @@ -27,6 +28,7 @@
#include "cobalt/media/audio/cobalt_audio_device_factory.h"
#include "cobalt/media/service/mojom/platform_window_provider.mojom.h"
#include "content/public/renderer/content_renderer_client.h"
#include "media/base/demuxer.h"
#include "media/base/key_systems_support_registration.h"
#include "media/base/starboard/renderer_factory_traits.h"
#include "mojo/public/cpp/bindings/remote.h"
Expand Down Expand Up @@ -74,6 +76,10 @@ class CobaltContentRendererClient : public content::ContentRendererClient {
void GetStarboardRendererFactoryTraits(
::media::RendererFactoryTraits* traits) override;
void PostSandboxInitialized() override;
std::unique_ptr<::media::Demuxer> OverrideDemuxerForUrl(
content::RenderFrame* render_frame,
const GURL& url,
scoped_refptr<base::SequencedTaskRunner> task_runner) override;

uint64_t GetSbWindowHandle() const { return sb_window_handle_; }

Expand Down
3 changes: 2 additions & 1 deletion cobalt/shell/browser/shell_platform_delegate_ios.mm
Original file line number Diff line number Diff line change
Expand Up @@ -365,7 +365,8 @@ - (void)viewDidLoad {
// Note that the actual size and and position of this view are irrelevant at
// this point: it will be changed in starboard's
// 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.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

I'd rather revert this part of the change to avoid confusion. The comment above this bit mentions how the size is actually set via AVSBVideoRenderer::SetBounds().

playerContainerView.accessibilityIdentifier = @"Player Container";
[_contentView addSubview:playerContainerView];
[SBDGetApplication() setPlayerContainerView:playerContainerView];
Expand Down
1 change: 1 addition & 0 deletions media/base/demuxer.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ enum class DemuxerType {
kFrameInjectingDemuxer = 5,
kStreamProviderDemuxer = 6,
kManifestDemuxer = 7,
kUrlPlayerDemuxer = 8, // URL player placeholder demuxer.
};

class MEDIA_EXPORT DemuxerHost {
Expand Down
6 changes: 6 additions & 0 deletions media/base/media_resource.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,10 @@ DemuxerStream* MediaResource::GetFirstStream(DemuxerStream::Type type) {
return nullptr;
}

#if BUILDFLAG(IS_IOS_TVOS)
GURL MediaResource::GetMediaUrl() const {
return GURL();
}
#endif // BUILDFLAG(IS_IOS_TVOS)

} // namespace media
9 changes: 9 additions & 0 deletions media/base/media_resource.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@

#include "base/memory/raw_ptr.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "media/base/demuxer_stream.h"
#include "media/base/media_export.h"
#if BUILDFLAG(IS_IOS_TVOS)
#include "url/gurl.h"
#endif // BUILDFLAG(IS_IOS_TVOS)

namespace media {

Expand Down Expand Up @@ -41,6 +45,11 @@ class MEDIA_EXPORT MediaResource {
// A helper function that return the first stream of the given `type` if one
// exists or a null pointer if there is no streams of that type.
DemuxerStream* GetFirstStream(DemuxerStream::Type type);

#if BUILDFLAG(IS_IOS_TVOS)
// Returns the media URL for URL player.
virtual GURL GetMediaUrl() const;
#endif // BUILDFLAG(IS_IOS_TVOS)
};

} // namespace media
Expand Down
25 changes: 23 additions & 2 deletions media/mojo/clients/starboard/starboard_renderer_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "base/functional/bind.h"
#include "base/time/time.h"
#include "base/unguessable_token.h"
#include "build/build_config.h"
#include "media/base/media_log.h"
#include "media/base/media_resource.h"
#include "media/base/media_switches.h"
Expand All @@ -30,6 +31,10 @@
#include "mojo/public/cpp/bindings/callback_helpers.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"

#if BUILDFLAG(IS_IOS_TVOS)
#include "url/gurl.h"
#endif // BUILDFLAG(IS_IOS_TVOS)
Comment thread
abhijeetk marked this conversation as resolved.

#if BUILDFLAG(IS_ANDROID)
#include "base/task/bind_post_task.h"
#endif // BUILDFLAG(IS_ANDROID)
Expand Down Expand Up @@ -351,8 +356,18 @@ void StarboardRendererClient::InitializeMojoRenderer(
DCHECK(media_task_runner_->RunsTasksInCurrentSequence());
DCHECK(AreMojoPipesConnected());

if (base::FeatureList::IsEnabled(kCobaltBypassMojoForMedia) ||
bypass_mojo_for_media_) {
// URL player is incompatible with the bypass bridge because the bypass
// bridge proxies demuxer streams, while the URL player delegates playback
// entirely to the native platform player.
bool is_url_player = false;
#if BUILDFLAG(IS_IOS_TVOS)
GURL url = media_resource->GetMediaUrl();
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.

(base::FeatureList::IsEnabled(kCobaltBypassMojoForMedia) ||
bypass_mojo_for_media_)) {
bypass_bridge_ = base::MakeRefCounted<MojoRendererBypassBridge>(
media_task_runner_,
base::BindRepeating(&StarboardRendererClient::OnTimeUpdateFromBridge,
Expand All @@ -378,6 +393,12 @@ void StarboardRendererClient::InitializeMojoRenderer(
return;
}

#if BUILDFLAG(IS_IOS_TVOS)
if (is_url_player) {
renderer_extension_->SetSourceUrl(url.spec());
}
#endif // BUILDFLAG(IS_IOS_TVOS)
Comment thread
abhijeetk marked this conversation as resolved.

MojoRendererWrapper::Initialize(media_resource, client, std::move(init_cb));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ class FakeStarboardRendererExtension
#endif // BUILDFLAG(IS_ANDROID)
void OnGpuChannelTokenReady(
mojom::CommandBufferIdPtr command_buffer_id) override {}
void SetSourceUrl(const std::string& source_url) override {}

private:
FakeMojomRendererCallRecord* record_ = nullptr;
Expand Down
1 change: 1 addition & 0 deletions media/mojo/mojom/media_types.mojom
Original file line number Diff line number Diff line change
Expand Up @@ -662,6 +662,7 @@ enum DemuxerType {
kFrameInjectingDemuxer = 5,
kStreamProviderDemuxer = 6,
kManifestDemuxer = 7,
kUrlPlayerDemuxer = 8, // URL player placeholder demuxer.
};

// See media::CreateCdmStatus
Expand Down
9 changes: 7 additions & 2 deletions media/mojo/mojom/media_types_enum_mojom_traits.h
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ struct EnumTraits<media::mojom::RendererType, ::media::RendererType> {
#if BUILDFLAG(USE_STARBOARD_MEDIA)
case ::media::RendererType::kStarboard:
return media::mojom::RendererType::kStarboard;
#endif // BUILDFLAG(USE_STARBOARD_MEDIA)
#endif // BUILDFLAG(USE_STARBOARD_MEDIA)
}

NOTREACHED();
Expand Down Expand Up @@ -436,7 +436,7 @@ struct EnumTraits<media::mojom::RendererType, ::media::RendererType> {
case media::mojom::RendererType::kStarboard:
*output = ::media::RendererType::kStarboard;
return true;
#endif // BUILDFLAG(USE_STARBOARD_MEDIA)
#endif // BUILDFLAG(USE_STARBOARD_MEDIA)
}

NOTREACHED();
Expand All @@ -461,6 +461,8 @@ struct EnumTraits<media::mojom::DemuxerType, ::media::DemuxerType> {
return media::mojom::DemuxerType::kStreamProviderDemuxer;
case ::media::DemuxerType::kManifestDemuxer:
return media::mojom::DemuxerType::kManifestDemuxer;
case ::media::DemuxerType::kUrlPlayerDemuxer:
return media::mojom::DemuxerType::kUrlPlayerDemuxer;
}

NOTREACHED();
Expand Down Expand Up @@ -492,6 +494,9 @@ struct EnumTraits<media::mojom::DemuxerType, ::media::DemuxerType> {
case media::mojom::DemuxerType::kManifestDemuxer:
*output = ::media::DemuxerType::kManifestDemuxer;
return true;
case media::mojom::DemuxerType::kUrlPlayerDemuxer:
*output = ::media::DemuxerType::kUrlPlayerDemuxer;
return true;
}

NOTREACHED();
Expand Down
3 changes: 3 additions & 0 deletions media/mojo/mojom/renderer_extensions.mojom
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,9 @@ interface StarboardRendererExtension {
// Initialize media bypass bridge in single-process mode.
InitializeWithBypassBridge(uint32 bypass_bridge_id) => (bool success);

// Pass source URL for URL player.
SetSourceUrl(string source_url);

[EnableIf=is_android]
// Notify StarboardRendererWrapper when the current OverlayInfo changes.
OnOverlayInfoChanged(OverlayInfo overlay_info);
Expand Down
8 changes: 8 additions & 0 deletions media/mojo/services/starboard/starboard_renderer_wrapper.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "base/functional/callback_helpers.h"
#include "base/task/bind_post_task.h"
#include "base/time/time.h"
#include "build/build_config.h"
#include "media/base/demuxer_stream.h"
#include "media/base/media_resource.h"
#include "media/base/starboard/starboard_rendering_mode.h"
Expand Down Expand Up @@ -515,6 +516,13 @@ void StarboardRendererWrapper::InitializeWithBypassBridge(
std::move(callback).Run(true);
}

void StarboardRendererWrapper::SetSourceUrl(const std::string& source_url) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
#if BUILDFLAG(IS_IOS_TVOS)
GetRenderer()->SetSourceUrl(source_url);
#endif // BUILDFLAG(IS_IOS_TVOS)
}

#if BUILDFLAG(IS_ANDROID)
void StarboardRendererWrapper::OnOverlayInfoChanged(
const OverlayInfo& overlay_info) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ class StarboardRendererWrapper
void InitializeWithBypassBridge(
uint32_t bypass_bridge_id,
InitializeWithBypassBridgeCallback callback) override;
void SetSourceUrl(const std::string& source_url) override;
#if BUILDFLAG(IS_ANDROID)
void OnOverlayInfoChanged(const OverlayInfo& overlay_info) override;
#endif // BUILDFLAG(IS_ANDROID)
Expand Down
6 changes: 6 additions & 0 deletions media/starboard/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ source_set("starboard") {
]

deps += [ ":buildflags" ]
if (is_ios && target_platform == "tvos") {
sources += [
"url_player_demuxer.cc",
"url_player_demuxer.h",
]
}
}

deps += [
Expand Down
Loading
Loading