mf/session: Forward more events to the application.
[wine/zf.git] / dlls / mfplat / buffer.c
blobf428630ea019f7bc86d1e49458d95f5f2803db92
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 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
918 HRESULT hr = S_OK;
920 TRACE("%p, %p, %p, %p.\n", iface, data, max_length, current_length);
922 if (!data)
923 return E_POINTER;
925 EnterCriticalSection(&buffer->cs);
927 if (!buffer->_2d.linear_buffer && buffer->_2d.locks)
928 hr = MF_E_INVALIDREQUEST;
929 else if (!buffer->_2d.linear_buffer)
931 if (!(buffer->_2d.linear_buffer = heap_alloc(ALIGN_SIZE(buffer->_2d.plane_size, MF_64_BYTE_ALIGNMENT))))
932 hr = E_OUTOFMEMORY;
934 if (SUCCEEDED(hr))
936 hr = dxgi_surface_buffer_map(buffer);
937 if (SUCCEEDED(hr))
939 MFCopyImage(buffer->_2d.linear_buffer, buffer->_2d.width, buffer->dxgi_surface.map_desc.pData,
940 buffer->dxgi_surface.map_desc.RowPitch, buffer->_2d.width, buffer->_2d.height);
945 if (SUCCEEDED(hr))
947 ++buffer->_2d.locks;
948 *data = buffer->_2d.linear_buffer;
949 if (max_length)
950 *max_length = buffer->_2d.plane_size;
951 if (current_length)
952 *current_length = buffer->_2d.plane_size;
955 LeaveCriticalSection(&buffer->cs);
957 return hr;
960 static HRESULT WINAPI dxgi_surface_buffer_Unlock(IMFMediaBuffer *iface)
962 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
963 HRESULT hr = S_OK;
965 TRACE("%p.\n", iface);
967 EnterCriticalSection(&buffer->cs);
969 if (!buffer->_2d.linear_buffer)
970 hr = HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED);
971 else if (!--buffer->_2d.locks)
973 MFCopyImage(buffer->dxgi_surface.map_desc.pData, buffer->dxgi_surface.map_desc.RowPitch,
974 buffer->_2d.linear_buffer, buffer->_2d.width, buffer->_2d.width, buffer->_2d.height);
975 dxgi_surface_buffer_unmap(buffer);
977 heap_free(buffer->_2d.linear_buffer);
978 buffer->_2d.linear_buffer = NULL;
981 LeaveCriticalSection(&buffer->cs);
983 return hr;
986 static HRESULT WINAPI dxgi_surface_buffer_SetCurrentLength(IMFMediaBuffer *iface, DWORD current_length)
988 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
990 TRACE("%p, %u.\n", iface, current_length);
992 buffer->current_length = current_length;
994 return S_OK;
997 static HRESULT WINAPI dxgi_surface_buffer_Lock2D(IMF2DBuffer2 *iface, BYTE **scanline0, LONG *pitch)
999 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
1000 HRESULT hr = S_OK;
1002 TRACE("%p, %p, %p.\n", iface, scanline0, pitch);
1004 if (!scanline0 || !pitch)
1005 return E_POINTER;
1007 EnterCriticalSection(&buffer->cs);
1009 if (buffer->_2d.linear_buffer)
1010 hr = MF_E_UNEXPECTED;
1011 else if (!buffer->_2d.locks++)
1012 hr = dxgi_surface_buffer_map(buffer);
1014 if (SUCCEEDED(hr))
1016 *scanline0 = buffer->dxgi_surface.map_desc.pData;
1017 *pitch = buffer->dxgi_surface.map_desc.RowPitch;
1020 LeaveCriticalSection(&buffer->cs);
1022 return hr;
1025 static HRESULT WINAPI dxgi_surface_buffer_Unlock2D(IMF2DBuffer2 *iface)
1027 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
1028 HRESULT hr = S_OK;
1030 TRACE("%p.\n", iface);
1032 EnterCriticalSection(&buffer->cs);
1034 if (buffer->_2d.locks)
1036 if (!--buffer->_2d.locks)
1037 dxgi_surface_buffer_unmap(buffer);
1039 else
1040 hr = HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED);
1042 LeaveCriticalSection(&buffer->cs);
1044 return hr;
1047 static HRESULT WINAPI dxgi_surface_buffer_GetScanline0AndPitch(IMF2DBuffer2 *iface, BYTE **scanline0, LONG *pitch)
1049 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
1050 HRESULT hr = S_OK;
1052 TRACE("%p, %p, %p.\n", iface, scanline0, pitch);
1054 if (!scanline0 || !pitch)
1055 return E_POINTER;
1057 EnterCriticalSection(&buffer->cs);
1059 if (!buffer->_2d.locks)
1061 *scanline0 = NULL;
1062 *pitch = 0;
1063 hr = HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED);
1065 else
1067 *scanline0 = buffer->dxgi_surface.map_desc.pData;
1068 *pitch = buffer->dxgi_surface.map_desc.RowPitch;
1071 LeaveCriticalSection(&buffer->cs);
1073 return hr;
1076 static HRESULT WINAPI dxgi_surface_buffer_Lock2DSize(IMF2DBuffer2 *iface, MF2DBuffer_LockFlags flags,
1077 BYTE **scanline0, LONG *pitch, BYTE **buffer_start, DWORD *buffer_length)
1079 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
1080 HRESULT hr = S_OK;
1082 TRACE("%p, %#x, %p, %p, %p, %p.\n", iface, flags, scanline0, pitch, buffer_start, buffer_length);
1084 if (!scanline0 || !pitch || !buffer_start || !buffer_length)
1085 return E_POINTER;
1087 EnterCriticalSection(&buffer->cs);
1089 if (buffer->_2d.linear_buffer)
1090 hr = MF_E_UNEXPECTED;
1091 else if (!buffer->_2d.locks++)
1092 hr = dxgi_surface_buffer_map(buffer);
1094 if (SUCCEEDED(hr))
1096 *scanline0 = buffer->dxgi_surface.map_desc.pData;
1097 *pitch = buffer->dxgi_surface.map_desc.RowPitch;
1098 if (buffer_start)
1099 *buffer_start = *scanline0;
1100 if (buffer_length)
1101 *buffer_length = buffer->dxgi_surface.map_desc.RowPitch * buffer->_2d.height;
1104 LeaveCriticalSection(&buffer->cs);
1106 return hr;
1109 static HRESULT WINAPI dxgi_buffer_QueryInterface(IMFDXGIBuffer *iface, REFIID riid, void **obj)
1111 struct buffer *buffer = impl_from_IMFDXGIBuffer(iface);
1112 return IMFMediaBuffer_QueryInterface(&buffer->IMFMediaBuffer_iface, riid, obj);
1115 static ULONG WINAPI dxgi_buffer_AddRef(IMFDXGIBuffer *iface)
1117 struct buffer *buffer = impl_from_IMFDXGIBuffer(iface);
1118 return IMFMediaBuffer_AddRef(&buffer->IMFMediaBuffer_iface);
1121 static ULONG WINAPI dxgi_buffer_Release(IMFDXGIBuffer *iface)
1123 struct buffer *buffer = impl_from_IMFDXGIBuffer(iface);
1124 return IMFMediaBuffer_Release(&buffer->IMFMediaBuffer_iface);
1127 static HRESULT WINAPI dxgi_buffer_GetResource(IMFDXGIBuffer *iface, REFIID riid, void **obj)
1129 struct buffer *buffer = impl_from_IMFDXGIBuffer(iface);
1131 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
1133 return ID3D11Texture2D_QueryInterface(buffer->dxgi_surface.texture, riid, obj);
1136 static HRESULT WINAPI dxgi_buffer_GetSubresourceIndex(IMFDXGIBuffer *iface, UINT *index)
1138 struct buffer *buffer = impl_from_IMFDXGIBuffer(iface);
1140 TRACE("%p, %p.\n", iface, index);
1142 if (!index)
1143 return E_POINTER;
1145 *index = buffer->dxgi_surface.sub_resource_idx;
1147 return S_OK;
1150 static HRESULT WINAPI dxgi_buffer_GetUnknown(IMFDXGIBuffer *iface, REFIID guid, REFIID riid, void **object)
1152 struct buffer *buffer = impl_from_IMFDXGIBuffer(iface);
1154 TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(guid), debugstr_guid(riid), object);
1156 if (attributes_GetUnknown(&buffer->dxgi_surface.attributes, guid, riid, object) == MF_E_ATTRIBUTENOTFOUND)
1157 return MF_E_NOT_FOUND;
1159 return S_OK;
1162 static HRESULT WINAPI dxgi_buffer_SetUnknown(IMFDXGIBuffer *iface, REFIID guid, IUnknown *data)
1164 struct buffer *buffer = impl_from_IMFDXGIBuffer(iface);
1165 HRESULT hr = S_OK;
1167 TRACE("%p, %s, %p.\n", iface, debugstr_guid(guid), data);
1169 EnterCriticalSection(&buffer->dxgi_surface.attributes.cs);
1170 if (data)
1172 if (SUCCEEDED(attributes_GetItem(&buffer->dxgi_surface.attributes, guid, NULL)))
1173 hr = HRESULT_FROM_WIN32(ERROR_OBJECT_ALREADY_EXISTS);
1174 else
1175 hr = attributes_SetUnknown(&buffer->dxgi_surface.attributes, guid, data);
1177 else
1179 attributes_DeleteItem(&buffer->dxgi_surface.attributes, guid);
1181 LeaveCriticalSection(&buffer->dxgi_surface.attributes.cs);
1183 return hr;
1186 static const IMFMediaBufferVtbl dxgi_surface_1d_buffer_vtbl =
1188 dxgi_1d_2d_buffer_QueryInterface,
1189 memory_buffer_AddRef,
1190 memory_buffer_Release,
1191 dxgi_surface_buffer_Lock,
1192 dxgi_surface_buffer_Unlock,
1193 memory_buffer_GetCurrentLength,
1194 dxgi_surface_buffer_SetCurrentLength,
1195 memory_buffer_GetMaxLength,
1198 static const IMF2DBuffer2Vtbl dxgi_surface_buffer_vtbl =
1200 memory_2d_buffer_QueryInterface,
1201 memory_2d_buffer_AddRef,
1202 memory_2d_buffer_Release,
1203 dxgi_surface_buffer_Lock2D,
1204 dxgi_surface_buffer_Unlock2D,
1205 dxgi_surface_buffer_GetScanline0AndPitch,
1206 memory_2d_buffer_IsContiguousFormat,
1207 memory_2d_buffer_GetContiguousLength,
1208 memory_2d_buffer_ContiguousCopyTo,
1209 memory_2d_buffer_ContiguousCopyFrom,
1210 dxgi_surface_buffer_Lock2DSize,
1211 memory_2d_buffer_Copy2DTo,
1214 static const IMFDXGIBufferVtbl dxgi_buffer_vtbl =
1216 dxgi_buffer_QueryInterface,
1217 dxgi_buffer_AddRef,
1218 dxgi_buffer_Release,
1219 dxgi_buffer_GetResource,
1220 dxgi_buffer_GetSubresourceIndex,
1221 dxgi_buffer_GetUnknown,
1222 dxgi_buffer_SetUnknown,
1225 static HRESULT memory_buffer_init(struct buffer *buffer, DWORD max_length, DWORD alignment,
1226 const IMFMediaBufferVtbl *vtbl)
1228 buffer->data = heap_alloc_zero(ALIGN_SIZE(max_length, alignment));
1229 if (!buffer->data)
1230 return E_OUTOFMEMORY;
1232 buffer->IMFMediaBuffer_iface.lpVtbl = vtbl;
1233 buffer->refcount = 1;
1234 buffer->max_length = max_length;
1235 buffer->current_length = 0;
1236 InitializeCriticalSection(&buffer->cs);
1238 return S_OK;
1241 static HRESULT create_1d_buffer(DWORD max_length, DWORD alignment, IMFMediaBuffer **buffer)
1243 struct buffer *object;
1244 HRESULT hr;
1246 if (!buffer)
1247 return E_POINTER;
1249 *buffer = NULL;
1251 object = heap_alloc_zero(sizeof(*object));
1252 if (!object)
1253 return E_OUTOFMEMORY;
1255 hr = memory_buffer_init(object, max_length, alignment, &memory_1d_buffer_vtbl);
1256 if (FAILED(hr))
1258 heap_free(object);
1259 return hr;
1262 *buffer = &object->IMFMediaBuffer_iface;
1264 return S_OK;
1267 static HRESULT create_2d_buffer(DWORD width, DWORD height, DWORD fourcc, BOOL bottom_up, IMFMediaBuffer **buffer)
1269 unsigned int stride, max_length, plane_size;
1270 struct buffer *object;
1271 unsigned int row_alignment;
1272 GUID subtype;
1273 BOOL is_yuv;
1274 HRESULT hr;
1275 int pitch;
1277 if (!buffer)
1278 return E_POINTER;
1280 *buffer = NULL;
1282 memcpy(&subtype, &MFVideoFormat_Base, sizeof(subtype));
1283 subtype.Data1 = fourcc;
1285 if (!(stride = mf_format_get_stride(&subtype, width, &is_yuv)))
1286 return MF_E_INVALIDMEDIATYPE;
1288 if (is_yuv && bottom_up)
1289 return MF_E_INVALIDMEDIATYPE;
1291 if (FAILED(hr = MFGetPlaneSize(fourcc, width, height, &plane_size)))
1292 return hr;
1294 object = heap_alloc_zero(sizeof(*object));
1295 if (!object)
1296 return E_OUTOFMEMORY;
1298 switch (fourcc)
1300 case MAKEFOURCC('I','M','C','1'):
1301 case MAKEFOURCC('I','M','C','2'):
1302 case MAKEFOURCC('I','M','C','3'):
1303 case MAKEFOURCC('I','M','C','4'):
1304 case MAKEFOURCC('Y','V','1','2'):
1305 row_alignment = MF_128_BYTE_ALIGNMENT;
1306 break;
1307 default:
1308 row_alignment = MF_64_BYTE_ALIGNMENT;
1311 pitch = ALIGN_SIZE(stride, row_alignment);
1313 switch (fourcc)
1315 case MAKEFOURCC('I','M','C','1'):
1316 case MAKEFOURCC('I','M','C','3'):
1317 max_length = pitch * height * 2;
1318 plane_size *= 2;
1319 break;
1320 case MAKEFOURCC('N','V','1','2'):
1321 max_length = pitch * height * 3 / 2;
1322 break;
1323 default:
1324 max_length = pitch * height;
1327 if (FAILED(hr = memory_buffer_init(object, max_length, MF_1_BYTE_ALIGNMENT, &memory_1d_2d_buffer_vtbl)))
1329 heap_free(object);
1330 return hr;
1333 object->IMF2DBuffer2_iface.lpVtbl = &memory_2d_buffer_vtbl;
1334 object->IMFGetService_iface.lpVtbl = &memory_2d_buffer_gs_vtbl;
1335 object->_2d.plane_size = plane_size;
1336 object->_2d.width = stride;
1337 object->_2d.height = height;
1338 object->_2d.pitch = bottom_up ? -pitch : pitch;
1339 object->_2d.scanline0 = bottom_up ? object->data + pitch * (object->_2d.height - 1) : object->data;
1341 *buffer = &object->IMFMediaBuffer_iface;
1343 return S_OK;
1346 static HRESULT create_d3d9_surface_buffer(IUnknown *surface, BOOL bottom_up, IMFMediaBuffer **buffer)
1348 struct buffer *object;
1349 D3DSURFACE_DESC desc;
1350 unsigned int stride;
1351 GUID subtype;
1352 BOOL is_yuv;
1354 IDirect3DSurface9_GetDesc((IDirect3DSurface9 *)surface, &desc);
1355 TRACE("format %#x, %u x %u.\n", desc.Format, desc.Width, desc.Height);
1357 memcpy(&subtype, &MFVideoFormat_Base, sizeof(subtype));
1358 subtype.Data1 = desc.Format;
1360 if (!(stride = mf_format_get_stride(&subtype, desc.Width, &is_yuv)))
1361 return MF_E_INVALIDMEDIATYPE;
1363 object = heap_alloc_zero(sizeof(*object));
1364 if (!object)
1365 return E_OUTOFMEMORY;
1367 object->IMFMediaBuffer_iface.lpVtbl = &d3d9_surface_1d_buffer_vtbl;
1368 object->IMF2DBuffer2_iface.lpVtbl = &d3d9_surface_buffer_vtbl;
1369 object->IMFGetService_iface.lpVtbl = &d3d9_surface_buffer_gs_vtbl;
1370 object->refcount = 1;
1371 InitializeCriticalSection(&object->cs);
1372 object->d3d9_surface.surface = (IDirect3DSurface9 *)surface;
1373 IUnknown_AddRef(surface);
1375 MFGetPlaneSize(desc.Format, desc.Width, desc.Height, &object->_2d.plane_size);
1376 object->_2d.width = stride;
1377 object->_2d.height = desc.Height;
1378 object->max_length = object->_2d.plane_size;
1380 *buffer = &object->IMFMediaBuffer_iface;
1382 return S_OK;
1385 static HRESULT create_dxgi_surface_buffer(IUnknown *surface, unsigned int sub_resource_idx,
1386 BOOL bottom_up, IMFMediaBuffer **buffer)
1388 struct buffer *object;
1389 D3D11_TEXTURE2D_DESC desc;
1390 ID3D11Texture2D *texture;
1391 unsigned int stride;
1392 D3DFORMAT format;
1393 GUID subtype;
1394 BOOL is_yuv;
1395 HRESULT hr;
1397 if (FAILED(hr = IUnknown_QueryInterface(surface, &IID_ID3D11Texture2D, (void **)&texture)))
1399 WARN("Failed to get texture interface, hr %#x.\n", hr);
1400 return hr;
1403 ID3D11Texture2D_GetDesc(texture, &desc);
1404 TRACE("format %#x, %u x %u.\n", desc.Format, desc.Width, desc.Height);
1406 memcpy(&subtype, &MFVideoFormat_Base, sizeof(subtype));
1407 subtype.Data1 = format = MFMapDXGIFormatToDX9Format(desc.Format);
1409 if (!(stride = mf_format_get_stride(&subtype, desc.Width, &is_yuv)))
1411 ID3D11Texture2D_Release(texture);
1412 return MF_E_INVALIDMEDIATYPE;
1415 object = heap_alloc_zero(sizeof(*object));
1416 if (!object)
1418 ID3D11Texture2D_Release(texture);
1419 return E_OUTOFMEMORY;
1422 object->IMFMediaBuffer_iface.lpVtbl = &dxgi_surface_1d_buffer_vtbl;
1423 object->IMF2DBuffer2_iface.lpVtbl = &dxgi_surface_buffer_vtbl;
1424 object->IMFDXGIBuffer_iface.lpVtbl = &dxgi_buffer_vtbl;
1425 object->refcount = 1;
1426 InitializeCriticalSection(&object->cs);
1427 object->dxgi_surface.texture = texture;
1428 object->dxgi_surface.sub_resource_idx = sub_resource_idx;
1430 MFGetPlaneSize(format, desc.Width, desc.Height, &object->_2d.plane_size);
1431 object->_2d.width = stride;
1432 object->_2d.height = desc.Height;
1433 object->max_length = object->_2d.plane_size;
1435 if (FAILED(hr = init_attributes_object(&object->dxgi_surface.attributes, 0)))
1437 IMFMediaBuffer_Release(&object->IMFMediaBuffer_iface);
1438 return hr;
1441 *buffer = &object->IMFMediaBuffer_iface;
1443 return S_OK;
1446 /***********************************************************************
1447 * MFCreateMemoryBuffer (mfplat.@)
1449 HRESULT WINAPI MFCreateMemoryBuffer(DWORD max_length, IMFMediaBuffer **buffer)
1451 TRACE("%u, %p.\n", max_length, buffer);
1453 return create_1d_buffer(max_length, MF_1_BYTE_ALIGNMENT, buffer);
1456 /***********************************************************************
1457 * MFCreateAlignedMemoryBuffer (mfplat.@)
1459 HRESULT WINAPI MFCreateAlignedMemoryBuffer(DWORD max_length, DWORD alignment, IMFMediaBuffer **buffer)
1461 TRACE("%u, %u, %p.\n", max_length, alignment, buffer);
1463 return create_1d_buffer(max_length, alignment, buffer);
1466 /***********************************************************************
1467 * MFCreate2DMediaBuffer (mfplat.@)
1469 HRESULT WINAPI MFCreate2DMediaBuffer(DWORD width, DWORD height, DWORD fourcc, BOOL bottom_up, IMFMediaBuffer **buffer)
1471 TRACE("%u, %u, %s, %d, %p.\n", width, height, debugstr_fourcc(fourcc), bottom_up, buffer);
1473 return create_2d_buffer(width, height, fourcc, bottom_up, buffer);
1476 /***********************************************************************
1477 * MFCreateDXSurfaceBuffer (mfplat.@)
1479 HRESULT WINAPI MFCreateDXSurfaceBuffer(REFIID riid, IUnknown *surface, BOOL bottom_up, IMFMediaBuffer **buffer)
1481 TRACE("%s, %p, %d, %p.\n", debugstr_guid(riid), surface, bottom_up, buffer);
1483 if (!IsEqualIID(riid, &IID_IDirect3DSurface9))
1484 return E_INVALIDARG;
1486 return create_d3d9_surface_buffer(surface, bottom_up, buffer);
1489 /***********************************************************************
1490 * MFCreateDXGISurfaceBuffer (mfplat.@)
1492 HRESULT WINAPI MFCreateDXGISurfaceBuffer(REFIID riid, IUnknown *surface, UINT subresource, BOOL bottom_up,
1493 IMFMediaBuffer **buffer)
1495 TRACE("%s, %p, %u, %d, %p.\n", debugstr_guid(riid), surface, subresource, bottom_up, buffer);
1497 if (!IsEqualIID(riid, &IID_ID3D11Texture2D))
1498 return E_INVALIDARG;
1500 return create_dxgi_surface_buffer(surface, subresource, bottom_up, buffer);
1503 static unsigned int buffer_get_aligned_length(unsigned int length, unsigned int alignment)
1505 length = (length + alignment) / alignment;
1506 length *= alignment;
1508 return length;
1511 HRESULT WINAPI MFCreateMediaBufferFromMediaType(IMFMediaType *media_type, LONGLONG duration, DWORD min_length,
1512 DWORD alignment, IMFMediaBuffer **buffer)
1514 UINT32 length = 0, block_alignment;
1515 LONGLONG avg_length;
1516 HRESULT hr;
1517 GUID major;
1519 TRACE("%p, %s, %u, %u, %p.\n", media_type, debugstr_time(duration), min_length, alignment, buffer);
1521 if (!media_type)
1522 return E_INVALIDARG;
1524 if (FAILED(hr = IMFMediaType_GetMajorType(media_type, &major)))
1525 return hr;
1527 if (IsEqualGUID(&major, &MFMediaType_Audio))
1529 block_alignment = 0;
1530 if (FAILED(IMFMediaType_GetUINT32(media_type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, &block_alignment)))
1531 WARN("Block alignment was not specified.\n");
1533 if (block_alignment)
1535 avg_length = 0;
1537 if (duration)
1539 length = 0;
1540 if (SUCCEEDED(IMFMediaType_GetUINT32(media_type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, &length)))
1542 /* 100 ns -> 1 s */
1543 avg_length = length * duration / (10 * 1000 * 1000);
1547 alignment = max(16, alignment);
1549 length = buffer_get_aligned_length(avg_length + 1, alignment);
1550 length = buffer_get_aligned_length(length, block_alignment);
1552 else
1553 length = 0;
1555 length = max(length, min_length);
1557 return create_1d_buffer(length, MF_1_BYTE_ALIGNMENT, buffer);
1559 else
1560 FIXME("Major type %s is not supported.\n", debugstr_guid(&major));
1562 return E_NOTIMPL;