[EMSS] `kEnableUpstreamArchitecture` support for WASM Player in low latency modes... 41/313541/13
authorPiotr Bałut <p.balut@samsung.com>
Tue, 13 Feb 2024 13:53:32 +0000 (14:53 +0100)
committerBot Blink <blinkbot@samsung.com>
Fri, 28 Jun 2024 13:47:47 +0000 (13:47 +0000)
This patch enables switches::kEnableUpstreamArchitecture support for
WASM Player in Low and Ultra Latency modes for video tracks (audio
support will be added in a future patch).

This change reduces dependency on platform libraries and also
eliminates the need to use any browser process implementation. The
maintenance cost is reduced and reliability of WASM Player is
increased when using upstream architecture, because reliable upstream
media pipeline can be now used.

Signed-off-by: Piotr Bałut <p.balut@samsung.com>
Bug: https://jira-eu.sec.samsung.net/browse/VDWASM-1320
Change-Id: I4addf25aec227552aa6c5426c718ab8c1b54bac6

65 files changed:
third_party/blink/public/platform/web_media_player_client.h
third_party/blink/public/web/modules/mediastream/webmediaplayer_ms.h
third_party/blink/renderer/core/html/media/html_media_element.cc
third_party/blink/renderer/core/html/media/html_media_element.h
third_party/blink/renderer/core/html/media/media_source_attachment.h
third_party/blink/renderer/modules/mediasource/media_source_attachment_supplement.cc
third_party/blink/renderer/modules/mediasource/media_source_attachment_supplement.h
third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc
third_party/blink/renderer/platform/media/web_media_player_impl.cc
tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/any_thread/BUILD.gn
tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/any_thread/common_tools.cc
tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/any_thread/common_tools.h
tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/any_thread/demuxer.h
tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/any_thread/demuxer_dispatcher.cc
tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/any_thread/demuxer_dispatcher.h
tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/any_thread/demuxer_impl.cc
tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/any_thread/demuxer_impl.h
tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/any_thread/elementary_media_stream_demuxer.cc
tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/any_thread/ms_decoding_stream.cc [new file with mode: 0644]
tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/any_thread/ms_decoding_stream.h [new file with mode: 0644]
tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/any_thread/packet.cc
tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/any_thread/packet.h
tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/any_thread/source_dispatcher.h
tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/any_thread/source_impl.cc
tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/control_thread/BUILD.gn
tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/control_thread/ms_decoding_stream.cc [new file with mode: 0644]
tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/control_thread/ms_decoding_stream.h [new file with mode: 0644]
tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/control_thread/source_impl.cc
tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/control_thread/source_impl.h
tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/worker_thread/BUILD.gn
tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/worker_thread/append_host.cc [new file with mode: 0644]
tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/worker_thread/append_host.h
tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/worker_thread/data_stream_demuxer_impl.cc
tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/worker_thread/data_stream_demuxer_impl.h
tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/worker_thread/demuxer.h
tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/worker_thread/media_stream_demuxer_impl.cc
tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/worker_thread/media_stream_demuxer_impl.h
tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/worker_thread/ms_decoding_stream.cc [new file with mode: 0644]
tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/worker_thread/ms_decoding_stream.h [new file with mode: 0644]
tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/worker_thread/source_dispatcher_client.h
tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/worker_thread/source_impl.cc
tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/worker_thread/source_impl.h
tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/worker_thread/track_dispatcher_client.h
tizen_src/chromium_impl/content/test/elementary_media_stream_source/worker_thread/mock_demuxer.h
tizen_src/chromium_impl/content/test/elementary_media_stream_source/worker_thread/mock_source_dispatcher_client.h
tizen_src/chromium_impl/content/test/elementary_media_stream_source/worker_thread/worker_thread_demuxer_impl_unittest.cc
tizen_src/chromium_impl/third_party/blink/renderer/modules/elementary_media_stream_source/BUILD.gn
tizen_src/chromium_impl/third_party/blink/renderer/modules/elementary_media_stream_source/elementary_media_stream_source.cc
tizen_src/chromium_impl/third_party/blink/renderer/modules/elementary_media_stream_source/elementary_media_stream_source.h
tizen_src/chromium_impl/third_party/blink/renderer/modules/elementary_media_stream_source/elementary_media_stream_source_version.h
tizen_src/chromium_impl/third_party/blink/renderer/modules/elementary_media_stream_source/elementary_media_track.cc
tizen_src/chromium_impl/third_party/blink/renderer/modules/elementary_media_stream_source/elementary_media_track.h
tizen_src/chromium_impl/third_party/blink/renderer/modules/elementary_media_stream_source/ms_audio_track_source.cc [new file with mode: 0644]
tizen_src/chromium_impl/third_party/blink/renderer/modules/elementary_media_stream_source/ms_audio_track_source.h [new file with mode: 0644]
tizen_src/chromium_impl/third_party/blink/renderer/modules/elementary_media_stream_source/ms_video_track_source.cc [new file with mode: 0644]
tizen_src/chromium_impl/third_party/blink/renderer/modules/elementary_media_stream_source/ms_video_track_source.h [new file with mode: 0644]
tizen_src/chromium_impl/third_party/blink/renderer/modules/elementary_media_stream_source/same_thread_elementary_media_stream_source_attachment.cc
tizen_src/chromium_impl/third_party/blink/renderer/modules/elementary_media_stream_source/same_thread_elementary_media_stream_source_attachment.h
tizen_src/chromium_impl/third_party/blink/renderer/platform/elementary_media_stream_source/BUILD.gn
tizen_src/chromium_impl/third_party/blink/renderer/platform/elementary_media_stream_source/web_elementary_media_stream_source_control.h
tizen_src/chromium_impl/third_party/blink/renderer/platform/elementary_media_stream_source/web_elementary_media_stream_source_dispatcher.cc
tizen_src/chromium_impl/third_party/blink/renderer/platform/elementary_media_stream_source/web_elementary_media_stream_source_dispatcher.h
tizen_src/chromium_impl/third_party/blink/renderer/platform/elementary_media_stream_source/web_elementary_media_track_control.h
tizen_src/chromium_impl/third_party/blink/renderer/platform/elementary_media_stream_source/web_elementary_media_track_ms_audio_sink.h [new file with mode: 0644]
tizen_src/chromium_impl/third_party/blink/renderer/platform/elementary_media_stream_source/web_elementary_media_track_ms_video_sink.h [new file with mode: 0644]

index c4b96a9aaed33447cedff1ac0bd293b455b9044e..b4f721736b053ec78c26518cf9f8ddee29f92214 100644 (file)
 #include "media/base/pipeline.h"
 #endif
 
+#if defined(SAMSUNG_ELEMENTARY_MEDIA_STREAM_SOURCE)
+#include "base/command_line.h"
+#include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/common_types.h"
+#include "media/base/media_switches.h"
+#endif  // defined(SAMSUNG_ELEMENTARY_MEDIA_STREAM_SOURCE)
+
 namespace cc {
 class Layer;
 }
@@ -126,7 +132,10 @@ class BLINK_PLATFORM_EXPORT WebMediaPlayerClient {
   virtual bool IsGameMode() const = 0;
   virtual bool IsLowLatencyMode() const = 0;
   virtual bool IsVideoTextureMode() const = 0;
-#endif
+  virtual void OnLoadDeferredUntilSourceOpen() = 0;
+  content::elementary_media_stream_source::PipelineMode GetEmssPipelineMode()
+      const;
+#endif  // defined(SAMSUNG_ELEMENTARY_MEDIA_STREAM_SOURCE)
   virtual void RemotePlaybackCompatibilityChanged(const WebURL&,
                                                   bool is_compatible) = 0;
 
@@ -278,6 +287,36 @@ class BLINK_PLATFORM_EXPORT WebMediaPlayerClient {
   ~WebMediaPlayerClient() = default;
 };
 
+#if defined(SAMSUNG_ELEMENTARY_MEDIA_STREAM_SOURCE)
+inline content::elementary_media_stream_source::PipelineMode
+WebMediaPlayerClient::GetEmssPipelineMode() const {
+  const auto demuxer_mode = ([&]() {
+    using DemuxerMode = content::elementary_media_stream_source::DemuxerMode;
+    return media::IsUpstreamArchitectureEnabled() ? DemuxerMode::kMediaStream
+                                                  : DemuxerMode::kDataStream;
+  })();
+
+  const auto latency_mode = ([&]() {
+    using LatencyMode = content::elementary_media_stream_source::LatencyMode;
+    if (IsGameMode()) {
+      return LatencyMode::kUltraLow;
+    }
+    if (IsLowLatencyMode()) {
+      return LatencyMode::kLow;
+    }
+    return LatencyMode::kNormal;
+  })();
+
+  const auto player_mode = ([&]() {
+    using PlayerMode = content::elementary_media_stream_source::PlayerMode;
+    return IsVideoTextureMode() ? PlayerMode::kDecodeToTexture
+                                : PlayerMode::kPlayer;
+  })();
+
+  return {demuxer_mode, latency_mode, player_mode};
+}
+#endif  // defined(SAMSUNG_ELEMENTARY_MEDIA_STREAM_SOURCE)
+
 }  // namespace blink
 
 #endif  // THIRD_PARTY_BLINK_PUBLIC_PLATFORM_WEB_MEDIA_PLAYER_CLIENT_H_
index 85880e0ca20fd0046487fd955a8457eeeda9267d..a5d9584ffd9e54b5a75e558e101ff2ebb3217fb7 100644 (file)
@@ -64,6 +64,10 @@ class WebMediaStreamVideoRenderer;
 class WebString;
 class WebVideoFrameSubmitter;
 
+#if defined(SAMSUNG_ELEMENTARY_MEDIA_STREAM_SOURCE)
+class WebElementaryMediaStreamSourceDispatcher;
+#endif  // defined(SAMSUNG_ELEMENTARY_MEDIA_STREAM_SOURCE)
+
 // WebMediaPlayerMS delegates calls from WebCore::MediaPlayerPrivate to
 // Chrome's media player when "src" is from media stream.
 //
@@ -290,6 +294,13 @@ class BLINK_MODULES_EXPORT WebMediaPlayerMS
   void PaintDecodedVideoFrame(scoped_refptr<media::VideoFrame> decoded_frame);
 #endif
 
+#if defined(SAMSUNG_ELEMENTARY_MEDIA_STREAM_SOURCE)
+  void StartLoadingEmss();
+  void OnEmssInitialized(
+      std::shared_ptr<WebElementaryMediaStreamSourceDispatcher>);
+  bool SourceHasTracks(const WebMediaPlayerSource& source);
+#endif  // defined(SAMSUNG_ELEMENTARY_MEDIA_STREAM_SOURCE)
+
   std::unique_ptr<MediaStreamInternalFrameWrapper> internal_frame_;
 
   WebMediaPlayer::NetworkState network_state_;
