media_foundation_texture_pool_unittest.cc 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543
  1. // Copyright 2021 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. #include "media/renderers/win/media_foundation_texture_pool.h"
  5. #include "base/memory/raw_ptr.h"
  6. #include "base/test/mock_callback.h"
  7. #include "base/test/task_environment.h"
  8. #include "media/base/mock_filters.h"
  9. #include "media/base/test_helpers.h"
  10. #include "media/base/win/test_utils.h"
  11. #include <d3d11.h>
  12. #include <dxgi1_2.h>
  13. #include <wrl/client.h>
  14. using Microsoft::WRL::ComPtr;
  15. namespace media {
  16. class MockD3D11Texture2D;
  17. class MockD3D11Resource final : public IDXGIResource1 {
  18. public:
  19. MockD3D11Resource() {}
  20. HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,
  21. void** ppvObject) override;
  22. ULONG STDMETHODCALLTYPE AddRef(void) override {
  23. return InterlockedIncrement(&refcount_);
  24. }
  25. ULONG STDMETHODCALLTYPE Release(void) override {
  26. ULONG refcount = InterlockedDecrement(&refcount_);
  27. if (refcount == 0) {
  28. refcount_ = 0xBAADF00D;
  29. delete this;
  30. }
  31. return refcount;
  32. }
  33. // IDXGIResource1
  34. HRESULT STDMETHODCALLTYPE
  35. CreateSubresourceSurface(UINT index, IDXGISurface2** ppSurface) override {
  36. return E_NOTIMPL;
  37. }
  38. HRESULT STDMETHODCALLTYPE
  39. CreateSharedHandle(const SECURITY_ATTRIBUTES* pAttributes,
  40. DWORD dwAccess,
  41. LPCWSTR lpName,
  42. HANDLE* pHandle) override;
  43. // IDXGIResource
  44. HRESULT STDMETHODCALLTYPE GetSharedHandle(HANDLE* pSharedHandle) override {
  45. return E_NOTIMPL;
  46. }
  47. HRESULT STDMETHODCALLTYPE GetUsage(DXGI_USAGE* pUsage) override {
  48. return E_NOTIMPL;
  49. }
  50. HRESULT STDMETHODCALLTYPE
  51. SetEvictionPriority(UINT eviction_priority) override;
  52. HRESULT STDMETHODCALLTYPE
  53. GetEvictionPriority(UINT* eviction_priority) override;
  54. // IDXGIDeviceSubObject
  55. HRESULT STDMETHODCALLTYPE GetDevice(REFIID riid, void** ppDevice) override {
  56. return E_NOTIMPL;
  57. }
  58. // IDXGIObject
  59. HRESULT STDMETHODCALLTYPE GetParent(REFIID riid, void** ppParent) override {
  60. return E_NOTIMPL;
  61. }
  62. HRESULT STDMETHODCALLTYPE GetPrivateData(REFGUID guid,
  63. UINT* pDataSize,
  64. void* pData) override {
  65. return E_NOTIMPL;
  66. }
  67. HRESULT STDMETHODCALLTYPE SetPrivateData(REFGUID guid,
  68. UINT DataSize,
  69. const void* pData) override {
  70. return E_NOTIMPL;
  71. }
  72. HRESULT STDMETHODCALLTYPE
  73. SetPrivateDataInterface(REFGUID guid, const IUnknown* pData) override;
  74. private:
  75. raw_ptr<MockD3D11Texture2D> parent_;
  76. volatile ULONG refcount_ = 1;
  77. };
  78. class MockD3D11Texture2D final : public ID3D11Texture2D {
  79. private:
  80. MockD3D11Texture2D(const D3D11_TEXTURE2D_DESC* texture_description)
  81. : resource_(new MockD3D11Resource()) {
  82. memcpy(&texture_description_, texture_description,
  83. sizeof(D3D11_TEXTURE2D_DESC));
  84. }
  85. public:
  86. static HRESULT CreateInstance(const D3D11_TEXTURE2D_DESC* texture_description,
  87. ID3D11Texture2D** texture2D);
  88. // IUnknown
  89. HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,
  90. void** ppvObject) override {
  91. if (ppvObject == nullptr) {
  92. return E_POINTER;
  93. }
  94. if (FAILED(QueryInterfaceInternal(riid, ppvObject))) {
  95. if (resource_ != nullptr)
  96. return resource_->QueryInterface(riid, ppvObject);
  97. else
  98. return E_NOINTERFACE;
  99. }
  100. AddRef();
  101. return S_OK;
  102. }
  103. HRESULT STDMETHODCALLTYPE QueryInterfaceInternal(REFIID riid,
  104. void** ppvObject) {
  105. if (ppvObject == nullptr) {
  106. return E_POINTER;
  107. }
  108. if (riid == IID_ID3D11Texture2D || riid == IID_IUnknown) {
  109. *ppvObject = static_cast<ID3D11Texture2D*>(this);
  110. } else if (riid == IID_ID3D11Resource) {
  111. *ppvObject = static_cast<ID3D11Resource*>(this);
  112. } else if (riid == IID_ID3D11DeviceChild) {
  113. *ppvObject = static_cast<ID3D11DeviceChild*>(this);
  114. } else {
  115. return E_NOINTERFACE;
  116. }
  117. AddRef();
  118. return S_OK;
  119. }
  120. ULONG STDMETHODCALLTYPE AddRef(void) override {
  121. return InterlockedIncrement(&refcount_);
  122. }
  123. ULONG STDMETHODCALLTYPE Release(void) override {
  124. ULONG refcount = InterlockedDecrement(&refcount_);
  125. if (refcount == 0) {
  126. refcount_ = 0xBAADF00D;
  127. delete this;
  128. }
  129. return refcount;
  130. }
  131. // ID3D11Texture2D
  132. void STDMETHODCALLTYPE GetDesc(D3D11_TEXTURE2D_DESC* description) override {
  133. memset(description, 0, sizeof(D3D11_TEXTURE2D_DESC));
  134. }
  135. // ID3D11Resource
  136. void STDMETHODCALLTYPE
  137. GetType(D3D11_RESOURCE_DIMENSION* resource_dimension) override {
  138. *resource_dimension =
  139. D3D11_RESOURCE_DIMENSION::D3D11_RESOURCE_DIMENSION_TEXTURE2D;
  140. }
  141. void STDMETHODCALLTYPE SetEvictionPriority(UINT eviction_priority) override {
  142. eviction_priority_ = eviction_priority;
  143. }
  144. UINT STDMETHODCALLTYPE GetEvictionPriority() override {
  145. return eviction_priority_;
  146. }
  147. // ID3D11DeviceChild
  148. void STDMETHODCALLTYPE GetDevice(ID3D11Device** ppDevice) override {
  149. device_.CopyTo(ppDevice);
  150. }
  151. HRESULT STDMETHODCALLTYPE GetPrivateData(REFGUID guid,
  152. UINT* pDataSize,
  153. void* pData) override {
  154. return E_NOTIMPL;
  155. }
  156. HRESULT STDMETHODCALLTYPE SetPrivateData(REFGUID guid,
  157. UINT DataSize,
  158. const void* pData) override {
  159. return E_NOTIMPL;
  160. }
  161. HRESULT STDMETHODCALLTYPE
  162. SetPrivateDataInterface(REFGUID guid, const IUnknown* pData) override {
  163. // Our tests aren't checking for this right now
  164. return S_OK;
  165. }
  166. private:
  167. volatile ULONG refcount_ = 1;
  168. UINT eviction_priority_ = 0;
  169. D3D11_TEXTURE2D_DESC texture_description_;
  170. ComPtr<ID3D11Device> device_;
  171. ComPtr<IDXGIResource1> resource_;
  172. };
  173. class MockD3D11Device : public ID3D11Device {
  174. public:
  175. HRESULT STDMETHODCALLTYPE QueryInterface(REFIID riid,
  176. void** ppvObject) override {
  177. if (ppvObject == nullptr) {
  178. return E_POINTER;
  179. }
  180. if (riid == IID_ID3D11Device || riid == IID_IUnknown) {
  181. *ppvObject = this;
  182. return S_OK;
  183. }
  184. return E_NOINTERFACE;
  185. }
  186. ULONG STDMETHODCALLTYPE AddRef(void) override { return 1; }
  187. ULONG STDMETHODCALLTYPE Release(void) override { return 1; }
  188. HRESULT STDMETHODCALLTYPE
  189. CreateBuffer(const D3D11_BUFFER_DESC* pDesc,
  190. const D3D11_SUBRESOURCE_DATA* pInitialData,
  191. ID3D11Buffer** ppBuffer) override {
  192. return E_NOTIMPL;
  193. }
  194. HRESULT STDMETHODCALLTYPE
  195. CreateTexture1D(const D3D11_TEXTURE1D_DESC* pDesc,
  196. const D3D11_SUBRESOURCE_DATA* pInitialData,
  197. ID3D11Texture1D** ppTexture1D) override {
  198. return E_NOTIMPL;
  199. }
  200. HRESULT STDMETHODCALLTYPE
  201. CreateTexture2D(const D3D11_TEXTURE2D_DESC* pDesc,
  202. const D3D11_SUBRESOURCE_DATA* pInitialData,
  203. ID3D11Texture2D** ppTexture2D) override;
  204. HRESULT STDMETHODCALLTYPE
  205. CreateTexture3D(const D3D11_TEXTURE3D_DESC* pDesc,
  206. const D3D11_SUBRESOURCE_DATA* pInitialData,
  207. ID3D11Texture3D** ppTexture3D) override {
  208. return E_NOTIMPL;
  209. }
  210. HRESULT STDMETHODCALLTYPE
  211. CreateShaderResourceView(ID3D11Resource* pResource,
  212. const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc,
  213. ID3D11ShaderResourceView** ppSRView) override {
  214. return E_NOTIMPL;
  215. }
  216. HRESULT STDMETHODCALLTYPE
  217. CreateUnorderedAccessView(ID3D11Resource* pResource,
  218. const D3D11_UNORDERED_ACCESS_VIEW_DESC* pDesc,
  219. ID3D11UnorderedAccessView** ppUAView) override {
  220. return E_NOTIMPL;
  221. }
  222. HRESULT STDMETHODCALLTYPE
  223. CreateRenderTargetView(ID3D11Resource* pResource,
  224. const D3D11_RENDER_TARGET_VIEW_DESC* pDesc,
  225. ID3D11RenderTargetView** ppRTView) override {
  226. return E_NOTIMPL;
  227. }
  228. HRESULT STDMETHODCALLTYPE
  229. CreateDepthStencilView(ID3D11Resource* pResource,
  230. const D3D11_DEPTH_STENCIL_VIEW_DESC* pDesc,
  231. ID3D11DepthStencilView** ppDepthStencilView) override {
  232. return E_NOTIMPL;
  233. }
  234. HRESULT STDMETHODCALLTYPE
  235. CreateInputLayout(const D3D11_INPUT_ELEMENT_DESC* pInputElementDescs,
  236. UINT NumElements,
  237. const void* pShaderBytecodeWithInputSignature,
  238. SIZE_T BytecodeLength,
  239. ID3D11InputLayout** ppInputLayout) override {
  240. return E_NOTIMPL;
  241. }
  242. HRESULT STDMETHODCALLTYPE
  243. CreateVertexShader(const void* pShaderBytecode,
  244. SIZE_T BytecodeLength,
  245. ID3D11ClassLinkage* pClassLinkage,
  246. ID3D11VertexShader** ppVertexShader) override {
  247. return E_NOTIMPL;
  248. }
  249. HRESULT STDMETHODCALLTYPE
  250. CreateGeometryShader(const void* pShaderBytecode,
  251. SIZE_T BytecodeLength,
  252. ID3D11ClassLinkage* pClassLinkage,
  253. ID3D11GeometryShader** ppGeometryShader) override {
  254. return E_NOTIMPL;
  255. }
  256. HRESULT STDMETHODCALLTYPE CreateGeometryShaderWithStreamOutput(
  257. const void* pShaderBytecode,
  258. SIZE_T BytecodeLength,
  259. const D3D11_SO_DECLARATION_ENTRY* pSODeclaration,
  260. UINT NumEntries,
  261. const UINT* pBufferStrides,
  262. UINT NumStrides,
  263. UINT RasterizedStream,
  264. ID3D11ClassLinkage* pClassLinkage,
  265. ID3D11GeometryShader** ppGeometryShader) override {
  266. return E_NOTIMPL;
  267. }
  268. HRESULT STDMETHODCALLTYPE
  269. CreatePixelShader(const void* pShaderBytecode,
  270. SIZE_T BytecodeLength,
  271. ID3D11ClassLinkage* pClassLinkage,
  272. ID3D11PixelShader** ppPixelShader) override {
  273. return E_NOTIMPL;
  274. }
  275. HRESULT STDMETHODCALLTYPE
  276. CreateHullShader(const void* pShaderBytecode,
  277. SIZE_T BytecodeLength,
  278. ID3D11ClassLinkage* pClassLinkage,
  279. ID3D11HullShader** ppHullShader) override {
  280. return E_NOTIMPL;
  281. }
  282. HRESULT STDMETHODCALLTYPE
  283. CreateDomainShader(const void* pShaderBytecode,
  284. SIZE_T BytecodeLength,
  285. ID3D11ClassLinkage* pClassLinkage,
  286. ID3D11DomainShader** ppDomainShader) override {
  287. return E_NOTIMPL;
  288. }
  289. HRESULT STDMETHODCALLTYPE
  290. CreateComputeShader(const void* pShaderBytecode,
  291. SIZE_T BytecodeLength,
  292. ID3D11ClassLinkage* pClassLinkage,
  293. ID3D11ComputeShader** ppComputeShader) override {
  294. return E_NOTIMPL;
  295. }
  296. HRESULT STDMETHODCALLTYPE
  297. CreateClassLinkage(ID3D11ClassLinkage** ppLinkage) override {
  298. return E_NOTIMPL;
  299. }
  300. HRESULT STDMETHODCALLTYPE
  301. CreateBlendState(const D3D11_BLEND_DESC* pBlendStateDesc,
  302. ID3D11BlendState** ppBlendState) override {
  303. return E_NOTIMPL;
  304. }
  305. HRESULT STDMETHODCALLTYPE CreateDepthStencilState(
  306. const D3D11_DEPTH_STENCIL_DESC* pDepthStencilDesc,
  307. ID3D11DepthStencilState** ppDepthStencilState) override {
  308. return E_NOTIMPL;
  309. }
  310. HRESULT STDMETHODCALLTYPE
  311. CreateRasterizerState(const D3D11_RASTERIZER_DESC* pRasterizerDesc,
  312. ID3D11RasterizerState** ppRasterizerState) override {
  313. return E_NOTIMPL;
  314. }
  315. HRESULT STDMETHODCALLTYPE
  316. CreateSamplerState(const D3D11_SAMPLER_DESC* pSamplerDesc,
  317. ID3D11SamplerState** ppSamplerState) override {
  318. return E_NOTIMPL;
  319. }
  320. HRESULT STDMETHODCALLTYPE CreateQuery(const D3D11_QUERY_DESC* pQueryDesc,
  321. ID3D11Query** ppQuery) override {
  322. return E_NOTIMPL;
  323. }
  324. HRESULT STDMETHODCALLTYPE
  325. CreatePredicate(const D3D11_QUERY_DESC* pPredicateDesc,
  326. ID3D11Predicate** ppPredicate) override {
  327. return E_NOTIMPL;
  328. }
  329. HRESULT STDMETHODCALLTYPE
  330. CreateCounter(const D3D11_COUNTER_DESC* pCounterDesc,
  331. ID3D11Counter** ppCounter) override {
  332. return E_NOTIMPL;
  333. }
  334. HRESULT STDMETHODCALLTYPE
  335. CreateDeferredContext(UINT ContextFlags,
  336. ID3D11DeviceContext** ppDeferredContext) override {
  337. return E_NOTIMPL;
  338. }
  339. HRESULT STDMETHODCALLTYPE OpenSharedResource(HANDLE hResource,
  340. REFIID ReturnedInterface,
  341. void** ppResource) override {
  342. return E_NOTIMPL;
  343. }
  344. HRESULT STDMETHODCALLTYPE CheckFormatSupport(DXGI_FORMAT Format,
  345. UINT* pFormatSupport) override {
  346. return E_NOTIMPL;
  347. }
  348. HRESULT STDMETHODCALLTYPE
  349. CheckMultisampleQualityLevels(DXGI_FORMAT Format,
  350. UINT SampleCount,
  351. UINT* pNumQualityLevels) override {
  352. return E_NOTIMPL;
  353. }
  354. void STDMETHODCALLTYPE
  355. CheckCounterInfo(D3D11_COUNTER_INFO* pCounterInfo) override {}
  356. HRESULT STDMETHODCALLTYPE CheckCounter(const D3D11_COUNTER_DESC* pDesc,
  357. D3D11_COUNTER_TYPE* pType,
  358. UINT* pActiveCounters,
  359. LPSTR szName,
  360. UINT* pNameLength,
  361. LPSTR szUnits,
  362. UINT* pUnitsLength,
  363. LPSTR szDescription,
  364. UINT* pDescriptionLength) override {
  365. return E_NOTIMPL;
  366. }
  367. HRESULT STDMETHODCALLTYPE
  368. CheckFeatureSupport(D3D11_FEATURE Feature,
  369. void* pFeatureSupportData,
  370. UINT FeatureSupportDataSize) override {
  371. return E_NOTIMPL;
  372. }
  373. HRESULT STDMETHODCALLTYPE GetPrivateData(REFGUID guid,
  374. UINT* pDataSize,
  375. void* pData) override {
  376. return E_NOTIMPL;
  377. }
  378. HRESULT STDMETHODCALLTYPE SetPrivateData(REFGUID guid,
  379. UINT DataSize,
  380. const void* pData) override {
  381. return E_NOTIMPL;
  382. }
  383. HRESULT STDMETHODCALLTYPE
  384. SetPrivateDataInterface(REFGUID guid, const IUnknown* pData) override {
  385. return E_NOTIMPL;
  386. }
  387. D3D_FEATURE_LEVEL STDMETHODCALLTYPE GetFeatureLevel(void) override {
  388. return D3D_FEATURE_LEVEL_11_1;
  389. }
  390. UINT STDMETHODCALLTYPE GetCreationFlags(void) override { return 0; }
  391. HRESULT STDMETHODCALLTYPE GetDeviceRemovedReason(void) override {
  392. return E_NOTIMPL;
  393. }
  394. void STDMETHODCALLTYPE
  395. GetImmediateContext(ID3D11DeviceContext** ppImmediateContext) override {}
  396. HRESULT STDMETHODCALLTYPE SetExceptionMode(UINT RaiseFlags) override {
  397. return E_NOTIMPL;
  398. }
  399. UINT STDMETHODCALLTYPE GetExceptionMode(void) override { return 0; }
  400. };
  401. // MockD3D11Resource
  402. HRESULT STDMETHODCALLTYPE MockD3D11Resource::QueryInterface(REFIID riid,
  403. void** ppvObject) {
  404. if (ppvObject == nullptr) {
  405. return E_POINTER;
  406. }
  407. if (riid == IID_IDXGIResource1) {
  408. *ppvObject = static_cast<IDXGIResource1*>(this);
  409. } else if (riid == IID_IDXGIResource) {
  410. *ppvObject = static_cast<IDXGIResource*>(this);
  411. } else if (riid == IID_IDXGIDeviceSubObject) {
  412. *ppvObject = static_cast<IDXGIDeviceSubObject*>(this);
  413. } else if (riid == IID_IDXGIObject) {
  414. *ppvObject = static_cast<IDXGIObject*>(this);
  415. } else if (parent_ != nullptr) {
  416. return parent_->QueryInterfaceInternal(riid, ppvObject);
  417. } else {
  418. return E_NOINTERFACE;
  419. }
  420. AddRef();
  421. return S_OK;
  422. }
  423. HRESULT STDMETHODCALLTYPE
  424. MockD3D11Resource::SetEvictionPriority(UINT eviction_priority) {
  425. parent_->SetEvictionPriority(eviction_priority);
  426. return S_OK;
  427. }
  428. HRESULT STDMETHODCALLTYPE
  429. MockD3D11Resource::GetEvictionPriority(UINT* eviction_priority) {
  430. *eviction_priority = parent_->GetEvictionPriority();
  431. return S_OK;
  432. }
  433. HRESULT STDMETHODCALLTYPE
  434. MockD3D11Resource::SetPrivateDataInterface(REFGUID guid,
  435. const IUnknown* pData) {
  436. return parent_->SetPrivateDataInterface(guid, pData);
  437. }
  438. HRESULT STDMETHODCALLTYPE
  439. MockD3D11Resource::CreateSharedHandle(const SECURITY_ATTRIBUTES* pAttributes,
  440. DWORD dwAccess,
  441. LPCWSTR lpName,
  442. HANDLE* pHandle) {
  443. // Using an event to create a valid nt handle
  444. *pHandle = CreateEvent(nullptr, FALSE, FALSE, nullptr);
  445. if (*pHandle == nullptr) {
  446. return HRESULT_FROM_WIN32(GetLastError());
  447. }
  448. return S_OK;
  449. }
  450. HRESULT MockD3D11Texture2D::CreateInstance(
  451. const D3D11_TEXTURE2D_DESC* texture_description,
  452. ID3D11Texture2D** texture2D) {
  453. MockD3D11Texture2D* mock_texture =
  454. new MockD3D11Texture2D(texture_description);
  455. if (!mock_texture) {
  456. return E_OUTOFMEMORY;
  457. }
  458. *texture2D = mock_texture;
  459. return S_OK;
  460. }
  461. HRESULT STDMETHODCALLTYPE
  462. MockD3D11Device::CreateTexture2D(const D3D11_TEXTURE2D_DESC* pDesc,
  463. const D3D11_SUBRESOURCE_DATA* pInitialData,
  464. ID3D11Texture2D** ppTexture2D) {
  465. return MockD3D11Texture2D::CreateInstance(pDesc, ppTexture2D);
  466. }
  467. class MediaFoundationTexturePoolTest : public testing::Test {
  468. public:
  469. MediaFoundationTexturePoolTest() {}
  470. base::WeakPtrFactory<MediaFoundationTexturePoolTest> weak_factory_{this};
  471. };
  472. TEST_F(MediaFoundationTexturePoolTest, VerifyTextureInitialization) {
  473. MockD3D11Device mock_d3d_device;
  474. media::MediaFoundationTexturePool test;
  475. base::WaitableEvent wait_event;
  476. gfx::Size frame_size(1920, 1080);
  477. class SpecialCallback {
  478. private:
  479. raw_ptr<base::WaitableEvent> wait_event_;
  480. raw_ptr<gfx::Size> frame_size_;
  481. public:
  482. SpecialCallback(base::WaitableEvent* wait_event, gfx::Size* frame_size)
  483. : wait_event_(wait_event), frame_size_(frame_size) {}
  484. void Invoke(std::vector<media::MediaFoundationFrameInfo> frame_textures,
  485. const gfx::Size& texture_size) {
  486. EXPECT_EQ(texture_size.width(), frame_size_->width());
  487. EXPECT_EQ(texture_size.height(), frame_size_->height());
  488. wait_event_->Signal();
  489. }
  490. } callback(&wait_event, &frame_size);
  491. EXPECT_HRESULT_SUCCEEDED(
  492. test.Initialize(&mock_d3d_device,
  493. base::BindRepeating(&SpecialCallback::Invoke,
  494. base::Unretained(&callback)),
  495. frame_size));
  496. wait_event.Wait();
  497. }
  498. } // namespace media