dinput: Delete the action mapping registry key on SetActionMap.
[wine.git] / dlls / mfplat / buffer.c
blobcb1b3176a08a9f48e181cc2bcb50f38c89a33f91
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 <malloc.h>
23 #include "mfplat_private.h"
24 #include "rtworkq.h"
26 #include "d3d11.h"
27 #include "initguid.h"
28 #include "d3d9.h"
29 #include "evr.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
33 #define ALIGN_SIZE(size, alignment) (((size) + (alignment)) & ~((alignment)))
35 typedef void (*p_copy_image_func)(BYTE *dest, LONG dest_stride, const BYTE *src, LONG src_stride, DWORD width, DWORD lines);
37 struct buffer
39 IMFMediaBuffer IMFMediaBuffer_iface;
40 IMF2DBuffer2 IMF2DBuffer2_iface;
41 IMFDXGIBuffer IMFDXGIBuffer_iface;
42 IMFGetService IMFGetService_iface;
43 LONG refcount;
45 BYTE *data;
46 DWORD max_length;
47 DWORD current_length;
49 struct
51 BYTE *linear_buffer;
52 DWORD plane_size;
54 BYTE *scanline0;
55 unsigned int width;
56 unsigned int height;
57 int pitch;
58 unsigned int locks;
59 MF2DBuffer_LockFlags lock_flags;
60 p_copy_image_func copy_image;
61 } _2d;
62 struct
64 IDirect3DSurface9 *surface;
65 D3DLOCKED_RECT rect;
66 } d3d9_surface;
67 struct
69 ID3D11Texture2D *texture;
70 unsigned int sub_resource_idx;
71 ID3D11Texture2D *rb_texture;
72 D3D11_MAPPED_SUBRESOURCE map_desc;
73 struct attributes attributes;
74 } dxgi_surface;
76 CRITICAL_SECTION cs;
79 static void copy_image(const struct buffer *buffer, BYTE *dest, LONG dest_stride, const BYTE *src,
80 LONG src_stride, DWORD width, DWORD lines)
82 MFCopyImage(dest, dest_stride, src, src_stride, width, lines);
84 if (buffer->_2d.copy_image)
86 dest += dest_stride * lines;
87 src += src_stride * lines;
88 buffer->_2d.copy_image(dest, dest_stride, src, src_stride, width, lines);
92 static void copy_image_nv12(BYTE *dest, LONG dest_stride, const BYTE *src, LONG src_stride, DWORD width, DWORD lines)
94 MFCopyImage(dest, dest_stride, src, src_stride, width, lines / 2);
97 static void copy_image_imc1(BYTE *dest, LONG dest_stride, const BYTE *src, LONG src_stride, DWORD width, DWORD lines)
99 MFCopyImage(dest, dest_stride, src, src_stride, width / 2, lines);
102 static void copy_image_imc2(BYTE *dest, LONG dest_stride, const BYTE *src, LONG src_stride, DWORD width, DWORD lines)
104 MFCopyImage(dest, dest_stride / 2, src, src_stride / 2, width / 2, lines);
107 static inline struct buffer *impl_from_IMFMediaBuffer(IMFMediaBuffer *iface)
109 return CONTAINING_RECORD(iface, struct buffer, IMFMediaBuffer_iface);
112 static struct buffer *impl_from_IMF2DBuffer2(IMF2DBuffer2 *iface)
114 return CONTAINING_RECORD(iface, struct buffer, IMF2DBuffer2_iface);
117 static struct buffer *impl_from_IMFGetService(IMFGetService *iface)
119 return CONTAINING_RECORD(iface, struct buffer, IMFGetService_iface);
122 static struct buffer *impl_from_IMFDXGIBuffer(IMFDXGIBuffer *iface)
124 return CONTAINING_RECORD(iface, struct buffer, IMFDXGIBuffer_iface);
127 static HRESULT WINAPI memory_buffer_QueryInterface(IMFMediaBuffer *iface, REFIID riid, void **out)
129 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
131 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
133 if (IsEqualIID(riid, &IID_IMFMediaBuffer) ||
134 IsEqualIID(riid, &IID_IUnknown))
136 *out = &buffer->IMFMediaBuffer_iface;
137 IMFMediaBuffer_AddRef(iface);
138 return S_OK;
141 WARN("Unsupported %s.\n", debugstr_guid(riid));
142 *out = NULL;
143 return E_NOINTERFACE;
146 static ULONG WINAPI memory_buffer_AddRef(IMFMediaBuffer *iface)
148 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
149 ULONG refcount = InterlockedIncrement(&buffer->refcount);
151 TRACE("%p, refcount %lu.\n", buffer, refcount);
153 return refcount;
156 static ULONG WINAPI memory_buffer_Release(IMFMediaBuffer *iface)
158 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
159 ULONG refcount = InterlockedDecrement(&buffer->refcount);
161 TRACE("%p, refcount %lu.\n", iface, refcount);
163 if (!refcount)
165 if (buffer->d3d9_surface.surface)
166 IDirect3DSurface9_Release(buffer->d3d9_surface.surface);
167 if (buffer->dxgi_surface.texture)
169 ID3D11Texture2D_Release(buffer->dxgi_surface.texture);
170 if (buffer->dxgi_surface.rb_texture)
171 ID3D11Texture2D_Release(buffer->dxgi_surface.rb_texture);
172 clear_attributes_object(&buffer->dxgi_surface.attributes);
174 DeleteCriticalSection(&buffer->cs);
175 free(buffer->_2d.linear_buffer);
176 _aligned_free(buffer->data);
177 free(buffer);
180 return refcount;
183 static HRESULT WINAPI memory_buffer_Lock(IMFMediaBuffer *iface, BYTE **data, DWORD *max_length, DWORD *current_length)
185 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
187 TRACE("%p, %p %p, %p.\n", iface, data, max_length, current_length);
189 if (!data)
190 return E_INVALIDARG;
192 *data = buffer->data;
193 if (max_length)
194 *max_length = buffer->max_length;
195 if (current_length)
196 *current_length = buffer->current_length;
198 return S_OK;
201 static HRESULT WINAPI memory_buffer_Unlock(IMFMediaBuffer *iface)
203 TRACE("%p.\n", iface);
205 return S_OK;
208 static HRESULT WINAPI memory_buffer_GetCurrentLength(IMFMediaBuffer *iface, DWORD *current_length)
210 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
212 TRACE("%p.\n", iface);
214 if (!current_length)
215 return E_INVALIDARG;
217 *current_length = buffer->current_length;
219 return S_OK;
222 static HRESULT WINAPI memory_buffer_SetCurrentLength(IMFMediaBuffer *iface, DWORD current_length)
224 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
226 TRACE("%p, %lu.\n", iface, current_length);
228 if (current_length > buffer->max_length)
229 return E_INVALIDARG;
231 buffer->current_length = current_length;
233 return S_OK;
236 static HRESULT WINAPI memory_buffer_GetMaxLength(IMFMediaBuffer *iface, DWORD *max_length)
238 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
240 TRACE("%p, %p.\n", iface, max_length);
242 if (!max_length)
243 return E_INVALIDARG;
245 *max_length = buffer->max_length;
247 return S_OK;
250 static const IMFMediaBufferVtbl memory_1d_buffer_vtbl =
252 memory_buffer_QueryInterface,
253 memory_buffer_AddRef,
254 memory_buffer_Release,
255 memory_buffer_Lock,
256 memory_buffer_Unlock,
257 memory_buffer_GetCurrentLength,
258 memory_buffer_SetCurrentLength,
259 memory_buffer_GetMaxLength,
262 static HRESULT WINAPI memory_1d_2d_buffer_QueryInterface(IMFMediaBuffer *iface, REFIID riid, void **out)
264 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
266 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
268 if (IsEqualIID(riid, &IID_IMFMediaBuffer) ||
269 IsEqualIID(riid, &IID_IUnknown))
271 *out = &buffer->IMFMediaBuffer_iface;
273 else if (IsEqualIID(riid, &IID_IMF2DBuffer2) ||
274 IsEqualIID(riid, &IID_IMF2DBuffer))
276 *out = &buffer->IMF2DBuffer2_iface;
278 else if (IsEqualIID(riid, &IID_IMFGetService))
280 *out = &buffer->IMFGetService_iface;
282 else
284 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
285 *out = NULL;
286 return E_NOINTERFACE;
289 IUnknown_AddRef((IUnknown*)*out);
290 return S_OK;
293 static HRESULT WINAPI memory_1d_2d_buffer_Lock(IMFMediaBuffer *iface, BYTE **data, DWORD *max_length, DWORD *current_length)
295 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
296 HRESULT hr = S_OK;
298 TRACE("%p, %p, %p, %p.\n", iface, data, max_length, current_length);
300 if (!data)
301 return E_POINTER;
303 /* Allocate linear buffer and return it as a copy of current content. Maximum and current length are
304 unrelated to 2D buffer maximum allocate length, or maintained current length. */
306 EnterCriticalSection(&buffer->cs);
308 if (!buffer->_2d.linear_buffer && buffer->_2d.locks)
309 hr = MF_E_INVALIDREQUEST;
310 else if (!buffer->_2d.linear_buffer)
312 if (!(buffer->_2d.linear_buffer = malloc(buffer->_2d.plane_size)))
313 hr = E_OUTOFMEMORY;
315 if (SUCCEEDED(hr))
316 copy_image(buffer, buffer->_2d.linear_buffer, buffer->_2d.width, buffer->data, buffer->_2d.pitch,
317 buffer->_2d.width, buffer->_2d.height);
320 if (SUCCEEDED(hr))
322 ++buffer->_2d.locks;
323 *data = buffer->_2d.linear_buffer;
324 if (max_length)
325 *max_length = buffer->_2d.plane_size;
326 if (current_length)
327 *current_length = buffer->_2d.plane_size;
330 LeaveCriticalSection(&buffer->cs);
332 return hr;
335 static HRESULT WINAPI memory_1d_2d_buffer_Unlock(IMFMediaBuffer *iface)
337 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
339 TRACE("%p.\n", iface);
341 EnterCriticalSection(&buffer->cs);
343 if (buffer->_2d.linear_buffer && !--buffer->_2d.locks)
345 copy_image(buffer, buffer->data, buffer->_2d.pitch, buffer->_2d.linear_buffer, buffer->_2d.width,
346 buffer->_2d.width, buffer->_2d.height);
348 free(buffer->_2d.linear_buffer);
349 buffer->_2d.linear_buffer = NULL;
352 LeaveCriticalSection(&buffer->cs);
354 return S_OK;
357 static const IMFMediaBufferVtbl memory_1d_2d_buffer_vtbl =
359 memory_1d_2d_buffer_QueryInterface,
360 memory_buffer_AddRef,
361 memory_buffer_Release,
362 memory_1d_2d_buffer_Lock,
363 memory_1d_2d_buffer_Unlock,
364 memory_buffer_GetCurrentLength,
365 memory_buffer_SetCurrentLength,
366 memory_buffer_GetMaxLength,
369 static HRESULT WINAPI d3d9_surface_buffer_Lock(IMFMediaBuffer *iface, BYTE **data, DWORD *max_length, DWORD *current_length)
371 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
372 HRESULT hr = S_OK;
374 TRACE("%p, %p, %p, %p.\n", iface, data, max_length, current_length);
376 if (!data)
377 return E_POINTER;
379 EnterCriticalSection(&buffer->cs);
381 if (!buffer->_2d.linear_buffer && buffer->_2d.locks)
382 hr = MF_E_INVALIDREQUEST;
383 else if (!buffer->_2d.linear_buffer)
385 D3DLOCKED_RECT rect;
387 if (!(buffer->_2d.linear_buffer = malloc(buffer->_2d.plane_size)))
388 hr = E_OUTOFMEMORY;
390 if (SUCCEEDED(hr))
392 hr = IDirect3DSurface9_LockRect(buffer->d3d9_surface.surface, &rect, NULL, 0);
393 if (SUCCEEDED(hr))
395 copy_image(buffer, buffer->_2d.linear_buffer, buffer->_2d.width, rect.pBits, rect.Pitch,
396 buffer->_2d.width, buffer->_2d.height);
397 IDirect3DSurface9_UnlockRect(buffer->d3d9_surface.surface);
402 if (SUCCEEDED(hr))
404 ++buffer->_2d.locks;
405 *data = buffer->_2d.linear_buffer;
406 if (max_length)
407 *max_length = buffer->_2d.plane_size;
408 if (current_length)
409 *current_length = buffer->_2d.plane_size;
412 LeaveCriticalSection(&buffer->cs);
414 return hr;
417 static HRESULT WINAPI d3d9_surface_buffer_Unlock(IMFMediaBuffer *iface)
419 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
420 HRESULT hr = S_OK;
422 TRACE("%p.\n", iface);
424 EnterCriticalSection(&buffer->cs);
426 if (!buffer->_2d.linear_buffer)
427 hr = HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED);
428 else if (!--buffer->_2d.locks)
430 D3DLOCKED_RECT rect;
432 if (SUCCEEDED(hr = IDirect3DSurface9_LockRect(buffer->d3d9_surface.surface, &rect, NULL, 0)))
434 copy_image(buffer, rect.pBits, rect.Pitch, buffer->_2d.linear_buffer, buffer->_2d.width,
435 buffer->_2d.width, buffer->_2d.height);
436 IDirect3DSurface9_UnlockRect(buffer->d3d9_surface.surface);
439 free(buffer->_2d.linear_buffer);
440 buffer->_2d.linear_buffer = NULL;
443 LeaveCriticalSection(&buffer->cs);
445 return hr;
448 static HRESULT WINAPI d3d9_surface_buffer_SetCurrentLength(IMFMediaBuffer *iface, DWORD current_length)
450 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
452 TRACE("%p, %lu.\n", iface, current_length);
454 buffer->current_length = current_length;
456 return S_OK;
459 static const IMFMediaBufferVtbl d3d9_surface_1d_buffer_vtbl =
461 memory_1d_2d_buffer_QueryInterface,
462 memory_buffer_AddRef,
463 memory_buffer_Release,
464 d3d9_surface_buffer_Lock,
465 d3d9_surface_buffer_Unlock,
466 memory_buffer_GetCurrentLength,
467 d3d9_surface_buffer_SetCurrentLength,
468 memory_buffer_GetMaxLength,
471 static HRESULT WINAPI memory_2d_buffer_QueryInterface(IMF2DBuffer2 *iface, REFIID riid, void **obj)
473 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
474 return IMFMediaBuffer_QueryInterface(&buffer->IMFMediaBuffer_iface, riid, obj);
477 static ULONG WINAPI memory_2d_buffer_AddRef(IMF2DBuffer2 *iface)
479 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
480 return IMFMediaBuffer_AddRef(&buffer->IMFMediaBuffer_iface);
483 static ULONG WINAPI memory_2d_buffer_Release(IMF2DBuffer2 *iface)
485 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
486 return IMFMediaBuffer_Release(&buffer->IMFMediaBuffer_iface);
489 static HRESULT memory_2d_buffer_lock(struct buffer *buffer, BYTE **scanline0, LONG *pitch,
490 BYTE **buffer_start, DWORD *buffer_length)
492 HRESULT hr = S_OK;
494 if (buffer->_2d.linear_buffer)
495 hr = MF_E_UNEXPECTED;
496 else
498 ++buffer->_2d.locks;
499 *scanline0 = buffer->_2d.scanline0;
500 *pitch = buffer->_2d.pitch;
501 if (buffer_start)
502 *buffer_start = buffer->data;
503 if (buffer_length)
504 *buffer_length = buffer->max_length;
507 return hr;
510 static HRESULT WINAPI memory_2d_buffer_Lock2D(IMF2DBuffer2 *iface, BYTE **scanline0, LONG *pitch)
512 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
513 HRESULT hr;
515 TRACE("%p, %p, %p.\n", iface, scanline0, pitch);
517 if (!scanline0 || !pitch)
518 return E_POINTER;
520 EnterCriticalSection(&buffer->cs);
522 hr = memory_2d_buffer_lock(buffer, scanline0, pitch, NULL, NULL);
524 LeaveCriticalSection(&buffer->cs);
526 return hr;
529 static HRESULT WINAPI memory_2d_buffer_Unlock2D(IMF2DBuffer2 *iface)
531 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
532 HRESULT hr = S_OK;
534 TRACE("%p.\n", iface);
536 EnterCriticalSection(&buffer->cs);
538 if (!buffer->_2d.linear_buffer)
540 if (buffer->_2d.locks)
541 --buffer->_2d.locks;
542 else
543 hr = HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED);
546 LeaveCriticalSection(&buffer->cs);
548 return hr;
551 static HRESULT WINAPI memory_2d_buffer_GetScanline0AndPitch(IMF2DBuffer2 *iface, BYTE **scanline0, LONG *pitch)
553 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
554 HRESULT hr = S_OK;
556 TRACE("%p, %p, %p.\n", iface, scanline0, pitch);
558 if (!scanline0 || !pitch)
559 return E_POINTER;
561 EnterCriticalSection(&buffer->cs);
563 if (buffer->_2d.linear_buffer || !buffer->_2d.locks)
564 hr = HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED);
565 else
567 *scanline0 = buffer->_2d.scanline0;
568 *pitch = buffer->_2d.pitch;
571 LeaveCriticalSection(&buffer->cs);
573 return hr;
576 static HRESULT WINAPI memory_2d_buffer_IsContiguousFormat(IMF2DBuffer2 *iface, BOOL *is_contiguous)
578 TRACE("%p, %p.\n", iface, is_contiguous);
580 if (!is_contiguous)
581 return E_POINTER;
583 *is_contiguous = FALSE;
585 return S_OK;
588 static HRESULT WINAPI memory_2d_buffer_GetContiguousLength(IMF2DBuffer2 *iface, DWORD *length)
590 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
592 TRACE("%p, %p.\n", iface, length);
594 if (!length)
595 return E_POINTER;
597 *length = buffer->_2d.plane_size;
599 return S_OK;
602 static HRESULT WINAPI memory_2d_buffer_ContiguousCopyTo(IMF2DBuffer2 *iface, BYTE *dest_buffer, DWORD dest_length)
604 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
605 BYTE *src_scanline0, *src_buffer_start;
606 DWORD src_length;
607 LONG src_pitch;
608 HRESULT hr;
610 TRACE("%p, %p, %lu.\n", iface, dest_buffer, dest_length);
612 if (dest_length < buffer->_2d.plane_size)
613 return E_INVALIDARG;
615 hr = IMF2DBuffer2_Lock2DSize(iface, MF2DBuffer_LockFlags_Read, &src_scanline0, &src_pitch, &src_buffer_start, &src_length);
617 if (SUCCEEDED(hr))
619 copy_image(buffer, dest_buffer, buffer->_2d.width, src_scanline0, src_pitch, buffer->_2d.width, buffer->_2d.height);
621 if (FAILED(IMF2DBuffer2_Unlock2D(iface)))
622 WARN("Couldn't unlock source buffer %p, hr %#lx.\n", iface, hr);
625 return S_OK;
628 static HRESULT WINAPI memory_2d_buffer_ContiguousCopyFrom(IMF2DBuffer2 *iface, const BYTE *src_buffer, DWORD src_length)
630 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
631 BYTE *dst_scanline0, *dst_buffer_start;
632 DWORD dst_length;
633 LONG dst_pitch;
634 HRESULT hr;
636 TRACE("%p, %p, %lu.\n", iface, src_buffer, src_length);
638 if (src_length < buffer->_2d.plane_size)
639 return E_INVALIDARG;
641 hr = IMF2DBuffer2_Lock2DSize(iface, MF2DBuffer_LockFlags_Write, &dst_scanline0, &dst_pitch, &dst_buffer_start, &dst_length);
643 if (SUCCEEDED(hr))
645 copy_image(buffer, dst_scanline0, dst_pitch, src_buffer, buffer->_2d.width, buffer->_2d.width, buffer->_2d.height);
647 if (FAILED(IMF2DBuffer2_Unlock2D(iface)))
648 WARN("Couldn't unlock destination buffer %p, hr %#lx.\n", iface, hr);
651 return hr;
654 static HRESULT WINAPI memory_2d_buffer_Lock2DSize(IMF2DBuffer2 *iface, MF2DBuffer_LockFlags flags, BYTE **scanline0,
655 LONG *pitch, BYTE **buffer_start, DWORD *buffer_length)
657 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
658 HRESULT hr;
660 TRACE("%p, %#x, %p, %p, %p, %p.\n", iface, flags, scanline0, pitch, buffer_start, buffer_length);
662 if (!scanline0 || !pitch || !buffer_start || !buffer_length)
663 return E_POINTER;
665 EnterCriticalSection(&buffer->cs);
667 hr = memory_2d_buffer_lock(buffer, scanline0, pitch, buffer_start, buffer_length);
669 LeaveCriticalSection(&buffer->cs);
671 return hr;
674 static HRESULT WINAPI memory_2d_buffer_Copy2DTo(IMF2DBuffer2 *iface, IMF2DBuffer2 *dest_buffer)
676 FIXME("%p, %p.\n", iface, dest_buffer);
678 return E_NOTIMPL;
681 static const IMF2DBuffer2Vtbl memory_2d_buffer_vtbl =
683 memory_2d_buffer_QueryInterface,
684 memory_2d_buffer_AddRef,
685 memory_2d_buffer_Release,
686 memory_2d_buffer_Lock2D,
687 memory_2d_buffer_Unlock2D,
688 memory_2d_buffer_GetScanline0AndPitch,
689 memory_2d_buffer_IsContiguousFormat,
690 memory_2d_buffer_GetContiguousLength,
691 memory_2d_buffer_ContiguousCopyTo,
692 memory_2d_buffer_ContiguousCopyFrom,
693 memory_2d_buffer_Lock2DSize,
694 memory_2d_buffer_Copy2DTo,
697 static HRESULT d3d9_surface_buffer_lock(struct buffer *buffer, MF2DBuffer_LockFlags flags, BYTE **scanline0,
698 LONG *pitch, BYTE **buffer_start, DWORD *buffer_length)
700 HRESULT hr = S_OK;
702 if (buffer->_2d.linear_buffer)
703 hr = MF_E_UNEXPECTED;
704 else if (!buffer->_2d.locks)
705 hr = IDirect3DSurface9_LockRect(buffer->d3d9_surface.surface, &buffer->d3d9_surface.rect, NULL, 0);
706 else if (buffer->_2d.lock_flags == MF2DBuffer_LockFlags_Write && flags != MF2DBuffer_LockFlags_Write)
707 hr = HRESULT_FROM_WIN32(ERROR_WAS_LOCKED);
709 if (SUCCEEDED(hr))
711 if (!buffer->_2d.locks)
712 buffer->_2d.lock_flags = flags;
713 buffer->_2d.locks++;
714 *scanline0 = buffer->d3d9_surface.rect.pBits;
715 *pitch = buffer->d3d9_surface.rect.Pitch;
716 if (buffer_start)
717 *buffer_start = *scanline0;
718 if (buffer_length)
719 *buffer_length = buffer->d3d9_surface.rect.Pitch * buffer->_2d.height;
722 return hr;
725 static HRESULT WINAPI d3d9_surface_buffer_Lock2D(IMF2DBuffer2 *iface, BYTE **scanline0, LONG *pitch)
727 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
728 HRESULT hr;
730 TRACE("%p, %p, %p.\n", iface, scanline0, pitch);
732 if (!scanline0 || !pitch)
733 return E_POINTER;
735 EnterCriticalSection(&buffer->cs);
737 hr = d3d9_surface_buffer_lock(buffer, MF2DBuffer_LockFlags_ReadWrite, scanline0, pitch, NULL, NULL);
739 LeaveCriticalSection(&buffer->cs);
741 return hr;
744 static HRESULT WINAPI d3d9_surface_buffer_Unlock2D(IMF2DBuffer2 *iface)
746 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
747 HRESULT hr = S_OK;
749 TRACE("%p.\n", iface);
751 EnterCriticalSection(&buffer->cs);
753 if (buffer->_2d.locks)
755 if (!--buffer->_2d.locks)
757 IDirect3DSurface9_UnlockRect(buffer->d3d9_surface.surface);
758 memset(&buffer->d3d9_surface.rect, 0, sizeof(buffer->d3d9_surface.rect));
759 buffer->_2d.lock_flags = 0;
762 else
763 hr = HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED);
765 LeaveCriticalSection(&buffer->cs);
767 return hr;
770 static HRESULT WINAPI d3d9_surface_buffer_GetScanline0AndPitch(IMF2DBuffer2 *iface, BYTE **scanline0, LONG *pitch)
772 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
773 HRESULT hr = S_OK;
775 TRACE("%p, %p, %p.\n", iface, scanline0, pitch);
777 if (!scanline0 || !pitch)
778 return E_POINTER;
780 EnterCriticalSection(&buffer->cs);
782 if (!buffer->_2d.locks)
784 *scanline0 = NULL;
785 *pitch = 0;
786 hr = HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED);
788 else
790 *scanline0 = buffer->d3d9_surface.rect.pBits;
791 *pitch = buffer->d3d9_surface.rect.Pitch;
794 LeaveCriticalSection(&buffer->cs);
796 return hr;
799 static HRESULT WINAPI d3d9_surface_buffer_Lock2DSize(IMF2DBuffer2 *iface, MF2DBuffer_LockFlags flags, BYTE **scanline0,
800 LONG *pitch, BYTE **buffer_start, DWORD *buffer_length)
802 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
803 HRESULT hr;
805 TRACE("%p, %#x, %p, %p, %p, %p.\n", iface, flags, scanline0, pitch, buffer_start, buffer_length);
807 if (!scanline0 || !pitch || !buffer_start || !buffer_length)
808 return E_POINTER;
810 EnterCriticalSection(&buffer->cs);
812 hr = d3d9_surface_buffer_lock(buffer, flags, scanline0, pitch, buffer_start, buffer_length);
814 LeaveCriticalSection(&buffer->cs);
816 return hr;
819 static const IMF2DBuffer2Vtbl d3d9_surface_buffer_vtbl =
821 memory_2d_buffer_QueryInterface,
822 memory_2d_buffer_AddRef,
823 memory_2d_buffer_Release,
824 d3d9_surface_buffer_Lock2D,
825 d3d9_surface_buffer_Unlock2D,
826 d3d9_surface_buffer_GetScanline0AndPitch,
827 memory_2d_buffer_IsContiguousFormat,
828 memory_2d_buffer_GetContiguousLength,
829 memory_2d_buffer_ContiguousCopyTo,
830 memory_2d_buffer_ContiguousCopyFrom,
831 d3d9_surface_buffer_Lock2DSize,
832 memory_2d_buffer_Copy2DTo,
835 static HRESULT WINAPI memory_2d_buffer_gs_QueryInterface(IMFGetService *iface, REFIID riid, void **obj)
837 struct buffer *buffer = impl_from_IMFGetService(iface);
838 return IMFMediaBuffer_QueryInterface(&buffer->IMFMediaBuffer_iface, riid, obj);
841 static ULONG WINAPI memory_2d_buffer_gs_AddRef(IMFGetService *iface)
843 struct buffer *buffer = impl_from_IMFGetService(iface);
844 return IMFMediaBuffer_AddRef(&buffer->IMFMediaBuffer_iface);
847 static ULONG WINAPI memory_2d_buffer_gs_Release(IMFGetService *iface)
849 struct buffer *buffer = impl_from_IMFGetService(iface);
850 return IMFMediaBuffer_Release(&buffer->IMFMediaBuffer_iface);
853 static HRESULT WINAPI memory_2d_buffer_gs_GetService(IMFGetService *iface, REFGUID service, REFIID riid, void **obj)
855 TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj);
857 return E_NOTIMPL;
860 static const IMFGetServiceVtbl memory_2d_buffer_gs_vtbl =
862 memory_2d_buffer_gs_QueryInterface,
863 memory_2d_buffer_gs_AddRef,
864 memory_2d_buffer_gs_Release,
865 memory_2d_buffer_gs_GetService,
868 static HRESULT WINAPI d3d9_surface_buffer_gs_GetService(IMFGetService *iface, REFGUID service, REFIID riid, void **obj)
870 struct buffer *buffer = impl_from_IMFGetService(iface);
872 TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj);
874 if (IsEqualGUID(service, &MR_BUFFER_SERVICE))
876 return IDirect3DSurface9_QueryInterface(buffer->d3d9_surface.surface, riid, obj);
879 return E_NOTIMPL;
882 static const IMFGetServiceVtbl d3d9_surface_buffer_gs_vtbl =
884 memory_2d_buffer_gs_QueryInterface,
885 memory_2d_buffer_gs_AddRef,
886 memory_2d_buffer_gs_Release,
887 d3d9_surface_buffer_gs_GetService,
890 static HRESULT WINAPI dxgi_1d_2d_buffer_QueryInterface(IMFMediaBuffer *iface, REFIID riid, void **out)
892 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
894 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
896 if (IsEqualIID(riid, &IID_IMFMediaBuffer) ||
897 IsEqualIID(riid, &IID_IUnknown))
899 *out = &buffer->IMFMediaBuffer_iface;
901 else if (IsEqualIID(riid, &IID_IMF2DBuffer2) ||
902 IsEqualIID(riid, &IID_IMF2DBuffer))
904 *out = &buffer->IMF2DBuffer2_iface;
906 else if (IsEqualIID(riid, &IID_IMFDXGIBuffer))
908 *out = &buffer->IMFDXGIBuffer_iface;
910 else
912 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
913 *out = NULL;
914 return E_NOINTERFACE;
917 IUnknown_AddRef((IUnknown*)*out);
918 return S_OK;
921 static HRESULT dxgi_surface_buffer_create_readback_texture(struct buffer *buffer)
923 D3D11_TEXTURE2D_DESC texture_desc;
924 ID3D11Device *device;
925 HRESULT hr;
927 if (buffer->dxgi_surface.rb_texture)
928 return S_OK;
930 ID3D11Texture2D_GetDevice(buffer->dxgi_surface.texture, &device);
932 ID3D11Texture2D_GetDesc(buffer->dxgi_surface.texture, &texture_desc);
933 texture_desc.Usage = D3D11_USAGE_STAGING;
934 texture_desc.BindFlags = 0;
935 texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
936 texture_desc.MiscFlags = 0;
937 texture_desc.MipLevels = 1;
938 if (FAILED(hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &buffer->dxgi_surface.rb_texture)))
939 WARN("Failed to create readback texture, hr %#lx.\n", hr);
941 ID3D11Device_Release(device);
943 return hr;
946 static HRESULT dxgi_surface_buffer_map(struct buffer *buffer, MF2DBuffer_LockFlags flags)
948 ID3D11DeviceContext *immediate_context;
949 ID3D11Device *device;
950 HRESULT hr;
952 if (FAILED(hr = dxgi_surface_buffer_create_readback_texture(buffer)))
953 return hr;
955 ID3D11Texture2D_GetDevice(buffer->dxgi_surface.texture, &device);
956 ID3D11Device_GetImmediateContext(device, &immediate_context);
958 if (flags == MF2DBuffer_LockFlags_Read || flags == MF2DBuffer_LockFlags_ReadWrite)
960 ID3D11DeviceContext_CopySubresourceRegion(immediate_context, (ID3D11Resource *)buffer->dxgi_surface.rb_texture,
961 0, 0, 0, 0, (ID3D11Resource *)buffer->dxgi_surface.texture, buffer->dxgi_surface.sub_resource_idx, NULL);
964 memset(&buffer->dxgi_surface.map_desc, 0, sizeof(buffer->dxgi_surface.map_desc));
965 if (FAILED(hr = ID3D11DeviceContext_Map(immediate_context, (ID3D11Resource *)buffer->dxgi_surface.rb_texture,
966 0, D3D11_MAP_READ_WRITE, 0, &buffer->dxgi_surface.map_desc)))
968 WARN("Failed to map readback texture, hr %#lx.\n", hr);
971 ID3D11DeviceContext_Release(immediate_context);
972 ID3D11Device_Release(device);
974 return hr;
977 static void dxgi_surface_buffer_unmap(struct buffer *buffer, MF2DBuffer_LockFlags flags)
979 ID3D11DeviceContext *immediate_context;
980 ID3D11Device *device;
982 ID3D11Texture2D_GetDevice(buffer->dxgi_surface.texture, &device);
983 ID3D11Device_GetImmediateContext(device, &immediate_context);
984 ID3D11DeviceContext_Unmap(immediate_context, (ID3D11Resource *)buffer->dxgi_surface.rb_texture, 0);
985 memset(&buffer->dxgi_surface.map_desc, 0, sizeof(buffer->dxgi_surface.map_desc));
987 if (flags == MF2DBuffer_LockFlags_Write || flags == MF2DBuffer_LockFlags_ReadWrite)
989 ID3D11DeviceContext_CopySubresourceRegion(immediate_context, (ID3D11Resource *)buffer->dxgi_surface.texture,
990 buffer->dxgi_surface.sub_resource_idx, 0, 0, 0, (ID3D11Resource *)buffer->dxgi_surface.rb_texture, 0, NULL);
993 ID3D11DeviceContext_Release(immediate_context);
994 ID3D11Device_Release(device);
997 static HRESULT WINAPI dxgi_surface_buffer_Lock(IMFMediaBuffer *iface, BYTE **data, DWORD *max_length,
998 DWORD *current_length)
1000 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
1001 HRESULT hr = S_OK;
1003 TRACE("%p, %p, %p, %p.\n", iface, data, max_length, current_length);
1005 if (!data)
1006 return E_POINTER;
1008 EnterCriticalSection(&buffer->cs);
1010 if (!buffer->_2d.linear_buffer && buffer->_2d.locks)
1011 hr = MF_E_INVALIDREQUEST;
1012 else if (!buffer->_2d.linear_buffer)
1014 if (!(buffer->_2d.linear_buffer = malloc(buffer->_2d.plane_size)))
1015 hr = E_OUTOFMEMORY;
1017 if (SUCCEEDED(hr))
1019 hr = dxgi_surface_buffer_map(buffer, MF2DBuffer_LockFlags_ReadWrite);
1020 if (SUCCEEDED(hr))
1022 copy_image(buffer, buffer->_2d.linear_buffer, buffer->_2d.width, buffer->dxgi_surface.map_desc.pData,
1023 buffer->dxgi_surface.map_desc.RowPitch, buffer->_2d.width, buffer->_2d.height);
1028 if (SUCCEEDED(hr))
1030 ++buffer->_2d.locks;
1031 *data = buffer->_2d.linear_buffer;
1032 if (max_length)
1033 *max_length = buffer->_2d.plane_size;
1034 if (current_length)
1035 *current_length = buffer->_2d.plane_size;
1038 LeaveCriticalSection(&buffer->cs);
1040 return hr;
1043 static HRESULT WINAPI dxgi_surface_buffer_Unlock(IMFMediaBuffer *iface)
1045 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
1046 HRESULT hr = S_OK;
1048 TRACE("%p.\n", iface);
1050 EnterCriticalSection(&buffer->cs);
1052 if (!buffer->_2d.linear_buffer)
1053 hr = HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED);
1054 else if (!--buffer->_2d.locks)
1056 copy_image(buffer, buffer->dxgi_surface.map_desc.pData, buffer->dxgi_surface.map_desc.RowPitch,
1057 buffer->_2d.linear_buffer, buffer->_2d.width, buffer->_2d.width, buffer->_2d.height);
1058 dxgi_surface_buffer_unmap(buffer, MF2DBuffer_LockFlags_ReadWrite);
1060 free(buffer->_2d.linear_buffer);
1061 buffer->_2d.linear_buffer = NULL;
1064 LeaveCriticalSection(&buffer->cs);
1066 return hr;
1069 static HRESULT WINAPI dxgi_surface_buffer_SetCurrentLength(IMFMediaBuffer *iface, DWORD current_length)
1071 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
1073 TRACE("%p, %lu.\n", iface, current_length);
1075 buffer->current_length = current_length;
1077 return S_OK;
1080 static HRESULT dxgi_surface_buffer_lock(struct buffer *buffer, MF2DBuffer_LockFlags flags,
1081 BYTE **scanline0, LONG *pitch, BYTE **buffer_start, DWORD *buffer_length)
1083 HRESULT hr = S_OK;
1085 if (buffer->_2d.linear_buffer)
1086 hr = MF_E_UNEXPECTED;
1087 else if (!buffer->_2d.locks)
1088 hr = dxgi_surface_buffer_map(buffer, flags);
1089 else if (buffer->_2d.lock_flags == MF2DBuffer_LockFlags_Write && flags != MF2DBuffer_LockFlags_Write)
1090 hr = HRESULT_FROM_WIN32(ERROR_WAS_LOCKED);
1092 if (SUCCEEDED(hr))
1094 if (!buffer->_2d.locks)
1095 buffer->_2d.lock_flags = flags;
1096 else
1097 buffer->_2d.lock_flags |= flags;
1098 buffer->_2d.locks++;
1099 *scanline0 = buffer->dxgi_surface.map_desc.pData;
1100 *pitch = buffer->dxgi_surface.map_desc.RowPitch;
1101 if (buffer_start)
1102 *buffer_start = *scanline0;
1103 if (buffer_length)
1104 *buffer_length = buffer->dxgi_surface.map_desc.DepthPitch;
1107 return hr;
1110 static HRESULT WINAPI dxgi_surface_buffer_Lock2D(IMF2DBuffer2 *iface, BYTE **scanline0, LONG *pitch)
1112 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
1113 HRESULT hr;
1115 TRACE("%p, %p, %p.\n", iface, scanline0, pitch);
1117 if (!scanline0 || !pitch)
1118 return E_POINTER;
1120 EnterCriticalSection(&buffer->cs);
1122 hr = dxgi_surface_buffer_lock(buffer, MF2DBuffer_LockFlags_ReadWrite, scanline0, pitch, NULL, NULL);
1124 LeaveCriticalSection(&buffer->cs);
1126 return hr;
1129 static HRESULT WINAPI dxgi_surface_buffer_Unlock2D(IMF2DBuffer2 *iface)
1131 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
1132 HRESULT hr = S_OK;
1134 TRACE("%p.\n", iface);
1136 EnterCriticalSection(&buffer->cs);
1138 if (buffer->_2d.locks)
1140 if (!--buffer->_2d.locks)
1142 dxgi_surface_buffer_unmap(buffer, buffer->_2d.lock_flags);
1143 buffer->_2d.lock_flags = 0;
1146 else
1147 hr = HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED);
1149 LeaveCriticalSection(&buffer->cs);
1151 return hr;
1154 static HRESULT WINAPI dxgi_surface_buffer_GetScanline0AndPitch(IMF2DBuffer2 *iface, BYTE **scanline0, LONG *pitch)
1156 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
1157 HRESULT hr = S_OK;
1159 TRACE("%p, %p, %p.\n", iface, scanline0, pitch);
1161 if (!scanline0 || !pitch)
1162 return E_POINTER;
1164 EnterCriticalSection(&buffer->cs);
1166 if (!buffer->_2d.locks)
1168 *scanline0 = NULL;
1169 *pitch = 0;
1170 hr = HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED);
1172 else
1174 *scanline0 = buffer->dxgi_surface.map_desc.pData;
1175 *pitch = buffer->dxgi_surface.map_desc.RowPitch;
1178 LeaveCriticalSection(&buffer->cs);
1180 return hr;
1183 static HRESULT WINAPI dxgi_surface_buffer_Lock2DSize(IMF2DBuffer2 *iface, MF2DBuffer_LockFlags flags,
1184 BYTE **scanline0, LONG *pitch, BYTE **buffer_start, DWORD *buffer_length)
1186 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
1187 HRESULT hr;
1189 TRACE("%p, %#x, %p, %p, %p, %p.\n", iface, flags, scanline0, pitch, buffer_start, buffer_length);
1191 if (!scanline0 || !pitch || !buffer_start || !buffer_length)
1192 return E_POINTER;
1194 EnterCriticalSection(&buffer->cs);
1196 hr = dxgi_surface_buffer_lock(buffer, flags, scanline0, pitch, buffer_start, buffer_length);
1198 LeaveCriticalSection(&buffer->cs);
1200 return hr;
1203 static HRESULT WINAPI dxgi_buffer_QueryInterface(IMFDXGIBuffer *iface, REFIID riid, void **obj)
1205 struct buffer *buffer = impl_from_IMFDXGIBuffer(iface);
1206 return IMFMediaBuffer_QueryInterface(&buffer->IMFMediaBuffer_iface, riid, obj);
1209 static ULONG WINAPI dxgi_buffer_AddRef(IMFDXGIBuffer *iface)
1211 struct buffer *buffer = impl_from_IMFDXGIBuffer(iface);
1212 return IMFMediaBuffer_AddRef(&buffer->IMFMediaBuffer_iface);
1215 static ULONG WINAPI dxgi_buffer_Release(IMFDXGIBuffer *iface)
1217 struct buffer *buffer = impl_from_IMFDXGIBuffer(iface);
1218 return IMFMediaBuffer_Release(&buffer->IMFMediaBuffer_iface);
1221 static HRESULT WINAPI dxgi_buffer_GetResource(IMFDXGIBuffer *iface, REFIID riid, void **obj)
1223 struct buffer *buffer = impl_from_IMFDXGIBuffer(iface);
1225 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
1227 return ID3D11Texture2D_QueryInterface(buffer->dxgi_surface.texture, riid, obj);
1230 static HRESULT WINAPI dxgi_buffer_GetSubresourceIndex(IMFDXGIBuffer *iface, UINT *index)
1232 struct buffer *buffer = impl_from_IMFDXGIBuffer(iface);
1234 TRACE("%p, %p.\n", iface, index);
1236 if (!index)
1237 return E_POINTER;
1239 *index = buffer->dxgi_surface.sub_resource_idx;
1241 return S_OK;
1244 static HRESULT WINAPI dxgi_buffer_GetUnknown(IMFDXGIBuffer *iface, REFIID guid, REFIID riid, void **object)
1246 struct buffer *buffer = impl_from_IMFDXGIBuffer(iface);
1248 TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(guid), debugstr_guid(riid), object);
1250 if (attributes_GetUnknown(&buffer->dxgi_surface.attributes, guid, riid, object) == MF_E_ATTRIBUTENOTFOUND)
1251 return MF_E_NOT_FOUND;
1253 return S_OK;
1256 static HRESULT WINAPI dxgi_buffer_SetUnknown(IMFDXGIBuffer *iface, REFIID guid, IUnknown *data)
1258 struct buffer *buffer = impl_from_IMFDXGIBuffer(iface);
1259 HRESULT hr = S_OK;
1261 TRACE("%p, %s, %p.\n", iface, debugstr_guid(guid), data);
1263 EnterCriticalSection(&buffer->dxgi_surface.attributes.cs);
1264 if (data)
1266 if (SUCCEEDED(attributes_GetItem(&buffer->dxgi_surface.attributes, guid, NULL)))
1267 hr = HRESULT_FROM_WIN32(ERROR_OBJECT_ALREADY_EXISTS);
1268 else
1269 hr = attributes_SetUnknown(&buffer->dxgi_surface.attributes, guid, data);
1271 else
1273 attributes_DeleteItem(&buffer->dxgi_surface.attributes, guid);
1275 LeaveCriticalSection(&buffer->dxgi_surface.attributes.cs);
1277 return hr;
1280 static const IMFMediaBufferVtbl dxgi_surface_1d_buffer_vtbl =
1282 dxgi_1d_2d_buffer_QueryInterface,
1283 memory_buffer_AddRef,
1284 memory_buffer_Release,
1285 dxgi_surface_buffer_Lock,
1286 dxgi_surface_buffer_Unlock,
1287 memory_buffer_GetCurrentLength,
1288 dxgi_surface_buffer_SetCurrentLength,
1289 memory_buffer_GetMaxLength,
1292 static const IMF2DBuffer2Vtbl dxgi_surface_buffer_vtbl =
1294 memory_2d_buffer_QueryInterface,
1295 memory_2d_buffer_AddRef,
1296 memory_2d_buffer_Release,
1297 dxgi_surface_buffer_Lock2D,
1298 dxgi_surface_buffer_Unlock2D,
1299 dxgi_surface_buffer_GetScanline0AndPitch,
1300 memory_2d_buffer_IsContiguousFormat,
1301 memory_2d_buffer_GetContiguousLength,
1302 memory_2d_buffer_ContiguousCopyTo,
1303 memory_2d_buffer_ContiguousCopyFrom,
1304 dxgi_surface_buffer_Lock2DSize,
1305 memory_2d_buffer_Copy2DTo,
1308 static const IMFDXGIBufferVtbl dxgi_buffer_vtbl =
1310 dxgi_buffer_QueryInterface,
1311 dxgi_buffer_AddRef,
1312 dxgi_buffer_Release,
1313 dxgi_buffer_GetResource,
1314 dxgi_buffer_GetSubresourceIndex,
1315 dxgi_buffer_GetUnknown,
1316 dxgi_buffer_SetUnknown,
1319 static HRESULT memory_buffer_init(struct buffer *buffer, DWORD max_length, DWORD alignment,
1320 const IMFMediaBufferVtbl *vtbl)
1322 if (alignment < MF_16_BYTE_ALIGNMENT)
1323 alignment = MF_16_BYTE_ALIGNMENT;
1324 alignment++;
1326 if (alignment & (alignment - 1))
1328 alignment--;
1329 alignment |= alignment >> 1;
1330 alignment |= alignment >> 2;
1331 alignment |= alignment >> 4;
1332 alignment |= alignment >> 8;
1333 alignment |= alignment >> 16;
1334 alignment++;
1337 if (!(buffer->data = _aligned_malloc(max_length, alignment)))
1338 return E_OUTOFMEMORY;
1339 memset(buffer->data, 0, max_length);
1341 buffer->IMFMediaBuffer_iface.lpVtbl = vtbl;
1342 buffer->refcount = 1;
1343 buffer->max_length = max_length;
1344 buffer->current_length = 0;
1345 InitializeCriticalSection(&buffer->cs);
1347 return S_OK;
1350 static HRESULT create_1d_buffer(DWORD max_length, DWORD alignment, IMFMediaBuffer **buffer)
1352 struct buffer *object;
1353 HRESULT hr;
1355 if (!buffer)
1356 return E_POINTER;
1358 *buffer = NULL;
1360 if (!(object = calloc(1, sizeof(*object))))
1361 return E_OUTOFMEMORY;
1363 hr = memory_buffer_init(object, max_length, alignment, &memory_1d_buffer_vtbl);
1364 if (FAILED(hr))
1366 free(object);
1367 return hr;
1370 *buffer = &object->IMFMediaBuffer_iface;
1372 return S_OK;
1375 static p_copy_image_func get_2d_buffer_copy_func(DWORD fourcc)
1377 switch (fourcc)
1379 case MAKEFOURCC('I','M','C','1'):
1380 case MAKEFOURCC('I','M','C','3'):
1381 return copy_image_imc1;
1383 case MAKEFOURCC('I','M','C','2'):
1384 case MAKEFOURCC('I','M','C','4'):
1385 case MAKEFOURCC('N','V','1','1'):
1386 case MAKEFOURCC('Y','V','1','2'):
1387 case MAKEFOURCC('I','4','2','0'):
1388 case MAKEFOURCC('I','Y','U','V'):
1389 return copy_image_imc2;
1391 case MAKEFOURCC('N','V','1','2'):
1392 return copy_image_nv12;
1394 default:
1395 return NULL;
1399 static HRESULT create_2d_buffer(DWORD width, DWORD height, DWORD fourcc, BOOL bottom_up, IMFMediaBuffer **buffer)
1401 unsigned int stride, max_length;
1402 unsigned int row_alignment;
1403 struct buffer *object;
1404 DWORD plane_size;
1405 GUID subtype;
1406 BOOL is_yuv;
1407 HRESULT hr;
1408 int pitch;
1410 if (!buffer)
1411 return E_POINTER;
1413 *buffer = NULL;
1415 memcpy(&subtype, &MFVideoFormat_Base, sizeof(subtype));
1416 subtype.Data1 = fourcc;
1418 if (!(stride = mf_format_get_stride(&subtype, width, &is_yuv)))
1419 return MF_E_INVALIDMEDIATYPE;
1421 if (is_yuv && bottom_up)
1422 return MF_E_INVALIDMEDIATYPE;
1424 switch (fourcc)
1426 case MAKEFOURCC('I','M','C','1'):
1427 case MAKEFOURCC('I','M','C','3'):
1428 plane_size = stride * height * 2;
1429 break;
1430 case MAKEFOURCC('I','M','C','2'):
1431 case MAKEFOURCC('I','M','C','4'):
1432 case MAKEFOURCC('N','V','1','1'):
1433 case MAKEFOURCC('Y','V','1','2'):
1434 case MAKEFOURCC('I','4','2','0'):
1435 case MAKEFOURCC('I','Y','U','V'):
1436 plane_size = stride * 3 / 2 * height;
1437 break;
1438 case MAKEFOURCC('N','V','1','2'):
1439 plane_size = stride * height * 3 / 2;
1440 break;
1441 default:
1442 plane_size = stride * height;
1445 if (!(object = calloc(1, sizeof(*object))))
1446 return E_OUTOFMEMORY;
1448 switch (fourcc)
1450 case MAKEFOURCC('I','M','C','1'):
1451 case MAKEFOURCC('I','M','C','2'):
1452 case MAKEFOURCC('I','M','C','3'):
1453 case MAKEFOURCC('I','M','C','4'):
1454 case MAKEFOURCC('Y','V','1','2'):
1455 case MAKEFOURCC('N','V','1','1'):
1456 case MAKEFOURCC('I','4','2','0'):
1457 case MAKEFOURCC('I','Y','U','V'):
1458 row_alignment = MF_128_BYTE_ALIGNMENT;
1459 break;
1460 default:
1461 row_alignment = MF_64_BYTE_ALIGNMENT;
1464 pitch = ALIGN_SIZE(stride, row_alignment);
1466 switch (fourcc)
1468 case MAKEFOURCC('I','M','C','1'):
1469 case MAKEFOURCC('I','M','C','3'):
1470 max_length = pitch * height * 2;
1471 break;
1472 case MAKEFOURCC('N','V','1','2'):
1473 case MAKEFOURCC('Y','V','1','2'):
1474 case MAKEFOURCC('I','M','C','2'):
1475 case MAKEFOURCC('I','M','C','4'):
1476 case MAKEFOURCC('N','V','1','1'):
1477 case MAKEFOURCC('I','4','2','0'):
1478 case MAKEFOURCC('I','Y','U','V'):
1479 max_length = pitch * height * 3 / 2;
1480 break;
1481 default:
1482 max_length = pitch * height;
1485 if (FAILED(hr = memory_buffer_init(object, max_length, row_alignment, &memory_1d_2d_buffer_vtbl)))
1487 free(object);
1488 return hr;
1491 object->IMF2DBuffer2_iface.lpVtbl = &memory_2d_buffer_vtbl;
1492 object->IMFGetService_iface.lpVtbl = &memory_2d_buffer_gs_vtbl;
1493 object->_2d.plane_size = plane_size;
1494 object->_2d.width = stride;
1495 object->_2d.height = height;
1496 object->_2d.pitch = bottom_up ? -pitch : pitch;
1497 object->_2d.scanline0 = bottom_up ? object->data + pitch * (object->_2d.height - 1) : object->data;
1498 object->_2d.copy_image = get_2d_buffer_copy_func(fourcc);
1500 *buffer = &object->IMFMediaBuffer_iface;
1502 return S_OK;
1505 static HRESULT create_d3d9_surface_buffer(IUnknown *surface, BOOL bottom_up, IMFMediaBuffer **buffer)
1507 struct buffer *object;
1508 D3DSURFACE_DESC desc;
1509 unsigned int stride;
1510 GUID subtype;
1511 BOOL is_yuv;
1513 IDirect3DSurface9_GetDesc((IDirect3DSurface9 *)surface, &desc);
1514 TRACE("format %#x, %u x %u.\n", desc.Format, desc.Width, desc.Height);
1516 memcpy(&subtype, &MFVideoFormat_Base, sizeof(subtype));
1517 subtype.Data1 = desc.Format;
1519 if (!(stride = mf_format_get_stride(&subtype, desc.Width, &is_yuv)))
1520 return MF_E_INVALIDMEDIATYPE;
1522 if (!(object = calloc(1, sizeof(*object))))
1523 return E_OUTOFMEMORY;
1525 object->IMFMediaBuffer_iface.lpVtbl = &d3d9_surface_1d_buffer_vtbl;
1526 object->IMF2DBuffer2_iface.lpVtbl = &d3d9_surface_buffer_vtbl;
1527 object->IMFGetService_iface.lpVtbl = &d3d9_surface_buffer_gs_vtbl;
1528 object->refcount = 1;
1529 InitializeCriticalSection(&object->cs);
1530 object->d3d9_surface.surface = (IDirect3DSurface9 *)surface;
1531 IUnknown_AddRef(surface);
1533 MFGetPlaneSize(desc.Format, desc.Width, desc.Height, &object->_2d.plane_size);
1534 object->_2d.width = stride;
1535 object->_2d.height = desc.Height;
1536 object->max_length = object->_2d.plane_size;
1537 object->_2d.copy_image = get_2d_buffer_copy_func(desc.Format);
1539 *buffer = &object->IMFMediaBuffer_iface;
1541 return S_OK;
1544 static HRESULT create_dxgi_surface_buffer(IUnknown *surface, unsigned int sub_resource_idx,
1545 BOOL bottom_up, IMFMediaBuffer **buffer)
1547 struct buffer *object;
1548 D3D11_TEXTURE2D_DESC desc;
1549 ID3D11Texture2D *texture;
1550 unsigned int stride;
1551 D3DFORMAT format;
1552 GUID subtype;
1553 BOOL is_yuv;
1554 HRESULT hr;
1556 if (FAILED(hr = IUnknown_QueryInterface(surface, &IID_ID3D11Texture2D, (void **)&texture)))
1558 WARN("Failed to get texture interface, hr %#lx.\n", hr);
1559 return hr;
1562 ID3D11Texture2D_GetDesc(texture, &desc);
1563 TRACE("format %#x, %u x %u.\n", desc.Format, desc.Width, desc.Height);
1565 memcpy(&subtype, &MFVideoFormat_Base, sizeof(subtype));
1566 subtype.Data1 = format = MFMapDXGIFormatToDX9Format(desc.Format);
1568 if (!(stride = mf_format_get_stride(&subtype, desc.Width, &is_yuv)))
1570 ID3D11Texture2D_Release(texture);
1571 return MF_E_INVALIDMEDIATYPE;
1574 if (!(object = calloc(1, sizeof(*object))))
1576 ID3D11Texture2D_Release(texture);
1577 return E_OUTOFMEMORY;
1580 object->IMFMediaBuffer_iface.lpVtbl = &dxgi_surface_1d_buffer_vtbl;
1581 object->IMF2DBuffer2_iface.lpVtbl = &dxgi_surface_buffer_vtbl;
1582 object->IMFDXGIBuffer_iface.lpVtbl = &dxgi_buffer_vtbl;
1583 object->refcount = 1;
1584 InitializeCriticalSection(&object->cs);
1585 object->dxgi_surface.texture = texture;
1586 object->dxgi_surface.sub_resource_idx = sub_resource_idx;
1588 MFGetPlaneSize(format, desc.Width, desc.Height, &object->_2d.plane_size);
1589 object->_2d.width = stride;
1590 object->_2d.height = desc.Height;
1591 object->max_length = object->_2d.plane_size;
1592 object->_2d.copy_image = get_2d_buffer_copy_func(format);
1594 if (FAILED(hr = init_attributes_object(&object->dxgi_surface.attributes, 0)))
1596 IMFMediaBuffer_Release(&object->IMFMediaBuffer_iface);
1597 return hr;
1600 *buffer = &object->IMFMediaBuffer_iface;
1602 return S_OK;
1605 /***********************************************************************
1606 * MFCreateMemoryBuffer (mfplat.@)
1608 HRESULT WINAPI MFCreateMemoryBuffer(DWORD max_length, IMFMediaBuffer **buffer)
1610 TRACE("%lu, %p.\n", max_length, buffer);
1612 return create_1d_buffer(max_length, MF_1_BYTE_ALIGNMENT, buffer);
1615 /***********************************************************************
1616 * MFCreateAlignedMemoryBuffer (mfplat.@)
1618 HRESULT WINAPI MFCreateAlignedMemoryBuffer(DWORD max_length, DWORD alignment, IMFMediaBuffer **buffer)
1620 TRACE("%lu, %lu, %p.\n", max_length, alignment, buffer);
1622 return create_1d_buffer(max_length, alignment, buffer);
1625 /***********************************************************************
1626 * MFCreate2DMediaBuffer (mfplat.@)
1628 HRESULT WINAPI MFCreate2DMediaBuffer(DWORD width, DWORD height, DWORD fourcc, BOOL bottom_up, IMFMediaBuffer **buffer)
1630 TRACE("%lu, %lu, %s, %d, %p.\n", width, height, debugstr_fourcc(fourcc), bottom_up, buffer);
1632 return create_2d_buffer(width, height, fourcc, bottom_up, buffer);
1635 /***********************************************************************
1636 * MFCreateDXSurfaceBuffer (mfplat.@)
1638 HRESULT WINAPI MFCreateDXSurfaceBuffer(REFIID riid, IUnknown *surface, BOOL bottom_up, IMFMediaBuffer **buffer)
1640 TRACE("%s, %p, %d, %p.\n", debugstr_guid(riid), surface, bottom_up, buffer);
1642 if (!IsEqualIID(riid, &IID_IDirect3DSurface9))
1643 return E_INVALIDARG;
1645 return create_d3d9_surface_buffer(surface, bottom_up, buffer);
1648 /***********************************************************************
1649 * MFCreateDXGISurfaceBuffer (mfplat.@)
1651 HRESULT WINAPI MFCreateDXGISurfaceBuffer(REFIID riid, IUnknown *surface, UINT subresource, BOOL bottom_up,
1652 IMFMediaBuffer **buffer)
1654 TRACE("%s, %p, %u, %d, %p.\n", debugstr_guid(riid), surface, subresource, bottom_up, buffer);
1656 if (!IsEqualIID(riid, &IID_ID3D11Texture2D))
1657 return E_INVALIDARG;
1659 return create_dxgi_surface_buffer(surface, subresource, bottom_up, buffer);
1662 static unsigned int buffer_get_aligned_length(unsigned int length, unsigned int alignment)
1664 length = (length + alignment) / alignment;
1665 length *= alignment;
1667 return length;
1670 HRESULT WINAPI MFCreateMediaBufferFromMediaType(IMFMediaType *media_type, LONGLONG duration, DWORD min_length,
1671 DWORD alignment, IMFMediaBuffer **buffer)
1673 UINT32 length = 0, block_alignment;
1674 LONGLONG avg_length;
1675 HRESULT hr;
1676 GUID major;
1678 TRACE("%p, %s, %lu, %lu, %p.\n", media_type, debugstr_time(duration), min_length, alignment, buffer);
1680 if (!media_type)
1681 return E_INVALIDARG;
1683 if (FAILED(hr = IMFMediaType_GetMajorType(media_type, &major)))
1684 return hr;
1686 if (IsEqualGUID(&major, &MFMediaType_Audio))
1688 block_alignment = 0;
1689 if (FAILED(IMFMediaType_GetUINT32(media_type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, &block_alignment)))
1690 WARN("Block alignment was not specified.\n");
1692 alignment = max(16, alignment);
1694 if (block_alignment)
1696 avg_length = 0;
1698 if (duration)
1700 length = 0;
1701 if (SUCCEEDED(IMFMediaType_GetUINT32(media_type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, &length)))
1703 /* 100 ns -> 1 s */
1704 avg_length = length * duration / (10 * 1000 * 1000);
1708 length = buffer_get_aligned_length(avg_length + 1, alignment);
1709 length = buffer_get_aligned_length(length, block_alignment);
1711 else
1712 length = 0;
1714 length = max(length, min_length);
1716 return create_1d_buffer(length, alignment - 1, buffer);
1718 else
1719 FIXME("Major type %s is not supported.\n", debugstr_guid(&major));
1721 return E_NOTIMPL;