[EMSS] Run TTvd low latency decoding on media thread 51/314351/3
authorPiotr Bałut <p.balut@samsung.com>
Tue, 18 Jun 2024 06:16:07 +0000 (08:16 +0200)
committerBot Blink <blinkbot@samsung.com>
Wed, 10 Jul 2024 15:25:53 +0000 (15:25 +0000)
[PROBLEM]
Not all media::GpuVideoAcceleratorFactories methods are thread safe,
including methods used by media::MojoVideoDecoder. Since low latency
decoding with TTvd uses MojoVideoDecoder, running a dedicated worker
thread for decoding separate from GpuVideoAcceleratorFactories caused
occacsional crashes.

[SOLUTION]
GpuVideoAcceleratorFactories lives on the media thread. Instead of
creating a dedicated worker thread for EMSS, media thread is reused as
worker thread in low latency modes that use TTvd.

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

third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc
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/worker_thread/ms_decoding_stream.cc

index 1714b3a4ed77405d26d721cbf3e07dc7c0411676..73f51664eb4e759564af3291be09f0b568493302 100644 (file)
@@ -1881,7 +1881,8 @@ void WebMediaPlayerMS::StartLoadingEmss() {
   client_->OnLoadDeferredUntilSourceOpen();
   const auto emss_pipeline_mode = client_->GetEmssPipelineMode();
   auto emss_demuxer_dispatcher = EmssDemuxerDispatcher::Create(
-      emss_pipeline_mode, base::SingleThreadTaskRunner::GetCurrentDefault());
+      emss_pipeline_mode, base::SingleThreadTaskRunner::GetCurrentDefault(),
+      media_task_runner_);
   auto [blink_source_dispatcher, any_thread_source_impl,
         control_thread_source_impl, worker_thread_source_impl] =
       WebElementaryMediaStreamSourceDispatcher::Create(
index bfc428f440af2632c12b7ee4f95db54c83cce645..065cdfd3434286d638383bcfbebf690e90eae16f 100644 (file)
@@ -83,20 +83,30 @@ void GetGpuFactoriesOnBlinkMainThread(
 std::shared_ptr<DemuxerDispatcher> DemuxerDispatcher::Create(
     PipelineMode pipeline_mode,
     const scoped_refptr<base::SingleThreadTaskRunner>&
-        control_thread_task_runner) {
+        control_thread_task_runner,
+    scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner) {
   EMSS_DEBUG_NO_INSTANCE();
 
+  if (!worker_task_runner) {
+    worker_task_runner = base::ThreadPool::CreateSingleThreadTaskRunner(
+        {base::TaskPriority::USER_BLOCKING,
+         base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
+        base::SingleThreadTaskRunnerThreadMode::DEDICATED);
+  }
+
   auto [demuxer_dispatcher, maybe_pending_data_stream_src] = ([&]() {
     if (pipeline_mode.demuxer_mode == DemuxerMode::kMediaStream) {
-      return std::make_tuple(std::make_shared<DemuxerDispatcher>(
-                                 std::nullopt, control_thread_task_runner),
-                             worker_thread::PendingDataStreamSrcInterfaces{});
+      return std::make_tuple(
+          std::make_shared<DemuxerDispatcher>(
+              std::nullopt, control_thread_task_runner, worker_task_runner),
+          worker_thread::PendingDataStreamSrcInterfaces{});
     }
 
     auto [pending_data_stream_src, pending_data_stream_sink] =
         CreateDataStream();
     auto dispatcher = std::make_shared<DemuxerDispatcher>(
-        std::move(pending_data_stream_sink), control_thread_task_runner);
+        std::move(pending_data_stream_sink), control_thread_task_runner,
+        worker_task_runner);
 
     return std::make_tuple(std::move(dispatcher),
                            std::move(pending_data_stream_src));
@@ -169,18 +179,6 @@ DemuxerDispatcher::~DemuxerDispatcher() {
   DispatchTask(&WorkerLifecycleObserver::OnDispatcherDisconnected);
 }
 
-DemuxerDispatcher::DemuxerDispatcher(
-    std::optional<PendingDataStreamSinkInterfaces> pending_data_stream_sink,
-    const scoped_refptr<base::SingleThreadTaskRunner>&
-        control_thread_task_runner)
-    : DemuxerDispatcher(
-          std::move(pending_data_stream_sink),
-          control_thread_task_runner,
-          base::ThreadPool::CreateSingleThreadTaskRunner(
-              {base::TaskPriority::USER_BLOCKING,
-               base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
-              base::SingleThreadTaskRunnerThreadMode::DEDICATED)) {}
-
 DemuxerDispatcher::DemuxerDispatcher(
     std::optional<PendingDataStreamSinkInterfaces> pending_data_stream_sink,
     const scoped_refptr<base::SingleThreadTaskRunner>&
index 4a11e48729bc00346ab4fb428303d27da7617c72..2af5ecbbb12063d4fc967f9f3f01e170ffb241cc 100644 (file)
@@ -96,14 +96,21 @@ class DemuxerDispatcher
   using WorkerThreadDemuxerAdapterClient =
       worker_thread::PlatformDemuxerAdapterClient;
 
+  // * control_task_runner is the task runner that controls playback and reports
+  //   to the app (typically the main JS thread runner).
+  // * worker_task_runner is the task runner that's used to process packets (if
+  //   unset a new task runner will be created).
   static std::shared_ptr<DemuxerDispatcher> Create(
       PipelineMode,
-      const scoped_refptr<base::SingleThreadTaskRunner>&);
+      const scoped_refptr<base::SingleThreadTaskRunner>& control_task_runner,
+      scoped_refptr<base::SingleThreadTaskRunner> worker_task_runner = {});
 
   DemuxerDispatcher(
       std::optional<PendingDataStreamSinkInterfaces> pending_data_stream_sink,
       const scoped_refptr<base::SingleThreadTaskRunner>&
-          control_thread_task_runner);
+          control_thread_task_runner,
+      const scoped_refptr<base::SingleThreadTaskRunner>&
+          worker_thread_task_runner);
   ~DemuxerDispatcher() override;
 
   std::optional<PendingDataStreamSinkInterfaces> ConsumeDataStreamSink();
@@ -129,14 +136,6 @@ class DemuxerDispatcher
     return worker_thread_task_runner_;
   }
 
- protected:
-  DemuxerDispatcher(
-      std::optional<PendingDataStreamSinkInterfaces> pending_data_stream_sink,
-      const scoped_refptr<base::SingleThreadTaskRunner>&
-          control_thread_task_runner,
-      const scoped_refptr<base::SingleThreadTaskRunner>&
-          worker_thread_task_runner);
-
  private:
   template <typename DemuxerImplT>
   static void SetAnyClients(
index f4cb60588b63d590106dc88e6e32bce65d943170..a28e92cb79cd7db0855e81ef7ea88f883cef0f6b 100644 (file)
@@ -6,6 +6,7 @@
 
 #include <sstream>
 
+#include "base/check.h"
 #include "base/functional/bind.h"
 #include "base/functional/callback_helpers.h"
 #include "base/task/sequenced_task_runner.h"
@@ -569,10 +570,6 @@ class MsDecodingStream::VideoStream : public DecodingStream<TrackType::kVideo> {
   void StartInitializingVideoDecoder(const media::VideoDecoderConfig&);
 
  private:
-  static std::unique_ptr<media::VideoDecoder>
-  CreateVideoDecoderOnGpuFactoriesThread(
-      media::GpuVideoAcceleratorFactories* gpu_factories,
-      media::MediaLog* media_log);
   void OnVideoDecoderInitialized(std::unique_ptr<media::VideoDecoder>,
                                  media::DecoderStatus);
 
@@ -639,23 +636,9 @@ void MsDecodingStream::VideoStream::StartInitializingVideoDecoder(
     return;
   }
 
-  gpu_factories_->GetTaskRunner()->PostTaskAndReplyWithResult(
-      FROM_HERE,
-      base::BindOnce(&MsDecodingStream::VideoStream::
-                         CreateVideoDecoderOnGpuFactoriesThread,
-                     gpu_factories_, media_log_),
-      base::BindOnce(&MsDecodingStream::VideoStream::InitializeDecoder,
-                     weak_ptr_factory_.GetWeakPtr(), video_conf));
-}
-
-// 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));
+  auto decoder = gpu_factories_->CreateVideoDecoder(
+      media_log_, base::BindRepeating(&OnRequestOverlayInfo));
+  InitializeDecoder(video_conf, std::move(decoder));
 }
 
 void MsDecodingStream::VideoStream::OnDecoderInitialized(
@@ -703,8 +686,20 @@ void MsDecodingStream::SetGpuFactories(
     media::GpuVideoAcceleratorFactories* gpu_factories) {
   EMSS_DEBUG() << gpu_factories;
 
+  if (!gpu_factories) {
+    EMSS_LOG(ERROR) << "GPU factories are empty?";
+    EmitError(BackendError::kPipelineError,
+              "Video acceleration failed to initialize.");
+    return;
+  }
+
   gpu_factories_ = gpu_factories;
 
+  CHECK(gpu_factories_->GetTaskRunner() ==
+        base::SingleThreadTaskRunner::GetCurrentDefault())
+      << "worker_thread must be GPU factories thread or MojoVideoDecoder may "
+         "crash.";
+
   if (video_stream_)
     video_stream_->SetGpuFactories(gpu_factories);
 }