index a9cc29c745dd65e8089714c8e9f404c69d34276e..e165da5f7deff365048d7c45172de543aee10679 100644 (file)
@@ -724,6 +724,18 @@ void HTMLMediaElement::ParseAttribute(
     DVLOG(2) << "parseAttribute(" << *this
              << ", kSrcAttr, old=" << params.old_value
              << ", new=" << params.new_value << ")";
+
+#if defined(SAMSUNG_ELEMENTARY_MEDIA_STREAM_SOURCE)
+    if (media_source_attachment_ &&
+        media_source_attachment_->IsElementaryMediaStreamSource()) {
+      // Contrary to WebRTC source which is set via `.srcObject` attribute, EMSS
+      // is set via `.src`. Clear fields that would be usually reset by changing
+      // `.srcObject` if EMSS was attached previously.
+      src_object_stream_descriptor_ = nullptr;
+      src_object_media_source_handle_ = nullptr;
+    }
+#endif  // defined(SAMSUNG_ELEMENTARY_MEDIA_STREAM_SOURCE)
+
     // A change to the src attribute can affect intrinsic size, which in turn
     // requires a style recalc.
     SetNeedsStyleRecalc(kLocalStyleChange,
@@ -1526,6 +1538,16 @@ bool HTMLMediaElement::IsVideoTextureMode() const {
 void HTMLMediaElement::StartPlayerLoad() {
   DCHECK(!web_media_player_);
 
+#if defined(SAMSUNG_ELEMENTARY_MEDIA_STREAM_SOURCE)
+  if (media_source_attachment_) {
+    if (auto* src_object_stream_descriptor =
+            media_source_attachment_->GetMediaStreamDescriptorIfAvailable(
+                media_source_tracer_)) {
+      src_object_stream_descriptor_ = src_object_stream_descriptor;
+    }
+  }
+#endif
+
   WebMediaPlayerSource source;
   if (src_object_stream_descriptor_) {
     source =
@@ -5421,6 +5443,27 @@ void HTMLMediaElement::ElementaryMediaStreamSourceOpened(
   media_source_attachment_->SetWebElementaryStreamSourceAndOpen(
       media_source_tracer_, std::move(web_elementary_stream_source_dispatcher));
 }
+
+void HTMLMediaElement::OnLoadDeferredUntilSourceOpen() {
+  media_source_attachment_->OnLoadDeferredUntilSourceOpen(
+      media_source_tracer_,
+      WTF::BindOnce(&HTMLMediaElement::FireDeferredLoadAfterSourceOpen,
+                    WrapWeakPersistent(this)));
+}
+
+void HTMLMediaElement::FireDeferredLoadAfterSourceOpen() {
+  LOG(INFO) << "FireDeferredLoadAfterSourceOpen(" << *this << ")";
+
+  if (!web_media_player_ || !src_object_stream_descriptor_)
+    return;
+
+  auto source =
+      WebMediaPlayerSource(WebMediaStream(src_object_stream_descriptor_));
+  bool is_cache_disabled = false;
+  probe::IsCacheDisabled(GetDocument().GetExecutionContext(),
+                         &is_cache_disabled);
+  web_media_player_->Load(GetLoadType(), source, CorsMode(), is_cache_disabled);
+}
 #endif
 
 bool HTMLMediaElement::IsInteractiveContent() const {
index 78b021acfba4188a40163e974ece5c7e192ad7c0..f4d9bc63728cd8c03c83a7d17948d9da5134c16d 100644 (file)
@@ -625,6 +625,8 @@ class CORE_EXPORT HTMLMediaElement
   void ElementaryMediaStreamSourceOpened(
       std::shared_ptr<WebElementaryMediaStreamSourceDispatcher>
           web_elementary_stream_source_dispatcher) final;
+  void OnLoadDeferredUntilSourceOpen() final;
+  void FireDeferredLoadAfterSourceOpen();
 #endif
   void RemotePlaybackCompatibilityChanged(const WebURL&,
                                           bool is_compatible) final;
index c04a621fb412fe70ad4ab3a45dca32cd8563ac5e..8c2764f1aad739e66fe51dc3011521bbfaa980d9 100644 (file)
@@ -21,6 +21,7 @@ class WebElementaryMediaStreamSourceDispatcher;
 
 class HTMLMediaElement;
 class MediaSourceRegistry;
+class MediaStreamDescriptor;
 class TrackBase;
 class WebMediaSource;
 
@@ -148,6 +149,9 @@ class CORE_EXPORT MediaSourceAttachment
   virtual bool IsGameMode(MediaSourceTracer* tracer) const = 0;
   virtual bool IsLowLatencyMode(MediaSourceTracer* tracer) const = 0;
   virtual bool IsVideoTextureMode(MediaSourceTracer* tracer) const = 0;
+  virtual void OnLoadDeferredUntilSourceOpen(
+      MediaSourceTracer* tracer,
+      base::OnceClosure on_source_opened) = 0;
   virtual void OnPause(MediaSourceTracer* tracer) = 0;
   virtual void OnPlay(MediaSourceTracer* tracer) = 0;
   virtual void OnResume(MediaSourceTracer* tracer) = 0;
@@ -162,6 +166,8 @@ class CORE_EXPORT MediaSourceAttachment
   virtual void UpdatePlaybackPosition(MediaSourceTracer* tracer,
                                       double playback_position,
                                       uint32_t session_id) = 0;
+  virtual MediaStreamDescriptor* GetMediaStreamDescriptorIfAvailable(
+      MediaSourceTracer* tracer) = 0;
 #endif  // defined(SAMSUNG_ELEMENTARY_MEDIA_STREAM_SOURCE)
 
  private:
index ad77ddf43240781b6a51b6da0a9e6686abe6d691..d2bd154df99d59e96c0de71fbd911578893f49e0 100644 (file)
@@ -87,6 +87,10 @@ bool MediaSourceAttachmentSupplement::IsVideoTextureMode(
   return false;
 }
 
+void MediaSourceAttachmentSupplement::OnLoadDeferredUntilSourceOpen(
+    MediaSourceTracer*,
+    base::OnceClosure) {}
+
 void MediaSourceAttachmentSupplement::OnPause(MediaSourceTracer*) {}
 
 void MediaSourceAttachmentSupplement::OnPlay(MediaSourceTracer*) {}
@@ -99,6 +103,12 @@ void MediaSourceAttachmentSupplement::UpdatePlaybackPosition(MediaSourceTracer*,
                                                              double,
                                                              uint32_t) {}
 
+MediaStreamDescriptor*
+MediaSourceAttachmentSupplement::GetMediaStreamDescriptorIfAvailable(
+    MediaSourceTracer*) {
+  return nullptr;
+}
+
 #endif  // defined(SAMSUNG_ELEMENTARY_MEDIA_STREAM_SOURCE)
 
 // protected
index 63b14283f22f21e4a1a14bdb850e8adcdcff35ec..c42c31393200f57cf3e1e9b0f795e5bf5dedf079 100644 (file)
@@ -149,6 +149,9 @@ class MediaSourceAttachmentSupplement : public MediaSourceAttachment {
   bool IsGameMode(MediaSourceTracer* tracer) const override;
   bool IsLowLatencyMode(MediaSourceTracer* tracer) const override;
   bool IsVideoTextureMode(MediaSourceTracer* tracer) const override;
+  void OnLoadDeferredUntilSourceOpen(
+      MediaSourceTracer* tracer,
+      base::OnceClosure on_source_opened) override;
   void OnPause(MediaSourceTracer* tracer) override;
   void OnPlay(MediaSourceTracer* tracer) override;
   void OnResume(MediaSourceTracer* tracer) override;
@@ -156,6 +159,8 @@ class MediaSourceAttachmentSupplement : public MediaSourceAttachment {
   void UpdatePlaybackPosition(MediaSourceTracer* tracer,
                               double playback_position,
                               uint32_t session_id) override;
+  MediaStreamDescriptor* GetMediaStreamDescriptorIfAvailable(
+      MediaSourceTracer* tracer) override;
 #endif  // defined(SAMSUNG_ELEMENTARY_MEDIA_STREAM_SOURCE)
 
  protected:
index 1577103dc585d4040e55775e2ddc0be1d6e9f610..1714b3a4ed77405d26d721cbf3e07dc7c0411676 100644 (file)
 #include "third_party/blink/renderer/platform/wtf/cross_thread_copier_media.h"
 #include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
 
+#if defined(SAMSUNG_ELEMENTARY_MEDIA_STREAM_SOURCE)
+#include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/demuxer_dispatcher.h"
+#include "third_party/blink/renderer/platform/elementary_media_stream_source/web_elementary_media_stream_source_dispatcher.h"
+#endif  // defined(SAMSUNG_ELEMENTARY_MEDIA_STREAM_SOURCE)
+
 #if BUILDFLAG(IS_TIZEN)
 #include "tizen/system_info.h"
 #endif
@@ -103,6 +108,10 @@ const char* LoadTypeToString(WebMediaPlayer::LoadType type) {
       return "MediaSource";
     case WebMediaPlayer::kLoadTypeMediaStream:
       return "MediaStream";
+#if defined(SAMSUNG_ELEMENTARY_MEDIA_STREAM_SOURCE)
+    case WebMediaPlayer::kLoadTypeSamsungElementaryMediaStreamSource:
+      return "ElementaryMediaStreamSource";
+#endif  // defined(SAMSUNG_ELEMENTARY_MEDIA_STREAM_SOURCE)
     default:
       return "Unknown type";
   }
@@ -572,6 +581,15 @@ WebMediaPlayer::LoadTiming WebMediaPlayerMS::Load(
     CorsMode /*cors_mode*/,
     bool is_cache_disabled) {
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+#if defined(SAMSUNG_ELEMENTARY_MEDIA_STREAM_SOURCE)
+  if (load_type ==
+          WebMediaPlayer::kLoadTypeSamsungElementaryMediaStreamSource &&
+      !SourceHasTracks(source)) {
+    LOG(INFO) << "Deferring load until EMSS opens...";
+    StartLoadingEmss();
+    return WebMediaPlayer::LoadTiming::kDeferred;
+  }
+#endif  // defined(SAMSUNG_ELEMENTARY_MEDIA_STREAM_SOURCE)
   SendLogMessage(String::Format("%s({load_type=%s})", __func__,
                                 LoadTypeToString(load_type)));
 
@@ -1856,4 +1874,44 @@ void WebMediaPlayerMS::SendVideoDecodedBufferRequest() {
 }
 #endif
 
+#if defined(SAMSUNG_ELEMENTARY_MEDIA_STREAM_SOURCE)
+void WebMediaPlayerMS::StartLoadingEmss() {
+  using EmssDemuxerDispatcher =
+      ::content::elementary_media_stream_source::any_thread::DemuxerDispatcher;
+  client_->OnLoadDeferredUntilSourceOpen();
+  const auto emss_pipeline_mode = client_->GetEmssPipelineMode();
+  auto emss_demuxer_dispatcher = EmssDemuxerDispatcher::Create(
+      emss_pipeline_mode, base::SingleThreadTaskRunner::GetCurrentDefault());
+  auto [blink_source_dispatcher, any_thread_source_impl,
+        control_thread_source_impl, worker_thread_source_impl] =
+      WebElementaryMediaStreamSourceDispatcher::Create(
+          emss_pipeline_mode, base::SingleThreadTaskRunner::GetCurrentDefault(),
+          emss_demuxer_dispatcher->GetWorkerThreadTaskRunner());
+  blink_source_dispatcher->KeepDemuxerDispatcher(emss_demuxer_dispatcher);
+  emss_demuxer_dispatcher->RegisterSource(
+      std::move(any_thread_source_impl), std::move(control_thread_source_impl),
+      std::move(worker_thread_source_impl),
+      media::BindToCurrentLoop(WTF::BindOnce(
+          &WebMediaPlayerMS::OnEmssInitialized, weak_factory_.GetWeakPtr(),
+          std::move(blink_source_dispatcher))));
+}
+
+void WebMediaPlayerMS::OnEmssInitialized(
+    std::shared_ptr<WebElementaryMediaStreamSourceDispatcher>
+        web_elementary_media_stream_source_dispatcher) {
+  client_->ElementaryMediaStreamSourceOpened(
+      std::move(web_elementary_media_stream_source_dispatcher));
+}
+
+bool WebMediaPlayerMS::SourceHasTracks(const WebMediaPlayerSource& source) {
+  auto web_stream = source.GetAsMediaStream();
+  if (web_stream.IsNull())
+    return false;
+
+  MediaStreamDescriptor& descriptor = *web_stream;
+  return descriptor.VideoComponents().size() != 0 ||
+         descriptor.AudioComponents().size() != 0;
+}
+#endif  // defined(SAMSUNG_ELEMENTARY_MEDIA_STREAM_SOURCE)
+
 }  // namespace blink
index 6485bd948313380aa3c1f47a7506236f224d7c67..9baaebceacbe533ed65779ed2fbf8cea145e1e91 100644 (file)
@@ -3675,40 +3675,20 @@ void WebMediaPlayerImpl::StartPipeline() {
   } else if (load_type_ == kLoadTypeSamsungElementaryMediaStreamSource) {
     using EmssDemuxer = content::elementary_media_stream_source::any_thread::
         ElementaryMediaStreamDemuxer;
-    using PipelineMode = content::elementary_media_stream_source::PipelineMode;
-
-    const auto demuxer_mode = ([&]() {
-      using DemuxerMode = content::elementary_media_stream_source::DemuxerMode;
-      return media::IsUpstreamArchitectureEnabled() ? DemuxerMode::kMediaStream
-                                                    : DemuxerMode::kDataStream;
-    })();
-
-    const auto latency_mode = ([&]() {
-      using content::elementary_media_stream_source::LatencyMode;
-      if (client_->IsGameMode()) {
-        return LatencyMode::kUltraLow;
-      }
-      if (client_->IsLowLatencyMode()) {
-        return LatencyMode::kLow;
-      }
-      return LatencyMode::kNormal;
-    })();
-
-    const auto player_mode = ([&]() {
-      using content::elementary_media_stream_source::PlayerMode;
-      if (client_->IsVideoTextureMode()) {
-        // In Video Texture mode, we disable video hole functionality, to
-        // force returning decoded frames from player instead of
-        // presenting them on as screen.
-        LOG(INFO) << "Disabling video hole in EMSS Video Texture mode";
-        is_video_hole_ = false;
-        return PlayerMode::kDecodeToTexture;
-      }
-      return PlayerMode::kPlayer;
-    })();
+    using PlayerMode = content::elementary_media_stream_source::PlayerMode;
+
+    auto pipeline_mode = client_->GetEmssPipelineMode();
+
+    if (pipeline_mode.player_mode == PlayerMode::kDecodeToTexture) {
+      // In Video Texture mode, we disable video hole functionality, to
+      // force returning decoded frames from player instead of
+      // presenting them on as screen.
+      LOG(INFO) << "Disabling video hole in EMSS Video Texture mode";
+      is_video_hole_ = false;
+    }
 
     auto elementary_stream_demuxer = std::make_unique<EmssDemuxer>(
-        PipelineMode{demuxer_mode, latency_mode, player_mode},
+        pipeline_mode,
         base::ThreadTaskRunnerHandle::Get(),
         media::BindToCurrentLoop(base::BindOnce(
             &WebMediaPlayerImpl::OnElementaryMediaStreamDemuxerOpened,
index 68bc30461bdf14a604b1c156fd1a75ad5ec173ca..8050d6e669cb71ef77e42bd4aa331dbf9ad83455 100644 (file)
@@ -40,6 +40,8 @@ elementary_media_stream_source_renderer("any_thread") {
     "mojo_shm_pool.h",
     "mojom_media_type_converters.cc",
     "mojom_media_type_converters.h",
+    "ms_decoding_stream.cc",
+    "ms_decoding_stream.h",
     "packet.cc",
     "packet.h",
     "platform_demuxer_adapter.h",
index 58fad95a815bf1124cd97d9a0ae85ae2b1f00920..62605b3805fdb2959aaef9b800d14e956061c331 100644 (file)
@@ -90,6 +90,16 @@ std::ostream& operator<<(std::ostream& os, DemuxerSeekingState status) {
   return os;
 }
 
+std::ostream& operator<<(std::ostream& os, LatencyMode latency_mode) {
+  switch (latency_mode) {
+    ENUM_VALUE_TO_OSTREAM(os, LatencyMode::kNormal);
+    ENUM_VALUE_TO_OSTREAM(os, LatencyMode::kLow);
+    ENUM_VALUE_TO_OSTREAM(os, LatencyMode::kUltraLow);
+    ENUM_DEFAULT_UNKNOWN(os, LatencyMode, latency_mode);
+  }
+  return os;
+}
+
 std::ostream& operator<<(std::ostream& os, OperationResult result) {
   switch (result) {
     ENUM_VALUE_TO_OSTREAM(os, OperationResult::kOk);
index a529220e5f0f2d5b17cb90b7b4018104b61f0ee9..40b3330ef0aeddace9a0ca9ac034a4e5f8e8d8ca 100644 (file)
@@ -22,6 +22,7 @@ std::ostream& operator<<(std::ostream&, ChangeReason);
 std::ostream& operator<<(std::ostream&, DecodingMode);
 std::ostream& operator<<(std::ostream&, DemuxerMode);
 std::ostream& operator<<(std::ostream&, DemuxerSeekingState);
+std::ostream& operator<<(std::ostream&, LatencyMode);
 std::ostream& operator<<(std::ostream&, OperationResult);
 std::ostream& operator<<(std::ostream&, PlayerMode);
 std::ostream& operator<<(std::ostream&, PlayerState);
index 4be12004ddec1d2ded6ec30bae8cd4bd16a4aa32..d4a8449024f2d10e12fd884b8843b1a703578c06 100644 (file)
@@ -18,7 +18,9 @@ class Demuxer {
  public:
   virtual ~Demuxer() = default;
 
-  virtual void OnInitialConfigReadyForMediaStream(
+  // Special OnInitialConfigReady variant dedicated for media::Demuxer
+  // implementation.
+  virtual void OnInitialConfigReadyForMediaDemuxer(
       MaybeAudioConfig audio_config,
       MaybeVideoConfig video_config) = 0;
 
index 7355de3e0236e1481d694914e59172536d492760..43442dc1839ec871470dc9d769bc0e154d1329b6 100644 (file)
@@ -7,24 +7,33 @@
 #include <cstddef>
 #include <optional>
 
+#include "base/task/bind_post_task.h"
 #include "base/task/single_thread_task_runner.h"
 #include "base/task/thread_pool.h"
 #include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/common_types.h"
 #include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/demuxer_impl.h"
 #include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/demuxer_params.h"
 #include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/lockable_demuxer_state.h"
+#include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/ms_decoding_stream.h"
 #include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/platform_demuxer_adapter_client.h"
+#include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/source_impl.h"
 #include "content/renderer/media/tizen/elementary_media_stream_source/control_thread/demuxer_dispatcher_client.h"
 #include "content/renderer/media/tizen/elementary_media_stream_source/control_thread/demuxer_impl.h"
+#include "content/renderer/media/tizen/elementary_media_stream_source/control_thread/ms_decoding_stream.h"
+#include "content/renderer/media/tizen/elementary_media_stream_source/control_thread/source_impl.h"
 #include "content/renderer/media/tizen/elementary_media_stream_source/media_thread/platform_demuxer_adapter.h"
 #include "content/renderer/media/tizen/elementary_media_stream_source/worker_thread/data_stream_demuxer_impl.h"
 #include "content/renderer/media/tizen/elementary_media_stream_source/worker_thread/demuxer_dispatcher_client.h"
 #include "content/renderer/media/tizen/elementary_media_stream_source/worker_thread/demuxer_dispatcher_lifecycle_observer.h"
 #include "content/renderer/media/tizen/elementary_media_stream_source/worker_thread/media_stream_demuxer_impl.h"
+#include "content/renderer/media/tizen/elementary_media_stream_source/worker_thread/ms_decoding_stream.h"
+#include "content/renderer/media/tizen/elementary_media_stream_source/worker_thread/source_impl.h"
 #include "mojo/public/cpp/bindings/remote.h"
+#include "platform/scheduler/public/thread.h"
 #include "services/elementary_media_stream_source/public/cpp/logger.h"
 #include "third_party/blink/public/common/thread_safe_browser_interface_broker_proxy.h"
 #include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/renderer/platform/scheduler/public/main_thread.h"
 
 // generated sources:
 #include "tizen_src/chromium_impl/services/elementary_media_stream_source/public/mojom/data_stream.mojom.h"
@@ -57,6 +66,14 @@ CreateDataStream() {
                       std::move(pending_data_stream_receiver)));
 }
 
+void GetGpuFactoriesOnBlinkMainThread(
+    base::OnceCallback<void(media::GpuVideoAcceleratorFactories*)>
+        on_got_gpu_factories) {
+  auto* gpu_factories = blink::Platform::Current()->GetGpuFactories();
+  EMSS_LOG_ASSERT(gpu_factories) << "Cannot retrieve GPU Factories!";
+  std::move(on_got_gpu_factories).Run(gpu_factories);
+}
+
 }  // anonymous namespace
 
 // static
@@ -85,27 +102,56 @@ std::shared_ptr<DemuxerDispatcher> DemuxerDispatcher::Create(
   DemuxerParams params(demuxer_dispatcher, pipeline_mode,
                        std::make_shared<LockableDemuxerState>());
 
-  auto any_demuxer_impl = std::make_shared<any_thread::DemuxerImpl>(params);
-  demuxer_dispatcher->SetClient<AnyThreadClient>(any_demuxer_impl);
-  demuxer_dispatcher->SetClient<AnyThreadDemuxerAdapterClient>(
-      std::move(any_demuxer_impl));
-
-  auto control_demuxer_client =
-      std::make_shared<control_thread::DemuxerImpl>(params);
-  demuxer_dispatcher->SetClient<ControlThreadClient>(control_demuxer_client);
-  demuxer_dispatcher->SetClient<ControlThreadDemuxerAdapterClient>(
-      std::move(control_demuxer_client));
+  if (pipeline_mode.demuxer_mode == DemuxerMode::kMediaStream &&
+      pipeline_mode.latency_mode != LatencyMode::kNormal) {
+    SetAnyClients(demuxer_dispatcher,
+                  std::make_shared<any_thread::MsDecodingStream>(params));
+    SetControlClients(
+        demuxer_dispatcher,
+        std::make_shared<control_thread::MsDecodingStream>(params));
+  } else {
+    SetAnyClients(demuxer_dispatcher,
+                  std::make_shared<any_thread::DemuxerImpl>(params));
+    SetControlClients(demuxer_dispatcher,
+                      std::make_shared<control_thread::DemuxerImpl>(params));
+  }
 
   if (pipeline_mode.demuxer_mode == DemuxerMode::kDataStream) {
     SetWorkerClients<worker_thread::DataStreamDemuxerImpl>(
         pipeline_mode, demuxer_dispatcher,
         std::move(maybe_pending_data_stream_src),
         std::make_shared<worker_thread::DataStreamDemuxerImpl>(params));
-  } else {
+  } else if (pipeline_mode.latency_mode == LatencyMode::kNormal) {
     SetWorkerClients<worker_thread::MediaStreamDemuxerImpl>(
         pipeline_mode, demuxer_dispatcher,
         std::move(maybe_pending_data_stream_src),
         std::make_shared<worker_thread::MediaStreamDemuxerImpl>(params));
+  } else {
+    auto worker_demuxer_impl =
+        std::make_shared<worker_thread::MsDecodingStream>(params);
+    auto weak_ms_decoding_stream =
+        std::weak_ptr<worker_thread::MsDecodingStream>{worker_demuxer_impl};
+    SetWorkerClients<worker_thread::MsDecodingStream>(
+        pipeline_mode, demuxer_dispatcher,
+        std::move(maybe_pending_data_stream_src),
+        std::move(worker_demuxer_impl));
+
+    blink::Thread::MainThread()->GetDeprecatedTaskRunner()->PostTask(
+        FROM_HERE,
+        base::BindOnce(
+            &GetGpuFactoriesOnBlinkMainThread,
+            base::BindPostTask(
+                demuxer_dispatcher->GetWorkerThreadTaskRunner(),
+                base::BindOnce(
+                    [](std::weak_ptr<worker_thread::MsDecodingStream>
+                           weak_ms_decoding_stream,
+                       media::GpuVideoAcceleratorFactories* gpu_factories) {
+                      if (auto ms_decoding_stream =
+                              weak_ms_decoding_stream.lock()) {
+                        ms_decoding_stream->SetGpuFactories(gpu_factories);
+                      }
+                    },
+                    std::move(weak_ms_decoding_stream)))));
   }
 
   return demuxer_dispatcher;
@@ -171,6 +217,23 @@ void DemuxerDispatcher::RegisterPlatformDemuxerAdapter(
   SetClient(platform_demuxer_adapter);
 }
 
+void DemuxerDispatcher::RegisterSource(
+    std::shared_ptr<any_thread::SourceImpl> any_thread_source_impl,
+    std::shared_ptr<control_thread::SourceImpl> control_thread_source_impl,
+    std::shared_ptr<worker_thread::SourceImpl> worker_thread_source_impl,
+    base::OnceClosure on_emss_initialized) {
+  RunTask(&any_thread::PlatformDemuxerAdapterClient::RegisterSource,
+          std::static_pointer_cast<any_thread::DemuxerClient>(
+              std::move(any_thread_source_impl)));
+  DispatchTask(&control_thread::PlatformDemuxerAdapterClient::RegisterSource,
+               std::static_pointer_cast<control_thread::DemuxerClient>(
+                   std::move(control_thread_source_impl)));
+  DispatchTask(&worker_thread::PlatformDemuxerAdapterClient::RegisterSource,
+               std::static_pointer_cast<worker_thread::DemuxerClient>(
+                   std::move(worker_thread_source_impl)),
+               std::move(on_emss_initialized));
+}
+
 }  // namespace any_thread
 
 }  // namespace elementary_media_stream_source
index e1662bb2fd58161028038b8d88b2c7c498d35eed..4a11e48729bc00346ab4fb428303d27da7617c72 100644 (file)
@@ -16,6 +16,7 @@
 #include "base/task/single_thread_task_runner.h"
 #include "base/threading/thread.h"
 #include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/common_types.h"
+#include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/source_impl.h"
 #include "content/renderer/media/tizen/elementary_media_stream_source/worker_thread/demuxer_dispatcher_lifecycle_observer.h"
 #include "content/renderer/media/tizen/elementary_media_stream_source/worker_thread/pending_data_stream_src_interfaces.h"
 #include "mojo/public/cpp/bindings/remote.h"
@@ -28,6 +29,7 @@ namespace elementary_media_stream_source {
 namespace control_thread {
 class DemuxerDispatcherClient;
 class PlatformDemuxerAdapterClient;
+class SourceImpl;
 }  // namespace control_thread
 
 namespace media_thread {
@@ -37,6 +39,7 @@ class PlatformDemuxerAdapter;
 namespace worker_thread {
 class DemuxerDispatcherClient;
 class PlatformDemuxerAdapterClient;
+class SourceImpl;
 }  // namespace worker_thread
 
 namespace any_thread {
@@ -116,6 +119,11 @@ class DemuxerDispatcher
     SetClient<TypedMediaStreamProxy<track_type>>(std::move(stream));
   }
 
+  void RegisterSource(std::shared_ptr<any_thread::SourceImpl>,
+                      std::shared_ptr<control_thread::SourceImpl>,
+                      std::shared_ptr<worker_thread::SourceImpl>,
+                      base::OnceClosure on_emss_initialized);
+
   scoped_refptr<base::SingleThreadTaskRunner> GetWorkerThreadTaskRunner()
       const {
     return worker_thread_task_runner_;
@@ -130,6 +138,24 @@ class DemuxerDispatcher
           worker_thread_task_runner);
 
  private:
+  template <typename DemuxerImplT>
+  static void SetAnyClients(
+      const std::shared_ptr<DemuxerDispatcher>& demuxer_dispatcher,
+      std::shared_ptr<DemuxerImplT>&& any_demuxer_impl) {
+    demuxer_dispatcher->SetClient<AnyThreadClient>(any_demuxer_impl);
+    demuxer_dispatcher->SetClient<AnyThreadDemuxerAdapterClient>(
+        std::move(any_demuxer_impl));
+  }
+
+  template <typename DemuxerImplT>
+  static void SetControlClients(
+      const std::shared_ptr<DemuxerDispatcher>& demuxer_dispatcher,
+      std::shared_ptr<DemuxerImplT>&& control_demuxer_impl) {
+    demuxer_dispatcher->SetClient<ControlThreadClient>(control_demuxer_impl);
+    demuxer_dispatcher->SetClient<ControlThreadDemuxerAdapterClient>(
+        std::move(control_demuxer_impl));
+  }
+
   template <typename DemuxerImplT>
   static void SetWorkerClients(
       PipelineMode pipeline_mode,
index a9566acdff71ecb9c60a0d31ed6046ef1f6fc97f..bbeda1b9337ad22ad55849565521c1a20c2f2d19 100644 (file)
@@ -34,12 +34,14 @@ DemuxerImpl::~DemuxerImpl() {
 
 //////////////////// Demuxer ////////////////////
 
-void DemuxerImpl::OnInitialConfigReadyForMediaStream(
+void DemuxerImpl::OnInitialConfigReadyForMediaDemuxer(
     MaybeAudioConfig maybe_audio_conf,
     MaybeVideoConfig maybe_video_conf) {
   EMSS_DEBUG();
-  EMSS_LOG_ASSERT(pipeline_mode_.demuxer_mode == DemuxerMode::kMediaStream)
-      << "Should not be called in " << pipeline_mode_.demuxer_mode;
+  EMSS_LOG_ASSERT(pipeline_mode_.demuxer_mode == DemuxerMode::kMediaStream &&
+                  pipeline_mode_.latency_mode == LatencyMode::kNormal)
+      << "Should not be called in " << pipeline_mode_.demuxer_mode << " and "
+      << pipeline_mode_.latency_mode;
 
   auto dispatcher = dispatcher_.lock();
 
index 149c970a8d19af0fc7bc9d6bc41ad506afdeec52..a8970b3c111b9a7b5fbf0609878e0cadd55518de 100644 (file)
@@ -30,7 +30,7 @@ class DemuxerImpl : public Demuxer,
   ~DemuxerImpl() override;
 
   // Demuxer
-  void OnInitialConfigReadyForMediaStream(
+  void OnInitialConfigReadyForMediaDemuxer(
       MaybeAudioConfig audio_config,
       MaybeVideoConfig video_config) override;
 
index 8e170e95ef3795496a131deb3ec3dfbc6dbb4d76..79b3a7457fd7e7eeef4e85271b9ff60552d57d3a 100644 (file)
@@ -113,35 +113,18 @@ void ElementaryMediaStreamDemuxer::Initialize(
 
   dispatcher_->RegisterPlatformDemuxerAdapter(this);
 
-  auto [source_dispatcher, any_thread_source_impl, control_thread_source_impl,
-        worker_thread_source_impl] =
-      SourceDispatcher::Create(pipeline_mode_, control_thread_task_runner_,
-                               dispatcher_->GetWorkerThreadTaskRunner());
-
-  auto blink_source_dispatcher = std::make_shared<
-      blink::WebElementaryMediaStreamSourceDispatcher>(
-      control_thread_task_runner_, std::move(source_dispatcher),
-      std::static_pointer_cast<blink::WebElementaryMediaStreamSourceControl>(
-          control_thread_source_impl));
-
-  dispatcher_->RunTask(&AnyThreadClient::RegisterSource,
-                       std::static_pointer_cast<any_thread::DemuxerClient>(
-                           any_thread_source_impl));
-  dispatcher_->DispatchTask(
-      &ControlThreadClient::RegisterSource,
-      std::static_pointer_cast<control_thread::DemuxerClient>(
-          control_thread_source_impl));
-
-  // FIXME(p.balut): better not unretained...
-  auto emss_initialized = media::BindToCurrentLoop(base::BindOnce(
-      &ElementaryMediaStreamDemuxer::OnInitializationDone,
-      base::Unretained(this), std::move(blink_source_dispatcher)));
-
-  dispatcher_->DispatchTask(
-      &WorkerThreadClient::RegisterSource,
-      std::static_pointer_cast<worker_thread::DemuxerClient>(
-          worker_thread_source_impl),
-      std::move(emss_initialized));
+  auto [blink_source_dispatcher, any_thread_source_impl,
+        control_thread_source_impl, worker_thread_source_impl] =
+      blink::WebElementaryMediaStreamSourceDispatcher::Create(
+          pipeline_mode_, control_thread_task_runner_,
+          dispatcher_->GetWorkerThreadTaskRunner());
+
+  dispatcher_->RegisterSource(
+      std::move(any_thread_source_impl), std::move(control_thread_source_impl),
+      std::move(worker_thread_source_impl),
+      media::BindToCurrentLoop(base::BindOnce(
+          &ElementaryMediaStreamDemuxer::OnInitializationDone,
+          base::Unretained(this), std::move(blink_source_dispatcher))));
 }
 
 void ElementaryMediaStreamDemuxer::AbortPendingReads() {
diff --git a/tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/any_thread/ms_decoding_stream.cc b/tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/any_thread/ms_decoding_stream.cc
new file mode 100644 (file)
index 0000000..c81cef8
--- /dev/null
@@ -0,0 +1,72 @@
+// Copyright (c) 2024 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/ms_decoding_stream.h"
+
+#include <memory>
+#include <utility>
+
+#include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/common_tools.h"
+#include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/common_types.h"
+#include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/demuxer_client.h"
+#include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/demuxer_dispatcher.h"
+#include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/media_stream_impl.h"
+#include "content/renderer/media/tizen/elementary_media_stream_source/media_thread/platform_demuxer_adapter.h"
+#include "services/elementary_media_stream_source/public/cpp/logger.h"
+
+namespace content {
+
+namespace elementary_media_stream_source {
+
+namespace any_thread {
+
+MsDecodingStream::MsDecodingStream(DemuxerParams params)
+    : pipeline_mode_(params.pipeline_mode),
+      dispatcher_(std::move(params.dispatcher)),
+      state_(std::move(params.state)) {
+  EMSS_DEBUG() << "Constructing object";
+}
+
+MsDecodingStream::~MsDecodingStream() {
+  EMSS_DEBUG() << "Destructing object";
+}
+
+//////////////////// Demuxer ////////////////////
+
+void MsDecodingStream::OnInitialConfigReadyForMediaDemuxer(
+    MaybeAudioConfig maybe_audio_conf,
+    MaybeVideoConfig maybe_video_conf) {
+  EMSS_DEBUG();
+  EMSS_LOG_ASSERT(false) << "Should not be called for MsDecodingStream";
+}
+
+//////////////////// DemuxerDispatcherClient ////////////////////
+
+blink::WebTimeRanges MsDecodingStream::GetBufferedRanges() const {
+  EMSS_LOG_ASSERT(false) << "Should not be called for MsDecodingStream";
+  return blink::WebTimeRanges();
+}
+
+bool MsDecodingStream::IsSeeking() const {
+  return false;
+}
+
+void MsDecodingStream::RegisterSessionIdChangeListeners(
+    SessionIdChangeListeners session_id_change_listeners) {
+  EMSS_LOG_ASSERT(false) << "Should not be called for MsDecodingStream";
+}
+
+//////////////////// PlatformDemuxerAdapterClient ////////////////////
+
+void MsDecodingStream::RegisterSource(std::shared_ptr<DemuxerClient> client) {
+  EMSS_DEBUG();
+
+  client->RegisterDemuxer(shared_from_this());
+}
+
+}  // namespace any_thread
+
+}  // namespace elementary_media_stream_source
+
+}  // namespace content
diff --git a/tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/any_thread/ms_decoding_stream.h b/tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/any_thread/ms_decoding_stream.h
new file mode 100644 (file)
index 0000000..d12a95b
--- /dev/null
@@ -0,0 +1,58 @@
+// Copyright (c) 2024 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TIZEN_SRC_CHROMIUM_IMPL_CONTENT_RENDERER_MEDIA_TIZEN_ELEMENTARY_MEDIA_STREAM_SOURCE_ANY_THREAD_MS_DECODING_STREAM_H_
+#define TIZEN_SRC_CHROMIUM_IMPL_CONTENT_RENDERER_MEDIA_TIZEN_ELEMENTARY_MEDIA_STREAM_SOURCE_ANY_THREAD_MS_DECODING_STREAM_H_
+
+#include <memory>
+
+#include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/demuxer.h"
+#include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/demuxer_client.h"
+#include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/demuxer_dispatcher_client.h"
+#include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/demuxer_params.h"
+#include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/lockable_demuxer_state.h"
+#include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/platform_demuxer_adapter_client.h"
+#include "third_party/blink/public/platform/web_time_range.h"
+
+namespace content {
+
+namespace elementary_media_stream_source {
+
+namespace any_thread {
+
+class MsDecodingStream : public Demuxer,
+                         public DemuxerDispatcherClient,
+                         public PlatformDemuxerAdapterClient,
+                         public std::enable_shared_from_this<MsDecodingStream> {
+ public:
+  explicit MsDecodingStream(DemuxerParams);
+  ~MsDecodingStream() override;
+
+  // Demuxer
+  void OnInitialConfigReadyForMediaDemuxer(
+      MaybeAudioConfig audio_config,
+      MaybeVideoConfig video_config) override;
+
+  // DemuxerDispatcherClient
+  blink::WebTimeRanges GetBufferedRanges() const override;
+  bool IsSeeking() const override;
+  void RegisterSessionIdChangeListeners(SessionIdChangeListeners) override;
+
+  // PlatformDemuxerAdapterClient
+  void RegisterSource(std::shared_ptr<DemuxerClient>) override;
+
+ private:
+  const PipelineMode pipeline_mode_;
+
+  std::weak_ptr<any_thread::DemuxerDispatcher> dispatcher_;
+  std::shared_ptr<LockableDemuxerState> state_;
+};
+
+}  // namespace any_thread
+
+}  // namespace elementary_media_stream_source
+
+}  // namespace content
+
+#endif  // TIZEN_SRC_CHROMIUM_IMPL_CONTENT_RENDERER_MEDIA_TIZEN_ELEMENTARY_MEDIA_STREAM_SOURCE_ANY_THREAD_MS_DECODING_STREAM_H_
index bfd39d5175725bb549c9d9023345d77a37e7e31f..bbb4292b39f4bcc5b84246d6d75508bd0947d8e2 100644 (file)
@@ -24,11 +24,12 @@ std::ostream& operator<<(std::ostream& os, const Packet& p) {
   if (std::holds_alternative<Packet::DataStreamPacket>(p.packet_)) {
     os << std::get<Packet::DataStreamPacket>(p.packet_);
   } else if (std::holds_alternative<Packet::MediaPacket>(p.packet_)) {
-    const auto& buffer = std::get<Packet::MediaPacket>(p.packet_).buffer;
-    if (buffer)
+    const auto& media_packet = std::get<Packet::MediaPacket>(p.packet_);
+    const auto& buffer = media_packet.buffer;
+    if (buffer) {
       os << buffer->AsHumanReadableString()
          << "; session id = " << p.session_id();
-    else
+    else
       os << "{ nullptr }";
   } else {
     NOTREACHED() << "unknown packet type";
index 745b9d726b1918f18f5f7d4b8c63919bbe6d59e8..d8206e08876a7d62e079e8e33420429ffede6800 100644 (file)
@@ -25,6 +25,8 @@ class Packet {
       ::elementary_media_stream_source::mojom::ElementaryMediaPacketPtr;
   using PacketType = ::elementary_media_stream_source::PacketType;
 
+  static constexpr const auto kNoCaptureTime = base::TimeTicks::Min();
+
   struct MediaPacket {
     scoped_refptr<media::DecoderBuffer> buffer;
     uint32_t session_id;
index caae667c46acfc991d702b5f27a810edf31dfff9..fcd12493b0de3bb4c938d385917e90fd5f345215 100644 (file)
@@ -106,7 +106,7 @@ class SourceDispatcher
   const PipelineMode pipeline_mode_;
   const scoped_refptr<base::SingleThreadTaskRunner> worker_thread_task_runner_;
 
-  friend class ElementaryMediaStreamDemuxer;
+  friend class ::blink::WebElementaryMediaStreamSourceDispatcher;
 };
 
 }  // namespace any_thread
index 4b170f836789204d364110ae33b4c3efdcb40b2e..35333b7fc3db7871e32b06780b605f10c13e87f5 100644 (file)
@@ -43,22 +43,19 @@ void SourceImpl::OnInitialConfigReady(MaybeAudioConfig audio_config,
                                       MaybeVideoConfig video_config) {
   EMSS_DEBUG();
 
-  switch (pipeline_mode_.demuxer_mode) {
-    case DemuxerMode::kDataStream:
-      if (auto dispatcher = dispatcher_.lock()) {
-        dispatcher->DispatchTask(&worker_thread::SourceDispatcherClient::
-                                     OnInitialConfigReadyForDataStream,
-                                 std::move(audio_config),
-                                 std::move(video_config));
-      }
-      break;
-
-    case DemuxerMode::kMediaStream:
-      if (auto demuxer = demuxer_.lock()) {
-        demuxer->OnInitialConfigReadyForMediaStream(std::move(audio_config),
-                                                    std::move(video_config));
-      }
-      break;
+  if (pipeline_mode_.demuxer_mode == DemuxerMode::kMediaStream &&
+      pipeline_mode_.latency_mode == LatencyMode::kNormal) {
+    if (auto demuxer = demuxer_.lock()) {
+      demuxer->OnInitialConfigReadyForMediaDemuxer(std::move(audio_config),
+                                                   std::move(video_config));
+    }
+    return;
+  }
+
+  if (auto dispatcher = dispatcher_.lock()) {
+    dispatcher->DispatchTask(
+        &worker_thread::SourceDispatcherClient::OnInitialConfigReady,
+        std::move(audio_config), std::move(video_config));
   }
 }
 
index c1ed827847baee3498d02caece0164acf68c5009..c6cb53567c4913cc5bcc2257e9b295b1290c8080 100644 (file)
@@ -15,6 +15,8 @@ elementary_media_stream_source_renderer("control_thread") {
     "demuxer_impl.cc",
     "demuxer_impl.h",
     "enable_dispatcher.h",
+    "ms_decoding_stream.cc",
+    "ms_decoding_stream.h",
     "platform_demuxer_adapter_client.h",
     "source.h",
     "source_client.h",
diff --git a/tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/control_thread/ms_decoding_stream.cc b/tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/control_thread/ms_decoding_stream.cc
new file mode 100644 (file)
index 0000000..9df07d0
--- /dev/null
@@ -0,0 +1,74 @@
+// Copyright (c) 2024 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/tizen/elementary_media_stream_source/control_thread/ms_decoding_stream.h"
+
+#include "content/renderer/media/tizen/elementary_media_stream_source/control_thread/demuxer_client.h"
+#include "services/elementary_media_stream_source/public/cpp/logger.h"
+
+namespace content {
+namespace elementary_media_stream_source {
+namespace control_thread {
+
+MsDecodingStream::MsDecodingStream(any_thread::DemuxerParams params)
+    : pipeline_mode_(params.pipeline_mode),
+      dispatcher_(std::move(params.dispatcher)) {
+  EMSS_DEBUG() << "Constructing object";
+}
+
+MsDecodingStream::~MsDecodingStream() {
+  EMSS_DEBUG() << "Destructing object";
+}
+
+//////////////////// Demuxer: ////////////////////
+
+void MsDecodingStream::NotifyDemuxerInitialized() {}
+
+void MsDecodingStream::OnBufferedTimeRangesChanged(
+    media::Ranges<base::TimeDelta>&&) {}
+
+void MsDecodingStream::OnDemuxerSeekDone(base::TimeDelta, uint32_t session_id) {
+}
+
+void MsDecodingStream::OnPipelineClosed() {}
+
+void MsDecodingStream::OnPipelineResuming() {}
+
+void MsDecodingStream::OnPipelineSuspended() {}
+
+void MsDecodingStream::SetDuration(base::TimeDelta) {}
+
+void MsDecodingStream::OnSessionIdChange(uint32_t session_id) {}
+
+//////////////////// DemuxerDispatcherClient: ////////////////////
+
+void MsDecodingStream::OnClosedCaptions(std::vector<uint8_t> closed_captions) {}
+
+void MsDecodingStream::OnPlayerError(BackendError,
+                                     std::string message,
+                                     base::OnceClosure on_error_reported) {}
+
+void MsDecodingStream::OnResumeComplete() {}
+
+//////////////////// PlatformDemuxerAdapterClient ////////////////////
+
+void MsDecodingStream::CancelPendingSeek(base::TimeDelta seek_time) {}
+
+void MsDecodingStream::RegisterSource(std::shared_ptr<DemuxerClient> client) {
+  EMSS_DEBUG();
+
+  client->RegisterDemuxer(shared_from_this());
+  client_ = std::move(client);
+}
+
+void MsDecodingStream::Stop() {}
+
+void MsDecodingStream::StartSeek(base::TimeDelta seek_time,
+                                 base::OnceClosure on_seek_done) {}
+
+void MsDecodingStream::StartWaitingForSeek(base::TimeDelta seek_time) {}
+
+}  // namespace control_thread
+}  // namespace elementary_media_stream_source
+}  // namespace content
diff --git a/tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/control_thread/ms_decoding_stream.h b/tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/control_thread/ms_decoding_stream.h
new file mode 100644 (file)
index 0000000..8c5d028
--- /dev/null
@@ -0,0 +1,76 @@
+// Copyright (c) 2024 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TIZEN_SRC_CHROMIUM_IMPL_CONTENT_RENDERER_MEDIA_TIZEN_ELEMENTARY_MEDIA_STREAM_SOURCE_CONTROL_THREAD_MS_DECODING_STREAM_H_
+#define TIZEN_SRC_CHROMIUM_IMPL_CONTENT_RENDERER_MEDIA_TIZEN_ELEMENTARY_MEDIA_STREAM_SOURCE_CONTROL_THREAD_MS_DECODING_STREAM_H_
+
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "base/callback.h"
+#include "base/functional/callback_helpers.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/task/single_thread_task_runner.h"
+#include "base/time/time.h"
+#include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/common_types.h"
+#include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/demuxer_dispatcher.h"
+#include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/demuxer_params.h"
+#include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/lockable_demuxer_state.h"
+#include "content/renderer/media/tizen/elementary_media_stream_source/control_thread/demuxer.h"
+#include "content/renderer/media/tizen/elementary_media_stream_source/control_thread/demuxer_dispatcher_client.h"
+#include "content/renderer/media/tizen/elementary_media_stream_source/control_thread/platform_demuxer_adapter_client.h"
+#include "content/renderer/media/tizen/elementary_media_stream_source/control_thread/platform_demuxer_adapter_client.h"
+
+namespace content {
+namespace elementary_media_stream_source {
+namespace control_thread {
+
+class MsDecodingStream : public Demuxer,
+                    public DemuxerDispatcherClient,
+                    public PlatformDemuxerAdapterClient,
+                    public std::enable_shared_from_this<MsDecodingStream> {
+ public:
+  explicit MsDecodingStream(any_thread::DemuxerParams);
+
+  ~MsDecodingStream() override;
+
+  // Demuxer
+  void NotifyDemuxerInitialized() override;
+  void OnBufferedTimeRangesChanged(media::Ranges<base::TimeDelta>&&) override;
+  void OnDemuxerSeekDone(base::TimeDelta, uint32_t session_id) override;
+  void OnPipelineClosed() override;
+  void OnPipelineResuming() override;
+  void OnPipelineSuspended() override;
+  void SetDuration(base::TimeDelta) override;
+  void OnSessionIdChange(uint32_t session_id) override;
+
+  // DemuxerDispatcherClient
+  void OnClosedCaptions(std::vector<uint8_t> closed_captions) override;
+  void OnPlayerError(BackendError,
+                     std::string message,
+                     base::OnceClosure on_error_reported) override;
+  void OnResumeComplete() override;
+
+  // PlatformDemuxerAdapterClient
+  void CancelPendingSeek(base::TimeDelta seek_time) override;
+  void RegisterSource(std::shared_ptr<DemuxerClient>) override;
+  void Stop() override;
+  void StartSeek(base::TimeDelta seek_time,
+                         base::OnceClosure on_seek_done) override;
+  void StartWaitingForSeek(base::TimeDelta seek_time) override;
+
+ private:
+  const PipelineMode pipeline_mode_;
+
+  std::weak_ptr<DemuxerClient> client_;
+  std::weak_ptr<any_thread::DemuxerDispatcher> dispatcher_;
+};
+
+}  // namespace control_thread
+}  // namespace elementary_media_stream_source
+}  // namespace content
+
+#endif  // TIZEN_SRC_CHROMIUM_IMPL_CONTENT_RENDERER_MEDIA_TIZEN_ELEMENTARY_MEDIA_STREAM_SOURCE_CONTROL_THREAD_MS_DECODING_STREAM_H_
index a8ac0e3330a498a37cd101a3381d65f88cc2d58c..ccdbd5b48869f52ab2c767ab11508d0da1e33220 100644 (file)
@@ -470,6 +470,26 @@ CallbackResult SourceImpl::SetSourceOpened() {
   return result;
 }
 
+void SourceImpl::SetMediaStreamAudioTrackSink(
+    std::shared_ptr<blink::WebElementaryMediaTrackMsAudioSink> audio_sink) {
+  EMSS_DEBUG();
+
+  if (auto dispatcher = dispatcher_.lock())
+    dispatcher->DispatchTask(
+        &worker_thread::SourceDispatcherClient::SetMediaStreamAudioTrackSink,
+        std::move(audio_sink));
+}
+
+void SourceImpl::SetMediaStreamVideoTrackSink(
+    std::shared_ptr<blink::WebElementaryMediaTrackMsVideoSink> video_sink) {
+  EMSS_DEBUG();
+
+  if (auto dispatcher = dispatcher_.lock())
+    dispatcher->DispatchTask(
+        &worker_thread::SourceDispatcherClient::SetMediaStreamVideoTrackSink,
+        std::move(video_sink));
+}
+
 //////////////////// private ////////////////////
 
 uint32_t SourceImpl::GenerateNextInputSessionId() {
index 5904fa078eb19d87f0fd7780cb79624643c22066..a437a9eca0239fec2e57461ceb6fb591d83a4cea 100644 (file)
@@ -74,6 +74,10 @@ class SourceImpl : public DemuxerClient,
   void SetDuration(double) override;
   OperationCallbackResult SetSourceClosed() override;
   OperationCallbackResult SetSourceOpened() override;
+  void SetMediaStreamAudioTrackSink(
+      std::shared_ptr<blink::WebElementaryMediaTrackMsAudioSink>) override;
+  void SetMediaStreamVideoTrackSink(
+      std::shared_ptr<blink::WebElementaryMediaTrackMsVideoSink>) override;
 
  private:
   uint32_t GenerateNextInputSessionId();
index 2a868f9651c6d15a58d2dd14aceba0e2cf73a3e7..6bf2bb016dcecd83766ca93611c147cc0fe8fd82 100644 (file)
@@ -8,6 +8,7 @@ import(
 elementary_media_stream_source_renderer("worker_thread") {
   sources = [
     "append_client.h",
+    "append_host.cc",
     "append_host.h",
     "audio_track_impl.cc",
     "audio_track_impl.h",
@@ -21,6 +22,8 @@ elementary_media_stream_source_renderer("worker_thread") {
     "enable_dispatcher.h",
     "media_stream_demuxer_impl.cc",
     "media_stream_demuxer_impl.h",
+    "ms_decoding_stream.cc",
+    "ms_decoding_stream.h",
     "pending_data_stream_src_interfaces.h",
     "platform_demuxer_adapter_client.h",
     "source.h",
diff --git a/tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/worker_thread/append_host.cc b/tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/worker_thread/append_host.cc
new file mode 100644 (file)
index 0000000..553790b
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright (c) 2020 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/tizen/elementary_media_stream_source/worker_thread/append_host.h"
+
+#include "services/elementary_media_stream_source/public/cpp/logger.h"
+
+namespace content {
+namespace elementary_media_stream_source {
+namespace worker_thread {
+
+void AppendHost::SetAudioSink(
+    std::shared_ptr<blink::WebElementaryMediaTrackMsAudioSink>) {
+  EMSS_LOG_ASSERT(false) << "Not implemented?";
+}
+
+void AppendHost::SetVideoSink(
+    std::shared_ptr<blink::WebElementaryMediaTrackMsVideoSink>) {
+  EMSS_LOG_ASSERT(false) << "Not implemented?";
+}
+
+}  // namespace worker_thread
+}  // namespace elementary_media_stream_source
+}  // namespace content
\ No newline at end of file
index 6fe1a5bbe2fd6bc51cc914464dca300161a74b31..7d73e49cf37c00bdc9ce021503888d3b4639dc10 100644 (file)
 #include "tizen_src/chromium_impl/services/elementary_media_stream_source/public/mojom/elementary_media_packet.mojom-forward.h"
 #include "tizen_src/chromium_impl/services/elementary_media_stream_source/public/mojom/video_track_config.mojom-forward.h"
 
+namespace blink {
+class WebElementaryMediaTrackMsAudioSink;
+class WebElementaryMediaTrackMsVideoSink;
+}  // namespace blink
+
 namespace content {
 namespace elementary_media_stream_source {
 namespace worker_thread {
@@ -36,6 +41,10 @@ class AppendHost {
   virtual void OnReadConfig(AudioTrackConfigPtr) = 0;
   virtual void OnReadConfig(VideoTrackConfigPtr) = 0;
   virtual void OnReadMediaPackets(TrackType, std::vector<Packet>) = 0;
+  virtual void SetAudioSink(
+      std::shared_ptr<blink::WebElementaryMediaTrackMsAudioSink>);
+  virtual void SetVideoSink(
+      std::shared_ptr<blink::WebElementaryMediaTrackMsVideoSink>);
 
  protected:
   AppendHost() = default;
index c232997563103048e244439ab6dcf944dd63921c..df44d1ec2a9442bc8efe16f3328df9e7ff4ea4f1 100644 (file)
@@ -245,7 +245,7 @@ void DataStreamDemuxerImpl::OnBufferedTimeRangesChanged(
         std::move(buffered_time_ranges));
 }
 
-void DataStreamDemuxerImpl::OnInitialConfigReadyForDataStream(
+void DataStreamDemuxerImpl::OnInitialConfigReady(
     const MaybeAudioConfig& audio_config,
     const MaybeVideoConfig& video_config) {
   EMSS_DEBUG();
index 0d7a39f0018f5f15798ea117ec69581fd21eb061..1b8a2207e704977b0920a29cffd8326d32fff2c1 100644 (file)
@@ -82,8 +82,8 @@ class DataStreamDemuxerImpl
   // Demuxer
   std::shared_ptr<AppendHost> GetAppendHost(TrackType) override;
   void OnBufferedTimeRangesChanged(media::Ranges<base::TimeDelta>&&) override;
-  void OnInitialConfigReadyForDataStream(const MaybeAudioConfig&,
-                                         const MaybeVideoConfig&) override;
+  void OnInitialConfigReady(const MaybeAudioConfig&,
+                            const MaybeVideoConfig&) override;
   void SetAppendClient(TrackType, std::shared_ptr<AppendClient>) override;
   void SetVideoTextureClient(std::shared_ptr<VideoTextureClient>) override;
 
index d5416105abe11ddc2d850d7c437ac5df38577c97..628ea91a5798bcb282a60c8e3413a1475d488167 100644 (file)
@@ -27,8 +27,8 @@ class Demuxer {
   virtual std::shared_ptr<AppendHost> GetAppendHost(TrackType) = 0;
   virtual void OnBufferedTimeRangesChanged(
       media::Ranges<base::TimeDelta>&&) = 0;
-  virtual void OnInitialConfigReadyForDataStream(const MaybeAudioConfig&,
-                                                 const MaybeVideoConfig&) = 0;
+  virtual void OnInitialConfigReady(const MaybeAudioConfig&,
+                                    const MaybeVideoConfig&) = 0;
   virtual void SetAppendClient(TrackType, std::shared_ptr<AppendClient>) = 0;
   virtual void SetVideoTextureClient(std::shared_ptr<VideoTextureClient>) = 0;
 
index 938086a33d01dc36b5022df4fb3fe99461ad3c10..59b5a99e0921f0831d08477c53c22b5e32117e9f 100644 (file)
@@ -53,9 +53,8 @@ void MediaStreamDemuxerImpl::OnBufferedTimeRangesChanged(
         std::move(buffered_time_ranges));
 }
 
-void MediaStreamDemuxerImpl::OnInitialConfigReadyForDataStream(
-    const MaybeAudioConfig&,
-    const MaybeVideoConfig&) {
+void MediaStreamDemuxerImpl::OnInitialConfigReady(const MaybeAudioConfig&,
+                                                  const MaybeVideoConfig&) {
   EMSS_LOG_ASSERT(pipeline_mode_.demuxer_mode == DemuxerMode::kDataStream)
       << "Should not be called in " << pipeline_mode_.demuxer_mode;
 }
index a19e7ea401ed8d79a08af390fa8e9e50c0a2c7e9..257a1da491b1267c3f27d497fcbafb884a4a2c47 100644 (file)
@@ -40,8 +40,8 @@ class MediaStreamDemuxerImpl
   // Demuxer
   std::shared_ptr<AppendHost> GetAppendHost(TrackType) override;
   void OnBufferedTimeRangesChanged(media::Ranges<base::TimeDelta>&&) override;
-  void OnInitialConfigReadyForDataStream(const MaybeAudioConfig&,
-                                         const MaybeVideoConfig&) override;
+  void OnInitialConfigReady(const MaybeAudioConfig&,
+                            const MaybeVideoConfig&) override;
   void SetAppendClient(TrackType, std::shared_ptr<AppendClient>) override;
   void SetVideoTextureClient(std::shared_ptr<VideoTextureClient>) override;
 
diff --git a/tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/worker_thread/ms_decoding_stream.cc b/tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/worker_thread/ms_decoding_stream.cc
new file mode 100644 (file)
index 0000000..b7bd929
--- /dev/null
@@ -0,0 +1,424 @@
+// Copyright (c) 2024 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "content/renderer/media/tizen/elementary_media_stream_source/worker_thread/ms_decoding_stream.h"
+
+#include "base/functional/callback_helpers.h"
+#include "base/task/sequenced_task_runner.h"
+#include "content/renderer/media/tizen/elementary_media_stream_source/control_thread/demuxer_dispatcher_client.h"
+#include "content/renderer/media/tizen/elementary_media_stream_source/worker_thread/demuxer_client.h"
+#include "media/base/bind_to_current_loop.h"
+#include "media/base/media_util.h"
+#include "media/video/gpu_video_accelerator_factories.h"
+#include "services/elementary_media_stream_source/public/cpp/logger.h"
+#include "services/elementary_media_stream_source/public/cpp/mojom_type_exports.h"
+#include "third_party/blink/public/platform/platform.h"
+#include "third_party/blink/renderer/platform/elementary_media_stream_source/web_elementary_media_track_ms_audio_sink.h"
+#include "third_party/blink/renderer/platform/elementary_media_stream_source/web_elementary_media_track_ms_video_sink.h"
+
+namespace media {
+
+#define ENUM_VALUE_TO_OSTREAM(os, enum_value) \
+  case (enum_value):                          \
+    os << (#enum_value);                      \
+    break
+
+std::ostream& operator<<(std::ostream& os, WaitingReason value) {
+  switch (value) {
+    ENUM_VALUE_TO_OSTREAM(os, WaitingReason::kNoCdm);
+    ENUM_VALUE_TO_OSTREAM(os, WaitingReason::kNoDecryptionKey);
+    ENUM_VALUE_TO_OSTREAM(os, WaitingReason::kDecoderStateLost);
+  }
+  return os;
+}
+
+}  // namespace media
+
+namespace content {
+namespace elementary_media_stream_source {
+namespace worker_thread {
+
+namespace {
+
+void OnRequestOverlayInfo(bool decoder_requires_restart_for_overlay,
+                          media::ProvideOverlayInfoCB overlay_info_cb) {
+  // Android overlays are not supported.
+  if (overlay_info_cb)
+    std::move(overlay_info_cb).Run(media::OverlayInfo());
+}
+
+}  // anonymous namespace
+
+//////////////////////// MsDecodingStream::VideoStream: ////////////////////////
+
+class MsDecodingStream::VideoStream {
+ public:
+  VideoStream(
+      MsDecodingStream* parent,
+      media::MediaLog* media_log,
+      std::shared_ptr<blink::WebElementaryMediaTrackMsVideoSink> video_sink);
+  ~VideoStream();
+
+  void DecodeFrames(std::vector<Packet> frames);
+  void SetGpuFactories(media::GpuVideoAcceleratorFactories* gpu_factories);
+  void StartInitializingVideoDecoder(const media::VideoDecoderConfig&);
+
+ private:
+  static std::unique_ptr<media::VideoDecoder>
+  CreateVideoDecoderOnGpuFactoriesThread(
+      media::GpuVideoAcceleratorFactories* gpu_factories,
+      media::MediaLog* media_log);
+  void OnVideoDecoderCreated(std::unique_ptr<media::VideoDecoder>);
+  void OnVideoDecoderInitialized(std::unique_ptr<media::VideoDecoder>,
+                                 media::DecoderStatus);
+  void OnVideoDecoderWaiting(media::WaitingReason);
+
+  bool HasDecodingSlots() const;
+  void TryProcessPendingVideoDecodes();
+  void EnqueueVideoFrameForDecoding(scoped_refptr<media::DecoderBuffer>);
+  void DoDecodeVideoFrame(scoped_refptr<media::DecoderBuffer>);
+  void OnDecodeVideoFrameDone(media::DecoderStatus);
+  void OnVideoFrameDecoded(scoped_refptr<media::VideoFrame>);
+
+  MsDecodingStream* parent_;
+  media::MediaLog* media_log_;
+
+  std::optional<media::VideoDecoderConfig> video_config_;
+  std::unique_ptr<media::VideoDecoder> video_decoder_;
+  std::shared_ptr<blink::WebElementaryMediaTrackMsVideoSink> video_sink_;
+  int32_t ongoing_decodes_{0};
+  std::queue<scoped_refptr<media::DecoderBuffer>> pending_decodes_;
+
+  media::GpuVideoAcceleratorFactories* gpu_factories_{nullptr};
+  base::OnceClosure on_got_gpu_factories_;
+
+  base::WeakPtrFactory<VideoStream> weak_ptr_factory_;
+};  // class MsDecodingStream::VideoStream
+
+MsDecodingStream::VideoStream::VideoStream(
+    MsDecodingStream* parent,
+    media::MediaLog* media_log,
+    std::shared_ptr<blink::WebElementaryMediaTrackMsVideoSink> video_sink)
+    : parent_(parent),
+      media_log_(media_log),
+      video_sink_(std::move(video_sink)),
+      weak_ptr_factory_(this) {
+  EMSS_DEBUG() << "Constructing object";
+}
+
+MsDecodingStream::VideoStream::~VideoStream() {
+  EMSS_DEBUG() << "Destructingg object";
+}
+
+void MsDecodingStream::VideoStream::DecodeFrames(std::vector<Packet> frames) {
+  EMSS_VERBOSE() << frames.size();
+
+  for (auto& frame : frames) {
+    auto media_packet = frame.leak_media_packet();
+    EnqueueVideoFrameForDecoding(std::move(media_packet.buffer));
+  }
+  if (!pending_decodes_.empty())
+    TryProcessPendingVideoDecodes();
+}
+
+void MsDecodingStream::VideoStream::SetGpuFactories(
+    media::GpuVideoAcceleratorFactories* gpu_factories) {
+  EMSS_DEBUG() << gpu_factories;
+
+  gpu_factories_ = gpu_factories;
+
+  if (on_got_gpu_factories_)
+    std::move(on_got_gpu_factories_).Run();
+}
+
+void MsDecodingStream::VideoStream::StartInitializingVideoDecoder(
+    const media::VideoDecoderConfig& video_conf) {
+  EMSS_LOG(INFO) << video_conf.AsHumanReadableString();
+
+  if (!gpu_factories_) {
+    EMSS_LOG(INFO) << "Waiting for GPU Factories to become available...";
+    on_got_gpu_factories_ = base::BindOnce(
+        &MsDecodingStream::VideoStream::StartInitializingVideoDecoder,
+        weak_ptr_factory_.GetWeakPtr(), video_conf);
+    return;
+  }
+
+  if (!gpu_factories_->IsDecoderSupportKnown()) {
+    EMSS_LOG(INFO)
+        << "Waiting for GPU Factories to establish supported decoders...";
+    gpu_factories_->NotifyDecoderSupportKnown(base::BindOnce(
+        &MsDecodingStream::VideoStream::StartInitializingVideoDecoder,
+        weak_ptr_factory_.GetWeakPtr(), video_conf));
+    return;
+  }
+
+  if (gpu_factories_->IsDecoderConfigSupportedOrUnknown(video_conf) !=
+      media::GpuVideoAcceleratorFactories::Supported::kTrue) {
+    EMSS_LOG(ERROR) << "Video config not supported?";
+    parent_->EmitError(BackendError::kConfigError, "Config not supported");
+    return;
+  }
+
+  video_config_ = video_conf;
+  gpu_factories_->GetTaskRunner()->PostTaskAndReplyWithResult(
+      FROM_HERE,
+      base::BindOnce(&MsDecodingStream::VideoStream::
+                         CreateVideoDecoderOnGpuFactoriesThread,
+                     gpu_factories_, media_log_),
+      base::BindOnce(&MsDecodingStream::VideoStream::OnVideoDecoderCreated,
+                     weak_ptr_factory_.GetWeakPtr()));
+}
+
+// static
+std::unique_ptr<media::VideoDecoder>
+MsDecodingStream::VideoStream::CreateVideoDecoderOnGpuFactoriesThread(
+    media::GpuVideoAcceleratorFactories* gpu_factories,
+    media::MediaLog* media_log) {
+  EMSS_DEBUG_NO_INSTANCE();
+  return gpu_factories->CreateVideoDecoder(
+      media_log, base::BindRepeating(&OnRequestOverlayInfo));
+}
+
+void MsDecodingStream::VideoStream::OnVideoDecoderCreated(
+    std::unique_ptr<media::VideoDecoder> video_decoder) {
+  EMSS_DEBUG();
+
+  auto* decoder_ptr = video_decoder.get();
+  decoder_ptr->Initialize(
+      *video_config_, /* low_delay */ true, /* cdm_context */ nullptr,
+      base::BindOnce(&MsDecodingStream::VideoStream::OnVideoDecoderInitialized,
+                     weak_ptr_factory_.GetWeakPtr(), std::move(video_decoder)),
+      base::BindRepeating(&MsDecodingStream::VideoStream::OnVideoFrameDecoded,
+                          weak_ptr_factory_.GetWeakPtr()),
+      base::BindRepeating(&MsDecodingStream::VideoStream::OnVideoDecoderWaiting,
+                          weak_ptr_factory_.GetWeakPtr()));
+}
+
+void MsDecodingStream::VideoStream::OnVideoDecoderInitialized(
+    std::unique_ptr<media::VideoDecoder> video_decoder,
+    media::DecoderStatus status) {
+  EMSS_DEBUG();
+
+  if (!status.is_ok()) {
+    const auto error_msg =
+        std::string{"Failed to initialize video decoder: "} + status.message();
+    EMSS_LOG(ERROR) << error_msg;
+    parent_->EmitError(BackendError::kPipelineError, error_msg);
+    return;
+  }
+
+  video_decoder_ = std::move(video_decoder);
+
+  TryProcessPendingVideoDecodes();
+}
+
+void MsDecodingStream::VideoStream::OnVideoDecoderWaiting(
+    media::WaitingReason reason) {
+  EMSS_LOG(WARNING) << "Decoder is waiting: " << reason;
+}
+
+bool MsDecodingStream::VideoStream::HasDecodingSlots() const {
+  return video_decoder_ &&
+         ongoing_decodes_ < video_decoder_->GetMaxDecodeRequests();
+}
+
+void MsDecodingStream::VideoStream::TryProcessPendingVideoDecodes() {
+  EMSS_DEBUG() << "pending decodes = " << pending_decodes_.size()
+               << ", ongoing decodes = " << ongoing_decodes_;
+  while (!pending_decodes_.empty() && HasDecodingSlots()) {
+    auto frame = std::move(pending_decodes_.front());
+    pending_decodes_.pop();
+    DoDecodeVideoFrame(std::move(frame));
+  }
+}
+
+void MsDecodingStream::VideoStream::EnqueueVideoFrameForDecoding(
+    scoped_refptr<media::DecoderBuffer> frame) {
+  if (pending_decodes_.empty() && HasDecodingSlots()) {
+    // This is the default code path. We expect frames in low latency to be
+    // immediately after they arrive when playback progresses normally. Frames
+    // should leave decoder before all decoding slots are taken.
+    DoDecodeVideoFrame(std::move(frame));
+    return;
+  }
+
+  EMSS_DEBUG();
+  pending_decodes_.push(std::move(frame));
+}
+
+void MsDecodingStream::VideoStream::DoDecodeVideoFrame(
+    scoped_refptr<media::DecoderBuffer> frame) {
+  EMSS_DEBUG() << frame->AsHumanReadableString();
+
+  ++ongoing_decodes_;
+  video_decoder_->Decode(
+      std::move(frame),
+      base::BindOnce(&MsDecodingStream::VideoStream::OnDecodeVideoFrameDone,
+                     weak_ptr_factory_.GetWeakPtr()));
+}
+
+void MsDecodingStream::VideoStream::OnDecodeVideoFrameDone(
+    media::DecoderStatus status) {
+  EMSS_VERBOSE();
+
+  --ongoing_decodes_;
+
+  if (!status.is_ok()) {
+    const auto error_msg =
+        std::string{"Video decoding error: "} + status.message();
+    EMSS_LOG(ERROR) << error_msg;
+    parent_->EmitError(BackendError::kPipelineError, error_msg);
+    return;
+  }
+
+  if (!pending_decodes_.empty())
+    TryProcessPendingVideoDecodes();
+}
+
+void MsDecodingStream::VideoStream::OnVideoFrameDecoded(
+    scoped_refptr<media::VideoFrame> frame) {
+  EMSS_VERBOSE() << frame->AsHumanReadableString();
+
+  video_sink_->AppendPacket(std::move(frame));
+}
+
+////////////////////////////// MsDecodingStream: ///////////////////////////////
+
+MsDecodingStream::MsDecodingStream(any_thread::DemuxerParams params)
+    : dispatcher_(std::move(params.dispatcher)),
+      // FIXME(p.balut): provide actual media log
+      media_log_(std::make_unique<media::NullMediaLog>()) {
+  EMSS_DEBUG() << "Constructing object";
+}
+
+MsDecodingStream::~MsDecodingStream() {
+  EMSS_DEBUG() << "Destructing object";
+}
+
+void MsDecodingStream::SetGpuFactories(
+    media::GpuVideoAcceleratorFactories* gpu_factories) {
+  EMSS_DEBUG() << gpu_factories;
+
+  gpu_factories_ = gpu_factories;
+
+  if (video_stream_)
+    video_stream_->SetGpuFactories(gpu_factories);
+}
+
+void MsDecodingStream::SetAudioSink(
+    std::shared_ptr<blink::WebElementaryMediaTrackMsAudioSink>) {
+  EMSS_DEBUG();
+  EmitError(BackendError::kConfigError, "Audio support not implemented yet.");
+}
+
+void MsDecodingStream::SetVideoSink(
+    std::shared_ptr<blink::WebElementaryMediaTrackMsVideoSink> video_sink) {
+  EMSS_DEBUG();
+
+  video_stream_ = std::make_unique<VideoStream>(this, media_log_.get(),
+                                                std::move(video_sink));
+
+  if (gpu_factories_)
+    video_stream_->SetGpuFactories(gpu_factories_);
+}
+
+//////////////////// Demuxer: ////////////////////
+
+std::shared_ptr<AppendHost> MsDecodingStream::GetAppendHost(TrackType) {
+  EMSS_VERBOSE();
+
+  return shared_from_this();
+}
+
+void MsDecodingStream::OnBufferedTimeRangesChanged(
+    media::Ranges<base::TimeDelta>&&) {}
+
+void MsDecodingStream::OnInitialConfigReady(
+    const MaybeAudioConfig& maybe_audio_conf,
+    const MaybeVideoConfig& maybe_video_conf) {
+  if (maybe_video_conf) {
+    EMSS_LOG_ASSERT(!!video_stream_) << "Video decoding stream should've been "
+                                        "set by now if video track is present";
+    video_stream_->StartInitializingVideoDecoder(
+        *std::get<std::unique_ptr<media::VideoDecoderConfig>>(
+            *maybe_video_conf));
+  }
+}
+
+void MsDecodingStream::SetAppendClient(TrackType,
+                                       std::shared_ptr<AppendClient>) {
+  EMSS_DEBUG();
+}
+
+void MsDecodingStream::SetVideoTextureClient(
+    std::shared_ptr<VideoTextureClient>) {
+  EMSS_LOG(ERROR) << "FIXME(p.balut): Not implemented!";
+  EmitError(BackendError::kUnknownError, "Not implemented");
+}
+
+//////////////////// DemuxerDispatcherClient: ////////////////////
+
+void MsDecodingStream::OnPipelineResuming() {}
+
+void MsDecodingStream::OnPipelineSuspended() {}
+
+void MsDecodingStream::OnReadRequested(TrackType) {}
+
+void MsDecodingStream::OnSeekDone(base::TimeDelta new_time,
+                                  uint32_t session_id) {}
+
+void MsDecodingStream::OnSessionIdChange(uint32_t session_id) {}
+
+//////////////////// AppendHost: ////////////////////
+
+void MsDecodingStream::NotifyFramerateSet(
+    const media::StreamFramerate::Framerate& framerate) {}
+
+void MsDecodingStream::OnReadConfig(AudioTrackConfigPtr) {}
+
+void MsDecodingStream::OnReadConfig(VideoTrackConfigPtr) {}
+
+void MsDecodingStream::OnReadMediaPackets(TrackType type,
+                                          std::vector<Packet> frames) {
+  EMSS_DEBUG() << "Got " << frames.size() << " " << type << " frames";
+
+  switch (type) {
+    case TrackType::kAudio:
+      break;
+    case TrackType::kVideo:
+      EMSS_LOG_ASSERT(!!video_stream_)
+          << "Video decoding stream should've been set by now if video track "
+             "is present";
+      video_stream_->DecodeFrames(std::move(frames));
+      break;
+  }
+}
+
+//////////////////// own private methods: ////////////////////
+
+void MsDecodingStream::EmitError(BackendError backend_error,
+                                 const std::string& message) {
+  EMSS_LOG(ERROR) << "error: " << backend_error << " message: '" << message
+                  << "'";
+
+  if (auto demuxer_dispatcher = dispatcher_.lock()) {
+    demuxer_dispatcher->DispatchTask(
+        &control_thread::DemuxerDispatcherClient::OnPlayerError, backend_error,
+        std::string{message}, base::DoNothing());
+  }
+}
+
+// PlatformDemuxerAdapterClient:
+void MsDecodingStream::RegisterSource(std::shared_ptr<DemuxerClient> client,
+                                      base::OnceClosure on_source_registered) {
+  EMSS_DEBUG();
+
+  client->RegisterDemuxer(shared_from_this());
+
+  std::move(on_source_registered).Run();
+}
+
+}  // namespace worker_thread
+}  // namespace elementary_media_stream_source
+}  // namespace content
diff --git a/tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/worker_thread/ms_decoding_stream.h b/tizen_src/chromium_impl/content/renderer/media/tizen/elementary_media_stream_source/worker_thread/ms_decoding_stream.h
new file mode 100644 (file)
index 0000000..8dbcfcc
--- /dev/null
@@ -0,0 +1,94 @@
+// Copyright (c) 2024 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <queue>
+
+#include "base/functional/callback_forward.h"
+#include "base/memory/weak_ptr.h"
+#include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/demuxer_dispatcher.h"
+#include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/demuxer_params.h"
+#include "content/renderer/media/tizen/elementary_media_stream_source/worker_thread/append_host.h"
+#include "content/renderer/media/tizen/elementary_media_stream_source/worker_thread/demuxer.h"
+#include "content/renderer/media/tizen/elementary_media_stream_source/worker_thread/demuxer_dispatcher_client.h"
+#include "content/renderer/media/tizen/elementary_media_stream_source/worker_thread/platform_demuxer_adapter_client.h"
+#include "media/base/media_log.h"
+#include "media/base/video_decoder.h"
+#include "media/video/gpu_video_accelerator_factories.h"
+
+namespace blink {
+class WebElementaryMediaTrackMsAudioSink;
+class WebElementaryMediaTrackMsVideoSink;
+}  // namespace blink
+
+namespace media {
+class GpuVideoAcceleratorFactories;
+}
+
+namespace content {
+namespace elementary_media_stream_source {
+namespace worker_thread {
+
+// AppendHost used when EMSS acts as source for media streams.
+//
+// Contrary to modes that use demuxer (DataStream or media::Demuxer), this class
+// wraps sinks that transfer data back to blink:: realm, where it is consumed by
+// media streams implementation (WebPlatformMediaStreamSource derivatives).
+class MsDecodingStream : public Demuxer,
+                         public DemuxerDispatcherClient,
+                         public AppendHost,
+                         public PlatformDemuxerAdapterClient,
+                         public std::enable_shared_from_this<MsDecodingStream> {
+ public:
+  explicit MsDecodingStream(any_thread::DemuxerParams params);
+  ~MsDecodingStream() override;
+
+  void SetGpuFactories(media::GpuVideoAcceleratorFactories* gpu_factories);
+
+  // Demuxer:
+  std::shared_ptr<AppendHost> GetAppendHost(TrackType) override;
+  void OnBufferedTimeRangesChanged(media::Ranges<base::TimeDelta>&&) override;
+  void OnInitialConfigReady(const MaybeAudioConfig&,
+                            const MaybeVideoConfig&) override;
+  void SetAppendClient(TrackType, std::shared_ptr<AppendClient>) override;
+  void SetVideoTextureClient(std::shared_ptr<VideoTextureClient>) override;
+
+  // DemuxerDispatcherClient:
+  void OnPipelineResuming() override;
+  void OnPipelineSuspended() override;
+  void OnReadRequested(TrackType) override;
+  void OnSeekDone(base::TimeDelta new_time, uint32_t session_id) override;
+  void OnSessionIdChange(uint32_t session_id) override;
+
+  // AppendHost:
+  void NotifyFramerateSet(
+      const media::StreamFramerate::Framerate& framerate) override;
+  void OnReadConfig(AudioTrackConfigPtr) override;
+  void OnReadConfig(VideoTrackConfigPtr) override;
+  void OnReadMediaPackets(TrackType, std::vector<Packet>) override;
+  void SetAudioSink(
+      std::shared_ptr<blink::WebElementaryMediaTrackMsAudioSink>) override;
+  void SetVideoSink(
+      std::shared_ptr<blink::WebElementaryMediaTrackMsVideoSink>) override;
+
+  // PlatformDemuxerAdapterClient:
+  void RegisterSource(std::shared_ptr<DemuxerClient>,
+                      base::OnceClosure on_source_registered) override;
+
+ private:
+  using BackendError = ::elementary_media_stream_source::mojom::BackendError;
+
+  class VideoStream;
+
+  void EmitError(BackendError backend_error, const std::string& message);
+
+  std::unique_ptr<VideoStream> video_stream_;
+
+  std::weak_ptr<any_thread::DemuxerDispatcher> dispatcher_;
+  media::GpuVideoAcceleratorFactories* gpu_factories_{nullptr};
+  std::unique_ptr<media::MediaLog> media_log_;
+};
+
+}  // namespace worker_thread
+}  // namespace elementary_media_stream_source
+}  // namespace content
index fe4de93bc98963fd3f03df4e3361616afe58fc97..ca50bfc14eb7ea01a252864b2785b37bd3d0b2e7 100644 (file)
 #include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/common_types.h"
 #include "content/renderer/media/tizen/elementary_media_stream_source/worker_thread/enable_dispatcher.h"
 
+namespace blink {
+class WebElementaryMediaTrackMsAudioSink;
+class WebElementaryMediaTrackMsVideoSink;
+}  // namespace blink
+
 namespace content {
 
 namespace elementary_media_stream_source {
@@ -26,9 +31,12 @@ class SourceDispatcherClient : public EnableDispatcher {
   virtual ~SourceDispatcherClient() = default;
 
   virtual void BufferedRangesChanged() const = 0;
-  virtual void OnInitialConfigReadyForDataStream(MaybeAudioConfig,
-                                                 MaybeVideoConfig) = 0;
+  virtual void OnInitialConfigReady(MaybeAudioConfig, MaybeVideoConfig) = 0;
   virtual void RegisterClient(std::shared_ptr<SourceClient>) = 0;
+  virtual void SetMediaStreamAudioTrackSink(
+      std::shared_ptr<blink::WebElementaryMediaTrackMsAudioSink>) = 0;
+  virtual void SetMediaStreamVideoTrackSink(
+      std::shared_ptr<blink::WebElementaryMediaTrackMsVideoSink>) = 0;
 
  protected:
   SourceDispatcherClient() = default;
index 7c4e72367159d60d6e03fd3e5ea783f8961c76b0..d5260bf834feb7755491b45cca123ae18134e574 100644 (file)
@@ -9,6 +9,7 @@
 #include "base/time/time.h"
 #include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/common_tools.h"
 #include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/common_types.h"
+#include "content/renderer/media/tizen/elementary_media_stream_source/worker_thread/append_host.h"
 #include "content/renderer/media/tizen/elementary_media_stream_source/worker_thread/demuxer.h"
 #include "content/renderer/media/tizen/elementary_media_stream_source/worker_thread/source_client.h"
 #include "services/elementary_media_stream_source/public/cpp/logger.h"
@@ -72,15 +73,16 @@ void SourceImpl::BufferedRangesChanged() const {
 
 //////////////////// SourceDispatcherClient ////////////////////
 
-void SourceImpl::OnInitialConfigReadyForDataStream(
-    MaybeAudioConfig audio_config,
-    MaybeVideoConfig video_config) {
+void SourceImpl::OnInitialConfigReady(MaybeAudioConfig audio_config,
+                                      MaybeVideoConfig video_config) {
   EMSS_DEBUG();
-  EMSS_LOG_ASSERT(pipeline_mode_.demuxer_mode == DemuxerMode::kDataStream)
-      << "Should not be called in " << pipeline_mode_.demuxer_mode;
+  EMSS_LOG_ASSERT(pipeline_mode_.demuxer_mode != DemuxerMode::kMediaStream ||
+                  pipeline_mode_.latency_mode != LatencyMode::kNormal)
+      << "Should not be called in " << pipeline_mode_.demuxer_mode << " and "
+      << pipeline_mode_.latency_mode;
 
   if (auto demuxer = demuxer_.lock()) {
-    demuxer->OnInitialConfigReadyForDataStream(audio_config, video_config);
+    demuxer->OnInitialConfigReady(audio_config, video_config);
   }
 }
 
@@ -102,6 +104,24 @@ void SourceImpl::RegisterClient(std::shared_ptr<SourceClient> client) {
   }
 }
 
+void SourceImpl::SetMediaStreamAudioTrackSink(
+    std::shared_ptr<blink::WebElementaryMediaTrackMsAudioSink> audio_sink) {
+  EMSS_DEBUG();
+  if (auto demuxer = demuxer_.lock()) {
+    demuxer->GetAppendHost(TrackType::kAudio)
+        ->SetAudioSink(std::move(audio_sink));
+  }
+}
+
+void SourceImpl::SetMediaStreamVideoTrackSink(
+    std::shared_ptr<blink::WebElementaryMediaTrackMsVideoSink> video_sink) {
+  EMSS_DEBUG();
+  if (auto demuxer = demuxer_.lock()) {
+    demuxer->GetAppendHost(TrackType::kVideo)
+        ->SetVideoSink(std::move(video_sink));
+  }
+}
+
 }  // namespace worker_thread
 
 }  // namespace elementary_media_stream_source
index cd0276fe11f97126e7744e6329e7a1ca5b5791fe..db79bc93f65c8a6142e84deecfcc31feed9df886 100644 (file)
@@ -41,14 +41,18 @@ class SourceImpl : public DemuxerClient,
   void BufferedRangesChanged() const override;
 
   // SourceDispatcherClient
-  void OnInitialConfigReadyForDataStream(MaybeAudioConfig,
-                                         MaybeVideoConfig) override;
+  void OnInitialConfigReady(MaybeAudioConfig, MaybeVideoConfig) override;
   void RegisterClient(std::shared_ptr<SourceClient>) override;
+  void SetMediaStreamAudioTrackSink(
+      std::shared_ptr<blink::WebElementaryMediaTrackMsAudioSink>) override;
+  void SetMediaStreamVideoTrackSink(
+      std::shared_ptr<blink::WebElementaryMediaTrackMsVideoSink>) override;
 
  private:
+  const PipelineMode pipeline_mode_;
+
   std::array<std::weak_ptr<SourceClient>, (+TrackType::kMaxValue + 1)> clients_;
   std::weak_ptr<Demuxer> demuxer_;
-  const PipelineMode pipeline_mode_;
   std::shared_ptr<any_thread::LockableSourceState> state_;
 };
 
index 56c83b6464192db4f164d64b02cf5c135873f342..0354f10220e426619c239cf49a2f224de1bda7d1 100644 (file)
 #include "content/renderer/media/tizen/elementary_media_stream_source/worker_thread/enable_dispatcher.h"
 #include "media/base/decryptor.h"
 
+namespace blink {
+class WebElementaryMediaTrackMsAudioSink;
+class WebElementaryMediaTrackMsVideoSink;
+}  // namespace blink
+
 namespace content {
 
 namespace elementary_media_stream_source {
index 1cbd46bc763e331d079af37a78ffa1d24517bdc7..c816894610072dcd9dc49604f5349201fd4ede23 100644 (file)
@@ -26,7 +26,7 @@ class MockDemuxer : public Demuxer {
               (override));
 
   MOCK_METHOD(void,
-              OnInitialConfigReadyForDataStream,
+              OnInitialConfigReady,
               (const MaybeAudioConfig&, const MaybeVideoConfig&),
               (override));
   MOCK_METHOD(void,
index 0e962dd21360431b7f75d23270a704f555f03f1c..ec57a29fb22de54336ecb4a0c8c027db267dc5af 100644 (file)
@@ -17,10 +17,23 @@ namespace worker_thread {
 
 class MockSourceDispatcherClient : public SourceDispatcherClient {
  public:
-  MOCK_CONST_METHOD0(BufferedRangesChanged, void());
-  MOCK_METHOD2(OnInitialConfigReadyForDataStream,
-               void(MaybeAudioConfig, MaybeVideoConfig));
-  MOCK_METHOD1(RegisterClient, void(std::shared_ptr<SourceClient>));
+  MOCK_METHOD(void, BufferedRangesChanged, (), (const override));
+  MOCK_METHOD(void,
+              OnInitialConfigReady,
+              (MaybeAudioConfig, MaybeVideoConfig),
+              (override));
+  MOCK_METHOD(void,
+              RegisterClient,
+              (std::shared_ptr<SourceClient>),
+              (override));
+  MOCK_METHOD(void,
+              SetMediaStreamAudioTrackSink,
+              (std::shared_ptr<blink::WebElementaryMediaTrackMsAudioSink>),
+              (override));
+  MOCK_METHOD(void,
+              SetMediaStreamVideoTrackSink,
+              (std::shared_ptr<blink::WebElementaryMediaTrackMsVideoSink>),
+              (override));
 };
 
 }  // namespace worker_thread
index 0826b4d02d55cbe1686a768d859b9ae8ab64aa71..b708b5657d1f69ebb27b2a2e8c93b711100fb8ed 100644 (file)
@@ -588,8 +588,7 @@ TEST_F(WorkerThreadDemuxerImplNormalLatencyPlayerTest, RegisterSource) {
              std::static_pointer_cast<DemuxerClient>(demuxer_client_mock),
              std::move(emss_initialized_));
   FlushForTesting();
-  CallMethod(demuxer_,
-             &DataStreamDemuxerImpl::OnInitialConfigReadyForDataStream,
+  CallMethod(demuxer_, &DataStreamDemuxerImpl::OnInitialConfigReady,
              MaybeAudioConfig{},
              std::make_tuple(std::make_unique<media::VideoDecoderConfig>(),
                              DecodingMode::kHardware));
index f69d8be601baa01aaca2906b5dc85e2c686c7404..12f95eefc26e1c90ddb7dcf963fd43a863a393ab 100644 (file)
@@ -58,6 +58,10 @@ blink_modules_sources("elementary_media_stream_source") {
     "elementary_media_track_seek_event.h",
     "elementary_media_track_session_id_changed_event.cc",
     "elementary_media_track_session_id_changed_event.h",
+    "ms_audio_track_source.cc",
+    "ms_audio_track_source.h",
+    "ms_video_track_source.cc",
+    "ms_video_track_source.h",
     "same_thread_elementary_media_stream_source_attachment.cc",
     "same_thread_elementary_media_stream_source_attachment.h",
     "side_thread_elementary_media_track.cc",
index f19ec3aec208a7fece5cfd1477e9b743706abd12..3cfb8dd14be0702f376167f6a3b62c476f58351e 100644 (file)
@@ -16,6 +16,7 @@
 #include "media/base/audio_decoder_config.h"
 #include "media/base/media_track.h"
 #include "media/base/video_decoder_config.h"
+#include "platform/mediastream/media_stream_component.h"
 #include "services/elementary_media_stream_source/public/cpp/logger.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
 #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
@@ -34,6 +35,7 @@
 #include "third_party/blink/renderer/platform/bindings/exception_code.h"
 #include "third_party/blink/renderer/platform/bindings/exception_messages.h"
 #include "third_party/blink/renderer/platform/elementary_media_stream_source/web_elementary_media_track_dispatcher.h"
+#include "third_party/blink/renderer/platform/mediastream/media_stream_descriptor.h"
 
 // autogenerated headers
 #include "third_party/blink/renderer/bindings/modules/v8/v8_elementary_audio_stream_track_config.h"
@@ -562,6 +564,12 @@ ScriptPromise ElementaryMediaStreamSource::open(ScriptState* script_state) {
   auto result = web_elementary_media_stream_source_dispatcher_->RunTask(
       &WebElementaryMediaStreamSourceControl::SetSourceOpened);
 
+  if (load_deferred_until_source_open_cb_) {
+    EMSS_LOG(INFO) << "Triggering deferred web media player load...";
+    main_js_task_runner_->PostTask(
+        FROM_HERE, std::move(load_deferred_until_source_open_cb_));
+  }
+
   main_js_task_runner_->PostTask(
       FROM_HERE,
       base::BindOnce(
@@ -810,6 +818,13 @@ bool ElementaryMediaStreamSource::IsVideoTextureMode() const {
   return rendering_mode_ == RenderingModeVideoTextureKeyword();
 }
 
+void ElementaryMediaStreamSource::OnLoadDeferredUntilSourceOpen(
+    base::OnceClosure on_source_opened) {
+  EMSS_DEBUG();
+
+  load_deferred_until_source_open_cb_ = std::move(on_source_opened);
+}
+
 void ElementaryMediaStreamSource::OnPause() {
   EMSS_DEBUG();
 
@@ -980,6 +995,27 @@ void ElementaryMediaStreamSource::UpdatePlaybackPosition(
       playback_position, session_id);
 }
 
+MediaStreamDescriptor*
+ElementaryMediaStreamSource::GetMediaStreamDescriptorIfAvailable() {
+  EMSS_DEBUG();
+
+  const base::CommandLine& command_line =
+      *base::CommandLine::ForCurrentProcess();
+  const bool enable_ttvd =
+      command_line.HasSwitch(switches::kEnableUpstreamArchitecture);
+  if (!enable_ttvd || !IsLowLatencyMode()) {
+    EMSS_DEBUG() << "Not available!";
+    return nullptr;
+  }
+
+  if (media_stream_descriptor_)
+    return media_stream_descriptor_;
+
+  media_stream_descriptor_ = MakeGarbageCollected<MediaStreamDescriptor>(
+      MediaStreamComponentVector{}, MediaStreamComponentVector{});
+  return media_stream_descriptor_;
+}
+
 //////////////// EventTarget interface ////////////////
 
 ExecutionContext* ElementaryMediaStreamSource::GetExecutionContext() const {
@@ -1008,6 +1044,7 @@ void ElementaryMediaStreamSource::Trace(blink::Visitor* visitor) const {
   visitor->Trace(emss_tracer_);
   visitor->Trace(open_resolver_);
   visitor->Trace(video_tracks_);
+  visitor->Trace(media_stream_descriptor_);
   EventTargetWithInlineData::Trace(visitor);
   ExecutionContextLifecycleObserver::Trace(visitor);
 }
@@ -1191,6 +1228,24 @@ void ElementaryMediaStreamSource::Stop() {
   Detach();
 }
 
+//////////////// Media Stream support: ////////////////
+
+void ElementaryMediaStreamSource::SetMediaStreamAudioTrackSink(
+    std::shared_ptr<blink::WebElementaryMediaTrackMsAudioSink> audio_sink) {
+  EMSS_DEBUG();
+  web_elementary_media_stream_source_dispatcher_->RunTask(
+      &WebElementaryMediaStreamSourceControl::SetMediaStreamAudioTrackSink,
+      std::move(audio_sink));
+}
+
+void ElementaryMediaStreamSource::SetMediaStreamVideoTrackSink(
+    std::shared_ptr<blink::WebElementaryMediaTrackMsVideoSink> video_sink) {
+  EMSS_DEBUG();
+  web_elementary_media_stream_source_dispatcher_->RunTask(
+      &WebElementaryMediaStreamSourceControl::SetMediaStreamVideoTrackSink,
+      std::move(video_sink));
+}
+
 /////////////////////////////////// private ////////////////////////////////////
 
 ElementaryMediaStreamSource::ElementaryMediaStreamSource(
@@ -1211,7 +1266,8 @@ ElementaryMediaStreamSource::ElementaryMediaStreamSource(
       // Garbage-collector managed:
       close_resolver_(nullptr),
       emss_tracer_(nullptr),
-      open_resolver_(nullptr) {
+      open_resolver_(nullptr),
+      media_stream_descriptor_(nullptr) {
   EMSS_LOG(INFO) << "Constructing object, EMSS version = "
                  << ElementaryMediaStreamSourceVersion::GetApiVersion() << ", "
                  << latency_mode_ << ", " << rendering_mode_;
@@ -1313,6 +1369,10 @@ ElementaryMediaTrack* ElementaryMediaStreamSource::addVideoTrackCommon(
       std::move(web_elementary_video_track_dispatcher), this,
       active_decoding_mode);
   video_tracks_.push_back(video_track);
+  if (media_stream_descriptor_) {
+    media_stream_descriptor_->AddComponent(
+        video_track->GetMediaStreamComponent());
+  }
   return video_track;
 }
 
index c306cd4946d5806c1535627f42f7a7e161480cf0..ae462b68e08722483137d0d597cea89aca0cf1a5 100644 (file)
@@ -143,6 +143,7 @@ class ElementaryMediaStreamSource final
   bool IsGameMode() const;
   bool IsLowLatencyMode() const;
   bool IsVideoTextureMode() const;
+  void OnLoadDeferredUntilSourceOpen(base::OnceClosure on_source_opened);
   void OnPause();
   void OnPlay();
   void OnResume();
@@ -151,6 +152,7 @@ class ElementaryMediaStreamSource final
   WebTimeRanges BufferedInternal() const;
   WebTimeRanges SeekableInternal() const;
   void UpdatePlaybackPosition(double playback_position, uint32_t session_id);
+  MediaStreamDescriptor* GetMediaStreamDescriptorIfAvailable();
 
   // EventTarget interface
   ExecutionContext* GetExecutionContext() const override;
@@ -177,6 +179,12 @@ class ElementaryMediaStreamSource final
   void SetPlayerOpenedPending() override;
   void Stop() override;
 
+  // Media Stream support:
+  void SetMediaStreamAudioTrackSink(
+      std::shared_ptr<blink::WebElementaryMediaTrackMsAudioSink>);
+  void SetMediaStreamVideoTrackSink(
+      std::shared_ptr<blink::WebElementaryMediaTrackMsVideoSink>);
+
  private:
   ElementaryMediaTrack* addAudioTrackCommon(
       const ElementaryAudioStreamTrackConfig*,
@@ -203,6 +211,7 @@ class ElementaryMediaStreamSource final
   scoped_refptr<ElementaryMediaStreamSourceAttachment> emss_attachment_;
   bool is_suspended_;
   double last_known_playback_position_;
+  base::OnceClosure load_deferred_until_source_open_cb_;
   const scoped_refptr<base::SingleThreadTaskRunner> main_js_task_runner_;
   ReadyState ready_state_;
   uint32_t session_id_;
@@ -229,6 +238,10 @@ class ElementaryMediaStreamSource final
   Member<ScriptPromiseResolver> open_resolver_;
   HeapVector<Member<ElementaryMediaTrack>> video_tracks_;
 
+  // Media streams integration (used only when EMSS works with
+  // webmediaplayer_ms):
+  WeakMember<MediaStreamDescriptor> media_stream_descriptor_;
+
   friend std::ostream& operator<<(std::ostream& os, ReadyState seeking_status);
 };
 
index 2fdcc8ba06df06d3a4878c650fd1c7af6d20c93f..c040be4417f92c4e13f5bc9b7140b4eb185a4e77 100644 (file)
@@ -125,9 +125,9 @@ struct ElementaryMediaStreamSourceVersion {
             {kBaseEmss, true, 1},
             {kVideoTexture, !IsUsingTTvd(), 2},
             {kSoftwareDecoding, true, 3},
-            {kConstructWithModes, !IsUsingTTvd(), 4},
+            {kConstructWithModes, true, 4},
             {kLowLatencyVideoTexture, !IsUsingTTvd(), 4},
-            {kUltraLowLatency, !IsUsingTTvd(), 5},
+            {kUltraLowLatency, true, 5},
             {kConfigValidation, true, 6},
             {kBackendError, true, 7},
         }};
index 1c149d85b47a9a3993d4d0e5ee8c57277b5aa030..1f86bb9fcca1fb4322be7e2db92d877e5092cccc 100644 (file)
 #include "media/base/video_codecs.h"
 #include "media/base/video_decoder_config.h"
 #include "media/base/video_types.h"
+#include "modules/elementary_media_stream_source/ms_audio_track_source.h"
+#include "modules/elementary_media_stream_source/ms_video_track_source.h"
+#include "modules/mediastream/media_stream_video_track.h"
 #include "platform/bindings/exception_code.h"
+#include "platform/heap/garbage_collected.h"
+#include "platform/mediastream/media_stream_audio_track.h"
+#include "platform/mediastream/media_stream_component_impl.h"
 #include "services/elementary_media_stream_source/public/cpp/codec_capabilities.h"
 #include "services/elementary_media_stream_source/public/cpp/logger.h"
 #include "services/elementary_media_stream_source/public/cpp/mojom_type_exports.h"
@@ -106,6 +112,60 @@ constexpr const unsigned kMaxBufferedVideoFramesCount = 5;
 // layers.
 constexpr const auto kSyncAppendTimeoutMs = base::Milliseconds(2000);
 
+int32_t GetNextMsTrackUniqueId() {
+  static std::atomic<int32_t> unique_id = 0;
+  return unique_id.fetch_add(1);
+}
+
+String MakeMsTrackId(int32_t unique_id, ElementaryMediaTrack::TrackType type) {
+  std::ostringstream oss;
+  oss << (type == ElementaryMediaTrack::TrackType::kVideo ? "video" : "audio")
+      << "-elementary-track-" << unique_id;
+  const auto id_str = oss.str();
+  return {id_str.c_str(), id_str.size()};
+}
+
+std::tuple<MediaStreamComponent*,
+           std::shared_ptr<WebElementaryMediaTrackMsAudioSink>>
+CreateMsAudioComponent() {
+  const auto unique_id = GetNextMsTrackUniqueId();
+  const auto id =
+      MakeMsTrackId(unique_id, ElementaryMediaTrack::TrackType::kAudio);
+  auto track_source =
+      std::make_unique<MsAudioTrackSource>(base::ThreadTaskRunnerHandle::Get());
+  auto track = std::make_unique<MediaStreamAudioTrack>(
+      /* is_local_track */ false);
+  auto sink = track_source->GetAudioSink();
+  return {MakeGarbageCollected<MediaStreamComponentImpl>(
+              id,
+              MakeGarbageCollected<MediaStreamSource>(
+                  id, MediaStreamSource::kTypeAudio, id, /* remote */ true,
+                  std::move(track_source)),
+              std::move(track)),
+          std::move(sink)};
+}
+
+std::tuple<MediaStreamComponent*,
+           std::shared_ptr<WebElementaryMediaTrackMsVideoSink>>
+CreateMsVideoComponent() {
+  const auto unique_id = GetNextMsTrackUniqueId();
+  const auto id =
+      MakeMsTrackId(unique_id, ElementaryMediaTrack::TrackType::kVideo);
+  auto track_source =
+      std::make_unique<MsVideoTrackSource>(base::ThreadTaskRunnerHandle::Get());
+  auto track = std::make_unique<MediaStreamVideoTrack>(
+      track_source.get(), MediaStreamVideoSource::ConstraintsOnceCallback(),
+      true);
+  auto sink = track_source->GetVideoSink();
+  return {MakeGarbageCollected<MediaStreamComponentImpl>(
+              id,
+              MakeGarbageCollected<MediaStreamSource>(
+                  id, MediaStreamSource::kTypeVideo, id, /* remote */ true,
+                  std::move(track_source)),
+              std::move(track)),
+          std::move(sink)};
+}
+
 media::EncryptionScheme EncryptionModeAsEnum(
     const WTF::String& encryption_mode) {
   EMSS_VERBOSE_NO_INSTANCE();
@@ -635,7 +695,8 @@ ElementaryMediaTrack::ElementaryMediaTrack(
       // Garbage-collector managed:
       get_picture_resolver_(nullptr),
       source_(source),
-      video_texture_(nullptr) {
+      video_texture_(nullptr),
+      ms_component_(nullptr) {
   EMSS_DEBUG_TYPED() << "Constructing object";
 
   EMSS_LOG_ASSERT(source_);
@@ -669,6 +730,7 @@ void ElementaryMediaTrack::Trace(blink::Visitor* visitor) const {
   visitor->Trace(get_picture_resolver_);
   visitor->Trace(source_);
   visitor->Trace(video_texture_);
+  visitor->Trace(ms_component_);
   EventTargetWithInlineData::Trace(visitor);
   ActiveScriptWrappable<ElementaryMediaTrack>::Trace(visitor);
   ExecutionContextLifecycleObserver::Trace(visitor);
@@ -1117,6 +1179,12 @@ ElementaryMediaTrack::CreateVideoDecoderConfig(
       video_size,                                          // natural_size
       video_extra_data,
       EncryptionScheme::kUnencrypted};
+  video_decoder_config.set_is_rtc(emss_latency_mode !=
+                                  EmssLatencyMode::kNormal);
+#if defined(TIZEN_TV_UPSTREAM_MULTIMEDIA)
+  video_decoder_config.set_is_game_mode(emss_latency_mode ==
+                                        EmssLatencyMode::kUltraLow);
+#endif  // defined(TIZEN_TV_UPSTREAM_MULTIMEDIA)
 
 #if BUILDFLAG(IS_TIZEN_TV)
   int framerate_num = static_cast<int>(config->framerateNum());
@@ -1147,6 +1215,27 @@ double ElementaryMediaTrack::GetHighestBufferedPresentationTimestamp() const {
       &WebElementaryMediaTrackControl::GetHighestBufferedPresentationTimestamp);
 }
 
+MediaStreamComponent* ElementaryMediaTrack::GetMediaStreamComponent() {
+  if (ms_component_)
+    return ms_component_;
+
+  if (!web_elementary_media_track_dispatcher_) {
+    return nullptr;
+  }
+
+  if (Type() == TrackType::kVideo) {
+    auto [component, video_sink] = CreateMsVideoComponent();
+    if (source_)
+      source_->SetMediaStreamVideoTrackSink(std::move(video_sink));
+    return ms_component_ = component;
+  }
+
+  auto [component, audio_sink] = CreateMsAudioComponent();
+  if (source_)
+    source_->SetMediaStreamAudioTrackSink(std::move(audio_sink));
+  return ms_component_ = component;
+}
+
 bool ElementaryMediaTrack::IsEnabled() const {
   EMSS_DEBUG_TYPED();
 
index 3f0c7d2bb7336fecd6d45c7a3383390e751bb551..0dd48570e6f01261488f80eab021efcef5949cf3 100644 (file)
@@ -26,6 +26,7 @@
 #include "third_party/blink/renderer/modules/elementary_media_stream_source/elementary_media_print_helpers.h"
 #include "third_party/blink/renderer/platform/bindings/exception_code.h"
 #include "third_party/blink/renderer/platform/elementary_media_stream_source/web_elementary_media_packet_metadata.h"
+#include "third_party/blink/renderer/platform/mediastream/media_stream_component.h"
 #include "third_party/blink/renderer/platform/elementary_media_stream_source/web_elementary_media_track_control.h"
 #include "third_party/blink/renderer/platform/elementary_media_stream_source/web_elementary_media_track_dispatcher.h"
 #include "third_party/blink/renderer/platform/elementary_media_stream_source/web_elementary_media_track_operations.h"
@@ -70,6 +71,7 @@ class ElementaryMediaTrack final
  public:
   using DecodingMode = WebElementaryMediaTrackOperations::DecodingMode;
   using PlayerMode = WebElementaryMediaTrackOperations::PlayerMode;
+  using TrackType = WebElementaryMediaTrackControl::TrackType;
 
   enum class ConfigVerificationResult {
     kConfigSupported,
@@ -152,8 +154,11 @@ class ElementaryMediaTrack final
                            const AtomicString& rendering_mode);
 
   double GetHighestBufferedPresentationTimestamp() const;
+  MediaStreamComponent* GetMediaStreamComponent();
   bool IsEnabled() const;
 
+  TrackType Type() const;
+
   // content::WebElementaryMediaTrackControl::
   //     WebElementaryMediaTrackControlClient
   void OnSeek(base::TimeDelta seek_to) override;
@@ -179,7 +184,6 @@ class ElementaryMediaTrack final
 
  private:
   using OperationResult = WebElementaryMediaTrackOperations::OperationResult;
-  using TrackType = WebElementaryMediaTrackControl::TrackType;
 
   struct SyncAppendData {
     base::Lock append_lock;
@@ -251,8 +255,6 @@ class ElementaryMediaTrack final
   OperationResult SyncAppendWaitWhileLocked(bool* is_call_finished)
       EXCLUSIVE_LOCKS_REQUIRED(sync_append_data_->append_lock);
 
-  TrackType Type() const;
-
   void UpdateFramerateAndVideoConfigurationIfNeeded(
       const WebElementaryMediaPacketMetadata&);
 
@@ -291,6 +293,10 @@ class ElementaryMediaTrack final
   WeakMember<ElementaryMediaStreamSource> source_;
   Member<WebGLTexture> video_texture_;
 
+  // Media streams integration (used only when EMSS works with
+  // webmediaplayer_ms):
+  Member<MediaStreamComponent> ms_component_;
+
   friend class SideThreadElementaryMediaTrack;
 };
 
diff --git a/tizen_src/chromium_impl/third_party/blink/renderer/modules/elementary_media_stream_source/ms_audio_track_source.cc b/tizen_src/chromium_impl/third_party/blink/renderer/modules/elementary_media_stream_source/ms_audio_track_source.cc
new file mode 100644 (file)
index 0000000..84c6a4c
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright (c) 2024 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "tizen_src/chromium_impl/third_party/blink/renderer/modules/elementary_media_stream_source/ms_audio_track_source.h"
+
+#include "services/elementary_media_stream_source/public/cpp/logger.h"
+
+namespace blink {
+
+class MsAudioTrackSource::SinkImpl : public WebElementaryMediaTrackMsAudioSink {
+ public:
+  SinkImpl() = default;
+  ~SinkImpl() override = default;
+};  // class MsAudioTrackSource::SinkImpl
+
+MsAudioTrackSource::MsAudioTrackSource(
+    scoped_refptr<base::SingleThreadTaskRunner> main_task_runner)
+    : MediaStreamAudioSource(std::move(main_task_runner),
+                             /* is_local_source */ false) {
+  EMSS_DEBUG() << "Constructing object";
+}
+
+MsAudioTrackSource::~MsAudioTrackSource() {
+  EMSS_DEBUG() << "Destructing object";
+}
+
+std::shared_ptr<WebElementaryMediaTrackMsAudioSink>
+MsAudioTrackSource::GetAudioSink() {
+  return sink_impl_;
+}
+
+}  // namespace blink
diff --git a/tizen_src/chromium_impl/third_party/blink/renderer/modules/elementary_media_stream_source/ms_audio_track_source.h b/tizen_src/chromium_impl/third_party/blink/renderer/modules/elementary_media_stream_source/ms_audio_track_source.h
new file mode 100644 (file)
index 0000000..42d64b2
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright (c) 2024 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TIZEN_SRC_CHROMIUM_IMPL_THIRD_PARTY_BLINK_RENDERER_MODULES_ELEMENTARY_MEDIA_STREAM_SOURCE_MS_AUDIO_TRACK_SOURCE_H_
+#define TIZEN_SRC_CHROMIUM_IMPL_THIRD_PARTY_BLINK_RENDERER_MODULES_ELEMENTARY_MEDIA_STREAM_SOURCE_MS_AUDIO_TRACK_SOURCE_H_
+
+#include "third_party/blink/renderer/platform/mediastream/media_stream_audio_source.h"
+
+#include "third_party/blink/renderer/platform/elementary_media_stream_source/web_elementary_media_track_ms_audio_sink.h"
+
+namespace blink {
+
+class MsAudioTrackSource : public MediaStreamAudioSource {
+ public:
+  explicit MsAudioTrackSource(
+      scoped_refptr<base::SingleThreadTaskRunner> main_task_runner);
+  ~MsAudioTrackSource() override;
+
+  std::shared_ptr<WebElementaryMediaTrackMsAudioSink> GetAudioSink();
+
+ private:
+  class SinkImpl;
+
+  std::shared_ptr<SinkImpl> sink_impl_;
+};
+
+}  // namespace blink
+
+#endif  // TIZEN_SRC_CHROMIUM_IMPL_THIRD_PARTY_BLINK_RENDERER_MODULES_ELEMENTARY_MEDIA_STREAM_SOURCE_MS_VIDEO_TRACK_SOURCE_H_
diff --git a/tizen_src/chromium_impl/third_party/blink/renderer/modules/elementary_media_stream_source/ms_video_track_source.cc b/tizen_src/chromium_impl/third_party/blink/renderer/modules/elementary_media_stream_source/ms_video_track_source.cc
new file mode 100644 (file)
index 0000000..3102bef
--- /dev/null
@@ -0,0 +1,93 @@
+// Copyright (c) 2024 Samsung Electronics. 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/elementary_media_stream_source/ms_video_track_source.h"
+
+#include "base/time/time.h"
+#include "services/elementary_media_stream_source/public/cpp/logger.h"
+
+namespace blink {
+
+class MsVideoTrackSource::SinkImpl : public WebElementaryMediaTrackMsVideoSink {
+ public:
+  explicit SinkImpl(base::SingleThreadTaskRunner* frame_delivery_task_runner)
+      : frame_delivery_task_runner_(frame_delivery_task_runner) {}
+
+  ~SinkImpl() override = default;
+
+  void Start(VideoCaptureDeliverFrameCB frame_cb,
+             EncodedVideoFrameCB encoded_frame_cb,
+             VideoCaptureCropVersionCB crop_version_cb) {
+    EMSS_DEBUG();
+    frame_cb_ = std::move(frame_cb);
+    encoded_frame_cb_ = std::move(encoded_frame_cb);
+    crop_version_cb_ = std::move(crop_version_cb);
+  }
+
+  // WebElementaryMediaTrackMsVideoSink:
+
+  void AppendPacket(scoped_refptr<media::VideoFrame> frame) override {
+    EMSS_VERBOSE() << "Transferring frame to frame delivery thread: "
+                   << frame->timestamp();
+    frame_delivery_task_runner_->PostTask(
+        FROM_HERE, base::BindOnce(
+                       [](VideoCaptureDeliverFrameCB frame_cb,
+                          scoped_refptr<media::VideoFrame> frame) {
+                         EMSS_VERBOSE_NO_INSTANCE()
+                             << "Delivering frame: " << frame->timestamp();
+                         auto capture_time = base::TimeTicks::Now();
+                         frame_cb.Run(std::move(frame), {}, capture_time);
+                       },
+                       frame_cb_, std::move(frame)));
+  }
+
+ private:
+  base::SingleThreadTaskRunner* frame_delivery_task_runner_;
+
+  VideoCaptureDeliverFrameCB frame_cb_;
+  EncodedVideoFrameCB encoded_frame_cb_;
+  VideoCaptureCropVersionCB crop_version_cb_;
+};  // class MsVideoTrackSource::SinkImpl
+
+//////////////////// own public methods: ////////////////////
+
+MsVideoTrackSource::MsVideoTrackSource(
+    scoped_refptr<base::SingleThreadTaskRunner> main_task_runner)
+    : MediaStreamVideoSource(std::move(main_task_runner)),
+      sink_impl_(std::make_shared<SinkImpl>(io_task_runner())),
+      weak_factory_(this) {
+  EMSS_DEBUG() << "Constructing object";
+}
+
+MsVideoTrackSource::~MsVideoTrackSource() {
+  EMSS_DEBUG() << "Destructing object";
+}
+
+std::shared_ptr<WebElementaryMediaTrackMsVideoSink>
+MsVideoTrackSource::GetVideoSink() {
+  return sink_impl_;
+}
+
+//////////////////// MediaStreamVideoSource: ////////////////////
+
+base::WeakPtr<MediaStreamVideoSource> MsVideoTrackSource::GetWeakPtr() {
+  return weak_factory_.GetWeakPtr();
+}
+
+void MsVideoTrackSource::StartSourceImpl(
+    VideoCaptureDeliverFrameCB frame_callback,
+    EncodedVideoFrameCB encoded_frame_callback,
+    VideoCaptureCropVersionCB crop_version_callback) {
+  EMSS_DEBUG();
+  sink_impl_->Start(std::move(frame_callback),
+                    std::move(encoded_frame_callback),
+                    std::move(crop_version_callback));
+  OnStartDone(mojom::MediaStreamRequestResult::OK);
+}
+
+void MsVideoTrackSource::StopSourceImpl() {
+  EMSS_DEBUG();
+}
+
+}  // namespace blink
diff --git a/tizen_src/chromium_impl/third_party/blink/renderer/modules/elementary_media_stream_source/ms_video_track_source.h b/tizen_src/chromium_impl/third_party/blink/renderer/modules/elementary_media_stream_source/ms_video_track_source.h
new file mode 100644 (file)
index 0000000..7675517
--- /dev/null
@@ -0,0 +1,39 @@
+// Copyright (c) 2024 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TIZEN_SRC_CHROMIUM_IMPL_THIRD_PARTY_BLINK_RENDERER_MODULES_ELEMENTARY_MEDIA_STREAM_SOURCE_MS_VIDEO_TRACK_SOURCE_H_
+#define TIZEN_SRC_CHROMIUM_IMPL_THIRD_PARTY_BLINK_RENDERER_MODULES_ELEMENTARY_MEDIA_STREAM_SOURCE_MS_VIDEO_TRACK_SOURCE_H_
+
+#include "third_party/blink/public/web/modules/mediastream/media_stream_video_source.h"
+
+#include "third_party/blink/renderer/platform/elementary_media_stream_source/web_elementary_media_track_ms_video_sink.h"
+
+namespace blink {
+
+class MsVideoTrackSource : public MediaStreamVideoSource {
+ public:
+  explicit MsVideoTrackSource(scoped_refptr<base::SingleThreadTaskRunner> main_task_runner);
+  ~MsVideoTrackSource() override;
+
+  std::shared_ptr<WebElementaryMediaTrackMsVideoSink> GetVideoSink();
+
+  // MediaStreamVideoSource:
+  base::WeakPtr<MediaStreamVideoSource> GetWeakPtr() override;
+  void StartSourceImpl(
+      VideoCaptureDeliverFrameCB frame_callback,
+      EncodedVideoFrameCB encoded_frame_callback,
+      VideoCaptureCropVersionCB crop_version_callback) override;
+  void StopSourceImpl() override;
+
+ private:
+  class SinkImpl;
+
+  std::shared_ptr<SinkImpl> sink_impl_;
+
+  base::WeakPtrFactory<MediaStreamVideoSource> weak_factory_;
+};
+
+}  // namespace blink
+
+#endif  // TIZEN_SRC_CHROMIUM_IMPL_THIRD_PARTY_BLINK_RENDERER_MODULES_ELEMENTARY_MEDIA_STREAM_SOURCE_MS_VIDEO_TRACK_SOURCE_H_
index d6e0467053de4a3f7031ef1456e243e7ffb83b92..ab6e5b296013d2035077ffc91723e0c99570dc2f 100644 (file)
@@ -165,6 +165,14 @@ void SameThreadElementaryMediaStreamSourceAttachment::OnPause(
   GetSource(tracer)->OnPause();
 }
 
+void SameThreadElementaryMediaStreamSourceAttachment::
+    OnLoadDeferredUntilSourceOpen(MediaSourceTracer* tracer,
+                                  base::OnceClosure on_source_opened) {
+  EMSS_DEBUG();
+
+  GetSource(tracer)->OnLoadDeferredUntilSourceOpen(std::move(on_source_opened));
+}
+
 void SameThreadElementaryMediaStreamSourceAttachment::OnPlay(
     blink::MediaSourceTracer* tracer) {
   EMSS_DEBUG();
@@ -195,6 +203,11 @@ void SameThreadElementaryMediaStreamSourceAttachment::UpdatePlaybackPosition(
   GetSource(tracer)->UpdatePlaybackPosition(playback_position, session_id);
 }
 
+MediaStreamDescriptor* SameThreadElementaryMediaStreamSourceAttachment::
+    GetMediaStreamDescriptorIfAvailable(MediaSourceTracer* tracer) {
+  return GetSource(tracer)->GetMediaStreamDescriptorIfAvailable();
+}
+
 // ElementaryMediaStreamSourceAttachment interface:
 
 void SameThreadElementaryMediaStreamSourceAttachment::OnDurationChanged(
index 5f88c902269e4af000c0cbce4b88b0b91747382a..6939397b93c227e09cc3cce888cb389d0bc08912 100644 (file)
@@ -58,6 +58,10 @@ class SameThreadElementaryMediaStreamSourceAttachment final
 
   bool IsVideoTextureMode(MediaSourceTracer* tracer) const override;
 
+  void OnLoadDeferredUntilSourceOpen(
+      MediaSourceTracer* tracer,
+      base::OnceClosure on_source_opened) override;
+
   void OnPause(MediaSourceTracer* tracer) override;
 
   void OnPlay(MediaSourceTracer* tracer) override;
@@ -70,6 +74,9 @@ class SameThreadElementaryMediaStreamSourceAttachment final
                               double playback_position,
                               uint32_t session_id) override;
 
+  MediaStreamDescriptor* GetMediaStreamDescriptorIfAvailable(
+      MediaSourceTracer* tracer) override;
+
   // ElementaryMediaStreamSourceAttachment interface:
 
   void OnDurationChanged(MediaSourceTracer* tracer,
index e1be41a60209e640fb8aa0237dd72499885a358a..e7d0fdb4e5d4f055ff663f03463b09a5854fd2ab 100644 (file)
@@ -30,6 +30,8 @@ source_set("elementary_media_stream_source") {
     "web_elementary_media_track_control.h",
     "web_elementary_media_track_dispatcher.cc",
     "web_elementary_media_track_dispatcher.h",
+    "web_elementary_media_track_ms_audio_sink.h",
+    "web_elementary_media_track_ms_video_sink.h",
     "web_elementary_media_track_operations.h",
   ]
 }
index 0312a34cce40369195050c468a73dce6d7b87bfc..c3af8dd6cccc1d4332826367c581b1c37f5f96f5 100644 (file)
@@ -70,6 +70,10 @@ class WebElementaryMediaStreamSourceControl
   virtual void SetDuration(double) = 0;
   virtual OperationCallbackResult SetSourceClosed() = 0;
   virtual OperationCallbackResult SetSourceOpened() = 0;
+  virtual void SetMediaStreamAudioTrackSink(
+      std::shared_ptr<WebElementaryMediaTrackMsAudioSink>) = 0;
+  virtual void SetMediaStreamVideoTrackSink(
+      std::shared_ptr<WebElementaryMediaTrackMsVideoSink>) = 0;
 
  protected:
   WebElementaryMediaStreamSourceControl() = default;
index 3ab0081e5a7973a67f167ba516e7a17ff30f9321..0c0e3032c3a8f3bd953cf5e6321af60add0b95ed 100644 (file)
@@ -4,10 +4,34 @@
 
 #include "third_party/blink/renderer/platform/elementary_media_stream_source/web_elementary_media_stream_source_dispatcher.h"
 
+#include "content/renderer/media/tizen/elementary_media_stream_source/control_thread/source_impl.h"
 #include "services/elementary_media_stream_source/public/cpp/logger.h"
 
 namespace blink {
 
+// static
+WebElementaryMediaStreamSourceDispatcher::CreationTuple
+WebElementaryMediaStreamSourceDispatcher::Create(
+    PipelineMode pipeline_mode,
+    scoped_refptr<base::SingleThreadTaskRunner> control_thread_task_runner,
+    scoped_refptr<base::SingleThreadTaskRunner> worker_thread_task_runner) {
+  auto [source_dispatcher, any_thread_source_impl, control_thread_source_impl,
+        worker_thread_source_impl] =
+      SourceDispatcher::Create(pipeline_mode, control_thread_task_runner,
+                               worker_thread_task_runner);
+
+  auto blink_source_dispatcher = std::make_shared<
+      blink::WebElementaryMediaStreamSourceDispatcher>(
+      control_thread_task_runner, std::move(source_dispatcher),
+      std::static_pointer_cast<blink::WebElementaryMediaStreamSourceControl>(
+          control_thread_source_impl));
+
+  return std::make_tuple(std::move(blink_source_dispatcher),
+                         std::move(any_thread_source_impl),
+                         std::move(control_thread_source_impl),
+                         std::move(worker_thread_source_impl));
+}
+
 WebElementaryMediaStreamSourceDispatcher::
     WebElementaryMediaStreamSourceDispatcher(
         scoped_refptr<base::SingleThreadTaskRunner> control_thread_task_runner,
index 937c72ac9803b0824dc62e5418e6eebfedf7e68a..16bee38972c3999e380a7b1613f94ed27a488cd6 100644 (file)
@@ -12,6 +12,7 @@
 #include "base/memory/scoped_refptr.h"
 #include "base/task/single_thread_task_runner.h"
 #include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/common_types.h"
+#include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/demuxer_dispatcher.h"
 #include "content/renderer/media/tizen/elementary_media_stream_source/any_thread/source_dispatcher.h"
 #include "media/base/audio_decoder_config.h"
 #include "media/base/tizen/stream_framerate.h"
@@ -36,16 +37,36 @@ class WebElementaryMediaStreamSourceDispatcher
 
  public:
   using DecodingMode = WebElementaryMediaTrackOperations::DecodingMode;
+  using PipelineMode = content::elementary_media_stream_source::PipelineMode;
+  using DemuxerDispatcher =
+      content::elementary_media_stream_source::any_thread::DemuxerDispatcher;
   using SourceDispatcher =
       content::elementary_media_stream_source::any_thread::SourceDispatcher;
   using TrackDispatcher =
       content::elementary_media_stream_source::any_thread::TrackDispatcher;
 
+  using AnySourceImpl =
+      content::elementary_media_stream_source::any_thread::SourceImpl;
+  using ControlSourceImpl =
+      content::elementary_media_stream_source::control_thread::SourceImpl;
+  using WorkerSourceImpl =
+      content::elementary_media_stream_source::worker_thread::SourceImpl;
+
+  using CreationTuple =
+      std::tuple<std::shared_ptr<WebElementaryMediaStreamSourceDispatcher>,
+                 std::shared_ptr<AnySourceImpl>,
+                 std::shared_ptr<ControlSourceImpl>,
+                 std::shared_ptr<WorkerSourceImpl>>;
+
+  static CreationTuple Create(
+      PipelineMode pipeline_mode,
+      scoped_refptr<base::SingleThreadTaskRunner> control_thread_task_runner,
+      scoped_refptr<base::SingleThreadTaskRunner> worker_thread_task_runner);
+
   WebElementaryMediaStreamSourceDispatcher(
       scoped_refptr<base::SingleThreadTaskRunner> control_thread_task_runner,
       std::shared_ptr<SourceDispatcher> source_dispatcher,
       std::shared_ptr<WebElementaryMediaStreamSourceControl> client);
-
   ~WebElementaryMediaStreamSourceDispatcher() override;
 
   std::shared_ptr<WebElementaryMediaTrackDispatcher> CreateAudioTrackDispatcher(
@@ -80,10 +101,20 @@ class WebElementaryMediaStreamSourceDispatcher
         std::move(track_control), std::move(track_operations));
   }
 
+  void KeepDemuxerDispatcher(
+      std::shared_ptr<DemuxerDispatcher> maybe_demuxer_dispatcher) {
+    maybe_demuxer_dispatcher_ = std::move(maybe_demuxer_dispatcher);
+  }
+
  private:
   std::tuple<std::shared_ptr<WebElementaryMediaStreamSourceControl>> clients_;
 
   std::shared_ptr<SourceDispatcher> source_dispatcher_;
+
+  // DemuxerDispatcher will be owned only by media::Demuxer implementation if
+  // available. If not available, WebElementaryMediaStreamSourceDispatcher will
+  // hold DemuxerDispatcher alive although it won't use it directly.
+  std::shared_ptr<DemuxerDispatcher> maybe_demuxer_dispatcher_;
 };
 
 }  // namespace blink
index cfe1541d284e5633b1ebffbfb12d6b55af2b6ce1..5b5a85cc9f584c8d4d039d0521e0cb37be1b4fff 100644 (file)
@@ -17,6 +17,8 @@
 #include "media/base/video_frame.h"
 #include "third_party/blink/renderer/platform/elementary_media_stream_source/web_elementary_media_enable_control_dispatcher.h"
 #include "third_party/blink/renderer/platform/elementary_media_stream_source/web_elementary_media_packet_metadata.h"
+#include "third_party/blink/renderer/platform/elementary_media_stream_source/web_elementary_media_track_ms_audio_sink.h"
+#include "third_party/blink/renderer/platform/elementary_media_stream_source/web_elementary_media_track_ms_video_sink.h"
 
 namespace blink {
 
diff --git a/tizen_src/chromium_impl/third_party/blink/renderer/platform/elementary_media_stream_source/web_elementary_media_track_ms_audio_sink.h b/tizen_src/chromium_impl/third_party/blink/renderer/platform/elementary_media_stream_source/web_elementary_media_track_ms_audio_sink.h
new file mode 100644 (file)
index 0000000..0b28d0f
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright (c) 2024 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TIZEN_SRC_CHROMIUM_IMPL_THIRD_PARTY_BLINK_PUBLIC_PLATFORM_TIZEN_ELEMENTARY_MEDIA_STREAM_SOURCE_WEB_ELEMENTARY_MEDIA_TRACK_MS_AUDIO_SINK_H_
+#define TIZEN_SRC_CHROMIUM_IMPL_THIRD_PARTY_BLINK_PUBLIC_PLATFORM_TIZEN_ELEMENTARY_MEDIA_STREAM_SOURCE_WEB_ELEMENTARY_MEDIA_TRACK_MS_AUDIO_SINK_H_
+
+namespace blink {
+
+class WebElementaryMediaTrackMsAudioSink {
+ public:
+  WebElementaryMediaTrackMsAudioSink() = default;
+  virtual ~WebElementaryMediaTrackMsAudioSink() = default;
+};
+
+}  // namespace blink
+
+#endif  // TIZEN_SRC_CHROMIUM_IMPL_THIRD_PARTY_BLINK_PUBLIC_PLATFORM_TIZEN_ELEMENTARY_MEDIA_STREAM_SOURCE_WEB_ELEMENTARY_MEDIA_TRACK_MS_AUDIO_SINK_H_
\ No newline at end of file
diff --git a/tizen_src/chromium_impl/third_party/blink/renderer/platform/elementary_media_stream_source/web_elementary_media_track_ms_video_sink.h b/tizen_src/chromium_impl/third_party/blink/renderer/platform/elementary_media_stream_source/web_elementary_media_track_ms_video_sink.h
new file mode 100644 (file)
index 0000000..cd35592
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright (c) 2024 Samsung Electronics. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef TIZEN_SRC_CHROMIUM_IMPL_THIRD_PARTY_BLINK_PUBLIC_PLATFORM_TIZEN_ELEMENTARY_MEDIA_STREAM_SOURCE_WEB_ELEMENTARY_MEDIA_TRACK_MS_VIDEO_SINK_H_
+#define TIZEN_SRC_CHROMIUM_IMPL_THIRD_PARTY_BLINK_PUBLIC_PLATFORM_TIZEN_ELEMENTARY_MEDIA_STREAM_SOURCE_WEB_ELEMENTARY_MEDIA_TRACK_MS_VIDEO_SINK_H_
+
+#include "media/base/video_frame.h"
+
+namespace blink {
+
+class WebElementaryMediaTrackMsVideoSink {
+ public:
+  WebElementaryMediaTrackMsVideoSink() = default;
+  virtual ~WebElementaryMediaTrackMsVideoSink() = default;
+
+  virtual void AppendPacket(scoped_refptr<media::VideoFrame>) = 0;
+};
+
+}  // namespace blink
+
+#endif  // TIZEN_SRC_CHROMIUM_IMPL_THIRD_PARTY_BLINK_PUBLIC_PLATFORM_TIZEN_ELEMENTARY_MEDIA_STREAM_SOURCE_WEB_ELEMENTARY_MEDIA_TRACK_MS_VIDEO_SINK_H_
\ No newline at end of file