recording_service.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267
  1. // Copyright 2020 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #ifndef ASH_SERVICES_RECORDING_RECORDING_SERVICE_H_
  5. #define ASH_SERVICES_RECORDING_RECORDING_SERVICE_H_
  6. #include <memory>
  7. #include <string>
  8. #include <utility>
  9. #include "ash/services/recording/public/mojom/recording_service.mojom.h"
  10. #include "ash/services/recording/recording_encoder_muxer.h"
  11. #include "ash/services/recording/video_capture_params.h"
  12. #include "base/bind.h"
  13. #include "base/callback_forward.h"
  14. #include "base/memory/scoped_refptr.h"
  15. #include "base/memory/weak_ptr.h"
  16. #include "base/sequence_checker.h"
  17. #include "base/task/bind_post_task.h"
  18. #include "base/task/sequenced_task_runner.h"
  19. #include "base/thread_annotations.h"
  20. #include "base/threading/sequence_bound.h"
  21. #include "base/threading/thread_checker.h"
  22. #include "media/base/audio_bus.h"
  23. #include "media/base/audio_capturer_source.h"
  24. #include "media/base/audio_parameters.h"
  25. #include "mojo/public/cpp/bindings/pending_remote.h"
  26. #include "mojo/public/cpp/bindings/receiver.h"
  27. #include "mojo/public/cpp/bindings/remote.h"
  28. #include "services/viz/privileged/mojom/compositing/frame_sink_video_capture.mojom.h"
  29. #include "ui/gfx/image/image_skia.h"
  30. namespace recording {
  31. class RecordingServiceTestApi;
  32. // Implements the mojo interface of the recording service which handles
  33. // recording audio and video of the screen or portion of it, and writes the webm
  34. // muxed video chunks directly to a file at a path provided to the Record*()
  35. // functions.
  36. class RecordingService : public mojom::RecordingService,
  37. public viz::mojom::FrameSinkVideoConsumer,
  38. public media::AudioCapturerSource::CaptureCallback {
  39. public:
  40. explicit RecordingService(
  41. mojo::PendingReceiver<mojom::RecordingService> receiver);
  42. RecordingService(const RecordingService&) = delete;
  43. RecordingService& operator=(const RecordingService&) = delete;
  44. ~RecordingService() override;
  45. // mojom::RecordingService:
  46. void RecordFullscreen(
  47. mojo::PendingRemote<mojom::RecordingServiceClient> client,
  48. mojo::PendingRemote<viz::mojom::FrameSinkVideoCapturer> video_capturer,
  49. mojo::PendingRemote<media::mojom::AudioStreamFactory>
  50. audio_stream_factory,
  51. mojo::PendingRemote<mojom::DriveFsQuotaDelegate> drive_fs_quota_delegate,
  52. const base::FilePath& webm_file_path,
  53. const viz::FrameSinkId& frame_sink_id,
  54. const gfx::Size& frame_sink_size_dip,
  55. float device_scale_factor) override;
  56. void RecordWindow(
  57. mojo::PendingRemote<mojom::RecordingServiceClient> client,
  58. mojo::PendingRemote<viz::mojom::FrameSinkVideoCapturer> video_capturer,
  59. mojo::PendingRemote<media::mojom::AudioStreamFactory>
  60. audio_stream_factory,
  61. mojo::PendingRemote<mojom::DriveFsQuotaDelegate> drive_fs_quota_delegate,
  62. const base::FilePath& webm_file_path,
  63. const viz::FrameSinkId& frame_sink_id,
  64. const gfx::Size& frame_sink_size_dip,
  65. float device_scale_factor,
  66. const viz::SubtreeCaptureId& subtree_capture_id,
  67. const gfx::Size& window_size_dip) override;
  68. void RecordRegion(
  69. mojo::PendingRemote<mojom::RecordingServiceClient> client,
  70. mojo::PendingRemote<viz::mojom::FrameSinkVideoCapturer> video_capturer,
  71. mojo::PendingRemote<media::mojom::AudioStreamFactory>
  72. audio_stream_factory,
  73. mojo::PendingRemote<mojom::DriveFsQuotaDelegate> drive_fs_quota_delegate,
  74. const base::FilePath& webm_file_path,
  75. const viz::FrameSinkId& frame_sink_id,
  76. const gfx::Size& frame_sink_size_dip,
  77. float device_scale_factor,
  78. const gfx::Rect& crop_region_dip) override;
  79. void StopRecording() override;
  80. void OnRecordedWindowChangingRoot(const viz::FrameSinkId& new_frame_sink_id,
  81. const gfx::Size& new_frame_sink_size_dip,
  82. float new_device_scale_factor) override;
  83. void OnRecordedWindowSizeChanged(
  84. const gfx::Size& new_window_size_dip) override;
  85. void OnFrameSinkSizeChanged(const gfx::Size& new_frame_sink_size_dip,
  86. float new_device_scale_factor) override;
  87. // viz::mojom::FrameSinkVideoConsumer:
  88. void OnFrameCaptured(
  89. media::mojom::VideoBufferHandlePtr data,
  90. media::mojom::VideoFrameInfoPtr info,
  91. const gfx::Rect& content_rect,
  92. mojo::PendingRemote<viz::mojom::FrameSinkVideoConsumerFrameCallbacks>
  93. callbacks) override;
  94. void OnNewCropVersion(uint32_t crop_version) override;
  95. void OnFrameWithEmptyRegionCapture() override;
  96. void OnStopped() override;
  97. void OnLog(const std::string& message) override;
  98. // media::AudioCapturerSource::CaptureCallback:
  99. void OnCaptureStarted() override;
  100. void Capture(const media::AudioBus* audio_source,
  101. base::TimeTicks audio_capture_time,
  102. double volume,
  103. bool key_pressed) override;
  104. void OnCaptureError(media::AudioCapturerSource::ErrorCode code,
  105. const std::string& message) override;
  106. void OnCaptureMuted(bool is_muted) override;
  107. private:
  108. friend class RecordingServiceTestApi;
  109. void StartNewRecording(
  110. mojo::PendingRemote<mojom::RecordingServiceClient> client,
  111. mojo::PendingRemote<viz::mojom::FrameSinkVideoCapturer> video_capturer,
  112. mojo::PendingRemote<media::mojom::AudioStreamFactory>
  113. audio_stream_factory,
  114. mojo::PendingRemote<mojom::DriveFsQuotaDelegate> drive_fs_quota_delegate,
  115. const base::FilePath& webm_file_path,
  116. std::unique_ptr<VideoCaptureParams> capture_params);
  117. // Called on the main thread during an on-going recording to reconfigure an
  118. // existing video encoder.
  119. void ReconfigureVideoEncoder();
  120. // Called on the main thread to end the recording with the given |status|.
  121. void TerminateRecording(mojom::RecordingStatus status);
  122. // Binds the given |video_capturer| to |video_capturer_remote_| and starts
  123. // video according to the current |current_video_capture_params_|.
  124. void ConnectAndStartVideoCapturer(
  125. mojo::PendingRemote<viz::mojom::FrameSinkVideoCapturer> video_capturer);
  126. // If the video capturer gets disconnected (e.g. Viz crashes) during an
  127. // ongoing recording, this attempts to reconnect to a new capturer and resumes
  128. // capturing with the same |current_video_capture_params_|.
  129. void OnVideoCapturerDisconnected();
  130. // The captured audio data is delivered to Capture() on a dedicated thread
  131. // created by the audio capturer. However, we can only schedule tasks on the
  132. // |encoder_muxer_| using its |base::SequenceBound| wrapper on the main
  133. // thread. This function is called on the main thread, and is scheduled using
  134. // |main_task_runner_| from Capture().
  135. void OnAudioCaptured(std::unique_ptr<media::AudioBus> audio_bus,
  136. base::TimeTicks audio_capture_time);
  137. // This is called by |encoder_muxer_| on the main thread (since we bound it as
  138. // a callback to be invoked on the main thread. See BindOnceToMainThread()),
  139. // when a failure of type |status| occurs during audio or video encoding. This
  140. // ends the ongoing recording and signals to the client that a failure
  141. // occurred.
  142. void OnEncodingFailure(mojom::RecordingStatus status);
  143. // At the end of recording we ask the |encoder_muxer_| to flush and process
  144. // any buffered frames. When this completes this function is called on the
  145. // main thread (since it's bound as a callback to be invoked on the main
  146. // thread. See BindOnceToMainThread()). |status| indicates the recording
  147. // termination status that lead to this flushing of the encoders and muxer.
  148. void OnEncoderMuxerFlushed(mojom::RecordingStatus status);
  149. // Called on the main thread to tell the client that recording ended,
  150. // providing it with the |status| of the recording as well as a chached
  151. // thumbnail of the video (if available).
  152. void SignalRecordingEndedToClient(mojom::RecordingStatus status);
  153. // By default, the |encoder_muxer_| will invoke any callback we provide it
  154. // with to notify us of certain events (such as failure errors, or flush done)
  155. // on the |encoding_task_runner_|'s sequence. But since these callbacks are
  156. // invoked asynchronously from other threads, they may get invoked after this
  157. // RecordingService instance had been destroyed. Therefore, we need to bind
  158. // these callbacks to weak ptrs, to prevent them from invoking after this
  159. // object's destruction. However, this won't work, since weak ptrs cannot be
  160. // invalidated except on the sequence on which they were invoked on. Hence, we
  161. // must make sure these callbacks are invoked on the main thread.
  162. //
  163. // The below is a convenience method to bind once callbacks to weak ptrs that
  164. // would only be invoked on the main thread.
  165. template <typename Functor, typename... Args>
  166. auto BindOnceToMainThread(Functor&& functor, Args&&... args) {
  167. return base::BindPostTask(main_task_runner_,
  168. base::BindOnce(std::forward<Functor>(functor),
  169. weak_ptr_factory_.GetWeakPtr(),
  170. std::forward<Args>(args)...));
  171. }
  172. THREAD_CHECKER(main_thread_checker_);
  173. // The audio parameters that will be used when recording audio.
  174. const media::AudioParameters audio_parameters_;
  175. // The mojo receiving end of the service.
  176. mojo::Receiver<mojom::RecordingService> receiver_;
  177. // The mojo receiving end of the service as a FrameSinkVideoConsumer.
  178. mojo::Receiver<viz::mojom::FrameSinkVideoConsumer> consumer_receiver_
  179. GUARDED_BY_CONTEXT(main_thread_checker_);
  180. // A task runner to post tasks on the main thread of the recording service.
  181. // It can be accessed from any thread.
  182. scoped_refptr<base::SingleThreadTaskRunner> main_task_runner_;
  183. // A sequenced blocking pool task runner used to run all encoding and muxing
  184. // tasks on. Can be accessed from any thread.
  185. scoped_refptr<base::SequencedTaskRunner> encoding_task_runner_;
  186. // A mojo remote end of client of this service (e.g. Ash). There can only be
  187. // a single client of this service.
  188. mojo::Remote<mojom::RecordingServiceClient> client_remote_
  189. GUARDED_BY_CONTEXT(main_thread_checker_);
  190. // A callback used for testing, which will be triggered when a video frame is
  191. // delivered to the service from the Viz capturer.
  192. using OnVideoFrameDeliveredCallback =
  193. base::OnceCallback<void(const media::VideoFrame& frame,
  194. const gfx::Rect& content_rect)>;
  195. OnVideoFrameDeliveredCallback on_video_frame_delivered_callback_for_testing_
  196. GUARDED_BY_CONTEXT(main_thread_checker_);
  197. // A cached scaled down rgb image of the first valid video frame which will be
  198. // used to provide the client with an image thumbnail representing the
  199. // recorded video.
  200. gfx::ImageSkia video_thumbnail_ GUARDED_BY_CONTEXT(main_thread_checker_);
  201. // True if a failure has been propagated from |encoder_muxer_| that we will
  202. // end recording abruptly and ignore any incoming audio/video frames.
  203. bool did_failure_occur_ GUARDED_BY_CONTEXT(main_thread_checker_) = false;
  204. // The parameters of the current ongoing video capture. This object knows how
  205. // to initialize the video capturer depending on which capture source
  206. // (fullscreen, window, or region) is currently being recorded. It is set to
  207. // a nullptr when there's no recording happening.
  208. std::unique_ptr<VideoCaptureParams> current_video_capture_params_
  209. GUARDED_BY_CONTEXT(main_thread_checker_);
  210. // The mojo remote end used to interact with a video capturer living on Viz.
  211. mojo::Remote<viz::mojom::FrameSinkVideoCapturer> video_capturer_remote_
  212. GUARDED_BY_CONTEXT(main_thread_checker_);
  213. // The audio capturer instance. It is created only if the service is requested
  214. // to record audio along side the video.
  215. scoped_refptr<media::AudioCapturerSource> audio_capturer_
  216. GUARDED_BY_CONTEXT(main_thread_checker_);
  217. // Performs all encoding and muxing operations asynchronously on the
  218. // |encoding_task_runner_|. However, the |encoder_muxer_| object itself is
  219. // constructed, used, and destroyed on the main thread sequence.
  220. base::SequenceBound<RecordingEncoderMuxer> encoder_muxer_
  221. GUARDED_BY_CONTEXT(main_thread_checker_);
  222. // The number of times the video encoder was reconfigured as a result of a
  223. // change in the video size in the middle of recording (See
  224. // ReconfigureVideoEncoder()).
  225. int number_of_video_encoder_reconfigures_
  226. GUARDED_BY_CONTEXT(main_thread_checker_) = 0;
  227. base::WeakPtrFactory<RecordingService> weak_ptr_factory_{this};
  228. };
  229. } // namespace recording
  230. #endif // ASH_SERVICES_RECORDING_RECORDING_SERVICE_H_