Commit 0b4e5b62 authored by Matt Wolenetz's avatar Matt Wolenetz Committed by Commit Bot

MSE-in-Workers: Remove direct usage of media element from MSE

Replaces remaining direct usage of the attached HTMLMediaElement from
MediaSource and SourceBuffer, relying instead on the attachment to
moderate that communication.

Specifically, this change:

* Adds attachment helpers to enable SourceBuffers to create their audio
  and video tracklist members, including a same-thread attachment
  implementation. Cross-thread attachment implementation of this is
  deferred until TrackListBase and TrackBase can be owned off the main
  thread (in a worker thread), and until they can function without
  themselves directly accessing an HTMLMediaElement.

* Removes superfluous usage in SourceBuffer of `source_->MediaElement()`
  in DCHECKs; other DCHECKs already suffice.

* Removes MediaSource::MediaElement() and `attached_element_`. Removes
  their superfluous implementation and usage from MediaSource.

* Fixes outdated assumptions in various DCHECKs that all attachments use
  a tracer. Only same-thread attachments use a tracer.

BUG=878133

Change-Id: I346b320804a0ffbf731788b7ea7c344588f660b3
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2439677
Commit-Queue: Matthew Wolenetz <wolenetz@chromium.org>
Reviewed-by: default avatarWill Cassella <cassew@google.com>
Cr-Commit-Position: refs/heads/master@{#814329}
parent d4220da0
...@@ -64,6 +64,22 @@ bool CrossThreadMediaSourceAttachment::GetElementError( ...@@ -64,6 +64,22 @@ bool CrossThreadMediaSourceAttachment::GetElementError(
return true; return true;
} }
AudioTrackList* CrossThreadMediaSourceAttachment::CreateAudioTrackList(
MediaSourceTracer* /* tracer */) {
// TODO(https://crbug.com/878133): Implement this once worker thread can
// create track lists.
NOTIMPLEMENTED();
return nullptr;
}
VideoTrackList* CrossThreadMediaSourceAttachment::CreateVideoTrackList(
MediaSourceTracer* /* tracer */) {
// TODO(https://crbug.com/878133): Implement this once worker thread can
// create track lists.
NOTIMPLEMENTED();
return nullptr;
}
void CrossThreadMediaSourceAttachment::AddAudioTrackToMediaElement( void CrossThreadMediaSourceAttachment::AddAudioTrackToMediaElement(
MediaSourceTracer* /* tracer */, MediaSourceTracer* /* tracer */,
AudioTrack* /* track */) { AudioTrack* /* track */) {
......
...@@ -39,6 +39,8 @@ class CrossThreadMediaSourceAttachment final ...@@ -39,6 +39,8 @@ class CrossThreadMediaSourceAttachment final
void NotifyDurationChanged(MediaSourceTracer* tracer, double duration) final; void NotifyDurationChanged(MediaSourceTracer* tracer, double duration) final;
double GetRecentMediaTime(MediaSourceTracer* tracer) final; double GetRecentMediaTime(MediaSourceTracer* tracer) final;
bool GetElementError(MediaSourceTracer* tracer) final; bool GetElementError(MediaSourceTracer* tracer) final;
AudioTrackList* CreateAudioTrackList(MediaSourceTracer* tracer) final;
VideoTrackList* CreateVideoTrackList(MediaSourceTracer* tracer) final;
void AddAudioTrackToMediaElement(MediaSourceTracer* tracer, void AddAudioTrackToMediaElement(MediaSourceTracer* tracer,
AudioTrack* track) final; AudioTrack* track) final;
void AddVideoTrackToMediaElement(MediaSourceTracer* tracer, void AddVideoTrackToMediaElement(MediaSourceTracer* tracer,
......
...@@ -108,7 +108,6 @@ MediaSource::MediaSource(ExecutionContext* context) ...@@ -108,7 +108,6 @@ MediaSource::MediaSource(ExecutionContext* context)
async_event_queue_( async_event_queue_(
MakeGarbageCollected<EventQueue>(context, MakeGarbageCollected<EventQueue>(context,
TaskType::kMediaElementEvent)), TaskType::kMediaElementEvent)),
attached_element_(nullptr),
source_buffers_( source_buffers_(
MakeGarbageCollected<SourceBufferList>(GetExecutionContext(), MakeGarbageCollected<SourceBufferList>(GetExecutionContext(),
async_event_queue_.Get())), async_event_queue_.Get())),
...@@ -291,7 +290,6 @@ void MediaSource::OnReadyStateChange(const ReadyState old_state, ...@@ -291,7 +290,6 @@ void MediaSource::OnReadyStateChange(const ReadyState old_state,
source_buffers_->item(i)->RemovedFromMediaSource(); source_buffers_->item(i)->RemovedFromMediaSource();
source_buffers_->Clear(); source_buffers_->Clear();
attached_element_.Clear();
media_source_attachment_.reset(); media_source_attachment_.reset();
attachment_tracer_ = nullptr; attachment_tracer_ = nullptr;
...@@ -387,7 +385,6 @@ ExecutionContext* MediaSource::GetExecutionContext() const { ...@@ -387,7 +385,6 @@ ExecutionContext* MediaSource::GetExecutionContext() const {
void MediaSource::Trace(Visitor* visitor) const { void MediaSource::Trace(Visitor* visitor) const {
visitor->Trace(async_event_queue_); visitor->Trace(async_event_queue_);
visitor->Trace(attachment_tracer_); visitor->Trace(attachment_tracer_);
visitor->Trace(attached_element_);
visitor->Trace(source_buffers_); visitor->Trace(source_buffers_);
visitor->Trace(active_source_buffers_); visitor->Trace(active_source_buffers_);
visitor->Trace(live_seekable_range_); visitor->Trace(live_seekable_range_);
...@@ -402,9 +399,8 @@ void MediaSource::CompleteAttachingToMediaElement( ...@@ -402,9 +399,8 @@ void MediaSource::CompleteAttachingToMediaElement(
TRACE_ID_LOCAL(this)); TRACE_ID_LOCAL(this));
DCHECK(web_media_source); DCHECK(web_media_source);
DCHECK(!web_media_source_); DCHECK(!web_media_source_);
DCHECK(attached_element_);
DCHECK(media_source_attachment_); DCHECK(media_source_attachment_);
DCHECK(attachment_tracer_); DCHECK_EQ(!attachment_tracer_, !IsMainThread());
web_media_source_ = std::move(web_media_source); web_media_source_ = std::move(web_media_source);
SetReadyState(ReadyState::kOpen); SetReadyState(ReadyState::kOpen);
...@@ -472,8 +468,9 @@ TimeRanges* MediaSource::Buffered() const { ...@@ -472,8 +468,9 @@ TimeRanges* MediaSource::Buffered() const {
} }
WebTimeRanges MediaSource::SeekableInternal() const { WebTimeRanges MediaSource::SeekableInternal() const {
DCHECK(attached_element_ && media_source_attachment_ && attachment_tracer_) DCHECK(media_source_attachment_)
<< "Seekable should only be used when attached to HTMLMediaElement"; << "Seekable should only be used when attached to HTMLMediaElement";
DCHECK_EQ(!attachment_tracer_, !IsMainThread());
// Implements MediaSource algorithm for HTMLMediaElement.seekable. // Implements MediaSource algorithm for HTMLMediaElement.seekable.
// http://w3c.github.io/media-source/#htmlmediaelement-extensions // http://w3c.github.io/media-source/#htmlmediaelement-extensions
...@@ -787,12 +784,6 @@ void MediaSource::SetSourceBufferActive(SourceBuffer* source_buffer, ...@@ -787,12 +784,6 @@ void MediaSource::SetSourceBufferActive(SourceBuffer* source_buffer,
active_source_buffers_->insert(insert_position, source_buffer); active_source_buffers_->insert(insert_position, source_buffer);
} }
// TODO(https://crbug.com/878133): Remove this getter and instead rely on
// Attachment() to communicate about the media element.
HTMLMediaElement* MediaSource::MediaElement() const {
return attached_element_.Get();
}
std::pair<scoped_refptr<MediaSourceAttachmentSupplement>, MediaSourceTracer*> std::pair<scoped_refptr<MediaSourceAttachmentSupplement>, MediaSourceTracer*>
MediaSource::AttachmentAndTracer() const { MediaSource::AttachmentAndTracer() const {
return std::make_pair(media_source_attachment_, attachment_tracer_); return std::make_pair(media_source_attachment_, attachment_tracer_);
...@@ -810,11 +801,11 @@ void MediaSource::EndOfStreamAlgorithm( ...@@ -810,11 +801,11 @@ void MediaSource::EndOfStreamAlgorithm(
web_media_source_->MarkEndOfStream(eos_status); web_media_source_->MarkEndOfStream(eos_status);
if (eos_status == WebMediaSource::kEndOfStreamStatusNoError) { if (eos_status == WebMediaSource::kEndOfStreamStatusNoError) {
// The implementation may not have immediately informed the // The implementation may not have immediately informed the attached element
// |attached_element_| (or the element known by the |attachment_tracer_| // (known by the |media_source_attachment_| and |attachment_tracer_|) of the
// for the current |media_source_attachment_|) of the potentially reduced // potentially reduced duration. Prevent app-visible duration race by
// duration. Prevent app-visible duration race by synchronously running the // synchronously running the duration change algorithm. The MSE spec
// duration change algorithm. The MSE spec supports this: // supports this:
// https://www.w3.org/TR/media-source/#end-of-stream-algorithm // https://www.w3.org/TR/media-source/#end-of-stream-algorithm
// 2.4.7.3 (If error is not set) // 2.4.7.3 (If error is not set)
// Run the duration change algorithm with new duration set to the largest // Run the duration change algorithm with new duration set to the largest
...@@ -844,20 +835,15 @@ void MediaSource::Close() { ...@@ -844,20 +835,15 @@ void MediaSource::Close() {
MediaSourceTracer* MediaSource::StartAttachingToMediaElement( MediaSourceTracer* MediaSource::StartAttachingToMediaElement(
scoped_refptr<MediaSourceAttachmentSupplement> attachment, scoped_refptr<MediaSourceAttachmentSupplement> attachment,
HTMLMediaElement* element) { HTMLMediaElement* element) {
if (attached_element_) { if (media_source_attachment_ || attachment_tracer_) {
DCHECK(media_source_attachment_);
DCHECK(attachment_tracer_);
return nullptr; return nullptr;
} }
DCHECK(!media_source_attachment_);
DCHECK(!attachment_tracer_);
DCHECK(IsClosed()); DCHECK(IsClosed());
TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("media", TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("media",
"MediaSource::StartAttachingToMediaElement", "MediaSource::StartAttachingToMediaElement",
TRACE_ID_LOCAL(this)); TRACE_ID_LOCAL(this));
attached_element_ = element;
media_source_attachment_ = attachment; media_source_attachment_ = attachment;
attachment_tracer_ = attachment_tracer_ =
MakeGarbageCollected<SameThreadMediaSourceTracer>(element, this); MakeGarbageCollected<SameThreadMediaSourceTracer>(element, this);
......
...@@ -107,7 +107,6 @@ class MediaSource final : public EventTargetWithInlineData, ...@@ -107,7 +107,6 @@ class MediaSource final : public EventTargetWithInlineData,
void OpenIfInEndedState(); void OpenIfInEndedState();
bool IsOpen() const; bool IsOpen() const;
void SetSourceBufferActive(SourceBuffer*, bool); void SetSourceBufferActive(SourceBuffer*, bool);
HTMLMediaElement* MediaElement() const;
std::pair<scoped_refptr<MediaSourceAttachmentSupplement>, MediaSourceTracer*> std::pair<scoped_refptr<MediaSourceAttachmentSupplement>, MediaSourceTracer*>
AttachmentAndTracer() const; AttachmentAndTracer() const;
void EndOfStreamAlgorithm(const WebMediaSource::EndOfStreamStatus); void EndOfStreamAlgorithm(const WebMediaSource::EndOfStreamStatus);
...@@ -148,11 +147,8 @@ class MediaSource final : public EventTargetWithInlineData, ...@@ -148,11 +147,8 @@ class MediaSource final : public EventTargetWithInlineData,
// cross-thread, for instance) must be the same semantic as the actual derived // cross-thread, for instance) must be the same semantic as the actual derived
// type of the tracer. Further, if there is no attachment, then there must be // type of the tracer. Further, if there is no attachment, then there must be
// no tracer that's tracking an active attachment. // no tracer that's tracking an active attachment.
// TODO(https://crbug.com/878133): Remove |attached_element_| once it is fully
// replaced by usage of |media_source_attachment_| and |attachment_tracer_|.
scoped_refptr<MediaSourceAttachmentSupplement> media_source_attachment_; scoped_refptr<MediaSourceAttachmentSupplement> media_source_attachment_;
Member<MediaSourceTracer> attachment_tracer_; Member<MediaSourceTracer> attachment_tracer_;
Member<HTMLMediaElement> attached_element_;
Member<SourceBufferList> source_buffers_; Member<SourceBufferList> source_buffers_;
Member<SourceBufferList> active_source_buffers_; Member<SourceBufferList> active_source_buffers_;
......
...@@ -15,7 +15,9 @@ ...@@ -15,7 +15,9 @@
namespace blink { namespace blink {
class AudioTrackList;
class MediaSource; class MediaSource;
class VideoTrackList;
// Modules-specific common extension of the core MediaSourceAttachment // Modules-specific common extension of the core MediaSourceAttachment
// interface. Includes extra interface methods used by concrete attachments to // interface. Includes extra interface methods used by concrete attachments to
...@@ -47,6 +49,13 @@ class MediaSourceAttachmentSupplement : public MediaSourceAttachment { ...@@ -47,6 +49,13 @@ class MediaSourceAttachmentSupplement : public MediaSourceAttachment {
// attachment (in a cross-thread implementation). // attachment (in a cross-thread implementation).
virtual bool GetElementError(MediaSourceTracer* tracer) = 0; virtual bool GetElementError(MediaSourceTracer* tracer) = 0;
// Construct track lists for use by a SourceBuffer.
// TODO(https://crbug.com/878133): Update these to support worker-owned
// SourceBuffer lists when completing AudioVideoTracks feature support with
// MSE-in-Workers.
virtual AudioTrackList* CreateAudioTrackList(MediaSourceTracer* tracer) = 0;
virtual VideoTrackList* CreateVideoTrackList(MediaSourceTracer* tracer) = 0;
// Add/Remove tracks to/from the media Element's audioTracks() or // Add/Remove tracks to/from the media Element's audioTracks() or
// videoTracks() list. Note that this is synchronous in // videoTracks() list. Note that this is synchronous in
// SameThreadMediaSourceAttachment, but the CrossThreadMediaSourceAttachment // SameThreadMediaSourceAttachment, but the CrossThreadMediaSourceAttachment
......
...@@ -95,6 +95,26 @@ bool SameThreadMediaSourceAttachment::GetElementError( ...@@ -95,6 +95,26 @@ bool SameThreadMediaSourceAttachment::GetElementError(
return current_element_error_state; return current_element_error_state;
} }
AudioTrackList* SameThreadMediaSourceAttachment::CreateAudioTrackList(
MediaSourceTracer* tracer) {
DVLOG(1) << __func__ << " this=" << this;
VerifyCalledWhileContextsAliveForDebugging();
HTMLMediaElement* element = GetMediaElement(tracer);
return MakeGarbageCollected<AudioTrackList>(*element);
}
VideoTrackList* SameThreadMediaSourceAttachment::CreateVideoTrackList(
MediaSourceTracer* tracer) {
DVLOG(1) << __func__ << " this=" << this;
VerifyCalledWhileContextsAliveForDebugging();
HTMLMediaElement* element = GetMediaElement(tracer);
return MakeGarbageCollected<VideoTrackList>(*element);
}
void SameThreadMediaSourceAttachment::AddAudioTrackToMediaElement( void SameThreadMediaSourceAttachment::AddAudioTrackToMediaElement(
MediaSourceTracer* tracer, MediaSourceTracer* tracer,
AudioTrack* track) { AudioTrack* track) {
......
...@@ -35,6 +35,8 @@ class SameThreadMediaSourceAttachment final ...@@ -35,6 +35,8 @@ class SameThreadMediaSourceAttachment final
void NotifyDurationChanged(MediaSourceTracer* tracer, double duration) final; void NotifyDurationChanged(MediaSourceTracer* tracer, double duration) final;
double GetRecentMediaTime(MediaSourceTracer* tracer) final; double GetRecentMediaTime(MediaSourceTracer* tracer) final;
bool GetElementError(MediaSourceTracer* tracer) final; bool GetElementError(MediaSourceTracer* tracer) final;
AudioTrackList* CreateAudioTrackList(MediaSourceTracer* tracer) final;
VideoTrackList* CreateVideoTrackList(MediaSourceTracer* tracer) final;
void AddAudioTrackToMediaElement(MediaSourceTracer* tracer, void AddAudioTrackToMediaElement(MediaSourceTracer* tracer,
AudioTrack* track) final; AudioTrack* track) final;
void AddVideoTrackToMediaElement(MediaSourceTracer* tracer, void AddVideoTrackToMediaElement(MediaSourceTracer* tracer,
......
...@@ -127,14 +127,23 @@ SourceBuffer::SourceBuffer(std::unique_ptr<WebSourceBuffer> web_source_buffer, ...@@ -127,14 +127,23 @@ SourceBuffer::SourceBuffer(std::unique_ptr<WebSourceBuffer> web_source_buffer,
DCHECK(web_source_buffer_); DCHECK(web_source_buffer_);
DCHECK(source_); DCHECK(source_);
DCHECK(source_->MediaElement());
scoped_refptr<MediaSourceAttachmentSupplement> attachment;
MediaSourceTracer* tracer;
std::tie(attachment, tracer) = source_->AttachmentAndTracer();
DCHECK(attachment);
if (GetExecutionContext()->IsWindow()) { if (GetExecutionContext()->IsWindow()) {
DCHECK(IsMainThread()); DCHECK(IsMainThread());
DCHECK(tracer); // Same-thread attachments must use a tracer.
audio_tracks_ =
MakeGarbageCollected<AudioTrackList>(*source_->MediaElement()); // Have the attachment construct our audio and video tracklist members for
video_tracks_ = // us, since it knows how to do this with knowledge of the attached media
MakeGarbageCollected<VideoTrackList>(*source_->MediaElement()); // element.
audio_tracks_ = attachment->CreateAudioTrackList(tracer);
DCHECK(audio_tracks_);
video_tracks_ = attachment->CreateVideoTrackList(tracer);
DCHECK(video_tracks_);
} else { } else {
DCHECK(RuntimeEnabledFeatures::MediaSourceInWorkersEnabled() && DCHECK(RuntimeEnabledFeatures::MediaSourceInWorkersEnabled() &&
GetExecutionContext()->IsDedicatedWorkerGlobalScope()); GetExecutionContext()->IsDedicatedWorkerGlobalScope());
...@@ -1001,7 +1010,6 @@ bool SourceBuffer::InitializationSegmentReceived( ...@@ -1001,7 +1010,6 @@ bool SourceBuffer::InitializationSegmentReceived(
const WebVector<MediaTrackInfo>& new_tracks) { const WebVector<MediaTrackInfo>& new_tracks) {
DVLOG(3) << __func__ << " this=" << this << " tracks=" << new_tracks.size(); DVLOG(3) << __func__ << " this=" << this << " tracks=" << new_tracks.size();
DCHECK(source_); DCHECK(source_);
DCHECK(source_->MediaElement());
scoped_refptr<MediaSourceAttachmentSupplement> attachment; scoped_refptr<MediaSourceAttachmentSupplement> attachment;
MediaSourceTracer* tracer; MediaSourceTracer* tracer;
...@@ -1435,7 +1443,6 @@ bool SourceBuffer::PrepareAppend(double media_time, ...@@ -1435,7 +1443,6 @@ bool SourceBuffer::PrepareAppend(double media_time,
bool SourceBuffer::EvictCodedFrames(double media_time, size_t new_data_size) { bool SourceBuffer::EvictCodedFrames(double media_time, size_t new_data_size) {
DCHECK(source_); DCHECK(source_);
DCHECK(source_->MediaElement());
// Nothing to do if this SourceBuffer does not yet have frames to evict. // Nothing to do if this SourceBuffer does not yet have frames to evict.
if (!first_initialization_segment_received_) if (!first_initialization_segment_received_)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment