mfplat: Implement Lock2DSize() for d3d11 buffers.
[wine/zf.git] / dlls / mfplat / buffer.c
blob77767c27d9487095ac86975715f46765834b5e74
1 /*
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
19 #define COBJMACROS
21 #include "mfplat_private.h"
22 #include "rtworkq.h"
24 #include "d3d11.h"
25 #include "initguid.h"
26 #include "d3d9.h"
27 #include "evr.h"
29 #include "wine/debug.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
33 #define ALIGN_SIZE(size, alignment) (((size) + (alignment)) & ~((alignment)))
35 struct buffer
37 IMFMediaBuffer IMFMediaBuffer_iface;
38 IMF2DBuffer2 IMF2DBuffer2_iface;
39 IMFDXGIBuffer IMFDXGIBuffer_iface;
40 IMFGetService IMFGetService_iface;
41 LONG refcount;
43 BYTE *data;
44 DWORD max_length;
45 DWORD current_length;
47 struct
49 BYTE *linear_buffer;
50 unsigned int plane_size;
52 BYTE *scanline0;
53 unsigned int width;
54 unsigned int height;
55 int pitch;
57 unsigned int locks;
58 } _2d;
59 struct
61 IDirect3DSurface9 *surface;
62 D3DLOCKED_RECT rect;
63 } d3d9_surface;
64 struct
66 ID3D11Texture2D *texture;
67 unsigned int sub_resource_idx;
68 ID3D11Texture2D *rb_texture;
69 D3D11_MAPPED_SUBRESOURCE map_desc;
70 struct attributes attributes;
71 } dxgi_surface;
73 CRITICAL_SECTION cs;
76 static inline struct buffer *impl_from_IMFMediaBuffer(IMFMediaBuffer *iface)
78 return CONTAINING_RECORD(iface, struct buffer, IMFMediaBuffer_iface);
81 static struct buffer *impl_from_IMF2DBuffer2(IMF2DBuffer2 *iface)
83 return CONTAINING_RECORD(iface, struct buffer, IMF2DBuffer2_iface);
86 static struct buffer *impl_from_IMFGetService(IMFGetService *iface)
88 return CONTAINING_RECORD(iface, struct buffer, IMFGetService_iface);
91 static struct buffer *impl_from_IMFDXGIBuffer(IMFDXGIBuffer *iface)
93 return CONTAINING_RECORD(iface, struct buffer, IMFDXGIBuffer_iface);
96 static HRESULT WINAPI memory_buffer_QueryInterface(IMFMediaBuffer *iface, REFIID riid, void **out)
98 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
100 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
102 if (IsEqualIID(riid, &IID_IMFMediaBuffer) ||
103 IsEqualIID(riid, &IID_IUnknown))
105 *out = &buffer->IMFMediaBuffer_iface;
106 IMFMediaBuffer_AddRef(iface);
107 return S_OK;
110 WARN("Unsupported %s.\n", debugstr_guid(riid));
111 *out = NULL;
112 return E_NOINTERFACE;
115 static ULONG WINAPI memory_buffer_AddRef(IMFMediaBuffer *iface)
117 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
118 ULONG refcount = InterlockedIncrement(&buffer->refcount);
120 TRACE("%p, refcount %u.\n", buffer, refcount);
122 return refcount;
125 static ULONG WINAPI memory_buffer_Release(IMFMediaBuffer *iface)
127 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
128 ULONG refcount = InterlockedDecrement(&buffer->refcount);
130 TRACE("%p, refcount %u.\n", iface, refcount);
132 if (!refcount)
134 if (buffer->d3d9_surface.surface)
135 IDirect3DSurface9_Release(buffer->d3d9_surface.surface);
136 if (buffer->dxgi_surface.texture)
138 ID3D11Texture2D_Release(buffer->dxgi_surface.texture);
139 if (buffer->dxgi_surface.rb_texture)
140 ID3D11Texture2D_Release(buffer->dxgi_surface.rb_texture);
141 clear_attributes_object(&buffer->dxgi_surface.attributes);
143 DeleteCriticalSection(&buffer->cs);
144 heap_free(buffer->_2d.linear_buffer);
145 heap_free(buffer->data);
146 heap_free(buffer);
149 return refcount;
152 static HRESULT WINAPI memory_buffer_Lock(IMFMediaBuffer *iface, BYTE **data, DWORD *max_length, DWORD *current_length)
154 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
156 TRACE("%p, %p %p, %p.\n", iface, data, max_length, current_length);
158 if (!data)
159 return E_INVALIDARG;
161 *data = buffer->data;
162 if (max_length)
163 *max_length = buffer->max_length;
164 if (current_length)
165 *current_length = buffer->current_length;
167 return S_OK;
170 static HRESULT WINAPI memory_buffer_Unlock(IMFMediaBuffer *iface)
172 TRACE("%p.\n", iface);
174 return S_OK;
177 static HRESULT WINAPI memory_buffer_GetCurrentLength(IMFMediaBuffer *iface, DWORD *current_length)
179 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
181 TRACE("%p.\n", iface);
183 if (!current_length)
184 return E_INVALIDARG;
186 *current_length = buffer->current_length;
188 return S_OK;
191 static HRESULT WINAPI memory_buffer_SetCurrentLength(IMFMediaBuffer *iface, DWORD current_length)
193 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
195 TRACE("%p, %u.\n", iface, current_length);
197 if (current_length > buffer->max_length)
198 return E_INVALIDARG;
200 buffer->current_length = current_length;
202 return S_OK;
205 static HRESULT WINAPI memory_buffer_GetMaxLength(IMFMediaBuffer *iface, DWORD *max_length)
207 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
209 TRACE("%p, %p.\n", iface, max_length);
211 if (!max_length)
212 return E_INVALIDARG;
214 *max_length = buffer->max_length;
216 return S_OK;
219 static const IMFMediaBufferVtbl memory_1d_buffer_vtbl =
221 memory_buffer_QueryInterface,
222 memory_buffer_AddRef,
223 memory_buffer_Release,
224 memory_buffer_Lock,
225 memory_buffer_Unlock,
226 memory_buffer_GetCurrentLength,
227 memory_buffer_SetCurrentLength,
228 memory_buffer_GetMaxLength,
231 static HRESULT WINAPI memory_1d_2d_buffer_QueryInterface(IMFMediaBuffer *iface, REFIID riid, void **out)
233 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
235 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
237 if (IsEqualIID(riid, &IID_IMFMediaBuffer) ||
238 IsEqualIID(riid, &IID_IUnknown))
240 *out = &buffer->IMFMediaBuffer_iface;
242 else if (IsEqualIID(riid, &IID_IMF2DBuffer2) ||
243 IsEqualIID(riid, &IID_IMF2DBuffer))
245 *out = &buffer->IMF2DBuffer2_iface;
247 else if (IsEqualIID(riid, &IID_IMFGetService))
249 *out = &buffer->IMFGetService_iface;
251 else
253 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
254 *out = NULL;
255 return E_NOINTERFACE;
258 IUnknown_AddRef((IUnknown*)*out);
259 return S_OK;
262 static HRESULT WINAPI memory_1d_2d_buffer_Lock(IMFMediaBuffer *iface, BYTE **data, DWORD *max_length, DWORD *current_length)
264 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
265 HRESULT hr = S_OK;
267 TRACE("%p, %p, %p, %p.\n", iface, data, max_length, current_length);
269 if (!data)
270 return E_POINTER;
272 /* Allocate linear buffer and return it as a copy of current content. Maximum and current length are
273 unrelated to 2D buffer maximum allocate length, or maintained current length. */
275 EnterCriticalSection(&buffer->cs);
277 if (!buffer->_2d.linear_buffer && buffer->_2d.locks)
278 hr = MF_E_INVALIDREQUEST;
279 else if (!buffer->_2d.linear_buffer)
281 if (!(buffer->_2d.linear_buffer = heap_alloc(ALIGN_SIZE(buffer->_2d.plane_size, MF_64_BYTE_ALIGNMENT))))
282 hr = E_OUTOFMEMORY;
285 if (SUCCEEDED(hr))
287 ++buffer->_2d.locks;
288 *data = buffer->_2d.linear_buffer;
289 if (max_length)
290 *max_length = buffer->_2d.plane_size;
291 if (current_length)
292 *current_length = buffer->_2d.plane_size;
295 LeaveCriticalSection(&buffer->cs);
297 return hr;
300 static HRESULT WINAPI memory_1d_2d_buffer_Unlock(IMFMediaBuffer *iface)
302 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
304 TRACE("%p.\n", iface);
306 EnterCriticalSection(&buffer->cs);
308 if (buffer->_2d.linear_buffer && !--buffer->_2d.locks)
310 MFCopyImage(buffer->data, buffer->_2d.pitch, buffer->_2d.linear_buffer, buffer->_2d.width,
311 buffer->_2d.width, buffer->_2d.height);
313 heap_free(buffer->_2d.linear_buffer);
314 buffer->_2d.linear_buffer = NULL;
317 LeaveCriticalSection(&buffer->cs);
319 return S_OK;
322 static const IMFMediaBufferVtbl memory_1d_2d_buffer_vtbl =
324 memory_1d_2d_buffer_QueryInterface,
325 memory_buffer_AddRef,
326 memory_buffer_Release,
327 memory_1d_2d_buffer_Lock,
328 memory_1d_2d_buffer_Unlock,
329 memory_buffer_GetCurrentLength,
330 memory_buffer_SetCurrentLength,
331 memory_buffer_GetMaxLength,
334 static HRESULT WINAPI d3d9_surface_buffer_Lock(IMFMediaBuffer *iface, BYTE **data, DWORD *max_length, DWORD *current_length)
336 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
337 HRESULT hr = S_OK;
339 TRACE("%p, %p, %p, %p.\n", iface, data, max_length, current_length);
341 if (!data)
342 return E_POINTER;
344 EnterCriticalSection(&buffer->cs);
346 if (!buffer->_2d.linear_buffer && buffer->_2d.locks)
347 hr = MF_E_INVALIDREQUEST;
348 else if (!buffer->_2d.linear_buffer)
350 D3DLOCKED_RECT rect;
352 if (!(buffer->_2d.linear_buffer = heap_alloc(ALIGN_SIZE(buffer->_2d.plane_size, MF_64_BYTE_ALIGNMENT))))
353 hr = E_OUTOFMEMORY;
355 if (SUCCEEDED(hr))
357 hr = IDirect3DSurface9_LockRect(buffer->d3d9_surface.surface, &rect, NULL, 0);
358 if (SUCCEEDED(hr))
360 MFCopyImage(buffer->_2d.linear_buffer, buffer->_2d.width, rect.pBits, rect.Pitch,
361 buffer->_2d.width, buffer->_2d.height);
362 IDirect3DSurface9_UnlockRect(buffer->d3d9_surface.surface);
367 if (SUCCEEDED(hr))
369 ++buffer->_2d.locks;
370 *data = buffer->_2d.linear_buffer;
371 if (max_length)
372 *max_length = buffer->_2d.plane_size;
373 if (current_length)
374 *current_length = buffer->_2d.plane_size;
377 LeaveCriticalSection(&buffer->cs);
379 return hr;
382 static HRESULT WINAPI d3d9_surface_buffer_Unlock(IMFMediaBuffer *iface)
384 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
385 HRESULT hr = S_OK;
387 TRACE("%p.\n", iface);
389 EnterCriticalSection(&buffer->cs);
391 if (!buffer->_2d.linear_buffer)
392 hr = HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED);
393 else if (!--buffer->_2d.locks)
395 D3DLOCKED_RECT rect;
397 if (SUCCEEDED(hr = IDirect3DSurface9_LockRect(buffer->d3d9_surface.surface, &rect, NULL, 0)))
399 MFCopyImage(rect.pBits, rect.Pitch, buffer->_2d.linear_buffer, buffer->_2d.width,
400 buffer->_2d.width, buffer->_2d.height);
401 IDirect3DSurface9_UnlockRect(buffer->d3d9_surface.surface);
404 heap_free(buffer->_2d.linear_buffer);
405 buffer->_2d.linear_buffer = NULL;
408 LeaveCriticalSection(&buffer->cs);
410 return hr;
413 static HRESULT WINAPI d3d9_surface_buffer_SetCurrentLength(IMFMediaBuffer *iface, DWORD current_length)
415 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
417 TRACE("%p, %u.\n", iface, current_length);
419 buffer->current_length = current_length;
421 return S_OK;
424 static const IMFMediaBufferVtbl d3d9_surface_1d_buffer_vtbl =
426 memory_1d_2d_buffer_QueryInterface,
427 memory_buffer_AddRef,
428 memory_buffer_Release,
429 d3d9_surface_buffer_Lock,
430 d3d9_surface_buffer_Unlock,
431 memory_buffer_GetCurrentLength,
432 d3d9_surface_buffer_SetCurrentLength,
433 memory_buffer_GetMaxLength,
436 static HRESULT WINAPI memory_2d_buffer_QueryInterface(IMF2DBuffer2 *iface, REFIID riid, void **obj)
438 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
439 return IMFMediaBuffer_QueryInterface(&buffer->IMFMediaBuffer_iface, riid, obj);
442 static ULONG WINAPI memory_2d_buffer_AddRef(IMF2DBuffer2 *iface)
444 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
445 return IMFMediaBuffer_AddRef(&buffer->IMFMediaBuffer_iface);
448 static ULONG WINAPI memory_2d_buffer_Release(IMF2DBuffer2 *iface)
450 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
451 return IMFMediaBuffer_Release(&buffer->IMFMediaBuffer_iface);
454 static HRESULT memory_2d_buffer_lock(struct buffer *buffer, BYTE **scanline0, LONG *pitch,
455 BYTE **buffer_start, DWORD *buffer_length)
457 HRESULT hr = S_OK;
459 if (buffer->_2d.linear_buffer)
460 hr = MF_E_UNEXPECTED;
461 else
463 ++buffer->_2d.locks;
464 *scanline0 = buffer->_2d.scanline0;
465 *pitch = buffer->_2d.pitch;
466 if (buffer_start)
467 *buffer_start = buffer->data;
468 if (buffer_length)
469 *buffer_length = buffer->max_length;
472 return hr;
475 static HRESULT WINAPI memory_2d_buffer_Lock2D(IMF2DBuffer2 *iface, BYTE **scanline0, LONG *pitch)
477 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
478 HRESULT hr;
480 TRACE("%p, %p, %p.\n", iface, scanline0, pitch);
482 if (!scanline0 || !pitch)
483 return E_POINTER;
485 EnterCriticalSection(&buffer->cs);
487 hr = memory_2d_buffer_lock(buffer, scanline0, pitch, NULL, NULL);
489 LeaveCriticalSection(&buffer->cs);
491 return hr;
494 static HRESULT WINAPI memory_2d_buffer_Unlock2D(IMF2DBuffer2 *iface)
496 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
497 HRESULT hr = S_OK;
499 TRACE("%p.\n", iface);
501 EnterCriticalSection(&buffer->cs);
503 if (!buffer->_2d.linear_buffer)
505 if (buffer->_2d.locks)
506 --buffer->_2d.locks;
507 else
508 hr = HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED);
511 LeaveCriticalSection(&buffer->cs);
513 return hr;
516 static HRESULT WINAPI memory_2d_buffer_GetScanline0AndPitch(IMF2DBuffer2 *iface, BYTE **scanline0, LONG *pitch)
518 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
519 HRESULT hr = S_OK;
521 TRACE("%p, %p, %p.\n", iface, scanline0, pitch);
523 if (!scanline0 || !pitch)
524 return E_POINTER;
526 EnterCriticalSection(&buffer->cs);
528 if (buffer->_2d.linear_buffer || !buffer->_2d.locks)
529 hr = HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED);
530 else
532 *scanline0 = buffer->_2d.scanline0;
533 *pitch = buffer->_2d.pitch;
536 LeaveCriticalSection(&buffer->cs);
538 return hr;
541 static HRESULT WINAPI memory_2d_buffer_IsContiguousFormat(IMF2DBuffer2 *iface, BOOL *is_contiguous)
543 TRACE("%p, %p.\n", iface, is_contiguous);
545 if (!is_contiguous)
546 return E_POINTER;
548 *is_contiguous = FALSE;
550 return S_OK;
553 static HRESULT WINAPI memory_2d_buffer_GetContiguousLength(IMF2DBuffer2 *iface, DWORD *length)
555 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
557 TRACE("%p, %p.\n", iface, length);
559 if (!length)
560 return E_POINTER;
562 *length = buffer->_2d.plane_size;
564 return S_OK;
567 static HRESULT WINAPI memory_2d_buffer_ContiguousCopyTo(IMF2DBuffer2 *iface, BYTE *dest_buffer, DWORD dest_length)
569 FIXME("%p, %p, %u.\n", iface, dest_buffer, dest_length);
571 return E_NOTIMPL;
574 static HRESULT WINAPI memory_2d_buffer_ContiguousCopyFrom(IMF2DBuffer2 *iface, const BYTE *src_buffer, DWORD src_length)
576 FIXME("%p, %p, %u.\n", iface, src_buffer, src_length);
578 return E_NOTIMPL;
581 static HRESULT WINAPI memory_2d_buffer_Lock2DSize(IMF2DBuffer2 *iface, MF2DBuffer_LockFlags flags, BYTE **scanline0,
582 LONG *pitch, BYTE **buffer_start, DWORD *buffer_length)
584 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
585 HRESULT hr;
587 TRACE("%p, %#x, %p, %p, %p, %p.\n", iface, flags, scanline0, pitch, buffer_start, buffer_length);
589 if (!scanline0 || !pitch || !buffer_start || !buffer_length)
590 return E_POINTER;
592 EnterCriticalSection(&buffer->cs);
594 hr = memory_2d_buffer_lock(buffer, scanline0, pitch, buffer_start, buffer_length);
596 LeaveCriticalSection(&buffer->cs);
598 return hr;
601 static HRESULT WINAPI memory_2d_buffer_Copy2DTo(IMF2DBuffer2 *iface, IMF2DBuffer2 *dest_buffer)
603 FIXME("%p, %p.\n", iface, dest_buffer);
605 return E_NOTIMPL;
608 static const IMF2DBuffer2Vtbl memory_2d_buffer_vtbl =
610 memory_2d_buffer_QueryInterface,
611 memory_2d_buffer_AddRef,
612 memory_2d_buffer_Release,
613 memory_2d_buffer_Lock2D,
614 memory_2d_buffer_Unlock2D,
615 memory_2d_buffer_GetScanline0AndPitch,
616 memory_2d_buffer_IsContiguousFormat,
617 memory_2d_buffer_GetContiguousLength,
618 memory_2d_buffer_ContiguousCopyTo,
619 memory_2d_buffer_ContiguousCopyFrom,
620 memory_2d_buffer_Lock2DSize,
621 memory_2d_buffer_Copy2DTo,
624 static HRESULT WINAPI d3d9_surface_buffer_Lock2D(IMF2DBuffer2 *iface, BYTE **scanline0, LONG *pitch)
626 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
627 HRESULT hr = S_OK;
629 TRACE("%p, %p, %p.\n", iface, scanline0, pitch);
631 if (!scanline0 || !pitch)
632 return E_POINTER;
634 EnterCriticalSection(&buffer->cs);
636 if (buffer->_2d.linear_buffer)
637 hr = MF_E_UNEXPECTED;
638 else if (!buffer->_2d.locks++)
640 hr = IDirect3DSurface9_LockRect(buffer->d3d9_surface.surface, &buffer->d3d9_surface.rect, NULL, 0);
643 if (SUCCEEDED(hr))
645 *scanline0 = buffer->d3d9_surface.rect.pBits;
646 *pitch = buffer->d3d9_surface.rect.Pitch;
649 LeaveCriticalSection(&buffer->cs);
651 return hr;
654 static HRESULT WINAPI d3d9_surface_buffer_Unlock2D(IMF2DBuffer2 *iface)
656 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
657 HRESULT hr = S_OK;
659 TRACE("%p.\n", iface);
661 EnterCriticalSection(&buffer->cs);
663 if (buffer->_2d.locks)
665 if (!--buffer->_2d.locks)
667 IDirect3DSurface9_UnlockRect(buffer->d3d9_surface.surface);
668 memset(&buffer->d3d9_surface.rect, 0, sizeof(buffer->d3d9_surface.rect));
671 else
672 hr = HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED);
674 LeaveCriticalSection(&buffer->cs);
676 return hr;
679 static HRESULT WINAPI d3d9_surface_buffer_GetScanline0AndPitch(IMF2DBuffer2 *iface, BYTE **scanline0, LONG *pitch)
681 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
682 HRESULT hr = S_OK;
684 TRACE("%p, %p, %p.\n", iface, scanline0, pitch);
686 if (!scanline0 || !pitch)
687 return E_POINTER;
689 EnterCriticalSection(&buffer->cs);
691 if (!buffer->_2d.locks)
693 *scanline0 = NULL;
694 *pitch = 0;
695 hr = HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED);
697 else
699 *scanline0 = buffer->d3d9_surface.rect.pBits;
700 *pitch = buffer->d3d9_surface.rect.Pitch;
703 LeaveCriticalSection(&buffer->cs);
705 return hr;
708 static HRESULT WINAPI d3d9_surface_buffer_Lock2DSize(IMF2DBuffer2 *iface, MF2DBuffer_LockFlags flags, BYTE **scanline0,
709 LONG *pitch, BYTE **buffer_start, DWORD *buffer_length)
711 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
712 HRESULT hr = S_OK;
714 TRACE("%p, %#x, %p, %p, %p, %p.\n", iface, flags, scanline0, pitch, buffer_start, buffer_length);
716 if (!scanline0 || !pitch || !buffer_start || !buffer_length)
717 return E_POINTER;
719 EnterCriticalSection(&buffer->cs);
721 if (buffer->_2d.linear_buffer)
722 hr = MF_E_UNEXPECTED;
723 else if (!buffer->_2d.locks++)
725 hr = IDirect3DSurface9_LockRect(buffer->d3d9_surface.surface, &buffer->d3d9_surface.rect, NULL, 0);
728 if (SUCCEEDED(hr))
730 *scanline0 = buffer->d3d9_surface.rect.pBits;
731 *pitch = buffer->d3d9_surface.rect.Pitch;
732 if (buffer_start)
733 *buffer_start = *scanline0;
734 if (buffer_length)
735 *buffer_length = buffer->d3d9_surface.rect.Pitch * buffer->_2d.height;
738 LeaveCriticalSection(&buffer->cs);
740 return hr;
743 static const IMF2DBuffer2Vtbl d3d9_surface_buffer_vtbl =
745 memory_2d_buffer_QueryInterface,
746 memory_2d_buffer_AddRef,
747 memory_2d_buffer_Release,
748 d3d9_surface_buffer_Lock2D,
749 d3d9_surface_buffer_Unlock2D,
750 d3d9_surface_buffer_GetScanline0AndPitch,
751 memory_2d_buffer_IsContiguousFormat,
752 memory_2d_buffer_GetContiguousLength,
753 memory_2d_buffer_ContiguousCopyTo,
754 memory_2d_buffer_ContiguousCopyFrom,
755 d3d9_surface_buffer_Lock2DSize,
756 memory_2d_buffer_Copy2DTo,
759 static HRESULT WINAPI memory_2d_buffer_gs_QueryInterface(IMFGetService *iface, REFIID riid, void **obj)
761 struct buffer *buffer = impl_from_IMFGetService(iface);
762 return IMFMediaBuffer_QueryInterface(&buffer->IMFMediaBuffer_iface, riid, obj);
765 static ULONG WINAPI memory_2d_buffer_gs_AddRef(IMFGetService *iface)
767 struct buffer *buffer = impl_from_IMFGetService(iface);
768 return IMFMediaBuffer_AddRef(&buffer->IMFMediaBuffer_iface);
771 static ULONG WINAPI memory_2d_buffer_gs_Release(IMFGetService *iface)
773 struct buffer *buffer = impl_from_IMFGetService(iface);
774 return IMFMediaBuffer_Release(&buffer->IMFMediaBuffer_iface);
777 static HRESULT WINAPI memory_2d_buffer_gs_GetService(IMFGetService *iface, REFGUID service, REFIID riid, void **obj)
779 TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj);
781 return E_NOTIMPL;
784 static const IMFGetServiceVtbl memory_2d_buffer_gs_vtbl =
786 memory_2d_buffer_gs_QueryInterface,
787 memory_2d_buffer_gs_AddRef,
788 memory_2d_buffer_gs_Release,
789 memory_2d_buffer_gs_GetService,
792 static HRESULT WINAPI d3d9_surface_buffer_gs_GetService(IMFGetService *iface, REFGUID service, REFIID riid, void **obj)
794 struct buffer *buffer = impl_from_IMFGetService(iface);
796 TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj);
798 if (IsEqualGUID(service, &MR_BUFFER_SERVICE))
800 return IDirect3DSurface9_QueryInterface(buffer->d3d9_surface.surface, riid, obj);
803 return E_NOTIMPL;
806 static const IMFGetServiceVtbl d3d9_surface_buffer_gs_vtbl =
808 memory_2d_buffer_gs_QueryInterface,
809 memory_2d_buffer_gs_AddRef,
810 memory_2d_buffer_gs_Release,
811 d3d9_surface_buffer_gs_GetService,
814 static HRESULT WINAPI dxgi_1d_2d_buffer_QueryInterface(IMFMediaBuffer *iface, REFIID riid, void **out)
816 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
818 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
820 if (IsEqualIID(riid, &IID_IMFMediaBuffer) ||
821 IsEqualIID(riid, &IID_IUnknown))
823 *out = &buffer->IMFMediaBuffer_iface;
825 else if (IsEqualIID(riid, &IID_IMF2DBuffer2) ||
826 IsEqualIID(riid, &IID_IMF2DBuffer))
828 *out = &buffer->IMF2DBuffer2_iface;
830 else if (IsEqualIID(riid, &IID_IMFDXGIBuffer))
832 *out = &buffer->IMFDXGIBuffer_iface;
834 else
836 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
837 *out = NULL;
838 return E_NOINTERFACE;
841 IUnknown_AddRef((IUnknown*)*out);
842 return S_OK;
845 static HRESULT dxgi_surface_buffer_create_readback_texture(struct buffer *buffer)
847 D3D11_TEXTURE2D_DESC texture_desc;
848 ID3D11Device *device;
849 HRESULT hr;
851 if (buffer->dxgi_surface.rb_texture)
852 return S_OK;
854 ID3D11Texture2D_GetDevice(buffer->dxgi_surface.texture, &device);
856 ID3D11Texture2D_GetDesc(buffer->dxgi_surface.texture, &texture_desc);
857 texture_desc.Usage = D3D11_USAGE_STAGING;
858 texture_desc.BindFlags = 0;
859 texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
860 texture_desc.MiscFlags = 0;
861 texture_desc.MipLevels = 1;
862 if (FAILED(hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &buffer->dxgi_surface.rb_texture)))
863 WARN("Failed to create readback texture, hr %#x.\n", hr);
865 ID3D11Device_Release(device);
867 return hr;
870 static HRESULT dxgi_surface_buffer_map(struct buffer *buffer)
872 ID3D11DeviceContext *immediate_context;
873 ID3D11Device *device;
874 HRESULT hr;
876 if (FAILED(hr = dxgi_surface_buffer_create_readback_texture(buffer)))
877 return hr;
879 ID3D11Texture2D_GetDevice(buffer->dxgi_surface.texture, &device);
880 ID3D11Device_GetImmediateContext(device, &immediate_context);
881 ID3D11DeviceContext_CopySubresourceRegion(immediate_context, (ID3D11Resource *)buffer->dxgi_surface.rb_texture,
882 0, 0, 0, 0, (ID3D11Resource *)buffer->dxgi_surface.texture, buffer->dxgi_surface.sub_resource_idx, NULL);
884 memset(&buffer->dxgi_surface.map_desc, 0, sizeof(buffer->dxgi_surface.map_desc));
885 if (FAILED(hr = ID3D11DeviceContext_Map(immediate_context, (ID3D11Resource *)buffer->dxgi_surface.rb_texture,
886 0, D3D11_MAP_READ_WRITE, 0, &buffer->dxgi_surface.map_desc)))
888 WARN("Failed to map readback texture, hr %#x.\n", hr);
891 ID3D11DeviceContext_Release(immediate_context);
892 ID3D11Device_Release(device);
894 return hr;
897 static void dxgi_surface_buffer_unmap(struct buffer *buffer)
899 ID3D11DeviceContext *immediate_context;
900 ID3D11Device *device;
902 ID3D11Texture2D_GetDevice(buffer->dxgi_surface.texture, &device);
903 ID3D11Device_GetImmediateContext(device, &immediate_context);
904 ID3D11DeviceContext_Unmap(immediate_context, (ID3D11Resource *)buffer->dxgi_surface.rb_texture, 0);
905 memset(&buffer->dxgi_surface.map_desc, 0, sizeof(buffer->dxgi_surface.map_desc));
907 ID3D11DeviceContext_CopySubresourceRegion(immediate_context, (ID3D11Resource *)buffer->dxgi_surface.texture,
908 buffer->dxgi_surface.sub_resource_idx, 0, 0, 0, (ID3D11Resource *)buffer->dxgi_surface.rb_texture, 0, NULL);
910 ID3D11DeviceContext_Release(immediate_context);
911 ID3D11Device_Release(device);
914 static HRESULT WINAPI dxgi_surface_buffer_Lock(IMFMediaBuffer *iface, BYTE **data, DWORD *max_length,
915 DWORD *current_length)
917 FIXME("%p, %p, %p, %p.\n", iface, data, max_length, current_length);
919 return E_NOTIMPL;
922 static HRESULT WINAPI dxgi_surface_buffer_Unlock(IMFMediaBuffer *iface)
924 FIXME("%p.\n", iface);
926 return E_NOTIMPL;
929 static HRESULT WINAPI dxgi_surface_buffer_SetCurrentLength(IMFMediaBuffer *iface, DWORD current_length)
931 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
933 TRACE("%p, %u.\n", iface, current_length);
935 buffer->current_length = current_length;
937 return S_OK;
940 static HRESULT WINAPI dxgi_surface_buffer_Lock2D(IMF2DBuffer2 *iface, BYTE **scanline0, LONG *pitch)
942 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
943 HRESULT hr = S_OK;
945 TRACE("%p, %p, %p.\n", iface, scanline0, pitch);
947 if (!scanline0 || !pitch)
948 return E_POINTER;
950 EnterCriticalSection(&buffer->cs);
952 if (buffer->_2d.linear_buffer)
953 hr = MF_E_UNEXPECTED;
954 else if (!buffer->_2d.locks++)
955 hr = dxgi_surface_buffer_map(buffer);
957 if (SUCCEEDED(hr))
959 *scanline0 = buffer->dxgi_surface.map_desc.pData;
960 *pitch = buffer->dxgi_surface.map_desc.RowPitch;
963 LeaveCriticalSection(&buffer->cs);
965 return hr;
968 static HRESULT WINAPI dxgi_surface_buffer_Unlock2D(IMF2DBuffer2 *iface)
970 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
971 HRESULT hr = S_OK;
973 TRACE("%p.\n", iface);
975 EnterCriticalSection(&buffer->cs);
977 if (buffer->_2d.locks)
979 if (!--buffer->_2d.locks)
980 dxgi_surface_buffer_unmap(buffer);
982 else
983 hr = HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED);
985 LeaveCriticalSection(&buffer->cs);
987 return hr;
990 static HRESULT WINAPI dxgi_surface_buffer_GetScanline0AndPitch(IMF2DBuffer2 *iface, BYTE **scanline0, LONG *pitch)
992 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
993 HRESULT hr = S_OK;
995 TRACE("%p, %p, %p.\n", iface, scanline0, pitch);
997 if (!scanline0 || !pitch)
998 return E_POINTER;
1000 EnterCriticalSection(&buffer->cs);
1002 if (!buffer->_2d.locks)
1004 *scanline0 = NULL;
1005 *pitch = 0;
1006 hr = HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED);
1008 else
1010 *scanline0 = buffer->dxgi_surface.map_desc.pData;
1011 *pitch = buffer->dxgi_surface.map_desc.RowPitch;
1014 LeaveCriticalSection(&buffer->cs);
1016 return hr;
1019 static HRESULT WINAPI dxgi_surface_buffer_Lock2DSize(IMF2DBuffer2 *iface, MF2DBuffer_LockFlags flags,
1020 BYTE **scanline0, LONG *pitch, BYTE **buffer_start, DWORD *buffer_length)
1022 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
1023 HRESULT hr = S_OK;
1025 TRACE("%p, %#x, %p, %p, %p, %p.\n", iface, flags, scanline0, pitch, buffer_start, buffer_length);
1027 if (!scanline0 || !pitch || !buffer_start || !buffer_length)
1028 return E_POINTER;
1030 EnterCriticalSection(&buffer->cs);
1032 if (buffer->_2d.linear_buffer)
1033 hr = MF_E_UNEXPECTED;
1034 else if (!buffer->_2d.locks++)
1035 hr = dxgi_surface_buffer_map(buffer);
1037 if (SUCCEEDED(hr))
1039 *scanline0 = buffer->dxgi_surface.map_desc.pData;
1040 *pitch = buffer->dxgi_surface.map_desc.RowPitch;
1041 if (buffer_start)
1042 *buffer_start = *scanline0;
1043 if (buffer_length)
1044 *buffer_length = buffer->dxgi_surface.map_desc.RowPitch * buffer->_2d.height;
1047 LeaveCriticalSection(&buffer->cs);
1049 return hr;
1052 static HRESULT WINAPI dxgi_buffer_QueryInterface(IMFDXGIBuffer *iface, REFIID riid, void **obj)
1054 struct buffer *buffer = impl_from_IMFDXGIBuffer(iface);
1055 return IMFMediaBuffer_QueryInterface(&buffer->IMFMediaBuffer_iface, riid, obj);
1058 static ULONG WINAPI dxgi_buffer_AddRef(IMFDXGIBuffer *iface)
1060 struct buffer *buffer = impl_from_IMFDXGIBuffer(iface);
1061 return IMFMediaBuffer_AddRef(&buffer->IMFMediaBuffer_iface);
1064 static ULONG WINAPI dxgi_buffer_Release(IMFDXGIBuffer *iface)
1066 struct buffer *buffer = impl_from_IMFDXGIBuffer(iface);
1067 return IMFMediaBuffer_Release(&buffer->IMFMediaBuffer_iface);
1070 static HRESULT WINAPI dxgi_buffer_GetResource(IMFDXGIBuffer *iface, REFIID riid, void **obj)
1072 struct buffer *buffer = impl_from_IMFDXGIBuffer(iface);
1074 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
1076 return ID3D11Texture2D_QueryInterface(buffer->dxgi_surface.texture, riid, obj);
1079 static HRESULT WINAPI dxgi_buffer_GetSubresourceIndex(IMFDXGIBuffer *iface, UINT *index)
1081 struct buffer *buffer = impl_from_IMFDXGIBuffer(iface);
1083 TRACE("%p, %p.\n", iface, index);
1085 if (!index)
1086 return E_POINTER;
1088 *index = buffer->dxgi_surface.sub_resource_idx;
1090 return S_OK;
1093 static HRESULT WINAPI dxgi_buffer_GetUnknown(IMFDXGIBuffer *iface, REFIID guid, REFIID riid, void **object)
1095 struct buffer *buffer = impl_from_IMFDXGIBuffer(iface);
1097 TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(guid), debugstr_guid(riid), object);
1099 if (attributes_GetUnknown(&buffer->dxgi_surface.attributes, guid, riid, object) == MF_E_ATTRIBUTENOTFOUND)
1100 return MF_E_NOT_FOUND;
1102 return S_OK;
1105 static HRESULT WINAPI dxgi_buffer_SetUnknown(IMFDXGIBuffer *iface, REFIID guid, IUnknown *data)
1107 struct buffer *buffer = impl_from_IMFDXGIBuffer(iface);
1108 HRESULT hr = S_OK;
1110 TRACE("%p, %s, %p.\n", iface, debugstr_guid(guid), data);
1112 EnterCriticalSection(&buffer->dxgi_surface.attributes.cs);
1113 if (data)
1115 if (SUCCEEDED(attributes_GetItem(&buffer->dxgi_surface.attributes, guid, NULL)))
1116 hr = HRESULT_FROM_WIN32(ERROR_OBJECT_ALREADY_EXISTS);
1117 else
1118 hr = attributes_SetUnknown(&buffer->dxgi_surface.attributes, guid, data);
1120 else
1122 attributes_DeleteItem(&buffer->dxgi_surface.attributes, guid);
1124 LeaveCriticalSection(&buffer->dxgi_surface.attributes.cs);
1126 return hr;
1129 static const IMFMediaBufferVtbl dxgi_surface_1d_buffer_vtbl =
1131 dxgi_1d_2d_buffer_QueryInterface,
1132 memory_buffer_AddRef,
1133 memory_buffer_Release,
1134 dxgi_surface_buffer_Lock,
1135 dxgi_surface_buffer_Unlock,
1136 memory_buffer_GetCurrentLength,
1137 dxgi_surface_buffer_SetCurrentLength,
1138 memory_buffer_GetMaxLength,
1141 static const IMF2DBuffer2Vtbl dxgi_surface_buffer_vtbl =
1143 memory_2d_buffer_QueryInterface,
1144 memory_2d_buffer_AddRef,
1145 memory_2d_buffer_Release,
1146 dxgi_surface_buffer_Lock2D,
1147 dxgi_surface_buffer_Unlock2D,
1148 dxgi_surface_buffer_GetScanline0AndPitch,
1149 memory_2d_buffer_IsContiguousFormat,
1150 memory_2d_buffer_GetContiguousLength,
1151 memory_2d_buffer_ContiguousCopyTo,
1152 memory_2d_buffer_ContiguousCopyFrom,
1153 dxgi_surface_buffer_Lock2DSize,
1154 memory_2d_buffer_Copy2DTo,
1157 static const IMFDXGIBufferVtbl dxgi_buffer_vtbl =
1159 dxgi_buffer_QueryInterface,
1160 dxgi_buffer_AddRef,
1161 dxgi_buffer_Release,
1162 dxgi_buffer_GetResource,
1163 dxgi_buffer_GetSubresourceIndex,
1164 dxgi_buffer_GetUnknown,
1165 dxgi_buffer_SetUnknown,
1168 static HRESULT memory_buffer_init(struct buffer *buffer, DWORD max_length, DWORD alignment,
1169 const IMFMediaBufferVtbl *vtbl)
1171 buffer->data = heap_alloc_zero(ALIGN_SIZE(max_length, alignment));
1172 if (!buffer->data)
1173 return E_OUTOFMEMORY;
1175 buffer->IMFMediaBuffer_iface.lpVtbl = vtbl;
1176 buffer->refcount = 1;
1177 buffer->max_length = max_length;
1178 buffer->current_length = 0;
1179 InitializeCriticalSection(&buffer->cs);
1181 return S_OK;
1184 static HRESULT create_1d_buffer(DWORD max_length, DWORD alignment, IMFMediaBuffer **buffer)
1186 struct buffer *object;
1187 HRESULT hr;
1189 if (!buffer)
1190 return E_POINTER;
1192 *buffer = NULL;
1194 object = heap_alloc_zero(sizeof(*object));
1195 if (!object)
1196 return E_OUTOFMEMORY;
1198 hr = memory_buffer_init(object, max_length, alignment, &memory_1d_buffer_vtbl);
1199 if (FAILED(hr))
1201 heap_free(object);
1202 return hr;
1205 *buffer = &object->IMFMediaBuffer_iface;
1207 return S_OK;
1210 static HRESULT create_2d_buffer(DWORD width, DWORD height, DWORD fourcc, BOOL bottom_up, IMFMediaBuffer **buffer)
1212 unsigned int stride, max_length, plane_size;
1213 struct buffer *object;
1214 unsigned int row_alignment;
1215 GUID subtype;
1216 BOOL is_yuv;
1217 HRESULT hr;
1218 int pitch;
1220 if (!buffer)
1221 return E_POINTER;
1223 *buffer = NULL;
1225 memcpy(&subtype, &MFVideoFormat_Base, sizeof(subtype));
1226 subtype.Data1 = fourcc;
1228 if (!(stride = mf_format_get_stride(&subtype, width, &is_yuv)))
1229 return MF_E_INVALIDMEDIATYPE;
1231 if (is_yuv && bottom_up)
1232 return MF_E_INVALIDMEDIATYPE;
1234 if (FAILED(hr = MFGetPlaneSize(fourcc, width, height, &plane_size)))
1235 return hr;
1237 object = heap_alloc_zero(sizeof(*object));
1238 if (!object)
1239 return E_OUTOFMEMORY;
1241 switch (fourcc)
1243 case MAKEFOURCC('I','M','C','1'):
1244 case MAKEFOURCC('I','M','C','2'):
1245 case MAKEFOURCC('I','M','C','3'):
1246 case MAKEFOURCC('I','M','C','4'):
1247 case MAKEFOURCC('Y','V','1','2'):
1248 row_alignment = MF_128_BYTE_ALIGNMENT;
1249 break;
1250 default:
1251 row_alignment = MF_64_BYTE_ALIGNMENT;
1254 pitch = ALIGN_SIZE(stride, row_alignment);
1256 switch (fourcc)
1258 case MAKEFOURCC('I','M','C','1'):
1259 case MAKEFOURCC('I','M','C','3'):
1260 max_length = pitch * height * 2;
1261 plane_size *= 2;
1262 break;
1263 case MAKEFOURCC('N','V','1','2'):
1264 max_length = pitch * height * 3 / 2;
1265 break;
1266 default:
1267 max_length = pitch * height;
1270 if (FAILED(hr = memory_buffer_init(object, max_length, MF_1_BYTE_ALIGNMENT, &memory_1d_2d_buffer_vtbl)))
1272 heap_free(object);
1273 return hr;
1276 object->IMF2DBuffer2_iface.lpVtbl = &memory_2d_buffer_vtbl;
1277 object->IMFGetService_iface.lpVtbl = &memory_2d_buffer_gs_vtbl;
1278 object->_2d.plane_size = plane_size;
1279 object->_2d.width = stride;
1280 object->_2d.height = height;
1281 object->_2d.pitch = bottom_up ? -pitch : pitch;
1282 object->_2d.scanline0 = bottom_up ? object->data + pitch * (object->_2d.height - 1) : object->data;
1284 *buffer = &object->IMFMediaBuffer_iface;
1286 return S_OK;
1289 static HRESULT create_d3d9_surface_buffer(IUnknown *surface, BOOL bottom_up, IMFMediaBuffer **buffer)
1291 struct buffer *object;
1292 D3DSURFACE_DESC desc;
1293 unsigned int stride;
1294 GUID subtype;
1295 BOOL is_yuv;
1297 IDirect3DSurface9_GetDesc((IDirect3DSurface9 *)surface, &desc);
1298 TRACE("format %#x, %u x %u.\n", desc.Format, desc.Width, desc.Height);
1300 memcpy(&subtype, &MFVideoFormat_Base, sizeof(subtype));
1301 subtype.Data1 = desc.Format;
1303 if (!(stride = mf_format_get_stride(&subtype, desc.Width, &is_yuv)))
1304 return MF_E_INVALIDMEDIATYPE;
1306 object = heap_alloc_zero(sizeof(*object));
1307 if (!object)
1308 return E_OUTOFMEMORY;
1310 object->IMFMediaBuffer_iface.lpVtbl = &d3d9_surface_1d_buffer_vtbl;
1311 object->IMF2DBuffer2_iface.lpVtbl = &d3d9_surface_buffer_vtbl;
1312 object->IMFGetService_iface.lpVtbl = &d3d9_surface_buffer_gs_vtbl;
1313 object->refcount = 1;
1314 InitializeCriticalSection(&object->cs);
1315 object->d3d9_surface.surface = (IDirect3DSurface9 *)surface;
1316 IUnknown_AddRef(surface);
1318 MFGetPlaneSize(desc.Format, desc.Width, desc.Height, &object->_2d.plane_size);
1319 object->_2d.width = stride;
1320 object->_2d.height = desc.Height;
1321 object->max_length = object->_2d.plane_size;
1323 *buffer = &object->IMFMediaBuffer_iface;
1325 return S_OK;
1328 static HRESULT create_dxgi_surface_buffer(IUnknown *surface, unsigned int sub_resource_idx,
1329 BOOL bottom_up, IMFMediaBuffer **buffer)
1331 struct buffer *object;
1332 D3D11_TEXTURE2D_DESC desc;
1333 ID3D11Texture2D *texture;
1334 unsigned int stride;
1335 D3DFORMAT format;
1336 GUID subtype;
1337 BOOL is_yuv;
1338 HRESULT hr;
1340 if (FAILED(hr = IUnknown_QueryInterface(surface, &IID_ID3D11Texture2D, (void **)&texture)))
1342 WARN("Failed to get texture interface, hr %#x.\n", hr);
1343 return hr;
1346 ID3D11Texture2D_GetDesc(texture, &desc);
1347 TRACE("format %#x, %u x %u.\n", desc.Format, desc.Width, desc.Height);
1349 memcpy(&subtype, &MFVideoFormat_Base, sizeof(subtype));
1350 subtype.Data1 = format = MFMapDXGIFormatToDX9Format(desc.Format);
1352 if (!(stride = mf_format_get_stride(&subtype, desc.Width, &is_yuv)))
1354 ID3D11Texture2D_Release(texture);
1355 return MF_E_INVALIDMEDIATYPE;
1358 object = heap_alloc_zero(sizeof(*object));
1359 if (!object)
1361 ID3D11Texture2D_Release(texture);
1362 return E_OUTOFMEMORY;
1365 object->IMFMediaBuffer_iface.lpVtbl = &dxgi_surface_1d_buffer_vtbl;
1366 object->IMF2DBuffer2_iface.lpVtbl = &dxgi_surface_buffer_vtbl;
1367 object->IMFDXGIBuffer_iface.lpVtbl = &dxgi_buffer_vtbl;
1368 object->refcount = 1;
1369 InitializeCriticalSection(&object->cs);
1370 object->dxgi_surface.texture = texture;
1371 object->dxgi_surface.sub_resource_idx = sub_resource_idx;
1373 MFGetPlaneSize(format, desc.Width, desc.Height, &object->_2d.plane_size);
1374 object->_2d.width = stride;
1375 object->_2d.height = desc.Height;
1376 object->max_length = object->_2d.plane_size;
1378 if (FAILED(hr = init_attributes_object(&object->dxgi_surface.attributes, 0)))
1380 IMFMediaBuffer_Release(&object->IMFMediaBuffer_iface);
1381 return hr;
1384 *buffer = &object->IMFMediaBuffer_iface;
1386 return S_OK;
1389 /***********************************************************************
1390 * MFCreateMemoryBuffer (mfplat.@)
1392 HRESULT WINAPI MFCreateMemoryBuffer(DWORD max_length, IMFMediaBuffer **buffer)
1394 TRACE("%u, %p.\n", max_length, buffer);
1396 return create_1d_buffer(max_length, MF_1_BYTE_ALIGNMENT, buffer);
1399 /***********************************************************************
1400 * MFCreateAlignedMemoryBuffer (mfplat.@)
1402 HRESULT WINAPI MFCreateAlignedMemoryBuffer(DWORD max_length, DWORD alignment, IMFMediaBuffer **buffer)
1404 TRACE("%u, %u, %p.\n", max_length, alignment, buffer);
1406 return create_1d_buffer(max_length, alignment, buffer);
1409 /***********************************************************************
1410 * MFCreate2DMediaBuffer (mfplat.@)
1412 HRESULT WINAPI MFCreate2DMediaBuffer(DWORD width, DWORD height, DWORD fourcc, BOOL bottom_up, IMFMediaBuffer **buffer)
1414 TRACE("%u, %u, %s, %d, %p.\n", width, height, debugstr_fourcc(fourcc), bottom_up, buffer);
1416 return create_2d_buffer(width, height, fourcc, bottom_up, buffer);
1419 /***********************************************************************
1420 * MFCreateDXSurfaceBuffer (mfplat.@)
1422 HRESULT WINAPI MFCreateDXSurfaceBuffer(REFIID riid, IUnknown *surface, BOOL bottom_up, IMFMediaBuffer **buffer)
1424 TRACE("%s, %p, %d, %p.\n", debugstr_guid(riid), surface, bottom_up, buffer);
1426 if (!IsEqualIID(riid, &IID_IDirect3DSurface9))
1427 return E_INVALIDARG;
1429 return create_d3d9_surface_buffer(surface, bottom_up, buffer);
1432 /***********************************************************************
1433 * MFCreateDXGISurfaceBuffer (mfplat.@)
1435 HRESULT WINAPI MFCreateDXGISurfaceBuffer(REFIID riid, IUnknown *surface, UINT subresource, BOOL bottom_up,
1436 IMFMediaBuffer **buffer)
1438 TRACE("%s, %p, %u, %d, %p.\n", debugstr_guid(riid), surface, subresource, bottom_up, buffer);
1440 if (!IsEqualIID(riid, &IID_ID3D11Texture2D))
1441 return E_INVALIDARG;
1443 return create_dxgi_surface_buffer(surface, subresource, bottom_up, buffer);
1446 static unsigned int buffer_get_aligned_length(unsigned int length, unsigned int alignment)
1448 length = (length + alignment) / alignment;
1449 length *= alignment;
1451 return length;
1454 HRESULT WINAPI MFCreateMediaBufferFromMediaType(IMFMediaType *media_type, LONGLONG duration, DWORD min_length,
1455 DWORD alignment, IMFMediaBuffer **buffer)
1457 UINT32 length = 0, block_alignment;
1458 LONGLONG avg_length;
1459 HRESULT hr;
1460 GUID major;
1462 TRACE("%p, %s, %u, %u, %p.\n", media_type, debugstr_time(duration), min_length, alignment, buffer);
1464 if (!media_type)
1465 return E_INVALIDARG;
1467 if (FAILED(hr = IMFMediaType_GetMajorType(media_type, &major)))
1468 return hr;
1470 if (IsEqualGUID(&major, &MFMediaType_Audio))
1472 block_alignment = 0;
1473 if (FAILED(IMFMediaType_GetUINT32(media_type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, &block_alignment)))
1474 WARN("Block alignment was not specified.\n");
1476 if (block_alignment)
1478 avg_length = 0;
1480 if (duration)
1482 length = 0;
1483 if (SUCCEEDED(IMFMediaType_GetUINT32(media_type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, &length)))
1485 /* 100 ns -> 1 s */
1486 avg_length = length * duration / (10 * 1000 * 1000);
1490 alignment = max(16, alignment);
1492 length = buffer_get_aligned_length(avg_length + 1, alignment);
1493 length = buffer_get_aligned_length(length, block_alignment);
1495 else
1496 length = 0;
1498 length = max(length, min_length);
1500 return create_1d_buffer(length, MF_1_BYTE_ALIGNMENT, buffer);
1502 else
1503 FIXME("Major type %s is not supported.\n", debugstr_guid(&major));
1505 return E_NOTIMPL;