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

Implement SourceBuffer.writeHead attribute #4559

Merged
merged 11 commits into from
Jan 8, 2025
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,8 @@ protected void createContent(final Bundle savedInstanceState) {
"--enable-features=LogJsConsoleMessages",
// Disable rescaling Webpage.
"--force-device-scale-factor=1",
// Enable Cobalt-specific JS attributes/methods.
"--enable-blink-features=SourceBufferWriteHead",
};
CommandLine.getInstance().appendSwitchesAndArguments(cobaltCommandLineParams);

Expand Down
2 changes: 2 additions & 0 deletions cobalt/cobalt.cc
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ int main(int argc, const char** argv) {
// This flag is added specifically for m114 and should be removed after
// rebasing to m120+
"--user-level-memory-pressure-signal-params",
// Enable Cobalt-specific JS attributes/methods.
"--enable-blink-features=SourceBufferWriteHead",
"https://www.youtube.com/tv"});
std::vector<const char*> args(argv, argv + argc);
args.insert(args.end(), cobalt_args.begin(), cobalt_args.end());
Expand Down
33 changes: 33 additions & 0 deletions media/filters/chunk_demuxer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,9 @@ void ChunkDemuxerStream::Seek(base::TimeDelta time) {
DCHECK(state_ == UNINITIALIZED || state_ == RETURNING_ABORT_FOR_READS)
<< state_;

#if BUILDFLAG(USE_STARBOARD_MEDIA)
write_head_ = time;
#endif // BUILDFLAG(USE_STARBOARD_MEDIA)
stream_->Seek(time);
}

Expand Down Expand Up @@ -217,6 +220,13 @@ bool ChunkDemuxerStream::EvictCodedFrames(base::TimeDelta media_time,
return stream_->GarbageCollectIfNeeded(media_time, newDataSize);
}

#if BUILDFLAG(USE_STARBOARD_MEDIA)
base::TimeDelta ChunkDemuxerStream::GetWriteHead() const {
base::AutoLock auto_lock(lock_);
return write_head_;
}
#endif // BUILDFLAG(USE_STARBOARD_MEDIA)

