MSE-in-Workers: Add modules-specific attachment interface
Adds a supplemental interface in modules to extend the core
MediaSourceAttachment, so common methods in specialized attachments can
be defined without requiring them known by core. This reduces complexity
of the core side of the attachment interface.
Specifically, adds MediaSourceAttachmentSupplement, with a new method
(implemented in concrete SameThreadMediaSourceAttachment) to notify the
attached element that the duration of the resource has changed. Later
specialization in a cross-thread version of the attachment will need to
perform this notification asynchronously.
Lifts the Unregister() method and the persistent MediaSource OilPan
reference member from the concrete implementation into this common
modules attachment supplement's implementation, since these are expected
to remain the same across all concrete attachment implementations.
Updates SameThreadMediaSourceAttachment to give the MediaSource a
thread-safe refcounted scoped_refptr for the attachment during
StartAttachingToMediaElement(). MediaSource, like HTMLMediaElement does
already, is updated to know both the attachment and the
MediaSourceTracer while the attachment is active.
Starts using NotifyDurationChanged from the MediaSource object via the
attachment instead of directly talking to the attached media element
from the MediaSource.
Further extensions of this attachment interface will come in later
changes for similar scenarios, eventually enabling the dropping of the
|attached_element_| member from the MediaSource class, with all
interactions on the element eventually done via the attachment.
BUG=878133
Change-Id: I86206f740b62f9ba6dc6a1b9fd16a44aff21f49a
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2387121
Reviewed-by: Will Cassella <cassew@google.com>
Commit-Queue: Matthew Wolenetz <wolenetz@chromium.org>
Cr-Commit-Position: refs/heads/master@{#804434}
diff --git a/third_party/blink/renderer/modules/mediasource/BUILD.gn b/third_party/blink/renderer/modules/mediasource/BUILD.gn
index a3046ff5..4c86168 100644
--- a/third_party/blink/renderer/modules/mediasource/BUILD.gn
+++ b/third_party/blink/renderer/modules/mediasource/BUILD.gn
@@ -10,6 +10,8 @@
"html_video_element_media_source.h",
"media_source.cc",
"media_source.h",
+ "media_source_attachment_supplement.cc",
+ "media_source_attachment_supplement.h",
"media_source_registry_impl.cc",
"media_source_registry_impl.h",
"media_source_tracer_impl.cc",
diff --git a/third_party/blink/renderer/modules/mediasource/media_source.cc b/third_party/blink/renderer/modules/mediasource/media_source.cc
index 5808e66..aef4fab9 100644
--- a/third_party/blink/renderer/modules/mediasource/media_source.cc
+++ b/third_party/blink/renderer/modules/mediasource/media_source.cc
@@ -293,6 +293,8 @@
source_buffers_->Clear();
attached_element_.Clear();
+ media_source_attachment_.reset();
+ attachment_tracer_ = nullptr;
ScheduleEvent(event_type_names::kSourceclose);
}
@@ -385,6 +387,7 @@
void MediaSource::Trace(Visitor* visitor) const {
visitor->Trace(async_event_queue_);
+ visitor->Trace(attachment_tracer_);
visitor->Trace(attached_element_);
visitor->Trace(source_buffers_);
visitor->Trace(active_source_buffers_);
@@ -401,6 +404,9 @@
DCHECK(web_media_source);
DCHECK(!web_media_source_);
DCHECK(attached_element_);
+ DCHECK(media_source_attachment_);
+ DCHECK(attachment_tracer_);
+
web_media_source_ = std::move(web_media_source);
SetReadyState(OpenKeyword());
}
@@ -467,7 +473,7 @@
}
WebTimeRanges MediaSource::SeekableInternal() const {
- DCHECK(attached_element_)
+ DCHECK(attached_element_ && media_source_attachment_ && attachment_tracer_)
<< "Seekable should only be used when attached to HTMLMediaElement";
// Implements MediaSource algorithm for HTMLMediaElement.seekable.
@@ -617,7 +623,6 @@
std::isnan(old_duration) ? 0 : old_duration);
// 4. Update duration to new duration.
- bool request_seek = attached_element_->currentTime() > new_duration;
web_media_source_->SetDuration(new_duration);
if (!RuntimeEnabledFeatures::MediaSourceNewAbortAndDurationEnabled() &&
@@ -640,7 +645,8 @@
// 6. Update the media controller duration to new duration and run the
// HTMLMediaElement duration change algorithm.
- attached_element_->DurationChanged(new_duration, request_seek);
+ media_source_attachment_->NotifyDurationChanged(attachment_tracer_,
+ new_duration);
}
void MediaSource::SetReadyState(const AtomicString& state) {
@@ -780,6 +786,9 @@
active_source_buffers_->insert(insert_position, source_buffer);
}
+// TODO(https://crbug.com/878133): Remove this getter and instead rely on
+// |media_source_attachment_| and |attachment_tracer_| to communicate about
+// the media element.
HTMLMediaElement* MediaSource::MediaElement() const {
return attached_element_.Get();
}
@@ -797,9 +806,10 @@
if (eos_status == WebMediaSource::kEndOfStreamStatusNoError) {
// The implementation may not have immediately informed the
- // |attached_element_| of the potentially reduced duration. Prevent
- // app-visible duration race by synchronously running the duration change
- // algorithm. The MSE spec supports this:
+ // |attached_element_| (or the element known by the |attachment_tracer_|
+ // for the current |media_source_attachment_|) of the potentially reduced
+ // duration. Prevent app-visible duration race by synchronously running the
+ // duration change algorithm. The MSE spec supports this:
// https://www.w3.org/TR/media-source/#end-of-stream-algorithm
// 2.4.7.3 (If error is not set)
// Run the duration change algorithm with new duration set to the largest
@@ -813,8 +823,8 @@
// to just mark end of stream, and move the duration reduction logic to here
// so we can just run DurationChangeAlgorithm(...) here.
double new_duration = duration();
- bool request_seek = attached_element_->currentTime() > new_duration;
- attached_element_->DurationChanged(new_duration, request_seek);
+ media_source_attachment_->NotifyDurationChanged(attachment_tracer_,
+ new_duration);
}
}
@@ -827,17 +837,26 @@
}
MediaSourceTracer* MediaSource::StartAttachingToMediaElement(
+ scoped_refptr<MediaSourceAttachmentSupplement> attachment,
HTMLMediaElement* element) {
- if (attached_element_)
+ if (attached_element_) {
+ DCHECK(media_source_attachment_);
+ DCHECK(attachment_tracer_);
return nullptr;
+ }
+ DCHECK(!media_source_attachment_);
+ DCHECK(!attachment_tracer_);
DCHECK(IsClosed());
TRACE_EVENT_NESTABLE_ASYNC_BEGIN0("media",
"MediaSource::StartAttachingToMediaElement",
TRACE_ID_LOCAL(this));
attached_element_ = element;
- return MakeGarbageCollected<MediaSourceTracerImpl>(element, this);
+ media_source_attachment_ = attachment;
+ attachment_tracer_ =
+ MakeGarbageCollected<MediaSourceTracerImpl>(element, this);
+ return attachment_tracer_;
}
void MediaSource::OpenIfInEndedState() {
diff --git a/third_party/blink/renderer/modules/mediasource/media_source.h b/third_party/blink/renderer/modules/mediasource/media_source.h
index 6754faa..2f45e6a 100644
--- a/third_party/blink/renderer/modules/mediasource/media_source.h
+++ b/third_party/blink/renderer/modules/mediasource/media_source.h
@@ -7,12 +7,14 @@
#include <memory>
+#include "base/memory/scoped_refptr.h"
#include "third_party/blink/public/platform/web_media_source.h"
#include "third_party/blink/renderer/bindings/core/v8/active_script_wrappable.h"
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
#include "third_party/blink/renderer/core/html/media/media_source_tracer.h"
#include "third_party/blink/renderer/core/html/time_ranges.h"
#include "third_party/blink/renderer/modules/event_target_modules.h"
+#include "third_party/blink/renderer/modules/mediasource/media_source_attachment_supplement.h"
#include "third_party/blink/renderer/modules/mediasource/source_buffer.h"
#include "third_party/blink/renderer/modules/mediasource/source_buffer_list.h"
#include "third_party/blink/renderer/platform/bindings/exception_code.h"
@@ -24,6 +26,7 @@
class EventQueue;
class ExceptionState;
class HTMLMediaElement;
+class MediaSourceAttachmentSupplement;
class TrackBase;
class WebSourceBuffer;
@@ -32,9 +35,9 @@
// HTMLMediaElement's instance to use the MSE API (also known as "attaching MSE
// to a media element") by using a Media Source object URL as the media
// element's src attribute or the src attribute of a <source> inside the media
-// element. A MediaSourceAttachment encapsulates the linkage of that object URL
-// to a MediaSource instance, and allows communication between the media element
-// and the MSE API.
+// element. A MediaSourceAttachmentSupplement encapsulates the linkage of that
+// object URL to a MediaSource instance, and allows communication between the
+// media element and the MSE API.
class MediaSource final : public EventTargetWithInlineData,
public ActiveScriptWrappable<MediaSource>,
public ExecutionContextLifecycleObserver {
@@ -76,9 +79,11 @@
static bool isTypeSupported(ExecutionContext* context, const String& type);
- // Methods needed by a MediaSourceAttachment to service operations proxied
- // from an HTMLMediaElement.
- MediaSourceTracer* StartAttachingToMediaElement(HTMLMediaElement*);
+ // Methods needed by a MediaSourceAttachmentSupplement to service operations
+ // proxied from an HTMLMediaElement.
+ MediaSourceTracer* StartAttachingToMediaElement(
+ scoped_refptr<MediaSourceAttachmentSupplement> attachment,
+ HTMLMediaElement* element);
void CompleteAttachingToMediaElement(std::unique_ptr<WebMediaSource>);
void Close();
bool IsClosed() const;
@@ -129,15 +134,21 @@
AtomicString ready_state_;
Member<EventQueue> async_event_queue_;
- // Keep the attached element (via tracer_), |source_buffers_|,
+ // Keep the attached element (via attachment_tracer_), |source_buffers_|,
// |active_source_buffers_|, and their wrappers from being collected if we are
- // alive or traceable from a GC root. Activity by this MediaSource or on
+ // alive or traceable from a GC root. Activity by this MediaSource or on
// references to objects returned by exercising this MediaSource (such as an
// app manipulating a SourceBuffer retrieved via activeSourceBuffers()) may
// cause events to be dispatched by these other objects.
- // TODO(https://crbug.com/878133): Replace |attached_element_| with
- // scoped_refptr to the attachment and also a Member of the MediaSourceTracer
- // for an active attachment.
+ // |media_source_attachment_| and |attachment_tracer_| must be carefully set
+ // and reset: the actual derived type of the attachment (same-thread vs
+ // 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
+ // 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_;
+ Member<MediaSourceTracer> attachment_tracer_;
Member<HTMLMediaElement> attached_element_;
Member<SourceBufferList> source_buffers_;
Member<SourceBufferList> active_source_buffers_;
diff --git a/third_party/blink/renderer/modules/mediasource/media_source_attachment_supplement.cc b/third_party/blink/renderer/modules/mediasource/media_source_attachment_supplement.cc
new file mode 100644
index 0000000..f89a84e
--- /dev/null
+++ b/third_party/blink/renderer/modules/mediasource/media_source_attachment_supplement.cc
@@ -0,0 +1,32 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "third_party/blink/renderer/modules/mediasource/media_source_attachment_supplement.h"
+
+#include "third_party/blink/renderer/modules/mediasource/media_source.h"
+#include "third_party/blink/renderer/modules/mediasource/media_source_tracer_impl.h"
+
+namespace blink {
+
+MediaSourceAttachmentSupplement::MediaSourceAttachmentSupplement(
+ MediaSource* media_source)
+ : registered_media_source_(media_source) {}
+
+MediaSourceAttachmentSupplement::~MediaSourceAttachmentSupplement() = default;
+
+void MediaSourceAttachmentSupplement::Unregister() {
+ DVLOG(1) << __func__ << " this=" << this;
+
+ // The only expected caller is a MediaSourceRegistryImpl on the main thread.
+ DCHECK(IsMainThread());
+
+ // Release our strong reference to the MediaSource. Note that revokeObjectURL
+ // of the url associated with this attachment could commonly follow this path
+ // while the MediaSource (and any attachment to an HTMLMediaElement) may still
+ // be alive/active.
+ DCHECK(registered_media_source_);
+ registered_media_source_ = nullptr;
+}
+
+} // namespace blink
diff --git a/third_party/blink/renderer/modules/mediasource/media_source_attachment_supplement.h b/third_party/blink/renderer/modules/mediasource/media_source_attachment_supplement.h
new file mode 100644
index 0000000..818cca5
--- /dev/null
+++ b/third_party/blink/renderer/modules/mediasource/media_source_attachment_supplement.h
@@ -0,0 +1,52 @@
+// Copyright 2020 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASOURCE_MEDIA_SOURCE_ATTACHMENT_SUPPLEMENT_H_
+#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASOURCE_MEDIA_SOURCE_ATTACHMENT_SUPPLEMENT_H_
+
+#include <memory>
+#include "third_party/blink/public/platform/web_time_range.h"
+#include "third_party/blink/renderer/core/html/media/media_source_attachment.h"
+#include "third_party/blink/renderer/core/html/media/media_source_tracer.h"
+#include "third_party/blink/renderer/modules/mediasource/media_source.h"
+#include "third_party/blink/renderer/platform/heap/handle.h"
+#include "third_party/blink/renderer/platform/heap/persistent.h"
+#include "third_party/blink/renderer/platform/wtf/forward.h"
+
+namespace blink {
+
+class MediaSource;
+
+// Modules-specific common extension of the core MediaSourceAttachment
+// interface. Includes extra interface methods used by concrete attachments to
+// communicate with the media element, as well as method implementations and
+// members common to all concrete attachments.
+class MediaSourceAttachmentSupplement : public MediaSourceAttachment {
+ public:
+ // Communicates a change in the media resource duration to the attached media
+ // element. In a same-thread attachment, communicates this information
+ // synchronously. In a cross-thread attachment, communicates asynchronously to
+ // the media element. Same-thread synchronous notification here is primarily
+ // to preserve compliance of API behavior when not using MSE-in-Worker
+ // (setting MediaSource.duration should be synchronously in agreement with
+ // subsequent retrieval of MediaElement.duration, all on the main thread).
+ virtual void NotifyDurationChanged(MediaSourceTracer* tracer,
+ double duration) = 0;
+ // MediaSourceAttachment
+ void Unregister() final;
+
+ protected:
+ explicit MediaSourceAttachmentSupplement(MediaSource* media_source);
+ ~MediaSourceAttachmentSupplement() override;
+
+ // Cache of the registered MediaSource. Retains strong reference from
+ // construction of this object until Unregister() is called.
+ Persistent<MediaSource> registered_media_source_;
+
+ DISALLOW_COPY_AND_ASSIGN(MediaSourceAttachmentSupplement);
+};
+
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASOURCE_MEDIA_SOURCE_ATTACHMENT_SUPPLEMENT_H_
diff --git a/third_party/blink/renderer/modules/mediasource/same_thread_media_source_attachment.cc b/third_party/blink/renderer/modules/mediasource/same_thread_media_source_attachment.cc
index 8280c96..8f9c77a 100644
--- a/third_party/blink/renderer/modules/mediasource/same_thread_media_source_attachment.cc
+++ b/third_party/blink/renderer/modules/mediasource/same_thread_media_source_attachment.cc
@@ -4,6 +4,8 @@
#include "third_party/blink/renderer/modules/mediasource/same_thread_media_source_attachment.h"
+#include "base/memory/scoped_refptr.h"
+#include "third_party/blink/renderer/core/html/media/html_media_element.h"
#include "third_party/blink/renderer/modules/mediasource/media_source.h"
#include "third_party/blink/renderer/modules/mediasource/media_source_tracer_impl.h"
@@ -20,13 +22,17 @@
return GetTracerImpl(tracer)->GetMediaSource();
}
+blink::HTMLMediaElement* GetMediaElement(blink::MediaSourceTracer* tracer) {
+ return GetTracerImpl(tracer)->GetMediaElement();
+}
+
} // namespace
namespace blink {
SameThreadMediaSourceAttachment::SameThreadMediaSourceAttachment(
MediaSource* media_source)
- : registered_media_source_(media_source) {
+ : MediaSourceAttachmentSupplement(media_source) {
// This kind of attachment only operates on the main thread.
DCHECK(IsMainThread());
@@ -37,20 +43,17 @@
DCHECK(HasOneRef());
}
-SameThreadMediaSourceAttachment::~SameThreadMediaSourceAttachment() = default;
-
-void SameThreadMediaSourceAttachment::Unregister() {
+SameThreadMediaSourceAttachment::~SameThreadMediaSourceAttachment() {
DVLOG(1) << __func__ << " this=" << this;
+}
- // The only expected caller is a MediaSourceRegistryImpl on the main thread.
- DCHECK(IsMainThread());
+void SameThreadMediaSourceAttachment::NotifyDurationChanged(
+ MediaSourceTracer* tracer,
+ double duration) {
+ HTMLMediaElement* element = GetMediaElement(tracer);
- // Release our strong reference to the MediaSource. Note that revokeObjectURL
- // of the url associated with this attachment could commonly follow this path
- // while the MediaSource (and any attachment to an HTMLMediaElement) may still
- // be alive/active.
- DCHECK(registered_media_source_);
- registered_media_source_ = nullptr;
+ bool request_seek = element->currentTime() > duration;
+ element->DurationChanged(duration, request_seek);
}
MediaSourceTracer*
@@ -59,7 +62,8 @@
if (!registered_media_source_)
return nullptr;
- return registered_media_source_->StartAttachingToMediaElement(element);
+ return registered_media_source_->StartAttachingToMediaElement(
+ WrapRefCounted(this), element);
}
void SameThreadMediaSourceAttachment::CompleteAttachingToMediaElement(
diff --git a/third_party/blink/renderer/modules/mediasource/same_thread_media_source_attachment.h b/third_party/blink/renderer/modules/mediasource/same_thread_media_source_attachment.h
index 79be4fa..48c90230 100644
--- a/third_party/blink/renderer/modules/mediasource/same_thread_media_source_attachment.h
+++ b/third_party/blink/renderer/modules/mediasource/same_thread_media_source_attachment.h
@@ -5,31 +5,25 @@
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASOURCE_SAME_THREAD_MEDIA_SOURCE_ATTACHMENT_H_
#define THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASOURCE_SAME_THREAD_MEDIA_SOURCE_ATTACHMENT_H_
-#include <memory>
-#include "third_party/blink/public/platform/web_time_range.h"
-#include "third_party/blink/renderer/core/html/media/media_source_attachment.h"
-#include "third_party/blink/renderer/core/html/media/media_source_tracer.h"
#include "third_party/blink/renderer/modules/mediasource/media_source.h"
-#include "third_party/blink/renderer/platform/heap/handle.h"
-#include "third_party/blink/renderer/platform/wtf/forward.h"
+#include "third_party/blink/renderer/modules/mediasource/media_source_attachment_supplement.h"
namespace blink {
-class HTMLMediaElement;
-class TimeRanges;
-class TrackBase;
-class WebMediaSource;
-
// Concrete attachment that supports operation only on the main thread.
-class SameThreadMediaSourceAttachment final : public MediaSourceAttachment {
+class SameThreadMediaSourceAttachment final
+ : public MediaSourceAttachmentSupplement {
public:
// The only intended caller of this constructor is
// URLMediaSource::createObjectUrl. The raw pointer is then adopted into a
// scoped_refptr in SameThreadMediaSourceRegistry::RegisterURL.
explicit SameThreadMediaSourceAttachment(MediaSource* media_source);
- void Unregister() override;
+ // MediaSourceAttachmentSupplement
+ void NotifyDurationChanged(MediaSourceTracer* tracer,
+ double duration) override;
+ // MediaSourceAttachment
MediaSourceTracer* StartAttachingToMediaElement(HTMLMediaElement*) override;
void CompleteAttachingToMediaElement(
MediaSourceTracer* tracer,
@@ -46,10 +40,6 @@
private:
~SameThreadMediaSourceAttachment() override;
- // Cache of the registered MediaSource. Retains strong reference until
- // Unregister() is called.
- Persistent<MediaSource> registered_media_source_;
-
DISALLOW_COPY_AND_ASSIGN(SameThreadMediaSourceAttachment);
};