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
23 #include "mfplat_private.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(mfplat
);
33 #define ALIGN_SIZE(size, alignment) (((size) + (alignment)) & ~((alignment)))
35 typedef void (*p_copy_image_func
)(BYTE
*dest
, LONG dest_stride
, const BYTE
*src
, LONG src_stride
, DWORD width
, DWORD lines
);
39 IMFMediaBuffer IMFMediaBuffer_iface
;
40 IMF2DBuffer2 IMF2DBuffer2_iface
;
41 IMFDXGIBuffer IMFDXGIBuffer_iface
;
42 IMFGetService IMFGetService_iface
;
59 p_copy_image_func copy_image
;
63 IDirect3DSurface9
*surface
;
68 ID3D11Texture2D
*texture
;
69 unsigned int sub_resource_idx
;
70 ID3D11Texture2D
*rb_texture
;
71 D3D11_MAPPED_SUBRESOURCE map_desc
;
72 struct attributes attributes
;
78 static void copy_image(const struct buffer
*buffer
, BYTE
*dest
, LONG dest_stride
, const BYTE
*src
,
79 LONG src_stride
, DWORD width
, DWORD lines
)
81 MFCopyImage(dest
, dest_stride
, src
, src_stride
, width
, lines
);
83 if (buffer
->_2d
.copy_image
)
85 dest
+= dest_stride
* lines
;
86 src
+= src_stride
* lines
;
87 buffer
->_2d
.copy_image(dest
, dest_stride
, src
, src_stride
, width
, lines
);
91 static void copy_image_nv12(BYTE
*dest
, LONG dest_stride
, const BYTE
*src
, LONG src_stride
, DWORD width
, DWORD lines
)
93 MFCopyImage(dest
, dest_stride
, src
, src_stride
, width
, lines
/ 2);
96 static void copy_image_imc1(BYTE
*dest
, LONG dest_stride
, const BYTE
*src
, LONG src_stride
, DWORD width
, DWORD lines
)
98 MFCopyImage(dest
, dest_stride
, src
, src_stride
, width
/ 2, lines
);
101 static void copy_image_imc2(BYTE
*dest
, LONG dest_stride
, const BYTE
*src
, LONG src_stride
, DWORD width
, DWORD lines
)
103 MFCopyImage(dest
, dest_stride
/ 2, src
, src_stride
/ 2, width
/ 2, lines
);
106 static inline struct buffer
*impl_from_IMFMediaBuffer(IMFMediaBuffer
*iface
)
108 return CONTAINING_RECORD(iface
, struct buffer
, IMFMediaBuffer_iface
);
111 static struct buffer
*impl_from_IMF2DBuffer2(IMF2DBuffer2
*iface
)
113 return CONTAINING_RECORD(iface
, struct buffer
, IMF2DBuffer2_iface
);
116 static struct buffer
*impl_from_IMFGetService(IMFGetService
*iface
)
118 return CONTAINING_RECORD(iface
, struct buffer
, IMFGetService_iface
);
121 static struct buffer
*impl_from_IMFDXGIBuffer(IMFDXGIBuffer
*iface
)
123 return CONTAINING_RECORD(iface
, struct buffer
, IMFDXGIBuffer_iface
);
126 static HRESULT WINAPI
memory_buffer_QueryInterface(IMFMediaBuffer
*iface
, REFIID riid
, void **out
)
128 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
130 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), out
);
132 if (IsEqualIID(riid
, &IID_IMFMediaBuffer
) ||
133 IsEqualIID(riid
, &IID_IUnknown
))
135 *out
= &buffer
->IMFMediaBuffer_iface
;
136 IMFMediaBuffer_AddRef(iface
);
140 WARN("Unsupported %s.\n", debugstr_guid(riid
));
142 return E_NOINTERFACE
;
145 static ULONG WINAPI
memory_buffer_AddRef(IMFMediaBuffer
*iface
)
147 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
148 ULONG refcount
= InterlockedIncrement(&buffer
->refcount
);
150 TRACE("%p, refcount %lu.\n", buffer
, refcount
);
155 static ULONG WINAPI
memory_buffer_Release(IMFMediaBuffer
*iface
)
157 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
158 ULONG refcount
= InterlockedDecrement(&buffer
->refcount
);
160 TRACE("%p, refcount %lu.\n", iface
, refcount
);
164 if (buffer
->d3d9_surface
.surface
)
165 IDirect3DSurface9_Release(buffer
->d3d9_surface
.surface
);
166 if (buffer
->dxgi_surface
.texture
)
168 ID3D11Texture2D_Release(buffer
->dxgi_surface
.texture
);
169 if (buffer
->dxgi_surface
.rb_texture
)
170 ID3D11Texture2D_Release(buffer
->dxgi_surface
.rb_texture
);
171 clear_attributes_object(&buffer
->dxgi_surface
.attributes
);
173 DeleteCriticalSection(&buffer
->cs
);
174 free(buffer
->_2d
.linear_buffer
);
175 _aligned_free(buffer
->data
);
182 static HRESULT WINAPI
memory_buffer_Lock(IMFMediaBuffer
*iface
, BYTE
**data
, DWORD
*max_length
, DWORD
*current_length
)
184 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
186 TRACE("%p, %p %p, %p.\n", iface
, data
, max_length
, current_length
);
191 *data
= buffer
->data
;
193 *max_length
= buffer
->max_length
;
195 *current_length
= buffer
->current_length
;
200 static HRESULT WINAPI
memory_buffer_Unlock(IMFMediaBuffer
*iface
)
202 TRACE("%p.\n", iface
);
207 static HRESULT WINAPI
memory_buffer_GetCurrentLength(IMFMediaBuffer
*iface
, DWORD
*current_length
)
209 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
211 TRACE("%p.\n", iface
);
216 *current_length
= buffer
->current_length
;
221 static HRESULT WINAPI
memory_buffer_SetCurrentLength(IMFMediaBuffer
*iface
, DWORD current_length
)
223 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
225 TRACE("%p, %lu.\n", iface
, current_length
);
227 if (current_length
> buffer
->max_length
)
230 buffer
->current_length
= current_length
;
235 static HRESULT WINAPI
memory_buffer_GetMaxLength(IMFMediaBuffer
*iface
, DWORD
*max_length
)
237 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
239 TRACE("%p, %p.\n", iface
, max_length
);
244 *max_length
= buffer
->max_length
;
249 static const IMFMediaBufferVtbl memory_1d_buffer_vtbl
=
251 memory_buffer_QueryInterface
,
252 memory_buffer_AddRef
,
253 memory_buffer_Release
,
255 memory_buffer_Unlock
,
256 memory_buffer_GetCurrentLength
,
257 memory_buffer_SetCurrentLength
,
258 memory_buffer_GetMaxLength
,
261 static HRESULT WINAPI
memory_1d_2d_buffer_QueryInterface(IMFMediaBuffer
*iface
, REFIID riid
, void **out
)
263 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
265 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), out
);
267 if (IsEqualIID(riid
, &IID_IMFMediaBuffer
) ||
268 IsEqualIID(riid
, &IID_IUnknown
))
270 *out
= &buffer
->IMFMediaBuffer_iface
;
272 else if (IsEqualIID(riid
, &IID_IMF2DBuffer2
) ||
273 IsEqualIID(riid
, &IID_IMF2DBuffer
))
275 *out
= &buffer
->IMF2DBuffer2_iface
;
277 else if (IsEqualIID(riid
, &IID_IMFGetService
))
279 *out
= &buffer
->IMFGetService_iface
;
283 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
285 return E_NOINTERFACE
;
288 IUnknown_AddRef((IUnknown
*)*out
);
292 static HRESULT WINAPI
memory_1d_2d_buffer_Lock(IMFMediaBuffer
*iface
, BYTE
**data
, DWORD
*max_length
, DWORD
*current_length
)
294 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
297 TRACE("%p, %p, %p, %p.\n", iface
, data
, max_length
, current_length
);
302 /* Allocate linear buffer and return it as a copy of current content. Maximum and current length are
303 unrelated to 2D buffer maximum allocate length, or maintained current length. */
305 EnterCriticalSection(&buffer
->cs
);
307 if (!buffer
->_2d
.linear_buffer
&& buffer
->_2d
.locks
)
308 hr
= MF_E_INVALIDREQUEST
;
309 else if (!buffer
->_2d
.linear_buffer
)
311 if (!(buffer
->_2d
.linear_buffer
= malloc(buffer
->_2d
.plane_size
)))
315 copy_image(buffer
, buffer
->_2d
.linear_buffer
, buffer
->_2d
.width
, buffer
->data
, buffer
->_2d
.pitch
,
316 buffer
->_2d
.width
, buffer
->_2d
.height
);
322 *data
= buffer
->_2d
.linear_buffer
;
324 *max_length
= buffer
->_2d
.plane_size
;
326 *current_length
= buffer
->_2d
.plane_size
;
329 LeaveCriticalSection(&buffer
->cs
);
334 static HRESULT WINAPI
memory_1d_2d_buffer_Unlock(IMFMediaBuffer
*iface
)
336 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
338 TRACE("%p.\n", iface
);
340 EnterCriticalSection(&buffer
->cs
);
342 if (buffer
->_2d
.linear_buffer
&& !--buffer
->_2d
.locks
)
344 copy_image(buffer
, buffer
->data
, buffer
->_2d
.pitch
, buffer
->_2d
.linear_buffer
, buffer
->_2d
.width
,
345 buffer
->_2d
.width
, buffer
->_2d
.height
);
347 free(buffer
->_2d
.linear_buffer
);
348 buffer
->_2d
.linear_buffer
= NULL
;
351 LeaveCriticalSection(&buffer
->cs
);
356 static const IMFMediaBufferVtbl memory_1d_2d_buffer_vtbl
=
358 memory_1d_2d_buffer_QueryInterface
,
359 memory_buffer_AddRef
,
360 memory_buffer_Release
,
361 memory_1d_2d_buffer_Lock
,
362 memory_1d_2d_buffer_Unlock
,
363 memory_buffer_GetCurrentLength
,
364 memory_buffer_SetCurrentLength
,
365 memory_buffer_GetMaxLength
,
368 static HRESULT WINAPI
d3d9_surface_buffer_Lock(IMFMediaBuffer
*iface
, BYTE
**data
, DWORD
*max_length
, DWORD
*current_length
)
370 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
373 TRACE("%p, %p, %p, %p.\n", iface
, data
, max_length
, current_length
);
378 EnterCriticalSection(&buffer
->cs
);
380 if (!buffer
->_2d
.linear_buffer
&& buffer
->_2d
.locks
)
381 hr
= MF_E_INVALIDREQUEST
;
382 else if (!buffer
->_2d
.linear_buffer
)
386 if (!(buffer
->_2d
.linear_buffer
= malloc(buffer
->_2d
.plane_size
)))
391 hr
= IDirect3DSurface9_LockRect(buffer
->d3d9_surface
.surface
, &rect
, NULL
, 0);
394 copy_image(buffer
, buffer
->_2d
.linear_buffer
, buffer
->_2d
.width
, rect
.pBits
, rect
.Pitch
,
395 buffer
->_2d
.width
, buffer
->_2d
.height
);
396 IDirect3DSurface9_UnlockRect(buffer
->d3d9_surface
.surface
);
404 *data
= buffer
->_2d
.linear_buffer
;
406 *max_length
= buffer
->_2d
.plane_size
;
408 *current_length
= buffer
->_2d
.plane_size
;
411 LeaveCriticalSection(&buffer
->cs
);
416 static HRESULT WINAPI
d3d9_surface_buffer_Unlock(IMFMediaBuffer
*iface
)
418 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
421 TRACE("%p.\n", iface
);
423 EnterCriticalSection(&buffer
->cs
);
425 if (!buffer
->_2d
.linear_buffer
)
426 hr
= HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED
);
427 else if (!--buffer
->_2d
.locks
)
431 if (SUCCEEDED(hr
= IDirect3DSurface9_LockRect(buffer
->d3d9_surface
.surface
, &rect
, NULL
, 0)))
433 copy_image(buffer
, rect
.pBits
, rect
.Pitch
, buffer
->_2d
.linear_buffer
, buffer
->_2d
.width
,
434 buffer
->_2d
.width
, buffer
->_2d
.height
);
435 IDirect3DSurface9_UnlockRect(buffer
->d3d9_surface
.surface
);
438 free(buffer
->_2d
.linear_buffer
);
439 buffer
->_2d
.linear_buffer
= NULL
;
442 LeaveCriticalSection(&buffer
->cs
);
447 static HRESULT WINAPI
d3d9_surface_buffer_SetCurrentLength(IMFMediaBuffer
*iface
, DWORD current_length
)
449 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
451 TRACE("%p, %lu.\n", iface
, current_length
);
453 buffer
->current_length
= current_length
;
458 static const IMFMediaBufferVtbl d3d9_surface_1d_buffer_vtbl
=
460 memory_1d_2d_buffer_QueryInterface
,
461 memory_buffer_AddRef
,
462 memory_buffer_Release
,
463 d3d9_surface_buffer_Lock
,
464 d3d9_surface_buffer_Unlock
,
465 memory_buffer_GetCurrentLength
,
466 d3d9_surface_buffer_SetCurrentLength
,
467 memory_buffer_GetMaxLength
,
470 static HRESULT WINAPI
memory_2d_buffer_QueryInterface(IMF2DBuffer2
*iface
, REFIID riid
, void **obj
)
472 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
473 return IMFMediaBuffer_QueryInterface(&buffer
->IMFMediaBuffer_iface
, riid
, obj
);
476 static ULONG WINAPI
memory_2d_buffer_AddRef(IMF2DBuffer2
*iface
)
478 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
479 return IMFMediaBuffer_AddRef(&buffer
->IMFMediaBuffer_iface
);
482 static ULONG WINAPI
memory_2d_buffer_Release(IMF2DBuffer2
*iface
)
484 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
485 return IMFMediaBuffer_Release(&buffer
->IMFMediaBuffer_iface
);
488 static HRESULT
memory_2d_buffer_lock(struct buffer
*buffer
, BYTE
**scanline0
, LONG
*pitch
,
489 BYTE
**buffer_start
, DWORD
*buffer_length
)
493 if (buffer
->_2d
.linear_buffer
)
494 hr
= MF_E_UNEXPECTED
;
498 *scanline0
= buffer
->_2d
.scanline0
;
499 *pitch
= buffer
->_2d
.pitch
;
501 *buffer_start
= buffer
->data
;
503 *buffer_length
= buffer
->max_length
;
509 static HRESULT WINAPI
memory_2d_buffer_Lock2D(IMF2DBuffer2
*iface
, BYTE
**scanline0
, LONG
*pitch
)
511 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
514 TRACE("%p, %p, %p.\n", iface
, scanline0
, pitch
);
516 if (!scanline0
|| !pitch
)
519 EnterCriticalSection(&buffer
->cs
);
521 hr
= memory_2d_buffer_lock(buffer
, scanline0
, pitch
, NULL
, NULL
);
523 LeaveCriticalSection(&buffer
->cs
);
528 static HRESULT WINAPI
memory_2d_buffer_Unlock2D(IMF2DBuffer2
*iface
)
530 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
533 TRACE("%p.\n", iface
);
535 EnterCriticalSection(&buffer
->cs
);
537 if (!buffer
->_2d
.linear_buffer
)
539 if (buffer
->_2d
.locks
)
542 hr
= HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED
);
545 LeaveCriticalSection(&buffer
->cs
);
550 static HRESULT WINAPI
memory_2d_buffer_GetScanline0AndPitch(IMF2DBuffer2
*iface
, BYTE
**scanline0
, LONG
*pitch
)
552 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
555 TRACE("%p, %p, %p.\n", iface
, scanline0
, pitch
);
557 if (!scanline0
|| !pitch
)
560 EnterCriticalSection(&buffer
->cs
);
562 if (buffer
->_2d
.linear_buffer
|| !buffer
->_2d
.locks
)
563 hr
= HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED
);
566 *scanline0
= buffer
->_2d
.scanline0
;
567 *pitch
= buffer
->_2d
.pitch
;
570 LeaveCriticalSection(&buffer
->cs
);
575 static HRESULT WINAPI
memory_2d_buffer_IsContiguousFormat(IMF2DBuffer2
*iface
, BOOL
*is_contiguous
)
577 TRACE("%p, %p.\n", iface
, is_contiguous
);
582 *is_contiguous
= FALSE
;
587 static HRESULT WINAPI
memory_2d_buffer_GetContiguousLength(IMF2DBuffer2
*iface
, DWORD
*length
)
589 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
591 TRACE("%p, %p.\n", iface
, length
);
596 *length
= buffer
->_2d
.plane_size
;
601 static HRESULT WINAPI
memory_2d_buffer_ContiguousCopyTo(IMF2DBuffer2
*iface
, BYTE
*dest_buffer
, DWORD dest_length
)
603 FIXME("%p, %p, %lu.\n", iface
, dest_buffer
, dest_length
);
608 static HRESULT WINAPI
memory_2d_buffer_ContiguousCopyFrom(IMF2DBuffer2
*iface
, const BYTE
*src_buffer
, DWORD src_length
)
610 FIXME("%p, %p, %lu.\n", iface
, src_buffer
, src_length
);
615 static HRESULT WINAPI
memory_2d_buffer_Lock2DSize(IMF2DBuffer2
*iface
, MF2DBuffer_LockFlags flags
, BYTE
**scanline0
,
616 LONG
*pitch
, BYTE
**buffer_start
, DWORD
*buffer_length
)
618 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
621 TRACE("%p, %#x, %p, %p, %p, %p.\n", iface
, flags
, scanline0
, pitch
, buffer_start
, buffer_length
);
623 if (!scanline0
|| !pitch
|| !buffer_start
|| !buffer_length
)
626 EnterCriticalSection(&buffer
->cs
);
628 hr
= memory_2d_buffer_lock(buffer
, scanline0
, pitch
, buffer_start
, buffer_length
);
630 LeaveCriticalSection(&buffer
->cs
);
635 static HRESULT WINAPI
memory_2d_buffer_Copy2DTo(IMF2DBuffer2
*iface
, IMF2DBuffer2
*dest_buffer
)
637 FIXME("%p, %p.\n", iface
, dest_buffer
);
642 static const IMF2DBuffer2Vtbl memory_2d_buffer_vtbl
=
644 memory_2d_buffer_QueryInterface
,
645 memory_2d_buffer_AddRef
,
646 memory_2d_buffer_Release
,
647 memory_2d_buffer_Lock2D
,
648 memory_2d_buffer_Unlock2D
,
649 memory_2d_buffer_GetScanline0AndPitch
,
650 memory_2d_buffer_IsContiguousFormat
,
651 memory_2d_buffer_GetContiguousLength
,
652 memory_2d_buffer_ContiguousCopyTo
,
653 memory_2d_buffer_ContiguousCopyFrom
,
654 memory_2d_buffer_Lock2DSize
,
655 memory_2d_buffer_Copy2DTo
,
658 static HRESULT
d3d9_surface_buffer_lock(struct buffer
*buffer
, MF2DBuffer_LockFlags flags
, BYTE
**scanline0
,
659 LONG
*pitch
, BYTE
**buffer_start
, DWORD
*buffer_length
)
663 if (buffer
->_2d
.linear_buffer
)
664 hr
= MF_E_UNEXPECTED
;
665 else if (!buffer
->_2d
.locks
)
667 hr
= IDirect3DSurface9_LockRect(buffer
->d3d9_surface
.surface
, &buffer
->d3d9_surface
.rect
, NULL
, 0);
673 *scanline0
= buffer
->d3d9_surface
.rect
.pBits
;
674 *pitch
= buffer
->d3d9_surface
.rect
.Pitch
;
676 *buffer_start
= *scanline0
;
678 *buffer_length
= buffer
->d3d9_surface
.rect
.Pitch
* buffer
->_2d
.height
;
684 static HRESULT WINAPI
d3d9_surface_buffer_Lock2D(IMF2DBuffer2
*iface
, BYTE
**scanline0
, LONG
*pitch
)
686 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
689 TRACE("%p, %p, %p.\n", iface
, scanline0
, pitch
);
691 if (!scanline0
|| !pitch
)
694 EnterCriticalSection(&buffer
->cs
);
696 hr
= d3d9_surface_buffer_lock(buffer
, MF2DBuffer_LockFlags_ReadWrite
, scanline0
, pitch
, NULL
, NULL
);
698 LeaveCriticalSection(&buffer
->cs
);
703 static HRESULT WINAPI
d3d9_surface_buffer_Unlock2D(IMF2DBuffer2
*iface
)
705 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
708 TRACE("%p.\n", iface
);
710 EnterCriticalSection(&buffer
->cs
);
712 if (buffer
->_2d
.locks
)
714 if (!--buffer
->_2d
.locks
)
716 IDirect3DSurface9_UnlockRect(buffer
->d3d9_surface
.surface
);
717 memset(&buffer
->d3d9_surface
.rect
, 0, sizeof(buffer
->d3d9_surface
.rect
));
721 hr
= HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED
);
723 LeaveCriticalSection(&buffer
->cs
);
728 static HRESULT WINAPI
d3d9_surface_buffer_GetScanline0AndPitch(IMF2DBuffer2
*iface
, BYTE
**scanline0
, LONG
*pitch
)
730 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
733 TRACE("%p, %p, %p.\n", iface
, scanline0
, pitch
);
735 if (!scanline0
|| !pitch
)
738 EnterCriticalSection(&buffer
->cs
);
740 if (!buffer
->_2d
.locks
)
744 hr
= HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED
);
748 *scanline0
= buffer
->d3d9_surface
.rect
.pBits
;
749 *pitch
= buffer
->d3d9_surface
.rect
.Pitch
;
752 LeaveCriticalSection(&buffer
->cs
);
757 static HRESULT WINAPI
d3d9_surface_buffer_Lock2DSize(IMF2DBuffer2
*iface
, MF2DBuffer_LockFlags flags
, BYTE
**scanline0
,
758 LONG
*pitch
, BYTE
**buffer_start
, DWORD
*buffer_length
)
760 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
763 TRACE("%p, %#x, %p, %p, %p, %p.\n", iface
, flags
, scanline0
, pitch
, buffer_start
, buffer_length
);
765 if (!scanline0
|| !pitch
|| !buffer_start
|| !buffer_length
)
768 EnterCriticalSection(&buffer
->cs
);
770 hr
= d3d9_surface_buffer_lock(buffer
, flags
, scanline0
, pitch
, buffer_start
, buffer_length
);
772 LeaveCriticalSection(&buffer
->cs
);
777 static const IMF2DBuffer2Vtbl d3d9_surface_buffer_vtbl
=
779 memory_2d_buffer_QueryInterface
,
780 memory_2d_buffer_AddRef
,
781 memory_2d_buffer_Release
,
782 d3d9_surface_buffer_Lock2D
,
783 d3d9_surface_buffer_Unlock2D
,
784 d3d9_surface_buffer_GetScanline0AndPitch
,
785 memory_2d_buffer_IsContiguousFormat
,
786 memory_2d_buffer_GetContiguousLength
,
787 memory_2d_buffer_ContiguousCopyTo
,
788 memory_2d_buffer_ContiguousCopyFrom
,
789 d3d9_surface_buffer_Lock2DSize
,
790 memory_2d_buffer_Copy2DTo
,
793 static HRESULT WINAPI
memory_2d_buffer_gs_QueryInterface(IMFGetService
*iface
, REFIID riid
, void **obj
)
795 struct buffer
*buffer
= impl_from_IMFGetService(iface
);
796 return IMFMediaBuffer_QueryInterface(&buffer
->IMFMediaBuffer_iface
, riid
, obj
);
799 static ULONG WINAPI
memory_2d_buffer_gs_AddRef(IMFGetService
*iface
)
801 struct buffer
*buffer
= impl_from_IMFGetService(iface
);
802 return IMFMediaBuffer_AddRef(&buffer
->IMFMediaBuffer_iface
);
805 static ULONG WINAPI
memory_2d_buffer_gs_Release(IMFGetService
*iface
)
807 struct buffer
*buffer
= impl_from_IMFGetService(iface
);
808 return IMFMediaBuffer_Release(&buffer
->IMFMediaBuffer_iface
);
811 static HRESULT WINAPI
memory_2d_buffer_gs_GetService(IMFGetService
*iface
, REFGUID service
, REFIID riid
, void **obj
)
813 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(service
), debugstr_guid(riid
), obj
);
818 static const IMFGetServiceVtbl memory_2d_buffer_gs_vtbl
=
820 memory_2d_buffer_gs_QueryInterface
,
821 memory_2d_buffer_gs_AddRef
,
822 memory_2d_buffer_gs_Release
,
823 memory_2d_buffer_gs_GetService
,
826 static HRESULT WINAPI
d3d9_surface_buffer_gs_GetService(IMFGetService
*iface
, REFGUID service
, REFIID riid
, void **obj
)
828 struct buffer
*buffer
= impl_from_IMFGetService(iface
);
830 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(service
), debugstr_guid(riid
), obj
);
832 if (IsEqualGUID(service
, &MR_BUFFER_SERVICE
))
834 return IDirect3DSurface9_QueryInterface(buffer
->d3d9_surface
.surface
, riid
, obj
);
840 static const IMFGetServiceVtbl d3d9_surface_buffer_gs_vtbl
=
842 memory_2d_buffer_gs_QueryInterface
,
843 memory_2d_buffer_gs_AddRef
,
844 memory_2d_buffer_gs_Release
,
845 d3d9_surface_buffer_gs_GetService
,
848 static HRESULT WINAPI
dxgi_1d_2d_buffer_QueryInterface(IMFMediaBuffer
*iface
, REFIID riid
, void **out
)
850 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
852 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), out
);
854 if (IsEqualIID(riid
, &IID_IMFMediaBuffer
) ||
855 IsEqualIID(riid
, &IID_IUnknown
))
857 *out
= &buffer
->IMFMediaBuffer_iface
;
859 else if (IsEqualIID(riid
, &IID_IMF2DBuffer2
) ||
860 IsEqualIID(riid
, &IID_IMF2DBuffer
))
862 *out
= &buffer
->IMF2DBuffer2_iface
;
864 else if (IsEqualIID(riid
, &IID_IMFDXGIBuffer
))
866 *out
= &buffer
->IMFDXGIBuffer_iface
;
870 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
872 return E_NOINTERFACE
;
875 IUnknown_AddRef((IUnknown
*)*out
);
879 static HRESULT
dxgi_surface_buffer_create_readback_texture(struct buffer
*buffer
)
881 D3D11_TEXTURE2D_DESC texture_desc
;
882 ID3D11Device
*device
;
885 if (buffer
->dxgi_surface
.rb_texture
)
888 ID3D11Texture2D_GetDevice(buffer
->dxgi_surface
.texture
, &device
);
890 ID3D11Texture2D_GetDesc(buffer
->dxgi_surface
.texture
, &texture_desc
);
891 texture_desc
.Usage
= D3D11_USAGE_STAGING
;
892 texture_desc
.BindFlags
= 0;
893 texture_desc
.CPUAccessFlags
= D3D11_CPU_ACCESS_READ
| D3D11_CPU_ACCESS_WRITE
;
894 texture_desc
.MiscFlags
= 0;
895 texture_desc
.MipLevels
= 1;
896 if (FAILED(hr
= ID3D11Device_CreateTexture2D(device
, &texture_desc
, NULL
, &buffer
->dxgi_surface
.rb_texture
)))
897 WARN("Failed to create readback texture, hr %#lx.\n", hr
);
899 ID3D11Device_Release(device
);
904 static HRESULT
dxgi_surface_buffer_map(struct buffer
*buffer
)
906 ID3D11DeviceContext
*immediate_context
;
907 ID3D11Device
*device
;
910 if (FAILED(hr
= dxgi_surface_buffer_create_readback_texture(buffer
)))
913 ID3D11Texture2D_GetDevice(buffer
->dxgi_surface
.texture
, &device
);
914 ID3D11Device_GetImmediateContext(device
, &immediate_context
);
915 ID3D11DeviceContext_CopySubresourceRegion(immediate_context
, (ID3D11Resource
*)buffer
->dxgi_surface
.rb_texture
,
916 0, 0, 0, 0, (ID3D11Resource
*)buffer
->dxgi_surface
.texture
, buffer
->dxgi_surface
.sub_resource_idx
, NULL
);
918 memset(&buffer
->dxgi_surface
.map_desc
, 0, sizeof(buffer
->dxgi_surface
.map_desc
));
919 if (FAILED(hr
= ID3D11DeviceContext_Map(immediate_context
, (ID3D11Resource
*)buffer
->dxgi_surface
.rb_texture
,
920 0, D3D11_MAP_READ_WRITE
, 0, &buffer
->dxgi_surface
.map_desc
)))
922 WARN("Failed to map readback texture, hr %#lx.\n", hr
);
925 ID3D11DeviceContext_Release(immediate_context
);
926 ID3D11Device_Release(device
);
931 static void dxgi_surface_buffer_unmap(struct buffer
*buffer
)
933 ID3D11DeviceContext
*immediate_context
;
934 ID3D11Device
*device
;
936 ID3D11Texture2D_GetDevice(buffer
->dxgi_surface
.texture
, &device
);
937 ID3D11Device_GetImmediateContext(device
, &immediate_context
);
938 ID3D11DeviceContext_Unmap(immediate_context
, (ID3D11Resource
*)buffer
->dxgi_surface
.rb_texture
, 0);
939 memset(&buffer
->dxgi_surface
.map_desc
, 0, sizeof(buffer
->dxgi_surface
.map_desc
));
941 ID3D11DeviceContext_CopySubresourceRegion(immediate_context
, (ID3D11Resource
*)buffer
->dxgi_surface
.texture
,
942 buffer
->dxgi_surface
.sub_resource_idx
, 0, 0, 0, (ID3D11Resource
*)buffer
->dxgi_surface
.rb_texture
, 0, NULL
);
944 ID3D11DeviceContext_Release(immediate_context
);
945 ID3D11Device_Release(device
);
948 static HRESULT WINAPI
dxgi_surface_buffer_Lock(IMFMediaBuffer
*iface
, BYTE
**data
, DWORD
*max_length
,
949 DWORD
*current_length
)
951 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
954 TRACE("%p, %p, %p, %p.\n", iface
, data
, max_length
, current_length
);
959 EnterCriticalSection(&buffer
->cs
);
961 if (!buffer
->_2d
.linear_buffer
&& buffer
->_2d
.locks
)
962 hr
= MF_E_INVALIDREQUEST
;
963 else if (!buffer
->_2d
.linear_buffer
)
965 if (!(buffer
->_2d
.linear_buffer
= malloc(buffer
->_2d
.plane_size
)))
970 hr
= dxgi_surface_buffer_map(buffer
);
973 copy_image(buffer
, buffer
->_2d
.linear_buffer
, buffer
->_2d
.width
, buffer
->dxgi_surface
.map_desc
.pData
,
974 buffer
->dxgi_surface
.map_desc
.RowPitch
, buffer
->_2d
.width
, buffer
->_2d
.height
);
982 *data
= buffer
->_2d
.linear_buffer
;
984 *max_length
= buffer
->_2d
.plane_size
;
986 *current_length
= buffer
->_2d
.plane_size
;
989 LeaveCriticalSection(&buffer
->cs
);
994 static HRESULT WINAPI
dxgi_surface_buffer_Unlock(IMFMediaBuffer
*iface
)
996 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
999 TRACE("%p.\n", iface
);
1001 EnterCriticalSection(&buffer
->cs
);
1003 if (!buffer
->_2d
.linear_buffer
)
1004 hr
= HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED
);
1005 else if (!--buffer
->_2d
.locks
)
1007 copy_image(buffer
, buffer
->dxgi_surface
.map_desc
.pData
, buffer
->dxgi_surface
.map_desc
.RowPitch
,
1008 buffer
->_2d
.linear_buffer
, buffer
->_2d
.width
, buffer
->_2d
.width
, buffer
->_2d
.height
);
1009 dxgi_surface_buffer_unmap(buffer
);
1011 free(buffer
->_2d
.linear_buffer
);
1012 buffer
->_2d
.linear_buffer
= NULL
;
1015 LeaveCriticalSection(&buffer
->cs
);
1020 static HRESULT WINAPI
dxgi_surface_buffer_SetCurrentLength(IMFMediaBuffer
*iface
, DWORD current_length
)
1022 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
1024 TRACE("%p, %lu.\n", iface
, current_length
);
1026 buffer
->current_length
= current_length
;
1031 static HRESULT
dxgi_surface_buffer_lock(struct buffer
*buffer
, MF2DBuffer_LockFlags flags
,
1032 BYTE
**scanline0
, LONG
*pitch
, BYTE
**buffer_start
, DWORD
*buffer_length
)
1036 if (buffer
->_2d
.linear_buffer
)
1037 hr
= MF_E_UNEXPECTED
;
1038 else if (!buffer
->_2d
.locks
++)
1039 hr
= dxgi_surface_buffer_map(buffer
);
1043 *scanline0
= buffer
->dxgi_surface
.map_desc
.pData
;
1044 *pitch
= buffer
->dxgi_surface
.map_desc
.RowPitch
;
1046 *buffer_start
= *scanline0
;
1048 *buffer_length
= buffer
->dxgi_surface
.map_desc
.RowPitch
* buffer
->_2d
.height
;
1054 static HRESULT WINAPI
dxgi_surface_buffer_Lock2D(IMF2DBuffer2
*iface
, BYTE
**scanline0
, LONG
*pitch
)
1056 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
1059 TRACE("%p, %p, %p.\n", iface
, scanline0
, pitch
);
1061 if (!scanline0
|| !pitch
)
1064 EnterCriticalSection(&buffer
->cs
);
1066 hr
= dxgi_surface_buffer_lock(buffer
, MF2DBuffer_LockFlags_ReadWrite
, scanline0
, pitch
, NULL
, NULL
);
1068 LeaveCriticalSection(&buffer
->cs
);
1073 static HRESULT WINAPI
dxgi_surface_buffer_Unlock2D(IMF2DBuffer2
*iface
)
1075 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
1078 TRACE("%p.\n", iface
);
1080 EnterCriticalSection(&buffer
->cs
);
1082 if (buffer
->_2d
.locks
)
1084 if (!--buffer
->_2d
.locks
)
1085 dxgi_surface_buffer_unmap(buffer
);
1088 hr
= HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED
);
1090 LeaveCriticalSection(&buffer
->cs
);
1095 static HRESULT WINAPI
dxgi_surface_buffer_GetScanline0AndPitch(IMF2DBuffer2
*iface
, BYTE
**scanline0
, LONG
*pitch
)
1097 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
1100 TRACE("%p, %p, %p.\n", iface
, scanline0
, pitch
);
1102 if (!scanline0
|| !pitch
)
1105 EnterCriticalSection(&buffer
->cs
);
1107 if (!buffer
->_2d
.locks
)
1111 hr
= HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED
);
1115 *scanline0
= buffer
->dxgi_surface
.map_desc
.pData
;
1116 *pitch
= buffer
->dxgi_surface
.map_desc
.RowPitch
;
1119 LeaveCriticalSection(&buffer
->cs
);
1124 static HRESULT WINAPI
dxgi_surface_buffer_Lock2DSize(IMF2DBuffer2
*iface
, MF2DBuffer_LockFlags flags
,
1125 BYTE
**scanline0
, LONG
*pitch
, BYTE
**buffer_start
, DWORD
*buffer_length
)
1127 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
1130 TRACE("%p, %#x, %p, %p, %p, %p.\n", iface
, flags
, scanline0
, pitch
, buffer_start
, buffer_length
);
1132 if (!scanline0
|| !pitch
|| !buffer_start
|| !buffer_length
)
1135 EnterCriticalSection(&buffer
->cs
);
1137 hr
= dxgi_surface_buffer_lock(buffer
, flags
, scanline0
, pitch
, buffer_start
, buffer_length
);
1139 LeaveCriticalSection(&buffer
->cs
);
1144 static HRESULT WINAPI
dxgi_buffer_QueryInterface(IMFDXGIBuffer
*iface
, REFIID riid
, void **obj
)
1146 struct buffer
*buffer
= impl_from_IMFDXGIBuffer(iface
);
1147 return IMFMediaBuffer_QueryInterface(&buffer
->IMFMediaBuffer_iface
, riid
, obj
);
1150 static ULONG WINAPI
dxgi_buffer_AddRef(IMFDXGIBuffer
*iface
)
1152 struct buffer
*buffer
= impl_from_IMFDXGIBuffer(iface
);
1153 return IMFMediaBuffer_AddRef(&buffer
->IMFMediaBuffer_iface
);
1156 static ULONG WINAPI
dxgi_buffer_Release(IMFDXGIBuffer
*iface
)
1158 struct buffer
*buffer
= impl_from_IMFDXGIBuffer(iface
);
1159 return IMFMediaBuffer_Release(&buffer
->IMFMediaBuffer_iface
);
1162 static HRESULT WINAPI
dxgi_buffer_GetResource(IMFDXGIBuffer
*iface
, REFIID riid
, void **obj
)
1164 struct buffer
*buffer
= impl_from_IMFDXGIBuffer(iface
);
1166 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
1168 return ID3D11Texture2D_QueryInterface(buffer
->dxgi_surface
.texture
, riid
, obj
);
1171 static HRESULT WINAPI
dxgi_buffer_GetSubresourceIndex(IMFDXGIBuffer
*iface
, UINT
*index
)
1173 struct buffer
*buffer
= impl_from_IMFDXGIBuffer(iface
);
1175 TRACE("%p, %p.\n", iface
, index
);
1180 *index
= buffer
->dxgi_surface
.sub_resource_idx
;
1185 static HRESULT WINAPI
dxgi_buffer_GetUnknown(IMFDXGIBuffer
*iface
, REFIID guid
, REFIID riid
, void **object
)
1187 struct buffer
*buffer
= impl_from_IMFDXGIBuffer(iface
);
1189 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(guid
), debugstr_guid(riid
), object
);
1191 if (attributes_GetUnknown(&buffer
->dxgi_surface
.attributes
, guid
, riid
, object
) == MF_E_ATTRIBUTENOTFOUND
)
1192 return MF_E_NOT_FOUND
;
1197 static HRESULT WINAPI
dxgi_buffer_SetUnknown(IMFDXGIBuffer
*iface
, REFIID guid
, IUnknown
*data
)
1199 struct buffer
*buffer
= impl_from_IMFDXGIBuffer(iface
);
1202 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(guid
), data
);
1204 EnterCriticalSection(&buffer
->dxgi_surface
.attributes
.cs
);
1207 if (SUCCEEDED(attributes_GetItem(&buffer
->dxgi_surface
.attributes
, guid
, NULL
)))
1208 hr
= HRESULT_FROM_WIN32(ERROR_OBJECT_ALREADY_EXISTS
);
1210 hr
= attributes_SetUnknown(&buffer
->dxgi_surface
.attributes
, guid
, data
);
1214 attributes_DeleteItem(&buffer
->dxgi_surface
.attributes
, guid
);
1216 LeaveCriticalSection(&buffer
->dxgi_surface
.attributes
.cs
);
1221 static const IMFMediaBufferVtbl dxgi_surface_1d_buffer_vtbl
=
1223 dxgi_1d_2d_buffer_QueryInterface
,
1224 memory_buffer_AddRef
,
1225 memory_buffer_Release
,
1226 dxgi_surface_buffer_Lock
,
1227 dxgi_surface_buffer_Unlock
,
1228 memory_buffer_GetCurrentLength
,
1229 dxgi_surface_buffer_SetCurrentLength
,
1230 memory_buffer_GetMaxLength
,
1233 static const IMF2DBuffer2Vtbl dxgi_surface_buffer_vtbl
=
1235 memory_2d_buffer_QueryInterface
,
1236 memory_2d_buffer_AddRef
,
1237 memory_2d_buffer_Release
,
1238 dxgi_surface_buffer_Lock2D
,
1239 dxgi_surface_buffer_Unlock2D
,
1240 dxgi_surface_buffer_GetScanline0AndPitch
,
1241 memory_2d_buffer_IsContiguousFormat
,
1242 memory_2d_buffer_GetContiguousLength
,
1243 memory_2d_buffer_ContiguousCopyTo
,
1244 memory_2d_buffer_ContiguousCopyFrom
,
1245 dxgi_surface_buffer_Lock2DSize
,
1246 memory_2d_buffer_Copy2DTo
,
1249 static const IMFDXGIBufferVtbl dxgi_buffer_vtbl
=
1251 dxgi_buffer_QueryInterface
,
1253 dxgi_buffer_Release
,
1254 dxgi_buffer_GetResource
,
1255 dxgi_buffer_GetSubresourceIndex
,
1256 dxgi_buffer_GetUnknown
,
1257 dxgi_buffer_SetUnknown
,
1260 static HRESULT
memory_buffer_init(struct buffer
*buffer
, DWORD max_length
, DWORD alignment
,
1261 const IMFMediaBufferVtbl
*vtbl
)
1263 if (alignment
< MF_16_BYTE_ALIGNMENT
)
1264 alignment
= MF_16_BYTE_ALIGNMENT
;
1267 if (alignment
& (alignment
- 1))
1270 alignment
|= alignment
>> 1;
1271 alignment
|= alignment
>> 2;
1272 alignment
|= alignment
>> 4;
1273 alignment
|= alignment
>> 8;
1274 alignment
|= alignment
>> 16;
1278 if (!(buffer
->data
= _aligned_malloc(max_length
, alignment
)))
1279 return E_OUTOFMEMORY
;
1280 memset(buffer
->data
, 0, max_length
);
1282 buffer
->IMFMediaBuffer_iface
.lpVtbl
= vtbl
;
1283 buffer
->refcount
= 1;
1284 buffer
->max_length
= max_length
;
1285 buffer
->current_length
= 0;
1286 InitializeCriticalSection(&buffer
->cs
);
1291 static HRESULT
create_1d_buffer(DWORD max_length
, DWORD alignment
, IMFMediaBuffer
**buffer
)
1293 struct buffer
*object
;
1301 if (!(object
= calloc(1, sizeof(*object
))))
1302 return E_OUTOFMEMORY
;
1304 hr
= memory_buffer_init(object
, max_length
, alignment
, &memory_1d_buffer_vtbl
);
1311 *buffer
= &object
->IMFMediaBuffer_iface
;
1316 static p_copy_image_func
get_2d_buffer_copy_func(DWORD fourcc
)
1318 if (fourcc
== MAKEFOURCC('N','V','1','2'))
1319 return copy_image_nv12
;
1320 if (fourcc
== MAKEFOURCC('I','M','C','1') || fourcc
== MAKEFOURCC('I','M','C','3'))
1321 return copy_image_imc1
;
1322 if (fourcc
== MAKEFOURCC('I','M','C','2') || fourcc
== MAKEFOURCC('I','M','C','4'))
1323 return copy_image_imc2
;
1327 static HRESULT
create_2d_buffer(DWORD width
, DWORD height
, DWORD fourcc
, BOOL bottom_up
, IMFMediaBuffer
**buffer
)
1329 unsigned int stride
, max_length
;
1330 unsigned int row_alignment
;
1331 struct buffer
*object
;
1343 memcpy(&subtype
, &MFVideoFormat_Base
, sizeof(subtype
));
1344 subtype
.Data1
= fourcc
;
1346 if (!(stride
= mf_format_get_stride(&subtype
, width
, &is_yuv
)))
1347 return MF_E_INVALIDMEDIATYPE
;
1349 if (is_yuv
&& bottom_up
)
1350 return MF_E_INVALIDMEDIATYPE
;
1354 case MAKEFOURCC('I','M','C','1'):
1355 case MAKEFOURCC('I','M','C','3'):
1356 plane_size
= stride
* height
* 2;
1358 case MAKEFOURCC('I','M','C','2'):
1359 case MAKEFOURCC('I','M','C','4'):
1360 plane_size
= stride
* 3 / 2 * height
;
1362 case MAKEFOURCC('N','V','1','2'):
1363 case MAKEFOURCC('Y','V','1','2'):
1364 case MAKEFOURCC('I','4','2','0'):
1365 case MAKEFOURCC('I','Y','U','V'):
1366 plane_size
= stride
* height
* 3 / 2;
1369 plane_size
= stride
* height
;
1372 if (!(object
= calloc(1, sizeof(*object
))))
1373 return E_OUTOFMEMORY
;
1377 case MAKEFOURCC('I','M','C','1'):
1378 case MAKEFOURCC('I','M','C','2'):
1379 case MAKEFOURCC('I','M','C','3'):
1380 case MAKEFOURCC('I','M','C','4'):
1381 case MAKEFOURCC('Y','V','1','2'):
1382 row_alignment
= MF_128_BYTE_ALIGNMENT
;
1385 row_alignment
= MF_64_BYTE_ALIGNMENT
;
1388 pitch
= ALIGN_SIZE(stride
, row_alignment
);
1392 case MAKEFOURCC('I','M','C','1'):
1393 case MAKEFOURCC('I','M','C','3'):
1394 max_length
= pitch
* height
* 2;
1396 case MAKEFOURCC('N','V','1','2'):
1397 case MAKEFOURCC('Y','V','1','2'):
1398 case MAKEFOURCC('I','M','C','2'):
1399 case MAKEFOURCC('I','M','C','4'):
1400 max_length
= pitch
* height
* 3 / 2;
1403 max_length
= pitch
* height
;
1406 if (FAILED(hr
= memory_buffer_init(object
, max_length
, row_alignment
, &memory_1d_2d_buffer_vtbl
)))
1412 object
->IMF2DBuffer2_iface
.lpVtbl
= &memory_2d_buffer_vtbl
;
1413 object
->IMFGetService_iface
.lpVtbl
= &memory_2d_buffer_gs_vtbl
;
1414 object
->_2d
.plane_size
= plane_size
;
1415 object
->_2d
.width
= stride
;
1416 object
->_2d
.height
= height
;
1417 object
->_2d
.pitch
= bottom_up
? -pitch
: pitch
;
1418 object
->_2d
.scanline0
= bottom_up
? object
->data
+ pitch
* (object
->_2d
.height
- 1) : object
->data
;
1419 object
->_2d
.copy_image
= get_2d_buffer_copy_func(fourcc
);
1421 *buffer
= &object
->IMFMediaBuffer_iface
;
1426 static HRESULT
create_d3d9_surface_buffer(IUnknown
*surface
, BOOL bottom_up
, IMFMediaBuffer
**buffer
)
1428 struct buffer
*object
;
1429 D3DSURFACE_DESC desc
;
1430 unsigned int stride
;
1434 IDirect3DSurface9_GetDesc((IDirect3DSurface9
*)surface
, &desc
);
1435 TRACE("format %#x, %u x %u.\n", desc
.Format
, desc
.Width
, desc
.Height
);
1437 memcpy(&subtype
, &MFVideoFormat_Base
, sizeof(subtype
));
1438 subtype
.Data1
= desc
.Format
;
1440 if (!(stride
= mf_format_get_stride(&subtype
, desc
.Width
, &is_yuv
)))
1441 return MF_E_INVALIDMEDIATYPE
;
1443 if (!(object
= calloc(1, sizeof(*object
))))
1444 return E_OUTOFMEMORY
;
1446 object
->IMFMediaBuffer_iface
.lpVtbl
= &d3d9_surface_1d_buffer_vtbl
;
1447 object
->IMF2DBuffer2_iface
.lpVtbl
= &d3d9_surface_buffer_vtbl
;
1448 object
->IMFGetService_iface
.lpVtbl
= &d3d9_surface_buffer_gs_vtbl
;
1449 object
->refcount
= 1;
1450 InitializeCriticalSection(&object
->cs
);
1451 object
->d3d9_surface
.surface
= (IDirect3DSurface9
*)surface
;
1452 IUnknown_AddRef(surface
);
1454 MFGetPlaneSize(desc
.Format
, desc
.Width
, desc
.Height
, &object
->_2d
.plane_size
);
1455 object
->_2d
.width
= stride
;
1456 object
->_2d
.height
= desc
.Height
;
1457 object
->max_length
= object
->_2d
.plane_size
;
1458 object
->_2d
.copy_image
= get_2d_buffer_copy_func(desc
.Format
);
1460 *buffer
= &object
->IMFMediaBuffer_iface
;
1465 static HRESULT
create_dxgi_surface_buffer(IUnknown
*surface
, unsigned int sub_resource_idx
,
1466 BOOL bottom_up
, IMFMediaBuffer
**buffer
)
1468 struct buffer
*object
;
1469 D3D11_TEXTURE2D_DESC desc
;
1470 ID3D11Texture2D
*texture
;
1471 unsigned int stride
;
1477 if (FAILED(hr
= IUnknown_QueryInterface(surface
, &IID_ID3D11Texture2D
, (void **)&texture
)))
1479 WARN("Failed to get texture interface, hr %#lx.\n", hr
);
1483 ID3D11Texture2D_GetDesc(texture
, &desc
);
1484 TRACE("format %#x, %u x %u.\n", desc
.Format
, desc
.Width
, desc
.Height
);
1486 memcpy(&subtype
, &MFVideoFormat_Base
, sizeof(subtype
));
1487 subtype
.Data1
= format
= MFMapDXGIFormatToDX9Format(desc
.Format
);
1489 if (!(stride
= mf_format_get_stride(&subtype
, desc
.Width
, &is_yuv
)))
1491 ID3D11Texture2D_Release(texture
);
1492 return MF_E_INVALIDMEDIATYPE
;
1495 if (!(object
= calloc(1, sizeof(*object
))))
1497 ID3D11Texture2D_Release(texture
);
1498 return E_OUTOFMEMORY
;
1501 object
->IMFMediaBuffer_iface
.lpVtbl
= &dxgi_surface_1d_buffer_vtbl
;
1502 object
->IMF2DBuffer2_iface
.lpVtbl
= &dxgi_surface_buffer_vtbl
;
1503 object
->IMFDXGIBuffer_iface
.lpVtbl
= &dxgi_buffer_vtbl
;
1504 object
->refcount
= 1;
1505 InitializeCriticalSection(&object
->cs
);
1506 object
->dxgi_surface
.texture
= texture
;
1507 object
->dxgi_surface
.sub_resource_idx
= sub_resource_idx
;
1509 MFGetPlaneSize(format
, desc
.Width
, desc
.Height
, &object
->_2d
.plane_size
);
1510 object
->_2d
.width
= stride
;
1511 object
->_2d
.height
= desc
.Height
;
1512 object
->max_length
= object
->_2d
.plane_size
;
1513 object
->_2d
.copy_image
= get_2d_buffer_copy_func(format
);
1515 if (FAILED(hr
= init_attributes_object(&object
->dxgi_surface
.attributes
, 0)))
1517 IMFMediaBuffer_Release(&object
->IMFMediaBuffer_iface
);
1521 *buffer
= &object
->IMFMediaBuffer_iface
;
1526 /***********************************************************************
1527 * MFCreateMemoryBuffer (mfplat.@)
1529 HRESULT WINAPI
MFCreateMemoryBuffer(DWORD max_length
, IMFMediaBuffer
**buffer
)
1531 TRACE("%lu, %p.\n", max_length
, buffer
);
1533 return create_1d_buffer(max_length
, MF_1_BYTE_ALIGNMENT
, buffer
);
1536 /***********************************************************************
1537 * MFCreateAlignedMemoryBuffer (mfplat.@)
1539 HRESULT WINAPI
MFCreateAlignedMemoryBuffer(DWORD max_length
, DWORD alignment
, IMFMediaBuffer
**buffer
)
1541 TRACE("%lu, %lu, %p.\n", max_length
, alignment
, buffer
);
1543 return create_1d_buffer(max_length
, alignment
, buffer
);
1546 /***********************************************************************
1547 * MFCreate2DMediaBuffer (mfplat.@)
1549 HRESULT WINAPI
MFCreate2DMediaBuffer(DWORD width
, DWORD height
, DWORD fourcc
, BOOL bottom_up
, IMFMediaBuffer
**buffer
)
1551 TRACE("%lu, %lu, %s, %d, %p.\n", width
, height
, debugstr_fourcc(fourcc
), bottom_up
, buffer
);
1553 return create_2d_buffer(width
, height
, fourcc
, bottom_up
, buffer
);
1556 /***********************************************************************
1557 * MFCreateDXSurfaceBuffer (mfplat.@)
1559 HRESULT WINAPI
MFCreateDXSurfaceBuffer(REFIID riid
, IUnknown
*surface
, BOOL bottom_up
, IMFMediaBuffer
**buffer
)
1561 TRACE("%s, %p, %d, %p.\n", debugstr_guid(riid
), surface
, bottom_up
, buffer
);
1563 if (!IsEqualIID(riid
, &IID_IDirect3DSurface9
))
1564 return E_INVALIDARG
;
1566 return create_d3d9_surface_buffer(surface
, bottom_up
, buffer
);
1569 /***********************************************************************
1570 * MFCreateDXGISurfaceBuffer (mfplat.@)
1572 HRESULT WINAPI
MFCreateDXGISurfaceBuffer(REFIID riid
, IUnknown
*surface
, UINT subresource
, BOOL bottom_up
,
1573 IMFMediaBuffer
**buffer
)
1575 TRACE("%s, %p, %u, %d, %p.\n", debugstr_guid(riid
), surface
, subresource
, bottom_up
, buffer
);
1577 if (!IsEqualIID(riid
, &IID_ID3D11Texture2D
))
1578 return E_INVALIDARG
;
1580 return create_dxgi_surface_buffer(surface
, subresource
, bottom_up
, buffer
);
1583 static unsigned int buffer_get_aligned_length(unsigned int length
, unsigned int alignment
)
1585 length
= (length
+ alignment
) / alignment
;
1586 length
*= alignment
;
1591 HRESULT WINAPI
MFCreateMediaBufferFromMediaType(IMFMediaType
*media_type
, LONGLONG duration
, DWORD min_length
,
1592 DWORD alignment
, IMFMediaBuffer
**buffer
)
1594 UINT32 length
= 0, block_alignment
;
1595 LONGLONG avg_length
;
1599 TRACE("%p, %s, %lu, %lu, %p.\n", media_type
, debugstr_time(duration
), min_length
, alignment
, buffer
);
1602 return E_INVALIDARG
;
1604 if (FAILED(hr
= IMFMediaType_GetMajorType(media_type
, &major
)))
1607 if (IsEqualGUID(&major
, &MFMediaType_Audio
))
1609 block_alignment
= 0;
1610 if (FAILED(IMFMediaType_GetUINT32(media_type
, &MF_MT_AUDIO_BLOCK_ALIGNMENT
, &block_alignment
)))
1611 WARN("Block alignment was not specified.\n");
1613 alignment
= max(16, alignment
);
1615 if (block_alignment
)
1622 if (SUCCEEDED(IMFMediaType_GetUINT32(media_type
, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND
, &length
)))
1625 avg_length
= length
* duration
/ (10 * 1000 * 1000);
1629 length
= buffer_get_aligned_length(avg_length
+ 1, alignment
);
1630 length
= buffer_get_aligned_length(length
, block_alignment
);
1635 length
= max(length
, min_length
);
1637 return create_1d_buffer(length
, alignment
- 1, buffer
);
1640 FIXME("Major type %s is not supported.\n", debugstr_guid(&major
));