[M120 Migration] Notify media device state to webbrowser 71/306871/5
authorzhishun.zhou <zhishun.zhou@samsung.com>
Wed, 28 Feb 2024 10:00:23 +0000 (18:00 +0800)
committerBot Blink <blinkbot@samsung.com>
Fri, 1 Mar 2024 06:11:58 +0000 (06:11 +0000)
1) web engine get current user media state from media device.
2) web engine notify webbrowser state by ewk callback.

Add new ewk type:
UserMediaState

DECLARE_EWK_VIEW_CALLBACK(UserMediaState, "usermedia,state", void*)

From patch:
https://review.tizen.org/gerrit/#/c/294421/

Change-Id: I6acab4de98627aa478017512da79f1e0520236f8
Signed-off-by: zhishun.zhou <zhishun.zhou@samsung.com>
Signed-off-by: xiaofang <fang.xiao@samsung.com>
26 files changed:
content/browser/renderer_host/media/media_stream_manager.cc
content/browser/renderer_host/media/media_stream_manager.h
content/browser/renderer_host/media/render_frame_audio_input_stream_factory.cc
content/public/browser/web_contents_delegate.h
content/renderer/render_frame_impl.h
media/mojo/mojom/BUILD.gn
media/mojo/mojom/audio_input_stream.mojom
services/audio/input_controller.cc
services/audio/input_controller.h
services/audio/input_stream.cc
services/audio/input_stream.h
services/audio/public/cpp/input_ipc.h
third_party/blink/public/mojom/media/renderer_audio_input_stream_factory.mojom
third_party/blink/public/web/web_local_frame_client.h
third_party/blink/renderer/modules/media/audio/audio_input_ipc_factory.cc
third_party/blink/renderer/modules/media/audio/mojo_audio_input_ipc.cc
third_party/blink/renderer/modules/media/audio/mojo_audio_input_ipc.h
tizen_src/chromium_impl/media/audio/tizen/capi_audio_input.h
tizen_src/chromium_impl/media/capture/video/tizen/camera_device_tizen.cc
tizen_src/chromium_impl/media/capture/video/tizen/camera_device_tizen.h
tizen_src/chromium_impl/media/capture/video/tizen/video_capture_device_tizen.cc
tizen_src/chromium_impl/media/capture/video/tizen/video_capture_device_tizen.h
tizen_src/ewk/efl_integration/eweb_view.cc
tizen_src/ewk/efl_integration/eweb_view.h
tizen_src/ewk/efl_integration/web_contents_delegate_efl.cc
tizen_src/ewk/efl_integration/web_contents_delegate_efl.h

index 7cc2d2d..78a925a 100644 (file)
 #include "chromeos/lacros/lacros_service.h"
 #endif
 
+#if BUILDFLAG(IS_TIZEN_TV)
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents_delegate.h"
+#endif
+
 using blink::mojom::MediaDeviceType;
 
 namespace content {
@@ -1628,6 +1633,11 @@ void MediaStreamManager::GenerateStreams(
         device_capture_configuration_change_cb,
     DeviceCaptureHandleChangeCallback device_capture_handle_change_cb) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
+
+#if BUILDFLAG(IS_TIZEN_TV)
+  render_frame_host_id_ = render_frame_host_id;
+#endif
+
   SendLogMessage(GetGenerateStreamsLogString(render_frame_host_id, requester_id,
                                              page_request_id));
   std::unique_ptr<DeviceRequest> request =
@@ -2423,6 +2433,28 @@ void MediaStreamManager::PostRequestToUI(
                          media::AudioParameters::UnavailableDeviceParams())));
 }
 
