msvcrt: Fix strtof() error reporting for values out of float range.
[wine.git] / dlls / mfplat / buffer.c
blob9081dc39eab52987f3108dddd0a9ca7267d63f8d
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 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 unsigned int plane_size;
54 BYTE *scanline0;
55 unsigned int width;
56 unsigned int height;
57 int pitch;
58 unsigned int locks;
59 p_copy_image_func copy_image;
60 } _2d;
61 struct
63 IDirect3DSurface9 *surface;
64 D3DLOCKED_RECT rect;
65 } d3d9_surface;
66 struct
68 ID3D11Texture2D *texture;
69 unsigned int sub_resource_idx;
70 ID3D11Texture2D *rb_texture;
71 D3D11_MAPPED_SUBRESOURCE map_desc;
72 struct attributes attributes;
73 } dxgi_surface;
75 CRITICAL_SECTION cs;
78 static void copy_image(const struct buffer *buffer, BYTE *dest, LONG dest_stride, const BYTE *src,
79 LONG src_stride, DWORD width, DWORD lines)
81 MFCopyImage(dest, dest_stride, src, src_stride, width, lines);
83 if (buffer->_2d.copy_image)
85 dest += dest_stride * lines;
86 src += src_stride * lines;
87 buffer->_2d.copy_image(dest, dest_stride, src, src_stride, width, lines);
91 static void copy_image_nv12(BYTE *dest, LONG dest_stride, const BYTE *src, LONG src_stride, DWORD width, DWORD lines)
93 MFCopyImage(dest, dest_stride, src, src_stride, width, lines / 2);
96 static void copy_image_imc1(BYTE *dest, LONG dest_stride, const BYTE *src, LONG src_stride, DWORD width, DWORD lines)
98 MFCopyImage(dest, dest_stride, src, src_stride, width / 2, lines);
101 static void copy_image_imc2(BYTE *dest, LONG dest_stride, const BYTE *src, LONG src_stride, DWORD width, DWORD lines)
103 MFCopyImage(dest, dest_stride, src, src_stride, width / 2, lines / 2);
104 MFCopyImage(dest + dest_stride / 2, dest_stride, src + src_stride / 2, src_stride, width / 2, lines / 2);
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 %u.\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 %u.\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 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, %u.\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(ALIGN_SIZE(buffer->_2d.plane_size, MF_64_BYTE_ALIGNMENT))))
313 hr = E_OUTOFMEMORY;
316 if (SUCCEEDED(hr))
318 ++buffer->_2d.locks;
319 *data = buffer->_2d.linear_buffer;
320 if (max_length)
321 *max_length = buffer->_2d.plane_size;
322 if (current_length)
323 *current_length = buffer->_2d.plane_size;
326 LeaveCriticalSection(&buffer->cs);
328 return hr;
331 static HRESULT WINAPI memory_1d_2d_buffer_Unlock(IMFMediaBuffer *iface)
333 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
335 TRACE("%p.\n", iface);
337 EnterCriticalSection(&buffer->cs);
339 if (buffer->_2d.linear_buffer && !--buffer->_2d.locks)
341 copy_image(buffer, buffer->data, buffer->_2d.pitch, buffer->_2d.linear_buffer, buffer->_2d.width,
342 buffer->_2d.width, buffer->_2d.height);
344 free(buffer->_2d.linear_buffer);
345 buffer->_2d.linear_buffer = NULL;
348 LeaveCriticalSection(&buffer->cs);
350 return S_OK;
353 static const IMFMediaBufferVtbl memory_1d_2d_buffer_vtbl =
355 memory_1d_2d_buffer_QueryInterface,
356 memory_buffer_AddRef,
357 memory_buffer_Release,
358 memory_1d_2d_buffer_Lock,
359 memory_1d_2d_buffer_Unlock,
360 memory_buffer_GetCurrentLength,
361 memory_buffer_SetCurrentLength,
362 memory_buffer_GetMaxLength,
365 static HRESULT WINAPI d3d9_surface_buffer_Lock(IMFMediaBuffer *iface, BYTE **data, DWORD *max_length, DWORD *current_length)
367 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
368 HRESULT hr = S_OK;
370 TRACE("%p, %p, %p, %p.\n", iface, data, max_length, current_length);
372 if (!data)
373 return E_POINTER;
375 EnterCriticalSection(&buffer->cs);
377 if (!buffer->_2d.linear_buffer && buffer->_2d.locks)
378 hr = MF_E_INVALIDREQUEST;
379 else if (!buffer->_2d.linear_buffer)
381 D3DLOCKED_RECT rect;
383 if (!(buffer->_2d.linear_buffer = malloc(ALIGN_SIZE(buffer->_2d.plane_size, MF_64_BYTE_ALIGNMENT))))
384 hr = E_OUTOFMEMORY;
386 if (SUCCEEDED(hr))
388 hr = IDirect3DSurface9_LockRect(buffer->d3d9_surface.surface, &rect, NULL, 0);
389 if (SUCCEEDED(hr))
391 copy_image(buffer, buffer->_2d.linear_buffer, buffer->_2d.width, rect.pBits, rect.Pitch,
392 buffer->_2d.width, buffer->_2d.height);
393 IDirect3DSurface9_UnlockRect(buffer->d3d9_surface.surface);
398 if (SUCCEEDED(hr))
400 ++buffer->_2d.locks;
401 *data = buffer->_2d.linear_buffer;
402 if (max_length)
403 *max_length = buffer->_2d.plane_size;
404 if (current_length)
405 *current_length = buffer->_2d.plane_size;
408 LeaveCriticalSection(&buffer->cs);
410 return hr;
413 static HRESULT WINAPI d3d9_surface_buffer_Unlock(IMFMediaBuffer *iface)
415 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
416 HRESULT hr = S_OK;
418 TRACE("%p.\n", iface);
420 EnterCriticalSection(&buffer->cs);
422 if (!buffer->_2d.linear_buffer)
423 hr = HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED);
424 else if (!--buffer->_2d.locks)
426 D3DLOCKED_RECT rect;
428 if (SUCCEEDED(hr = IDirect3DSurface9_LockRect(buffer->d3d9_surface.surface, &rect, NULL, 0)))
430 copy_image(buffer, rect.pBits, rect.Pitch, buffer->_2d.linear_buffer, buffer->_2d.width,
431 buffer->_2d.width, buffer->_2d.height);
432 IDirect3DSurface9_UnlockRect(buffer->d3d9_surface.surface);
435 free(buffer->_2d.linear_buffer);
436 buffer->_2d.linear_buffer = NULL;
439 LeaveCriticalSection(&buffer->cs);
441 return hr;
444 static HRESULT WINAPI d3d9_surface_buffer_SetCurrentLength(IMFMediaBuffer *iface, DWORD current_length)
446 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
448 TRACE("%p, %u.\n", iface, current_length);
450 buffer->current_length = current_length;
452 return S_OK;
455 static const IMFMediaBufferVtbl d3d9_surface_1d_buffer_vtbl =
457 memory_1d_2d_buffer_QueryInterface,
458 memory_buffer_AddRef,
459 memory_buffer_Release,
460 d3d9_surface_buffer_Lock,
461 d3d9_surface_buffer_Unlock,
462 memory_buffer_GetCurrentLength,
463 d3d9_surface_buffer_SetCurrentLength,
464 memory_buffer_GetMaxLength,
467 static HRESULT WINAPI memory_2d_buffer_QueryInterface(IMF2DBuffer2 *iface, REFIID riid, void **obj)
469 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
470 return IMFMediaBuffer_QueryInterface(&buffer->IMFMediaBuffer_iface, riid, obj);
473 static ULONG WINAPI memory_2d_buffer_AddRef(IMF2DBuffer2 *iface)
475 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
476 return IMFMediaBuffer_AddRef(&buffer->IMFMediaBuffer_iface);
479 static ULONG WINAPI memory_2d_buffer_Release(IMF2DBuffer2 *iface)
481 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
482 return IMFMediaBuffer_Release(&buffer->IMFMediaBuffer_iface);
485 static HRESULT memory_2d_buffer_lock(struct buffer *buffer, BYTE **scanline0, LONG *pitch,
486 BYTE **buffer_start, DWORD *buffer_length)
488 HRESULT hr = S_OK;
490 if (buffer->_2d.linear_buffer)
491 hr = MF_E_UNEXPECTED;
492 else
494 ++buffer->_2d.locks;
495 *scanline0 = buffer->_2d.scanline0;
496 *pitch = buffer->_2d.pitch;
497 if (buffer_start)
498 *buffer_start = buffer->data;
499 if (buffer_length)
500 *buffer_length = buffer->max_length;
503 return hr;
506 static HRESULT WINAPI memory_2d_buffer_Lock2D(IMF2DBuffer2 *iface, BYTE **scanline0, LONG *pitch)
508 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
509 HRESULT hr;
511 TRACE("%p, %p, %p.\n", iface, scanline0, pitch);
513 if (!scanline0 || !pitch)
514 return E_POINTER;
516 EnterCriticalSection(&buffer->cs);
518 hr = memory_2d_buffer_lock(buffer, scanline0, pitch, NULL, NULL);
520 LeaveCriticalSection(&buffer->cs);
522 return hr;
525 static HRESULT WINAPI memory_2d_buffer_Unlock2D(IMF2DBuffer2 *iface)
527 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
528 HRESULT hr = S_OK;
530 TRACE("%p.\n", iface);
532 EnterCriticalSection(&buffer->cs);
534 if (!buffer->_2d.linear_buffer)
536 if (buffer->_2d.locks)
537 --buffer->_2d.locks;
538 else
539 hr = HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED);
542 LeaveCriticalSection(&buffer->cs);
544 return hr;
547 static HRESULT WINAPI memory_2d_buffer_GetScanline0AndPitch(IMF2DBuffer2 *iface, BYTE **scanline0, LONG *pitch)
549 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
550 HRESULT hr = S_OK;
552 TRACE("%p, %p, %p.\n", iface, scanline0, pitch);
554 if (!scanline0 || !pitch)
555 return E_POINTER;
557 EnterCriticalSection(&buffer->cs);
559 if (buffer->_2d.linear_buffer || !buffer->_2d.locks)
560 hr = HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED);
561 else
563 *scanline0 = buffer->_2d.scanline0;
564 *pitch = buffer->_2d.pitch;
567 LeaveCriticalSection(&buffer->cs);
569 return hr;
572 static HRESULT WINAPI memory_2d_buffer_IsContiguousFormat(IMF2DBuffer2 *iface, BOOL *is_contiguous)
574 TRACE("%p, %p.\n", iface, is_contiguous);
576 if (!is_contiguous)
577 return E_POINTER;
579 *is_contiguous = FALSE;
581 return S_OK;
584 static HRESULT WINAPI memory_2d_buffer_GetContiguousLength(IMF2DBuffer2 *iface, DWORD *length)
586 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
588 TRACE("%p, %p.\n", iface, length);
590 if (!length)
591 return E_POINTER;
593 *length = buffer->_2d.plane_size;
595 return S_OK;
598 static HRESULT WINAPI memory_2d_buffer_ContiguousCopyTo(IMF2DBuffer2 *iface, BYTE *dest_buffer, DWORD dest_length)
600 FIXME("%p, %p, %u.\n", iface, dest_buffer, dest_length);
602 return E_NOTIMPL;
605 static HRESULT WINAPI memory_2d_buffer_ContiguousCopyFrom(IMF2DBuffer2 *iface, const BYTE *src_buffer, DWORD src_length)
607 FIXME("%p, %p, %u.\n", iface, src_buffer, src_length);
609 return E_NOTIMPL;
612 static HRESULT WINAPI memory_2d_buffer_Lock2DSize(IMF2DBuffer2 *iface, MF2DBuffer_LockFlags flags, BYTE **scanline0,
613 LONG *pitch, BYTE **buffer_start, DWORD *buffer_length)
615 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
616 HRESULT hr;
618 TRACE("%p, %#x, %p, %p, %p, %p.\n", iface, flags, scanline0, pitch, buffer_start, buffer_length);
620 if (!scanline0 || !pitch || !buffer_start || !buffer_length)
621 return E_POINTER;
623 EnterCriticalSection(&buffer->cs);
625 hr = memory_2d_buffer_lock(buffer, scanline0, pitch, buffer_start, buffer_length);
627 LeaveCriticalSection(&buffer->cs);
629 return hr;
632 static HRESULT WINAPI memory_2d_buffer_Copy2DTo(IMF2DBuffer2 *iface, IMF2DBuffer2 *dest_buffer)
634 FIXME("%p, %p.\n", iface, dest_buffer);
636 return E_NOTIMPL;
639 static const IMF2DBuffer2Vtbl memory_2d_buffer_vtbl =
641 memory_2d_buffer_QueryInterface,
642 memory_2d_buffer_AddRef,
643 memory_2d_buffer_Release,
644 memory_2d_buffer_Lock2D,
645 memory_2d_buffer_Unlock2D,
646 memory_2d_buffer_GetScanline0AndPitch,
647 memory_2d_buffer_IsContiguousFormat,
648 memory_2d_buffer_GetContiguousLength,
649 memory_2d_buffer_ContiguousCopyTo,
650 memory_2d_buffer_ContiguousCopyFrom,
651 memory_2d_buffer_Lock2DSize,
652 memory_2d_buffer_Copy2DTo,
655 static HRESULT WINAPI d3d9_surface_buffer_Lock2D(IMF2DBuffer2 *iface, BYTE **scanline0, LONG *pitch)
657 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
658 HRESULT hr = S_OK;
660 TRACE("%p, %p, %p.\n", iface, scanline0, pitch);
662 if (!scanline0 || !pitch)
663 return E_POINTER;
665 EnterCriticalSection(&buffer->cs);
667 if (buffer->_2d.linear_buffer)
668 hr = MF_E_UNEXPECTED;
669 else if (!buffer->_2d.locks++)
671 hr = IDirect3DSurface9_LockRect(buffer->d3d9_surface.surface, &buffer->d3d9_surface.rect, NULL, 0);
674 if (SUCCEEDED(hr))
676 *scanline0 = buffer->d3d9_surface.rect.pBits;
677 *pitch = buffer->d3d9_surface.rect.Pitch;
680 LeaveCriticalSection(&buffer->cs);
682 return hr;
685 static HRESULT WINAPI d3d9_surface_buffer_Unlock2D(IMF2DBuffer2 *iface)
687 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
688 HRESULT hr = S_OK;
690 TRACE("%p.\n", iface);
692 EnterCriticalSection(&buffer->cs);
694 if (buffer->_2d.locks)
696 if (!--buffer->_2d.locks)
698 IDirect3DSurface9_UnlockRect(buffer->d3d9_surface.surface);
699 memset(&buffer->d3d9_surface.rect, 0, sizeof(buffer->d3d9_surface.rect));
702 else
703 hr = HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED);
705 LeaveCriticalSection(&buffer->cs);
707 return hr;
710 static HRESULT WINAPI d3d9_surface_buffer_GetScanline0AndPitch(IMF2DBuffer2 *iface, BYTE **scanline0, LONG *pitch)
712 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
713 HRESULT hr = S_OK;
715 TRACE("%p, %p, %p.\n", iface, scanline0, pitch);
717 if (!scanline0 || !pitch)
718 return E_POINTER;
720 EnterCriticalSection(&buffer->cs);
722 if (!buffer->_2d.locks)
724 *scanline0 = NULL;
725 *pitch = 0;
726 hr = HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED);
728 else
730 *scanline0 = buffer->d3d9_surface.rect.pBits;
731 *pitch = buffer->d3d9_surface.rect.Pitch;
734 LeaveCriticalSection(&buffer->cs);
736 return hr;
739 static HRESULT WINAPI d3d9_surface_buffer_Lock2DSize(IMF2DBuffer2 *iface, MF2DBuffer_LockFlags flags, BYTE **scanline0,
740 LONG *pitch, BYTE **buffer_start, DWORD *buffer_length)
742 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
743 HRESULT hr = S_OK;
745 TRACE("%p, %#x, %p, %p, %p, %p.\n", iface, flags, scanline0, pitch, buffer_start, buffer_length);
747 if (!scanline0 || !pitch || !buffer_start || !buffer_length)
748 return E_POINTER;
750 EnterCriticalSection(&buffer->cs);
752 if (buffer->_2d.linear_buffer)
753 hr = MF_E_UNEXPECTED;
754 else if (!buffer->_2d.locks++)
756 hr = IDirect3DSurface9_LockRect(buffer->d3d9_surface.surface, &buffer->d3d9_surface.rect, NULL, 0);
759 if (SUCCEEDED(hr))
761 *scanline0 = buffer->d3d9_surface.rect.pBits;
762 *pitch = buffer->d3d9_surface.rect.Pitch;
763 if (buffer_start)
764 *buffer_start = *scanline0;
765 if (buffer_length)
766 *buffer_length = buffer->d3d9_surface.rect.Pitch * buffer->_2d.height;
769 LeaveCriticalSection(&buffer->cs);
771 return hr;
774 static const IMF2DBuffer2Vtbl d3d9_surface_buffer_vtbl =
776 memory_2d_buffer_QueryInterface,
777 memory_2d_buffer_AddRef,
778 memory_2d_buffer_Release,
779 d3d9_surface_buffer_Lock2D,
780 d3d9_surface_buffer_Unlock2D,
781 d3d9_surface_buffer_GetScanline0AndPitch,
782 memory_2d_buffer_IsContiguousFormat,
783 memory_2d_buffer_GetContiguousLength,
784 memory_2d_buffer_ContiguousCopyTo,
785 memory_2d_buffer_ContiguousCopyFrom,
786 d3d9_surface_buffer_Lock2DSize,
787 memory_2d_buffer_Copy2DTo,
790 static HRESULT WINAPI memory_2d_buffer_gs_QueryInterface(IMFGetService *iface, REFIID riid, void **obj)
792 struct buffer *buffer = impl_from_IMFGetService(iface);
793 return IMFMediaBuffer_QueryInterface(&buffer->IMFMediaBuffer_iface, riid, obj);
796 static ULONG WINAPI memory_2d_buffer_gs_AddRef(IMFGetService *iface)
798 struct buffer *buffer = impl_from_IMFGetService(iface);
799 return IMFMediaBuffer_AddRef(&buffer->IMFMediaBuffer_iface);
802 static ULONG WINAPI memory_2d_buffer_gs_Release(IMFGetService *iface)
804 struct buffer *buffer = impl_from_IMFGetService(iface);
805 return IMFMediaBuffer_Release(&buffer->IMFMediaBuffer_iface);
808 static HRESULT WINAPI memory_2d_buffer_gs_GetService(IMFGetService *iface, REFGUID service, REFIID riid, void **obj)
810 TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj);
812 return E_NOTIMPL;
815 static const IMFGetServiceVtbl memory_2d_buffer_gs_vtbl =
817 memory_2d_buffer_gs_QueryInterface,
818 memory_2d_buffer_gs_AddRef,
819 memory_2d_buffer_gs_Release,
820 memory_2d_buffer_gs_GetService,
823 static HRESULT WINAPI d3d9_surface_buffer_gs_GetService(IMFGetService *iface, REFGUID service, REFIID riid, void **obj)
825 struct buffer *buffer = impl_from_IMFGetService(iface);
827 TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(service), debugstr_guid(riid), obj);
829 if (IsEqualGUID(service, &MR_BUFFER_SERVICE))
831 return IDirect3DSurface9_QueryInterface(buffer->d3d9_surface.surface, riid, obj);
834 return E_NOTIMPL;
837 static const IMFGetServiceVtbl d3d9_surface_buffer_gs_vtbl =
839 memory_2d_buffer_gs_QueryInterface,
840 memory_2d_buffer_gs_AddRef,
841 memory_2d_buffer_gs_Release,
842 d3d9_surface_buffer_gs_GetService,
845 static HRESULT WINAPI dxgi_1d_2d_buffer_QueryInterface(IMFMediaBuffer *iface, REFIID riid, void **out)
847 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
849 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
851 if (IsEqualIID(riid, &IID_IMFMediaBuffer) ||
852 IsEqualIID(riid, &IID_IUnknown))
854 *out = &buffer->IMFMediaBuffer_iface;
856 else if (IsEqualIID(riid, &IID_IMF2DBuffer2) ||
857 IsEqualIID(riid, &IID_IMF2DBuffer))
859 *out = &buffer->IMF2DBuffer2_iface;
861 else if (IsEqualIID(riid, &IID_IMFDXGIBuffer))
863 *out = &buffer->IMFDXGIBuffer_iface;
865 else
867 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
868 *out = NULL;
869 return E_NOINTERFACE;
872 IUnknown_AddRef((IUnknown*)*out);
873 return S_OK;
876 static HRESULT dxgi_surface_buffer_create_readback_texture(struct buffer *buffer)
878 D3D11_TEXTURE2D_DESC texture_desc;
879 ID3D11Device *device;
880 HRESULT hr;
882 if (buffer->dxgi_surface.rb_texture)
883 return S_OK;
885 ID3D11Texture2D_GetDevice(buffer->dxgi_surface.texture, &device);
887 ID3D11Texture2D_GetDesc(buffer->dxgi_surface.texture, &texture_desc);
888 texture_desc.Usage = D3D11_USAGE_STAGING;
889 texture_desc.BindFlags = 0;
890 texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
891 texture_desc.MiscFlags = 0;
892 texture_desc.MipLevels = 1;
893 if (FAILED(hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &buffer->dxgi_surface.rb_texture)))
894 WARN("Failed to create readback texture, hr %#x.\n", hr);
896 ID3D11Device_Release(device);
898 return hr;
901 static HRESULT dxgi_surface_buffer_map(struct buffer *buffer)
903 ID3D11DeviceContext *immediate_context;
904 ID3D11Device *device;
905 HRESULT hr;
907 if (FAILED(hr = dxgi_surface_buffer_create_readback_texture(buffer)))
908 return hr;
910 ID3D11Texture2D_GetDevice(buffer->dxgi_surface.texture, &device);
911 ID3D11Device_GetImmediateContext(device, &immediate_context);
912 ID3D11DeviceContext_CopySubresourceRegion(immediate_context, (ID3D11Resource *)buffer->dxgi_surface.rb_texture,
913 0, 0, 0, 0, (ID3D11Resource *)buffer->dxgi_surface.texture, buffer->dxgi_surface.sub_resource_idx, NULL);
915 memset(&buffer->dxgi_surface.map_desc, 0, sizeof(buffer->dxgi_surface.map_desc));
916 if (FAILED(hr = ID3D11DeviceContext_Map(immediate_context, (ID3D11Resource *)buffer->dxgi_surface.rb_texture,
917 0, D3D11_MAP_READ_WRITE, 0, &buffer->dxgi_surface.map_desc)))
919 WARN("Failed to map readback texture, hr %#x.\n", hr);
922 ID3D11DeviceContext_Release(immediate_context);
923 ID3D11Device_Release(device);
925 return hr;
928 static void dxgi_surface_buffer_unmap(struct buffer *buffer)
930 ID3D11DeviceContext *immediate_context;
931 ID3D11Device *device;
933 ID3D11Texture2D_GetDevice(buffer->dxgi_surface.texture, &device);
934 ID3D11Device_GetImmediateContext(device, &immediate_context);
935 ID3D11DeviceContext_Unmap(immediate_context, (ID3D11Resource *)buffer->dxgi_surface.rb_texture, 0);
936 memset(&buffer->dxgi_surface.map_desc, 0, sizeof(buffer->dxgi_surface.map_desc));
938 ID3D11DeviceContext_CopySubresourceRegion(immediate_context, (ID3D11Resource *)buffer->dxgi_surface.texture,
939 buffer->dxgi_surface.sub_resource_idx, 0, 0, 0, (ID3D11Resource *)buffer->dxgi_surface.rb_texture, 0, NULL);
941 ID3D11DeviceContext_Release(immediate_context);
942 ID3D11Device_Release(device);
945 static HRESULT WINAPI dxgi_surface_buffer_Lock(IMFMediaBuffer *iface, BYTE **data, DWORD *max_length,
946 DWORD *current_length)
948 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
949 HRESULT hr = S_OK;
951 TRACE("%p, %p, %p, %p.\n", iface, data, max_length, current_length);
953 if (!data)
954 return E_POINTER;
956 EnterCriticalSection(&buffer->cs);
958 if (!buffer->_2d.linear_buffer && buffer->_2d.locks)
959 hr = MF_E_INVALIDREQUEST;
960 else if (!buffer->_2d.linear_buffer)
962 if (!(buffer->_2d.linear_buffer = malloc(ALIGN_SIZE(buffer->_2d.plane_size, MF_64_BYTE_ALIGNMENT))))
963 hr = E_OUTOFMEMORY;
965 if (SUCCEEDED(hr))
967 hr = dxgi_surface_buffer_map(buffer);
968 if (SUCCEEDED(hr))
970 copy_image(buffer, buffer->_2d.linear_buffer, buffer->_2d.width, buffer->dxgi_surface.map_desc.pData,
971 buffer->dxgi_surface.map_desc.RowPitch, buffer->_2d.width, buffer->_2d.height);
976 if (SUCCEEDED(hr))
978 ++buffer->_2d.locks;
979 *data = buffer->_2d.linear_buffer;
980 if (max_length)
981 *max_length = buffer->_2d.plane_size;
982 if (current_length)
983 *current_length = buffer->_2d.plane_size;
986 LeaveCriticalSection(&buffer->cs);
988 return hr;
991 static HRESULT WINAPI dxgi_surface_buffer_Unlock(IMFMediaBuffer *iface)
993 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
994 HRESULT hr = S_OK;
996 TRACE("%p.\n", iface);
998 EnterCriticalSection(&buffer->cs);
1000 if (!buffer->_2d.linear_buffer)
1001 hr = HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED);
1002 else if (!--buffer->_2d.locks)
1004 copy_image(buffer, buffer->dxgi_surface.map_desc.pData, buffer->dxgi_surface.map_desc.RowPitch,
1005 buffer->_2d.linear_buffer, buffer->_2d.width, buffer->_2d.width, buffer->_2d.height);
1006 dxgi_surface_buffer_unmap(buffer);
1008 free(buffer->_2d.linear_buffer);
1009 buffer->_2d.linear_buffer = NULL;
1012 LeaveCriticalSection(&buffer->cs);
1014 return hr;
1017 static HRESULT WINAPI dxgi_surface_buffer_SetCurrentLength(IMFMediaBuffer *iface, DWORD current_length)
1019 struct buffer *buffer = impl_from_IMFMediaBuffer(iface);
1021 TRACE("%p, %u.\n", iface, current_length);
1023 buffer->current_length = current_length;
1025 return S_OK;
1028 static HRESULT WINAPI dxgi_surface_buffer_Lock2D(IMF2DBuffer2 *iface, BYTE **scanline0, LONG *pitch)
1030 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
1031 HRESULT hr = S_OK;
1033 TRACE("%p, %p, %p.\n", iface, scanline0, pitch);
1035 if (!scanline0 || !pitch)
1036 return E_POINTER;
1038 EnterCriticalSection(&buffer->cs);
1040 if (buffer->_2d.linear_buffer)
1041 hr = MF_E_UNEXPECTED;
1042 else if (!buffer->_2d.locks++)
1043 hr = dxgi_surface_buffer_map(buffer);
1045 if (SUCCEEDED(hr))
1047 *scanline0 = buffer->dxgi_surface.map_desc.pData;
1048 *pitch = buffer->dxgi_surface.map_desc.RowPitch;
1051 LeaveCriticalSection(&buffer->cs);
1053 return hr;
1056 static HRESULT WINAPI dxgi_surface_buffer_Unlock2D(IMF2DBuffer2 *iface)
1058 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
1059 HRESULT hr = S_OK;
1061 TRACE("%p.\n", iface);
1063 EnterCriticalSection(&buffer->cs);
1065 if (buffer->_2d.locks)
1067 if (!--buffer->_2d.locks)
1068 dxgi_surface_buffer_unmap(buffer);
1070 else
1071 hr = HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED);
1073 LeaveCriticalSection(&buffer->cs);
1075 return hr;
1078 static HRESULT WINAPI dxgi_surface_buffer_GetScanline0AndPitch(IMF2DBuffer2 *iface, BYTE **scanline0, LONG *pitch)
1080 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
1081 HRESULT hr = S_OK;
1083 TRACE("%p, %p, %p.\n", iface, scanline0, pitch);
1085 if (!scanline0 || !pitch)
1086 return E_POINTER;
1088 EnterCriticalSection(&buffer->cs);
1090 if (!buffer->_2d.locks)
1092 *scanline0 = NULL;
1093 *pitch = 0;
1094 hr = HRESULT_FROM_WIN32(ERROR_WAS_UNLOCKED);
1096 else
1098 *scanline0 = buffer->dxgi_surface.map_desc.pData;
1099 *pitch = buffer->dxgi_surface.map_desc.RowPitch;
1102 LeaveCriticalSection(&buffer->cs);
1104 return hr;
1107 static HRESULT WINAPI dxgi_surface_buffer_Lock2DSize(IMF2DBuffer2 *iface, MF2DBuffer_LockFlags flags,
1108 BYTE **scanline0, LONG *pitch, BYTE **buffer_start, DWORD *buffer_length)
1110 struct buffer *buffer = impl_from_IMF2DBuffer2(iface);
1111 HRESULT hr = S_OK;
1113 TRACE("%p, %#x, %p, %p, %p, %p.\n", iface, flags, scanline0, pitch, buffer_start, buffer_length);
1115 if (!scanline0 || !pitch || !buffer_start || !buffer_length)
1116 return E_POINTER;
1118 EnterCriticalSection(&buffer->cs);
1120 if (buffer->_2d.linear_buffer)
1121 hr = MF_E_UNEXPECTED;
1122 else if (!buffer->_2d.locks++)
1123 hr = dxgi_surface_buffer_map(buffer);
1125 if (SUCCEEDED(hr))
1127 *scanline0 = buffer->dxgi_surface.map_desc.pData;
1128 *pitch = buffer->dxgi_surface.map_desc.RowPitch;
1129 if (buffer_start)
1130 *buffer_start = *scanline0;
1131 if (buffer_length)
1132 *buffer_length = buffer->dxgi_surface.map_desc.RowPitch * buffer->_2d.height;
1135 LeaveCriticalSection(&buffer->cs);
1137 return hr;
1140 static HRESULT WINAPI dxgi_buffer_QueryInterface(IMFDXGIBuffer *iface, REFIID riid, void **obj)
1142 struct buffer *buffer = impl_from_IMFDXGIBuffer(iface);
1143 return IMFMediaBuffer_QueryInterface(&buffer->IMFMediaBuffer_iface, riid, obj);
1146 static ULONG WINAPI dxgi_buffer_AddRef(IMFDXGIBuffer *iface)
1148 struct buffer *buffer = impl_from_IMFDXGIBuffer(iface);
1149 return IMFMediaBuffer_AddRef(&buffer->IMFMediaBuffer_iface);
1152 static ULONG WINAPI dxgi_buffer_Release(IMFDXGIBuffer *iface)
1154 struct buffer *buffer = impl_from_IMFDXGIBuffer(iface);
1155 return IMFMediaBuffer_Release(&buffer->IMFMediaBuffer_iface);
1158 static HRESULT WINAPI dxgi_buffer_GetResource(IMFDXGIBuffer *iface, REFIID riid, void **obj)
1160 struct buffer *buffer = impl_from_IMFDXGIBuffer(iface);
1162 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), obj);
1164 return ID3D11Texture2D_QueryInterface(buffer->dxgi_surface.texture, riid, obj);
1167 static HRESULT WINAPI dxgi_buffer_GetSubresourceIndex(IMFDXGIBuffer *iface, UINT *index)
1169 struct buffer *buffer = impl_from_IMFDXGIBuffer(iface);
1171 TRACE("%p, %p.\n", iface, index);
1173 if (!index)
1174 return E_POINTER;
1176 *index = buffer->dxgi_surface.sub_resource_idx;
1178 return S_OK;
1181 static HRESULT WINAPI dxgi_buffer_GetUnknown(IMFDXGIBuffer *iface, REFIID guid, REFIID riid, void **object)
1183 struct buffer *buffer = impl_from_IMFDXGIBuffer(iface);
1185 TRACE("%p, %s, %s, %p.\n", iface, debugstr_guid(guid), debugstr_guid(riid), object);
1187 if (attributes_GetUnknown(&buffer->dxgi_surface.attributes, guid, riid, object) == MF_E_ATTRIBUTENOTFOUND)
1188 return MF_E_NOT_FOUND;
1190 return S_OK;
1193 static HRESULT WINAPI dxgi_buffer_SetUnknown(IMFDXGIBuffer *iface, REFIID guid, IUnknown *data)
1195 struct buffer *buffer = impl_from_IMFDXGIBuffer(iface);
1196 HRESULT hr = S_OK;
1198 TRACE("%p, %s, %p.\n", iface, debugstr_guid(guid), data);
1200 EnterCriticalSection(&buffer->dxgi_surface.attributes.cs);
1201 if (data)
1203 if (SUCCEEDED(attributes_GetItem(&buffer->dxgi_surface.attributes, guid, NULL)))
1204 hr = HRESULT_FROM_WIN32(ERROR_OBJECT_ALREADY_EXISTS);
1205 else
1206 hr = attributes_SetUnknown(&buffer->dxgi_surface.attributes, guid, data);
1208 else
1210 attributes_DeleteItem(&buffer->dxgi_surface.attributes, guid);
1212 LeaveCriticalSection(&buffer->dxgi_surface.attributes.cs);
1214 return hr;
1217 static const IMFMediaBufferVtbl dxgi_surface_1d_buffer_vtbl =
1219 dxgi_1d_2d_buffer_QueryInterface,
1220 memory_buffer_AddRef,
1221 memory_buffer_Release,
1222 dxgi_surface_buffer_Lock,
1223 dxgi_surface_buffer_Unlock,
1224 memory_buffer_GetCurrentLength,
1225 dxgi_surface_buffer_SetCurrentLength,
1226 memory_buffer_GetMaxLength,
1229 static const IMF2DBuffer2Vtbl dxgi_surface_buffer_vtbl =
1231 memory_2d_buffer_QueryInterface,
1232 memory_2d_buffer_AddRef,
1233 memory_2d_buffer_Release,
1234 dxgi_surface_buffer_Lock2D,
1235 dxgi_surface_buffer_Unlock2D,
1236 dxgi_surface_buffer_GetScanline0AndPitch,
1237 memory_2d_buffer_IsContiguousFormat,
1238 memory_2d_buffer_GetContiguousLength,
1239 memory_2d_buffer_ContiguousCopyTo,
1240 memory_2d_buffer_ContiguousCopyFrom,
1241 dxgi_surface_buffer_Lock2DSize,
1242 memory_2d_buffer_Copy2DTo,
1245 static const IMFDXGIBufferVtbl dxgi_buffer_vtbl =
1247 dxgi_buffer_QueryInterface,
1248 dxgi_buffer_AddRef,
1249 dxgi_buffer_Release,
1250 dxgi_buffer_GetResource,
1251 dxgi_buffer_GetSubresourceIndex,
1252 dxgi_buffer_GetUnknown,
1253 dxgi_buffer_SetUnknown,
1256 static HRESULT memory_buffer_init(struct buffer *buffer, DWORD max_length, DWORD alignment,
1257 const IMFMediaBufferVtbl *vtbl)
1259 if (!(buffer->data = calloc(1, ALIGN_SIZE(max_length, alignment))))
1260 return E_OUTOFMEMORY;
1262 buffer->IMFMediaBuffer_iface.lpVtbl = vtbl;
1263 buffer->refcount = 1;
1264 buffer->max_length = max_length;
1265 buffer->current_length = 0;
1266 InitializeCriticalSection(&buffer->cs);
1268 return S_OK;
1271 static HRESULT create_1d_buffer(DWORD max_length, DWORD alignment, IMFMediaBuffer **buffer)
1273 struct buffer *object;
1274 HRESULT hr;
1276 if (!buffer)
1277 return E_POINTER;
1279 *buffer = NULL;
1281 if (!(object = calloc(1, sizeof(*object))))
1282 return E_OUTOFMEMORY;
1284 hr = memory_buffer_init(object, max_length, alignment, &memory_1d_buffer_vtbl);
1285 if (FAILED(hr))
1287 free(object);
1288 return hr;
1291 *buffer = &object->IMFMediaBuffer_iface;
1293 return S_OK;
1296 static p_copy_image_func get_2d_buffer_copy_func(DWORD fourcc)
1298 if (fourcc == MAKEFOURCC('N','V','1','2'))
1299 return copy_image_nv12;
1300 if (fourcc == MAKEFOURCC('I','M','C','1') || fourcc == MAKEFOURCC('I','M','C','3'))
1301 return copy_image_imc1;
1302 if (fourcc == MAKEFOURCC('I','M','C','2') || fourcc == MAKEFOURCC('I','M','C','4'))
1303 return copy_image_imc2;
1304 return NULL;
1307 static HRESULT create_2d_buffer(DWORD width, DWORD height, DWORD fourcc, BOOL bottom_up, IMFMediaBuffer **buffer)
1309 unsigned int stride, max_length, plane_size;
1310 struct buffer *object;
1311 unsigned int row_alignment;
1312 GUID subtype;
1313 BOOL is_yuv;
1314 HRESULT hr;
1315 int pitch;
1317 if (!buffer)
1318 return E_POINTER;
1320 *buffer = NULL;
1322 memcpy(&subtype, &MFVideoFormat_Base, sizeof(subtype));
1323 subtype.Data1 = fourcc;
1325 if (!(stride = mf_format_get_stride(&subtype, width, &is_yuv)))
1326 return MF_E_INVALIDMEDIATYPE;
1328 if (is_yuv && bottom_up)
1329 return MF_E_INVALIDMEDIATYPE;
1331 if (FAILED(hr = MFGetPlaneSize(fourcc, width, height, &plane_size)))
1332 return hr;
1334 if (!(object = calloc(1, sizeof(*object))))
1335 return E_OUTOFMEMORY;
1337 switch (fourcc)
1339 case MAKEFOURCC('I','M','C','1'):
1340 case MAKEFOURCC('I','M','C','2'):
1341 case MAKEFOURCC('I','M','C','3'):
1342 case MAKEFOURCC('I','M','C','4'):
1343 case MAKEFOURCC('Y','V','1','2'):
1344 row_alignment = MF_128_BYTE_ALIGNMENT;
1345 break;
1346 default:
1347 row_alignment = MF_64_BYTE_ALIGNMENT;
1350 pitch = ALIGN_SIZE(stride, row_alignment);
1352 switch (fourcc)
1354 case MAKEFOURCC('I','M','C','1'):
1355 case MAKEFOURCC('I','M','C','3'):
1356 max_length = pitch * height * 2;
1357 plane_size *= 2;
1358 break;
1359 case MAKEFOURCC('N','V','1','2'):
1360 case MAKEFOURCC('Y','V','1','2'):
1361 case MAKEFOURCC('I','M','C','2'):
1362 case MAKEFOURCC('I','M','C','4'):
1363 max_length = pitch * height * 3 / 2;
1364 break;
1365 default:
1366 max_length = pitch * height;
1369 if (FAILED(hr = memory_buffer_init(object, max_length, MF_1_BYTE_ALIGNMENT, &memory_1d_2d_buffer_vtbl)))
1371 free(object);
1372 return hr;
1375 object->IMF2DBuffer2_iface.lpVtbl = &memory_2d_buffer_vtbl;
1376 object->IMFGetService_iface.lpVtbl = &memory_2d_buffer_gs_vtbl;
1377 object->_2d.plane_size = plane_size;
1378 object->_2d.width = stride;
1379 object->_2d.height = height;
1380 object->_2d.pitch = bottom_up ? -pitch : pitch;
1381 object->_2d.scanline0 = bottom_up ? object->data + pitch * (object->_2d.height - 1) : object->data;
1382 object->_2d.copy_image = get_2d_buffer_copy_func(fourcc);
1384 *buffer = &object->IMFMediaBuffer_iface;
1386 return S_OK;
1389 static HRESULT create_d3d9_surface_buffer(IUnknown *surface, BOOL bottom_up, IMFMediaBuffer **buffer)
1391 struct buffer *object;
1392 D3DSURFACE_DESC desc;
1393 unsigned int stride;
1394 GUID subtype;
1395 BOOL is_yuv;
1397 IDirect3DSurface9_GetDesc((IDirect3DSurface9 *)surface, &desc);
1398 TRACE("format %#x, %u x %u.\n", desc.Format, desc.Width, desc.Height);
1400 memcpy(&subtype, &MFVideoFormat_Base, sizeof(subtype));
1401 subtype.Data1 = desc.Format;
1403 if (!(stride = mf_format_get_stride(&subtype, desc.Width, &is_yuv)))
1404 return MF_E_INVALIDMEDIATYPE;
1406 if (!(object = calloc(1, sizeof(*object))))
1407 return E_OUTOFMEMORY;
1409 object->IMFMediaBuffer_iface.lpVtbl = &d3d9_surface_1d_buffer_vtbl;
1410 object->IMF2DBuffer2_iface.lpVtbl = &d3d9_surface_buffer_vtbl;
1411 object->IMFGetService_iface.lpVtbl = &d3d9_surface_buffer_gs_vtbl;
1412 object->refcount = 1;
1413 InitializeCriticalSection(&object->cs);
1414 object->d3d9_surface.surface = (IDirect3DSurface9 *)surface;
1415 IUnknown_AddRef(surface);
1417 MFGetPlaneSize(desc.Format, desc.Width, desc.Height, &object->_2d.plane_size);
1418 object->_2d.width = stride;
1419 object->_2d.height = desc.Height;
1420 object->max_length = object->_2d.plane_size;
1421 object->_2d.copy_image = get_2d_buffer_copy_func(desc.Format);
1423 *buffer = &object->IMFMediaBuffer_iface;
1425 return S_OK;
1428 static HRESULT create_dxgi_surface_buffer(IUnknown *surface, unsigned int sub_resource_idx,
1429 BOOL bottom_up, IMFMediaBuffer **buffer)
1431 struct buffer *object;
1432 D3D11_TEXTURE2D_DESC desc;
1433 ID3D11Texture2D *texture;
1434 unsigned int stride;
1435 D3DFORMAT format;
1436 GUID subtype;
1437 BOOL is_yuv;
1438 HRESULT hr;
1440 if (FAILED(hr = IUnknown_QueryInterface(surface, &IID_ID3D11Texture2D, (void **)&texture)))
1442 WARN("Failed to get texture interface, hr %#x.\n", hr);
1443 return hr;
1446 ID3D11Texture2D_GetDesc(texture, &desc);
1447 TRACE("format %#x, %u x %u.\n", desc.Format, desc.Width, desc.Height);
1449 memcpy(&subtype, &MFVideoFormat_Base, sizeof(subtype));
1450 subtype.Data1 = format = MFMapDXGIFormatToDX9Format(desc.Format);
1452 if (!(stride = mf_format_get_stride(&subtype, desc.Width, &is_yuv)))
1454 ID3D11Texture2D_Release(texture);
1455 return MF_E_INVALIDMEDIATYPE;
1458 if (!(object = calloc(1, sizeof(*object))))
1460 ID3D11Texture2D_Release(texture);
1461 return E_OUTOFMEMORY;
1464 object->IMFMediaBuffer_iface.lpVtbl = &dxgi_surface_1d_buffer_vtbl;
1465 object->IMF2DBuffer2_iface.lpVtbl = &dxgi_surface_buffer_vtbl;
1466 object->IMFDXGIBuffer_iface.lpVtbl = &dxgi_buffer_vtbl;
1467 object->refcount = 1;
1468 InitializeCriticalSection(&object->cs);
1469 object->dxgi_surface.texture = texture;
1470 object->dxgi_surface.sub_resource_idx = sub_resource_idx;
1472 MFGetPlaneSize(format, desc.Width, desc.Height, &object->_2d.plane_size);
1473 object->_2d.width = stride;
1474 object->_2d.height = desc.Height;
1475 object->max_length = object->_2d.plane_size;
1476 object->_2d.copy_image = get_2d_buffer_copy_func(format);
1478 if (FAILED(hr = init_attributes_object(&object->dxgi_surface.attributes, 0)))
1480 IMFMediaBuffer_Release(&object->IMFMediaBuffer_iface);
1481 return hr;
1484 *buffer = &object->IMFMediaBuffer_iface;
1486 return S_OK;
1489 /***********************************************************************
1490 * MFCreateMemoryBuffer (mfplat.@)
1492 HRESULT WINAPI MFCreateMemoryBuffer(DWORD max_length, IMFMediaBuffer **buffer)
1494 TRACE("%u, %p.\n", max_length, buffer);
1496 return create_1d_buffer(max_length, MF_1_BYTE_ALIGNMENT, buffer);
1499 /***********************************************************************
1500 * MFCreateAlignedMemoryBuffer (mfplat.@)
1502 HRESULT WINAPI MFCreateAlignedMemoryBuffer(DWORD max_length, DWORD alignment, IMFMediaBuffer **buffer)
1504 TRACE("%u, %u, %p.\n", max_length, alignment, buffer);
1506 return create_1d_buffer(max_length, alignment, buffer);
1509 /***********************************************************************
1510 * MFCreate2DMediaBuffer (mfplat.@)
1512 HRESULT WINAPI MFCreate2DMediaBuffer(DWORD width, DWORD height, DWORD fourcc, BOOL bottom_up, IMFMediaBuffer **buffer)
1514 TRACE("%u, %u, %s, %d, %p.\n", width, height, debugstr_fourcc(fourcc), bottom_up, buffer);
1516 return create_2d_buffer(width, height, fourcc, bottom_up, buffer);
1519 /***********************************************************************
1520 * MFCreateDXSurfaceBuffer (mfplat.@)
1522 HRESULT WINAPI MFCreateDXSurfaceBuffer(REFIID riid, IUnknown *surface, BOOL bottom_up, IMFMediaBuffer **buffer)
1524 TRACE("%s, %p, %d, %p.\n", debugstr_guid(riid), surface, bottom_up, buffer);
1526 if (!IsEqualIID(riid, &IID_IDirect3DSurface9))
1527 return E_INVALIDARG;
1529 return create_d3d9_surface_buffer(surface, bottom_up, buffer);
1532 /***********************************************************************
1533 * MFCreateDXGISurfaceBuffer (mfplat.@)
1535 HRESULT WINAPI MFCreateDXGISurfaceBuffer(REFIID riid, IUnknown *surface, UINT subresource, BOOL bottom_up,
1536 IMFMediaBuffer **buffer)
1538 TRACE("%s, %p, %u, %d, %p.\n", debugstr_guid(riid), surface, subresource, bottom_up, buffer);
1540 if (!IsEqualIID(riid, &IID_ID3D11Texture2D))
1541 return E_INVALIDARG;
1543 return create_dxgi_surface_buffer(surface, subresource, bottom_up, buffer);
1546 static unsigned int buffer_get_aligned_length(unsigned int length, unsigned int alignment)
1548 length = (length + alignment) / alignment;
1549 length *= alignment;
1551 return length;
1554 HRESULT WINAPI MFCreateMediaBufferFromMediaType(IMFMediaType *media_type, LONGLONG duration, DWORD min_length,
1555 DWORD alignment, IMFMediaBuffer **buffer)
1557 UINT32 length = 0, block_alignment;
1558 LONGLONG avg_length;
1559 HRESULT hr;
1560 GUID major;
1562 TRACE("%p, %s, %u, %u, %p.\n", media_type, debugstr_time(duration), min_length, alignment, buffer);
1564 if (!media_type)
1565 return E_INVALIDARG;
1567 if (FAILED(hr = IMFMediaType_GetMajorType(media_type, &major)))
1568 return hr;
1570 if (IsEqualGUID(&major, &MFMediaType_Audio))
1572 block_alignment = 0;
1573 if (FAILED(IMFMediaType_GetUINT32(media_type, &MF_MT_AUDIO_BLOCK_ALIGNMENT, &block_alignment)))
1574 WARN("Block alignment was not specified.\n");
1576 if (block_alignment)
1578 avg_length = 0;
1580 if (duration)
1582 length = 0;
1583 if (SUCCEEDED(IMFMediaType_GetUINT32(media_type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, &length)))
1585 /* 100 ns -> 1 s */
1586 avg_length = length * duration / (10 * 1000 * 1000);
1590 alignment = max(16, alignment);
1592 length = buffer_get_aligned_length(avg_length + 1, alignment);
1593 length = buffer_get_aligned_length(length, block_alignment);
1595 else
1596 length = 0;
1598 length = max(length, min_length);
1600 return create_1d_buffer(length, MF_1_BYTE_ALIGNMENT, buffer);
1602 else
1603 FIXME("Major type %s is not supported.\n", debugstr_guid(&major));
1605 return E_NOTIMPL;