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
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());
Copy link
Contributor

Choose a reason for hiding this comment

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

Did we consider extending media/filters/chunk_demuxer_unittest.cc for the new behaviour?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

There's an existing bug to address this b/380001431, it's unblocked now so I'll be able to add tests for this and other ChunkDemuxer changes

}
}
#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 queued in the
// stream.
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 to be read
// from the DemuxerStream.
[[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 Renderer.
virtual double GetWriteHead(ExceptionState& exception_state) const = 0;
#endif // BUILDFLAG(USE_STARBOARD_MEDIA)
};

} // namespace blink
Expand Down
16 changes: 15 additions & 1 deletion 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 @@ -1204,7 +1208,8 @@ static_idl_files_in_modules = get_path_info(

if (is_cobalt) {
static_idl_files_in_modules += get_path_info(
[ "//third_party/blink/renderer/modules/cobalt/crash_annotator/crash_annotator.idl",
[
"//third_party/blink/renderer/modules/cobalt/crash_annotator/crash_annotator.idl",
"//third_party/blink/renderer/modules/cobalt/crash_annotator/navigator_crash_annotator.idl",
],
"abspath")
Expand Down Expand Up @@ -1287,6 +1292,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 Renderer.
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
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)" ]
}
}
14 changes: 14 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,20 @@ VideoTrackList& SourceBuffer::videoTracks() {
return *video_tracks_;
}

#if BUILDFLAG(USE_STARBOARD_MEDIA)
double SourceBuffer::GetWriteHead(ExceptionState& exception_state) const {
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_->GetWriteHead(exception_state);
}
#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,12 @@ class SourceBuffer final : public EventTargetWithInlineData,
AudioTrackList& audioTracks();
VideoTrackList& videoTracks();

#if BUILDFLAG(USE_STARBOARD_MEDIA)
// Cobalt-specific method that returns the highest presentation
// timestamp written to the Renderer.
double GetWriteHead(ExceptionState& exception_state) const;
#endif // BUILDFLAG(USE_STARBOARD_MEDIA)

// "_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,31 @@
// 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"

#if !BUILDFLAG(USE_STARBOARD_MEDIA)
#error "This file only works with Starboard media"
#endif // !BUILDFLAG(USE_STARBOARD_MEDIA)

namespace blink {

// static
double SourceBufferWriteHead::writeHead(SourceBuffer& source_buffer,
ExceptionState& exception_state) {
return source_buffer.GetWriteHead(exception_state);
}
} // namespace blink
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
// 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 "build/build_config.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"

#if !BUILDFLAG(USE_STARBOARD_MEDIA)
#error "This file only works with Starboard media"
#endif // !BUILDFLAG(USE_STARBOARD_MEDIA)

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 Renderer;
// 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 {
Copy link
Contributor

Choose a reason for hiding this comment

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

Since this is an interface extension, could we put it in a blink/renderer/modules/cobalt or some such? That way it'd make it easier down the line to identify all Cobalt Web Platform extensions.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure, is that the practice we'll have going forward? I approached it how it would look if it were merged to Chrome.

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm less sure about the right way to approach this change, because my understanding is that it's more likely to be upstreamed (and I think relatively soon?), so we actually wouldn't want it to be separate from the other changes. But maybe we want to always separate it out until it's actually accepted upstream as it may also change once it goes in upstream. I'll think about it and add it to go/cobalt-web-api-design

Copy link
Contributor

Choose a reason for hiding this comment

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

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I can move this as soon as we have a defined location for these interface changes to go

[RaisesException] readonly attribute double writeHead;
};
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,14 @@ void WebSourceBufferImpl::RemovedFromMediaSource() {
client_ = nullptr;
}

#if BUILDFLAG(USE_STARBOARD_MEDIA)
double WebSourceBufferImpl::GetWriteHead(
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 Renderer.
double GetWriteHead(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
Loading
Loading