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)))
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
;
52 unsigned int plane_size
;
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
, src
, src_stride
, width
/ 2, lines
/ 2);
104 MFCopyImage(dest
+ dest_stride
/ 2, dest_stride
, src
+ src_stride
/ 2, src_stride
, width
/ 2, lines
/ 2);
107 static inline struct buffer
*impl_from_IMFMediaBuffer(IMFMediaBuffer
*iface
)
109 return CONTAINING_RECORD(iface
, struct buffer
, IMFMediaBuffer_iface
);
112 static struct buffer
*impl_from_IMF2DBuffer2(IMF2DBuffer2
*iface
)
114 return CONTAINING_RECORD(iface
, struct buffer
, IMF2DBuffer2_iface
);
117 static struct buffer
*impl_from_IMFGetService(IMFGetService
*iface
)
119 return CONTAINING_RECORD(iface
, struct buffer
, IMFGetService_iface
);
122 static struct buffer
*impl_from_IMFDXGIBuffer(IMFDXGIBuffer
*iface
)
124 return CONTAINING_RECORD(iface
, struct buffer
, IMFDXGIBuffer_iface
);
127 static HRESULT WINAPI
memory_buffer_QueryInterface(IMFMediaBuffer
*iface
, REFIID riid
, void **out
)
129 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
131 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), out
);
133 if (IsEqualIID(riid
, &IID_IMFMediaBuffer
) ||
134 IsEqualIID(riid
, &IID_IUnknown
))
136 *out
= &buffer
->IMFMediaBuffer_iface
;
137 IMFMediaBuffer_AddRef(iface
);
141 WARN("Unsupported %s.\n", debugstr_guid(riid
));
143 return E_NOINTERFACE
;
146 static ULONG WINAPI
memory_buffer_AddRef(IMFMediaBuffer
*iface
)
148 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
149 ULONG refcount
= InterlockedIncrement(&buffer
->refcount
);
151 TRACE("%p, refcount %u.\n", buffer
, refcount
);
156 static ULONG WINAPI
memory_buffer_Release(IMFMediaBuffer
*iface
)
158 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
159 ULONG refcount
= InterlockedDecrement(&buffer
->refcount
);
161 TRACE("%p, refcount %u.\n", iface
, refcount
);
165 if (buffer
->d3d9_surface
.surface
)
166 IDirect3DSurface9_Release(buffer
->d3d9_surface
.surface
);
167 if (buffer
->dxgi_surface
.texture
)
169 ID3D11Texture2D_Release(buffer
->dxgi_surface
.texture
);
170 if (buffer
->dxgi_surface
.rb_texture
)
171 ID3D11Texture2D_Release(buffer
->dxgi_surface
.rb_texture
);
172 clear_attributes_object(&buffer
->dxgi_surface
.attributes
);
174 DeleteCriticalSection(&buffer
->cs
);
175 free(buffer
->_2d
.linear_buffer
);
183 static HRESULT WINAPI
memory_buffer_Lock(IMFMediaBuffer
*iface
, BYTE
**data
, DWORD
*max_length
, DWORD
*current_length
)
185 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
187 TRACE("%p, %p %p, %p.\n", iface
, data
, max_length
, current_length
);
192 *data
= buffer
->data
;
194 *max_length
= buffer
->max_length
;
196 *current_length
= buffer
->current_length
;
201 static HRESULT WINAPI
memory_buffer_Unlock(IMFMediaBuffer
*iface
)
203 TRACE("%p.\n", iface
);
208 static HRESULT WINAPI
memory_buffer_GetCurrentLength(IMFMediaBuffer
*iface
, DWORD
*current_length
)
210 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
212 TRACE("%p.\n", iface
);
217 *current_length
= buffer
->current_length
;
222 static HRESULT WINAPI
memory_buffer_SetCurrentLength(IMFMediaBuffer
*iface
, DWORD current_length
)
224 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
226 TRACE("%p, %u.\n", iface
, current_length
);
228 if (current_length
> buffer
->max_length
)
231 buffer
->current_length
= current_length
;
236 static HRESULT WINAPI
memory_buffer_GetMaxLength(IMFMediaBuffer
*iface
, DWORD
*max_length
)
238 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
240 TRACE("%p, %p.\n", iface
, max_length
);
245 *max_length
= buffer
->max_length
;
250 static const IMFMediaBufferVtbl memory_1d_buffer_vtbl
=
252 memory_buffer_QueryInterface
,
253 memory_buffer_AddRef
,
254 memory_buffer_Release
,
256 memory_buffer_Unlock
,
257 memory_buffer_GetCurrentLength
,
258 memory_buffer_SetCurrentLength
,
259 memory_buffer_GetMaxLength
,
262 static HRESULT WINAPI
memory_1d_2d_buffer_QueryInterface(IMFMediaBuffer
*iface
, REFIID riid
, void **out
)
264 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
266 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), out
);
268 if (IsEqualIID(riid
, &IID_IMFMediaBuffer
) ||
269 IsEqualIID(riid
, &IID_IUnknown
))
271 *out
= &buffer
->IMFMediaBuffer_iface
;
273 else if (IsEqualIID(riid
, &IID_IMF2DBuffer2
) ||
274 IsEqualIID(riid
, &IID_IMF2DBuffer
))
276 *out
= &buffer
->IMF2DBuffer2_iface
;
278 else if (IsEqualIID(riid
, &IID_IMFGetService
))
280 *out
= &buffer
->IMFGetService_iface
;
284 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
286 return E_NOINTERFACE
;
289 IUnknown_AddRef((IUnknown
*)*out
);
293 static HRESULT WINAPI
memory_1d_2d_buffer_Lock(IMFMediaBuffer
*iface
, BYTE
**data
, DWORD
*max_length
, DWORD
*current_length
)
295 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
298 TRACE("%p, %p, %p, %p.\n", iface
, data
, max_length
, current_length
);
303 /* Allocate linear buffer and return it as a copy of current content. Maximum and current length are
304 unrelated to 2D buffer maximum allocate length, or maintained current length. */
306 EnterCriticalSection(&buffer
->cs
);
308 if (!buffer
->_2d
.linear_buffer
&& buffer
->_2d
.locks
)
309 hr
= MF_E_INVALIDREQUEST
;
310 else if (!buffer
->_2d
.linear_buffer
)
312 if (!(buffer
->_2d
.linear_buffer
= malloc(ALIGN_SIZE(buffer
->_2d
.plane_size
, MF_64_BYTE_ALIGNMENT
))))
319 *data
= buffer
->_2d
.linear_buffer
;
321 *max_length
= buffer
->_2d
.plane_size
;
323 *current_length
= buffer
->_2d
.plane_size
;
326 LeaveCriticalSection(&buffer
->cs
);
331 static HRESULT WINAPI
memory_1d_2d_buffer_Unlock(IMFMediaBuffer
*iface
)
333 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
335 TRACE("%p.\n", iface
);
337 EnterCriticalSection(&buffer
->cs
);
339 if (buffer
->_2d
.linear_buffer
&& !--buffer
->_2d
.locks
)
341 copy_image(buffer
, buffer
->data
, buffer
->_2d
.pitch
, buffer
->_2d
.linear_buffer
, buffer
->_2d
.width
,
342 buffer
->_2d
.width
, buffer
->_2d
.height
);
344 free(buffer
->_2d
.linear_buffer
);
345 buffer
->_2d
.linear_buffer
= NULL
;
348 LeaveCriticalSection(&buffer
->cs
);
353 static const IMFMediaBufferVtbl memory_1d_2d_buffer_vtbl
=
355 memory_1d_2d_buffer_QueryInterface
,
356 memory_buffer_AddRef
,
357 memory_buffer_Release
,
358 memory_1d_2d_buffer_Lock
,
359 memory_1d_2d_buffer_Unlock
,
360 memory_buffer_GetCurrentLength
,
361 memory_buffer_SetCurrentLength
,
362 memory_buffer_GetMaxLength
,
365 static HRESULT WINAPI
d3d9_surface_buffer_Lock(IMFMediaBuffer
*iface
, BYTE
**data
, DWORD
*max_length
, DWORD
*current_length
)
367 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
370 TRACE("%p, %p, %p, %p.\n", iface
, data
, max_length
, current_length
);
375 EnterCriticalSection(&buffer
->cs
);
377 if (!buffer
->_2d
.linear_buffer
&& buffer
->_2d
.locks
)
378 hr
= MF_E_INVALIDREQUEST
;
379 else if (!buffer
->_2d
.linear_buffer
)
383 if (!(buffer
->_2d
.linear_buffer
= malloc(ALIGN_SIZE(buffer
->_2d
.plane_size
, MF_64_BYTE_ALIGNMENT
))))
388 hr
= IDirect3DSurface9_LockRect(buffer
->d3d9_surface
.surface
, &rect
, NULL
, 0);
391 copy_image(buffer
, buffer
->_2d
.linear_buffer
, buffer
->_2d
.width
, rect
.pBits
, rect
.Pitch
,
392 buffer
->_2d
.width
, buffer
->_2d
.height
);
393 IDirect3DSurface9_UnlockRect(buffer
->d3d9_surface
.surface
);
401 *data
= buffer
->_2d
.linear_buffer
;
403 *max_length
= buffer
->_2d
.plane_size
;
405 *current_length
= buffer
->_2d
.plane_size
;
408 LeaveCriticalSection(&buffer
->cs
);
413 static HRESULT WINAPI
d3d9_surface_buffer_Unlock(IMFMediaBuffer
*iface
)
415 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
418 TRACE("%p.\n", iface
);
420 EnterCriticalSection(&buffer
->cs
);
422 if (!buffer
->_2d
.linear_buffer
)
423 hr
= HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED
);
424 else if (!--buffer
->_2d
.locks
)
428 if (SUCCEEDED(hr
= IDirect3DSurface9_LockRect(buffer
->d3d9_surface
.surface
, &rect
, NULL
, 0)))
430 copy_image(buffer
, rect
.pBits
, rect
.Pitch
, buffer
->_2d
.linear_buffer
, buffer
->_2d
.width
,
431 buffer
->_2d
.width
, buffer
->_2d
.height
);
432 IDirect3DSurface9_UnlockRect(buffer
->d3d9_surface
.surface
);
435 free(buffer
->_2d
.linear_buffer
);
436 buffer
->_2d
.linear_buffer
= NULL
;
439 LeaveCriticalSection(&buffer
->cs
);
444 static HRESULT WINAPI
d3d9_surface_buffer_SetCurrentLength(IMFMediaBuffer
*iface
, DWORD current_length
)
446 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
448 TRACE("%p, %u.\n", iface
, current_length
);
450 buffer
->current_length
= current_length
;
455 static const IMFMediaBufferVtbl d3d9_surface_1d_buffer_vtbl
=
457 memory_1d_2d_buffer_QueryInterface
,
458 memory_buffer_AddRef
,
459 memory_buffer_Release
,
460 d3d9_surface_buffer_Lock
,
461 d3d9_surface_buffer_Unlock
,
462 memory_buffer_GetCurrentLength
,
463 d3d9_surface_buffer_SetCurrentLength
,
464 memory_buffer_GetMaxLength
,
467 static HRESULT WINAPI
memory_2d_buffer_QueryInterface(IMF2DBuffer2
*iface
, REFIID riid
, void **obj
)
469 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
470 return IMFMediaBuffer_QueryInterface(&buffer
->IMFMediaBuffer_iface
, riid
, obj
);
473 static ULONG WINAPI
memory_2d_buffer_AddRef(IMF2DBuffer2
*iface
)
475 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
476 return IMFMediaBuffer_AddRef(&buffer
->IMFMediaBuffer_iface
);
479 static ULONG WINAPI
memory_2d_buffer_Release(IMF2DBuffer2
*iface
)
481 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
482 return IMFMediaBuffer_Release(&buffer
->IMFMediaBuffer_iface
);
485 static HRESULT
memory_2d_buffer_lock(struct buffer
*buffer
, BYTE
**scanline0
, LONG
*pitch
,
486 BYTE
**buffer_start
, DWORD
*buffer_length
)
490 if (buffer
->_2d
.linear_buffer
)
491 hr
= MF_E_UNEXPECTED
;
495 *scanline0
= buffer
->_2d
.scanline0
;
496 *pitch
= buffer
->_2d
.pitch
;
498 *buffer_start
= buffer
->data
;
500 *buffer_length
= buffer
->max_length
;
506 static HRESULT WINAPI
memory_2d_buffer_Lock2D(IMF2DBuffer2
*iface
, BYTE
**scanline0
, LONG
*pitch
)
508 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
511 TRACE("%p, %p, %p.\n", iface
, scanline0
, pitch
);
513 if (!scanline0
|| !pitch
)
516 EnterCriticalSection(&buffer
->cs
);
518 hr
= memory_2d_buffer_lock(buffer
, scanline0
, pitch
, NULL
, NULL
);
520 LeaveCriticalSection(&buffer
->cs
);
525 static HRESULT WINAPI
memory_2d_buffer_Unlock2D(IMF2DBuffer2
*iface
)
527 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
530 TRACE("%p.\n", iface
);
532 EnterCriticalSection(&buffer
->cs
);
534 if (!buffer
->_2d
.linear_buffer
)
536 if (buffer
->_2d
.locks
)
539 hr
= HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED
);
542 LeaveCriticalSection(&buffer
->cs
);
547 static HRESULT WINAPI
memory_2d_buffer_GetScanline0AndPitch(IMF2DBuffer2
*iface
, BYTE
**scanline0
, LONG
*pitch
)
549 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
552 TRACE("%p, %p, %p.\n", iface
, scanline0
, pitch
);
554 if (!scanline0
|| !pitch
)
557 EnterCriticalSection(&buffer
->cs
);
559 if (buffer
->_2d
.linear_buffer
|| !buffer
->_2d
.locks
)
560 hr
= HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED
);
563 *scanline0
= buffer
->_2d
.scanline0
;
564 *pitch
= buffer
->_2d
.pitch
;
567 LeaveCriticalSection(&buffer
->cs
);
572 static HRESULT WINAPI
memory_2d_buffer_IsContiguousFormat(IMF2DBuffer2
*iface
, BOOL
*is_contiguous
)
574 TRACE("%p, %p.\n", iface
, is_contiguous
);
579 *is_contiguous
= FALSE
;
584 static HRESULT WINAPI
memory_2d_buffer_GetContiguousLength(IMF2DBuffer2
*iface
, DWORD
*length
)
586 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
588 TRACE("%p, %p.\n", iface
, length
);
593 *length
= buffer
->_2d
.plane_size
;
598 static HRESULT WINAPI
memory_2d_buffer_ContiguousCopyTo(IMF2DBuffer2
*iface
, BYTE
*dest_buffer
, DWORD dest_length
)
600 FIXME("%p, %p, %u.\n", iface
, dest_buffer
, dest_length
);
605 static HRESULT WINAPI
memory_2d_buffer_ContiguousCopyFrom(IMF2DBuffer2
*iface
, const BYTE
*src_buffer
, DWORD src_length
)
607 FIXME("%p, %p, %u.\n", iface
, src_buffer
, src_length
);
612 static HRESULT WINAPI
memory_2d_buffer_Lock2DSize(IMF2DBuffer2
*iface
, MF2DBuffer_LockFlags flags
, BYTE
**scanline0
,
613 LONG
*pitch
, BYTE
**buffer_start
, DWORD
*buffer_length
)
615 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
618 TRACE("%p, %#x, %p, %p, %p, %p.\n", iface
, flags
, scanline0
, pitch
, buffer_start
, buffer_length
);
620 if (!scanline0
|| !pitch
|| !buffer_start
|| !buffer_length
)
623 EnterCriticalSection(&buffer
->cs
);
625 hr
= memory_2d_buffer_lock(buffer
, scanline0
, pitch
, buffer_start
, buffer_length
);
627 LeaveCriticalSection(&buffer
->cs
);
632 static HRESULT WINAPI
memory_2d_buffer_Copy2DTo(IMF2DBuffer2
*iface
, IMF2DBuffer2
*dest_buffer
)
634 FIXME("%p, %p.\n", iface
, dest_buffer
);
639 static const IMF2DBuffer2Vtbl memory_2d_buffer_vtbl
=
641 memory_2d_buffer_QueryInterface
,
642 memory_2d_buffer_AddRef
,
643 memory_2d_buffer_Release
,
644 memory_2d_buffer_Lock2D
,
645 memory_2d_buffer_Unlock2D
,
646 memory_2d_buffer_GetScanline0AndPitch
,
647 memory_2d_buffer_IsContiguousFormat
,
648 memory_2d_buffer_GetContiguousLength
,
649 memory_2d_buffer_ContiguousCopyTo
,
650 memory_2d_buffer_ContiguousCopyFrom
,
651 memory_2d_buffer_Lock2DSize
,
652 memory_2d_buffer_Copy2DTo
,
655 static HRESULT WINAPI
d3d9_surface_buffer_Lock2D(IMF2DBuffer2
*iface
, BYTE
**scanline0
, LONG
*pitch
)
657 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
660 TRACE("%p, %p, %p.\n", iface
, scanline0
, pitch
);
662 if (!scanline0
|| !pitch
)
665 EnterCriticalSection(&buffer
->cs
);
667 if (buffer
->_2d
.linear_buffer
)
668 hr
= MF_E_UNEXPECTED
;
669 else if (!buffer
->_2d
.locks
++)
671 hr
= IDirect3DSurface9_LockRect(buffer
->d3d9_surface
.surface
, &buffer
->d3d9_surface
.rect
, NULL
, 0);
676 *scanline0
= buffer
->d3d9_surface
.rect
.pBits
;
677 *pitch
= buffer
->d3d9_surface
.rect
.Pitch
;
680 LeaveCriticalSection(&buffer
->cs
);
685 static HRESULT WINAPI
d3d9_surface_buffer_Unlock2D(IMF2DBuffer2
*iface
)
687 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
690 TRACE("%p.\n", iface
);
692 EnterCriticalSection(&buffer
->cs
);
694 if (buffer
->_2d
.locks
)
696 if (!--buffer
->_2d
.locks
)
698 IDirect3DSurface9_UnlockRect(buffer
->d3d9_surface
.surface
);
699 memset(&buffer
->d3d9_surface
.rect
, 0, sizeof(buffer
->d3d9_surface
.rect
));
703 hr
= HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED
);
705 LeaveCriticalSection(&buffer
->cs
);
710 static HRESULT WINAPI
d3d9_surface_buffer_GetScanline0AndPitch(IMF2DBuffer2
*iface
, BYTE
**scanline0
, LONG
*pitch
)
712 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
715 TRACE("%p, %p, %p.\n", iface
, scanline0
, pitch
);
717 if (!scanline0
|| !pitch
)
720 EnterCriticalSection(&buffer
->cs
);
722 if (!buffer
->_2d
.locks
)
726 hr
= HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED
);
730 *scanline0
= buffer
->d3d9_surface
.rect
.pBits
;
731 *pitch
= buffer
->d3d9_surface
.rect
.Pitch
;
734 LeaveCriticalSection(&buffer
->cs
);
739 static HRESULT WINAPI
d3d9_surface_buffer_Lock2DSize(IMF2DBuffer2
*iface
, MF2DBuffer_LockFlags flags
, BYTE
**scanline0
,
740 LONG
*pitch
, BYTE
**buffer_start
, DWORD
*buffer_length
)
742 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
745 TRACE("%p, %#x, %p, %p, %p, %p.\n", iface
, flags
, scanline0
, pitch
, buffer_start
, buffer_length
);
747 if (!scanline0
|| !pitch
|| !buffer_start
|| !buffer_length
)
750 EnterCriticalSection(&buffer
->cs
);
752 if (buffer
->_2d
.linear_buffer
)
753 hr
= MF_E_UNEXPECTED
;
754 else if (!buffer
->_2d
.locks
++)
756 hr
= IDirect3DSurface9_LockRect(buffer
->d3d9_surface
.surface
, &buffer
->d3d9_surface
.rect
, NULL
, 0);
761 *scanline0
= buffer
->d3d9_surface
.rect
.pBits
;
762 *pitch
= buffer
->d3d9_surface
.rect
.Pitch
;
764 *buffer_start
= *scanline0
;
766 *buffer_length
= buffer
->d3d9_surface
.rect
.Pitch
* buffer
->_2d
.height
;
769 LeaveCriticalSection(&buffer
->cs
);
774 static const IMF2DBuffer2Vtbl d3d9_surface_buffer_vtbl
=
776 memory_2d_buffer_QueryInterface
,
777 memory_2d_buffer_AddRef
,
778 memory_2d_buffer_Release
,
779 d3d9_surface_buffer_Lock2D
,
780 d3d9_surface_buffer_Unlock2D
,
781 d3d9_surface_buffer_GetScanline0AndPitch
,
782 memory_2d_buffer_IsContiguousFormat
,
783 memory_2d_buffer_GetContiguousLength
,
784 memory_2d_buffer_ContiguousCopyTo
,
785 memory_2d_buffer_ContiguousCopyFrom
,
786 d3d9_surface_buffer_Lock2DSize
,
787 memory_2d_buffer_Copy2DTo
,
790 static HRESULT WINAPI
memory_2d_buffer_gs_QueryInterface(IMFGetService
*iface
, REFIID riid
, void **obj
)
792 struct buffer
*buffer
= impl_from_IMFGetService(iface
);
793 return IMFMediaBuffer_QueryInterface(&buffer
->IMFMediaBuffer_iface
, riid
, obj
);
796 static ULONG WINAPI
memory_2d_buffer_gs_AddRef(IMFGetService
*iface
)
798 struct buffer
*buffer
= impl_from_IMFGetService(iface
);
799 return IMFMediaBuffer_AddRef(&buffer
->IMFMediaBuffer_iface
);
802 static ULONG WINAPI
memory_2d_buffer_gs_Release(IMFGetService
*iface
)
804 struct buffer
*buffer
= impl_from_IMFGetService(iface
);
805 return IMFMediaBuffer_Release(&buffer
->IMFMediaBuffer_iface
);
808 static HRESULT WINAPI
memory_2d_buffer_gs_GetService(IMFGetService
*iface
, REFGUID service
, REFIID riid
, void **obj
)
810 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(service
), debugstr_guid(riid
), obj
);
815 static const IMFGetServiceVtbl memory_2d_buffer_gs_vtbl
=
817 memory_2d_buffer_gs_QueryInterface
,
818 memory_2d_buffer_gs_AddRef
,
819 memory_2d_buffer_gs_Release
,
820 memory_2d_buffer_gs_GetService
,
823 static HRESULT WINAPI
d3d9_surface_buffer_gs_GetService(IMFGetService
*iface
, REFGUID service
, REFIID riid
, void **obj
)
825 struct buffer
*buffer
= impl_from_IMFGetService(iface
);
827 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(service
), debugstr_guid(riid
), obj
);
829 if (IsEqualGUID(service
, &MR_BUFFER_SERVICE
))
831 return IDirect3DSurface9_QueryInterface(buffer
->d3d9_surface
.surface
, riid
, obj
);
837 static const IMFGetServiceVtbl d3d9_surface_buffer_gs_vtbl
=
839 memory_2d_buffer_gs_QueryInterface
,
840 memory_2d_buffer_gs_AddRef
,
841 memory_2d_buffer_gs_Release
,
842 d3d9_surface_buffer_gs_GetService
,
845 static HRESULT WINAPI
dxgi_1d_2d_buffer_QueryInterface(IMFMediaBuffer
*iface
, REFIID riid
, void **out
)
847 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
849 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), out
);
851 if (IsEqualIID(riid
, &IID_IMFMediaBuffer
) ||
852 IsEqualIID(riid
, &IID_IUnknown
))
854 *out
= &buffer
->IMFMediaBuffer_iface
;
856 else if (IsEqualIID(riid
, &IID_IMF2DBuffer2
) ||
857 IsEqualIID(riid
, &IID_IMF2DBuffer
))
859 *out
= &buffer
->IMF2DBuffer2_iface
;
861 else if (IsEqualIID(riid
, &IID_IMFDXGIBuffer
))
863 *out
= &buffer
->IMFDXGIBuffer_iface
;
867 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
869 return E_NOINTERFACE
;
872 IUnknown_AddRef((IUnknown
*)*out
);
876 static HRESULT
dxgi_surface_buffer_create_readback_texture(struct buffer
*buffer
)
878 D3D11_TEXTURE2D_DESC texture_desc
;
879 ID3D11Device
*device
;
882 if (buffer
->dxgi_surface
.rb_texture
)
885 ID3D11Texture2D_GetDevice(buffer
->dxgi_surface
.texture
, &device
);
887 ID3D11Texture2D_GetDesc(buffer
->dxgi_surface
.texture
, &texture_desc
);
888 texture_desc
.Usage
= D3D11_USAGE_STAGING
;
889 texture_desc
.BindFlags
= 0;
890 texture_desc
.CPUAccessFlags
= D3D11_CPU_ACCESS_READ
| D3D11_CPU_ACCESS_WRITE
;
891 texture_desc
.MiscFlags
= 0;
892 texture_desc
.MipLevels
= 1;
893 if (FAILED(hr
= ID3D11Device_CreateTexture2D(device
, &texture_desc
, NULL
, &buffer
->dxgi_surface
.rb_texture
)))
894 WARN("Failed to create readback texture, hr %#x.\n", hr
);
896 ID3D11Device_Release(device
);
901 static HRESULT
dxgi_surface_buffer_map(struct buffer
*buffer
)
903 ID3D11DeviceContext
*immediate_context
;
904 ID3D11Device
*device
;
907 if (FAILED(hr
= dxgi_surface_buffer_create_readback_texture(buffer
)))
910 ID3D11Texture2D_GetDevice(buffer
->dxgi_surface
.texture
, &device
);
911 ID3D11Device_GetImmediateContext(device
, &immediate_context
);
912 ID3D11DeviceContext_CopySubresourceRegion(immediate_context
, (ID3D11Resource
*)buffer
->dxgi_surface
.rb_texture
,
913 0, 0, 0, 0, (ID3D11Resource
*)buffer
->dxgi_surface
.texture
, buffer
->dxgi_surface
.sub_resource_idx
, NULL
);
915 memset(&buffer
->dxgi_surface
.map_desc
, 0, sizeof(buffer
->dxgi_surface
.map_desc
));
916 if (FAILED(hr
= ID3D11DeviceContext_Map(immediate_context
, (ID3D11Resource
*)buffer
->dxgi_surface
.rb_texture
,
917 0, D3D11_MAP_READ_WRITE
, 0, &buffer
->dxgi_surface
.map_desc
)))
919 WARN("Failed to map readback texture, hr %#x.\n", hr
);
922 ID3D11DeviceContext_Release(immediate_context
);
923 ID3D11Device_Release(device
);
928 static void dxgi_surface_buffer_unmap(struct buffer
*buffer
)
930 ID3D11DeviceContext
*immediate_context
;
931 ID3D11Device
*device
;
933 ID3D11Texture2D_GetDevice(buffer
->dxgi_surface
.texture
, &device
);
934 ID3D11Device_GetImmediateContext(device
, &immediate_context
);
935 ID3D11DeviceContext_Unmap(immediate_context
, (ID3D11Resource
*)buffer
->dxgi_surface
.rb_texture
, 0);
936 memset(&buffer
->dxgi_surface
.map_desc
, 0, sizeof(buffer
->dxgi_surface
.map_desc
));
938 ID3D11DeviceContext_CopySubresourceRegion(immediate_context
, (ID3D11Resource
*)buffer
->dxgi_surface
.texture
,
939 buffer
->dxgi_surface
.sub_resource_idx
, 0, 0, 0, (ID3D11Resource
*)buffer
->dxgi_surface
.rb_texture
, 0, NULL
);
941 ID3D11DeviceContext_Release(immediate_context
);
942 ID3D11Device_Release(device
);
945 static HRESULT WINAPI
dxgi_surface_buffer_Lock(IMFMediaBuffer
*iface
, BYTE
**data
, DWORD
*max_length
,
946 DWORD
*current_length
)
948 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
951 TRACE("%p, %p, %p, %p.\n", iface
, data
, max_length
, current_length
);
956 EnterCriticalSection(&buffer
->cs
);
958 if (!buffer
->_2d
.linear_buffer
&& buffer
->_2d
.locks
)
959 hr
= MF_E_INVALIDREQUEST
;
960 else if (!buffer
->_2d
.linear_buffer
)
962 if (!(buffer
->_2d
.linear_buffer
= malloc(ALIGN_SIZE(buffer
->_2d
.plane_size
, MF_64_BYTE_ALIGNMENT
))))
967 hr
= dxgi_surface_buffer_map(buffer
);
970 copy_image(buffer
, buffer
->_2d
.linear_buffer
, buffer
->_2d
.width
, buffer
->dxgi_surface
.map_desc
.pData
,
971 buffer
->dxgi_surface
.map_desc
.RowPitch
, buffer
->_2d
.width
, buffer
->_2d
.height
);
979 *data
= buffer
->_2d
.linear_buffer
;
981 *max_length
= buffer
->_2d
.plane_size
;
983 *current_length
= buffer
->_2d
.plane_size
;
986 LeaveCriticalSection(&buffer
->cs
);
991 static HRESULT WINAPI
dxgi_surface_buffer_Unlock(IMFMediaBuffer
*iface
)
993 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
996 TRACE("%p.\n", iface
);
998 EnterCriticalSection(&buffer
->cs
);
1000 if (!buffer
->_2d
.linear_buffer
)
1001 hr
= HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED
);
1002 else if (!--buffer
->_2d
.locks
)
1004 copy_image(buffer
, buffer
->dxgi_surface
.map_desc
.pData
, buffer
->dxgi_surface
.map_desc
.RowPitch
,
1005 buffer
->_2d
.linear_buffer
, buffer
->_2d
.width
, buffer
->_2d
.width
, buffer
->_2d
.height
);
1006 dxgi_surface_buffer_unmap(buffer
);
1008 free(buffer
->_2d
.linear_buffer
);
1009 buffer
->_2d
.linear_buffer
= NULL
;
1012 LeaveCriticalSection(&buffer
->cs
);
1017 static HRESULT WINAPI
dxgi_surface_buffer_SetCurrentLength(IMFMediaBuffer
*iface
, DWORD current_length
)
1019 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
1021 TRACE("%p, %u.\n", iface
, current_length
);
1023 buffer
->current_length
= current_length
;
1028 static HRESULT WINAPI
dxgi_surface_buffer_Lock2D(IMF2DBuffer2
*iface
, BYTE
**scanline0
, LONG
*pitch
)
1030 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
1033 TRACE("%p, %p, %p.\n", iface
, scanline0
, pitch
);
1035 if (!scanline0
|| !pitch
)
1038 EnterCriticalSection(&buffer
->cs
);
1040 if (buffer
->_2d
.linear_buffer
)
1041 hr
= MF_E_UNEXPECTED
;
1042 else if (!buffer
->_2d
.locks
++)
1043 hr
= dxgi_surface_buffer_map(buffer
);
1047 *scanline0
= buffer
->dxgi_surface
.map_desc
.pData
;
1048 *pitch
= buffer
->dxgi_surface
.map_desc
.RowPitch
;
1051 LeaveCriticalSection(&buffer
->cs
);
1056 static HRESULT WINAPI
dxgi_surface_buffer_Unlock2D(IMF2DBuffer2
*iface
)
1058 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
1061 TRACE("%p.\n", iface
);
1063 EnterCriticalSection(&buffer
->cs
);
1065 if (buffer
->_2d
.locks
)
1067 if (!--buffer
->_2d
.locks
)
1068 dxgi_surface_buffer_unmap(buffer
);
1071 hr
= HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED
);
1073 LeaveCriticalSection(&buffer
->cs
);
1078 static HRESULT WINAPI
dxgi_surface_buffer_GetScanline0AndPitch(IMF2DBuffer2
*iface
, BYTE
**scanline0
, LONG
*pitch
)
1080 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
1083 TRACE("%p, %p, %p.\n", iface
, scanline0
, pitch
);
1085 if (!scanline0
|| !pitch
)
1088 EnterCriticalSection(&buffer
->cs
);
1090 if (!buffer
->_2d
.locks
)
1094 hr
= HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED
);
1098 *scanline0
= buffer
->dxgi_surface
.map_desc
.pData
;
1099 *pitch
= buffer
->dxgi_surface
.map_desc
.RowPitch
;
1102 LeaveCriticalSection(&buffer
->cs
);
1107 static HRESULT WINAPI
dxgi_surface_buffer_Lock2DSize(IMF2DBuffer2
*iface
, MF2DBuffer_LockFlags flags
,
1108 BYTE
**scanline0
, LONG
*pitch
, BYTE
**buffer_start
, DWORD
*buffer_length
)
1110 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
1113 TRACE("%p, %#x, %p, %p, %p, %p.\n", iface
, flags
, scanline0
, pitch
, buffer_start
, buffer_length
);
1115 if (!scanline0
|| !pitch
|| !buffer_start
|| !buffer_length
)
1118 EnterCriticalSection(&buffer
->cs
);
1120 if (buffer
->_2d
.linear_buffer
)
1121 hr
= MF_E_UNEXPECTED
;
1122 else if (!buffer
->_2d
.locks
++)
1123 hr
= dxgi_surface_buffer_map(buffer
);
1127 *scanline0
= buffer
->dxgi_surface
.map_desc
.pData
;
1128 *pitch
= buffer
->dxgi_surface
.map_desc
.RowPitch
;
1130 *buffer_start
= *scanline0
;
1132 *buffer_length
= buffer
->dxgi_surface
.map_desc
.RowPitch
* buffer
->_2d
.height
;
1135 LeaveCriticalSection(&buffer
->cs
);
1140 static HRESULT WINAPI
dxgi_buffer_QueryInterface(IMFDXGIBuffer
*iface
, REFIID riid
, void **obj
)
1142 struct buffer
*buffer
= impl_from_IMFDXGIBuffer(iface
);
1143 return IMFMediaBuffer_QueryInterface(&buffer
->IMFMediaBuffer_iface
, riid
, obj
);
1146 static ULONG WINAPI
dxgi_buffer_AddRef(IMFDXGIBuffer
*iface
)
1148 struct buffer
*buffer
= impl_from_IMFDXGIBuffer(iface
);
1149 return IMFMediaBuffer_AddRef(&buffer
->IMFMediaBuffer_iface
);
1152 static ULONG WINAPI
dxgi_buffer_Release(IMFDXGIBuffer
*iface
)
1154 struct buffer
*buffer
= impl_from_IMFDXGIBuffer(iface
);
1155 return IMFMediaBuffer_Release(&buffer
->IMFMediaBuffer_iface
);
1158 static HRESULT WINAPI
dxgi_buffer_GetResource(IMFDXGIBuffer
*iface
, REFIID riid
, void **obj
)
1160 struct buffer
*buffer
= impl_from_IMFDXGIBuffer(iface
);
1162 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
1164 return ID3D11Texture2D_QueryInterface(buffer
->dxgi_surface
.texture
, riid
, obj
);
1167 static HRESULT WINAPI
dxgi_buffer_GetSubresourceIndex(IMFDXGIBuffer
*iface
, UINT
*index
)
1169 struct buffer
*buffer
= impl_from_IMFDXGIBuffer(iface
);
1171 TRACE("%p, %p.\n", iface
, index
);
1176 *index
= buffer
->dxgi_surface
.sub_resource_idx
;
1181 static HRESULT WINAPI
dxgi_buffer_GetUnknown(IMFDXGIBuffer
*iface
, REFIID guid
, REFIID riid
, void **object
)
1183 struct buffer
*buffer
= impl_from_IMFDXGIBuffer(iface
);
1185 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(guid
), debugstr_guid(riid
), object
);
1187 if (attributes_GetUnknown(&buffer
->dxgi_surface
.attributes
, guid
, riid
, object
) == MF_E_ATTRIBUTENOTFOUND
)
1188 return MF_E_NOT_FOUND
;
1193 static HRESULT WINAPI
dxgi_buffer_SetUnknown(IMFDXGIBuffer
*iface
, REFIID guid
, IUnknown
*data
)
1195 struct buffer
*buffer
= impl_from_IMFDXGIBuffer(iface
);
1198 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(guid
), data
);
1200 EnterCriticalSection(&buffer
->dxgi_surface
.attributes
.cs
);
1203 if (SUCCEEDED(attributes_GetItem(&buffer
->dxgi_surface
.attributes
, guid
, NULL
)))
1204 hr
= HRESULT_FROM_WIN32(ERROR_OBJECT_ALREADY_EXISTS
);
1206 hr
= attributes_SetUnknown(&buffer
->dxgi_surface
.attributes
, guid
, data
);
1210 attributes_DeleteItem(&buffer
->dxgi_surface
.attributes
, guid
);
1212 LeaveCriticalSection(&buffer
->dxgi_surface
.attributes
.cs
);
1217 static const IMFMediaBufferVtbl dxgi_surface_1d_buffer_vtbl
=
1219 dxgi_1d_2d_buffer_QueryInterface
,
1220 memory_buffer_AddRef
,
1221 memory_buffer_Release
,
1222 dxgi_surface_buffer_Lock
,
1223 dxgi_surface_buffer_Unlock
,
1224 memory_buffer_GetCurrentLength
,
1225 dxgi_surface_buffer_SetCurrentLength
,
1226 memory_buffer_GetMaxLength
,
1229 static const IMF2DBuffer2Vtbl dxgi_surface_buffer_vtbl
=
1231 memory_2d_buffer_QueryInterface
,
1232 memory_2d_buffer_AddRef
,
1233 memory_2d_buffer_Release
,
1234 dxgi_surface_buffer_Lock2D
,
1235 dxgi_surface_buffer_Unlock2D
,
1236 dxgi_surface_buffer_GetScanline0AndPitch
,
1237 memory_2d_buffer_IsContiguousFormat
,
1238 memory_2d_buffer_GetContiguousLength
,
1239 memory_2d_buffer_ContiguousCopyTo
,
1240 memory_2d_buffer_ContiguousCopyFrom
,
1241 dxgi_surface_buffer_Lock2DSize
,
1242 memory_2d_buffer_Copy2DTo
,
1245 static const IMFDXGIBufferVtbl dxgi_buffer_vtbl
=
1247 dxgi_buffer_QueryInterface
,
1249 dxgi_buffer_Release
,
1250 dxgi_buffer_GetResource
,
1251 dxgi_buffer_GetSubresourceIndex
,
1252 dxgi_buffer_GetUnknown
,
1253 dxgi_buffer_SetUnknown
,
1256 static HRESULT
memory_buffer_init(struct buffer
*buffer
, DWORD max_length
, DWORD alignment
,
1257 const IMFMediaBufferVtbl
*vtbl
)
1259 if (!(buffer
->data
= calloc(1, ALIGN_SIZE(max_length
, alignment
))))
1260 return E_OUTOFMEMORY
;
1262 buffer
->IMFMediaBuffer_iface
.lpVtbl
= vtbl
;
1263 buffer
->refcount
= 1;
1264 buffer
->max_length
= max_length
;
1265 buffer
->current_length
= 0;
1266 InitializeCriticalSection(&buffer
->cs
);
1271 static HRESULT
create_1d_buffer(DWORD max_length
, DWORD alignment
, IMFMediaBuffer
**buffer
)
1273 struct buffer
*object
;
1281 if (!(object
= calloc(1, sizeof(*object
))))
1282 return E_OUTOFMEMORY
;
1284 hr
= memory_buffer_init(object
, max_length
, alignment
, &memory_1d_buffer_vtbl
);
1291 *buffer
= &object
->IMFMediaBuffer_iface
;
1296 static p_copy_image_func
get_2d_buffer_copy_func(DWORD fourcc
)
1298 if (fourcc
== MAKEFOURCC('N','V','1','2'))
1299 return copy_image_nv12
;
1300 if (fourcc
== MAKEFOURCC('I','M','C','1') || fourcc
== MAKEFOURCC('I','M','C','3'))
1301 return copy_image_imc1
;
1302 if (fourcc
== MAKEFOURCC('I','M','C','2') || fourcc
== MAKEFOURCC('I','M','C','4'))
1303 return copy_image_imc2
;
1307 static HRESULT
create_2d_buffer(DWORD width
, DWORD height
, DWORD fourcc
, BOOL bottom_up
, IMFMediaBuffer
**buffer
)
1309 unsigned int stride
, max_length
, plane_size
;
1310 struct buffer
*object
;
1311 unsigned int row_alignment
;
1322 memcpy(&subtype
, &MFVideoFormat_Base
, sizeof(subtype
));
1323 subtype
.Data1
= fourcc
;
1325 if (!(stride
= mf_format_get_stride(&subtype
, width
, &is_yuv
)))
1326 return MF_E_INVALIDMEDIATYPE
;
1328 if (is_yuv
&& bottom_up
)
1329 return MF_E_INVALIDMEDIATYPE
;
1331 if (FAILED(hr
= MFGetPlaneSize(fourcc
, width
, height
, &plane_size
)))
1334 if (!(object
= calloc(1, sizeof(*object
))))
1335 return E_OUTOFMEMORY
;
1339 case MAKEFOURCC('I','M','C','1'):
1340 case MAKEFOURCC('I','M','C','2'):
1341 case MAKEFOURCC('I','M','C','3'):
1342 case MAKEFOURCC('I','M','C','4'):
1343 case MAKEFOURCC('Y','V','1','2'):
1344 row_alignment
= MF_128_BYTE_ALIGNMENT
;
1347 row_alignment
= MF_64_BYTE_ALIGNMENT
;
1350 pitch
= ALIGN_SIZE(stride
, row_alignment
);
1354 case MAKEFOURCC('I','M','C','1'):
1355 case MAKEFOURCC('I','M','C','3'):
1356 max_length
= pitch
* height
* 2;
1359 case MAKEFOURCC('N','V','1','2'):
1360 case MAKEFOURCC('Y','V','1','2'):
1361 case MAKEFOURCC('I','M','C','2'):
1362 case MAKEFOURCC('I','M','C','4'):
1363 max_length
= pitch
* height
* 3 / 2;
1366 max_length
= pitch
* height
;
1369 if (FAILED(hr
= memory_buffer_init(object
, max_length
, MF_1_BYTE_ALIGNMENT
, &memory_1d_2d_buffer_vtbl
)))
1375 object
->IMF2DBuffer2_iface
.lpVtbl
= &memory_2d_buffer_vtbl
;
1376 object
->IMFGetService_iface
.lpVtbl
= &memory_2d_buffer_gs_vtbl
;
1377 object
->_2d
.plane_size
= plane_size
;
1378 object
->_2d
.width
= stride
;
1379 object
->_2d
.height
= height
;
1380 object
->_2d
.pitch
= bottom_up
? -pitch
: pitch
;
1381 object
->_2d
.scanline0
= bottom_up
? object
->data
+ pitch
* (object
->_2d
.height
- 1) : object
->data
;
1382 object
->_2d
.copy_image
= get_2d_buffer_copy_func(fourcc
);
1384 *buffer
= &object
->IMFMediaBuffer_iface
;
1389 static HRESULT
create_d3d9_surface_buffer(IUnknown
*surface
, BOOL bottom_up
, IMFMediaBuffer
**buffer
)
1391 struct buffer
*object
;
1392 D3DSURFACE_DESC desc
;
1393 unsigned int stride
;
1397 IDirect3DSurface9_GetDesc((IDirect3DSurface9
*)surface
, &desc
);
1398 TRACE("format %#x, %u x %u.\n", desc
.Format
, desc
.Width
, desc
.Height
);
1400 memcpy(&subtype
, &MFVideoFormat_Base
, sizeof(subtype
));
1401 subtype
.Data1
= desc
.Format
;
1403 if (!(stride
= mf_format_get_stride(&subtype
, desc
.Width
, &is_yuv
)))
1404 return MF_E_INVALIDMEDIATYPE
;
1406 if (!(object
= calloc(1, sizeof(*object
))))
1407 return E_OUTOFMEMORY
;
1409 object
->IMFMediaBuffer_iface
.lpVtbl
= &d3d9_surface_1d_buffer_vtbl
;
1410 object
->IMF2DBuffer2_iface
.lpVtbl
= &d3d9_surface_buffer_vtbl
;
1411 object
->IMFGetService_iface
.lpVtbl
= &d3d9_surface_buffer_gs_vtbl
;
1412 object
->refcount
= 1;
1413 InitializeCriticalSection(&object
->cs
);
1414 object
->d3d9_surface
.surface
= (IDirect3DSurface9
*)surface
;
1415 IUnknown_AddRef(surface
);
1417 MFGetPlaneSize(desc
.Format
, desc
.Width
, desc
.Height
, &object
->_2d
.plane_size
);
1418 object
->_2d
.width
= stride
;
1419 object
->_2d
.height
= desc
.Height
;
1420 object
->max_length
= object
->_2d
.plane_size
;
1421 object
->_2d
.copy_image
= get_2d_buffer_copy_func(desc
.Format
);
1423 *buffer
= &object
->IMFMediaBuffer_iface
;
1428 static HRESULT
create_dxgi_surface_buffer(IUnknown
*surface
, unsigned int sub_resource_idx
,
1429 BOOL bottom_up
, IMFMediaBuffer
**buffer
)
1431 struct buffer
*object
;
1432 D3D11_TEXTURE2D_DESC desc
;
1433 ID3D11Texture2D
*texture
;
1434 unsigned int stride
;
1440 if (FAILED(hr
= IUnknown_QueryInterface(surface
, &IID_ID3D11Texture2D
, (void **)&texture
)))
1442 WARN("Failed to get texture interface, hr %#x.\n", hr
);
1446 ID3D11Texture2D_GetDesc(texture
, &desc
);
1447 TRACE("format %#x, %u x %u.\n", desc
.Format
, desc
.Width
, desc
.Height
);
1449 memcpy(&subtype
, &MFVideoFormat_Base
, sizeof(subtype
));
1450 subtype
.Data1
= format
= MFMapDXGIFormatToDX9Format(desc
.Format
);
1452 if (!(stride
= mf_format_get_stride(&subtype
, desc
.Width
, &is_yuv
)))
1454 ID3D11Texture2D_Release(texture
);
1455 return MF_E_INVALIDMEDIATYPE
;
1458 if (!(object
= calloc(1, sizeof(*object
))))
1460 ID3D11Texture2D_Release(texture
);
1461 return E_OUTOFMEMORY
;
1464 object
->IMFMediaBuffer_iface
.lpVtbl
= &dxgi_surface_1d_buffer_vtbl
;
1465 object
->IMF2DBuffer2_iface
.lpVtbl
= &dxgi_surface_buffer_vtbl
;
1466 object
->IMFDXGIBuffer_iface
.lpVtbl
= &dxgi_buffer_vtbl
;
1467 object
->refcount
= 1;
1468 InitializeCriticalSection(&object
->cs
);
1469 object
->dxgi_surface
.texture
= texture
;
1470 object
->dxgi_surface
.sub_resource_idx
= sub_resource_idx
;
1472 MFGetPlaneSize(format
, desc
.Width
, desc
.Height
, &object
->_2d
.plane_size
);
1473 object
->_2d
.width
= stride
;
1474 object
->_2d
.height
= desc
.Height
;
1475 object
->max_length
= object
->_2d
.plane_size
;
1476 object
->_2d
.copy_image
= get_2d_buffer_copy_func(format
);
1478 if (FAILED(hr
= init_attributes_object(&object
->dxgi_surface
.attributes
, 0)))
1480 IMFMediaBuffer_Release(&object
->IMFMediaBuffer_iface
);
1484 *buffer
= &object
->IMFMediaBuffer_iface
;
1489 /***********************************************************************
1490 * MFCreateMemoryBuffer (mfplat.@)
1492 HRESULT WINAPI
MFCreateMemoryBuffer(DWORD max_length
, IMFMediaBuffer
**buffer
)
1494 TRACE("%u, %p.\n", max_length
, buffer
);
1496 return create_1d_buffer(max_length
, MF_1_BYTE_ALIGNMENT
, buffer
);
1499 /***********************************************************************
1500 * MFCreateAlignedMemoryBuffer (mfplat.@)
1502 HRESULT WINAPI
MFCreateAlignedMemoryBuffer(DWORD max_length
, DWORD alignment
, IMFMediaBuffer
**buffer
)
1504 TRACE("%u, %u, %p.\n", max_length
, alignment
, buffer
);
1506 return create_1d_buffer(max_length
, alignment
, buffer
);
1509 /***********************************************************************
1510 * MFCreate2DMediaBuffer (mfplat.@)
1512 HRESULT WINAPI
MFCreate2DMediaBuffer(DWORD width
, DWORD height
, DWORD fourcc
, BOOL bottom_up
, IMFMediaBuffer
**buffer
)
1514 TRACE("%u, %u, %s, %d, %p.\n", width
, height
, debugstr_fourcc(fourcc
), bottom_up
, buffer
);
1516 return create_2d_buffer(width
, height
, fourcc
, bottom_up
, buffer
);
1519 /***********************************************************************
1520 * MFCreateDXSurfaceBuffer (mfplat.@)
1522 HRESULT WINAPI
MFCreateDXSurfaceBuffer(REFIID riid
, IUnknown
*surface
, BOOL bottom_up
, IMFMediaBuffer
**buffer
)
1524 TRACE("%s, %p, %d, %p.\n", debugstr_guid(riid
), surface
, bottom_up
, buffer
);
1526 if (!IsEqualIID(riid
, &IID_IDirect3DSurface9
))
1527 return E_INVALIDARG
;
1529 return create_d3d9_surface_buffer(surface
, bottom_up
, buffer
);
1532 /***********************************************************************
1533 * MFCreateDXGISurfaceBuffer (mfplat.@)
1535 HRESULT WINAPI
MFCreateDXGISurfaceBuffer(REFIID riid
, IUnknown
*surface
, UINT subresource
, BOOL bottom_up
,
1536 IMFMediaBuffer
**buffer
)
1538 TRACE("%s, %p, %u, %d, %p.\n", debugstr_guid(riid
), surface
, subresource
, bottom_up
, buffer
);
1540 if (!IsEqualIID(riid
, &IID_ID3D11Texture2D
))
1541 return E_INVALIDARG
;
1543 return create_dxgi_surface_buffer(surface
, subresource
, bottom_up
, buffer
);
1546 static unsigned int buffer_get_aligned_length(unsigned int length
, unsigned int alignment
)
1548 length
= (length
+ alignment
) / alignment
;
1549 length
*= alignment
;
1554 HRESULT WINAPI
MFCreateMediaBufferFromMediaType(IMFMediaType
*media_type
, LONGLONG duration
, DWORD min_length
,
1555 DWORD alignment
, IMFMediaBuffer
**buffer
)
1557 UINT32 length
= 0, block_alignment
;
1558 LONGLONG avg_length
;
1562 TRACE("%p, %s, %u, %u, %p.\n", media_type
, debugstr_time(duration
), min_length
, alignment
, buffer
);
1565 return E_INVALIDARG
;
1567 if (FAILED(hr
= IMFMediaType_GetMajorType(media_type
, &major
)))
1570 if (IsEqualGUID(&major
, &MFMediaType_Audio
))
1572 block_alignment
= 0;
1573 if (FAILED(IMFMediaType_GetUINT32(media_type
, &MF_MT_AUDIO_BLOCK_ALIGNMENT
, &block_alignment
)))
1574 WARN("Block alignment was not specified.\n");
1576 if (block_alignment
)
1583 if (SUCCEEDED(IMFMediaType_GetUINT32(media_type
, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND
, &length
)))
1586 avg_length
= length
* duration
/ (10 * 1000 * 1000);
1590 alignment
= max(16, alignment
);
1592 length
= buffer_get_aligned_length(avg_length
+ 1, alignment
);
1593 length
= buffer_get_aligned_length(length
, block_alignment
);
1598 length
= max(length
, min_length
);
1600 return create_1d_buffer(length
, MF_1_BYTE_ALIGNMENT
, buffer
);
1603 FIXME("Major type %s is not supported.\n", debugstr_guid(&major
));