void ChunkDemuxerStream::OnMemoryPressure(
base::TimeDelta media_time,
base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level,
Expand Down Expand Up @@ -490,6 +500,13 @@ void ChunkDemuxerStream::CompletePendingReadIfPossible_Locked() {
// Other cases are kOk and just return the buffers.
DCHECK(!buffers.empty());
requested_buffer_count_ = 0;
#if BUILDFLAG(USE_STARBOARD_MEDIA)
for (auto&& buffer : buffers) {
if (!buffer->end_of_stream()) {
write_head_ = std::max(write_head_, buffer->timestamp());
}
}
#endif // BUILDFLAG(USE_STARBOARD_MEDIA)
std::move(read_cb_).Run(kOk, std::move(buffers));
}

Expand Down Expand Up @@ -1051,6 +1068,22 @@ bool ChunkDemuxer::EvictCodedFrames(const std::string& id,
return itr->second->EvictCodedFrames(currentMediaTime, newDataSize);
}

#if BUILDFLAG(USE_STARBOARD_MEDIA)
base::TimeDelta ChunkDemuxer::GetWriteHead(const std::string& id) const {
base::AutoLock auto_lock(lock_);
DCHECK(IsValidId_Locked(id));

auto iter = id_to_streams_map_.find(id);
if (iter == id_to_streams_map_.end() || iter->second.empty()) {
// Handled just in case.
NOTREACHED();
return base::TimeDelta();
}

return iter->second[0]->GetWriteHead();
}
#endif // BUILDFLAG(USE_STARBOARD_MEDIA)

bool ChunkDemuxer::AppendToParseBuffer(const std::string& id,
const uint8_t* data,
size_t length) {
Expand Down
13 changes: 13 additions & 0 deletions media/filters/chunk_demuxer.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,12 @@ class MEDIA_EXPORT ChunkDemuxerStream : public DemuxerStream {
// https://w3c.github.io/media-source/#sourcebuffer-coded-frame-eviction
bool EvictCodedFrames(base::TimeDelta media_time, size_t newDataSize);

#if BUILDFLAG(USE_STARBOARD_MEDIA)
// Returns the latest presentation timestamp of the buffers received
// from the ChunkDemuxer.
base::TimeDelta GetWriteHead() const;
#endif // BUILDFLAG(USE_STARBOARD_MEDIA)

void OnMemoryPressure(
base::TimeDelta media_time,
base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level,
Expand Down Expand Up @@ -190,6 +196,7 @@ class MEDIA_EXPORT ChunkDemuxerStream : public DemuxerStream {

#if BUILDFLAG(USE_STARBOARD_MEDIA)
const std::string mime_type_;
base::TimeDelta write_head_ GUARDED_BY(lock_);
#endif // BUILDFLAG(USE_STARBOARD_MEDIA)

// Specifies the type of the stream.
Expand Down Expand Up @@ -416,6 +423,12 @@ class MEDIA_EXPORT ChunkDemuxer : public Demuxer {
base::TimeDelta currentMediaTime,
size_t newDataSize);

#if BUILDFLAG(USE_STARBOARD_MEDIA)
// Returns the latest presentation timestamp of the buffers sent to the
// DemuxerStream.
osagie98 marked this conversation as resolved.
Show resolved Hide resolved
[[nodiscard]] base::TimeDelta GetWriteHead(const std::string& id) const;
#endif // BUILDFLAG(USE_STARBOARD_MEDIA)

void OnMemoryPressure(
base::TimeDelta currentMediaTime,
base::MemoryPressureListener::MemoryPressureLevel memory_pressure_level,
Expand Down
9 changes: 9 additions & 0 deletions third_party/blink/public/platform/web_source_buffer.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@

namespace blink {

#if BUILDFLAG(USE_STARBOARD_MEDIA)
class ExceptionState;
#endif // BUILDFLAG(USE_STARBOARD_MEDIA)

class WebSourceBufferClient;

// Interface for actuating the media engine implementation of Media Source
Expand Down Expand Up @@ -140,6 +144,11 @@ class WebSourceBuffer {
// After this method is called, this WebSourceBuffer should never use the
// client pointer passed to SetClient().
virtual void RemovedFromMediaSource() = 0;

#if BUILDFLAG(USE_STARBOARD_MEDIA)
// Return the highest presentation timestamp written to the SbPlayer.
osagie98 marked this conversation as resolved.
Show resolved Hide resolved
virtual double WriteHead(ExceptionState& exception_state) const = 0;
#endif // BUILDFLAG(USE_STARBOARD_MEDIA)
};

} // namespace blink
Expand Down
13 changes: 13 additions & 0 deletions third_party/blink/renderer/bindings/idl_in_modules.gni
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@

import("//third_party/blink/renderer/config.gni")

if (is_cobalt) {
import("//starboard/build/buildflags.gni")
}

# Statically-defined (not build-time-generated) IDL files in 'modules' component
# for production.
static_idl_files_in_modules = get_path_info(
Expand Down Expand Up @@ -1279,6 +1283,15 @@ if (target_os != "android") {
"abspath")
}

# SourceBufferWriteHead
# An extension to the SourceBuffer interface that allows web apps to check the
# highest presentation timestamp written to the SbPlayer.
if (is_cobalt && use_starboard_media) {
static_idl_files_in_modules += get_path_info(
[ "//third_party/blink/renderer/modules/mediasource/source_buffer_write_head.idl" ],
"abspath")
}

# Statically-defined (not runtime-generated) IDL files in 'modules' component.
# These IDL definitions are used only for testing.
static_idl_files_in_modules_for_testing = get_path_info(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ class PLATFORM_EXPORT RuntimeEnabledFeatures : public RuntimeEnabledFeaturesBase
// platform/testing/runtime_enabled_features_test_helpers.h.
friend class DevToolsEmulator;
friend class InternalRuntimeFlags;
friend class SourceBuffer;
friend class V8ContextSnapshotImpl;
friend class WebRuntimeFeaturesBase;
friend class WebRuntimeFeatures;
Expand Down
6 changes: 4 additions & 2 deletions third_party/blink/renderer/modules/mediasource/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,10 @@ blink_modules_sources("mediasource") {
"//third_party/blink/renderer/modules/webcodecs:webcodecs",
]
if (is_cobalt && use_starboard_media) {
deps += [
"//starboard($starboard_toolchain)",
sources += [
"source_buffer_write_head.cc",
"source_buffer_write_head.h",
]
deps += [ "//starboard($starboard_toolchain)" ]
}
}
19 changes: 19 additions & 0 deletions third_party/blink/renderer/modules/mediasource/source_buffer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,25 @@ VideoTrackList& SourceBuffer::videoTracks() {
return *video_tracks_;
}

double SourceBuffer::writeHead(ExceptionState& exception_state) const {
if (!RuntimeEnabledFeatures::SourceBufferWriteHeadEnabled()) {
return 0.0;
}
#if BUILDFLAG(USE_STARBOARD_MEDIA)
if (source_ == NULL) {
MediaSource::LogAndThrowDOMException(
exception_state, DOMExceptionCode::kInvalidStateError,
"Cannot obtain SourceBuffer write head with an invalid MediaSource");
return 0.0;
}

DCHECK(web_source_buffer_);
return web_source_buffer_->WriteHead(exception_state);
#else
return 0.0;
#endif // BUILDFLAG(USE_STARBOARD_MEDIA)
}

double SourceBuffer::appendWindowStart() const {
return append_window_start_;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,10 @@ class SourceBuffer final : public EventTargetWithInlineData,
AudioTrackList& audioTracks();
VideoTrackList& videoTracks();

// Cobalt-specific method that returns the highest presentation
// timestamp written to the SbPlayer.
double writeHead(ExceptionState& exception_state) const;
osagie98 marked this conversation as resolved.
Show resolved Hide resolved
osagie98 marked this conversation as resolved.
Show resolved Hide resolved

// "_Locked" requires these be called while in the scope of callback of
// |source_|'s attachment's RunExclusively(). Other methods without "_Locked"
// may also require the same, since they can be called from within these
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2024 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "third_party/blink/renderer/modules/mediasource/source_buffer_write_head.h"

#include "third_party/blink/renderer/modules/mediasource/source_buffer.h"
#include "third_party/blink/renderer/platform/bindings/exception_state.h"

namespace blink {

// static
double SourceBufferWriteHead::writeHead(SourceBuffer& source_buffer,
ExceptionState& exception_state) {
return source_buffer.writeHead(exception_state);
}
} // namespace blink
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright 2024 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASOURCE_SOURCE_BUFFER_WRITE_HEAD_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASOURCE_SOURCE_BUFFER_WRITE_HEAD_H_

#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"

namespace blink {

class ExceptionState;
class SourceBuffer;

class SourceBufferWriteHead {
STATIC_ONLY(SourceBufferWriteHead);

public:
static double writeHead(SourceBuffer&, ExceptionState&);
};

} // namespace blink

#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASOURCE_SOURCE_BUFFER_WRITE_HEAD_H_
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// Copyright 2024 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Non standard interface used for Cobalt only.
// Returns the highest presentation timestamp written to the SbPlayer;
// raises `InvalidStateError` if the SourceBuffer object has been removed
// from the MediaSource object.

[
ImplementedAs=SourceBufferWriteHead
osagie98 marked this conversation as resolved.
Show resolved Hide resolved
] partial interface SourceBuffer {
[RaisesException, RuntimeEnabled=SourceBufferWriteHead] readonly attribute double writeHead;
};
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,13 @@ void WebSourceBufferImpl::RemovedFromMediaSource() {
client_ = nullptr;
}

#if BUILDFLAG(USE_STARBOARD_MEDIA)
double WebSourceBufferImpl::WriteHead(ExceptionState& exception_state) const {
DCHECK(demuxer_);
return demuxer_->GetWriteHead(id_).InSecondsF();
}
#endif // BUILDFLAG(USE_STARBOARD_MEDIA)

WebMediaPlayer::TrackType mediaTrackTypeToBlink(media::MediaTrack::Type type) {
switch (type) {
case media::MediaTrack::Audio:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ enum class SourceBufferParseWarning;

namespace blink {

#if BUILDFLAG(USE_STARBOARD_MEDIA)
class ExceptionState;
#endif // BUILDFLAG(USE_STARBOARD_MEDIA)

class PLATFORM_EXPORT WebSourceBufferImpl : public WebSourceBuffer {
public:
WebSourceBufferImpl(const std::string& id, media::ChunkDemuxer* demuxer);
Expand Down Expand Up @@ -57,6 +61,11 @@ class PLATFORM_EXPORT WebSourceBufferImpl : public WebSourceBuffer {
void SetAppendWindowEnd(double end) override;
void RemovedFromMediaSource() override;

#if BUILDFLAG(USE_STARBOARD_MEDIA)
// Return the highest presentation timestamp written to the SbPlayer.
double WriteHead(ExceptionState& exception_state) const override;
#endif // BUILDFLAG(USE_STARBOARD_MEDIA)

private:
// Demuxer callback handler to process an initialization segment received
// during an append() call.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3181,6 +3181,12 @@
{
name: "SolidColorLayers",
},
// Cobalt-specific feature that lets the web app query the latest
// presentation timestamp of buffers written to the Renderer.
{
name: "SourceBufferWriteHead",
base_feature: "none",
},
// An origin trial feature name is required for this, even though it's
// actually enabled by the more specific trial. Having these as separate
// features will allow Blink to distinguish for which thing the trial
Expand Down
Loading