+#if BUILDFLAG(IS_TIZEN_TV)
+void MediaStreamManager::NotifyMediaStateChanged(uint32_t type,
+                                                 uint32_t previous,
+                                                 uint32_t current) {
+  content::WebContents* web_contents =
+      content::WebContents::FromRenderFrameHost(
+          content::RenderFrameHost::FromID(render_frame_host_id_));
+  if (!web_contents) {
+    LOG(ERROR) << "web_contents is null";
+    return;
+  }
+
+  content::WebContentsDelegate* web_contents_delegate =
+      web_contents->GetDelegate();
+  if (!web_contents_delegate) {
+    LOG(ERROR) << "web_contents_delegate is null";
+    return;
+  }
+
+  web_contents_delegate->NotifyMediaStateChanged(type, previous, current);
+}
+#endif
 void MediaStreamManager::SetUpRequest(const std::string& label) {
   DCHECK_CURRENTLY_ON(BrowserThread::IO);
 
index 840fe68..4434172 100644 (file)
@@ -59,6 +59,10 @@ class Origin;
 
 namespace content {
 
+#if BUILDFLAG(IS_TIZEN_TV)
+enum MediaInputStreamType { NO_STREAM, AUDIO_CAPTURE, VIDEO_CAPTURE };
+#endif
+
 class AudioInputDeviceManager;
 class AudioServiceListener;
 class FakeMediaStreamUIProxy;
@@ -339,6 +343,13 @@ class CONTENT_EXPORT MediaStreamManager
   void NotifyDevicesChanged(blink::mojom::MediaDeviceType stream_type,
                             const blink::WebMediaDeviceInfoArray& devices);
 
+#if BUILDFLAG(IS_TIZEN_TV)
+  // Notify media(camera/microphone) status change to web browser.
+  void NotifyMediaStateChanged(uint32_t type,
+                               uint32_t previous,
+                               uint32_t current);
+#endif
+
   // This method is called when an audio or video device is removed. It makes
   // sure all MediaStreams that use a removed device are stopped and that the
   // render process is notified. Must be called on the IO thread.
@@ -759,6 +770,10 @@ class CONTENT_EXPORT MediaStreamManager
   mojo::UniqueReceiverSet<media::mojom::VideoCaptureHost> video_capture_hosts_;
 
   GenerateStreamTestCallback generate_stream_test_callback_;
+
+#if BUILDFLAG(IS_TIZEN_TV)
+  GlobalRenderFrameHostId render_frame_host_id_;
+#endif
 };
 
 }  // namespace content
index 587a9ee..6af445d 100644 (file)
 #include "third_party/blink/public/common/mediastream/media_stream_request.h"
 #include "url/origin.h"
 
+#if BUILDFLAG(IS_TIZEN_TV)
+#include "content/browser/browser_main_loop.h"
+#endif
+
 using blink::mojom::MediaDeviceType;
 
 namespace content {
@@ -158,6 +162,11 @@ class RenderFrameAudioInputStreamFactory::Core final
       const base::UnguessableToken& input_stream_id,
       const std::string& raw_output_device_id);
 
+#if BUILDFLAG(IS_TIZEN_TV)
+  void OnMediaStateChanged(uint32_t previous, uint32_t current);
+  void NotifyMediaStateChanged(uint32_t previous, uint32_t current);
+#endif
+
   const raw_ptr<MediaStreamManager> media_stream_manager_;
   const int process_id_;
   const int frame_id_;
@@ -362,4 +371,33 @@ void RenderFrameAudioInputStreamFactory::Core::
                                                      raw_output_device_id);
 }
 
+#if BUILDFLAG(IS_TIZEN_TV)
+void RenderFrameAudioInputStreamFactory::Core::OnMediaStateChanged(
+    uint32_t previous,
+    uint32_t current) {
+  DCHECK_CURRENTLY_ON(BrowserThread::IO);
+  GetUIThreadTaskRunner({})->PostTask(
+      FROM_HERE,
+      base::BindOnce(&Core::NotifyMediaStateChanged,
+                     weak_ptr_factory_.GetWeakPtr(), previous, current));
+}
+
+void RenderFrameAudioInputStreamFactory::Core::NotifyMediaStateChanged(
+    uint32_t previous,
+    uint32_t current) {
+  content::BrowserMainLoop* browser_main_loop =
+      content::BrowserMainLoop::GetInstance();
+  if (!browser_main_loop) {
+    LOG(ERROR) << "browser_main_loop is null";
+    return;
+  }
+  content::MediaStreamManager* msm = browser_main_loop->media_stream_manager();
+  if (!msm) {
+    LOG(ERROR) << "MediaStreamManager is null";
+    return;
+  }
+  msm->NotifyMediaStateChanged(content::MediaInputStreamType::AUDIO_CAPTURE,
+                               previous, current);
+}
+#endif
 }  // namespace content
