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