2 * Copyright 2018 Alistair Leslie-Hughes
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "mfplat_private.h"
29 #include "wine/debug.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(mfplat
);
33 #define ALIGN_SIZE(size, alignment) (((size) + (alignment)) & ~((alignment)))
37 IMFMediaBuffer IMFMediaBuffer_iface
;
38 IMF2DBuffer2 IMF2DBuffer2_iface
;
39 IMFDXGIBuffer IMFDXGIBuffer_iface
;
40 IMFGetService IMFGetService_iface
;
50 unsigned int plane_size
;
61 IDirect3DSurface9
*surface
;
66 ID3D11Texture2D
*texture
;
67 unsigned int sub_resource_idx
;
68 ID3D11Texture2D
*rb_texture
;
69 D3D11_MAPPED_SUBRESOURCE map_desc
;
70 struct attributes attributes
;
76 static inline struct buffer
*impl_from_IMFMediaBuffer(IMFMediaBuffer
*iface
)
78 return CONTAINING_RECORD(iface
, struct buffer
, IMFMediaBuffer_iface
);
81 static struct buffer
*impl_from_IMF2DBuffer2(IMF2DBuffer2
*iface
)
83 return CONTAINING_RECORD(iface
, struct buffer
, IMF2DBuffer2_iface
);
86 static struct buffer
*impl_from_IMFGetService(IMFGetService
*iface
)
88 return CONTAINING_RECORD(iface
, struct buffer
, IMFGetService_iface
);
91 static struct buffer
*impl_from_IMFDXGIBuffer(IMFDXGIBuffer
*iface
)
93 return CONTAINING_RECORD(iface
, struct buffer
, IMFDXGIBuffer_iface
);
96 static HRESULT WINAPI
memory_buffer_QueryInterface(IMFMediaBuffer
*iface
, REFIID riid
, void **out
)
98 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
100 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), out
);
102 if (IsEqualIID(riid
, &IID_IMFMediaBuffer
) ||
103 IsEqualIID(riid
, &IID_IUnknown
))
105 *out
= &buffer
->IMFMediaBuffer_iface
;
106 IMFMediaBuffer_AddRef(iface
);
110 WARN("Unsupported %s.\n", debugstr_guid(riid
));
112 return E_NOINTERFACE
;
115 static ULONG WINAPI
memory_buffer_AddRef(IMFMediaBuffer
*iface
)
117 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
118 ULONG refcount
= InterlockedIncrement(&buffer
->refcount
);
120 TRACE("%p, refcount %u.\n", buffer
, refcount
);
125 static ULONG WINAPI
memory_buffer_Release(IMFMediaBuffer
*iface
)
127 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
128 ULONG refcount
= InterlockedDecrement(&buffer
->refcount
);
130 TRACE("%p, refcount %u.\n", iface
, refcount
);
134 if (buffer
->d3d9_surface
.surface
)
135 IDirect3DSurface9_Release(buffer
->d3d9_surface
.surface
);
136 if (buffer
->dxgi_surface
.texture
)
138 ID3D11Texture2D_Release(buffer
->dxgi_surface
.texture
);
139 if (buffer
->dxgi_surface
.rb_texture
)
140 ID3D11Texture2D_Release(buffer
->dxgi_surface
.rb_texture
);
141 clear_attributes_object(&buffer
->dxgi_surface
.attributes
);
143 DeleteCriticalSection(&buffer
->cs
);
144 heap_free(buffer
->_2d
.linear_buffer
);
145 heap_free(buffer
->data
);
152 static HRESULT WINAPI
memory_buffer_Lock(IMFMediaBuffer
*iface
, BYTE
**data
, DWORD
*max_length
, DWORD
*current_length
)
154 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
156 TRACE("%p, %p %p, %p.\n", iface
, data
, max_length
, current_length
);
161 *data
= buffer
->data
;
163 *max_length
= buffer
->max_length
;
165 *current_length
= buffer
->current_length
;
170 static HRESULT WINAPI
memory_buffer_Unlock(IMFMediaBuffer
*iface
)
172 TRACE("%p.\n", iface
);
177 static HRESULT WINAPI
memory_buffer_GetCurrentLength(IMFMediaBuffer
*iface
, DWORD
*current_length
)
179 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
181 TRACE("%p.\n", iface
);
186 *current_length
= buffer
->current_length
;
191 static HRESULT WINAPI
memory_buffer_SetCurrentLength(IMFMediaBuffer
*iface
, DWORD current_length
)
193 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
195 TRACE("%p, %u.\n", iface
, current_length
);
197 if (current_length
> buffer
->max_length
)
200 buffer
->current_length
= current_length
;
205 static HRESULT WINAPI
memory_buffer_GetMaxLength(IMFMediaBuffer
*iface
, DWORD
*max_length
)
207 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
209 TRACE("%p, %p.\n", iface
, max_length
);
214 *max_length
= buffer
->max_length
;
219 static const IMFMediaBufferVtbl memory_1d_buffer_vtbl
=
221 memory_buffer_QueryInterface
,
222 memory_buffer_AddRef
,
223 memory_buffer_Release
,
225 memory_buffer_Unlock
,
226 memory_buffer_GetCurrentLength
,
227 memory_buffer_SetCurrentLength
,
228 memory_buffer_GetMaxLength
,
231 static HRESULT WINAPI
memory_1d_2d_buffer_QueryInterface(IMFMediaBuffer
*iface
, REFIID riid
, void **out
)
233 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
235 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), out
);
237 if (IsEqualIID(riid
, &IID_IMFMediaBuffer
) ||
238 IsEqualIID(riid
, &IID_IUnknown
))
240 *out
= &buffer
->IMFMediaBuffer_iface
;
242 else if (IsEqualIID(riid
, &IID_IMF2DBuffer2
) ||
243 IsEqualIID(riid
, &IID_IMF2DBuffer
))
245 *out
= &buffer
->IMF2DBuffer2_iface
;
247 else if (IsEqualIID(riid
, &IID_IMFGetService
))
249 *out
= &buffer
->IMFGetService_iface
;
253 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
255 return E_NOINTERFACE
;
258 IUnknown_AddRef((IUnknown
*)*out
);
262 static HRESULT WINAPI
memory_1d_2d_buffer_Lock(IMFMediaBuffer
*iface
, BYTE
**data
, DWORD
*max_length
, DWORD
*current_length
)
264 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
267 TRACE("%p, %p, %p, %p.\n", iface
, data
, max_length
, current_length
);
272 /* Allocate linear buffer and return it as a copy of current content. Maximum and current length are
273 unrelated to 2D buffer maximum allocate length, or maintained current length. */
275 EnterCriticalSection(&buffer
->cs
);
277 if (!buffer
->_2d
.linear_buffer
&& buffer
->_2d
.locks
)
278 hr
= MF_E_INVALIDREQUEST
;
279 else if (!buffer
->_2d
.linear_buffer
)
281 if (!(buffer
->_2d
.linear_buffer
= heap_alloc(ALIGN_SIZE(buffer
->_2d
.plane_size
, MF_64_BYTE_ALIGNMENT
))))
288 *data
= buffer
->_2d
.linear_buffer
;
290 *max_length
= buffer
->_2d
.plane_size
;
292 *current_length
= buffer
->_2d
.plane_size
;
295 LeaveCriticalSection(&buffer
->cs
);
300 static HRESULT WINAPI
memory_1d_2d_buffer_Unlock(IMFMediaBuffer
*iface
)
302 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
304 TRACE("%p.\n", iface
);
306 EnterCriticalSection(&buffer
->cs
);
308 if (buffer
->_2d
.linear_buffer
&& !--buffer
->_2d
.locks
)
310 MFCopyImage(buffer
->data
, buffer
->_2d
.pitch
, buffer
->_2d
.linear_buffer
, buffer
->_2d
.width
,
311 buffer
->_2d
.width
, buffer
->_2d
.height
);
313 heap_free(buffer
->_2d
.linear_buffer
);
314 buffer
->_2d
.linear_buffer
= NULL
;
317 LeaveCriticalSection(&buffer
->cs
);
322 static const IMFMediaBufferVtbl memory_1d_2d_buffer_vtbl
=
324 memory_1d_2d_buffer_QueryInterface
,
325 memory_buffer_AddRef
,
326 memory_buffer_Release
,
327 memory_1d_2d_buffer_Lock
,
328 memory_1d_2d_buffer_Unlock
,
329 memory_buffer_GetCurrentLength
,
330 memory_buffer_SetCurrentLength
,
331 memory_buffer_GetMaxLength
,
334 static HRESULT WINAPI
d3d9_surface_buffer_Lock(IMFMediaBuffer
*iface
, BYTE
**data
, DWORD
*max_length
, DWORD
*current_length
)
336 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
339 TRACE("%p, %p, %p, %p.\n", iface
, data
, max_length
, current_length
);
344 EnterCriticalSection(&buffer
->cs
);
346 if (!buffer
->_2d
.linear_buffer
&& buffer
->_2d
.locks
)
347 hr
= MF_E_INVALIDREQUEST
;
348 else if (!buffer
->_2d
.linear_buffer
)
352 if (!(buffer
->_2d
.linear_buffer
= heap_alloc(ALIGN_SIZE(buffer
->_2d
.plane_size
, MF_64_BYTE_ALIGNMENT
))))
357 hr
= IDirect3DSurface9_LockRect(buffer
->d3d9_surface
.surface
, &rect
, NULL
, 0);
360 MFCopyImage(buffer
->_2d
.linear_buffer
, buffer
->_2d
.width
, rect
.pBits
, rect
.Pitch
,
361 buffer
->_2d
.width
, buffer
->_2d
.height
);
362 IDirect3DSurface9_UnlockRect(buffer
->d3d9_surface
.surface
);
370 *data
= buffer
->_2d
.linear_buffer
;
372 *max_length
= buffer
->_2d
.plane_size
;
374 *current_length
= buffer
->_2d
.plane_size
;
377 LeaveCriticalSection(&buffer
->cs
);
382 static HRESULT WINAPI
d3d9_surface_buffer_Unlock(IMFMediaBuffer
*iface
)
384 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
387 TRACE("%p.\n", iface
);
389 EnterCriticalSection(&buffer
->cs
);
391 if (!buffer
->_2d
.linear_buffer
)
392 hr
= HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED
);
393 else if (!--buffer
->_2d
.locks
)
397 if (SUCCEEDED(hr
= IDirect3DSurface9_LockRect(buffer
->d3d9_surface
.surface
, &rect
, NULL
, 0)))
399 MFCopyImage(rect
.pBits
, rect
.Pitch
, buffer
->_2d
.linear_buffer
, buffer
->_2d
.width
,
400 buffer
->_2d
.width
, buffer
->_2d
.height
);
401 IDirect3DSurface9_UnlockRect(buffer
->d3d9_surface
.surface
);
404 heap_free(buffer
->_2d
.linear_buffer
);
405 buffer
->_2d
.linear_buffer
= NULL
;
408 LeaveCriticalSection(&buffer
->cs
);
413 static HRESULT WINAPI
d3d9_surface_buffer_SetCurrentLength(IMFMediaBuffer
*iface
, DWORD current_length
)
415 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
417 TRACE("%p, %u.\n", iface
, current_length
);
419 buffer
->current_length
= current_length
;
424 static const IMFMediaBufferVtbl d3d9_surface_1d_buffer_vtbl
=
426 memory_1d_2d_buffer_QueryInterface
,
427 memory_buffer_AddRef
,
428 memory_buffer_Release
,
429 d3d9_surface_buffer_Lock
,
430 d3d9_surface_buffer_Unlock
,
431 memory_buffer_GetCurrentLength
,
432 d3d9_surface_buffer_SetCurrentLength
,
433 memory_buffer_GetMaxLength
,
436 static HRESULT WINAPI
memory_2d_buffer_QueryInterface(IMF2DBuffer2
*iface
, REFIID riid
, void **obj
)
438 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
439 return IMFMediaBuffer_QueryInterface(&buffer
->IMFMediaBuffer_iface
, riid
, obj
);
442 static ULONG WINAPI
memory_2d_buffer_AddRef(IMF2DBuffer2
*iface
)
444 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
445 return IMFMediaBuffer_AddRef(&buffer
->IMFMediaBuffer_iface
);
448 static ULONG WINAPI
memory_2d_buffer_Release(IMF2DBuffer2
*iface
)
450 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
451 return IMFMediaBuffer_Release(&buffer
->IMFMediaBuffer_iface
);
454 static HRESULT
memory_2d_buffer_lock(struct buffer
*buffer
, BYTE
**scanline0
, LONG
*pitch
,
455 BYTE
**buffer_start
, DWORD
*buffer_length
)
459 if (buffer
->_2d
.linear_buffer
)
460 hr
= MF_E_UNEXPECTED
;
464 *scanline0
= buffer
->_2d
.scanline0
;
465 *pitch
= buffer
->_2d
.pitch
;
467 *buffer_start
= buffer
->data
;
469 *buffer_length
= buffer
->max_length
;
475 static HRESULT WINAPI
memory_2d_buffer_Lock2D(IMF2DBuffer2
*iface
, BYTE
**scanline0
, LONG
*pitch
)
477 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
480 TRACE("%p, %p, %p.\n", iface
, scanline0
, pitch
);
482 if (!scanline0
|| !pitch
)
485 EnterCriticalSection(&buffer
->cs
);
487 hr
= memory_2d_buffer_lock(buffer
, scanline0
, pitch
, NULL
, NULL
);
489 LeaveCriticalSection(&buffer
->cs
);
494 static HRESULT WINAPI
memory_2d_buffer_Unlock2D(IMF2DBuffer2
*iface
)
496 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
499 TRACE("%p.\n", iface
);
501 EnterCriticalSection(&buffer
->cs
);
503 if (!buffer
->_2d
.linear_buffer
)
505 if (buffer
->_2d
.locks
)
508 hr
= HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED
);
511 LeaveCriticalSection(&buffer
->cs
);
516 static HRESULT WINAPI
memory_2d_buffer_GetScanline0AndPitch(IMF2DBuffer2
*iface
, BYTE
**scanline0
, LONG
*pitch
)
518 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
521 TRACE("%p, %p, %p.\n", iface
, scanline0
, pitch
);
523 if (!scanline0
|| !pitch
)
526 EnterCriticalSection(&buffer
->cs
);
528 if (buffer
->_2d
.linear_buffer
|| !buffer
->_2d
.locks
)
529 hr
= HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED
);
532 *scanline0
= buffer
->_2d
.scanline0
;
533 *pitch
= buffer
->_2d
.pitch
;
536 LeaveCriticalSection(&buffer
->cs
);
541 static HRESULT WINAPI
memory_2d_buffer_IsContiguousFormat(IMF2DBuffer2
*iface
, BOOL
*is_contiguous
)
543 TRACE("%p, %p.\n", iface
, is_contiguous
);
548 *is_contiguous
= FALSE
;
553 static HRESULT WINAPI
memory_2d_buffer_GetContiguousLength(IMF2DBuffer2
*iface
, DWORD
*length
)
555 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
557 TRACE("%p, %p.\n", iface
, length
);
562 *length
= buffer
->_2d
.plane_size
;
567 static HRESULT WINAPI
memory_2d_buffer_ContiguousCopyTo(IMF2DBuffer2
*iface
, BYTE
*dest_buffer
, DWORD dest_length
)
569 FIXME("%p, %p, %u.\n", iface
, dest_buffer
, dest_length
);
574 static HRESULT WINAPI
memory_2d_buffer_ContiguousCopyFrom(IMF2DBuffer2
*iface
, const BYTE
*src_buffer
, DWORD src_length
)
576 FIXME("%p, %p, %u.\n", iface
, src_buffer
, src_length
);
581 static HRESULT WINAPI
memory_2d_buffer_Lock2DSize(IMF2DBuffer2
*iface
, MF2DBuffer_LockFlags flags
, BYTE
**scanline0
,
582 LONG
*pitch
, BYTE
**buffer_start
, DWORD
*buffer_length
)
584 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
587 TRACE("%p, %#x, %p, %p, %p, %p.\n", iface
, flags
, scanline0
, pitch
, buffer_start
, buffer_length
);
589 if (!scanline0
|| !pitch
|| !buffer_start
|| !buffer_length
)
592 EnterCriticalSection(&buffer
->cs
);
594 hr
= memory_2d_buffer_lock(buffer
, scanline0
, pitch
, buffer_start
, buffer_length
);
596 LeaveCriticalSection(&buffer
->cs
);
601 static HRESULT WINAPI
memory_2d_buffer_Copy2DTo(IMF2DBuffer2
*iface
, IMF2DBuffer2
*dest_buffer
)
603 FIXME("%p, %p.\n", iface
, dest_buffer
);
608 static const IMF2DBuffer2Vtbl memory_2d_buffer_vtbl
=
610 memory_2d_buffer_QueryInterface
,
611 memory_2d_buffer_AddRef
,
612 memory_2d_buffer_Release
,
613 memory_2d_buffer_Lock2D
,
614 memory_2d_buffer_Unlock2D
,
615 memory_2d_buffer_GetScanline0AndPitch
,
616 memory_2d_buffer_IsContiguousFormat
,
617 memory_2d_buffer_GetContiguousLength
,
618 memory_2d_buffer_ContiguousCopyTo
,
619 memory_2d_buffer_ContiguousCopyFrom
,
620 memory_2d_buffer_Lock2DSize
,
621 memory_2d_buffer_Copy2DTo
,
624 static HRESULT WINAPI
d3d9_surface_buffer_Lock2D(IMF2DBuffer2
*iface
, BYTE
**scanline0
, LONG
*pitch
)
626 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
629 TRACE("%p, %p, %p.\n", iface
, scanline0
, pitch
);
631 if (!scanline0
|| !pitch
)
634 EnterCriticalSection(&buffer
->cs
);
636 if (buffer
->_2d
.linear_buffer
)
637 hr
= MF_E_UNEXPECTED
;
638 else if (!buffer
->_2d
.locks
++)
640 hr
= IDirect3DSurface9_LockRect(buffer
->d3d9_surface
.surface
, &buffer
->d3d9_surface
.rect
, NULL
, 0);
645 *scanline0
= buffer
->d3d9_surface
.rect
.pBits
;
646 *pitch
= buffer
->d3d9_surface
.rect
.Pitch
;
649 LeaveCriticalSection(&buffer
->cs
);
654 static HRESULT WINAPI
d3d9_surface_buffer_Unlock2D(IMF2DBuffer2
*iface
)
656 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
659 TRACE("%p.\n", iface
);
661 EnterCriticalSection(&buffer
->cs
);
663 if (buffer
->_2d
.locks
)
665 if (!--buffer
->_2d
.locks
)
667 IDirect3DSurface9_UnlockRect(buffer
->d3d9_surface
.surface
);
668 memset(&buffer
->d3d9_surface
.rect
, 0, sizeof(buffer
->d3d9_surface
.rect
));
672 hr
= HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED
);
674 LeaveCriticalSection(&buffer
->cs
);
679 static HRESULT WINAPI
d3d9_surface_buffer_GetScanline0AndPitch(IMF2DBuffer2
*iface
, BYTE
**scanline0
, LONG
*pitch
)
681 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
684 TRACE("%p, %p, %p.\n", iface
, scanline0
, pitch
);
686 if (!scanline0
|| !pitch
)
689 EnterCriticalSection(&buffer
->cs
);
691 if (!buffer
->_2d
.locks
)
695 hr
= HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED
);
699 *scanline0
= buffer
->d3d9_surface
.rect
.pBits
;
700 *pitch
= buffer
->d3d9_surface
.rect
.Pitch
;
703 LeaveCriticalSection(&buffer
->cs
);
708 static HRESULT WINAPI
d3d9_surface_buffer_Lock2DSize(IMF2DBuffer2
*iface
, MF2DBuffer_LockFlags flags
, BYTE
**scanline0
,
709 LONG
*pitch
, BYTE
**buffer_start
, DWORD
*buffer_length
)
711 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
714 TRACE("%p, %#x, %p, %p, %p, %p.\n", iface
, flags
, scanline0
, pitch
, buffer_start
, buffer_length
);
716 if (!scanline0
|| !pitch
|| !buffer_start
|| !buffer_length
)
719 EnterCriticalSection(&buffer
->cs
);
721 if (buffer
->_2d
.linear_buffer
)
722 hr
= MF_E_UNEXPECTED
;
723 else if (!buffer
->_2d
.locks
++)
725 hr
= IDirect3DSurface9_LockRect(buffer
->d3d9_surface
.surface
, &buffer
->d3d9_surface
.rect
, NULL
, 0);
730 *scanline0
= buffer
->d3d9_surface
.rect
.pBits
;
731 *pitch
= buffer
->d3d9_surface
.rect
.Pitch
;
733 *buffer_start
= *scanline0
;
735 *buffer_length
= buffer
->d3d9_surface
.rect
.Pitch
* buffer
->_2d
.height
;
738 LeaveCriticalSection(&buffer
->cs
);
743 static const IMF2DBuffer2Vtbl d3d9_surface_buffer_vtbl
=
745 memory_2d_buffer_QueryInterface
,
746 memory_2d_buffer_AddRef
,
747 memory_2d_buffer_Release
,
748 d3d9_surface_buffer_Lock2D
,
749 d3d9_surface_buffer_Unlock2D
,
750 d3d9_surface_buffer_GetScanline0AndPitch
,
751 memory_2d_buffer_IsContiguousFormat
,
752 memory_2d_buffer_GetContiguousLength
,
753 memory_2d_buffer_ContiguousCopyTo
,
754 memory_2d_buffer_ContiguousCopyFrom
,
755 d3d9_surface_buffer_Lock2DSize
,
756 memory_2d_buffer_Copy2DTo
,
759 static HRESULT WINAPI
memory_2d_buffer_gs_QueryInterface(IMFGetService
*iface
, REFIID riid
, void **obj
)
761 struct buffer
*buffer
= impl_from_IMFGetService(iface
);
762 return IMFMediaBuffer_QueryInterface(&buffer
->IMFMediaBuffer_iface
, riid
, obj
);
765 static ULONG WINAPI
memory_2d_buffer_gs_AddRef(IMFGetService
*iface
)
767 struct buffer
*buffer
= impl_from_IMFGetService(iface
);
768 return IMFMediaBuffer_AddRef(&buffer
->IMFMediaBuffer_iface
);
771 static ULONG WINAPI
memory_2d_buffer_gs_Release(IMFGetService
*iface
)
773 struct buffer
*buffer
= impl_from_IMFGetService(iface
);
774 return IMFMediaBuffer_Release(&buffer
->IMFMediaBuffer_iface
);
777 static HRESULT WINAPI
memory_2d_buffer_gs_GetService(IMFGetService
*iface
, REFGUID service
, REFIID riid
, void **obj
)
779 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(service
), debugstr_guid(riid
), obj
);
784 static const IMFGetServiceVtbl memory_2d_buffer_gs_vtbl
=
786 memory_2d_buffer_gs_QueryInterface
,
787 memory_2d_buffer_gs_AddRef
,
788 memory_2d_buffer_gs_Release
,
789 memory_2d_buffer_gs_GetService
,
792 static HRESULT WINAPI
d3d9_surface_buffer_gs_GetService(IMFGetService
*iface
, REFGUID service
, REFIID riid
, void **obj
)
794 struct buffer
*buffer
= impl_from_IMFGetService(iface
);
796 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(service
), debugstr_guid(riid
), obj
);
798 if (IsEqualGUID(service
, &MR_BUFFER_SERVICE
))
800 return IDirect3DSurface9_QueryInterface(buffer
->d3d9_surface
.surface
, riid
, obj
);
806 static const IMFGetServiceVtbl d3d9_surface_buffer_gs_vtbl
=
808 memory_2d_buffer_gs_QueryInterface
,
809 memory_2d_buffer_gs_AddRef
,
810 memory_2d_buffer_gs_Release
,
811 d3d9_surface_buffer_gs_GetService
,
814 static HRESULT WINAPI
dxgi_1d_2d_buffer_QueryInterface(IMFMediaBuffer
*iface
, REFIID riid
, void **out
)
816 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
818 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), out
);
820 if (IsEqualIID(riid
, &IID_IMFMediaBuffer
) ||
821 IsEqualIID(riid
, &IID_IUnknown
))
823 *out
= &buffer
->IMFMediaBuffer_iface
;
825 else if (IsEqualIID(riid
, &IID_IMF2DBuffer2
) ||
826 IsEqualIID(riid
, &IID_IMF2DBuffer
))
828 *out
= &buffer
->IMF2DBuffer2_iface
;
830 else if (IsEqualIID(riid
, &IID_IMFDXGIBuffer
))
832 *out
= &buffer
->IMFDXGIBuffer_iface
;
836 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
838 return E_NOINTERFACE
;
841 IUnknown_AddRef((IUnknown
*)*out
);
845 static HRESULT
dxgi_surface_buffer_create_readback_texture(struct buffer
*buffer
)
847 D3D11_TEXTURE2D_DESC texture_desc
;
848 ID3D11Device
*device
;
851 if (buffer
->dxgi_surface
.rb_texture
)
854 ID3D11Texture2D_GetDevice(buffer
->dxgi_surface
.texture
, &device
);
856 ID3D11Texture2D_GetDesc(buffer
->dxgi_surface
.texture
, &texture_desc
);
857 texture_desc
.Usage
= D3D11_USAGE_STAGING
;
858 texture_desc
.BindFlags
= 0;
859 texture_desc
.CPUAccessFlags
= D3D11_CPU_ACCESS_READ
| D3D11_CPU_ACCESS_WRITE
;
860 texture_desc
.MiscFlags
= 0;
861 texture_desc
.MipLevels
= 1;
862 if (FAILED(hr
= ID3D11Device_CreateTexture2D(device
, &texture_desc
, NULL
, &buffer
->dxgi_surface
.rb_texture
)))
863 WARN("Failed to create readback texture, hr %#x.\n", hr
);
865 ID3D11Device_Release(device
);
870 static HRESULT
dxgi_surface_buffer_map(struct buffer
*buffer
)
872 ID3D11DeviceContext
*immediate_context
;
873 ID3D11Device
*device
;
876 if (FAILED(hr
= dxgi_surface_buffer_create_readback_texture(buffer
)))
879 ID3D11Texture2D_GetDevice(buffer
->dxgi_surface
.texture
, &device
);
880 ID3D11Device_GetImmediateContext(device
, &immediate_context
);
881 ID3D11DeviceContext_CopySubresourceRegion(immediate_context
, (ID3D11Resource
*)buffer
->dxgi_surface
.rb_texture
,
882 0, 0, 0, 0, (ID3D11Resource
*)buffer
->dxgi_surface
.texture
, buffer
->dxgi_surface
.sub_resource_idx
, NULL
);
884 memset(&buffer
->dxgi_surface
.map_desc
, 0, sizeof(buffer
->dxgi_surface
.map_desc
));
885 if (FAILED(hr
= ID3D11DeviceContext_Map(immediate_context
, (ID3D11Resource
*)buffer
->dxgi_surface
.rb_texture
,
886 0, D3D11_MAP_READ_WRITE
, 0, &buffer
->dxgi_surface
.map_desc
)))
888 WARN("Failed to map readback texture, hr %#x.\n", hr
);
891 ID3D11DeviceContext_Release(immediate_context
);
892 ID3D11Device_Release(device
);
897 static void dxgi_surface_buffer_unmap(struct buffer
*buffer
)
899 ID3D11DeviceContext
*immediate_context
;
900 ID3D11Device
*device
;
902 ID3D11Texture2D_GetDevice(buffer
->dxgi_surface
.texture
, &device
);
903 ID3D11Device_GetImmediateContext(device
, &immediate_context
);
904 ID3D11DeviceContext_Unmap(immediate_context
, (ID3D11Resource
*)buffer
->dxgi_surface
.rb_texture
, 0);
905 memset(&buffer
->dxgi_surface
.map_desc
, 0, sizeof(buffer
->dxgi_surface
.map_desc
));
907 ID3D11DeviceContext_CopySubresourceRegion(immediate_context
, (ID3D11Resource
*)buffer
->dxgi_surface
.texture
,
908 buffer
->dxgi_surface
.sub_resource_idx
, 0, 0, 0, (ID3D11Resource
*)buffer
->dxgi_surface
.rb_texture
, 0, NULL
);
910 ID3D11DeviceContext_Release(immediate_context
);
911 ID3D11Device_Release(device
);
914 static HRESULT WINAPI
dxgi_surface_buffer_Lock(IMFMediaBuffer
*iface
, BYTE
**data
, DWORD
*max_length
,
915 DWORD
*current_length
)
917 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
920 TRACE("%p, %p, %p, %p.\n", iface
, data
, max_length
, current_length
);
925 EnterCriticalSection(&buffer
->cs
);
927 if (!buffer
->_2d
.linear_buffer
&& buffer
->_2d
.locks
)
928 hr
= MF_E_INVALIDREQUEST
;
929 else if (!buffer
->_2d
.linear_buffer
)
931 if (!(buffer
->_2d
.linear_buffer
= heap_alloc(ALIGN_SIZE(buffer
->_2d
.plane_size
, MF_64_BYTE_ALIGNMENT
))))
936 hr
= dxgi_surface_buffer_map(buffer
);
939 MFCopyImage(buffer
->_2d
.linear_buffer
, buffer
->_2d
.width
, buffer
->dxgi_surface
.map_desc
.pData
,
940 buffer
->dxgi_surface
.map_desc
.RowPitch
, buffer
->_2d
.width
, buffer
->_2d
.height
);
948 *data
= buffer
->_2d
.linear_buffer
;
950 *max_length
= buffer
->_2d
.plane_size
;
952 *current_length
= buffer
->_2d
.plane_size
;
955 LeaveCriticalSection(&buffer
->cs
);
960 static HRESULT WINAPI
dxgi_surface_buffer_Unlock(IMFMediaBuffer
*iface
)
962 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
965 TRACE("%p.\n", iface
);
967 EnterCriticalSection(&buffer
->cs
);
969 if (!buffer
->_2d
.linear_buffer
)
970 hr
= HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED
);
971 else if (!--buffer
->_2d
.locks
)
973 MFCopyImage(buffer
->dxgi_surface
.map_desc
.pData
, buffer
->dxgi_surface
.map_desc
.RowPitch
,
974 buffer
->_2d
.linear_buffer
, buffer
->_2d
.width
, buffer
->_2d
.width
, buffer
->_2d
.height
);
975 dxgi_surface_buffer_unmap(buffer
);
977 heap_free(buffer
->_2d
.linear_buffer
);
978 buffer
->_2d
.linear_buffer
= NULL
;
981 LeaveCriticalSection(&buffer
->cs
);
986 static HRESULT WINAPI
dxgi_surface_buffer_SetCurrentLength(IMFMediaBuffer
*iface
, DWORD current_length
)
988 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
990 TRACE("%p, %u.\n", iface
, current_length
);
992 buffer
->current_length
= current_length
;
997 static HRESULT WINAPI
dxgi_surface_buffer_Lock2D(IMF2DBuffer2
*iface
, BYTE
**scanline0
, LONG
*pitch
)
999 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
1002 TRACE("%p, %p, %p.\n", iface
, scanline0
, pitch
);
1004 if (!scanline0
|| !pitch
)
1007 EnterCriticalSection(&buffer
->cs
);
1009 if (buffer
->_2d
.linear_buffer
)
1010 hr
= MF_E_UNEXPECTED
;
1011 else if (!buffer
->_2d
.locks
++)
1012 hr
= dxgi_surface_buffer_map(buffer
);
1016 *scanline0
= buffer
->dxgi_surface
.map_desc
.pData
;
1017 *pitch
= buffer
->dxgi_surface
.map_desc
.RowPitch
;
1020 LeaveCriticalSection(&buffer
->cs
);
1025 static HRESULT WINAPI
dxgi_surface_buffer_Unlock2D(IMF2DBuffer2
*iface
)
1027 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
1030 TRACE("%p.\n", iface
);
1032 EnterCriticalSection(&buffer
->cs
);
1034 if (buffer
->_2d
.locks
)
1036 if (!--buffer
->_2d
.locks
)
1037 dxgi_surface_buffer_unmap(buffer
);
1040 hr
= HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED
);
1042 LeaveCriticalSection(&buffer
->cs
);
1047 static HRESULT WINAPI
dxgi_surface_buffer_GetScanline0AndPitch(IMF2DBuffer2
*iface
, BYTE
**scanline0
, LONG
*pitch
)
1049 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
1052 TRACE("%p, %p, %p.\n", iface
, scanline0
, pitch
);
1054 if (!scanline0
|| !pitch
)
1057 EnterCriticalSection(&buffer
->cs
);
1059 if (!buffer
->_2d
.locks
)
1063 hr
= HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED
);
1067 *scanline0
= buffer
->dxgi_surface
.map_desc
.pData
;
1068 *pitch
= buffer
->dxgi_surface
.map_desc
.RowPitch
;
1071 LeaveCriticalSection(&buffer
->cs
);
1076 static HRESULT WINAPI
dxgi_surface_buffer_Lock2DSize(IMF2DBuffer2
*iface
, MF2DBuffer_LockFlags flags
,
1077 BYTE
**scanline0
, LONG
*pitch
, BYTE
**buffer_start
, DWORD
*buffer_length
)
1079 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
1082 TRACE("%p, %#x, %p, %p, %p, %p.\n", iface
, flags
, scanline0
, pitch
, buffer_start
, buffer_length
);
1084 if (!scanline0
|| !pitch
|| !buffer_start
|| !buffer_length
)
1087 EnterCriticalSection(&buffer
->cs
);
1089 if (buffer
->_2d
.linear_buffer
)
1090 hr
= MF_E_UNEXPECTED
;
1091 else if (!buffer
->_2d
.locks
++)
1092 hr
= dxgi_surface_buffer_map(buffer
);
1096 *scanline0
= buffer
->dxgi_surface
.map_desc
.pData
;
1097 *pitch
= buffer
->dxgi_surface
.map_desc
.RowPitch
;
1099 *buffer_start
= *scanline0
;
1101 *buffer_length
= buffer
->dxgi_surface
.map_desc
.RowPitch
* buffer
->_2d
.height
;
1104 LeaveCriticalSection(&buffer
->cs
);
1109 static HRESULT WINAPI
dxgi_buffer_QueryInterface(IMFDXGIBuffer
*iface
, REFIID riid
, void **obj
)
1111 struct buffer
*buffer
= impl_from_IMFDXGIBuffer(iface
);
1112 return IMFMediaBuffer_QueryInterface(&buffer
->IMFMediaBuffer_iface
, riid
, obj
);
1115 static ULONG WINAPI
dxgi_buffer_AddRef(IMFDXGIBuffer
*iface
)
1117 struct buffer
*buffer
= impl_from_IMFDXGIBuffer(iface
);
1118 return IMFMediaBuffer_AddRef(&buffer
->IMFMediaBuffer_iface
);
1121 static ULONG WINAPI
dxgi_buffer_Release(IMFDXGIBuffer
*iface
)
1123 struct buffer
*buffer
= impl_from_IMFDXGIBuffer(iface
);
1124 return IMFMediaBuffer_Release(&buffer
->IMFMediaBuffer_iface
);
1127 static HRESULT WINAPI
dxgi_buffer_GetResource(IMFDXGIBuffer
*iface
, REFIID riid
, void **obj
)
1129 struct buffer
*buffer
= impl_from_IMFDXGIBuffer(iface
);
1131 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
1133 return ID3D11Texture2D_QueryInterface(buffer
->dxgi_surface
.texture
, riid
, obj
);
1136 static HRESULT WINAPI
dxgi_buffer_GetSubresourceIndex(IMFDXGIBuffer
*iface
, UINT
*index
)
1138 struct buffer
*buffer
= impl_from_IMFDXGIBuffer(iface
);
1140 TRACE("%p, %p.\n", iface
, index
);
1145 *index
= buffer
->dxgi_surface
.sub_resource_idx
;
1150 static HRESULT WINAPI
dxgi_buffer_GetUnknown(IMFDXGIBuffer
*iface
, REFIID guid
, REFIID riid
, void **object
)
1152 struct buffer
*buffer
= impl_from_IMFDXGIBuffer(iface
);
1154 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(guid
), debugstr_guid(riid
), object
);
1156 if (attributes_GetUnknown(&buffer
->dxgi_surface
.attributes
, guid
, riid
, object
) == MF_E_ATTRIBUTENOTFOUND
)
1157 return MF_E_NOT_FOUND
;
1162 static HRESULT WINAPI
dxgi_buffer_SetUnknown(IMFDXGIBuffer
*iface
, REFIID guid
, IUnknown
*data
)
1164 struct buffer
*buffer
= impl_from_IMFDXGIBuffer(iface
);
1167 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(guid
), data
);
1169 EnterCriticalSection(&buffer
->dxgi_surface
.attributes
.cs
);
1172 if (SUCCEEDED(attributes_GetItem(&buffer
->dxgi_surface
.attributes
, guid
, NULL
)))
1173 hr
= HRESULT_FROM_WIN32(ERROR_OBJECT_ALREADY_EXISTS
);
1175 hr
= attributes_SetUnknown(&buffer
->dxgi_surface
.attributes
, guid
, data
);
1179 attributes_DeleteItem(&buffer
->dxgi_surface
.attributes
, guid
);
1181 LeaveCriticalSection(&buffer
->dxgi_surface
.attributes
.cs
);
1186 static const IMFMediaBufferVtbl dxgi_surface_1d_buffer_vtbl
=
1188 dxgi_1d_2d_buffer_QueryInterface
,
1189 memory_buffer_AddRef
,
1190 memory_buffer_Release
,
1191 dxgi_surface_buffer_Lock
,
1192 dxgi_surface_buffer_Unlock
,
1193 memory_buffer_GetCurrentLength
,
1194 dxgi_surface_buffer_SetCurrentLength
,
1195 memory_buffer_GetMaxLength
,
1198 static const IMF2DBuffer2Vtbl dxgi_surface_buffer_vtbl
=
1200 memory_2d_buffer_QueryInterface
,
1201 memory_2d_buffer_AddRef
,
1202 memory_2d_buffer_Release
,
1203 dxgi_surface_buffer_Lock2D
,
1204 dxgi_surface_buffer_Unlock2D
,
1205 dxgi_surface_buffer_GetScanline0AndPitch
,
1206 memory_2d_buffer_IsContiguousFormat
,
1207 memory_2d_buffer_GetContiguousLength
,
1208 memory_2d_buffer_ContiguousCopyTo
,
1209 memory_2d_buffer_ContiguousCopyFrom
,
1210 dxgi_surface_buffer_Lock2DSize
,
1211 memory_2d_buffer_Copy2DTo
,
1214 static const IMFDXGIBufferVtbl dxgi_buffer_vtbl
=
1216 dxgi_buffer_QueryInterface
,
1218 dxgi_buffer_Release
,
1219 dxgi_buffer_GetResource
,
1220 dxgi_buffer_GetSubresourceIndex
,
1221 dxgi_buffer_GetUnknown
,
1222 dxgi_buffer_SetUnknown
,
1225 static HRESULT
memory_buffer_init(struct buffer
*buffer
, DWORD max_length
, DWORD alignment
,
1226 const IMFMediaBufferVtbl
*vtbl
)
1228 buffer
->data
= heap_alloc_zero(ALIGN_SIZE(max_length
, alignment
));
1230 return E_OUTOFMEMORY
;
1232 buffer
->IMFMediaBuffer_iface
.lpVtbl
= vtbl
;
1233 buffer
->refcount
= 1;
1234 buffer
->max_length
= max_length
;
1235 buffer
->current_length
= 0;
1236 InitializeCriticalSection(&buffer
->cs
);
1241 static HRESULT
create_1d_buffer(DWORD max_length
, DWORD alignment
, IMFMediaBuffer
**buffer
)
1243 struct buffer
*object
;
1251 object
= heap_alloc_zero(sizeof(*object
));
1253 return E_OUTOFMEMORY
;
1255 hr
= memory_buffer_init(object
, max_length
, alignment
, &memory_1d_buffer_vtbl
);
1262 *buffer
= &object
->IMFMediaBuffer_iface
;
1267 static HRESULT
create_2d_buffer(DWORD width
, DWORD height
, DWORD fourcc
, BOOL bottom_up
, IMFMediaBuffer
**buffer
)
1269 unsigned int stride
, max_length
, plane_size
;
1270 struct buffer
*object
;
1271 unsigned int row_alignment
;
1282 memcpy(&subtype
, &MFVideoFormat_Base
, sizeof(subtype
));
1283 subtype
.Data1
= fourcc
;
1285 if (!(stride
= mf_format_get_stride(&subtype
, width
, &is_yuv
)))
1286 return MF_E_INVALIDMEDIATYPE
;
1288 if (is_yuv
&& bottom_up
)
1289 return MF_E_INVALIDMEDIATYPE
;
1291 if (FAILED(hr
= MFGetPlaneSize(fourcc
, width
, height
, &plane_size
)))
1294 object
= heap_alloc_zero(sizeof(*object
));
1296 return E_OUTOFMEMORY
;
1300 case MAKEFOURCC('I','M','C','1'):
1301 case MAKEFOURCC('I','M','C','2'):
1302 case MAKEFOURCC('I','M','C','3'):
1303 case MAKEFOURCC('I','M','C','4'):
1304 case MAKEFOURCC('Y','V','1','2'):
1305 row_alignment
= MF_128_BYTE_ALIGNMENT
;
1308 row_alignment
= MF_64_BYTE_ALIGNMENT
;
1311 pitch
= ALIGN_SIZE(stride
, row_alignment
);
1315 case MAKEFOURCC('I','M','C','1'):
1316 case MAKEFOURCC('I','M','C','3'):
1317 max_length
= pitch
* height
* 2;
1320 case MAKEFOURCC('N','V','1','2'):
1321 max_length
= pitch
* height
* 3 / 2;
1324 max_length
= pitch
* height
;
1327 if (FAILED(hr
= memory_buffer_init(object
, max_length
, MF_1_BYTE_ALIGNMENT
, &memory_1d_2d_buffer_vtbl
)))
1333 object
->IMF2DBuffer2_iface
.lpVtbl
= &memory_2d_buffer_vtbl
;
1334 object
->IMFGetService_iface
.lpVtbl
= &memory_2d_buffer_gs_vtbl
;
1335 object
->_2d
.plane_size
= plane_size
;
1336 object
->_2d
.width
= stride
;
1337 object
->_2d
.height
= height
;
1338 object
->_2d
.pitch
= bottom_up
? -pitch
: pitch
;
1339 object
->_2d
.scanline0
= bottom_up
? object
->data
+ pitch
* (object
->_2d
.height
- 1) : object
->data
;
1341 *buffer
= &object
->IMFMediaBuffer_iface
;
1346 static HRESULT
create_d3d9_surface_buffer(IUnknown
*surface
, BOOL bottom_up
, IMFMediaBuffer
**buffer
)
1348 struct buffer
*object
;
1349 D3DSURFACE_DESC desc
;
1350 unsigned int stride
;
1354 IDirect3DSurface9_GetDesc((IDirect3DSurface9
*)surface
, &desc
);
1355 TRACE("format %#x, %u x %u.\n", desc
.Format
, desc
.Width
, desc
.Height
);
1357 memcpy(&subtype
, &MFVideoFormat_Base
, sizeof(subtype
));
1358 subtype
.Data1
= desc
.Format
;
1360 if (!(stride
= mf_format_get_stride(&subtype
, desc
.Width
, &is_yuv
)))
1361 return MF_E_INVALIDMEDIATYPE
;
1363 object
= heap_alloc_zero(sizeof(*object
));
1365 return E_OUTOFMEMORY
;
1367 object
->IMFMediaBuffer_iface
.lpVtbl
= &d3d9_surface_1d_buffer_vtbl
;
1368 object
->IMF2DBuffer2_iface
.lpVtbl
= &d3d9_surface_buffer_vtbl
;
1369 object
->IMFGetService_iface
.lpVtbl
= &d3d9_surface_buffer_gs_vtbl
;
1370 object
->refcount
= 1;
1371 InitializeCriticalSection(&object
->cs
);
1372 object
->d3d9_surface
.surface
= (IDirect3DSurface9
*)surface
;
1373 IUnknown_AddRef(surface
);
1375 MFGetPlaneSize(desc
.Format
, desc
.Width
, desc
.Height
, &object
->_2d
.plane_size
);
1376 object
->_2d
.width
= stride
;
1377 object
->_2d
.height
= desc
.Height
;
1378 object
->max_length
= object
->_2d
.plane_size
;
1380 *buffer
= &object
->IMFMediaBuffer_iface
;
1385 static HRESULT
create_dxgi_surface_buffer(IUnknown
*surface
, unsigned int sub_resource_idx
,
1386 BOOL bottom_up
, IMFMediaBuffer
**buffer
)
1388 struct buffer
*object
;
1389 D3D11_TEXTURE2D_DESC desc
;
1390 ID3D11Texture2D
*texture
;
1391 unsigned int stride
;
1397 if (FAILED(hr
= IUnknown_QueryInterface(surface
, &IID_ID3D11Texture2D
, (void **)&texture
)))
1399 WARN("Failed to get texture interface, hr %#x.\n", hr
);
1403 ID3D11Texture2D_GetDesc(texture
, &desc
);
1404 TRACE("format %#x, %u x %u.\n", desc
.Format
, desc
.Width
, desc
.Height
);
1406 memcpy(&subtype
, &MFVideoFormat_Base
, sizeof(subtype
));
1407 subtype
.Data1
= format
= MFMapDXGIFormatToDX9Format(desc
.Format
);
1409 if (!(stride
= mf_format_get_stride(&subtype
, desc
.Width
, &is_yuv
)))
1411 ID3D11Texture2D_Release(texture
);
1412 return MF_E_INVALIDMEDIATYPE
;
1415 object
= heap_alloc_zero(sizeof(*object
));
1418 ID3D11Texture2D_Release(texture
);
1419 return E_OUTOFMEMORY
;
1422 object
->IMFMediaBuffer_iface
.lpVtbl
= &dxgi_surface_1d_buffer_vtbl
;
1423 object
->IMF2DBuffer2_iface
.lpVtbl
= &dxgi_surface_buffer_vtbl
;
1424 object
->IMFDXGIBuffer_iface
.lpVtbl
= &dxgi_buffer_vtbl
;
1425 object
->refcount
= 1;
1426 InitializeCriticalSection(&object
->cs
);
1427 object
->dxgi_surface
.texture
= texture
;
1428 object
->dxgi_surface
.sub_resource_idx
= sub_resource_idx
;
1430 MFGetPlaneSize(format
, desc
.Width
, desc
.Height
, &object
->_2d
.plane_size
);
1431 object
->_2d
.width
= stride
;
1432 object
->_2d
.height
= desc
.Height
;
1433 object
->max_length
= object
->_2d
.plane_size
;
1435 if (FAILED(hr
= init_attributes_object(&object
->dxgi_surface
.attributes
, 0)))
1437 IMFMediaBuffer_Release(&object
->IMFMediaBuffer_iface
);
1441 *buffer
= &object
->IMFMediaBuffer_iface
;
1446 /***********************************************************************
1447 * MFCreateMemoryBuffer (mfplat.@)
1449 HRESULT WINAPI
MFCreateMemoryBuffer(DWORD max_length
, IMFMediaBuffer
**buffer
)
1451 TRACE("%u, %p.\n", max_length
, buffer
);
1453 return create_1d_buffer(max_length
, MF_1_BYTE_ALIGNMENT
, buffer
);
1456 /***********************************************************************
1457 * MFCreateAlignedMemoryBuffer (mfplat.@)
1459 HRESULT WINAPI
MFCreateAlignedMemoryBuffer(DWORD max_length
, DWORD alignment
, IMFMediaBuffer
**buffer
)
1461 TRACE("%u, %u, %p.\n", max_length
, alignment
, buffer
);
1463 return create_1d_buffer(max_length
, alignment
, buffer
);
1466 /***********************************************************************
1467 * MFCreate2DMediaBuffer (mfplat.@)
1469 HRESULT WINAPI
MFCreate2DMediaBuffer(DWORD width
, DWORD height
, DWORD fourcc
, BOOL bottom_up
, IMFMediaBuffer
**buffer
)
1471 TRACE("%u, %u, %s, %d, %p.\n", width
, height
, debugstr_fourcc(fourcc
), bottom_up
, buffer
);
1473 return create_2d_buffer(width
, height
, fourcc
, bottom_up
, buffer
);
1476 /***********************************************************************
1477 * MFCreateDXSurfaceBuffer (mfplat.@)
1479 HRESULT WINAPI
MFCreateDXSurfaceBuffer(REFIID riid
, IUnknown
*surface
, BOOL bottom_up
, IMFMediaBuffer
**buffer
)
1481 TRACE("%s, %p, %d, %p.\n", debugstr_guid(riid
), surface
, bottom_up
, buffer
);
1483 if (!IsEqualIID(riid
, &IID_IDirect3DSurface9
))
1484 return E_INVALIDARG
;
1486 return create_d3d9_surface_buffer(surface
, bottom_up
, buffer
);
1489 /***********************************************************************
1490 * MFCreateDXGISurfaceBuffer (mfplat.@)
1492 HRESULT WINAPI
MFCreateDXGISurfaceBuffer(REFIID riid
, IUnknown
*surface
, UINT subresource
, BOOL bottom_up
,
1493 IMFMediaBuffer
**buffer
)
1495 TRACE("%s, %p, %u, %d, %p.\n", debugstr_guid(riid
), surface
, subresource
, bottom_up
, buffer
);
1497 if (!IsEqualIID(riid
, &IID_ID3D11Texture2D
))
1498 return E_INVALIDARG
;
1500 return create_dxgi_surface_buffer(surface
, subresource
, bottom_up
, buffer
);
1503 static unsigned int buffer_get_aligned_length(unsigned int length
, unsigned int alignment
)
1505 length
= (length
+ alignment
) / alignment
;
1506 length
*= alignment
;
1511 HRESULT WINAPI
MFCreateMediaBufferFromMediaType(IMFMediaType
*media_type
, LONGLONG duration
, DWORD min_length
,
1512 DWORD alignment
, IMFMediaBuffer
**buffer
)
1514 UINT32 length
= 0, block_alignment
;
1515 LONGLONG avg_length
;
1519 TRACE("%p, %s, %u, %u, %p.\n", media_type
, debugstr_time(duration
), min_length
, alignment
, buffer
);
1522 return E_INVALIDARG
;
1524 if (FAILED(hr
= IMFMediaType_GetMajorType(media_type
, &major
)))
1527 if (IsEqualGUID(&major
, &MFMediaType_Audio
))
1529 block_alignment
= 0;
1530 if (FAILED(IMFMediaType_GetUINT32(media_type
, &MF_MT_AUDIO_BLOCK_ALIGNMENT
, &block_alignment
)))
1531 WARN("Block alignment was not specified.\n");
1533 if (block_alignment
)
1540 if (SUCCEEDED(IMFMediaType_GetUINT32(media_type
, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND
, &length
)))
1543 avg_length
= length
* duration
/ (10 * 1000 * 1000);
1547 alignment
= max(16, alignment
);
1549 length
= buffer_get_aligned_length(avg_length
+ 1, alignment
);
1550 length
= buffer_get_aligned_length(length
, block_alignment
);
1555 length
= max(length
, min_length
);
1557 return create_1d_buffer(length
, MF_1_BYTE_ALIGNMENT
, buffer
);
1560 FIXME("Major type %s is not supported.\n", debugstr_guid(&major
));