blob: 851c43abfa8a30382e6d8b28b461cae3bf2c6b5f [file] [log] [blame]
// 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_CORE_HTML_MEDIA_MEDIA_SOURCE_ATTACHMENT_H_
#define THIRD_PARTY_BLINK_RENDERER_CORE_HTML_MEDIA_MEDIA_SOURCE_ATTACHMENT_H_
#include <memory>
#include "third_party/blink/public/platform/web_time_range.h"
#include "third_party/blink/renderer/core/core_export.h"
#include "third_party/blink/renderer/core/fileapi/url_registry.h"
#include "third_party/blink/renderer/core/html/media/media_source_tracer.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"
#include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h"
namespace blink {
class HTMLMediaElement;
class MediaSourceRegistry;
class TrackBase;
class WebMediaSource;
// Interface for concrete non-oilpan types to coordinate potentially
// cross-context registration, deregistration, lookup of a MediaSource via the
// MediaSourceRegistry, and for proxying operations on an attached MediaSource.
// Upon successful lookup, enables the extension of an HTMLMediaElement by the
// MSE API, aka attachment. This type is not managed by oilpan due to the
// potentially varying context lifetimes. Concrete implementations of this
// handle same-thread (main thread) attachments distinctly from cross-context
// (MSE-in-Worker, HTMLMediaElement in main thread) attachments due to the
// increased complexity for handling the latter. Concrete implementations of
// this interface are reference counted to ensure they are available potentially
// cross-thread and from the registry.
//
// TODO(https://crbug.com/878133): This is not yet implementing the multi-thread
// aspect.
class CORE_EXPORT MediaSourceAttachment
: public URLRegistrable,
public WTF::ThreadSafeRefCounted<MediaSourceAttachment> {
public:
// Intended to be set by the MediaSourceRegistry during its singleton
// initialization on the main thread. Caches the pointer in |registry_|.
static void SetRegistry(MediaSourceRegistry*);
// Services lookup calls, expected from HTMLMediaElement during its load
// algorithm. If |url| is not known by MediaSourceRegistry, returns nullptr.
// Otherwise, returns the MediaSourceAttachment associated with |url|.
static scoped_refptr<MediaSourceAttachment> LookupMediaSource(
const String& url);
MediaSourceAttachment();
~MediaSourceAttachment() override;
// This is called on the main thread when the URLRegistry unregisters the
// objectURL for this attachment. Concrete implementation overrides should use
// this signal to release their strong reference to the MediaSource such that
// GC might collect it if there is no active attachment represented by other
// strong references.
virtual void Unregister() = 0;
// URLRegistrable
URLRegistry& Registry() const override { return *registry_; }
// These two methods are called in sequence when an HTMLMediaElement is
// attempting to attach to the MediaSource object using this attachment
// instance. The WebMediaSource is not available to the element initially, so
// between the two calls, the attachment could be considered partially setup.
// If attachment start fails (for example, if the underlying MediaSource is
// already attached, or if this attachment has already been unregistered from
// the MediaSourceRegistry), StartAttachingToMediaElement() sets |*success|
// false and returns nullptr. |success| must not be nullptr.
// Otherwise, the underlying MediaSource must be in 'closed' state, and
// indicates success by setting |*success| true and optionally returning a
// tracer object useful in at least same-thread attachments for enabling
// automatic idle unreferenced same-thread attachment object garbage
// collection. Note that that tracer could be nullptr even if attachment start
// was successful, for instance in a cross-thread attachment where there is no
// tracer.
// CompleteAttachingToMediaElement() provides the attached MediaSource with
// the underlying WebMediaSource, enabling parsing of media provided by the
// application for playback, for example.
// Once attached, the MediaSource and the HTMLMediaElement use each other via
// this attachment to accomplish the extended API.
// The MediaSourceTracer argument to calls in this interface enables at least
// the same-thread attachment to dynamically retrieve the Oilpan-managed
// objects without itself being managed by oilpan. Alternatives like requiring
// the (non-GC'ed) attachment to remember the tracer as a Persistent would
// break the ability for automatic collection of idle unreferenced same-thread
// HTMLME+MSE object collections. The tracer argument must be the same as that
// returned by the most recent call to the attachment's
// StartAttachingToMediaElement. We cannot have the tracer as a Member, and
// using Persistent to hold it instead would break the ability for automatic
// collection of idle unreferenced same-thread attached HTMLMediaElement +
// MediaSource object groups.
virtual MediaSourceTracer* StartAttachingToMediaElement(HTMLMediaElement*,
bool* success) = 0;
virtual void CompleteAttachingToMediaElement(
MediaSourceTracer* tracer,
std::unique_ptr<WebMediaSource>) = 0;
virtual void Close(MediaSourceTracer* tracer) = 0;
// 'Internal' in these methods doesn't mean private, it means that they are
// internal to chromium and are not exposed to JavaScript.
virtual WebTimeRanges BufferedInternal(MediaSourceTracer* tracer) const = 0;
virtual WebTimeRanges SeekableInternal(MediaSourceTracer* tracer) const = 0;
virtual void OnTrackChanged(MediaSourceTracer* tracer, TrackBase*) = 0;
// Provide state updates to the MediaSource that are necessary for its
// operation. These are pushed rather than pulled to reduce complexity and
// latency, especially when the MediaSource is in a Worker context.
// OnElementTimeUpdate() gives the MediaSource a notion of the recent media
// element currentTime so that it can more effectively prevent evicting
// buffered media near to playback and/or seek target time in its heuristic.
// Alternatives such as pumping this via the media pipeline are insufficient,
// as the media pipeline may not be aware of overrides to the playback start
// position.
virtual void OnElementTimeUpdate(double time) = 0;
// Needed as a precondition in the Prepare Append algorithm, OnElementError()
// lets the MediaSource know if the attached media element has transitioned to
// having an error.
virtual void OnElementError() = 0;
// Needed in cross-thread attachments to prevent the attachment from UAF of
// the media element when the media element's context might be destroyed
// before a worker-context MSE's context has been destroyed. In such case,
// neither the media element, nor the underlying main-thread-owned MSE demuxer
// should be used further.
virtual void OnElementContextDestroyed() = 0;
private:
friend class WTF::ThreadSafeRefCounted<MediaSourceAttachment>;
static URLRegistry* registry_;
DISALLOW_COPY_AND_ASSIGN(MediaSourceAttachment);
};
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_CORE_HTML_MEDIA_MEDIA_SOURCE_ATTACHMENT_H_