[M120 Migration][WebRTC] Merge fixup patches 51/309251/3
authorpeng.yin <peng8.yin@samsung.com>
Mon, 8 Apr 2024 01:20:13 +0000 (09:20 +0800)
committerpeng.yin <peng8.yin@samsung.com>
Tue, 9 Apr 2024 03:17:14 +0000 (11:17 +0800)
fixup!fixup![M108 Aura Migration][MM][WebRtc] New implementation for local stream renderer
https://review.tizen.org/gerrit/#/c/293279/

Fixup! [M108 Migration] Support camera to canvas feature
https://review.tizen.org/gerrit/#/c/292855/

Optimize video hole frame updates
https://review.tizen.org/gerrit/#/c/291925/

fixup! [VD][MM] Get H264 max_res from RS on M108
https://review.tizen.org/gerrit/#/c/301521/

[MM] Do not perform operation by buffering state during in low latency mode.
https://review.tizen.org/gerrit/#/c/301932/

Change-Id: I4046fb2ebee17c9305f1d7c38e21841398bce2b4
Signed-off-by: peng.yin <peng8.yin@samsung.com>
20 files changed:
gpu/ipc/client/command_buffer_proxy_impl.cc
media/base/video_frame.h
media/mojo/mojom/media_types.mojom
media/mojo/mojom/video_decoder_config_mojom_traits.cc
media/mojo/mojom/video_decoder_config_mojom_traits.h
third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc
third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.cc
third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.h
tizen_src/chromium_impl/media/filters/media_player_esplusplayer.cc
tizen_src/chromium_impl/media/filters/media_player_esplusplayer.h
tizen_src/chromium_impl/media/filters/media_player_esplusplayer_common.cc
tizen_src/chromium_impl/media/filters/media_player_esplusplayer_common.h
tizen_src/chromium_impl/media/filters/media_player_esplusplayer_tv.cc
tizen_src/chromium_impl/media/filters/media_player_esplusplayer_tv.h
tizen_src/chromium_impl/ui/gfx/tbm_buffer_handle.h
ui/gfx/gpu_memory_buffer.h
ui/gfx/mojom/BUILD.gn
ui/gfx/mojom/buffer_types.mojom
ui/gfx/mojom/buffer_types_mojom_traits.cc
ui/gfx/mojom/buffer_types_mojom_traits.h

index 7c88a96..e820e74 100644 (file)
@@ -447,6 +447,7 @@ int32_t CommandBufferProxyImpl::CreateEGLImage(
   }
   handle.width = width;
   handle.height = height;
+  handle.tbm_destroy_type = buffer_handle.tbm_destroy_type;
 
   params->gpu_memory_buffer = std::move(handle);
   command_buffer_->CreateImage(std::move(params));
index f31ae5b..d47128e 100644 (file)
@@ -416,6 +416,9 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe<VideoFrame> {
       scoped_refptr<viz::ContextProvider> context_provider) {
     context_provider_ = context_provider;
   }
+  void SetTbmDestroyType(gfx::TbmDestroyType type) {
+    buffer_handle_.tbm_destroy_type = type;
+  }
 #endif
 
   // Creates a frame which indicates end-of-stream.
index 7ea0505..7da8210 100644 (file)
@@ -197,6 +197,8 @@ struct VideoDecoderConfig {
   VideoColorSpace color_space_info;
   gfx.mojom.HDRMetadata? hdr_metadata;
   bool is_rtc;
+  [EnableIf=tizen_multimedia]
+  gfx.mojom.Size max_coded_size;
   [EnableIf=is_tizen_tv]
   string hdr_info;
   [EnableIf=is_tizen_tv]
index dcf30fa..160c7fd 100644 (file)
@@ -75,6 +75,12 @@ bool StructTraits<media::mojom::VideoDecoderConfigDataView,
   output->set_framerate_den(input.framerate_den());
 #endif
 
+#if defined(TIZEN_MULTIMEDIA)
+  gfx::Size max_coded_size;
+  input.ReadMaxCodedSize(&max_coded_size);
+  output->set_max_coded_size(max_coded_size);
+#endif
+
   if (!output->IsValidConfig())
     return false;
 
index 204c0ab..8046361 100644 (file)
@@ -92,6 +92,13 @@ struct StructTraits<media::mojom::VideoDecoderConfigDataView,
   }
 #endif
 
