mfplat: Add a stub for 2D system memory buffer object.
[wine.git] / dlls / mfplat / buffer.c
blob590288e3442e4272b39dd558a58b8b7449f2f375
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"
23 #include "wine/debug.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(mfplat);
27 #define ALIGN_SIZE(size, alignment) (((size) + (alignment - 1)) & ~((alignment - 1)))
29 struct memory_buffer
31 IMFMediaBuffer IMFMediaBuffer_iface;
32 IMF2DBuffer2 IMF2DBuffer2_iface;
33 LONG refcount;
35 BYTE *data;
36 DWORD max_length;
37 DWORD current_length;
40 enum sample_prop_flags
42 SAMPLE_PROP_HAS_DURATION = 1 << 0,
43 SAMPLE_PROP_HAS_TIMESTAMP = 1 << 1,
46 struct sample
48 struct attributes attributes;
49 IMFSample IMFSample_iface;
51 IMFMediaBuffer **buffers;
52 size_t buffer_count;
53 size_t capacity;
54 DWORD flags;
55 DWORD prop_flags;
56 LONGLONG duration;
57 LONGLONG timestamp;
60 static inline struct memory_buffer *impl_from_IMFMediaBuffer(IMFMediaBuffer *iface)
62 return CONTAINING_RECORD(iface, struct memory_buffer, IMFMediaBuffer_iface);
65 static struct memory_buffer *impl_from_IMF2DBuffer2(IMF2DBuffer2 *iface)
67 return CONTAINING_RECORD(iface, struct memory_buffer, IMF2DBuffer2_iface);
70 static inline struct sample *impl_from_IMFSample(IMFSample *iface)
72 return CONTAINING_RECORD(iface, struct sample, IMFSample_iface);
75 static HRESULT WINAPI memory_buffer_QueryInterface(IMFMediaBuffer *iface, REFIID riid, void **out)
77 struct memory_buffer *buffer = impl_from_IMFMediaBuffer(iface);
79 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
81 if (IsEqualIID(riid, &IID_IMFMediaBuffer) ||
82 IsEqualIID(riid, &IID_IUnknown))
84 *out = &buffer->IMFMediaBuffer_iface;
86 else
88 FIXME("(%s, %p)\n", debugstr_guid(riid), out);
89 *out = NULL;
90 return E_NOINTERFACE;
93 IUnknown_AddRef((IUnknown*)*out);
94 return S_OK;
97 static ULONG WINAPI memory_buffer_AddRef(IMFMediaBuffer *iface)
99 struct memory_buffer *buffer = impl_from_IMFMediaBuffer(iface);
100 ULONG refcount = InterlockedIncrement(&buffer->refcount);
102 TRACE("%p, refcount %u.\n", buffer, refcount);
104 return refcount;
107 static ULONG WINAPI memory_buffer_Release(IMFMediaBuffer *iface)
109 struct memory_buffer *buffer = impl_from_IMFMediaBuffer(iface);
110 ULONG refcount = InterlockedDecrement(&buffer->refcount);
112 TRACE("%p, refcount %u.\n", iface, refcount);
114 if (!refcount)
116 heap_free(buffer->data);
117 heap_free(buffer);
120 return refcount;
123 static HRESULT WINAPI memory_buffer_Lock(IMFMediaBuffer *iface, BYTE **data, DWORD *max_length, DWORD *current_length)
125 struct memory_buffer *buffer = impl_from_IMFMediaBuffer(iface);
127 TRACE("%p, %p %p, %p.\n", iface, data, max_length, current_length);
129 if (!data)
130 return E_INVALIDARG;
132 *data = buffer->data;
133 if (max_length)
134 *max_length = buffer->max_length;
135 if (current_length)
136 *current_length = buffer->current_length;
138 return S_OK;
141 static HRESULT WINAPI memory_buffer_Unlock(IMFMediaBuffer *iface)
143 TRACE("%p.\n", iface);
145 return S_OK;
148 static HRESULT WINAPI memory_buffer_GetCurrentLength(IMFMediaBuffer *iface, DWORD *current_length)
150 struct memory_buffer *buffer = impl_from_IMFMediaBuffer(iface);
152 TRACE("%p.\n", iface);
154 if (!current_length)
155 return E_INVALIDARG;
157 *current_length = buffer->current_length;
159 return S_OK;
162 static HRESULT WINAPI memory_buffer_SetCurrentLength(IMFMediaBuffer *iface, DWORD current_length)
164 struct memory_buffer *buffer = impl_from_IMFMediaBuffer(iface);
166 TRACE("%p, %u.\n", iface, current_length);
168 if (current_length > buffer->max_length)
169 return E_INVALIDARG;
171 buffer->current_length = current_length;
173 return S_OK;
176 static HRESULT WINAPI memory_buffer_GetMaxLength(IMFMediaBuffer *iface, DWORD *max_length)
178 struct memory_buffer *buffer = impl_from_IMFMediaBuffer(iface);
180 TRACE("%p, %p.\n", iface, max_length);
182 if (!max_length)
183 return E_INVALIDARG;
185 *max_length = buffer->max_length;
187 return S_OK;
190 static const IMFMediaBufferVtbl memory_1d_buffer_vtbl =
192 memory_buffer_QueryInterface,
193 memory_buffer_AddRef,
194 memory_buffer_Release,
195 memory_buffer_Lock,
196 memory_buffer_Unlock,
197 memory_buffer_GetCurrentLength,
198 memory_buffer_SetCurrentLength,
199 memory_buffer_GetMaxLength,
202 static HRESULT WINAPI memory_1d_2d_buffer_QueryInterface(IMFMediaBuffer *iface, REFIID riid, void **out)
204 struct memory_buffer *buffer = impl_from_IMFMediaBuffer(iface);
206 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
208 if (IsEqualIID(riid, &IID_IMFMediaBuffer) ||
209 IsEqualIID(riid, &IID_IUnknown))
211 *out = &buffer->IMFMediaBuffer_iface;
213 else if (IsEqualIID(riid, &IID_IMF2DBuffer2) ||
214 IsEqualIID(riid, &IID_IMF2DBuffer))
216 *out = &buffer->IMF2DBuffer2_iface;
218 else
220 WARN("Unsupported interface %s.\n", debugstr_guid(riid));
221 *out = NULL;
222 return E_NOINTERFACE;
225 IUnknown_AddRef((IUnknown*)*out);
226 return S_OK;
229 static const IMFMediaBufferVtbl memory_1d_2d_buffer_vtbl =
231 memory_1d_2d_buffer_QueryInterface,
232 memory_buffer_AddRef,
233 memory_buffer_Release,
234 memory_buffer_Lock,
235 memory_buffer_Unlock,
236 memory_buffer_GetCurrentLength,
237 memory_buffer_SetCurrentLength,
238 memory_buffer_GetMaxLength,
241 static HRESULT WINAPI memory_2d_buffer_QueryInterface(IMF2DBuffer2 *iface, REFIID riid, void **obj)
243 struct memory_buffer *buffer = impl_from_IMF2DBuffer2(iface);
244 return IMFMediaBuffer_QueryInterface(&buffer->IMFMediaBuffer_iface, riid, obj);
247 static ULONG WINAPI memory_2d_buffer_AddRef(IMF2DBuffer2 *iface)
249 struct memory_buffer *buffer = impl_from_IMF2DBuffer2(iface);
250 return IMFMediaBuffer_AddRef(&buffer->IMFMediaBuffer_iface);
253 static ULONG WINAPI memory_2d_buffer_Release(IMF2DBuffer2 *iface)
255 struct memory_buffer *buffer = impl_from_IMF2DBuffer2(iface);
256 return IMFMediaBuffer_Release(&buffer->IMFMediaBuffer_iface);
259 static HRESULT WINAPI memory_2d_buffer_Lock2D(IMF2DBuffer2 *iface, BYTE **scanline0, LONG *pitch)
261 FIXME("%p, %p, %p.\n", iface, scanline0, pitch);
263 return E_NOTIMPL;
266 static HRESULT WINAPI memory_2d_buffer_Unlock2D(IMF2DBuffer2 *iface)
268 FIXME("%p.\n", iface);
270 return E_NOTIMPL;
273 static HRESULT WINAPI memory_2d_buffer_GetScanline0AndPitch(IMF2DBuffer2 *iface, BYTE **scanline0, LONG *pitch)
275 FIXME("%p, %p, %p.\n", iface, scanline0, pitch);
277 return E_NOTIMPL;
280 static HRESULT WINAPI memory_2d_buffer_IsContiguousFormat(IMF2DBuffer2 *iface, BOOL *is_contiguous)
282 FIXME("%p, %p.\n", iface, is_contiguous);
284 return E_NOTIMPL;
287 static HRESULT WINAPI memory_2d_buffer_GetContiguousLength(IMF2DBuffer2 *iface, DWORD *length)
289 FIXME("%p, %p.\n", iface, length);
291 return E_NOTIMPL;
294 static HRESULT WINAPI memory_2d_buffer_ContiguousCopyTo(IMF2DBuffer2 *iface, BYTE *dest_buffer, DWORD dest_length)
296 FIXME("%p, %p, %u.\n", iface, dest_buffer, dest_length);
298 return E_NOTIMPL;
301 static HRESULT WINAPI memory_2d_buffer_ContiguousCopyFrom(IMF2DBuffer2 *iface, const BYTE *src_buffer, DWORD src_length)
303 FIXME("%p, %p, %u.\n", iface, src_buffer, src_length);
305 return E_NOTIMPL;
308 static HRESULT WINAPI memory_2d_buffer_Lock2DSize(IMF2DBuffer2 *iface, MF2DBuffer_LockFlags flags, BYTE **scanline0,
309 LONG *pitch, BYTE **buffer_start, DWORD *buffer_length)
311 FIXME("%p, %#x, %p, %p, %p, %p.\n", iface, flags, scanline0, pitch, buffer_start, buffer_length);
313 return E_NOTIMPL;
316 static HRESULT WINAPI memory_2d_buffer_Copy2DTo(IMF2DBuffer2 *iface, IMF2DBuffer2 *dest_buffer)
318 FIXME("%p, %p.\n", iface, dest_buffer);
320 return E_NOTIMPL;
323 static const IMF2DBuffer2Vtbl memory_2d_buffer_vtbl =
325 memory_2d_buffer_QueryInterface,
326 memory_2d_buffer_AddRef,
327 memory_2d_buffer_Release,
328 memory_2d_buffer_Lock2D,
329 memory_2d_buffer_Unlock2D,
330 memory_2d_buffer_GetScanline0AndPitch,
331 memory_2d_buffer_IsContiguousFormat,
332 memory_2d_buffer_GetContiguousLength,
333 memory_2d_buffer_ContiguousCopyTo,
334 memory_2d_buffer_ContiguousCopyFrom,
335 memory_2d_buffer_Lock2DSize,
336 memory_2d_buffer_Copy2DTo,
339 static HRESULT memory_buffer_init(struct memory_buffer *buffer, DWORD max_length, DWORD alignment,
340 const IMFMediaBufferVtbl *vtbl)
342 buffer->data = heap_alloc(ALIGN_SIZE(max_length, alignment));
343 if (!buffer->data)
344 return E_OUTOFMEMORY;
346 buffer->IMFMediaBuffer_iface.lpVtbl = vtbl;
347 buffer->refcount = 1;
348 buffer->max_length = max_length;
349 buffer->current_length = 0;
351 return S_OK;
354 static HRESULT create_1d_buffer(DWORD max_length, DWORD alignment, IMFMediaBuffer **buffer)
356 struct memory_buffer *object;
357 HRESULT hr;
359 if (!buffer)
360 return E_POINTER;
362 *buffer = NULL;
364 object = heap_alloc_zero(sizeof(*object));
365 if (!object)
366 return E_OUTOFMEMORY;
368 hr = memory_buffer_init(object, max_length, alignment, &memory_1d_buffer_vtbl);
369 if (FAILED(hr))
371 heap_free(object);
372 return hr;
375 *buffer = &object->IMFMediaBuffer_iface;
377 return S_OK;
380 static HRESULT create_2d_buffer(DWORD width, DWORD height, DWORD fourcc, IMFMediaBuffer **buffer)
382 struct memory_buffer *object;
383 unsigned int bpp, max_length;
384 GUID subtype;
385 HRESULT hr;
387 if (!buffer)
388 return E_POINTER;
390 *buffer = NULL;
392 memcpy(&subtype, &MFVideoFormat_Base, sizeof(subtype));
393 subtype.Data1 = fourcc;
395 if (!(bpp = mf_format_get_bpp(&subtype)))
396 return MF_E_INVALIDMEDIATYPE;
398 object = heap_alloc_zero(sizeof(*object));
399 if (!object)
400 return E_OUTOFMEMORY;
402 switch (fourcc)
404 case MAKEFOURCC('N','V','1','2'):
405 max_length = ALIGN_SIZE(width * bpp, 64) * height * 3 / 2;
406 break;
407 default:
408 max_length = ALIGN_SIZE(width * bpp, 64) * height;
411 hr = memory_buffer_init(object, max_length, MF_1_BYTE_ALIGNMENT, &memory_1d_2d_buffer_vtbl);
412 object->IMF2DBuffer2_iface.lpVtbl = &memory_2d_buffer_vtbl;
413 if (FAILED(hr))
415 heap_free(object);
416 return hr;
419 *buffer = &object->IMFMediaBuffer_iface;
421 return S_OK;
424 /***********************************************************************
425 * MFCreateMemoryBuffer (mfplat.@)
427 HRESULT WINAPI MFCreateMemoryBuffer(DWORD max_length, IMFMediaBuffer **buffer)
429 TRACE("%u, %p.\n", max_length, buffer);
431 return create_1d_buffer(max_length, MF_1_BYTE_ALIGNMENT, buffer);
434 /***********************************************************************
435 * MFCreateAlignedMemoryBuffer (mfplat.@)
437 HRESULT WINAPI MFCreateAlignedMemoryBuffer(DWORD max_length, DWORD alignment, IMFMediaBuffer **buffer)
439 TRACE("%u, %u, %p.\n", max_length, alignment, buffer);
441 return create_1d_buffer(max_length, alignment, buffer);
444 HRESULT WINAPI MFCreate2DMediaBuffer(DWORD width, DWORD height, DWORD fourcc, BOOL bottom_up, IMFMediaBuffer **buffer)
446 TRACE("%u, %u, %#x, %d, %p.\n", width, height, fourcc, bottom_up, buffer);
448 return create_2d_buffer(width, height, fourcc, buffer);
451 static HRESULT WINAPI sample_QueryInterface(IMFSample *iface, REFIID riid, void **out)
453 TRACE("%p, %s, %p.\n", iface, debugstr_guid(riid), out);
455 if (IsEqualIID(riid, &IID_IMFSample) ||
456 IsEqualIID(riid, &IID_IMFAttributes) ||
457 IsEqualIID(riid, &IID_IUnknown))
459 *out = iface;
460 IMFSample_AddRef(iface);
461 return S_OK;
464 WARN("Unsupported %s.\n", debugstr_guid(riid));
465 *out = NULL;
466 return E_NOINTERFACE;
469 static ULONG WINAPI sample_AddRef(IMFSample *iface)
471 struct sample *sample = impl_from_IMFSample(iface);
472 ULONG refcount = InterlockedIncrement(&sample->attributes.ref);
474 TRACE("%p, refcount %u.\n", iface, refcount);
476 return refcount;
479 static ULONG WINAPI sample_Release(IMFSample *iface)
481 struct sample *sample = impl_from_IMFSample(iface);
482 ULONG refcount = InterlockedDecrement(&sample->attributes.ref);
483 size_t i;
485 TRACE("%p, refcount %u.\n", iface, refcount);
487 if (!refcount)
489 for (i = 0; i < sample->buffer_count; ++i)
490 IMFMediaBuffer_Release(sample->buffers[i]);
491 clear_attributes_object(&sample->attributes);
492 heap_free(sample->buffers);
493 heap_free(sample);
496 return refcount;
499 static HRESULT WINAPI sample_GetItem(IMFSample *iface, REFGUID key, PROPVARIANT *value)
501 struct sample *sample = impl_from_IMFSample(iface);
503 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
505 return attributes_GetItem(&sample->attributes, key, value);
508 static HRESULT WINAPI sample_GetItemType(IMFSample *iface, REFGUID key, MF_ATTRIBUTE_TYPE *type)
510 struct sample *sample = impl_from_IMFSample(iface);
512 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), type);
514 return attributes_GetItemType(&sample->attributes, key, type);
517 static HRESULT WINAPI sample_CompareItem(IMFSample *iface, REFGUID key, REFPROPVARIANT value, BOOL *result)
519 struct sample *sample = impl_from_IMFSample(iface);
521 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_propvar(value), result);
523 return attributes_CompareItem(&sample->attributes, key, value, result);
526 static HRESULT WINAPI sample_Compare(IMFSample *iface, IMFAttributes *theirs, MF_ATTRIBUTES_MATCH_TYPE type,
527 BOOL *result)
529 struct sample *sample = impl_from_IMFSample(iface);
531 TRACE("%p, %p, %d, %p.\n", iface, theirs, type, result);
533 return attributes_Compare(&sample->attributes, theirs, type, result);
536 static HRESULT WINAPI sample_GetUINT32(IMFSample *iface, REFGUID key, UINT32 *value)
538 struct sample *sample = impl_from_IMFSample(iface);
540 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
542 return attributes_GetUINT32(&sample->attributes, key, value);
545 static HRESULT WINAPI sample_GetUINT64(IMFSample *iface, REFGUID key, UINT64 *value)
547 struct sample *sample = impl_from_IMFSample(iface);
549 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
551 return attributes_GetUINT64(&sample->attributes, key, value);
554 static HRESULT WINAPI sample_GetDouble(IMFSample *iface, REFGUID key, double *value)
556 struct sample *sample = impl_from_IMFSample(iface);
558 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
560 return attributes_GetDouble(&sample->attributes, key, value);
563 static HRESULT WINAPI sample_GetGUID(IMFSample *iface, REFGUID key, GUID *value)
565 struct sample *sample = impl_from_IMFSample(iface);
567 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), value);
569 return attributes_GetGUID(&sample->attributes, key, value);
572 static HRESULT WINAPI sample_GetStringLength(IMFSample *iface, REFGUID key, UINT32 *length)
574 struct sample *sample = impl_from_IMFSample(iface);
576 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), length);
578 return attributes_GetStringLength(&sample->attributes, key, length);
581 static HRESULT WINAPI sample_GetString(IMFSample *iface, REFGUID key, WCHAR *value, UINT32 size, UINT32 *length)
583 struct sample *sample = impl_from_IMFSample(iface);
585 TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_attr(key), value, size, length);
587 return attributes_GetString(&sample->attributes, key, value, size, length);
590 static HRESULT WINAPI sample_GetAllocatedString(IMFSample *iface, REFGUID key, WCHAR **value, UINT32 *length)
592 struct sample *sample = impl_from_IMFSample(iface);
594 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), value, length);
596 return attributes_GetAllocatedString(&sample->attributes, key, value, length);
599 static HRESULT WINAPI sample_GetBlobSize(IMFSample *iface, REFGUID key, UINT32 *size)
601 struct sample *sample = impl_from_IMFSample(iface);
603 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), size);
605 return attributes_GetBlobSize(&sample->attributes, key, size);
608 static HRESULT WINAPI sample_GetBlob(IMFSample *iface, REFGUID key, UINT8 *buf, UINT32 bufsize, UINT32 *blobsize)
610 struct sample *sample = impl_from_IMFSample(iface);
612 TRACE("%p, %s, %p, %u, %p.\n", iface, debugstr_attr(key), buf, bufsize, blobsize);
614 return attributes_GetBlob(&sample->attributes, key, buf, bufsize, blobsize);
617 static HRESULT WINAPI sample_GetAllocatedBlob(IMFSample *iface, REFGUID key, UINT8 **buf, UINT32 *size)
619 struct sample *sample = impl_from_IMFSample(iface);
621 TRACE("%p, %s, %p, %p.\n", iface, debugstr_attr(key), buf, size);
623 return attributes_GetAllocatedBlob(&sample->attributes, key, buf, size);
626 static HRESULT WINAPI sample_GetUnknown(IMFSample *iface, REFGUID key, REFIID riid, void **out)
628 struct sample *sample = impl_from_IMFSample(iface);
630 TRACE("%p, %s, %s, %p.\n", iface, debugstr_attr(key), debugstr_guid(riid), out);
632 return attributes_GetUnknown(&sample->attributes, key, riid, out);
635 static HRESULT WINAPI sample_SetItem(IMFSample *iface, REFGUID key, REFPROPVARIANT value)
637 struct sample *sample = impl_from_IMFSample(iface);
639 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_propvar(value));
641 return attributes_SetItem(&sample->attributes, key, value);
644 static HRESULT WINAPI sample_DeleteItem(IMFSample *iface, REFGUID key)
646 struct sample *sample = impl_from_IMFSample(iface);
648 TRACE("%p, %s.\n", iface, debugstr_attr(key));
650 return attributes_DeleteItem(&sample->attributes, key);
653 static HRESULT WINAPI sample_DeleteAllItems(IMFSample *iface)
655 struct sample *sample = impl_from_IMFSample(iface);
657 TRACE("%p.\n", iface);
659 return attributes_DeleteAllItems(&sample->attributes);
662 static HRESULT WINAPI sample_SetUINT32(IMFSample *iface, REFGUID key, UINT32 value)
664 struct sample *sample = impl_from_IMFSample(iface);
666 TRACE("%p, %s, %u.\n", iface, debugstr_attr(key), value);
668 return attributes_SetUINT32(&sample->attributes, key, value);
671 static HRESULT WINAPI sample_SetUINT64(IMFSample *iface, REFGUID key, UINT64 value)
673 struct sample *sample = impl_from_IMFSample(iface);
675 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), wine_dbgstr_longlong(value));
677 return attributes_SetUINT64(&sample->attributes, key, value);
680 static HRESULT WINAPI sample_SetDouble(IMFSample *iface, REFGUID key, double value)
682 struct sample *sample = impl_from_IMFSample(iface);
684 TRACE("%p, %s, %f.\n", iface, debugstr_attr(key), value);
686 return attributes_SetDouble(&sample->attributes, key, value);
689 static HRESULT WINAPI sample_SetGUID(IMFSample *iface, REFGUID key, REFGUID value)
691 struct sample *sample = impl_from_IMFSample(iface);
693 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_mf_guid(value));
695 return attributes_SetGUID(&sample->attributes, key, value);
698 static HRESULT WINAPI sample_SetString(IMFSample *iface, REFGUID key, const WCHAR *value)
700 struct sample *sample = impl_from_IMFSample(iface);
702 TRACE("%p, %s, %s.\n", iface, debugstr_attr(key), debugstr_w(value));
704 return attributes_SetString(&sample->attributes, key, value);
707 static HRESULT WINAPI sample_SetBlob(IMFSample *iface, REFGUID key, const UINT8 *buf, UINT32 size)
709 struct sample *sample = impl_from_IMFSample(iface);
711 TRACE("%p, %s, %p, %u.\n", iface, debugstr_attr(key), buf, size);
713 return attributes_SetBlob(&sample->attributes, key, buf, size);
716 static HRESULT WINAPI sample_SetUnknown(IMFSample *iface, REFGUID key, IUnknown *unknown)
718 struct sample *sample = impl_from_IMFSample(iface);
720 TRACE("%p, %s, %p.\n", iface, debugstr_attr(key), unknown);
722 return attributes_SetUnknown(&sample->attributes, key, unknown);
725 static HRESULT WINAPI sample_LockStore(IMFSample *iface)
727 struct sample *sample = impl_from_IMFSample(iface);
729 TRACE("%p.\n", iface);
731 return attributes_LockStore(&sample->attributes);
734 static HRESULT WINAPI sample_UnlockStore(IMFSample *iface)
736 struct sample *sample = impl_from_IMFSample(iface);
738 TRACE("%p.\n", iface);
740 return attributes_UnlockStore(&sample->attributes);
743 static HRESULT WINAPI sample_GetCount(IMFSample *iface, UINT32 *count)
745 struct sample *sample = impl_from_IMFSample(iface);
747 TRACE("%p, %p.\n", iface, count);
749 return attributes_GetCount(&sample->attributes, count);
752 static HRESULT WINAPI sample_GetItemByIndex(IMFSample *iface, UINT32 index, GUID *key, PROPVARIANT *value)
754 struct sample *sample = impl_from_IMFSample(iface);
756 TRACE("%p, %u, %p, %p.\n", iface, index, key, value);
758 return attributes_GetItemByIndex(&sample->attributes, index, key, value);
761 static HRESULT WINAPI sample_CopyAllItems(IMFSample *iface, IMFAttributes *dest)
763 struct sample *sample = impl_from_IMFSample(iface);
765 TRACE("%p, %p.\n", iface, dest);
767 return attributes_CopyAllItems(&sample->attributes, dest);
770 static HRESULT WINAPI sample_GetSampleFlags(IMFSample *iface, DWORD *flags)
772 struct sample *sample = impl_from_IMFSample(iface);
774 TRACE("%p, %p.\n", iface, flags);
776 EnterCriticalSection(&sample->attributes.cs);
777 *flags = sample->flags;
778 LeaveCriticalSection(&sample->attributes.cs);
780 return S_OK;
783 static HRESULT WINAPI sample_SetSampleFlags(IMFSample *iface, DWORD flags)
785 struct sample *sample = impl_from_IMFSample(iface);
787 TRACE("%p, %#x.\n", iface, flags);
789 EnterCriticalSection(&sample->attributes.cs);
790 sample->flags = flags;
791 LeaveCriticalSection(&sample->attributes.cs);
793 return S_OK;
796 static HRESULT WINAPI sample_GetSampleTime(IMFSample *iface, LONGLONG *timestamp)
798 struct sample *sample = impl_from_IMFSample(iface);
799 HRESULT hr = S_OK;
801 TRACE("%p, %p.\n", iface, timestamp);
803 EnterCriticalSection(&sample->attributes.cs);
804 if (sample->prop_flags & SAMPLE_PROP_HAS_TIMESTAMP)
805 *timestamp = sample->timestamp;
806 else
807 hr = MF_E_NO_SAMPLE_TIMESTAMP;
808 LeaveCriticalSection(&sample->attributes.cs);
810 return hr;
813 static HRESULT WINAPI sample_SetSampleTime(IMFSample *iface, LONGLONG timestamp)
815 struct sample *sample = impl_from_IMFSample(iface);
817 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(timestamp));
819 EnterCriticalSection(&sample->attributes.cs);
820 sample->timestamp = timestamp;
821 sample->prop_flags |= SAMPLE_PROP_HAS_TIMESTAMP;
822 LeaveCriticalSection(&sample->attributes.cs);
824 return S_OK;
827 static HRESULT WINAPI sample_GetSampleDuration(IMFSample *iface, LONGLONG *duration)
829 struct sample *sample = impl_from_IMFSample(iface);
830 HRESULT hr = S_OK;
832 TRACE("%p, %p.\n", iface, duration);
834 EnterCriticalSection(&sample->attributes.cs);
835 if (sample->prop_flags & SAMPLE_PROP_HAS_DURATION)
836 *duration = sample->duration;
837 else
838 hr = MF_E_NO_SAMPLE_DURATION;
839 LeaveCriticalSection(&sample->attributes.cs);
841 return hr;
844 static HRESULT WINAPI sample_SetSampleDuration(IMFSample *iface, LONGLONG duration)
846 struct sample *sample = impl_from_IMFSample(iface);
848 TRACE("%p, %s.\n", iface, wine_dbgstr_longlong(duration));
850 EnterCriticalSection(&sample->attributes.cs);
851 sample->duration = duration;
852 sample->prop_flags |= SAMPLE_PROP_HAS_DURATION;
853 LeaveCriticalSection(&sample->attributes.cs);
855 return S_OK;
858 static HRESULT WINAPI sample_GetBufferCount(IMFSample *iface, DWORD *count)
860 struct sample *sample = impl_from_IMFSample(iface);
862 TRACE("%p, %p.\n", iface, count);
864 if (!count)
865 return E_INVALIDARG;
867 EnterCriticalSection(&sample->attributes.cs);
868 *count = sample->buffer_count;
869 LeaveCriticalSection(&sample->attributes.cs);
871 return S_OK;
874 static HRESULT WINAPI sample_GetBufferByIndex(IMFSample *iface, DWORD index, IMFMediaBuffer **buffer)
876 struct sample *sample = impl_from_IMFSample(iface);
877 HRESULT hr = S_OK;
879 TRACE("%p, %u, %p.\n", iface, index, buffer);
881 EnterCriticalSection(&sample->attributes.cs);
882 if (index < sample->buffer_count)
884 *buffer = sample->buffers[index];
885 IMFMediaBuffer_AddRef(*buffer);
887 else
888 hr = E_INVALIDARG;
889 LeaveCriticalSection(&sample->attributes.cs);
891 return hr;
894 static HRESULT WINAPI sample_ConvertToContiguousBuffer(IMFSample *iface, IMFMediaBuffer **buffer)
896 struct sample *sample = impl_from_IMFSample(iface);
897 HRESULT hr = S_OK;
899 TRACE("%p, %p.\n", iface, buffer);
901 EnterCriticalSection(&sample->attributes.cs);
903 if (sample->buffer_count == 0)
904 hr = E_UNEXPECTED;
905 else if (sample->buffer_count == 1)
907 *buffer = sample->buffers[0];
908 IMFMediaBuffer_AddRef(*buffer);
910 else
912 FIXME("Samples with multiple buffers are not supported.\n");
913 hr = E_NOTIMPL;
916 LeaveCriticalSection(&sample->attributes.cs);
918 return hr;
921 static HRESULT WINAPI sample_AddBuffer(IMFSample *iface, IMFMediaBuffer *buffer)
923 struct sample *sample = impl_from_IMFSample(iface);
924 HRESULT hr = S_OK;
926 TRACE("%p, %p.\n", iface, buffer);
928 EnterCriticalSection(&sample->attributes.cs);
929 if (!mf_array_reserve((void **)&sample->buffers, &sample->capacity, sample->buffer_count + 1,
930 sizeof(*sample->buffers)))
931 hr = E_OUTOFMEMORY;
932 else
934 sample->buffers[sample->buffer_count++] = buffer;
935 IMFMediaBuffer_AddRef(buffer);
937 LeaveCriticalSection(&sample->attributes.cs);
939 return hr;
942 static HRESULT WINAPI sample_RemoveBufferByIndex(IMFSample *iface, DWORD index)
944 struct sample *sample = impl_from_IMFSample(iface);
945 HRESULT hr = S_OK;
947 TRACE("%p, %u.\n", iface, index);
949 EnterCriticalSection(&sample->attributes.cs);
950 if (index < sample->buffer_count)
952 IMFMediaBuffer_Release(sample->buffers[index]);
953 if (index < sample->buffer_count - 1)
955 memmove(&sample->buffers[index], &sample->buffers[index+1],
956 (sample->buffer_count - index - 1) * sizeof(*sample->buffers));
958 sample->buffer_count--;
960 else
961 hr = E_INVALIDARG;
962 LeaveCriticalSection(&sample->attributes.cs);
964 return hr;
967 static HRESULT WINAPI sample_RemoveAllBuffers(IMFSample *iface)
969 struct sample *sample = impl_from_IMFSample(iface);
970 size_t i;
972 TRACE("%p.\n", iface);
974 EnterCriticalSection(&sample->attributes.cs);
975 for (i = 0; i < sample->buffer_count; ++i)
976 IMFMediaBuffer_Release(sample->buffers[i]);
977 sample->buffer_count = 0;
978 LeaveCriticalSection(&sample->attributes.cs);
980 return S_OK;
983 static DWORD sample_get_total_length(struct sample *sample)
985 DWORD total_length = 0, length;
986 size_t i;
988 for (i = 0; i < sample->buffer_count; ++i)
990 length = 0;
991 if (SUCCEEDED(IMFMediaBuffer_GetCurrentLength(sample->buffers[i], &length)))
992 total_length += length;
995 return total_length;
998 static HRESULT WINAPI sample_GetTotalLength(IMFSample *iface, DWORD *total_length)
1000 struct sample *sample = impl_from_IMFSample(iface);
1002 TRACE("%p, %p.\n", iface, total_length);
1004 EnterCriticalSection(&sample->attributes.cs);
1005 *total_length = sample_get_total_length(sample);
1006 LeaveCriticalSection(&sample->attributes.cs);
1008 return S_OK;
1011 static HRESULT WINAPI sample_CopyToBuffer(IMFSample *iface, IMFMediaBuffer *buffer)
1013 struct sample *sample = impl_from_IMFSample(iface);
1014 DWORD total_length, dst_length, dst_current_length, src_max_length, current_length;
1015 BYTE *src_ptr, *dst_ptr;
1016 BOOL locked;
1017 HRESULT hr;
1018 size_t i;
1020 TRACE("%p, %p.\n", iface, buffer);
1022 EnterCriticalSection(&sample->attributes.cs);
1024 total_length = sample_get_total_length(sample);
1025 dst_current_length = 0;
1027 dst_ptr = NULL;
1028 dst_length = current_length = 0;
1029 locked = SUCCEEDED(hr = IMFMediaBuffer_Lock(buffer, &dst_ptr, &dst_length, &current_length));
1030 if (locked)
1032 if (dst_length < total_length)
1033 hr = MF_E_BUFFERTOOSMALL;
1034 else if (dst_ptr)
1036 for (i = 0; i < sample->buffer_count && SUCCEEDED(hr); ++i)
1038 src_ptr = NULL;
1039 src_max_length = current_length = 0;
1040 if (SUCCEEDED(hr = IMFMediaBuffer_Lock(sample->buffers[i], &src_ptr, &src_max_length, &current_length)))
1042 if (src_ptr)
1044 if (current_length > dst_length)
1045 hr = MF_E_BUFFERTOOSMALL;
1046 else if (current_length)
1048 memcpy(dst_ptr, src_ptr, current_length);
1049 dst_length -= current_length;
1050 dst_current_length += current_length;
1051 dst_ptr += current_length;
1054 IMFMediaBuffer_Unlock(sample->buffers[i]);
1060 IMFMediaBuffer_SetCurrentLength(buffer, dst_current_length);
1062 if (locked)
1063 IMFMediaBuffer_Unlock(buffer);
1065 LeaveCriticalSection(&sample->attributes.cs);
1067 return hr;
1070 static const IMFSampleVtbl samplevtbl =
1072 sample_QueryInterface,
1073 sample_AddRef,
1074 sample_Release,
1075 sample_GetItem,
1076 sample_GetItemType,
1077 sample_CompareItem,
1078 sample_Compare,
1079 sample_GetUINT32,
1080 sample_GetUINT64,
1081 sample_GetDouble,
1082 sample_GetGUID,
1083 sample_GetStringLength,
1084 sample_GetString,
1085 sample_GetAllocatedString,
1086 sample_GetBlobSize,
1087 sample_GetBlob,
1088 sample_GetAllocatedBlob,
1089 sample_GetUnknown,
1090 sample_SetItem,
1091 sample_DeleteItem,
1092 sample_DeleteAllItems,
1093 sample_SetUINT32,
1094 sample_SetUINT64,
1095 sample_SetDouble,
1096 sample_SetGUID,
1097 sample_SetString,
1098 sample_SetBlob,
1099 sample_SetUnknown,
1100 sample_LockStore,
1101 sample_UnlockStore,
1102 sample_GetCount,
1103 sample_GetItemByIndex,
1104 sample_CopyAllItems,
1105 sample_GetSampleFlags,
1106 sample_SetSampleFlags,
1107 sample_GetSampleTime,
1108 sample_SetSampleTime,
1109 sample_GetSampleDuration,
1110 sample_SetSampleDuration,
1111 sample_GetBufferCount,
1112 sample_GetBufferByIndex,
1113 sample_ConvertToContiguousBuffer,
1114 sample_AddBuffer,
1115 sample_RemoveBufferByIndex,
1116 sample_RemoveAllBuffers,
1117 sample_GetTotalLength,
1118 sample_CopyToBuffer,
1121 /***********************************************************************
1122 * MFCreateSample (mfplat.@)
1124 HRESULT WINAPI MFCreateSample(IMFSample **sample)
1126 struct sample *object;
1127 HRESULT hr;
1129 TRACE("%p.\n", sample);
1131 object = heap_alloc_zero(sizeof(*object));
1132 if (!object)
1133 return E_OUTOFMEMORY;
1135 if (FAILED(hr = init_attributes_object(&object->attributes, 0)))
1137 heap_free(object);
1138 return hr;
1141 object->IMFSample_iface.lpVtbl = &samplevtbl;
1143 *sample = &object->IMFSample_iface;
1145 TRACE("Created sample %p.\n", *sample);
1147 return S_OK;