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
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)))
31 IMFMediaBuffer IMFMediaBuffer_iface
;
32 IMF2DBuffer2 IMF2DBuffer2_iface
;
40 enum sample_prop_flags
42 SAMPLE_PROP_HAS_DURATION
= 1 << 0,
43 SAMPLE_PROP_HAS_TIMESTAMP
= 1 << 1,
48 struct attributes attributes
;
49 IMFSample IMFSample_iface
;
51 IMFMediaBuffer
**buffers
;
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
;
88 FIXME("(%s, %p)\n", debugstr_guid(riid
), out
);
93 IUnknown_AddRef((IUnknown
*)*out
);
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
);
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
);
116 heap_free(buffer
->data
);
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
);
132 *data
= buffer
->data
;
134 *max_length
= buffer
->max_length
;
136 *current_length
= buffer
->current_length
;
141 static HRESULT WINAPI
memory_buffer_Unlock(IMFMediaBuffer
*iface
)
143 TRACE("%p.\n", iface
);
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
);
157 *current_length
= buffer
->current_length
;
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
)
171 buffer
->current_length
= current_length
;
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
);
185 *max_length
= buffer
->max_length
;
190 static const IMFMediaBufferVtbl memory_1d_buffer_vtbl
=
192 memory_buffer_QueryInterface
,
193 memory_buffer_AddRef
,
194 memory_buffer_Release
,
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
;
220 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
222 return E_NOINTERFACE
;
225 IUnknown_AddRef((IUnknown
*)*out
);
229 static const IMFMediaBufferVtbl memory_1d_2d_buffer_vtbl
=
231 memory_1d_2d_buffer_QueryInterface
,
232 memory_buffer_AddRef
,
233 memory_buffer_Release
,
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
);
266 static HRESULT WINAPI
memory_2d_buffer_Unlock2D(IMF2DBuffer2
*iface
)
268 FIXME("%p.\n", iface
);
273 static HRESULT WINAPI
memory_2d_buffer_GetScanline0AndPitch(IMF2DBuffer2
*iface
, BYTE
**scanline0
, LONG
*pitch
)
275 FIXME("%p, %p, %p.\n", iface
, scanline0
, pitch
);
280 static HRESULT WINAPI
memory_2d_buffer_IsContiguousFormat(IMF2DBuffer2
*iface
, BOOL
*is_contiguous
)
282 FIXME("%p, %p.\n", iface
, is_contiguous
);
287 static HRESULT WINAPI
memory_2d_buffer_GetContiguousLength(IMF2DBuffer2
*iface
, DWORD
*length
)
289 FIXME("%p, %p.\n", iface
, length
);
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
);
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
);
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
);
316 static HRESULT WINAPI
memory_2d_buffer_Copy2DTo(IMF2DBuffer2
*iface
, IMF2DBuffer2
*dest_buffer
)
318 FIXME("%p, %p.\n", iface
, dest_buffer
);
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
));
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;
354 static HRESULT
create_1d_buffer(DWORD max_length
, DWORD alignment
, IMFMediaBuffer
**buffer
)
356 struct memory_buffer
*object
;
364 object
= heap_alloc_zero(sizeof(*object
));
366 return E_OUTOFMEMORY
;
368 hr
= memory_buffer_init(object
, max_length
, alignment
, &memory_1d_buffer_vtbl
);
375 *buffer
= &object
->IMFMediaBuffer_iface
;
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
;
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
));
400 return E_OUTOFMEMORY
;
404 case MAKEFOURCC('N','V','1','2'):
405 max_length
= ALIGN_SIZE(width
* bpp
, 64) * height
* 3 / 2;
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
;
419 *buffer
= &object
->IMFMediaBuffer_iface
;
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
))
460 IMFSample_AddRef(iface
);
464 WARN("Unsupported %s.\n", debugstr_guid(riid
));
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
);
479 static ULONG WINAPI
sample_Release(IMFSample
*iface
)
481 struct sample
*sample
= impl_from_IMFSample(iface
);
482 ULONG refcount
= InterlockedDecrement(&sample
->attributes
.ref
);
485 TRACE("%p, refcount %u.\n", iface
, 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
);
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
,
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
);
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
);
796 static HRESULT WINAPI
sample_GetSampleTime(IMFSample
*iface
, LONGLONG
*timestamp
)
798 struct sample
*sample
= impl_from_IMFSample(iface
);
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
;
807 hr
= MF_E_NO_SAMPLE_TIMESTAMP
;
808 LeaveCriticalSection(&sample
->attributes
.cs
);
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
);
827 static HRESULT WINAPI
sample_GetSampleDuration(IMFSample
*iface
, LONGLONG
*duration
)
829 struct sample
*sample
= impl_from_IMFSample(iface
);
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
;
838 hr
= MF_E_NO_SAMPLE_DURATION
;
839 LeaveCriticalSection(&sample
->attributes
.cs
);
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
);
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
);
867 EnterCriticalSection(&sample
->attributes
.cs
);
868 *count
= sample
->buffer_count
;
869 LeaveCriticalSection(&sample
->attributes
.cs
);
874 static HRESULT WINAPI
sample_GetBufferByIndex(IMFSample
*iface
, DWORD index
, IMFMediaBuffer
**buffer
)
876 struct sample
*sample
= impl_from_IMFSample(iface
);
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
);
889 LeaveCriticalSection(&sample
->attributes
.cs
);
894 static HRESULT WINAPI
sample_ConvertToContiguousBuffer(IMFSample
*iface
, IMFMediaBuffer
**buffer
)
896 struct sample
*sample
= impl_from_IMFSample(iface
);
899 TRACE("%p, %p.\n", iface
, buffer
);
901 EnterCriticalSection(&sample
->attributes
.cs
);
903 if (sample
->buffer_count
== 0)
905 else if (sample
->buffer_count
== 1)
907 *buffer
= sample
->buffers
[0];
908 IMFMediaBuffer_AddRef(*buffer
);
912 FIXME("Samples with multiple buffers are not supported.\n");
916 LeaveCriticalSection(&sample
->attributes
.cs
);
921 static HRESULT WINAPI
sample_AddBuffer(IMFSample
*iface
, IMFMediaBuffer
*buffer
)
923 struct sample
*sample
= impl_from_IMFSample(iface
);
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
)))
934 sample
->buffers
[sample
->buffer_count
++] = buffer
;
935 IMFMediaBuffer_AddRef(buffer
);
937 LeaveCriticalSection(&sample
->attributes
.cs
);
942 static HRESULT WINAPI
sample_RemoveBufferByIndex(IMFSample
*iface
, DWORD index
)
944 struct sample
*sample
= impl_from_IMFSample(iface
);
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
--;
962 LeaveCriticalSection(&sample
->attributes
.cs
);
967 static HRESULT WINAPI
sample_RemoveAllBuffers(IMFSample
*iface
)
969 struct sample
*sample
= impl_from_IMFSample(iface
);
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
);
983 static DWORD
sample_get_total_length(struct sample
*sample
)
985 DWORD total_length
= 0, length
;
988 for (i
= 0; i
< sample
->buffer_count
; ++i
)
991 if (SUCCEEDED(IMFMediaBuffer_GetCurrentLength(sample
->buffers
[i
], &length
)))
992 total_length
+= 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
);
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
;
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;
1028 dst_length
= current_length
= 0;
1029 locked
= SUCCEEDED(hr
= IMFMediaBuffer_Lock(buffer
, &dst_ptr
, &dst_length
, ¤t_length
));
1032 if (dst_length
< total_length
)
1033 hr
= MF_E_BUFFERTOOSMALL
;
1036 for (i
= 0; i
< sample
->buffer_count
&& SUCCEEDED(hr
); ++i
)
1039 src_max_length
= current_length
= 0;
1040 if (SUCCEEDED(hr
= IMFMediaBuffer_Lock(sample
->buffers
[i
], &src_ptr
, &src_max_length
, ¤t_length
)))
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
);
1063 IMFMediaBuffer_Unlock(buffer
);
1065 LeaveCriticalSection(&sample
->attributes
.cs
);
1070 static const IMFSampleVtbl samplevtbl
=
1072 sample_QueryInterface
,
1083 sample_GetStringLength
,
1085 sample_GetAllocatedString
,
1088 sample_GetAllocatedBlob
,
1092 sample_DeleteAllItems
,
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
,
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
;
1129 TRACE("%p.\n", sample
);
1131 object
= heap_alloc_zero(sizeof(*object
));
1133 return E_OUTOFMEMORY
;
1135 if (FAILED(hr
= init_attributes_object(&object
->attributes
, 0)))
1141 object
->IMFSample_iface
.lpVtbl
= &samplevtbl
;
1143 *sample
= &object
->IMFSample_iface
;
1145 TRACE("Created sample %p.\n", *sample
);