+#if defined(TIZEN_MULTIMEDIA)
+  static const gfx::Size& max_coded_size(
+      const media::VideoDecoderConfig& input) {
+    return input.max_coded_size();
+  }
+#endif
+
   static bool Read(media::mojom::VideoDecoderConfigDataView input,
                    media::VideoDecoderConfig* output);
 };
index cd2f694..02649bb 100644 (file)
@@ -1149,13 +1149,57 @@ bool WebMediaPlayerMS::DidLoadingProgress() {
   return true;
 }
 
+#if BUILDFLAG(IS_TIZEN_TV) && defined(TIZEN_TBM_SUPPORT)
+void WebMediaPlayerMS::PaintDecodedVideoFrame(
+    scoped_refptr<media::VideoFrame> decoded_frame) {
+  base::AutoLock auto_lock(request_frame_lock_);
+  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+  // update decoded frame
+  decoded_video_frame_ = decoded_frame;
+  request_frame_waiter_.Signal();
+}
+#endif
+
 void WebMediaPlayerMS::Paint(cc::PaintCanvas* canvas,
                              const gfx::Rect& rect,
                              cc::PaintFlags& flags) {
   DVLOG(3) << __func__;
   DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
 
+#if BUILDFLAG(IS_TIZEN_TV) && defined(TIZEN_TBM_SUPPORT) && \
+    defined(TIZEN_MULTIMEDIA)
+  LOG(INFO) << __func__ << ", rect " << rect.ToString();
+  scoped_refptr<media::VideoFrame> decoded_frame =
+      compositor_->GetCurrentFrame();
+
+  const base::CommandLine& command_line =
+      *base::CommandLine::ForCurrentProcess();
+  if (command_line.HasSwitch(switches::kEnableFrameRawDataCopy) &&
+      (!decoded_frame ||
+       decoded_frame->storage_type() == media::VideoFrame::STORAGE_HOLE)) {
+    frame_deliverer_->RequestVideoDecodedBuffer();
+    for (int i = 0; i < 3; ++i) {
+      SendVideoDecodedBufferRequest();
+      // need to wait some time to ensure decoded frame have return.
+      bool signaled =
+          request_frame_waiter_.TimedWait(  // FIXME: will block UI thread
+              base::Milliseconds(22));      // wait max 22ms
+      if (signaled) {
+        break;
+      }
+    }
+    base::AutoLock auto_lock(request_frame_lock_);
+    decoded_frame = decoded_video_frame_;
+
+    // Prevent to paint a black screen when a decoded frame is not prepared.
+    if (!decoded_frame)
+      return;
+  }
+
+  const scoped_refptr<media::VideoFrame> frame = decoded_frame;
+#else
   const scoped_refptr<media::VideoFrame> frame = compositor_->GetCurrentFrame();
+#endif
 
   scoped_refptr<viz::RasterContextProvider> provider;
   if (frame && frame->HasTextures()) {
@@ -1167,6 +1211,11 @@ void WebMediaPlayerMS::Paint(cc::PaintCanvas* canvas,
   const gfx::RectF dest_rect(rect);
   video_renderer_.Paint(frame, canvas, dest_rect, flags,
                         GetFrameTransformation(frame), provider.get());
+#if BUILDFLAG(IS_TIZEN_TV) && defined(TIZEN_TBM_SUPPORT)
+  // Do not keep decoded video frame resource here,
+  // renderer will paint black rectangle if no new decoded frame
+  decoded_video_frame_ = nullptr;
+#endif
 }
 
 scoped_refptr<media::VideoFrame> WebMediaPlayerMS::GetCurrentFrameThenUpdate() {
index 337cf39..d4938d9 100644 (file)
@@ -63,7 +63,13 @@ scoped_refptr<media::VideoFrame> CopyFrame(
     scoped_refptr<media::VideoFrame> frame,
     media::PaintCanvasVideoRenderer* video_renderer) {
   scoped_refptr<media::VideoFrame> new_frame;
+#if BUILDFLAG(IS_TIZEN_TV) && defined(TIZEN_VIDEO_HOLE)
+  if (frame->storage_type() == media::VideoFrame::STORAGE_HOLE) {
+    new_frame = media::VideoFrame::CreateHoleFrame(frame->natural_size());
+  } else if (frame->HasTextures()) {
+#else
   if (frame->HasTextures()) {
+#endif
     DCHECK(frame->format() == media::PIXEL_FORMAT_ARGB ||
            frame->format() == media::PIXEL_FORMAT_XRGB ||
            frame->format() == media::PIXEL_FORMAT_ABGR ||
@@ -367,6 +373,9 @@ void WebMediaPlayerMSCompositor::SetVideoFrameProviderClient(
     video_frame_provider_client_->StopUsingProvider();
 
   video_frame_provider_client_ = client;
+#if defined(TIZEN_VIDEO_HOLE)
+  video_frame_provider_client_changed_ = true;
+#endif
   if (video_frame_provider_client_ && !stopped_)
     video_frame_provider_client_->StartRendering();
 }
@@ -440,6 +449,15 @@ void WebMediaPlayerMSCompositor::EnqueueFrame(
     return;
   }
 
+#if defined(TIZEN_VIDEO_HOLE)
+  // Turn off rendering algorithm for pure video-hole frames
+  if (frame->storage_type() == media::VideoFrame::STORAGE_HOLE) {
+    rendering_frame_buffer_.reset();
+    RenderWithoutAlgorithm(std::move(frame), is_copy);
+    return;
+  }
+#endif
+
   // This is a signal frame saying that the stream is stopped.
   if (frame->metadata().end_of_stream) {
     rendering_frame_buffer_.reset();
@@ -707,6 +725,14 @@ void WebMediaPlayerMSCompositor::RenderWithoutAlgorithmOnCompositor(
     scoped_refptr<media::VideoFrame> frame,
     bool is_copy) {
   DCHECK(video_frame_compositor_task_runner_->BelongsToCurrentThread());
+  bool frame_size_changed = true;
+  bool is_video_hole = false;
+  bool provider_changed = true;
+#if defined(TIZEN_VIDEO_HOLE)
+  is_video_hole = frame->storage_type() == media::VideoFrame::STORAGE_HOLE;
+  provider_changed = video_frame_provider_client_changed_;
+#endif
+
   {
     base::AutoLock auto_lock(current_frame_lock_);
     // Last timestamp in the stream might not have timestamp.
@@ -714,13 +740,22 @@ void WebMediaPlayerMSCompositor::RenderWithoutAlgorithmOnCompositor(
         frame->timestamp() > current_frame_->timestamp()) {
       last_render_length_ = frame->timestamp() - current_frame_->timestamp();
     }
-    SetCurrentFrame(std::move(frame), is_copy, absl::nullopt);
+    frame_size_changed =
+        SetCurrentFrame(std::move(frame), is_copy, absl::nullopt);
   }
-  if (video_frame_provider_client_)
+
+  if (is_video_hole && !frame_size_changed && !provider_changed)
+    return;
+
+  if (video_frame_provider_client_) {
     video_frame_provider_client_->DidReceiveFrame();
+  }
+#if defined(TIZEN_VIDEO_HOLE)
+  video_frame_provider_client_changed_ = false;
+#endif
 }
 
-void WebMediaPlayerMSCompositor::SetCurrentFrame(
+bool WebMediaPlayerMSCompositor::SetCurrentFrame(
     scoped_refptr<media::VideoFrame> frame,
     bool is_copy,
     absl::optional<base::TimeTicks> expected_display_time) {
@@ -732,12 +767,14 @@ void WebMediaPlayerMSCompositor::SetCurrentFrame(
 
   if (!current_frame_rendered_)
     ++dropped_frame_count_;
+  bool previous_frame_rendered = current_frame_rendered_;
   current_frame_rendered_ = false;
 
   // Compare current frame with |frame|. Initialize values as if there is no
   // current frame.
   bool is_first_frame = true;
   bool has_frame_size_changed = false;
+  bool frame_content_did_not_change = false;
 
   absl::optional<media::VideoTransformation> new_transform =
       media::kNoTransformation;
@@ -764,8 +801,17 @@ void WebMediaPlayerMSCompositor::SetCurrentFrame(
 
     if (*new_opacity == media::IsOpaque(current_frame_->format()))
       new_opacity.reset();
+#if defined(TIZEN_VIDEO_HOLE)
+    if (frame->storage_type() == media::VideoFrame::STORAGE_HOLE &&
+        current_frame_->storage_type() == media::VideoFrame::STORAGE_HOLE &&
+        !has_frame_size_changed) {
+      frame_content_did_not_change = true;
+    }
+#endif
   }
 
+  if (frame_content_did_not_change)
+    current_frame_rendered_ = previous_frame_rendered;
   current_frame_ = std::move(frame);
   current_frame_is_copy_ = is_copy;
   SetMetadata();
@@ -802,6 +848,7 @@ void WebMediaPlayerMSCompositor::SetCurrentFrame(
       CrossThreadBindOnce(&WebMediaPlayerMSCompositor::CheckForFrameChanges,
                           weak_this_, is_first_frame, has_frame_size_changed,
                           std::move(new_transform), std::move(new_opacity)));
+  return has_frame_size_changed || is_first_frame;
 }
 
 void WebMediaPlayerMSCompositor::CheckForFrameChanges(
index 9b81ccb..ec68749 100644 (file)
@@ -199,7 +199,7 @@ class MODULES_EXPORT WebMediaPlayerMSCompositor
       bool is_copy);
 
   // Update |current_frame_| and |dropped_frame_count_|
-  void SetCurrentFrame(
+  bool SetCurrentFrame(
       scoped_refptr<media::VideoFrame> frame,
       bool is_copy,
       absl::optional<base::TimeTicks> expected_presentation_time);
@@ -248,6 +248,10 @@ class MODULES_EXPORT WebMediaPlayerMSCompositor
   raw_ptr<cc::VideoFrameProvider::Client, DanglingUntriaged>
       video_frame_provider_client_;
 
+#if defined(TIZEN_VIDEO_HOLE)
+  bool video_frame_provider_client_changed_{false};
+#endif
+
   // |current_frame_| is updated only on compositor thread. The object it
   // holds can be freed on the compositor thread if it is the last to hold a
   // reference but media::VideoFrame is a thread-safe ref-pointer. It is
index 6b1d9f3..af00b63 100644 (file)
@@ -245,7 +245,7 @@ void MediaPlayerESPlusPlayer::Initialize(VideoRendererSink* sink) {
   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__
             << " state:" << GetString(GetPlayerState());
 
-  if (!SetBufferType())
+  if (!SetBufferType(VideoDecoderConfig{}))
     return;
 
   sink_ = sink;
@@ -653,8 +653,11 @@ player_buffer_size_t MediaPlayerESPlusPlayer::GetMaxVideoBufferSize(
 int MediaPlayerESPlusPlayer::SetVideoStreamInfo(
     const media::VideoDecoderConfig& video_config,
     esplusplayer_video_stream_info& video_stream_info) {
-  video_stream_info.width = video_config.coded_size().width();
-  video_stream_info.height = video_config.coded_size().height();
+  if (!SetBufferType(video_config)) {
+    LOG_ID(ERROR, player_id_) << "SetBufferType failed.";
+    return ESPLUSPLAYER_ERROR_TYPE_UNKNOWN;
+  }
+
   video_stream_info.mime_type =
       ConvertToESPlusVideoMimeType(video_config.codec());
 
@@ -668,12 +671,36 @@ int MediaPlayerESPlusPlayer::SetVideoStreamInfo(
   } else {
     video_stream_info.codec_data = nullptr;
   }
-  auto max_resolution =
+  auto ri_max_resolution =
       GetMaxResolution(video_stream_info.mime_type, is_video_hole_);
-  LOG(INFO) << "max resolution: " << max_resolution.ToString();
-
-  video_stream_info.max_width = max_resolution.width();
-  video_stream_info.max_height = max_resolution.height();
+  // |video_resolution| is the current video size, |video_max_resolution|
+  // is the potential max video size, it to say that the video source
+  // size may be changed to that size in playback state dynamically.
+  // for every video playback scenarios, the caller should set it to a
+  // suitable value to |video_max_resolution| to avoid decoder resource
+  // waste or resource conflicts.
+  auto video_max_resolution = video_config.max_coded_size();
+  auto video_resolution = video_config.coded_size();
+  LOG_ID(INFO, player_id_) << "Available max resolution from resource manager:"
+                           << ri_max_resolution.ToString()
+                           << " video max resolution:"
+                           << video_max_resolution.ToString()
+                           << " video resolution:"
+                           << video_resolution.ToString();
+
+  // Correct the video max resolution if it is smaller than video resolution.
+  video_max_resolution.SetToMax(video_resolution);
+
+  // Constrain the video resolution within the ri max resolution.
+  video_resolution.SetToMin(ri_max_resolution);
+
+  // Constrain the video max resolution within the ri max resolution.
+  video_max_resolution.SetToMin(ri_max_resolution);
+
+  video_stream_info.max_width = video_max_resolution.width();
+  video_stream_info.max_height = video_max_resolution.height();
+  video_stream_info.width = video_resolution.width();
+  video_stream_info.height = video_resolution.height();
 
   return ESPLUSPLAYER_ERROR_TYPE_NONE;
 }
@@ -990,6 +1017,11 @@ void MediaPlayerESPlusPlayer::ReportBufferingStateIfNeeded(
 }
 
 void MediaPlayerESPlusPlayer::PerformOperationForData() {
+  // The low latency mode doesn't buffer packets. It decodes and renders
+  // a packet at once. WebRtc uses this feature.
+  if (is_video_low_latency_)
+    return;
+
   if (is_seeking_ || is_preparing_)
     return;
 
index ec62e6b..8e8a9bc 100644 (file)
@@ -139,12 +139,13 @@ class MEDIA_EXPORT MediaPlayerESPlusPlayer : public MediaPlayerTizen {
   void SetShouldFeed(DemuxerStream::Type type, bool value);
   bool ReadRequested(DemuxerStream::Type type) const;
   void ReadBuffer(DemuxerStream::Type type);
-  virtual bool SetBufferType() = 0;
+  virtual bool SetBufferType(const media::VideoDecoderConfig&) = 0;
 #if defined(TIZEN_VIDEO_HOLE)
   void PrepareVideoHole() override;
 #endif
 
   bool is_video_hole_ = false;
+  bool is_video_low_latency_ = false;
   int player_id_ = 0;
   // first -> pts, second -> duration
   base::StaticMap<DemuxerStream::Type,
index b2d26bc..e6fa139 100644 (file)
@@ -16,7 +16,8 @@ MediaPlayerESPlusPlayerCommon::~MediaPlayerESPlusPlayerCommon() {
   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
 }
 
-bool MediaPlayerESPlusPlayerCommon::SetBufferType() {
+bool MediaPlayerESPlusPlayerCommon::SetBufferType(
+    const media::VideoDecoderConfig&) {
   if (GetPlayerState() != ESPLUSPLAYER_STATE_IDLE)
     return true;
 
index 48eb779..3d2fd6e 100644 (file)
@@ -15,7 +15,7 @@ class MEDIA_EXPORT MediaPlayerESPlusPlayerCommon
   MediaPlayerESPlusPlayerCommon();
   ~MediaPlayerESPlusPlayerCommon() override;
 
-  bool SetBufferType() override;
+  bool SetBufferType(const media::VideoDecoderConfig&) override;
   void ToggleFullscreenMode(bool is_fullscreen) override;
 #if defined(TIZEN_VIDEO_HOLE)
   void PrepareVideoHole() override;
index a56e135..f76d963 100644 (file)
@@ -219,17 +219,85 @@ player_buffer_size_t MediaPlayerESPlusPlayerTV::GetMaxVideoBufferSize(
   return total_buffer_size - kPlayerAudioBufferSize;
 }
 
-bool MediaPlayerESPlusPlayerTV::SetBufferType() {
-  esplusplayer_decoded_video_frame_buffer_type video_frame_buffer_type =
-      is_video_hole_ ? ESPLUSPLAYER_DECODED_VIDEO_FRAME_BUFFER_TYPE_NONE
-                     : ESPLUSPLAYER_DECODED_VIDEO_FRAME_BUFFER_TYPE_COPY;
+void MediaPlayerESPlusPlayerTV::SetTbmCallbackPolicy(
+    const media::VideoDecoderConfig& video_config) {
+  auto policy = ESPLUSPLAYER_RSC_ALLOC_EXCLUSIVE;
+#if TIZEN_VERSION_AT_LEAST(8, 0, 0)
+  // Although we set the decoder config to fit the spec of mfc decoder in
+  // hopes of getting its priority, some other tizen apps (e.g. live TV) may
+  // still hold the mfc even they go into background. so it requires us to set
+  // proper RM policy to force ESPP to acquire a mfc decoder ownership from
+  // these apps.
+  policy = ESPLUSPLAYER_RSC_ALLOC_EXCLUSIVE_MFC_FORCED;
+#endif  // TIZEN_VERSION_AT_LEAST(8, 0, 0)
+
+#if defined(TIZEN_MULTIMEDIA_MJPEG_SUPPORT)
+  if (video_config.codec() == VideoCodec::kMJPEG) {
+    policy = ESPLUSPLAYER_RSC_ALLOC_EXCLUSIVE;
+  }
+#endif  // defined(TIZEN_MULTIMEDIA_MJPEG_SUPPORT)
+  LOG_ID(INFO, player_id_) << " Set RM policy for Tbm:"
+                           << static_cast<int>(policy);
+
+  auto error = esplusplayer_set_resource_allocate_policy(esplayer_, policy);
+  if (error != ESPLUSPLAYER_ERROR_TYPE_NONE) {
+    LOG_ID(ERROR, player_id_)
+        << "esplusplayer_set_resource_allocate_policy failed. error #"
+        << esplusplayer_get_error_string(
+               static_cast<esplusplayer_error_type>(error));
+  }
+}
 
-  int error = esplusplayer_set_video_frame_buffer_type(esplayer_,
-                                                       video_frame_buffer_type);
+bool MediaPlayerESPlusPlayerTV::SetBufferType(
+    const media::VideoDecoderConfig& video_config) {
+  if (!video_config.IsValidConfig()) {
+    LOG_ID(INFO, player_id_) << "Invalid video config.";
+    return false;
+  }
+
+  if (enable_tbm_buffer_callback_) {
+    LOG_ID(INFO, player_id_) << "Recall EnableTbmBufferCallback.";
+    SetTbmCallbackPolicy(video_config);
+    EnableTbmBufferCallback(true);
+    return true;
+  }
+
+  if (!is_video_hole_) {
+    decoded_frame_buffer_type_ =
+        ESPLUSPLAYER_DECODED_VIDEO_FRAME_BUFFER_TYPE_COPY;
+  }
+
+#if defined(TIZEN_VIDEO_HOLE) && defined(TIZEN_TBM_SUPPORT) && \
+    TIZEN_VERSION_AT_LEAST(6, 5, 0)
+  bool enable_frame_raw_data_copy =
+      base::CommandLine::ForCurrentProcess()->HasSwitch(
+          switches::kEnableFrameRawDataCopy);
+  LOG_ID(INFO, player_id_) << "(" << static_cast<void*>(this) << ") "
+                           << __func__ << ", kEnableFrameRawDataCopy: "
+                           << enable_frame_raw_data_copy;
+
+  if (video_config.enable_manual_copy()) {
+    // `enable_manual_copy` means there is a potential requirement to enable
+    // TBM decoded data return, but this function is only available on mfc &
+    // mjpeg decoders.
+    SetTbmCallbackPolicy(video_config);
+
+    if (is_video_hole_ && !is_video_drm_eme_ && enable_frame_raw_data_copy) {
+      // should ensure App can get frame buffer by canvas2d API drawImage and
+      // getImageData
+      decoded_frame_buffer_type_ =
+          ESPLUSPLAYER_DECODED_VIDEO_FRAME_BUFFER_TYPE_MANUAL_COPY;
+    }
+  }
+#endif
+
+  int error = esplusplayer_set_video_frame_buffer_type(
+      esplayer_, decoded_frame_buffer_type_);
   if (error != ESPLUSPLAYER_ERROR_TYPE_NONE) {
-    LOG(ERROR) << "esplusplayer_set_video_frame_buffer_type failed. error #"
-               << esplusplayer_get_error_string(
-                      static_cast<esplusplayer_error_type>(error));
+    LOG_ID(ERROR, player_id_)
+        << "esplusplayer_set_video_frame_buffer_type failed. error #"
+        << esplusplayer_get_error_string(
+               static_cast<esplusplayer_error_type>(error));
     return false;
   }
 
index 0a23727..8aa5b27 100644 (file)
@@ -66,9 +66,10 @@ class MEDIA_EXPORT MediaPlayerESPlusPlayerTV : public MediaPlayerESPlusPlayer {
       DemuxerStream::Type type,
       scoped_refptr<DecoderBuffer> buffer) override;
   void InitializeStreamConfig(DemuxerStream::Type type) override;
-  bool SetBufferType() override;
+  bool SetBufferType(const media::VideoDecoderConfig& video_config) override;
   player_buffer_size_t GetMaxVideoBufferSize(
       const media::VideoDecoderConfig& video_config) override;
+  void SetTbmCallbackPolicy(const media::VideoDecoderConfig& video_config);
 
  private:
 #if TIZEN_VERSION_AT_LEAST(6, 0, 0)
@@ -118,7 +119,6 @@ class MEDIA_EXPORT MediaPlayerESPlusPlayerTV : public MediaPlayerESPlusPlayer {
   bool is_hdr_changed_{false};
   esplusplayer_matroska_color matroska_color_;
 
-  bool is_video_low_latency_{false};
   esplusplayer_decoded_video_frame_buffer_type decoded_frame_buffer_type_{
       ESPLUSPLAYER_DECODED_VIDEO_FRAME_BUFFER_TYPE_NONE};
   bool enable_tbm_buffer_callback_{false};
index 1bef1ed..ea7dab6 100644 (file)
 #endif
 
 namespace gfx {
+#if defined(TIZEN_TBM_SUPPORT)
+// There are 2 flows could trigger TBM destroy: GLImageEGL::~GLImageEGL()
+// and TizenEsPlusPlayerRenderer::ReleaseTbmBuffer;
+// Define a type to specify how to destroy TBM.
+enum TbmDestroyType {
+  // triggered by GLImageEGL::~GLImageEGL()
+  kDestroyTbmByEgl = 0,
+  // triggered by video frame DestructionObserver
+  kDestroyTbmByVideoFrame = 1,
+};
+#endif
 
 struct GFX_EXPORT TbmBufferHandle {
   TbmBufferHandle() {}
 #if defined(TIZEN_TBM_SUPPORT)
   size_t tbm_surface{0};
   size_t media_packet{0};
+  TbmDestroyType tbm_destroy_type = kDestroyTbmByEgl;
   int32_t player_id = 0;
   int32_t key_num = 0;
   int32_t key[4];
index 74be880..56272bb 100644 (file)
 #include "base/android/scoped_hardware_buffer_handle.h"
 #endif
 
+#if defined(TIZEN_TBM_SUPPORT)
+#include "ui/gfx/tbm_buffer_handle.h"
+#endif
+
 namespace base {
 namespace trace_event {
 class ProcessMemoryDump;
@@ -88,6 +92,7 @@ struct GFX_EXPORT GpuMemoryBufferHandle {
 #if defined(TIZEN_TBM_SUPPORT)
   size_t tbm_surface{0};
   size_t media_packet{0};
+  TbmDestroyType tbm_destroy_type = kDestroyTbmByEgl;
   int32_t player_id = 0;
   int32_t key_num = 0;
   int32_t key[4];
index 2a5a793..bbfb870 100644 (file)
@@ -88,6 +88,10 @@ mojom("mojom") {
           copyable_pass_by_value = true
         },
         {
+          mojom = "gfx.mojom.TbmDestroyType"
+          cpp = "::gfx::TbmDestroyType"
+        },
+        {
           mojom = "gfx.mojom.GpuMemoryBufferType"
           cpp = "::gfx::GpuMemoryBufferType"
         },
index c285550..88c3c04 100644 (file)
@@ -62,6 +62,13 @@ struct GpuMemoryBufferId {
   int32 id;
 };
 
+// gfx::TbmDestroyType
+[EnableIf=tizen_tbm_support]
+enum TbmDestroyType {
+  kDestroyTbmByEgl = 0,
+  kDestroyTbmByVideoFrame = 1,
+};
+
 // gfx::GpuMemoryBufferHandle
 struct GpuMemoryBufferHandle {
   GpuMemoryBufferId id;
@@ -75,6 +82,9 @@ struct GpuMemoryBufferHandle {
   uint64 media_packet;
 
   [EnableIf=tizen_tbm_support]
+  TbmDestroyType tbm_destroy_type;
+
+  [EnableIf=tizen_tbm_support]
   int32 player_id;
 
   [EnableIf=tizen_tbm_support]
@@ -104,6 +114,9 @@ struct TbmBufferHandle {
   uint32 media_packet;
 
   [EnableIf=tizen_tbm_support]
+  TbmDestroyType tbm_destroy_type;
+
+  [EnableIf=tizen_tbm_support]
   int32 player_id;
 
   [EnableIf=tizen_tbm_support]
index 5f95c30..d990b94 100644 (file)
@@ -105,6 +105,7 @@ bool StructTraits<gfx::mojom::GpuMemoryBufferHandleDataView,
   out->key_num = data.key_num();
   out->width = data.width();
   out->height = data.height();
+  data.ReadTbmDestroyType(&out->tbm_destroy_type);
   base::span<int32_t> key(out->key);
   if (!data.ReadKey(&key))
     return false;
@@ -206,6 +207,7 @@ bool StructTraits<gfx::mojom::TbmBufferHandleDataView, gfx::TbmBufferHandle>::
   out->key_num = data.key_num();
   out->width = data.width();
   out->height = data.height();
+  data.ReadTbmDestroyType(&out->tbm_destroy_type);
   base::span<int32_t> key(out->key);
   if (!data.ReadKey(&key))
     return false;
index 609f420..2146030 100644 (file)
@@ -266,6 +266,10 @@ struct COMPONENT_EXPORT(GFX_SHARED_MOJOM_TRAITS)
   static int32_t height(const gfx::GpuMemoryBufferHandle& handle) {
     return handle.height;
   }
+  static gfx::TbmDestroyType tbm_destroy_type(
+      const gfx::GpuMemoryBufferHandle& handle) {
+    return handle.tbm_destroy_type;
+  }
 #endif
   static mojo::StructPtr<gfx::mojom::GpuMemoryBufferPlatformHandle>
   platform_handle(gfx::GpuMemoryBufferHandle& handle);
@@ -300,10 +304,42 @@ struct COMPONENT_EXPORT(GFX_SHARED_MOJOM_TRAITS)
   static int32_t height(const gfx::TbmBufferHandle& handle) {
     return handle.height;
   }
-
+  static gfx::TbmDestroyType tbm_destroy_type(
+      const gfx::TbmBufferHandle& handle) {
+    return handle.tbm_destroy_type;
+  }
   static bool Read(gfx::mojom::TbmBufferHandleDataView data,
                    gfx::TbmBufferHandle* handle);
 };
+
+template <>
+struct COMPONENT_EXPORT(GFX_SHARED_MOJOM_TRAITS)
+    EnumTraits<gfx::mojom::TbmDestroyType, gfx::TbmDestroyType> {
+  static gfx::mojom::TbmDestroyType ToMojom(gfx::TbmDestroyType type) {
+    switch (type) {
+      case gfx::TbmDestroyType::kDestroyTbmByVideoFrame:
+        return gfx::mojom::TbmDestroyType::kDestroyTbmByVideoFrame;
+      case gfx::TbmDestroyType::kDestroyTbmByEgl:
+        return gfx::mojom::TbmDestroyType::kDestroyTbmByEgl;
+    }
+    NOTREACHED();
+    return gfx::mojom::TbmDestroyType::kDestroyTbmByVideoFrame;
+  }
+
+  static bool FromMojom(gfx::mojom::TbmDestroyType input,
+                        gfx::TbmDestroyType* out) {
+    switch (input) {
+      case gfx::mojom::TbmDestroyType::kDestroyTbmByVideoFrame:
+        *out = gfx::TbmDestroyType::kDestroyTbmByVideoFrame;
+        return true;
+      case gfx::mojom::TbmDestroyType::kDestroyTbmByEgl:
+        *out = gfx::TbmDestroyType::kDestroyTbmByEgl;
+        return true;
+    }
+    NOTREACHED();
+    return false;
+  }
+};
 #endif
 
 template <>