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 MF2DBuffer_LockFlags lock_flags
;
60 p_copy_image_func copy_image
;
64 IDirect3DSurface9
*surface
;
69 ID3D11Texture2D
*texture
;
70 unsigned int sub_resource_idx
;
71 ID3D11Texture2D
*rb_texture
;
72 D3D11_MAPPED_SUBRESOURCE map_desc
;
73 struct attributes attributes
;
79 static void copy_image(const struct buffer
*buffer
, BYTE
*dest
, LONG dest_stride
, const BYTE
*src
,
80 LONG src_stride
, DWORD width
, DWORD lines
)
82 MFCopyImage(dest
, dest_stride
, src
, src_stride
, width
, lines
);
84 if (buffer
->_2d
.copy_image
)
86 dest
+= dest_stride
* lines
;
87 src
+= src_stride
* lines
;
88 buffer
->_2d
.copy_image(dest
, dest_stride
, src
, src_stride
, width
, lines
);
92 static void copy_image_nv12(BYTE
*dest
, LONG dest_stride
, const BYTE
*src
, LONG src_stride
, DWORD width
, DWORD lines
)
94 MFCopyImage(dest
, dest_stride
, src
, src_stride
, width
, lines
/ 2);
97 static void copy_image_imc1(BYTE
*dest
, LONG dest_stride
, const BYTE
*src
, LONG src_stride
, DWORD width
, DWORD lines
)
99 MFCopyImage(dest
, dest_stride
, src
, src_stride
, width
/ 2, lines
);
102 static void copy_image_imc2(BYTE
*dest
, LONG dest_stride
, const BYTE
*src
, LONG src_stride
, DWORD width
, DWORD lines
)
104 MFCopyImage(dest
, dest_stride
/ 2, src
, src_stride
/ 2, width
/ 2, lines
);
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 %lu.\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 %lu.\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
);
176 _aligned_free(buffer
->data
);
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, %lu.\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(buffer
->_2d
.plane_size
)))
316 copy_image(buffer
, buffer
->_2d
.linear_buffer
, buffer
->_2d
.width
, buffer
->data
, buffer
->_2d
.pitch
,
317 buffer
->_2d
.width
, buffer
->_2d
.height
);
323 *data
= buffer
->_2d
.linear_buffer
;
325 *max_length
= buffer
->_2d
.plane_size
;
327 *current_length
= buffer
->_2d
.plane_size
;
330 LeaveCriticalSection(&buffer
->cs
);
335 static HRESULT WINAPI
memory_1d_2d_buffer_Unlock(IMFMediaBuffer
*iface
)
337 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
339 TRACE("%p.\n", iface
);
341 EnterCriticalSection(&buffer
->cs
);
343 if (buffer
->_2d
.linear_buffer
&& !--buffer
->_2d
.locks
)
345 copy_image(buffer
, buffer
->data
, buffer
->_2d
.pitch
, buffer
->_2d
.linear_buffer
, buffer
->_2d
.width
,
346 buffer
->_2d
.width
, buffer
->_2d
.height
);
348 free(buffer
->_2d
.linear_buffer
);
349 buffer
->_2d
.linear_buffer
= NULL
;
352 LeaveCriticalSection(&buffer
->cs
);
357 static const IMFMediaBufferVtbl memory_1d_2d_buffer_vtbl
=
359 memory_1d_2d_buffer_QueryInterface
,
360 memory_buffer_AddRef
,
361 memory_buffer_Release
,
362 memory_1d_2d_buffer_Lock
,
363 memory_1d_2d_buffer_Unlock
,
364 memory_buffer_GetCurrentLength
,
365 memory_buffer_SetCurrentLength
,
366 memory_buffer_GetMaxLength
,
369 static HRESULT WINAPI
d3d9_surface_buffer_Lock(IMFMediaBuffer
*iface
, BYTE
**data
, DWORD
*max_length
, DWORD
*current_length
)
371 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
374 TRACE("%p, %p, %p, %p.\n", iface
, data
, max_length
, current_length
);
379 EnterCriticalSection(&buffer
->cs
);
381 if (!buffer
->_2d
.linear_buffer
&& buffer
->_2d
.locks
)
382 hr
= MF_E_INVALIDREQUEST
;
383 else if (!buffer
->_2d
.linear_buffer
)
387 if (!(buffer
->_2d
.linear_buffer
= malloc(buffer
->_2d
.plane_size
)))
392 hr
= IDirect3DSurface9_LockRect(buffer
->d3d9_surface
.surface
, &rect
, NULL
, 0);
395 copy_image(buffer
, buffer
->_2d
.linear_buffer
, buffer
->_2d
.width
, rect
.pBits
, rect
.Pitch
,
396 buffer
->_2d
.width
, buffer
->_2d
.height
);
397 IDirect3DSurface9_UnlockRect(buffer
->d3d9_surface
.surface
);
405 *data
= buffer
->_2d
.linear_buffer
;
407 *max_length
= buffer
->_2d
.plane_size
;
409 *current_length
= buffer
->_2d
.plane_size
;
412 LeaveCriticalSection(&buffer
->cs
);
417 static HRESULT WINAPI
d3d9_surface_buffer_Unlock(IMFMediaBuffer
*iface
)
419 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
422 TRACE("%p.\n", iface
);
424 EnterCriticalSection(&buffer
->cs
);
426 if (!buffer
->_2d
.linear_buffer
)
427 hr
= HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED
);
428 else if (!--buffer
->_2d
.locks
)
432 if (SUCCEEDED(hr
= IDirect3DSurface9_LockRect(buffer
->d3d9_surface
.surface
, &rect
, NULL
, 0)))
434 copy_image(buffer
, rect
.pBits
, rect
.Pitch
, buffer
->_2d
.linear_buffer
, buffer
->_2d
.width
,
435 buffer
->_2d
.width
, buffer
->_2d
.height
);
436 IDirect3DSurface9_UnlockRect(buffer
->d3d9_surface
.surface
);
439 free(buffer
->_2d
.linear_buffer
);
440 buffer
->_2d
.linear_buffer
= NULL
;
443 LeaveCriticalSection(&buffer
->cs
);
448 static HRESULT WINAPI
d3d9_surface_buffer_SetCurrentLength(IMFMediaBuffer
*iface
, DWORD current_length
)
450 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
452 TRACE("%p, %lu.\n", iface
, current_length
);
454 buffer
->current_length
= current_length
;
459 static const IMFMediaBufferVtbl d3d9_surface_1d_buffer_vtbl
=
461 memory_1d_2d_buffer_QueryInterface
,
462 memory_buffer_AddRef
,
463 memory_buffer_Release
,
464 d3d9_surface_buffer_Lock
,
465 d3d9_surface_buffer_Unlock
,
466 memory_buffer_GetCurrentLength
,
467 d3d9_surface_buffer_SetCurrentLength
,
468 memory_buffer_GetMaxLength
,
471 static HRESULT WINAPI
memory_2d_buffer_QueryInterface(IMF2DBuffer2
*iface
, REFIID riid
, void **obj
)
473 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
474 return IMFMediaBuffer_QueryInterface(&buffer
->IMFMediaBuffer_iface
, riid
, obj
);
477 static ULONG WINAPI
memory_2d_buffer_AddRef(IMF2DBuffer2
*iface
)
479 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
480 return IMFMediaBuffer_AddRef(&buffer
->IMFMediaBuffer_iface
);
483 static ULONG WINAPI
memory_2d_buffer_Release(IMF2DBuffer2
*iface
)
485 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
486 return IMFMediaBuffer_Release(&buffer
->IMFMediaBuffer_iface
);
489 static HRESULT
memory_2d_buffer_lock(struct buffer
*buffer
, BYTE
**scanline0
, LONG
*pitch
,
490 BYTE
**buffer_start
, DWORD
*buffer_length
)
494 if (buffer
->_2d
.linear_buffer
)
495 hr
= MF_E_UNEXPECTED
;
499 *scanline0
= buffer
->_2d
.scanline0
;
500 *pitch
= buffer
->_2d
.pitch
;
502 *buffer_start
= buffer
->data
;
504 *buffer_length
= buffer
->max_length
;
510 static HRESULT WINAPI
memory_2d_buffer_Lock2D(IMF2DBuffer2
*iface
, BYTE
**scanline0
, LONG
*pitch
)
512 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
515 TRACE("%p, %p, %p.\n", iface
, scanline0
, pitch
);
517 if (!scanline0
|| !pitch
)
520 EnterCriticalSection(&buffer
->cs
);
522 hr
= memory_2d_buffer_lock(buffer
, scanline0
, pitch
, NULL
, NULL
);
524 LeaveCriticalSection(&buffer
->cs
);
529 static HRESULT WINAPI
memory_2d_buffer_Unlock2D(IMF2DBuffer2
*iface
)
531 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
534 TRACE("%p.\n", iface
);
536 EnterCriticalSection(&buffer
->cs
);
538 if (!buffer
->_2d
.linear_buffer
)
540 if (buffer
->_2d
.locks
)
543 hr
= HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED
);
546 LeaveCriticalSection(&buffer
->cs
);
551 static HRESULT WINAPI
memory_2d_buffer_GetScanline0AndPitch(IMF2DBuffer2
*iface
, BYTE
**scanline0
, LONG
*pitch
)
553 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
556 TRACE("%p, %p, %p.\n", iface
, scanline0
, pitch
);
558 if (!scanline0
|| !pitch
)
561 EnterCriticalSection(&buffer
->cs
);
563 if (buffer
->_2d
.linear_buffer
|| !buffer
->_2d
.locks
)
564 hr
= HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED
);
567 *scanline0
= buffer
->_2d
.scanline0
;
568 *pitch
= buffer
->_2d
.pitch
;
571 LeaveCriticalSection(&buffer
->cs
);
576 static HRESULT WINAPI
memory_2d_buffer_IsContiguousFormat(IMF2DBuffer2
*iface
, BOOL
*is_contiguous
)
578 TRACE("%p, %p.\n", iface
, is_contiguous
);
583 *is_contiguous
= FALSE
;
588 static HRESULT WINAPI
memory_2d_buffer_GetContiguousLength(IMF2DBuffer2
*iface
, DWORD
*length
)
590 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
592 TRACE("%p, %p.\n", iface
, length
);
597 *length
= buffer
->_2d
.plane_size
;
602 static HRESULT WINAPI
memory_2d_buffer_ContiguousCopyTo(IMF2DBuffer2
*iface
, BYTE
*dest_buffer
, DWORD dest_length
)
604 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
605 BYTE
*src_scanline0
, *src_buffer_start
;
610 TRACE("%p, %p, %lu.\n", iface
, dest_buffer
, dest_length
);
612 if (dest_length
< buffer
->_2d
.plane_size
)
615 hr
= IMF2DBuffer2_Lock2DSize(iface
, MF2DBuffer_LockFlags_Read
, &src_scanline0
, &src_pitch
, &src_buffer_start
, &src_length
);
619 copy_image(buffer
, dest_buffer
, buffer
->_2d
.width
, src_scanline0
, src_pitch
, buffer
->_2d
.width
, buffer
->_2d
.height
);
621 if (FAILED(IMF2DBuffer2_Unlock2D(iface
)))
622 WARN("Couldn't unlock source buffer %p, hr %#lx.\n", iface
, hr
);
628 static HRESULT WINAPI
memory_2d_buffer_ContiguousCopyFrom(IMF2DBuffer2
*iface
, const BYTE
*src_buffer
, DWORD src_length
)
630 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
631 BYTE
*dst_scanline0
, *dst_buffer_start
;
636 TRACE("%p, %p, %lu.\n", iface
, src_buffer
, src_length
);
638 if (src_length
< buffer
->_2d
.plane_size
)
641 hr
= IMF2DBuffer2_Lock2DSize(iface
, MF2DBuffer_LockFlags_Write
, &dst_scanline0
, &dst_pitch
, &dst_buffer_start
, &dst_length
);
645 copy_image(buffer
, dst_scanline0
, dst_pitch
, src_buffer
, buffer
->_2d
.width
, buffer
->_2d
.width
, buffer
->_2d
.height
);
647 if (FAILED(IMF2DBuffer2_Unlock2D(iface
)))
648 WARN("Couldn't unlock destination buffer %p, hr %#lx.\n", iface
, hr
);
654 static HRESULT WINAPI
memory_2d_buffer_Lock2DSize(IMF2DBuffer2
*iface
, MF2DBuffer_LockFlags flags
, BYTE
**scanline0
,
655 LONG
*pitch
, BYTE
**buffer_start
, DWORD
*buffer_length
)
657 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
660 TRACE("%p, %#x, %p, %p, %p, %p.\n", iface
, flags
, scanline0
, pitch
, buffer_start
, buffer_length
);
662 if (!scanline0
|| !pitch
|| !buffer_start
|| !buffer_length
)
665 EnterCriticalSection(&buffer
->cs
);
667 hr
= memory_2d_buffer_lock(buffer
, scanline0
, pitch
, buffer_start
, buffer_length
);
669 LeaveCriticalSection(&buffer
->cs
);
674 static HRESULT WINAPI
memory_2d_buffer_Copy2DTo(IMF2DBuffer2
*iface
, IMF2DBuffer2
*dest_buffer
)
676 FIXME("%p, %p.\n", iface
, dest_buffer
);
681 static const IMF2DBuffer2Vtbl memory_2d_buffer_vtbl
=
683 memory_2d_buffer_QueryInterface
,
684 memory_2d_buffer_AddRef
,
685 memory_2d_buffer_Release
,
686 memory_2d_buffer_Lock2D
,
687 memory_2d_buffer_Unlock2D
,
688 memory_2d_buffer_GetScanline0AndPitch
,
689 memory_2d_buffer_IsContiguousFormat
,
690 memory_2d_buffer_GetContiguousLength
,
691 memory_2d_buffer_ContiguousCopyTo
,
692 memory_2d_buffer_ContiguousCopyFrom
,
693 memory_2d_buffer_Lock2DSize
,
694 memory_2d_buffer_Copy2DTo
,
697 static HRESULT
d3d9_surface_buffer_lock(struct buffer
*buffer
, MF2DBuffer_LockFlags flags
, BYTE
**scanline0
,
698 LONG
*pitch
, BYTE
**buffer_start
, DWORD
*buffer_length
)
702 if (buffer
->_2d
.linear_buffer
)
703 hr
= MF_E_UNEXPECTED
;
704 else if (!buffer
->_2d
.locks
)
705 hr
= IDirect3DSurface9_LockRect(buffer
->d3d9_surface
.surface
, &buffer
->d3d9_surface
.rect
, NULL
, 0);
706 else if (buffer
->_2d
.lock_flags
== MF2DBuffer_LockFlags_Write
&& flags
!= MF2DBuffer_LockFlags_Write
)
707 hr
= HRESULT_FROM_WIN32(ERROR_WAS_LOCKED
);
711 if (!buffer
->_2d
.locks
)
712 buffer
->_2d
.lock_flags
= flags
;
714 *scanline0
= buffer
->d3d9_surface
.rect
.pBits
;
715 *pitch
= buffer
->d3d9_surface
.rect
.Pitch
;
717 *buffer_start
= *scanline0
;
719 *buffer_length
= buffer
->d3d9_surface
.rect
.Pitch
* buffer
->_2d
.height
;
725 static HRESULT WINAPI
d3d9_surface_buffer_Lock2D(IMF2DBuffer2
*iface
, BYTE
**scanline0
, LONG
*pitch
)
727 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
730 TRACE("%p, %p, %p.\n", iface
, scanline0
, pitch
);
732 if (!scanline0
|| !pitch
)
735 EnterCriticalSection(&buffer
->cs
);
737 hr
= d3d9_surface_buffer_lock(buffer
, MF2DBuffer_LockFlags_ReadWrite
, scanline0
, pitch
, NULL
, NULL
);
739 LeaveCriticalSection(&buffer
->cs
);
744 static HRESULT WINAPI
d3d9_surface_buffer_Unlock2D(IMF2DBuffer2
*iface
)
746 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
749 TRACE("%p.\n", iface
);
751 EnterCriticalSection(&buffer
->cs
);
753 if (buffer
->_2d
.locks
)
755 if (!--buffer
->_2d
.locks
)
757 IDirect3DSurface9_UnlockRect(buffer
->d3d9_surface
.surface
);
758 memset(&buffer
->d3d9_surface
.rect
, 0, sizeof(buffer
->d3d9_surface
.rect
));
759 buffer
->_2d
.lock_flags
= 0;
763 hr
= HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED
);
765 LeaveCriticalSection(&buffer
->cs
);
770 static HRESULT WINAPI
d3d9_surface_buffer_GetScanline0AndPitch(IMF2DBuffer2
*iface
, BYTE
**scanline0
, LONG
*pitch
)
772 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
775 TRACE("%p, %p, %p.\n", iface
, scanline0
, pitch
);
777 if (!scanline0
|| !pitch
)
780 EnterCriticalSection(&buffer
->cs
);
782 if (!buffer
->_2d
.locks
)
786 hr
= HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED
);
790 *scanline0
= buffer
->d3d9_surface
.rect
.pBits
;
791 *pitch
= buffer
->d3d9_surface
.rect
.Pitch
;
794 LeaveCriticalSection(&buffer
->cs
);
799 static HRESULT WINAPI
d3d9_surface_buffer_Lock2DSize(IMF2DBuffer2
*iface
, MF2DBuffer_LockFlags flags
, BYTE
**scanline0
,
800 LONG
*pitch
, BYTE
**buffer_start
, DWORD
*buffer_length
)
802 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
805 TRACE("%p, %#x, %p, %p, %p, %p.\n", iface
, flags
, scanline0
, pitch
, buffer_start
, buffer_length
);
807 if (!scanline0
|| !pitch
|| !buffer_start
|| !buffer_length
)
810 EnterCriticalSection(&buffer
->cs
);
812 hr
= d3d9_surface_buffer_lock(buffer
, flags
, scanline0
, pitch
, buffer_start
, buffer_length
);
814 LeaveCriticalSection(&buffer
->cs
);
819 static const IMF2DBuffer2Vtbl d3d9_surface_buffer_vtbl
=
821 memory_2d_buffer_QueryInterface
,
822 memory_2d_buffer_AddRef
,
823 memory_2d_buffer_Release
,
824 d3d9_surface_buffer_Lock2D
,
825 d3d9_surface_buffer_Unlock2D
,
826 d3d9_surface_buffer_GetScanline0AndPitch
,
827 memory_2d_buffer_IsContiguousFormat
,
828 memory_2d_buffer_GetContiguousLength
,
829 memory_2d_buffer_ContiguousCopyTo
,
830 memory_2d_buffer_ContiguousCopyFrom
,
831 d3d9_surface_buffer_Lock2DSize
,
832 memory_2d_buffer_Copy2DTo
,
835 static HRESULT WINAPI
memory_2d_buffer_gs_QueryInterface(IMFGetService
*iface
, REFIID riid
, void **obj
)
837 struct buffer
*buffer
= impl_from_IMFGetService(iface
);
838 return IMFMediaBuffer_QueryInterface(&buffer
->IMFMediaBuffer_iface
, riid
, obj
);
841 static ULONG WINAPI
memory_2d_buffer_gs_AddRef(IMFGetService
*iface
)
843 struct buffer
*buffer
= impl_from_IMFGetService(iface
);
844 return IMFMediaBuffer_AddRef(&buffer
->IMFMediaBuffer_iface
);
847 static ULONG WINAPI
memory_2d_buffer_gs_Release(IMFGetService
*iface
)
849 struct buffer
*buffer
= impl_from_IMFGetService(iface
);
850 return IMFMediaBuffer_Release(&buffer
->IMFMediaBuffer_iface
);
853 static HRESULT WINAPI
memory_2d_buffer_gs_GetService(IMFGetService
*iface
, REFGUID service
, REFIID riid
, void **obj
)
855 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(service
), debugstr_guid(riid
), obj
);
860 static const IMFGetServiceVtbl memory_2d_buffer_gs_vtbl
=
862 memory_2d_buffer_gs_QueryInterface
,
863 memory_2d_buffer_gs_AddRef
,
864 memory_2d_buffer_gs_Release
,
865 memory_2d_buffer_gs_GetService
,
868 static HRESULT WINAPI
d3d9_surface_buffer_gs_GetService(IMFGetService
*iface
, REFGUID service
, REFIID riid
, void **obj
)
870 struct buffer
*buffer
= impl_from_IMFGetService(iface
);
872 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(service
), debugstr_guid(riid
), obj
);
874 if (IsEqualGUID(service
, &MR_BUFFER_SERVICE
))
876 return IDirect3DSurface9_QueryInterface(buffer
->d3d9_surface
.surface
, riid
, obj
);
882 static const IMFGetServiceVtbl d3d9_surface_buffer_gs_vtbl
=
884 memory_2d_buffer_gs_QueryInterface
,
885 memory_2d_buffer_gs_AddRef
,
886 memory_2d_buffer_gs_Release
,
887 d3d9_surface_buffer_gs_GetService
,
890 static HRESULT WINAPI
dxgi_1d_2d_buffer_QueryInterface(IMFMediaBuffer
*iface
, REFIID riid
, void **out
)
892 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
894 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), out
);
896 if (IsEqualIID(riid
, &IID_IMFMediaBuffer
) ||
897 IsEqualIID(riid
, &IID_IUnknown
))
899 *out
= &buffer
->IMFMediaBuffer_iface
;
901 else if (IsEqualIID(riid
, &IID_IMF2DBuffer2
) ||
902 IsEqualIID(riid
, &IID_IMF2DBuffer
))
904 *out
= &buffer
->IMF2DBuffer2_iface
;
906 else if (IsEqualIID(riid
, &IID_IMFDXGIBuffer
))
908 *out
= &buffer
->IMFDXGIBuffer_iface
;
912 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
914 return E_NOINTERFACE
;
917 IUnknown_AddRef((IUnknown
*)*out
);
921 static HRESULT
dxgi_surface_buffer_create_readback_texture(struct buffer
*buffer
)
923 D3D11_TEXTURE2D_DESC texture_desc
;
924 ID3D11Device
*device
;
927 if (buffer
->dxgi_surface
.rb_texture
)
930 ID3D11Texture2D_GetDevice(buffer
->dxgi_surface
.texture
, &device
);
932 ID3D11Texture2D_GetDesc(buffer
->dxgi_surface
.texture
, &texture_desc
);
933 texture_desc
.Usage
= D3D11_USAGE_STAGING
;
934 texture_desc
.BindFlags
= 0;
935 texture_desc
.CPUAccessFlags
= D3D11_CPU_ACCESS_READ
| D3D11_CPU_ACCESS_WRITE
;
936 texture_desc
.MiscFlags
= 0;
937 texture_desc
.MipLevels
= 1;
938 if (FAILED(hr
= ID3D11Device_CreateTexture2D(device
, &texture_desc
, NULL
, &buffer
->dxgi_surface
.rb_texture
)))
939 WARN("Failed to create readback texture, hr %#lx.\n", hr
);
941 ID3D11Device_Release(device
);
946 static HRESULT
dxgi_surface_buffer_map(struct buffer
*buffer
, MF2DBuffer_LockFlags flags
)
948 ID3D11DeviceContext
*immediate_context
;
949 ID3D11Device
*device
;
952 if (FAILED(hr
= dxgi_surface_buffer_create_readback_texture(buffer
)))
955 ID3D11Texture2D_GetDevice(buffer
->dxgi_surface
.texture
, &device
);
956 ID3D11Device_GetImmediateContext(device
, &immediate_context
);
958 if (flags
== MF2DBuffer_LockFlags_Read
|| flags
== MF2DBuffer_LockFlags_ReadWrite
)
960 ID3D11DeviceContext_CopySubresourceRegion(immediate_context
, (ID3D11Resource
*)buffer
->dxgi_surface
.rb_texture
,
961 0, 0, 0, 0, (ID3D11Resource
*)buffer
->dxgi_surface
.texture
, buffer
->dxgi_surface
.sub_resource_idx
, NULL
);
964 memset(&buffer
->dxgi_surface
.map_desc
, 0, sizeof(buffer
->dxgi_surface
.map_desc
));
965 if (FAILED(hr
= ID3D11DeviceContext_Map(immediate_context
, (ID3D11Resource
*)buffer
->dxgi_surface
.rb_texture
,
966 0, D3D11_MAP_READ_WRITE
, 0, &buffer
->dxgi_surface
.map_desc
)))
968 WARN("Failed to map readback texture, hr %#lx.\n", hr
);
971 ID3D11DeviceContext_Release(immediate_context
);
972 ID3D11Device_Release(device
);
977 static void dxgi_surface_buffer_unmap(struct buffer
*buffer
, MF2DBuffer_LockFlags flags
)
979 ID3D11DeviceContext
*immediate_context
;
980 ID3D11Device
*device
;
982 ID3D11Texture2D_GetDevice(buffer
->dxgi_surface
.texture
, &device
);
983 ID3D11Device_GetImmediateContext(device
, &immediate_context
);
984 ID3D11DeviceContext_Unmap(immediate_context
, (ID3D11Resource
*)buffer
->dxgi_surface
.rb_texture
, 0);
985 memset(&buffer
->dxgi_surface
.map_desc
, 0, sizeof(buffer
->dxgi_surface
.map_desc
));
987 if (flags
== MF2DBuffer_LockFlags_Write
|| flags
== MF2DBuffer_LockFlags_ReadWrite
)
989 ID3D11DeviceContext_CopySubresourceRegion(immediate_context
, (ID3D11Resource
*)buffer
->dxgi_surface
.texture
,
990 buffer
->dxgi_surface
.sub_resource_idx
, 0, 0, 0, (ID3D11Resource
*)buffer
->dxgi_surface
.rb_texture
, 0, NULL
);
993 ID3D11DeviceContext_Release(immediate_context
);
994 ID3D11Device_Release(device
);
997 static HRESULT WINAPI
dxgi_surface_buffer_Lock(IMFMediaBuffer
*iface
, BYTE
**data
, DWORD
*max_length
,
998 DWORD
*current_length
)
1000 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
1003 TRACE("%p, %p, %p, %p.\n", iface
, data
, max_length
, current_length
);
1008 EnterCriticalSection(&buffer
->cs
);
1010 if (!buffer
->_2d
.linear_buffer
&& buffer
->_2d
.locks
)
1011 hr
= MF_E_INVALIDREQUEST
;
1012 else if (!buffer
->_2d
.linear_buffer
)
1014 if (!(buffer
->_2d
.linear_buffer
= malloc(buffer
->_2d
.plane_size
)))
1019 hr
= dxgi_surface_buffer_map(buffer
, MF2DBuffer_LockFlags_ReadWrite
);
1022 copy_image(buffer
, buffer
->_2d
.linear_buffer
, buffer
->_2d
.width
, buffer
->dxgi_surface
.map_desc
.pData
,
1023 buffer
->dxgi_surface
.map_desc
.RowPitch
, buffer
->_2d
.width
, buffer
->_2d
.height
);
1030 ++buffer
->_2d
.locks
;
1031 *data
= buffer
->_2d
.linear_buffer
;
1033 *max_length
= buffer
->_2d
.plane_size
;
1035 *current_length
= buffer
->_2d
.plane_size
;
1038 LeaveCriticalSection(&buffer
->cs
);
1043 static HRESULT WINAPI
dxgi_surface_buffer_Unlock(IMFMediaBuffer
*iface
)
1045 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
1048 TRACE("%p.\n", iface
);
1050 EnterCriticalSection(&buffer
->cs
);
1052 if (!buffer
->_2d
.linear_buffer
)
1053 hr
= HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED
);
1054 else if (!--buffer
->_2d
.locks
)
1056 copy_image(buffer
, buffer
->dxgi_surface
.map_desc
.pData
, buffer
->dxgi_surface
.map_desc
.RowPitch
,
1057 buffer
->_2d
.linear_buffer
, buffer
->_2d
.width
, buffer
->_2d
.width
, buffer
->_2d
.height
);
1058 dxgi_surface_buffer_unmap(buffer
, MF2DBuffer_LockFlags_ReadWrite
);
1060 free(buffer
->_2d
.linear_buffer
);
1061 buffer
->_2d
.linear_buffer
= NULL
;
1064 LeaveCriticalSection(&buffer
->cs
);
1069 static HRESULT WINAPI
dxgi_surface_buffer_SetCurrentLength(IMFMediaBuffer
*iface
, DWORD current_length
)
1071 struct buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
1073 TRACE("%p, %lu.\n", iface
, current_length
);
1075 buffer
->current_length
= current_length
;
1080 static HRESULT
dxgi_surface_buffer_lock(struct buffer
*buffer
, MF2DBuffer_LockFlags flags
,
1081 BYTE
**scanline0
, LONG
*pitch
, BYTE
**buffer_start
, DWORD
*buffer_length
)
1085 if (buffer
->_2d
.linear_buffer
)
1086 hr
= MF_E_UNEXPECTED
;
1087 else if (!buffer
->_2d
.locks
)
1088 hr
= dxgi_surface_buffer_map(buffer
, flags
);
1089 else if (buffer
->_2d
.lock_flags
== MF2DBuffer_LockFlags_Write
&& flags
!= MF2DBuffer_LockFlags_Write
)
1090 hr
= HRESULT_FROM_WIN32(ERROR_WAS_LOCKED
);
1094 if (!buffer
->_2d
.locks
)
1095 buffer
->_2d
.lock_flags
= flags
;
1097 buffer
->_2d
.lock_flags
|= flags
;
1098 buffer
->_2d
.locks
++;
1099 *scanline0
= buffer
->dxgi_surface
.map_desc
.pData
;
1100 *pitch
= buffer
->dxgi_surface
.map_desc
.RowPitch
;
1102 *buffer_start
= *scanline0
;
1104 *buffer_length
= buffer
->dxgi_surface
.map_desc
.DepthPitch
;
1110 static HRESULT WINAPI
dxgi_surface_buffer_Lock2D(IMF2DBuffer2
*iface
, BYTE
**scanline0
, LONG
*pitch
)
1112 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
1115 TRACE("%p, %p, %p.\n", iface
, scanline0
, pitch
);
1117 if (!scanline0
|| !pitch
)
1120 EnterCriticalSection(&buffer
->cs
);
1122 hr
= dxgi_surface_buffer_lock(buffer
, MF2DBuffer_LockFlags_ReadWrite
, scanline0
, pitch
, NULL
, NULL
);
1124 LeaveCriticalSection(&buffer
->cs
);
1129 static HRESULT WINAPI
dxgi_surface_buffer_Unlock2D(IMF2DBuffer2
*iface
)
1131 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
1134 TRACE("%p.\n", iface
);
1136 EnterCriticalSection(&buffer
->cs
);
1138 if (buffer
->_2d
.locks
)
1140 if (!--buffer
->_2d
.locks
)
1142 dxgi_surface_buffer_unmap(buffer
, buffer
->_2d
.lock_flags
);
1143 buffer
->_2d
.lock_flags
= 0;
1147 hr
= HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED
);
1149 LeaveCriticalSection(&buffer
->cs
);
1154 static HRESULT WINAPI
dxgi_surface_buffer_GetScanline0AndPitch(IMF2DBuffer2
*iface
, BYTE
**scanline0
, LONG
*pitch
)
1156 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
1159 TRACE("%p, %p, %p.\n", iface
, scanline0
, pitch
);
1161 if (!scanline0
|| !pitch
)
1164 EnterCriticalSection(&buffer
->cs
);
1166 if (!buffer
->_2d
.locks
)
1170 hr
= HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED
);
1174 *scanline0
= buffer
->dxgi_surface
.map_desc
.pData
;
1175 *pitch
= buffer
->dxgi_surface
.map_desc
.RowPitch
;
1178 LeaveCriticalSection(&buffer
->cs
);
1183 static HRESULT WINAPI
dxgi_surface_buffer_Lock2DSize(IMF2DBuffer2
*iface
, MF2DBuffer_LockFlags flags
,
1184 BYTE
**scanline0
, LONG
*pitch
, BYTE
**buffer_start
, DWORD
*buffer_length
)
1186 struct buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
1189 TRACE("%p, %#x, %p, %p, %p, %p.\n", iface
, flags
, scanline0
, pitch
, buffer_start
, buffer_length
);
1191 if (!scanline0
|| !pitch
|| !buffer_start
|| !buffer_length
)
1194 EnterCriticalSection(&buffer
->cs
);
1196 hr
= dxgi_surface_buffer_lock(buffer
, flags
, scanline0
, pitch
, buffer_start
, buffer_length
);
1198 LeaveCriticalSection(&buffer
->cs
);
1203 static HRESULT WINAPI
dxgi_buffer_QueryInterface(IMFDXGIBuffer
*iface
, REFIID riid
, void **obj
)
1205 struct buffer
*buffer
= impl_from_IMFDXGIBuffer(iface
);
1206 return IMFMediaBuffer_QueryInterface(&buffer
->IMFMediaBuffer_iface
, riid
, obj
);
1209 static ULONG WINAPI
dxgi_buffer_AddRef(IMFDXGIBuffer
*iface
)
1211 struct buffer
*buffer
= impl_from_IMFDXGIBuffer(iface
);
1212 return IMFMediaBuffer_AddRef(&buffer
->IMFMediaBuffer_iface
);
1215 static ULONG WINAPI
dxgi_buffer_Release(IMFDXGIBuffer
*iface
)
1217 struct buffer
*buffer
= impl_from_IMFDXGIBuffer(iface
);
1218 return IMFMediaBuffer_Release(&buffer
->IMFMediaBuffer_iface
);
1221 static HRESULT WINAPI
dxgi_buffer_GetResource(IMFDXGIBuffer
*iface
, REFIID riid
, void **obj
)
1223 struct buffer
*buffer
= impl_from_IMFDXGIBuffer(iface
);
1225 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
1227 return ID3D11Texture2D_QueryInterface(buffer
->dxgi_surface
.texture
, riid
, obj
);
1230 static HRESULT WINAPI
dxgi_buffer_GetSubresourceIndex(IMFDXGIBuffer
*iface
, UINT
*index
)
1232 struct buffer
*buffer
= impl_from_IMFDXGIBuffer(iface
);
1234 TRACE("%p, %p.\n", iface
, index
);
1239 *index
= buffer
->dxgi_surface
.sub_resource_idx
;
1244 static HRESULT WINAPI
dxgi_buffer_GetUnknown(IMFDXGIBuffer
*iface
, REFIID guid
, REFIID riid
, void **object
)
1246 struct buffer
*buffer
= impl_from_IMFDXGIBuffer(iface
);
1248 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(guid
), debugstr_guid(riid
), object
);
1250 if (attributes_GetUnknown(&buffer
->dxgi_surface
.attributes
, guid
, riid
, object
) == MF_E_ATTRIBUTENOTFOUND
)
1251 return MF_E_NOT_FOUND
;
1256 static HRESULT WINAPI
dxgi_buffer_SetUnknown(IMFDXGIBuffer
*iface
, REFIID guid
, IUnknown
*data
)
1258 struct buffer
*buffer
= impl_from_IMFDXGIBuffer(iface
);
1261 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(guid
), data
);
1263 EnterCriticalSection(&buffer
->dxgi_surface
.attributes
.cs
);
1266 if (SUCCEEDED(attributes_GetItem(&buffer
->dxgi_surface
.attributes
, guid
, NULL
)))
1267 hr
= HRESULT_FROM_WIN32(ERROR_OBJECT_ALREADY_EXISTS
);
1269 hr
= attributes_SetUnknown(&buffer
->dxgi_surface
.attributes
, guid
, data
);
1273 attributes_DeleteItem(&buffer
->dxgi_surface
.attributes
, guid
);
1275 LeaveCriticalSection(&buffer
->dxgi_surface
.attributes
.cs
);
1280 static const IMFMediaBufferVtbl dxgi_surface_1d_buffer_vtbl
=
1282 dxgi_1d_2d_buffer_QueryInterface
,
1283 memory_buffer_AddRef
,
1284 memory_buffer_Release
,
1285 dxgi_surface_buffer_Lock
,
1286 dxgi_surface_buffer_Unlock
,
1287 memory_buffer_GetCurrentLength
,
1288 dxgi_surface_buffer_SetCurrentLength
,
1289 memory_buffer_GetMaxLength
,
1292 static const IMF2DBuffer2Vtbl dxgi_surface_buffer_vtbl
=
1294 memory_2d_buffer_QueryInterface
,
1295 memory_2d_buffer_AddRef
,
1296 memory_2d_buffer_Release
,
1297 dxgi_surface_buffer_Lock2D
,
1298 dxgi_surface_buffer_Unlock2D
,
1299 dxgi_surface_buffer_GetScanline0AndPitch
,
1300 memory_2d_buffer_IsContiguousFormat
,
1301 memory_2d_buffer_GetContiguousLength
,
1302 memory_2d_buffer_ContiguousCopyTo
,
1303 memory_2d_buffer_ContiguousCopyFrom
,
1304 dxgi_surface_buffer_Lock2DSize
,
1305 memory_2d_buffer_Copy2DTo
,
1308 static const IMFDXGIBufferVtbl dxgi_buffer_vtbl
=
1310 dxgi_buffer_QueryInterface
,
1312 dxgi_buffer_Release
,
1313 dxgi_buffer_GetResource
,
1314 dxgi_buffer_GetSubresourceIndex
,
1315 dxgi_buffer_GetUnknown
,
1316 dxgi_buffer_SetUnknown
,
1319 static HRESULT
memory_buffer_init(struct buffer
*buffer
, DWORD max_length
, DWORD alignment
,
1320 const IMFMediaBufferVtbl
*vtbl
)
1322 if (alignment
< MF_16_BYTE_ALIGNMENT
)
1323 alignment
= MF_16_BYTE_ALIGNMENT
;
1326 if (alignment
& (alignment
- 1))
1329 alignment
|= alignment
>> 1;
1330 alignment
|= alignment
>> 2;
1331 alignment
|= alignment
>> 4;
1332 alignment
|= alignment
>> 8;
1333 alignment
|= alignment
>> 16;
1337 if (!(buffer
->data
= _aligned_malloc(max_length
, alignment
)))
1338 return E_OUTOFMEMORY
;
1339 memset(buffer
->data
, 0, max_length
);
1341 buffer
->IMFMediaBuffer_iface
.lpVtbl
= vtbl
;
1342 buffer
->refcount
= 1;
1343 buffer
->max_length
= max_length
;
1344 buffer
->current_length
= 0;
1345 InitializeCriticalSection(&buffer
->cs
);
1350 static HRESULT
create_1d_buffer(DWORD max_length
, DWORD alignment
, IMFMediaBuffer
**buffer
)
1352 struct buffer
*object
;
1360 if (!(object
= calloc(1, sizeof(*object
))))
1361 return E_OUTOFMEMORY
;
1363 hr
= memory_buffer_init(object
, max_length
, alignment
, &memory_1d_buffer_vtbl
);
1370 *buffer
= &object
->IMFMediaBuffer_iface
;
1375 static p_copy_image_func
get_2d_buffer_copy_func(DWORD fourcc
)
1379 case MAKEFOURCC('I','M','C','1'):
1380 case MAKEFOURCC('I','M','C','3'):
1381 return copy_image_imc1
;
1383 case MAKEFOURCC('I','M','C','2'):
1384 case MAKEFOURCC('I','M','C','4'):
1385 case MAKEFOURCC('N','V','1','1'):
1386 case MAKEFOURCC('Y','V','1','2'):
1387 case MAKEFOURCC('I','4','2','0'):
1388 case MAKEFOURCC('I','Y','U','V'):
1389 return copy_image_imc2
;
1391 case MAKEFOURCC('N','V','1','2'):
1392 return copy_image_nv12
;
1399 static HRESULT
create_2d_buffer(DWORD width
, DWORD height
, DWORD fourcc
, BOOL bottom_up
, IMFMediaBuffer
**buffer
)
1401 unsigned int stride
, max_length
;
1402 unsigned int row_alignment
;
1403 struct buffer
*object
;
1415 memcpy(&subtype
, &MFVideoFormat_Base
, sizeof(subtype
));
1416 subtype
.Data1
= fourcc
;
1418 if (!(stride
= mf_format_get_stride(&subtype
, width
, &is_yuv
)))
1419 return MF_E_INVALIDMEDIATYPE
;
1421 if (is_yuv
&& bottom_up
)
1422 return MF_E_INVALIDMEDIATYPE
;
1426 case MAKEFOURCC('I','M','C','1'):
1427 case MAKEFOURCC('I','M','C','3'):
1428 plane_size
= stride
* height
* 2;
1430 case MAKEFOURCC('I','M','C','2'):
1431 case MAKEFOURCC('I','M','C','4'):
1432 case MAKEFOURCC('N','V','1','1'):
1433 case MAKEFOURCC('Y','V','1','2'):
1434 case MAKEFOURCC('I','4','2','0'):
1435 case MAKEFOURCC('I','Y','U','V'):
1436 plane_size
= stride
* 3 / 2 * height
;
1438 case MAKEFOURCC('N','V','1','2'):
1439 plane_size
= stride
* height
* 3 / 2;
1442 plane_size
= stride
* height
;
1445 if (!(object
= calloc(1, sizeof(*object
))))
1446 return E_OUTOFMEMORY
;
1450 case MAKEFOURCC('I','M','C','1'):
1451 case MAKEFOURCC('I','M','C','2'):
1452 case MAKEFOURCC('I','M','C','3'):
1453 case MAKEFOURCC('I','M','C','4'):
1454 case MAKEFOURCC('Y','V','1','2'):
1455 case MAKEFOURCC('N','V','1','1'):
1456 case MAKEFOURCC('I','4','2','0'):
1457 case MAKEFOURCC('I','Y','U','V'):
1458 row_alignment
= MF_128_BYTE_ALIGNMENT
;
1461 row_alignment
= MF_64_BYTE_ALIGNMENT
;
1464 pitch
= ALIGN_SIZE(stride
, row_alignment
);
1468 case MAKEFOURCC('I','M','C','1'):
1469 case MAKEFOURCC('I','M','C','3'):
1470 max_length
= pitch
* height
* 2;
1472 case MAKEFOURCC('N','V','1','2'):
1473 case MAKEFOURCC('Y','V','1','2'):
1474 case MAKEFOURCC('I','M','C','2'):
1475 case MAKEFOURCC('I','M','C','4'):
1476 case MAKEFOURCC('N','V','1','1'):
1477 case MAKEFOURCC('I','4','2','0'):
1478 case MAKEFOURCC('I','Y','U','V'):
1479 max_length
= pitch
* height
* 3 / 2;
1482 max_length
= pitch
* height
;
1485 if (FAILED(hr
= memory_buffer_init(object
, max_length
, row_alignment
, &memory_1d_2d_buffer_vtbl
)))
1491 object
->IMF2DBuffer2_iface
.lpVtbl
= &memory_2d_buffer_vtbl
;
1492 object
->IMFGetService_iface
.lpVtbl
= &memory_2d_buffer_gs_vtbl
;
1493 object
->_2d
.plane_size
= plane_size
;
1494 object
->_2d
.width
= stride
;
1495 object
->_2d
.height
= height
;
1496 object
->_2d
.pitch
= bottom_up
? -pitch
: pitch
;
1497 object
->_2d
.scanline0
= bottom_up
? object
->data
+ pitch
* (object
->_2d
.height
- 1) : object
->data
;
1498 object
->_2d
.copy_image
= get_2d_buffer_copy_func(fourcc
);
1500 *buffer
= &object
->IMFMediaBuffer_iface
;
1505 static HRESULT
create_d3d9_surface_buffer(IUnknown
*surface
, BOOL bottom_up
, IMFMediaBuffer
**buffer
)
1507 struct buffer
*object
;
1508 D3DSURFACE_DESC desc
;
1509 unsigned int stride
;
1513 IDirect3DSurface9_GetDesc((IDirect3DSurface9
*)surface
, &desc
);
1514 TRACE("format %#x, %u x %u.\n", desc
.Format
, desc
.Width
, desc
.Height
);
1516 memcpy(&subtype
, &MFVideoFormat_Base
, sizeof(subtype
));
1517 subtype
.Data1
= desc
.Format
;
1519 if (!(stride
= mf_format_get_stride(&subtype
, desc
.Width
, &is_yuv
)))
1520 return MF_E_INVALIDMEDIATYPE
;
1522 if (!(object
= calloc(1, sizeof(*object
))))
1523 return E_OUTOFMEMORY
;
1525 object
->IMFMediaBuffer_iface
.lpVtbl
= &d3d9_surface_1d_buffer_vtbl
;
1526 object
->IMF2DBuffer2_iface
.lpVtbl
= &d3d9_surface_buffer_vtbl
;
1527 object
->IMFGetService_iface
.lpVtbl
= &d3d9_surface_buffer_gs_vtbl
;
1528 object
->refcount
= 1;
1529 InitializeCriticalSection(&object
->cs
);
1530 object
->d3d9_surface
.surface
= (IDirect3DSurface9
*)surface
;
1531 IUnknown_AddRef(surface
);
1533 MFGetPlaneSize(desc
.Format
, desc
.Width
, desc
.Height
, &object
->_2d
.plane_size
);
1534 object
->_2d
.width
= stride
;
1535 object
->_2d
.height
= desc
.Height
;
1536 object
->max_length
= object
->_2d
.plane_size
;
1537 object
->_2d
.copy_image
= get_2d_buffer_copy_func(desc
.Format
);
1539 *buffer
= &object
->IMFMediaBuffer_iface
;
1544 static HRESULT
create_dxgi_surface_buffer(IUnknown
*surface
, unsigned int sub_resource_idx
,
1545 BOOL bottom_up
, IMFMediaBuffer
**buffer
)
1547 struct buffer
*object
;
1548 D3D11_TEXTURE2D_DESC desc
;
1549 ID3D11Texture2D
*texture
;
1550 unsigned int stride
;
1556 if (FAILED(hr
= IUnknown_QueryInterface(surface
, &IID_ID3D11Texture2D
, (void **)&texture
)))
1558 WARN("Failed to get texture interface, hr %#lx.\n", hr
);
1562 ID3D11Texture2D_GetDesc(texture
, &desc
);
1563 TRACE("format %#x, %u x %u.\n", desc
.Format
, desc
.Width
, desc
.Height
);
1565 memcpy(&subtype
, &MFVideoFormat_Base
, sizeof(subtype
));
1566 subtype
.Data1
= format
= MFMapDXGIFormatToDX9Format(desc
.Format
);
1568 if (!(stride
= mf_format_get_stride(&subtype
, desc
.Width
, &is_yuv
)))
1570 ID3D11Texture2D_Release(texture
);
1571 return MF_E_INVALIDMEDIATYPE
;
1574 if (!(object
= calloc(1, sizeof(*object
))))
1576 ID3D11Texture2D_Release(texture
);
1577 return E_OUTOFMEMORY
;
1580 object
->IMFMediaBuffer_iface
.lpVtbl
= &dxgi_surface_1d_buffer_vtbl
;
1581 object
->IMF2DBuffer2_iface
.lpVtbl
= &dxgi_surface_buffer_vtbl
;
1582 object
->IMFDXGIBuffer_iface
.lpVtbl
= &dxgi_buffer_vtbl
;
1583 object
->refcount
= 1;
1584 InitializeCriticalSection(&object
->cs
);
1585 object
->dxgi_surface
.texture
= texture
;
1586 object
->dxgi_surface
.sub_resource_idx
= sub_resource_idx
;
1588 MFGetPlaneSize(format
, desc
.Width
, desc
.Height
, &object
->_2d
.plane_size
);
1589 object
->_2d
.width
= stride
;
1590 object
->_2d
.height
= desc
.Height
;
1591 object
->max_length
= object
->_2d
.plane_size
;
1592 object
->_2d
.copy_image
= get_2d_buffer_copy_func(format
);
1594 if (FAILED(hr
= init_attributes_object(&object
->dxgi_surface
.attributes
, 0)))
1596 IMFMediaBuffer_Release(&object
->IMFMediaBuffer_iface
);
1600 *buffer
= &object
->IMFMediaBuffer_iface
;
1605 /***********************************************************************
1606 * MFCreateMemoryBuffer (mfplat.@)
1608 HRESULT WINAPI
MFCreateMemoryBuffer(DWORD max_length
, IMFMediaBuffer
**buffer
)
1610 TRACE("%lu, %p.\n", max_length
, buffer
);
1612 return create_1d_buffer(max_length
, MF_1_BYTE_ALIGNMENT
, buffer
);
1615 /***********************************************************************
1616 * MFCreateAlignedMemoryBuffer (mfplat.@)
1618 HRESULT WINAPI
MFCreateAlignedMemoryBuffer(DWORD max_length
, DWORD alignment
, IMFMediaBuffer
**buffer
)
1620 TRACE("%lu, %lu, %p.\n", max_length
, alignment
, buffer
);
1622 return create_1d_buffer(max_length
, alignment
, buffer
);
1625 /***********************************************************************
1626 * MFCreate2DMediaBuffer (mfplat.@)
1628 HRESULT WINAPI
MFCreate2DMediaBuffer(DWORD width
, DWORD height
, DWORD fourcc
, BOOL bottom_up
, IMFMediaBuffer
**buffer
)
1630 TRACE("%lu, %lu, %s, %d, %p.\n", width
, height
, debugstr_fourcc(fourcc
), bottom_up
, buffer
);
1632 return create_2d_buffer(width
, height
, fourcc
, bottom_up
, buffer
);
1635 /***********************************************************************
1636 * MFCreateDXSurfaceBuffer (mfplat.@)
1638 HRESULT WINAPI
MFCreateDXSurfaceBuffer(REFIID riid
, IUnknown
*surface
, BOOL bottom_up
, IMFMediaBuffer
**buffer
)
1640 TRACE("%s, %p, %d, %p.\n", debugstr_guid(riid
), surface
, bottom_up
, buffer
);
1642 if (!IsEqualIID(riid
, &IID_IDirect3DSurface9
))
1643 return E_INVALIDARG
;
1645 return create_d3d9_surface_buffer(surface
, bottom_up
, buffer
);
1648 /***********************************************************************
1649 * MFCreateDXGISurfaceBuffer (mfplat.@)
1651 HRESULT WINAPI
MFCreateDXGISurfaceBuffer(REFIID riid
, IUnknown
*surface
, UINT subresource
, BOOL bottom_up
,
1652 IMFMediaBuffer
**buffer
)
1654 TRACE("%s, %p, %u, %d, %p.\n", debugstr_guid(riid
), surface
, subresource
, bottom_up
, buffer
);
1656 if (!IsEqualIID(riid
, &IID_ID3D11Texture2D
))
1657 return E_INVALIDARG
;
1659 return create_dxgi_surface_buffer(surface
, subresource
, bottom_up
, buffer
);
1662 static unsigned int buffer_get_aligned_length(unsigned int length
, unsigned int alignment
)
1664 length
= (length
+ alignment
) / alignment
;
1665 length
*= alignment
;
1670 HRESULT WINAPI
MFCreateMediaBufferFromMediaType(IMFMediaType
*media_type
, LONGLONG duration
, DWORD min_length
,
1671 DWORD alignment
, IMFMediaBuffer
**buffer
)
1673 UINT32 length
= 0, block_alignment
;
1674 LONGLONG avg_length
;
1678 TRACE("%p, %s, %lu, %lu, %p.\n", media_type
, debugstr_time(duration
), min_length
, alignment
, buffer
);
1681 return E_INVALIDARG
;
1683 if (FAILED(hr
= IMFMediaType_GetMajorType(media_type
, &major
)))
1686 if (IsEqualGUID(&major
, &MFMediaType_Audio
))
1688 block_alignment
= 0;
1689 if (FAILED(IMFMediaType_GetUINT32(media_type
, &MF_MT_AUDIO_BLOCK_ALIGNMENT
, &block_alignment
)))
1690 WARN("Block alignment was not specified.\n");
1692 alignment
= max(16, alignment
);
1694 if (block_alignment
)
1701 if (SUCCEEDED(IMFMediaType_GetUINT32(media_type
, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND
, &length
)))
1704 avg_length
= length
* duration
/ (10 * 1000 * 1000);
1708 length
= buffer_get_aligned_length(avg_length
+ 1, alignment
);
1709 length
= buffer_get_aligned_length(length
, block_alignment
);
1714 length
= max(length
, min_length
);
1716 return create_1d_buffer(length
, alignment
- 1, buffer
);
1719 FIXME("Major type %s is not supported.\n", debugstr_guid(&major
));