index f552c07..e7cdfd4 100644 (file)
@@ -734,6 +734,12 @@ class CONTENT_EXPORT WebContentsDelegate {
   // Picture-in-Picture mode has ended.
   virtual void ExitPictureInPicture() {}
 
+#if BUILDFLAG(IS_TIZEN_TV)
+  // Notify Media State to Web browser
+  virtual void NotifyMediaStateChanged(uint32_t type,
+                                       uint32_t previous,
+                                       uint32_t current) {};
+#endif
 #if BUILDFLAG(IS_ANDROID)
   // Updates information to determine whether a user gesture should carryover to
   // future navigations. This is needed so navigations within a certain
index cdc7c32..1996d43 100644 (file)
@@ -636,7 +636,8 @@ class CONTENT_EXPORT RenderFrameImpl
   blink::WebEncryptedMediaClient* EncryptedMediaClient() override;
   blink::WebString UserAgentOverride() override;
   absl::optional<blink::UserAgentMetadata> UserAgentMetadataOverride() override;
-  blink::mojom::RendererAudioInputStreamFactory* GetAudioInputStreamFactory();
+  blink::mojom::RendererAudioInputStreamFactory* GetAudioInputStreamFactory()
+      override;
   bool AllowContentInitiatedDataUrlNavigations(
       const blink::WebURL& url) override;
   void PostAccessibilityEvent(const ui::AXEvent& event) override;
index f6658cd..84f8d98 100644 (file)
@@ -133,6 +133,10 @@ mojom("mojom") {
     enabled_features += [ "tizen_video_hole" ]
   }
 
+  if (tizen_product_tv) {
+    enabled_features += [ "is_tizen_tv" ]
+  }
+
   shared_typemaps = [
     {
       types = [
index ddc547a..5437365 100644 (file)
@@ -23,6 +23,9 @@ interface AudioInputStream {
 interface AudioInputStreamClient {
   OnError(InputStreamErrorCode code);
   OnMutedStateChanged(bool is_muted);
+
+  [EnableIf=is_tizen_tv]
+  OnMediaStateChanged(uint32 previous, uint32 current);
 };
 
 // An AudioInputStreamObserver gets notifications about events related to an
index aaa1f46..b569c15 100644 (file)
@@ -333,8 +333,12 @@ void InputController::Record() {
   DCHECK(task_runner_->BelongsToCurrentThread());
   SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.RecordTime");
 
-  if (!stream_ || audio_callback_)
+  if (!stream_ || audio_callback_) {
+#if BUILDFLAG(IS_TIZEN_TV)
+    OnMediaStateChanged(AUDIO_IO_ERROR);
+#endif
     return;
+  }
 
   event_handler_->OnLog("AIC::Record()");
 
@@ -370,6 +374,10 @@ void InputController::Record() {
 #endif
 
   stream_->Start(audio_callback_.get());
+#if BUILDFLAG(IS_TIZEN_TV)
+  OnMediaStateChanged(AUDIO_IO_STARTED);
+#endif
+
   return;
 }
 
@@ -377,8 +385,12 @@ void InputController::Close() {
   DCHECK(task_runner_->BelongsToCurrentThread());
   SCOPED_UMA_HISTOGRAM_TIMER("Media.AudioInputController.CloseTime");
 
-  if (!stream_)
+  if (!stream_) {
+#if BUILDFLAG(IS_TIZEN_TV)
+    OnMediaStateChanged(AUDIO_IO_ERROR);
+#endif
     return;
+  }
 
   check_muted_state_timer_.AbandonAndStop();
 
@@ -446,6 +458,10 @@ void InputController::Close() {
   stream_->Close();
   stream_ = nullptr;
 
+#if BUILDFLAG(IS_TIZEN_TV)
+  OnMediaStateChanged(AUDIO_IO_STOPPED);
+#endif
+
   sync_writer_->Close();
 
 #if defined(AUDIO_POWER_MONITORING)
@@ -550,6 +566,9 @@ void InputController::DoCreate(media::AudioManager* audio_manager,
   if (!stream) {
     LogCaptureStartupResult(CAPTURE_STARTUP_CREATE_STREAM_FAILED);
     event_handler_->OnError(STREAM_CREATE_ERROR);
+#if BUILDFLAG(IS_TIZEN_TV)
+    OnMediaStateChanged(AUDIO_IO_ERROR);
+#endif
     return;
   }
 
@@ -558,6 +577,9 @@ void InputController::DoCreate(media::AudioManager* audio_manager,
     stream->Close();
     LogCaptureStartupResult(CAPTURE_STARTUP_OPEN_STREAM_FAILED);
     event_handler_->OnError(MapOpenOutcomeToErrorCode(open_outcome));
+#if BUILDFLAG(IS_TIZEN_TV)
+    OnMediaStateChanged(AUDIO_IO_ERROR);
+#endif
     return;
   }
 
@@ -782,6 +804,18 @@ void InputController::DeliverProcessedAudio(
 }
 #endif
 
+#if BUILDFLAG(IS_TIZEN_TV)
+void InputController::OnMediaStateChanged(uint32_t current_state) {
+  DCHECK_CALLED_ON_VALID_THREAD(owning_thread_);
+  if (current_state != previous_state_) {
+    LOG(INFO) << "microphone state change previous: " << previous_state_
+              << " ;current : " << current_state;
+    event_handler_->OnMediaStateChanged(previous_state_, current_state);
+    previous_state_ = current_state;
+  }
+}
+#endif
+
 // static
 InputController::StreamType InputController::ParamsToStreamType(
     const media::AudioParameters& params) {
index 884ade5..0d16241 100644 (file)
@@ -47,6 +47,15 @@ class OutputTapper;
 class DeviceOutputListener;
 class ProcessingAudioFifo;
 
+#if BUILDFLAG(IS_TIZEN_TV)
+enum AudioIOState {
+  AUDIO_IO_IDLE,
+  AUDIO_IO_STARTED,
+  AUDIO_IO_STOPPED,
+  AUDIO_IO_ERROR
+};
+#endif
+
 // Only do power monitoring for non-mobile platforms to save resources.
 #if !BUILDFLAG(IS_ANDROID) && !BUILDFLAG(IS_IOS)
 #define AUDIO_POWER_MONITORING
@@ -141,6 +150,9 @@ class InputController final : public StreamMonitor {
     virtual void OnLog(base::StringPiece) = 0;
     // Called whenever the muted state of the underlying stream changes.
     virtual void OnMuted(bool is_muted) = 0;
+#if BUILDFLAG(IS_TIZEN_TV)
+    virtual void OnMediaStateChanged(uint32_t previous, uint32_t current) = 0;
+#endif
 
    protected:
     virtual ~EventHandler() {}
@@ -209,6 +221,10 @@ class InputController final : public StreamMonitor {
   void OnStreamActive(Snoopable* snoopable) override;
   void OnStreamInactive(Snoopable* snoopable) override;
 
+#if BUILDFLAG(IS_TIZEN_TV)
+  void OnMediaStateChanged(uint32_t current);
+#endif
+
  private:
   friend class InputControllerTestHelper;
 
@@ -371,6 +387,10 @@ class InputController final : public StreamMonitor {
   // in the AudioCallback class in the cc file.
   std::unique_ptr<AudioCallback> audio_callback_;
 
+#if BUILDFLAG(IS_TIZEN_TV)
+  uint32_t previous_state_{AUDIO_IO_IDLE};
+#endif
+
   // A weak pointer factory that we use when posting tasks to the audio thread
   // that we want to be automatically discarded after Close() has been called
   // and that we do not want to keep the InputController instance alive
index fbcb609..220a7b0 100644 (file)
@@ -321,4 +321,12 @@ void InputStream::SendLogMessage(const char* format, ...) {
   va_end(args);
 }
 
+#if BUILDFLAG(IS_TIZEN_TV)
+void InputStream::OnMediaStateChanged(uint32_t previous, uint32_t current) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
+  if (client_.get()) {
+    client_->OnMediaStateChanged(previous, current);
+  }
+}
+#endif
 }  // namespace audio
index 1b08341..db99d85 100644 (file)
@@ -76,6 +76,10 @@ class InputStream final : public media::mojom::AudioInputStream,
   void OnLog(base::StringPiece) override;
   void OnMuted(bool is_muted) override;
 
+#if BUILDFLAG(IS_TIZEN_TV)
+  void OnMediaStateChanged(uint32_t previous, uint32_t current) override;
+#endif
+
  private:
   void OnStreamError(
       absl::optional<media::mojom::AudioInputStreamObserver::DisconnectReason>
index 258ae0e..ebdd2bd 100644 (file)
@@ -54,6 +54,10 @@ class COMPONENT_EXPORT(AUDIO_PUBLIC_CPP) InputIPC
   void OnError(media::mojom::InputStreamErrorCode code) override;
   void OnMutedStateChanged(bool is_muted) override;
 
+#if BUILDFLAG(IS_TIZEN_TV)
+  void OnMediaStateChanged(uint32_t previous, uint32_t current) override {}
+#endif
+
   void StreamCreated(media::mojom::ReadOnlyAudioDataPipePtr data_pipe,
                      bool is_muted,
                      const absl::optional<base::UnguessableToken>& stream_id);
index dde423c..d7281b8 100644 (file)
@@ -34,6 +34,10 @@ interface RendererAudioInputStreamFactory {
   AssociateInputAndOutputForAec(
       mojo_base.mojom.UnguessableToken input_stream_id,
       string output_device_id);
+
+  // Notify Audio device state to web browser
+  [EnableIf=is_tizen_tv]
+  OnMediaStateChanged(uint32 previous, uint32 current);
 };
 
 interface RendererAudioInputStreamFactoryClient {
index 0931182..6fdde7c 100644 (file)
@@ -63,6 +63,7 @@
 #include "third_party/blink/public/mojom/frame/user_activation_update_types.mojom-shared.h"
 #include "third_party/blink/public/mojom/loader/same_document_navigation_type.mojom-shared.h"
 #include "third_party/blink/public/mojom/media/renderer_audio_input_stream_factory.mojom-shared.h"
+#include "third_party/blink/public/mojom/media/renderer_audio_input_stream_factory.mojom.h"
 #include "third_party/blink/public/mojom/portal/portal.mojom-shared.h"
 #include "third_party/blink/public/platform/child_url_loader_factory_bundle.h"
 #include "third_party/blink/public/platform/cross_variant_mojo_util.h"
@@ -790,6 +791,11 @@ class BLINK_EXPORT WebLocalFrameClient {
       const base::UnguessableToken& input_stream_id,
       const std::string& output_device_id) {}
 
+  virtual blink::mojom::RendererAudioInputStreamFactory*
+  GetAudioInputStreamFactory() {
+    return nullptr;
+  }
+
   // Notifies the observers of the origins for which subresource redirect
   // optimizations can be preloaded.
   virtual void PreloadSubresourceOptimizationsForOrigins(
index c882187..339001e 100644 (file)
@@ -90,7 +90,7 @@ std::unique_ptr<media::AudioInputIPC> AudioInputIPCFactory::CreateAudioInputIPC(
     const media::AudioSourceParameters& source_params) {
   CHECK(!source_params.session_id.is_empty());
   return std::make_unique<MojoAudioInputIPC>(
-      source_params,
+      frame_token, source_params,
       base::BindRepeating(&CreateMojoAudioInputStream, main_task_runner,
                           frame_token),
       base::BindRepeating(&AssociateInputAndOutputForAec, main_task_runner,
index 9ae6fee..fa9d962 100644 (file)
 namespace blink {
 
 MojoAudioInputIPC::MojoAudioInputIPC(
+    const blink::LocalFrameToken& frame_token,
     const media::AudioSourceParameters& source_params,
     StreamCreatorCB stream_creator,
     StreamAssociatorCB stream_associator)
     : source_params_(source_params),
+#if BUILDFLAG(IS_TIZEN_TV)
+      frame_token_(frame_token),
+#endif
       stream_creator_(std::move(stream_creator)),
       stream_associator_(std::move(stream_associator)) {
   DETACH_FROM_SEQUENCE(sequence_checker_);
@@ -85,6 +89,16 @@ media::AudioProcessorControls* MojoAudioInputIPC::GetProcessorControls() {
 
 void MojoAudioInputIPC::CloseStream() {
   DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+#if BUILDFLAG(IS_TIZEN_TV)
+  auto* web_frame = static_cast<WebLocalFrame*>(
+      blink::WebFrame::FromFrameToken(frame_token_));
+  if (web_frame) {
+    web_frame->Client()->GetAudioInputStreamFactory()->OnMediaStateChanged(
+        audio_previous_state_, audio::AUDIO_IO_IDLE);
+    audio_previous_state_ = audio::AUDIO_IO_IDLE;
+  }
+#endif
+
   delegate_ = nullptr;
   factory_client_receiver_.reset();
   stream_client_receiver_.reset();
@@ -153,4 +167,17 @@ void MojoAudioInputIPC::OnMutedStateChanged(bool is_muted) {
   delegate_->OnMuted(is_muted);
 }
 
+#if BUILDFLAG(IS_TIZEN_TV)
+void MojoAudioInputIPC::OnMediaStateChanged(uint32_t previous,
+                                            uint32_t current) {
+  DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
+  auto* web_frame = static_cast<WebLocalFrame*>(
+      blink::WebFrame::FromFrameToken(frame_token_));
+  if (web_frame) {
+    audio_previous_state_ = current;
+    web_frame->Client()->GetAudioInputStreamFactory()->OnMediaStateChanged(
+        previous, current);
+  }
+}
+#endif
 }  // namespace blink
index c0adcba..a5a8ecf 100644 (file)
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "third_party/blink/public/mojom/media/renderer_audio_input_stream_factory.mojom-blink.h"
+#include "third_party/blink/public/web/web_local_frame.h"
+#include "third_party/blink/public/web/web_local_frame_client.h"
 #include "third_party/blink/renderer/modules/modules_export.h"
 
+#if BUILDFLAG(IS_TIZEN_TV)
+#include "services/audio/input_controller.h"
+#endif
+
 namespace blink {
 
 // MojoAudioInputIPC is a renderer-side class for handling creation,
@@ -51,7 +57,8 @@ class MODULES_EXPORT MojoAudioInputIPC
       base::RepeatingCallback<void(const base::UnguessableToken& stream_id,
                                    const std::string& output_device_id)>;
 
-  MojoAudioInputIPC(const media::AudioSourceParameters& source_params,
+  MojoAudioInputIPC(const blink::LocalFrameToken& frame_token,
+                    const media::AudioSourceParameters& source_params,
                     StreamCreatorCB stream_creator,
                     StreamAssociatorCB stream_associator);
 
@@ -86,12 +93,19 @@ class MODULES_EXPORT MojoAudioInputIPC
       const absl::optional<base::UnguessableToken>& stream_id) override;
   void OnError(media::mojom::InputStreamErrorCode code) override;
   void OnMutedStateChanged(bool is_muted) override;
+#if BUILDFLAG(IS_TIZEN_TV)
+  void OnMediaStateChanged(uint32_t previous, uint32_t current) override;
+#endif
 
   void OnDisconnect(uint32_t error, const std::string& reason);
 
   SEQUENCE_CHECKER(sequence_checker_);
 
   const media::AudioSourceParameters source_params_;
+#if BUILDFLAG(IS_TIZEN_TV)
+  const blink::LocalFrameToken frame_token_;
+  uint32_t audio_previous_state_{audio::AUDIO_IO_IDLE};
+#endif
 
   StreamCreatorCB stream_creator_;
   StreamAssociatorCB stream_associator_;
index bc9bd4b..826139f 100644 (file)
@@ -60,7 +60,7 @@ class CapiAudioInputStream : public AgcAudioStream<AudioInputStream> {
   AudioBlockFifo fifo_;
 
  private:
-  AudioManagerCapi* audio_manager_;
+  AudioManagerCapi* audio_manager_{nullptr};
   double volume_;
 };
 
index 62a2236..2fab2f0 100644 (file)
@@ -1054,4 +1054,14 @@ int CameraHandle::CameraSetStreamFlip(camera_flip_e flip) {
   return camera_attr_set_stream_flip(camera_handle_, flip);
 }
 
+#if BUILDFLAG(IS_TIZEN_TV)
+int CameraHandle::CameraSetStateChangedCb(camera_state_changed_cb callback,
+                                          void* data) {
+  return camera_set_state_changed_cb(camera_handle_, callback, data);
+}
+
+int CameraHandle::CameraUnSetStateChangedCb() {
+  return camera_unset_state_changed_cb(camera_handle_);
+}
+#endif
 }  // namespace media
index 09adc72..e49d786 100644 (file)
@@ -188,6 +188,11 @@ class CameraHandle final {
   CameraHandle(const CameraHandle&) = delete;
   CameraHandle& operator=(const CameraHandle&) = delete;
 
+#if BUILDFLAG(IS_TIZEN_TV)
+  int CameraSetStateChangedCb(camera_state_changed_cb callback, void* data);
+  int CameraUnSetStateChangedCb();
+#endif
+
  private:
   bool GetSupportedPreviewResolutions(
       std::vector<CameraCapability::Resolution>& supported_resolutions) const;
index 1003d4f..69836c0 100644 (file)
 #include "ui/display/display.h"
 #include "ui/display/screen.h"
 
+#if BUILDFLAG(IS_TIZEN_TV)
+#include "content/browser/browser_main_loop.h"
+#include "content/browser/renderer_host/media/media_stream_manager.h"
+#endif
+
 namespace gfx {
 class Size;
 }
@@ -813,6 +818,15 @@ void VideoCaptureDeviceTizen::OnAllocateAndStart(
     }
   }
 
+#if BUILDFLAG(IS_TIZEN_TV)
+  /* add camera status callback to webbrowser */
+  err = camera_instance_->CameraSetStateChangedCb(OnCameraStateChanged, this);
+  if (CAMERA_ERROR_NONE != err) {
+    SetErrorState(CameraHandle::GetErrorString(err), FROM_HERE);
+    return;
+  }
+#endif
+
   if (IsMobileProfile() && !IsEmulatorArch() &&
       (camera_instance_->GetDeviceIndex() == CAMERA_DEVICE_CAMERA1)) {
     err = camera_instance_->CameraSetStreamFlip(CAMERA_FLIP_HORIZONTAL);
@@ -841,6 +855,9 @@ void VideoCaptureDeviceTizen::OnStopAndDeAllocate() {
   else
     camera_instance_->CameraUnsetPreviewCb();
   camera_instance_->CameraStopPreview();
+#if BUILDFLAG(IS_TIZEN_TV)
+  camera_instance_->CameraUnSetStateChangedCb();
+#endif
 
   if (IsMobileProfile())
     ReleaseDisplayLock();
@@ -960,4 +977,31 @@ void VideoCaptureDeviceTizen::StopPreview() {
     SetErrorState(CameraHandle::GetErrorString(err), FROM_HERE);
 }
 
+#if BUILDFLAG(IS_TIZEN_TV)
+void VideoCaptureDeviceTizen::OnCameraStateChanged(camera_state_e previous,
+                                                   camera_state_e current,
+                                                   bool by_policy,
+                                                   void* data) {
+  VideoCaptureDeviceTizen* video_capture_device_tizen =
+      static_cast<VideoCaptureDeviceTizen*>(data);
+  if (!video_capture_device_tizen) {
+    LOG(ERROR) << "video_capture_device_tizen is null";
+    return;
+  }
+
+  content::BrowserMainLoop* browser_main_loop =
+      content::BrowserMainLoop::GetInstance();
+  if (!browser_main_loop) {
+    LOG(ERROR) << "browser_main_loop is null";
+    return;
+  }
+  content::MediaStreamManager* msm = browser_main_loop->media_stream_manager();
+  if (!msm) {
+    LOG(ERROR) << "MediaStreamManager is null";
+    return;
+  }
+  msm->NotifyMediaStateChanged(content::MediaInputStreamType::VIDEO_CAPTURE,
+                               previous, current);
+}
+#endif
 }  // namespace media
index da296e4..f10a00b 100644 (file)
@@ -63,6 +63,13 @@ class VideoCaptureDeviceTizen : public VideoCaptureDevice,
                          void* userData);
   static void CaptureCompletedCb(void* userData);
 
+#if BUILDFLAG(IS_TIZEN_TV)
+  static void OnCameraStateChanged(camera_state_e previous,
+                                   camera_state_e current,
+                                   bool by_policy,
+                                   void* data);
+#endif
+
   void MaybeSuspend() override;
   void Resume() override;
 
index 5e33357..6c39a8d 100644 (file)
 #include "common/application_type.h"
 #include "devtools_port_manager.h"
 #include "public/ewk_media_downloadable_font_info.h"
+#include "public/ewk_user_media_internal.h"
 #include "browser/mixed_content_observer.h"
 #endif
 
@@ -3449,4 +3450,21 @@ bool EWebView::SetMixedContents(bool allow) {
       MixedContentObserver::FromWebContents(web_contents_.get());
   return mixed_content_observer->MixedContentReply(allow);
 }
+
+void EWebView::NotifyMediaStateChanged(uint32_t device_type,
+                                       uint32_t previous,
+                                       uint32_t current) {
+  LOG(INFO) << "NotifyMediaStateChanged type : " << device_type
+            << " ;previous: " << previous << " ; current: " << current;
+  Ewk_User_Media_State_Info* user_media_state_info =
+      new _Ewk_User_Media_State_Info;
+  user_media_state_info->device_type =
+      static_cast<Ewk_User_Media_Device_Type>(device_type);
+  user_media_state_info->previous_state = previous;
+  user_media_state_info->current_state = current;
+  SmartCallback<EWebViewCallbacks::UserMediaState>().call(
+      static_cast<void*>(user_media_state_info));
+
+  delete user_media_state_info;
+}
 #endif
index 2108ae3..87c9d0e 100644 (file)
@@ -739,6 +739,9 @@ class EWebView {
   bool RWIInfoShowed() { return rwi_info_showed_; }
   GURL RWIURL() { return rwi_gurl_; }
   void OnDialogClosed();
+  void NotifyMediaStateChanged(uint32_t type,
+                               uint32_t previous,
+                               uint32_t current);
 #endif  // IS_TIZEN_TV
 
   void SetDidChangeThemeColorCallback(
index 98fdf55..ad3d799 100644 (file)
@@ -208,6 +208,19 @@ WebContents* WebContentsDelegateEfl::OpenURLFromTab(
   return source;
 }
 
+#if BUILDFLAG(IS_TIZEN_TV)
+void WebContentsDelegateEfl::NotifyMediaStateChanged(uint32_t type,
+                                                     uint32_t previous,
+                                                     uint32_t current) {
+  if (!web_view_) {
+    LOG(ERROR) << "web_view_ is null";
+    return;
+  }
+
+  web_view_->NotifyMediaStateChanged(type, previous, current);
+}
+#endif
+
 void WebContentsDelegateEfl::NavigationStateChanged(
     WebContents* source, InvalidateTypes changed_flags) {
   // We always notfiy clients about title invalidation, even if its text
index 44cc7dd..5d0a080 100644 (file)
@@ -138,6 +138,9 @@ class WebContentsDelegateEfl : public WebContentsDelegate {
 #if BUILDFLAG(IS_TIZEN_TV)
   void UpdateTargetURL(WebContents* source, const GURL& url) override;
   void ShowInspectorPortInfo();
+  void NotifyMediaStateChanged(uint32_t type,
+                               uint32_t previous,
+                               uint32_t current) override;
 #endif
 
 #if defined(TIZEN_AUTOFILL)