media_foundation_renderer.h 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  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 MEDIA_RENDERERS_WIN_MEDIA_FOUNDATION_RENDERER_H_
  5. #define MEDIA_RENDERERS_WIN_MEDIA_FOUNDATION_RENDERER_H_
  6. #include <d3d11.h>
  7. #include <mfapi.h>
  8. #include <mfmediaengine.h>
  9. #include <wrl.h>
  10. #include "base/callback.h"
  11. #include "base/memory/raw_ptr.h"
  12. #include "base/memory/scoped_refptr.h"
  13. #include "base/memory/weak_ptr.h"
  14. #include "base/task/sequenced_task_runner.h"
  15. #include "base/time/time.h"
  16. #include "base/timer/timer.h"
  17. #include "base/unguessable_token.h"
  18. #include "base/win/windows_types.h"
  19. #include "media/base/buffering_state.h"
  20. #include "media/base/media_export.h"
  21. #include "media/base/media_resource.h"
  22. #include "media/base/pipeline_status.h"
  23. #include "media/base/renderer.h"
  24. #include "media/base/renderer_client.h"
  25. #include "media/renderers/win/media_engine_extension.h"
  26. #include "media/renderers/win/media_engine_notify_impl.h"
  27. #include "media/renderers/win/media_foundation_protection_manager.h"
  28. #include "media/renderers/win/media_foundation_renderer_extension.h"
  29. #include "media/renderers/win/media_foundation_source_wrapper.h"
  30. #include "media/renderers/win/media_foundation_texture_pool.h"
  31. namespace media {
  32. class MediaLog;
  33. // MediaFoundationRenderer bridges the Renderer and Windows MFMediaEngine
  34. // interfaces.
  35. class MEDIA_EXPORT MediaFoundationRenderer
  36. : public Renderer,
  37. public MediaFoundationRendererExtension {
  38. public:
  39. // An enum for recording MediaFoundationRenderer playback error reason.
  40. // Reported to UMA. Do not change existing values.
  41. enum class ErrorReason {
  42. kUnknown = 0,
  43. kCdmProxyReceivedInInvalidState = 1,
  44. kFailedToSetSourceOnMediaEngine = 2,
  45. kFailedToSetCurrentTime = 3,
  46. kFailedToPlay = 4,
  47. kOnPlaybackError = 5,
  48. kOnDCompSurfaceReceivedError [[deprecated]] = 6,
  49. kOnDCompSurfaceHandleSetError = 7,
  50. kOnConnectionError = 8,
  51. kFailedToSetDCompMode = 9,
  52. kFailedToGetDCompSurface = 10,
  53. kFailedToDuplicateHandle = 11,
  54. kFailedToCreateMediaEngine = 12,
  55. // Add new values here and update `kMaxValue`. Never reuse existing values.
  56. kMaxValue = kFailedToCreateMediaEngine,
  57. };
  58. // Report `reason` to UMA.
  59. static void ReportErrorReason(ErrorReason reason);
  60. // Whether MediaFoundationRenderer() is supported on the current device.
  61. static bool IsSupported();
  62. MediaFoundationRenderer(scoped_refptr<base::SequencedTaskRunner> task_runner,
  63. std::unique_ptr<MediaLog> media_log,
  64. LUID gpu_process_adapter_luid,
  65. bool force_dcomp_mode_for_testing = false);
  66. MediaFoundationRenderer(const MediaFoundationRenderer&) = delete;
  67. MediaFoundationRenderer& operator=(const MediaFoundationRenderer&) = delete;
  68. ~MediaFoundationRenderer() override;
  69. // Renderer implementation.
  70. void Initialize(MediaResource* media_resource,
  71. RendererClient* client,
  72. PipelineStatusCallback init_cb) override;
  73. void SetCdm(CdmContext* cdm_context, CdmAttachedCB cdm_attached_cb) override;
  74. void SetLatencyHint(absl::optional<base::TimeDelta> latency_hint) override;
  75. void Flush(base::OnceClosure flush_cb) override;
  76. void StartPlayingFrom(base::TimeDelta time) override;
  77. void SetPlaybackRate(double playback_rate) override;
  78. void SetVolume(float volume) override;
  79. base::TimeDelta GetMediaTime() override;
  80. // MediaFoundationRendererExtension implementation.
  81. void GetDCompSurface(GetDCompSurfaceCB callback) override;
  82. void SetVideoStreamEnabled(bool enabled) override;
  83. void SetOutputRect(const gfx::Rect& output_rect,
  84. SetOutputRectCB callback) override;
  85. void NotifyFrameReleased(const base::UnguessableToken& frame_token) override;
  86. void RequestNextFrameBetweenTimestamps(base::TimeTicks deadline_min,
  87. base::TimeTicks deadline_max) override;
  88. void SetMediaFoundationRenderingMode(
  89. MediaFoundationRenderingMode render_mode) override;
  90. using FrameReturnCallback = base::RepeatingCallback<
  91. void(const base::UnguessableToken&, const gfx::Size&, base::TimeDelta)>;
  92. void SetFrameReturnCallbacks(
  93. FrameReturnCallback frame_available_cb,
  94. FramePoolInitializedCallback initialized_frame_pool_cb);
  95. void SetGpuProcessAdapterLuid(LUID gpu_process_adapter_luid);
  96. // Testing verification
  97. bool InFrameServerMode();
  98. private:
  99. HRESULT CreateMediaEngine(MediaResource* media_resource);
  100. HRESULT InitializeDXGIDeviceManager();
  101. HRESULT InitializeVirtualVideoWindow();
  102. // Update RendererClient with rendering statistics periodically.
  103. HRESULT PopulateStatistics(PipelineStatistics& statistics);
  104. void SendStatistics();
  105. void StartSendingStatistics();
  106. void StopSendingStatistics();
  107. // Callbacks for `mf_media_engine_notify_`.
  108. void OnPlaybackError(PipelineStatus status, HRESULT hr);
  109. void OnPlaybackEnded();
  110. void OnFormatChange();
  111. void OnLoadedData();
  112. void OnPlaying();
  113. void OnWaiting();
  114. void OnTimeUpdate();
  115. // Callback for `content_protection_manager_`.
  116. void OnProtectionManagerWaiting(WaitingReason reason);
  117. void OnCdmProxyReceived();
  118. void OnBufferingStateChange(BufferingState state,
  119. BufferingStateChangeReason reason);
  120. HRESULT SetDCompModeInternal();
  121. HRESULT GetDCompSurfaceInternal(HANDLE* surface_handle);
  122. HRESULT SetSourceOnMediaEngine();
  123. HRESULT UpdateVideoStream(const gfx::Rect& rect);
  124. HRESULT PauseInternal();
  125. HRESULT InitializeTexturePool(const gfx::Size& size);
  126. void OnVideoNaturalSizeChange();
  127. // Handles errors in MediaFoundationRenderer:
  128. // - DLOG for local debugging
  129. // - MEDIA_LOG for media-internals, dev tools etc.
  130. // - Report error reason to UMA.
  131. // - Notify the `cdm_proxy_`.
  132. // - Notify the client via `status_cb`, or if `status_cb` is null, notify
  133. // `renderer_client` via OnError().
  134. void OnError(PipelineStatus status,
  135. ErrorReason reason,
  136. absl::optional<HRESULT> hresult = absl::nullopt,
  137. PipelineStatusCallback status_cb = base::NullCallback());
  138. // Renderer methods are running in the same sequence.
  139. scoped_refptr<base::SequencedTaskRunner> task_runner_;
  140. // Used to report media logs. Can be called on any thread.
  141. std::unique_ptr<MediaLog> media_log_;
  142. // LUID identifying the graphics adapter used by the GPU process, the DXGI
  143. // device created for Media Foundation Renderer must match in order to share
  144. // handles between the two processes for Frame Server mode.
  145. LUID gpu_process_adapter_luid_;
  146. // Once set, will force `mf_media_engine_` to use DirectComposition mode.
  147. // This is used for testing.
  148. const bool force_dcomp_mode_for_testing_;
  149. raw_ptr<RendererClient> renderer_client_;
  150. FrameReturnCallback frame_available_cb_;
  151. FramePoolInitializedCallback initialized_frame_pool_cb_;
  152. Microsoft::WRL::ComPtr<IMFMediaEngine> mf_media_engine_;
  153. Microsoft::WRL::ComPtr<MediaEngineNotifyImpl> mf_media_engine_notify_;
  154. Microsoft::WRL::ComPtr<MediaEngineExtension> mf_media_engine_extension_;
  155. Microsoft::WRL::ComPtr<MediaFoundationSourceWrapper> mf_source_;
  156. // This enables MFMediaEngine to use hardware acceleration for video decoding
  157. // and video processing.
  158. Microsoft::WRL::ComPtr<IMFDXGIDeviceManager> dxgi_device_manager_;
  159. // Current duration of the media.
  160. base::TimeDelta duration_;
  161. // This is the same as "natural_size" in Chromium.
  162. gfx::Size native_video_size_;
  163. // Keep the last volume value being set.
  164. float volume_ = 1.0;
  165. // Used for RendererClient::OnBufferingStateChange().
  166. BufferingState max_buffering_state_ = BufferingState::BUFFERING_HAVE_NOTHING;
  167. // Used for RendererClient::OnStatisticsUpdate().
  168. PipelineStatistics statistics_ = {};
  169. base::RepeatingTimer statistics_timer_;
  170. // Tracks the number of MEDIA_LOGs emitted for failure to populate statistics.
  171. // Useful to prevent log spam.
  172. int populate_statistics_failure_count_ = 0;
  173. // A fake window handle passed to MF-based rendering pipeline for OPM.
  174. HWND virtual_video_window_ = nullptr;
  175. bool waiting_for_mf_cdm_ = false;
  176. raw_ptr<CdmContext> cdm_context_ = nullptr;
  177. scoped_refptr<MediaFoundationCdmProxy> cdm_proxy_;
  178. Microsoft::WRL::ComPtr<MediaFoundationProtectionManager>
  179. content_protection_manager_;
  180. // Texture pool of ID3D11Texture2D for the media engine to draw video frames
  181. // when the media engine is in frame server mode instead of Direct
  182. // Composition mode.
  183. MediaFoundationTexturePool texture_pool_;
  184. // Rendering mode the Media Engine will use.
  185. MediaFoundationRenderingMode rendering_mode_ =
  186. MediaFoundationRenderingMode::DirectComposition;
  187. bool has_reported_significant_playback_ = false;
  188. // NOTE: Weak pointers must be invalidated before all other member variables.
  189. base::WeakPtrFactory<MediaFoundationRenderer> weak_factory_{this};
  190. };
  191. } // namespace media
  192. #endif // MEDIA_RENDERERS_WIN_MEDIA_FOUNDATION_RENDERER_H_