2 * Copyright 2018 Alistair Leslie-Hughes
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 #include "mfplat_private.h"
29 #include "wine/debug.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(mfplat
);
33 #define ALIGN_SIZE(size, alignment) (((size) + (alignment)) & ~((alignment)))
37 IMFMediaBuffer IMFMediaBuffer_iface
;
38 IMF2DBuffer2 IMF2DBuffer2_iface
;
39 IMFDXGIBuffer IMFDXGIBuffer_iface
;
40 IMFGetService IMFGetService_iface
;
50 unsigned int plane_size
;
61 IDirect3DSurface9
*surface
;
67 unsigned int subresource
;
68 struct attributes attributes
;
74 static inline struct memory_buffer
*impl_from_IMFMediaBuffer(IMFMediaBuffer
*iface
)
76 return CONTAINING_RECORD(iface
, struct memory_buffer
, IMFMediaBuffer_iface
);
79 static struct memory_buffer
*impl_from_IMF2DBuffer2(IMF2DBuffer2
*iface
)
81 return CONTAINING_RECORD(iface
, struct memory_buffer
, IMF2DBuffer2_iface
);
84 static struct memory_buffer
*impl_from_IMFGetService(IMFGetService
*iface
)
86 return CONTAINING_RECORD(iface
, struct memory_buffer
, IMFGetService_iface
);
89 static struct memory_buffer
*impl_from_IMFDXGIBuffer(IMFDXGIBuffer
*iface
)
91 return CONTAINING_RECORD(iface
, struct memory_buffer
, IMFDXGIBuffer_iface
);
94 static HRESULT WINAPI
memory_buffer_QueryInterface(IMFMediaBuffer
*iface
, REFIID riid
, void **out
)
96 struct memory_buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
98 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), out
);
100 if (IsEqualIID(riid
, &IID_IMFMediaBuffer
) ||
101 IsEqualIID(riid
, &IID_IUnknown
))
103 *out
= &buffer
->IMFMediaBuffer_iface
;
104 IMFMediaBuffer_AddRef(iface
);
108 WARN("Unsupported %s.\n", debugstr_guid(riid
));
110 return E_NOINTERFACE
;
113 static ULONG WINAPI
memory_buffer_AddRef(IMFMediaBuffer
*iface
)
115 struct memory_buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
116 ULONG refcount
= InterlockedIncrement(&buffer
->refcount
);
118 TRACE("%p, refcount %u.\n", buffer
, refcount
);
123 static ULONG WINAPI
memory_buffer_Release(IMFMediaBuffer
*iface
)
125 struct memory_buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
126 ULONG refcount
= InterlockedDecrement(&buffer
->refcount
);
128 TRACE("%p, refcount %u.\n", iface
, refcount
);
132 if (buffer
->d3d9_surface
.surface
)
133 IDirect3DSurface9_Release(buffer
->d3d9_surface
.surface
);
134 if (buffer
->dxgi_surface
.surface
)
136 IUnknown_Release(buffer
->dxgi_surface
.surface
);
137 clear_attributes_object(&buffer
->dxgi_surface
.attributes
);
139 DeleteCriticalSection(&buffer
->cs
);
140 heap_free(buffer
->_2d
.linear_buffer
);
141 heap_free(buffer
->data
);
148 static HRESULT WINAPI
memory_buffer_Lock(IMFMediaBuffer
*iface
, BYTE
**data
, DWORD
*max_length
, DWORD
*current_length
)
150 struct memory_buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
152 TRACE("%p, %p %p, %p.\n", iface
, data
, max_length
, current_length
);
157 *data
= buffer
->data
;
159 *max_length
= buffer
->max_length
;
161 *current_length
= buffer
->current_length
;
166 static HRESULT WINAPI
memory_buffer_Unlock(IMFMediaBuffer
*iface
)
168 TRACE("%p.\n", iface
);
173 static HRESULT WINAPI
memory_buffer_GetCurrentLength(IMFMediaBuffer
*iface
, DWORD
*current_length
)
175 struct memory_buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
177 TRACE("%p.\n", iface
);
182 *current_length
= buffer
->current_length
;
187 static HRESULT WINAPI
memory_buffer_SetCurrentLength(IMFMediaBuffer
*iface
, DWORD current_length
)
189 struct memory_buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
191 TRACE("%p, %u.\n", iface
, current_length
);
193 if (current_length
> buffer
->max_length
)
196 buffer
->current_length
= current_length
;
201 static HRESULT WINAPI
memory_buffer_GetMaxLength(IMFMediaBuffer
*iface
, DWORD
*max_length
)
203 struct memory_buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
205 TRACE("%p, %p.\n", iface
, max_length
);
210 *max_length
= buffer
->max_length
;
215 static const IMFMediaBufferVtbl memory_1d_buffer_vtbl
=
217 memory_buffer_QueryInterface
,
218 memory_buffer_AddRef
,
219 memory_buffer_Release
,
221 memory_buffer_Unlock
,
222 memory_buffer_GetCurrentLength
,
223 memory_buffer_SetCurrentLength
,
224 memory_buffer_GetMaxLength
,
227 static HRESULT WINAPI
memory_1d_2d_buffer_QueryInterface(IMFMediaBuffer
*iface
, REFIID riid
, void **out
)
229 struct memory_buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
231 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), out
);
233 if (IsEqualIID(riid
, &IID_IMFMediaBuffer
) ||
234 IsEqualIID(riid
, &IID_IUnknown
))
236 *out
= &buffer
->IMFMediaBuffer_iface
;
238 else if (IsEqualIID(riid
, &IID_IMF2DBuffer2
) ||
239 IsEqualIID(riid
, &IID_IMF2DBuffer
))
241 *out
= &buffer
->IMF2DBuffer2_iface
;
243 else if (IsEqualIID(riid
, &IID_IMFGetService
))
245 *out
= &buffer
->IMFGetService_iface
;
249 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
251 return E_NOINTERFACE
;
254 IUnknown_AddRef((IUnknown
*)*out
);
258 static HRESULT WINAPI
memory_1d_2d_buffer_Lock(IMFMediaBuffer
*iface
, BYTE
**data
, DWORD
*max_length
, DWORD
*current_length
)
260 struct memory_buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
263 TRACE("%p, %p, %p, %p.\n", iface
, data
, max_length
, current_length
);
268 /* Allocate linear buffer and return it as a copy of current content. Maximum and current length are
269 unrelated to 2D buffer maximum allocate length, or maintained current length. */
271 EnterCriticalSection(&buffer
->cs
);
273 if (!buffer
->_2d
.linear_buffer
&& buffer
->_2d
.locks
)
274 hr
= MF_E_INVALIDREQUEST
;
275 else if (!buffer
->_2d
.linear_buffer
)
277 if (!(buffer
->_2d
.linear_buffer
= heap_alloc(ALIGN_SIZE(buffer
->_2d
.plane_size
, MF_64_BYTE_ALIGNMENT
))))
284 *data
= buffer
->_2d
.linear_buffer
;
286 *max_length
= buffer
->_2d
.plane_size
;
288 *current_length
= buffer
->_2d
.plane_size
;
291 LeaveCriticalSection(&buffer
->cs
);
296 static HRESULT WINAPI
memory_1d_2d_buffer_Unlock(IMFMediaBuffer
*iface
)
298 struct memory_buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
300 TRACE("%p.\n", iface
);
302 EnterCriticalSection(&buffer
->cs
);
304 if (buffer
->_2d
.linear_buffer
&& !--buffer
->_2d
.locks
)
306 MFCopyImage(buffer
->data
, buffer
->_2d
.pitch
, buffer
->_2d
.linear_buffer
, buffer
->_2d
.width
,
307 buffer
->_2d
.width
, buffer
->_2d
.height
);
309 heap_free(buffer
->_2d
.linear_buffer
);
310 buffer
->_2d
.linear_buffer
= NULL
;
313 LeaveCriticalSection(&buffer
->cs
);
318 static const IMFMediaBufferVtbl memory_1d_2d_buffer_vtbl
=
320 memory_1d_2d_buffer_QueryInterface
,
321 memory_buffer_AddRef
,
322 memory_buffer_Release
,
323 memory_1d_2d_buffer_Lock
,
324 memory_1d_2d_buffer_Unlock
,
325 memory_buffer_GetCurrentLength
,
326 memory_buffer_SetCurrentLength
,
327 memory_buffer_GetMaxLength
,
330 static HRESULT WINAPI
d3d9_surface_buffer_Lock(IMFMediaBuffer
*iface
, BYTE
**data
, DWORD
*max_length
, DWORD
*current_length
)
332 struct memory_buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
335 TRACE("%p, %p, %p, %p.\n", iface
, data
, max_length
, current_length
);
340 EnterCriticalSection(&buffer
->cs
);
342 if (!buffer
->_2d
.linear_buffer
&& buffer
->_2d
.locks
)
343 hr
= MF_E_INVALIDREQUEST
;
344 else if (!buffer
->_2d
.linear_buffer
)
348 if (!(buffer
->_2d
.linear_buffer
= heap_alloc(ALIGN_SIZE(buffer
->_2d
.plane_size
, MF_64_BYTE_ALIGNMENT
))))
353 hr
= IDirect3DSurface9_LockRect(buffer
->d3d9_surface
.surface
, &rect
, NULL
, 0);
356 MFCopyImage(buffer
->_2d
.linear_buffer
, buffer
->_2d
.width
, rect
.pBits
, rect
.Pitch
,
357 buffer
->_2d
.width
, buffer
->_2d
.height
);
358 IDirect3DSurface9_UnlockRect(buffer
->d3d9_surface
.surface
);
366 *data
= buffer
->_2d
.linear_buffer
;
368 *max_length
= buffer
->_2d
.plane_size
;
370 *current_length
= buffer
->_2d
.plane_size
;
373 LeaveCriticalSection(&buffer
->cs
);
378 static HRESULT WINAPI
d3d9_surface_buffer_Unlock(IMFMediaBuffer
*iface
)
380 struct memory_buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
383 TRACE("%p.\n", iface
);
385 EnterCriticalSection(&buffer
->cs
);
387 if (!buffer
->_2d
.linear_buffer
)
388 hr
= HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED
);
389 else if (!--buffer
->_2d
.locks
)
393 if (SUCCEEDED(hr
= IDirect3DSurface9_LockRect(buffer
->d3d9_surface
.surface
, &rect
, NULL
, 0)))
395 MFCopyImage(rect
.pBits
, rect
.Pitch
, buffer
->_2d
.linear_buffer
, buffer
->_2d
.width
,
396 buffer
->_2d
.width
, buffer
->_2d
.height
);
397 IDirect3DSurface9_UnlockRect(buffer
->d3d9_surface
.surface
);
400 heap_free(buffer
->_2d
.linear_buffer
);
401 buffer
->_2d
.linear_buffer
= NULL
;
404 LeaveCriticalSection(&buffer
->cs
);
409 static const IMFMediaBufferVtbl d3d9_surface_1d_buffer_vtbl
=
411 memory_1d_2d_buffer_QueryInterface
,
412 memory_buffer_AddRef
,
413 memory_buffer_Release
,
414 d3d9_surface_buffer_Lock
,
415 d3d9_surface_buffer_Unlock
,
416 memory_buffer_GetCurrentLength
,
417 memory_buffer_SetCurrentLength
,
418 memory_buffer_GetMaxLength
,
421 static HRESULT WINAPI
memory_2d_buffer_QueryInterface(IMF2DBuffer2
*iface
, REFIID riid
, void **obj
)
423 struct memory_buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
424 return IMFMediaBuffer_QueryInterface(&buffer
->IMFMediaBuffer_iface
, riid
, obj
);
427 static ULONG WINAPI
memory_2d_buffer_AddRef(IMF2DBuffer2
*iface
)
429 struct memory_buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
430 return IMFMediaBuffer_AddRef(&buffer
->IMFMediaBuffer_iface
);
433 static ULONG WINAPI
memory_2d_buffer_Release(IMF2DBuffer2
*iface
)
435 struct memory_buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
436 return IMFMediaBuffer_Release(&buffer
->IMFMediaBuffer_iface
);
439 static HRESULT
memory_2d_buffer_lock(struct memory_buffer
*buffer
, BYTE
**scanline0
, LONG
*pitch
,
440 BYTE
**buffer_start
, DWORD
*buffer_length
)
444 if (buffer
->_2d
.linear_buffer
)
445 hr
= MF_E_UNEXPECTED
;
449 *scanline0
= buffer
->_2d
.scanline0
;
450 *pitch
= buffer
->_2d
.pitch
;
452 *buffer_start
= buffer
->data
;
454 *buffer_length
= buffer
->max_length
;
460 static HRESULT WINAPI
memory_2d_buffer_Lock2D(IMF2DBuffer2
*iface
, BYTE
**scanline0
, LONG
*pitch
)
462 struct memory_buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
465 TRACE("%p, %p, %p.\n", iface
, scanline0
, pitch
);
467 if (!scanline0
|| !pitch
)
470 EnterCriticalSection(&buffer
->cs
);
472 hr
= memory_2d_buffer_lock(buffer
, scanline0
, pitch
, NULL
, NULL
);
474 LeaveCriticalSection(&buffer
->cs
);
479 static HRESULT WINAPI
memory_2d_buffer_Unlock2D(IMF2DBuffer2
*iface
)
481 struct memory_buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
484 TRACE("%p.\n", iface
);
486 EnterCriticalSection(&buffer
->cs
);
488 if (!buffer
->_2d
.linear_buffer
)
490 if (buffer
->_2d
.locks
)
493 hr
= HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED
);
496 LeaveCriticalSection(&buffer
->cs
);
501 static HRESULT WINAPI
memory_2d_buffer_GetScanline0AndPitch(IMF2DBuffer2
*iface
, BYTE
**scanline0
, LONG
*pitch
)
503 struct memory_buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
506 TRACE("%p, %p, %p.\n", iface
, scanline0
, pitch
);
508 if (!scanline0
|| !pitch
)
511 EnterCriticalSection(&buffer
->cs
);
513 if (buffer
->_2d
.linear_buffer
|| !buffer
->_2d
.locks
)
514 hr
= HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED
);
517 *scanline0
= buffer
->_2d
.scanline0
;
518 *pitch
= buffer
->_2d
.pitch
;
521 LeaveCriticalSection(&buffer
->cs
);
526 static HRESULT WINAPI
memory_2d_buffer_IsContiguousFormat(IMF2DBuffer2
*iface
, BOOL
*is_contiguous
)
528 TRACE("%p, %p.\n", iface
, is_contiguous
);
533 *is_contiguous
= FALSE
;
538 static HRESULT WINAPI
memory_2d_buffer_GetContiguousLength(IMF2DBuffer2
*iface
, DWORD
*length
)
540 struct memory_buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
542 TRACE("%p, %p.\n", iface
, length
);
547 *length
= buffer
->_2d
.plane_size
;
552 static HRESULT WINAPI
memory_2d_buffer_ContiguousCopyTo(IMF2DBuffer2
*iface
, BYTE
*dest_buffer
, DWORD dest_length
)
554 FIXME("%p, %p, %u.\n", iface
, dest_buffer
, dest_length
);
559 static HRESULT WINAPI
memory_2d_buffer_ContiguousCopyFrom(IMF2DBuffer2
*iface
, const BYTE
*src_buffer
, DWORD src_length
)
561 FIXME("%p, %p, %u.\n", iface
, src_buffer
, src_length
);
566 static HRESULT WINAPI
memory_2d_buffer_Lock2DSize(IMF2DBuffer2
*iface
, MF2DBuffer_LockFlags flags
, BYTE
**scanline0
,
567 LONG
*pitch
, BYTE
**buffer_start
, DWORD
*buffer_length
)
569 struct memory_buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
572 TRACE("%p, %#x, %p, %p, %p, %p.\n", iface
, flags
, scanline0
, pitch
, buffer_start
, buffer_length
);
574 if (!scanline0
|| !pitch
|| !buffer_start
|| !buffer_length
)
577 EnterCriticalSection(&buffer
->cs
);
579 hr
= memory_2d_buffer_lock(buffer
, scanline0
, pitch
, buffer_start
, buffer_length
);
581 LeaveCriticalSection(&buffer
->cs
);
586 static HRESULT WINAPI
memory_2d_buffer_Copy2DTo(IMF2DBuffer2
*iface
, IMF2DBuffer2
*dest_buffer
)
588 FIXME("%p, %p.\n", iface
, dest_buffer
);
593 static const IMF2DBuffer2Vtbl memory_2d_buffer_vtbl
=
595 memory_2d_buffer_QueryInterface
,
596 memory_2d_buffer_AddRef
,
597 memory_2d_buffer_Release
,
598 memory_2d_buffer_Lock2D
,
599 memory_2d_buffer_Unlock2D
,
600 memory_2d_buffer_GetScanline0AndPitch
,
601 memory_2d_buffer_IsContiguousFormat
,
602 memory_2d_buffer_GetContiguousLength
,
603 memory_2d_buffer_ContiguousCopyTo
,
604 memory_2d_buffer_ContiguousCopyFrom
,
605 memory_2d_buffer_Lock2DSize
,
606 memory_2d_buffer_Copy2DTo
,
609 static HRESULT WINAPI
d3d9_surface_buffer_Lock2D(IMF2DBuffer2
*iface
, BYTE
**scanline0
, LONG
*pitch
)
611 struct memory_buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
614 TRACE("%p, %p, %p.\n", iface
, scanline0
, pitch
);
616 if (!scanline0
|| !pitch
)
619 EnterCriticalSection(&buffer
->cs
);
621 if (buffer
->_2d
.linear_buffer
)
622 hr
= MF_E_UNEXPECTED
;
623 else if (!buffer
->_2d
.locks
++)
625 hr
= IDirect3DSurface9_LockRect(buffer
->d3d9_surface
.surface
, &buffer
->d3d9_surface
.rect
, NULL
, 0);
630 *scanline0
= buffer
->d3d9_surface
.rect
.pBits
;
631 *pitch
= buffer
->d3d9_surface
.rect
.Pitch
;
634 LeaveCriticalSection(&buffer
->cs
);
639 static HRESULT WINAPI
d3d9_surface_buffer_Unlock2D(IMF2DBuffer2
*iface
)
641 struct memory_buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
644 TRACE("%p.\n", iface
);
646 EnterCriticalSection(&buffer
->cs
);
648 if (buffer
->_2d
.locks
)
650 if (!--buffer
->_2d
.locks
)
652 IDirect3DSurface9_UnlockRect(buffer
->d3d9_surface
.surface
);
653 memset(&buffer
->d3d9_surface
.rect
, 0, sizeof(buffer
->d3d9_surface
.rect
));
657 hr
= HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED
);
659 LeaveCriticalSection(&buffer
->cs
);
664 static HRESULT WINAPI
d3d9_surface_buffer_GetScanline0AndPitch(IMF2DBuffer2
*iface
, BYTE
**scanline0
, LONG
*pitch
)
666 struct memory_buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
669 TRACE("%p, %p, %p.\n", iface
, scanline0
, pitch
);
671 if (!scanline0
|| !pitch
)
674 EnterCriticalSection(&buffer
->cs
);
676 if (!buffer
->_2d
.locks
)
677 hr
= HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED
);
680 *scanline0
= buffer
->d3d9_surface
.rect
.pBits
;
681 *pitch
= buffer
->d3d9_surface
.rect
.Pitch
;
684 LeaveCriticalSection(&buffer
->cs
);
689 static HRESULT WINAPI
d3d9_surface_buffer_GetContiguousLength(IMF2DBuffer2
*iface
, DWORD
*length
)
691 FIXME("%p, %p.\n", iface
, length
);
696 static HRESULT WINAPI
d3d9_surface_buffer_Lock2DSize(IMF2DBuffer2
*iface
, MF2DBuffer_LockFlags flags
, BYTE
**scanline0
,
697 LONG
*pitch
, BYTE
**buffer_start
, DWORD
*buffer_length
)
699 struct memory_buffer
*buffer
= impl_from_IMF2DBuffer2(iface
);
702 TRACE("%p, %#x, %p, %p, %p, %p.\n", iface
, flags
, scanline0
, pitch
, buffer_start
, buffer_length
);
704 if (!scanline0
|| !pitch
|| !buffer_start
|| !buffer_length
)
707 EnterCriticalSection(&buffer
->cs
);
709 if (buffer
->_2d
.linear_buffer
)
710 hr
= MF_E_UNEXPECTED
;
711 else if (!buffer
->_2d
.locks
++)
713 hr
= IDirect3DSurface9_LockRect(buffer
->d3d9_surface
.surface
, &buffer
->d3d9_surface
.rect
, NULL
, 0);
718 *scanline0
= buffer
->d3d9_surface
.rect
.pBits
;
719 *pitch
= buffer
->d3d9_surface
.rect
.Pitch
;
721 *buffer_start
= *scanline0
;
723 *buffer_length
= buffer
->d3d9_surface
.rect
.Pitch
* buffer
->_2d
.height
;
726 LeaveCriticalSection(&buffer
->cs
);
731 static const IMF2DBuffer2Vtbl d3d9_surface_buffer_vtbl
=
733 memory_2d_buffer_QueryInterface
,
734 memory_2d_buffer_AddRef
,
735 memory_2d_buffer_Release
,
736 d3d9_surface_buffer_Lock2D
,
737 d3d9_surface_buffer_Unlock2D
,
738 d3d9_surface_buffer_GetScanline0AndPitch
,
739 memory_2d_buffer_IsContiguousFormat
,
740 d3d9_surface_buffer_GetContiguousLength
,
741 memory_2d_buffer_ContiguousCopyTo
,
742 memory_2d_buffer_ContiguousCopyFrom
,
743 d3d9_surface_buffer_Lock2DSize
,
744 memory_2d_buffer_Copy2DTo
,
747 static HRESULT WINAPI
memory_2d_buffer_gs_QueryInterface(IMFGetService
*iface
, REFIID riid
, void **obj
)
749 struct memory_buffer
*buffer
= impl_from_IMFGetService(iface
);
750 return IMFMediaBuffer_QueryInterface(&buffer
->IMFMediaBuffer_iface
, riid
, obj
);
753 static ULONG WINAPI
memory_2d_buffer_gs_AddRef(IMFGetService
*iface
)
755 struct memory_buffer
*buffer
= impl_from_IMFGetService(iface
);
756 return IMFMediaBuffer_AddRef(&buffer
->IMFMediaBuffer_iface
);
759 static ULONG WINAPI
memory_2d_buffer_gs_Release(IMFGetService
*iface
)
761 struct memory_buffer
*buffer
= impl_from_IMFGetService(iface
);
762 return IMFMediaBuffer_Release(&buffer
->IMFMediaBuffer_iface
);
765 static HRESULT WINAPI
memory_2d_buffer_gs_GetService(IMFGetService
*iface
, REFGUID service
, REFIID riid
, void **obj
)
767 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(service
), debugstr_guid(riid
), obj
);
772 static const IMFGetServiceVtbl memory_2d_buffer_gs_vtbl
=
774 memory_2d_buffer_gs_QueryInterface
,
775 memory_2d_buffer_gs_AddRef
,
776 memory_2d_buffer_gs_Release
,
777 memory_2d_buffer_gs_GetService
,
780 static HRESULT WINAPI
d3d9_surface_buffer_gs_GetService(IMFGetService
*iface
, REFGUID service
, REFIID riid
, void **obj
)
782 struct memory_buffer
*buffer
= impl_from_IMFGetService(iface
);
784 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(service
), debugstr_guid(riid
), obj
);
786 if (IsEqualGUID(service
, &MR_BUFFER_SERVICE
))
788 return IDirect3DSurface9_QueryInterface(buffer
->d3d9_surface
.surface
, riid
, obj
);
794 static const IMFGetServiceVtbl d3d9_surface_buffer_gs_vtbl
=
796 memory_2d_buffer_gs_QueryInterface
,
797 memory_2d_buffer_gs_AddRef
,
798 memory_2d_buffer_gs_Release
,
799 d3d9_surface_buffer_gs_GetService
,
802 static HRESULT WINAPI
dxgi_1d_2d_buffer_QueryInterface(IMFMediaBuffer
*iface
, REFIID riid
, void **out
)
804 struct memory_buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
806 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), out
);
808 if (IsEqualIID(riid
, &IID_IMFMediaBuffer
) ||
809 IsEqualIID(riid
, &IID_IUnknown
))
811 *out
= &buffer
->IMFMediaBuffer_iface
;
813 else if (IsEqualIID(riid
, &IID_IMF2DBuffer2
) ||
814 IsEqualIID(riid
, &IID_IMF2DBuffer
))
816 *out
= &buffer
->IMF2DBuffer2_iface
;
818 else if (IsEqualIID(riid
, &IID_IMFDXGIBuffer
))
820 *out
= &buffer
->IMFDXGIBuffer_iface
;
824 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
826 return E_NOINTERFACE
;
829 IUnknown_AddRef((IUnknown
*)*out
);
833 static HRESULT WINAPI
dxgi_surface_buffer_Lock(IMFMediaBuffer
*iface
, BYTE
**data
, DWORD
*max_length
,
834 DWORD
*current_length
)
836 FIXME("%p, %p, %p, %p.\n", iface
, data
, max_length
, current_length
);
841 static HRESULT WINAPI
dxgi_surface_buffer_Unlock(IMFMediaBuffer
*iface
)
843 FIXME("%p.\n", iface
);
848 static HRESULT WINAPI
dxgi_surface_buffer_Lock2D(IMF2DBuffer2
*iface
, BYTE
**scanline0
, LONG
*pitch
)
850 FIXME("%p, %p, %p.\n", iface
, scanline0
, pitch
);
855 static HRESULT WINAPI
dxgi_surface_buffer_Unlock2D(IMF2DBuffer2
*iface
)
857 FIXME("%p.\n", iface
);
862 static HRESULT WINAPI
dxgi_surface_buffer_GetScanline0AndPitch(IMF2DBuffer2
*iface
, BYTE
**scanline0
, LONG
*pitch
)
864 FIXME("%p, %p, %p.\n", iface
, scanline0
, pitch
);
869 static HRESULT WINAPI
dxgi_surface_buffer_GetContiguousLength(IMF2DBuffer2
*iface
, DWORD
*length
)
871 FIXME("%p, %p.\n", iface
, length
);
876 static HRESULT WINAPI
dxgi_surface_buffer_Lock2DSize(IMF2DBuffer2
*iface
, MF2DBuffer_LockFlags flags
,
877 BYTE
**scanline0
, LONG
*pitch
, BYTE
**buffer_start
, DWORD
*buffer_length
)
879 FIXME("%p, %#x, %p, %p, %p, %p.\n", iface
, flags
, scanline0
, pitch
, buffer_start
, buffer_length
);
884 static HRESULT WINAPI
dxgi_buffer_QueryInterface(IMFDXGIBuffer
*iface
, REFIID riid
, void **obj
)
886 struct memory_buffer
*buffer
= impl_from_IMFDXGIBuffer(iface
);
887 return IMFMediaBuffer_QueryInterface(&buffer
->IMFMediaBuffer_iface
, riid
, obj
);
890 static ULONG WINAPI
dxgi_buffer_AddRef(IMFDXGIBuffer
*iface
)
892 struct memory_buffer
*buffer
= impl_from_IMFDXGIBuffer(iface
);
893 return IMFMediaBuffer_AddRef(&buffer
->IMFMediaBuffer_iface
);
896 static ULONG WINAPI
dxgi_buffer_Release(IMFDXGIBuffer
*iface
)
898 struct memory_buffer
*buffer
= impl_from_IMFDXGIBuffer(iface
);
899 return IMFMediaBuffer_Release(&buffer
->IMFMediaBuffer_iface
);
902 static HRESULT WINAPI
dxgi_buffer_GetResource(IMFDXGIBuffer
*iface
, REFIID riid
, void **obj
)
904 struct memory_buffer
*buffer
= impl_from_IMFDXGIBuffer(iface
);
906 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
908 return IUnknown_QueryInterface(buffer
->dxgi_surface
.surface
, riid
, obj
);
911 static HRESULT WINAPI
dxgi_buffer_GetSubresourceIndex(IMFDXGIBuffer
*iface
, UINT
*index
)
913 struct memory_buffer
*buffer
= impl_from_IMFDXGIBuffer(iface
);
915 TRACE("%p, %p.\n", iface
, index
);
920 *index
= buffer
->dxgi_surface
.subresource
;
925 static HRESULT WINAPI
dxgi_buffer_GetUnknown(IMFDXGIBuffer
*iface
, REFIID guid
, REFIID riid
, void **object
)
927 struct memory_buffer
*buffer
= impl_from_IMFDXGIBuffer(iface
);
929 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(guid
), debugstr_guid(riid
), object
);
931 if (attributes_GetUnknown(&buffer
->dxgi_surface
.attributes
, guid
, riid
, object
) == MF_E_ATTRIBUTENOTFOUND
)
932 return MF_E_NOT_FOUND
;
937 static HRESULT WINAPI
dxgi_buffer_SetUnknown(IMFDXGIBuffer
*iface
, REFIID guid
, IUnknown
*data
)
939 struct memory_buffer
*buffer
= impl_from_IMFDXGIBuffer(iface
);
942 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(guid
), data
);
944 EnterCriticalSection(&buffer
->dxgi_surface
.attributes
.cs
);
947 if (SUCCEEDED(attributes_GetItem(&buffer
->dxgi_surface
.attributes
, guid
, NULL
)))
948 hr
= HRESULT_FROM_WIN32(ERROR_OBJECT_ALREADY_EXISTS
);
950 hr
= attributes_SetUnknown(&buffer
->dxgi_surface
.attributes
, guid
, data
);
954 attributes_DeleteItem(&buffer
->dxgi_surface
.attributes
, guid
);
956 LeaveCriticalSection(&buffer
->dxgi_surface
.attributes
.cs
);
961 static const IMFMediaBufferVtbl dxgi_surface_1d_buffer_vtbl
=
963 dxgi_1d_2d_buffer_QueryInterface
,
964 memory_buffer_AddRef
,
965 memory_buffer_Release
,
966 dxgi_surface_buffer_Lock
,
967 dxgi_surface_buffer_Unlock
,
968 memory_buffer_GetCurrentLength
,
969 memory_buffer_SetCurrentLength
,
970 memory_buffer_GetMaxLength
,
973 static const IMF2DBuffer2Vtbl dxgi_surface_buffer_vtbl
=
975 memory_2d_buffer_QueryInterface
,
976 memory_2d_buffer_AddRef
,
977 memory_2d_buffer_Release
,
978 dxgi_surface_buffer_Lock2D
,
979 dxgi_surface_buffer_Unlock2D
,
980 dxgi_surface_buffer_GetScanline0AndPitch
,
981 memory_2d_buffer_IsContiguousFormat
,
982 dxgi_surface_buffer_GetContiguousLength
,
983 memory_2d_buffer_ContiguousCopyTo
,
984 memory_2d_buffer_ContiguousCopyFrom
,
985 dxgi_surface_buffer_Lock2DSize
,
986 memory_2d_buffer_Copy2DTo
,
989 static const IMFDXGIBufferVtbl dxgi_buffer_vtbl
=
991 dxgi_buffer_QueryInterface
,
994 dxgi_buffer_GetResource
,
995 dxgi_buffer_GetSubresourceIndex
,
996 dxgi_buffer_GetUnknown
,
997 dxgi_buffer_SetUnknown
,
1000 static HRESULT
memory_buffer_init(struct memory_buffer
*buffer
, DWORD max_length
, DWORD alignment
,
1001 const IMFMediaBufferVtbl
*vtbl
)
1003 buffer
->data
= heap_alloc_zero(ALIGN_SIZE(max_length
, alignment
));
1005 return E_OUTOFMEMORY
;
1007 buffer
->IMFMediaBuffer_iface
.lpVtbl
= vtbl
;
1008 buffer
->refcount
= 1;
1009 buffer
->max_length
= max_length
;
1010 buffer
->current_length
= 0;
1011 InitializeCriticalSection(&buffer
->cs
);
1016 static HRESULT
create_1d_buffer(DWORD max_length
, DWORD alignment
, IMFMediaBuffer
**buffer
)
1018 struct memory_buffer
*object
;
1026 object
= heap_alloc_zero(sizeof(*object
));
1028 return E_OUTOFMEMORY
;
1030 hr
= memory_buffer_init(object
, max_length
, alignment
, &memory_1d_buffer_vtbl
);
1037 *buffer
= &object
->IMFMediaBuffer_iface
;
1042 static HRESULT
create_2d_buffer(DWORD width
, DWORD height
, DWORD fourcc
, BOOL bottom_up
, IMFMediaBuffer
**buffer
)
1044 unsigned int stride
, max_length
, plane_size
;
1045 struct memory_buffer
*object
;
1046 unsigned int row_alignment
;
1057 memcpy(&subtype
, &MFVideoFormat_Base
, sizeof(subtype
));
1058 subtype
.Data1
= fourcc
;
1060 if (!(stride
= mf_format_get_stride(&subtype
, width
, &is_yuv
)))
1061 return MF_E_INVALIDMEDIATYPE
;
1063 if (is_yuv
&& bottom_up
)
1064 return MF_E_INVALIDMEDIATYPE
;
1066 if (FAILED(hr
= MFGetPlaneSize(fourcc
, width
, height
, &plane_size
)))
1069 object
= heap_alloc_zero(sizeof(*object
));
1071 return E_OUTOFMEMORY
;
1075 case MAKEFOURCC('I','M','C','1'):
1076 case MAKEFOURCC('I','M','C','2'):
1077 case MAKEFOURCC('I','M','C','3'):
1078 case MAKEFOURCC('I','M','C','4'):
1079 case MAKEFOURCC('Y','V','1','2'):
1080 row_alignment
= MF_128_BYTE_ALIGNMENT
;
1083 row_alignment
= MF_64_BYTE_ALIGNMENT
;
1086 pitch
= ALIGN_SIZE(stride
, row_alignment
);
1090 case MAKEFOURCC('I','M','C','1'):
1091 case MAKEFOURCC('I','M','C','3'):
1092 max_length
= pitch
* height
* 2;
1095 case MAKEFOURCC('N','V','1','2'):
1096 max_length
= pitch
* height
* 3 / 2;
1099 max_length
= pitch
* height
;
1102 if (FAILED(hr
= memory_buffer_init(object
, max_length
, MF_1_BYTE_ALIGNMENT
, &memory_1d_2d_buffer_vtbl
)))
1108 object
->IMF2DBuffer2_iface
.lpVtbl
= &memory_2d_buffer_vtbl
;
1109 object
->IMFGetService_iface
.lpVtbl
= &memory_2d_buffer_gs_vtbl
;
1110 object
->_2d
.plane_size
= plane_size
;
1111 object
->_2d
.width
= stride
;
1112 object
->_2d
.height
= height
;
1113 object
->_2d
.pitch
= bottom_up
? -pitch
: pitch
;
1114 object
->_2d
.scanline0
= bottom_up
? object
->data
+ pitch
* (object
->_2d
.height
- 1) : object
->data
;
1116 *buffer
= &object
->IMFMediaBuffer_iface
;
1121 static HRESULT
create_d3d9_surface_buffer(IUnknown
*surface
, BOOL bottom_up
, IMFMediaBuffer
**buffer
)
1123 struct memory_buffer
*object
;
1124 D3DSURFACE_DESC desc
;
1125 unsigned int stride
;
1129 IDirect3DSurface9_GetDesc((IDirect3DSurface9
*)surface
, &desc
);
1130 TRACE("format %#x, %u x %u.\n", desc
.Format
, desc
.Width
, desc
.Height
);
1132 memcpy(&subtype
, &MFVideoFormat_Base
, sizeof(subtype
));
1133 subtype
.Data1
= desc
.Format
;
1135 if (!(stride
= mf_format_get_stride(&subtype
, desc
.Width
, &is_yuv
)))
1136 return MF_E_INVALIDMEDIATYPE
;
1138 object
= heap_alloc_zero(sizeof(*object
));
1140 return E_OUTOFMEMORY
;
1142 object
->IMFMediaBuffer_iface
.lpVtbl
= &d3d9_surface_1d_buffer_vtbl
;
1143 object
->IMF2DBuffer2_iface
.lpVtbl
= &d3d9_surface_buffer_vtbl
;
1144 object
->IMFGetService_iface
.lpVtbl
= &d3d9_surface_buffer_gs_vtbl
;
1145 object
->refcount
= 1;
1146 InitializeCriticalSection(&object
->cs
);
1147 object
->d3d9_surface
.surface
= (IDirect3DSurface9
*)surface
;
1148 IUnknown_AddRef(surface
);
1150 MFGetPlaneSize(desc
.Format
, desc
.Width
, desc
.Height
, &object
->_2d
.plane_size
);
1151 object
->_2d
.width
= stride
;
1152 object
->_2d
.height
= desc
.Height
;
1153 object
->max_length
= object
->_2d
.plane_size
;
1155 *buffer
= &object
->IMFMediaBuffer_iface
;
1160 static HRESULT
create_dxgi_surface_buffer(IUnknown
*surface
, UINT subresource
, BOOL bottom_up
,
1161 IMFMediaBuffer
**buffer
)
1163 struct memory_buffer
*object
;
1164 D3D11_TEXTURE2D_DESC desc
;
1165 unsigned int stride
;
1171 ID3D11Texture2D_GetDesc((ID3D11Texture2D
*)surface
, &desc
);
1172 TRACE("format %#x, %u x %u.\n", desc
.Format
, desc
.Width
, desc
.Height
);
1174 memcpy(&subtype
, &MFVideoFormat_Base
, sizeof(subtype
));
1175 subtype
.Data1
= format
= MFMapDXGIFormatToDX9Format(desc
.Format
);
1177 if (!(stride
= mf_format_get_stride(&subtype
, desc
.Width
, &is_yuv
)))
1178 return MF_E_INVALIDMEDIATYPE
;
1180 object
= heap_alloc_zero(sizeof(*object
));
1182 return E_OUTOFMEMORY
;
1184 object
->IMFMediaBuffer_iface
.lpVtbl
= &dxgi_surface_1d_buffer_vtbl
;
1185 object
->IMF2DBuffer2_iface
.lpVtbl
= &dxgi_surface_buffer_vtbl
;
1186 object
->IMFDXGIBuffer_iface
.lpVtbl
= &dxgi_buffer_vtbl
;
1187 object
->refcount
= 1;
1188 InitializeCriticalSection(&object
->cs
);
1189 object
->dxgi_surface
.surface
= surface
;
1190 IUnknown_AddRef(surface
);
1191 object
->dxgi_surface
.subresource
= subresource
;
1193 MFGetPlaneSize(format
, desc
.Width
, desc
.Height
, &object
->_2d
.plane_size
);
1194 object
->_2d
.width
= stride
;
1195 object
->_2d
.height
= desc
.Height
;
1196 object
->max_length
= object
->_2d
.plane_size
;
1198 if (FAILED(hr
= init_attributes_object(&object
->dxgi_surface
.attributes
, 0)))
1200 IMFMediaBuffer_Release(&object
->IMFMediaBuffer_iface
);
1204 *buffer
= &object
->IMFMediaBuffer_iface
;
1209 /***********************************************************************
1210 * MFCreateMemoryBuffer (mfplat.@)
1212 HRESULT WINAPI
MFCreateMemoryBuffer(DWORD max_length
, IMFMediaBuffer
**buffer
)
1214 TRACE("%u, %p.\n", max_length
, buffer
);
1216 return create_1d_buffer(max_length
, MF_1_BYTE_ALIGNMENT
, buffer
);
1219 /***********************************************************************
1220 * MFCreateAlignedMemoryBuffer (mfplat.@)
1222 HRESULT WINAPI
MFCreateAlignedMemoryBuffer(DWORD max_length
, DWORD alignment
, IMFMediaBuffer
**buffer
)
1224 TRACE("%u, %u, %p.\n", max_length
, alignment
, buffer
);
1226 return create_1d_buffer(max_length
, alignment
, buffer
);
1229 /***********************************************************************
1230 * MFCreate2DMediaBuffer (mfplat.@)
1232 HRESULT WINAPI
MFCreate2DMediaBuffer(DWORD width
, DWORD height
, DWORD fourcc
, BOOL bottom_up
, IMFMediaBuffer
**buffer
)
1234 TRACE("%u, %u, %s, %d, %p.\n", width
, height
, debugstr_fourcc(fourcc
), bottom_up
, buffer
);
1236 return create_2d_buffer(width
, height
, fourcc
, bottom_up
, buffer
);
1239 /***********************************************************************
1240 * MFCreateDXSurfaceBuffer (mfplat.@)
1242 HRESULT WINAPI
MFCreateDXSurfaceBuffer(REFIID riid
, IUnknown
*surface
, BOOL bottom_up
, IMFMediaBuffer
**buffer
)
1244 TRACE("%s, %p, %d, %p.\n", debugstr_guid(riid
), surface
, bottom_up
, buffer
);
1246 if (!IsEqualIID(riid
, &IID_IDirect3DSurface9
))
1247 return E_INVALIDARG
;
1249 return create_d3d9_surface_buffer(surface
, bottom_up
, buffer
);
1252 /***********************************************************************
1253 * MFCreateDXGISurfaceBuffer (mfplat.@)
1255 HRESULT WINAPI
MFCreateDXGISurfaceBuffer(REFIID riid
, IUnknown
*surface
, UINT subresource
, BOOL bottom_up
,
1256 IMFMediaBuffer
**buffer
)
1258 TRACE("%s, %p, %u, %d, %p.\n", debugstr_guid(riid
), surface
, subresource
, bottom_up
, buffer
);
1260 if (!IsEqualIID(riid
, &IID_ID3D11Texture2D
))
1261 return E_INVALIDARG
;
1263 return create_dxgi_surface_buffer(surface
, subresource
, bottom_up
, buffer
);
1266 static unsigned int buffer_get_aligned_length(unsigned int length
, unsigned int alignment
)
1268 length
= (length
+ alignment
) / alignment
;
1269 length
*= alignment
;
1274 HRESULT WINAPI
MFCreateMediaBufferFromMediaType(IMFMediaType
*media_type
, LONGLONG duration
, DWORD min_length
,
1275 DWORD alignment
, IMFMediaBuffer
**buffer
)
1277 UINT32 length
= 0, block_alignment
;
1278 LONGLONG avg_length
;
1282 TRACE("%p, %s, %u, %u, %p.\n", media_type
, debugstr_time(duration
), min_length
, alignment
, buffer
);
1285 return E_INVALIDARG
;
1287 if (FAILED(hr
= IMFMediaType_GetMajorType(media_type
, &major
)))
1290 if (IsEqualGUID(&major
, &MFMediaType_Audio
))
1292 block_alignment
= 0;
1293 if (FAILED(IMFMediaType_GetUINT32(media_type
, &MF_MT_AUDIO_BLOCK_ALIGNMENT
, &block_alignment
)))
1294 WARN("Block alignment was not specified.\n");
1296 if (block_alignment
)
1303 if (SUCCEEDED(IMFMediaType_GetUINT32(media_type
, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND
, &length
)))
1306 avg_length
= length
* duration
/ (10 * 1000 * 1000);
1310 alignment
= max(16, alignment
);
1312 length
= buffer_get_aligned_length(avg_length
+ 1, alignment
);
1313 length
= buffer_get_aligned_length(length
, block_alignment
);
1318 length
= max(length
, min_length
);
1320 return create_1d_buffer(length
, MF_1_BYTE_ALIGNMENT
, buffer
);
1323 FIXME("Major type %s is not supported.\n", debugstr_guid(&major
));