2 * Copyright 2020 Nikolay Sivov
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
27 #include "wine/debug.h"
28 #include "wine/list.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(evr
);
32 static const char *debugstr_time(LONGLONG time
)
34 ULONGLONG abstime
= time
>= 0 ? time
: -time
;
35 unsigned int i
= 0, j
= 0;
36 char buffer
[23], rev
[23];
38 while (abstime
|| i
<= 8)
40 buffer
[i
++] = '0' + (abstime
% 10);
42 if (i
== 7) buffer
[i
++] = '.';
44 if (time
< 0) buffer
[i
++] = '-';
46 while (i
--) rev
[j
++] = buffer
[i
];
47 while (rev
[j
-1] == '0' && rev
[j
-2] != '.') --j
;
50 return wine_dbg_sprintf("%s", rev
);
55 IMFMediaBuffer IMFMediaBuffer_iface
;
56 IMFGetService IMFGetService_iface
;
63 enum sample_prop_flags
65 SAMPLE_PROP_HAS_DURATION
= 1 << 0,
66 SAMPLE_PROP_HAS_TIMESTAMP
= 1 << 1,
67 SAMPLE_PROP_HAS_DESIRED_PROPS
= 1 << 2,
72 IMFSample IMFSample_iface
;
73 IMFTrackedSample IMFTrackedSample_iface
;
74 IMFDesiredSample IMFDesiredSample_iface
;
79 IMFAsyncResult
*tracked_result
;
80 LONG tracked_refcount
;
84 LONGLONG desired_timestamp
;
85 LONGLONG desired_duration
;
90 static struct video_sample
*impl_from_IMFSample(IMFSample
*iface
)
92 return CONTAINING_RECORD(iface
, struct video_sample
, IMFSample_iface
);
95 static struct video_sample
*impl_from_IMFTrackedSample(IMFTrackedSample
*iface
)
97 return CONTAINING_RECORD(iface
, struct video_sample
, IMFTrackedSample_iface
);
100 static struct video_sample
*impl_from_IMFDesiredSample(IMFDesiredSample
*iface
)
102 return CONTAINING_RECORD(iface
, struct video_sample
, IMFDesiredSample_iface
);
105 static struct surface_buffer
*impl_from_IMFMediaBuffer(IMFMediaBuffer
*iface
)
107 return CONTAINING_RECORD(iface
, struct surface_buffer
, IMFMediaBuffer_iface
);
110 static struct surface_buffer
*impl_from_IMFGetService(IMFGetService
*iface
)
112 return CONTAINING_RECORD(iface
, struct surface_buffer
, IMFGetService_iface
);
115 struct tracked_async_result
117 MFASYNCRESULT result
;
123 static struct tracked_async_result
*impl_from_IMFAsyncResult(IMFAsyncResult
*iface
)
125 return CONTAINING_RECORD(iface
, struct tracked_async_result
, result
.AsyncResult
);
128 static HRESULT WINAPI
tracked_async_result_QueryInterface(IMFAsyncResult
*iface
, REFIID riid
, void **obj
)
130 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
132 if (IsEqualIID(riid
, &IID_IMFAsyncResult
) ||
133 IsEqualIID(riid
, &IID_IUnknown
))
136 IMFAsyncResult_AddRef(iface
);
141 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
142 return E_NOINTERFACE
;
145 static ULONG WINAPI
tracked_async_result_AddRef(IMFAsyncResult
*iface
)
147 struct tracked_async_result
*result
= impl_from_IMFAsyncResult(iface
);
148 ULONG refcount
= InterlockedIncrement(&result
->refcount
);
150 TRACE("%p, refcount %lu.\n", iface
, refcount
);
155 static ULONG WINAPI
tracked_async_result_Release(IMFAsyncResult
*iface
)
157 struct tracked_async_result
*result
= impl_from_IMFAsyncResult(iface
);
158 ULONG refcount
= InterlockedDecrement(&result
->refcount
);
160 TRACE("%p, refcount %lu.\n", iface
, refcount
);
164 if (result
->result
.pCallback
)
165 IMFAsyncCallback_Release(result
->result
.pCallback
);
167 IUnknown_Release(result
->object
);
169 IUnknown_Release(result
->state
);
176 static HRESULT WINAPI
tracked_async_result_GetState(IMFAsyncResult
*iface
, IUnknown
**state
)
178 struct tracked_async_result
*result
= impl_from_IMFAsyncResult(iface
);
180 TRACE("%p, %p.\n", iface
, state
);
185 *state
= result
->state
;
186 IUnknown_AddRef(*state
);
191 static HRESULT WINAPI
tracked_async_result_GetStatus(IMFAsyncResult
*iface
)
193 struct tracked_async_result
*result
= impl_from_IMFAsyncResult(iface
);
195 TRACE("%p.\n", iface
);
197 return result
->result
.hrStatusResult
;
200 static HRESULT WINAPI
tracked_async_result_SetStatus(IMFAsyncResult
*iface
, HRESULT status
)
202 struct tracked_async_result
*result
= impl_from_IMFAsyncResult(iface
);
204 TRACE("%p, %#lx.\n", iface
, status
);
206 result
->result
.hrStatusResult
= status
;
211 static HRESULT WINAPI
tracked_async_result_GetObject(IMFAsyncResult
*iface
, IUnknown
**object
)
213 struct tracked_async_result
*result
= impl_from_IMFAsyncResult(iface
);
215 TRACE("%p, %p.\n", iface
, object
);
220 *object
= result
->object
;
221 IUnknown_AddRef(*object
);
226 static IUnknown
* WINAPI
tracked_async_result_GetStateNoAddRef(IMFAsyncResult
*iface
)
228 struct tracked_async_result
*result
= impl_from_IMFAsyncResult(iface
);
230 TRACE("%p.\n", iface
);
232 return result
->state
;
235 static const IMFAsyncResultVtbl tracked_async_result_vtbl
=
237 tracked_async_result_QueryInterface
,
238 tracked_async_result_AddRef
,
239 tracked_async_result_Release
,
240 tracked_async_result_GetState
,
241 tracked_async_result_GetStatus
,
242 tracked_async_result_SetStatus
,
243 tracked_async_result_GetObject
,
244 tracked_async_result_GetStateNoAddRef
,
247 static HRESULT
create_async_result(IUnknown
*object
, IMFAsyncCallback
*callback
,
248 IUnknown
*state
, IMFAsyncResult
**out
)
250 struct tracked_async_result
*result
;
252 result
= calloc(1, sizeof(*result
));
254 return E_OUTOFMEMORY
;
256 result
->result
.AsyncResult
.lpVtbl
= &tracked_async_result_vtbl
;
257 result
->refcount
= 1;
258 result
->object
= object
;
260 IUnknown_AddRef(result
->object
);
261 result
->result
.pCallback
= callback
;
262 if (result
->result
.pCallback
)
263 IMFAsyncCallback_AddRef(result
->result
.pCallback
);
264 result
->state
= state
;
266 IUnknown_AddRef(result
->state
);
268 *out
= &result
->result
.AsyncResult
;
273 struct tracking_thread
279 static struct tracking_thread tracking_thread
;
281 static CRITICAL_SECTION tracking_thread_cs
= { NULL
, -1, 0, 0, 0, 0 };
283 enum tracking_thread_message
285 TRACKM_STOP
= WM_USER
,
286 TRACKM_INVOKE
= WM_USER
+ 1,
289 static DWORD CALLBACK
tracking_thread_proc(void *arg
)
291 HANDLE ready_event
= arg
;
292 BOOL stop_thread
= FALSE
;
293 IMFAsyncResult
*result
;
297 PeekMessageW(&msg
, NULL
, WM_USER
, WM_USER
, PM_NOREMOVE
);
299 SetEvent(ready_event
);
303 MsgWaitForMultipleObjects(0, NULL
, FALSE
, INFINITE
, QS_POSTMESSAGE
);
305 while (PeekMessageW(&msg
, NULL
, 0, 0, PM_REMOVE
))
310 result
= (IMFAsyncResult
*)msg
.lParam
;
311 data
= (MFASYNCRESULT
*)result
;
313 IMFAsyncCallback_Invoke(data
->pCallback
, result
);
314 IMFAsyncResult_Release(result
);
327 TRACE("Tracking thread exiting.\n");
332 static void video_sample_create_tracking_thread(void)
334 EnterCriticalSection(&tracking_thread_cs
);
336 if (++tracking_thread
.refcount
== 1)
340 ready_event
= CreateEventW(NULL
, FALSE
, FALSE
, NULL
);
342 if (!(tracking_thread
.hthread
= CreateThread(NULL
, 0, tracking_thread_proc
,
343 ready_event
, 0, &tracking_thread
.tid
)))
345 WARN("Failed to create sample tracking thread.\n");
346 CloseHandle(ready_event
);
347 LeaveCriticalSection(&tracking_thread_cs
);
351 WaitForSingleObject(ready_event
, INFINITE
);
352 CloseHandle(ready_event
);
354 TRACE("Create tracking thread %#lx.\n", tracking_thread
.tid
);
357 LeaveCriticalSection(&tracking_thread_cs
);
360 static void video_sample_stop_tracking_thread(void)
362 EnterCriticalSection(&tracking_thread_cs
);
364 if (!--tracking_thread
.refcount
)
366 PostThreadMessageW(tracking_thread
.tid
, TRACKM_STOP
, 0, 0);
367 CloseHandle(tracking_thread
.hthread
);
368 memset(&tracking_thread
, 0, sizeof(tracking_thread
));
371 LeaveCriticalSection(&tracking_thread_cs
);
374 static void video_sample_tracking_thread_invoke(IMFAsyncResult
*result
)
376 if (!tracking_thread
.tid
)
378 WARN("Sample tracking thread is not initialized.\n");
382 IMFAsyncResult_AddRef(result
);
383 PostThreadMessageW(tracking_thread
.tid
, TRACKM_INVOKE
, 0, (LPARAM
)result
);
386 struct sample_allocator
388 IMFVideoSampleAllocator IMFVideoSampleAllocator_iface
;
389 IMFVideoSampleAllocatorCallback IMFVideoSampleAllocatorCallback_iface
;
390 IMFAsyncCallback tracking_callback
;
393 IMFVideoSampleAllocatorNotify
*callback
;
394 IDirect3DDeviceManager9
*device_manager
;
395 unsigned int free_sample_count
;
396 struct list free_samples
;
397 struct list used_samples
;
407 static struct sample_allocator
*impl_from_IMFVideoSampleAllocator(IMFVideoSampleAllocator
*iface
)
409 return CONTAINING_RECORD(iface
, struct sample_allocator
, IMFVideoSampleAllocator_iface
);
412 static struct sample_allocator
*impl_from_IMFVideoSampleAllocatorCallback(IMFVideoSampleAllocatorCallback
*iface
)
414 return CONTAINING_RECORD(iface
, struct sample_allocator
, IMFVideoSampleAllocatorCallback_iface
);
417 static struct sample_allocator
*impl_from_IMFAsyncCallback(IMFAsyncCallback
*iface
)
419 return CONTAINING_RECORD(iface
, struct sample_allocator
, tracking_callback
);
422 static HRESULT WINAPI
sample_allocator_QueryInterface(IMFVideoSampleAllocator
*iface
, REFIID riid
, void **obj
)
424 struct sample_allocator
*allocator
= impl_from_IMFVideoSampleAllocator(iface
);
426 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
428 if (IsEqualIID(riid
, &IID_IMFVideoSampleAllocator
) ||
429 IsEqualIID(riid
, &IID_IUnknown
))
431 *obj
= &allocator
->IMFVideoSampleAllocator_iface
;
433 else if (IsEqualIID(riid
, &IID_IMFVideoSampleAllocatorCallback
))
435 *obj
= &allocator
->IMFVideoSampleAllocatorCallback_iface
;
439 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
441 return E_NOINTERFACE
;
444 IUnknown_AddRef((IUnknown
*)*obj
);
448 static ULONG WINAPI
sample_allocator_AddRef(IMFVideoSampleAllocator
*iface
)
450 struct sample_allocator
*allocator
= impl_from_IMFVideoSampleAllocator(iface
);
451 ULONG refcount
= InterlockedIncrement(&allocator
->refcount
);
453 TRACE("%p, refcount %lu.\n", iface
, refcount
);
458 static void sample_allocator_release_samples(struct sample_allocator
*allocator
)
460 struct queued_sample
*iter
, *iter2
;
462 LIST_FOR_EACH_ENTRY_SAFE(iter
, iter2
, &allocator
->free_samples
, struct queued_sample
, entry
)
464 list_remove(&iter
->entry
);
465 IMFSample_Release(iter
->sample
);
469 LIST_FOR_EACH_ENTRY_SAFE(iter
, iter2
, &allocator
->used_samples
, struct queued_sample
, entry
)
471 list_remove(&iter
->entry
);
476 static ULONG WINAPI
sample_allocator_Release(IMFVideoSampleAllocator
*iface
)
478 struct sample_allocator
*allocator
= impl_from_IMFVideoSampleAllocator(iface
);
479 ULONG refcount
= InterlockedDecrement(&allocator
->refcount
);
481 TRACE("%p, refcount %lu.\n", iface
, refcount
);
485 if (allocator
->callback
)
486 IMFVideoSampleAllocatorNotify_Release(allocator
->callback
);
487 if (allocator
->device_manager
)
488 IDirect3DDeviceManager9_Release(allocator
->device_manager
);
489 sample_allocator_release_samples(allocator
);
490 DeleteCriticalSection(&allocator
->cs
);
497 static HRESULT WINAPI
sample_allocator_SetDirectXManager(IMFVideoSampleAllocator
*iface
,
500 struct sample_allocator
*allocator
= impl_from_IMFVideoSampleAllocator(iface
);
501 IDirect3DDeviceManager9
*device_manager
= NULL
;
504 TRACE("%p, %p.\n", iface
, manager
);
506 if (manager
&& FAILED(hr
= IUnknown_QueryInterface(manager
, &IID_IDirect3DDeviceManager9
,
507 (void **)&device_manager
)))
512 EnterCriticalSection(&allocator
->cs
);
514 if (allocator
->device_manager
)
515 IDirect3DDeviceManager9_Release(allocator
->device_manager
);
516 allocator
->device_manager
= device_manager
;
518 LeaveCriticalSection(&allocator
->cs
);
523 static HRESULT WINAPI
sample_allocator_UninitializeSampleAllocator(IMFVideoSampleAllocator
*iface
)
525 struct sample_allocator
*allocator
= impl_from_IMFVideoSampleAllocator(iface
);
527 TRACE("%p.\n", iface
);
529 EnterCriticalSection(&allocator
->cs
);
531 sample_allocator_release_samples(allocator
);
532 allocator
->free_sample_count
= 0;
534 LeaveCriticalSection(&allocator
->cs
);
539 static HRESULT
sample_allocator_create_samples(struct sample_allocator
*allocator
, unsigned int sample_count
,
540 IMFMediaType
*media_type
)
542 IDirectXVideoProcessorService
*service
= NULL
;
543 unsigned int i
, width
, height
;
544 IDirect3DSurface9
*surface
;
545 HANDLE hdevice
= NULL
;
552 if (FAILED(IMFMediaType_GetMajorType(media_type
, &major
)))
553 return MF_E_INVALIDMEDIATYPE
;
555 if (!IsEqualGUID(&major
, &MFMediaType_Video
))
556 return MF_E_INVALIDMEDIATYPE
;
558 if (FAILED(IMFMediaType_GetUINT64(media_type
, &MF_MT_FRAME_SIZE
, &frame_size
)))
559 return MF_E_INVALIDMEDIATYPE
;
561 if (FAILED(IMFMediaType_GetGUID(media_type
, &MF_MT_SUBTYPE
, &subtype
)))
562 return MF_E_INVALIDMEDIATYPE
;
564 format
= subtype
.Data1
;
566 width
= frame_size
>> 32;
568 if (allocator
->device_manager
)
570 if (SUCCEEDED(hr
= IDirect3DDeviceManager9_OpenDeviceHandle(allocator
->device_manager
, &hdevice
)))
572 hr
= IDirect3DDeviceManager9_GetVideoService(allocator
->device_manager
, hdevice
,
573 &IID_IDirectXVideoProcessorService
, (void **)&service
);
578 WARN("Failed to get processor service, %#lx.\n", hr
);
583 sample_allocator_release_samples(allocator
);
585 for (i
= 0; i
< sample_count
; ++i
)
587 struct queued_sample
*queued_sample
;
588 IMFMediaBuffer
*buffer
;
590 if (SUCCEEDED(hr
= MFCreateVideoSampleFromSurface(NULL
, &sample
)))
594 if (SUCCEEDED(hr
= IDirectXVideoProcessorService_CreateSurface(service
, width
, height
,
595 0, format
, D3DPOOL_DEFAULT
, 0, DXVA2_VideoProcessorRenderTarget
, &surface
, NULL
)))
597 hr
= MFCreateDXSurfaceBuffer(&IID_IDirect3DSurface9
, (IUnknown
*)surface
, FALSE
, &buffer
);
598 IDirect3DSurface9_Release(surface
);
603 hr
= MFCreate2DMediaBuffer(width
, height
, format
, FALSE
, &buffer
);
608 hr
= IMFSample_AddBuffer(sample
, buffer
);
609 IMFMediaBuffer_Release(buffer
);
615 WARN("Unable to allocate %u samples.\n", sample_count
);
616 sample_allocator_release_samples(allocator
);
620 queued_sample
= malloc(sizeof(*queued_sample
));
621 queued_sample
->sample
= sample
;
622 list_add_tail(&allocator
->free_samples
, &queued_sample
->entry
);
623 allocator
->free_sample_count
++;
627 IDirectXVideoProcessorService_Release(service
);
629 if (allocator
->device_manager
)
630 IDirect3DDeviceManager9_CloseDeviceHandle(allocator
->device_manager
, hdevice
);
635 static HRESULT WINAPI
sample_allocator_InitializeSampleAllocator(IMFVideoSampleAllocator
*iface
,
636 DWORD sample_count
, IMFMediaType
*media_type
)
638 struct sample_allocator
*allocator
= impl_from_IMFVideoSampleAllocator(iface
);
641 TRACE("%p, %lu, %p.\n", iface
, sample_count
, media_type
);
646 EnterCriticalSection(&allocator
->cs
);
648 hr
= sample_allocator_create_samples(allocator
, sample_count
, media_type
);
650 LeaveCriticalSection(&allocator
->cs
);
655 static HRESULT WINAPI
sample_allocator_AllocateSample(IMFVideoSampleAllocator
*iface
, IMFSample
**out
)
657 struct sample_allocator
*allocator
= impl_from_IMFVideoSampleAllocator(iface
);
658 IMFTrackedSample
*tracked_sample
;
662 TRACE("%p, %p.\n", iface
, out
);
664 EnterCriticalSection(&allocator
->cs
);
666 if (list_empty(&allocator
->free_samples
) && list_empty(&allocator
->used_samples
))
667 hr
= MF_E_NOT_INITIALIZED
;
668 else if (list_empty(&allocator
->free_samples
))
669 hr
= MF_E_SAMPLEALLOCATOR_EMPTY
;
672 struct list
*head
= list_head(&allocator
->free_samples
);
674 sample
= LIST_ENTRY(head
, struct queued_sample
, entry
)->sample
;
676 if (SUCCEEDED(hr
= IMFSample_QueryInterface(sample
, &IID_IMFTrackedSample
, (void **)&tracked_sample
)))
678 hr
= IMFTrackedSample_SetAllocator(tracked_sample
, &allocator
->tracking_callback
, NULL
);
679 IMFTrackedSample_Release(tracked_sample
);
685 list_add_tail(&allocator
->used_samples
, head
);
686 allocator
->free_sample_count
--;
688 /* Reference counter is not increased when sample is returned, so next release could trigger
689 tracking condition. This is balanced by incremented reference counter when sample is returned
690 back to the free list. */
695 LeaveCriticalSection(&allocator
->cs
);
700 static const IMFVideoSampleAllocatorVtbl sample_allocator_vtbl
=
702 sample_allocator_QueryInterface
,
703 sample_allocator_AddRef
,
704 sample_allocator_Release
,
705 sample_allocator_SetDirectXManager
,
706 sample_allocator_UninitializeSampleAllocator
,
707 sample_allocator_InitializeSampleAllocator
,
708 sample_allocator_AllocateSample
,
711 static HRESULT WINAPI
sample_allocator_callback_QueryInterface(IMFVideoSampleAllocatorCallback
*iface
,
712 REFIID riid
, void **obj
)
714 struct sample_allocator
*allocator
= impl_from_IMFVideoSampleAllocatorCallback(iface
);
715 return IMFVideoSampleAllocator_QueryInterface(&allocator
->IMFVideoSampleAllocator_iface
, riid
, obj
);
718 static ULONG WINAPI
sample_allocator_callback_AddRef(IMFVideoSampleAllocatorCallback
*iface
)
720 struct sample_allocator
*allocator
= impl_from_IMFVideoSampleAllocatorCallback(iface
);
721 return IMFVideoSampleAllocator_AddRef(&allocator
->IMFVideoSampleAllocator_iface
);
724 static ULONG WINAPI
sample_allocator_callback_Release(IMFVideoSampleAllocatorCallback
*iface
)
726 struct sample_allocator
*allocator
= impl_from_IMFVideoSampleAllocatorCallback(iface
);
727 return IMFVideoSampleAllocator_Release(&allocator
->IMFVideoSampleAllocator_iface
);
730 static HRESULT WINAPI
sample_allocator_callback_SetCallback(IMFVideoSampleAllocatorCallback
*iface
,
731 IMFVideoSampleAllocatorNotify
*callback
)
733 struct sample_allocator
*allocator
= impl_from_IMFVideoSampleAllocatorCallback(iface
);
735 TRACE("%p, %p.\n", iface
, callback
);
737 EnterCriticalSection(&allocator
->cs
);
738 if (allocator
->callback
)
739 IMFVideoSampleAllocatorNotify_Release(allocator
->callback
);
740 allocator
->callback
= callback
;
741 if (allocator
->callback
)
742 IMFVideoSampleAllocatorNotify_AddRef(allocator
->callback
);
743 LeaveCriticalSection(&allocator
->cs
);
748 static HRESULT WINAPI
sample_allocator_callback_GetFreeSampleCount(IMFVideoSampleAllocatorCallback
*iface
,
751 struct sample_allocator
*allocator
= impl_from_IMFVideoSampleAllocatorCallback(iface
);
753 TRACE("%p, %p.\n", iface
, count
);
755 EnterCriticalSection(&allocator
->cs
);
757 *count
= allocator
->free_sample_count
;
758 LeaveCriticalSection(&allocator
->cs
);
763 static const IMFVideoSampleAllocatorCallbackVtbl sample_allocator_callback_vtbl
=
765 sample_allocator_callback_QueryInterface
,
766 sample_allocator_callback_AddRef
,
767 sample_allocator_callback_Release
,
768 sample_allocator_callback_SetCallback
,
769 sample_allocator_callback_GetFreeSampleCount
,
772 static HRESULT WINAPI
sample_allocator_tracking_callback_QueryInterface(IMFAsyncCallback
*iface
,
773 REFIID riid
, void **obj
)
775 if (IsEqualIID(riid
, &IID_IMFAsyncCallback
) ||
776 IsEqualIID(riid
, &IID_IUnknown
))
779 IMFAsyncCallback_AddRef(iface
);
783 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
785 return E_NOINTERFACE
;
788 static ULONG WINAPI
sample_allocator_tracking_callback_AddRef(IMFAsyncCallback
*iface
)
790 struct sample_allocator
*allocator
= impl_from_IMFAsyncCallback(iface
);
791 return IMFVideoSampleAllocator_AddRef(&allocator
->IMFVideoSampleAllocator_iface
);
794 static ULONG WINAPI
sample_allocator_tracking_callback_Release(IMFAsyncCallback
*iface
)
796 struct sample_allocator
*allocator
= impl_from_IMFAsyncCallback(iface
);
797 return IMFVideoSampleAllocator_Release(&allocator
->IMFVideoSampleAllocator_iface
);
800 static HRESULT WINAPI
sample_allocator_tracking_callback_GetParameters(IMFAsyncCallback
*iface
,
801 DWORD
*flags
, DWORD
*queue
)
806 static HRESULT WINAPI
sample_allocator_tracking_callback_Invoke(IMFAsyncCallback
*iface
, IMFAsyncResult
*result
)
808 struct sample_allocator
*allocator
= impl_from_IMFAsyncCallback(iface
);
809 struct queued_sample
*iter
;
810 IUnknown
*object
= NULL
;
811 IMFSample
*sample
= NULL
;
814 if (FAILED(IMFAsyncResult_GetObject(result
, &object
)))
817 hr
= IUnknown_QueryInterface(object
, &IID_IMFSample
, (void **)&sample
);
818 IUnknown_Release(object
);
822 EnterCriticalSection(&allocator
->cs
);
824 LIST_FOR_EACH_ENTRY(iter
, &allocator
->used_samples
, struct queued_sample
, entry
)
826 if (sample
== iter
->sample
)
828 list_remove(&iter
->entry
);
829 list_add_tail(&allocator
->free_samples
, &iter
->entry
);
830 IMFSample_AddRef(iter
->sample
);
831 allocator
->free_sample_count
++;
836 IMFSample_Release(sample
);
838 if (allocator
->callback
)
839 IMFVideoSampleAllocatorNotify_NotifyRelease(allocator
->callback
);
841 LeaveCriticalSection(&allocator
->cs
);
846 static const IMFAsyncCallbackVtbl sample_allocator_tracking_callback_vtbl
=
848 sample_allocator_tracking_callback_QueryInterface
,
849 sample_allocator_tracking_callback_AddRef
,
850 sample_allocator_tracking_callback_Release
,
851 sample_allocator_tracking_callback_GetParameters
,
852 sample_allocator_tracking_callback_Invoke
,
855 HRESULT WINAPI
MFCreateVideoSampleAllocator(REFIID riid
, void **obj
)
857 struct sample_allocator
*object
;
860 TRACE("%s, %p.\n", debugstr_guid(riid
), obj
);
862 if (!(object
= calloc(1, sizeof(*object
))))
863 return E_OUTOFMEMORY
;
865 object
->IMFVideoSampleAllocator_iface
.lpVtbl
= &sample_allocator_vtbl
;
866 object
->IMFVideoSampleAllocatorCallback_iface
.lpVtbl
= &sample_allocator_callback_vtbl
;
867 object
->tracking_callback
.lpVtbl
= &sample_allocator_tracking_callback_vtbl
;
868 object
->refcount
= 1;
869 list_init(&object
->used_samples
);
870 list_init(&object
->free_samples
);
871 InitializeCriticalSection(&object
->cs
);
873 hr
= IMFVideoSampleAllocator_QueryInterface(&object
->IMFVideoSampleAllocator_iface
, riid
, obj
);
874 IMFVideoSampleAllocator_Release(&object
->IMFVideoSampleAllocator_iface
);
879 static HRESULT WINAPI
video_sample_QueryInterface(IMFSample
*iface
, REFIID riid
, void **out
)
881 struct video_sample
*sample
= impl_from_IMFSample(iface
);
883 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), out
);
885 if (IsEqualIID(riid
, &IID_IMFSample
) ||
886 IsEqualIID(riid
, &IID_IMFAttributes
) ||
887 IsEqualIID(riid
, &IID_IUnknown
))
889 *out
= &sample
->IMFSample_iface
;
891 else if (IsEqualIID(riid
, &IID_IMFTrackedSample
))
893 *out
= &sample
->IMFTrackedSample_iface
;
895 else if (IsEqualIID(riid
, &IID_IMFDesiredSample
))
897 *out
= &sample
->IMFDesiredSample_iface
;
901 WARN("Unsupported %s.\n", debugstr_guid(riid
));
903 return E_NOINTERFACE
;
906 IUnknown_AddRef((IUnknown
*)*out
);
910 static ULONG WINAPI
video_sample_AddRef(IMFSample
*iface
)
912 struct video_sample
*sample
= impl_from_IMFSample(iface
);
913 ULONG refcount
= InterlockedIncrement(&sample
->refcount
);
915 TRACE("%p, refcount %lu.\n", iface
, refcount
);
920 static ULONG WINAPI
video_sample_Release(IMFSample
*iface
)
922 struct video_sample
*sample
= impl_from_IMFSample(iface
);
923 ULONG refcount
= InterlockedDecrement(&sample
->refcount
);
924 IMFAsyncResult
*tracked_result
= NULL
;
926 EnterCriticalSection(&sample
->cs
);
927 if (sample
->tracked_result
&& sample
->tracked_refcount
== refcount
)
929 tracked_result
= sample
->tracked_result
;
930 video_sample_tracking_thread_invoke(tracked_result
);
931 sample
->tracked_result
= NULL
;
932 sample
->tracked_refcount
= 0;
934 LeaveCriticalSection(&sample
->cs
);
937 IMFAsyncResult_Release(tracked_result
);
939 TRACE("%p, refcount %lu.\n", iface
, refcount
);
943 video_sample_stop_tracking_thread();
945 IMFSample_Release(sample
->sample
);
946 DeleteCriticalSection(&sample
->cs
);
953 static HRESULT WINAPI
video_sample_GetItem(IMFSample
*iface
, REFGUID key
, PROPVARIANT
*value
)
955 struct video_sample
*sample
= impl_from_IMFSample(iface
);
957 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
959 return IMFSample_GetItem(sample
->sample
, key
, value
);
962 static HRESULT WINAPI
video_sample_GetItemType(IMFSample
*iface
, REFGUID key
, MF_ATTRIBUTE_TYPE
*type
)
964 struct video_sample
*sample
= impl_from_IMFSample(iface
);
966 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), type
);
968 return IMFSample_GetItemType(sample
->sample
, key
, type
);
971 static HRESULT WINAPI
video_sample_CompareItem(IMFSample
*iface
, REFGUID key
, REFPROPVARIANT value
, BOOL
*result
)
973 struct video_sample
*sample
= impl_from_IMFSample(iface
);
975 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), value
, result
);
977 return IMFSample_CompareItem(sample
->sample
, key
, value
, result
);
980 static HRESULT WINAPI
video_sample_Compare(IMFSample
*iface
, IMFAttributes
*theirs
, MF_ATTRIBUTES_MATCH_TYPE type
,
983 struct video_sample
*sample
= impl_from_IMFSample(iface
);
985 TRACE("%p, %p, %d, %p.\n", iface
, theirs
, type
, result
);
987 return IMFSample_Compare(sample
->sample
, theirs
, type
, result
);
990 static HRESULT WINAPI
video_sample_GetUINT32(IMFSample
*iface
, REFGUID key
, UINT32
*value
)
992 struct video_sample
*sample
= impl_from_IMFSample(iface
);
994 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
996 return IMFSample_GetUINT32(sample
->sample
, key
, value
);
999 static HRESULT WINAPI
video_sample_GetUINT64(IMFSample
*iface
, REFGUID key
, UINT64
*value
)
1001 struct video_sample
*sample
= impl_from_IMFSample(iface
);
1003 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
1005 return IMFSample_GetUINT64(sample
->sample
, key
, value
);
1008 static HRESULT WINAPI
video_sample_GetDouble(IMFSample
*iface
, REFGUID key
, double *value
)
1010 struct video_sample
*sample
= impl_from_IMFSample(iface
);
1012 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
1014 return IMFSample_GetDouble(sample
->sample
, key
, value
);
1017 static HRESULT WINAPI
video_sample_GetGUID(IMFSample
*iface
, REFGUID key
, GUID
*value
)
1019 struct video_sample
*sample
= impl_from_IMFSample(iface
);
1021 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
1023 return IMFSample_GetGUID(sample
->sample
, key
, value
);
1026 static HRESULT WINAPI
video_sample_GetStringLength(IMFSample
*iface
, REFGUID key
, UINT32
*length
)
1028 struct video_sample
*sample
= impl_from_IMFSample(iface
);
1030 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), length
);
1032 return IMFSample_GetStringLength(sample
->sample
, key
, length
);
1035 static HRESULT WINAPI
video_sample_GetString(IMFSample
*iface
, REFGUID key
, WCHAR
*value
, UINT32 size
, UINT32
*length
)
1037 struct video_sample
*sample
= impl_from_IMFSample(iface
);
1039 TRACE("%p, %s, %p, %u, %p.\n", iface
, debugstr_guid(key
), value
, size
, length
);
1041 return IMFSample_GetString(sample
->sample
, key
, value
, size
, length
);
1044 static HRESULT WINAPI
video_sample_GetAllocatedString(IMFSample
*iface
, REFGUID key
, WCHAR
**value
, UINT32
*length
)
1046 struct video_sample
*sample
= impl_from_IMFSample(iface
);
1048 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), value
, length
);
1050 return IMFSample_GetAllocatedString(sample
->sample
, key
, value
, length
);
1053 static HRESULT WINAPI
video_sample_GetBlobSize(IMFSample
*iface
, REFGUID key
, UINT32
*size
)
1055 struct video_sample
*sample
= impl_from_IMFSample(iface
);
1057 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), size
);
1059 return IMFSample_GetBlobSize(sample
->sample
, key
, size
);
1062 static HRESULT WINAPI
video_sample_GetBlob(IMFSample
*iface
, REFGUID key
, UINT8
*buf
, UINT32 bufsize
, UINT32
*blobsize
)
1064 struct video_sample
*sample
= impl_from_IMFSample(iface
);
1066 TRACE("%p, %s, %p, %u, %p.\n", iface
, debugstr_guid(key
), buf
, bufsize
, blobsize
);
1068 return IMFSample_GetBlob(sample
->sample
, key
, buf
, bufsize
, blobsize
);
1071 static HRESULT WINAPI
video_sample_GetAllocatedBlob(IMFSample
*iface
, REFGUID key
, UINT8
**buf
, UINT32
*size
)
1073 struct video_sample
*sample
= impl_from_IMFSample(iface
);
1075 TRACE("%p, %s, %p, %p.\n", iface
, debugstr_guid(key
), buf
, size
);
1077 return IMFSample_GetAllocatedBlob(sample
->sample
, key
, buf
, size
);
1080 static HRESULT WINAPI
video_sample_GetUnknown(IMFSample
*iface
, REFGUID key
, REFIID riid
, void **out
)
1082 struct video_sample
*sample
= impl_from_IMFSample(iface
);
1084 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(key
), debugstr_guid(riid
), out
);
1086 return IMFSample_GetUnknown(sample
->sample
, key
, riid
, out
);
1089 static HRESULT WINAPI
video_sample_SetItem(IMFSample
*iface
, REFGUID key
, REFPROPVARIANT value
)
1091 struct video_sample
*sample
= impl_from_IMFSample(iface
);
1093 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), value
);
1095 return IMFSample_SetItem(sample
->sample
, key
, value
);
1098 static HRESULT WINAPI
video_sample_DeleteItem(IMFSample
*iface
, REFGUID key
)
1100 struct video_sample
*sample
= impl_from_IMFSample(iface
);
1102 TRACE("%p, %s.\n", iface
, debugstr_guid(key
));
1104 return IMFSample_DeleteItem(sample
->sample
, key
);
1107 static HRESULT WINAPI
video_sample_DeleteAllItems(IMFSample
*iface
)
1109 struct video_sample
*sample
= impl_from_IMFSample(iface
);
1111 TRACE("%p.\n", iface
);
1113 return IMFSample_DeleteAllItems(sample
->sample
);
1116 static HRESULT WINAPI
video_sample_SetUINT32(IMFSample
*iface
, REFGUID key
, UINT32 value
)
1118 struct video_sample
*sample
= impl_from_IMFSample(iface
);
1120 TRACE("%p, %s, %u.\n", iface
, debugstr_guid(key
), value
);
1122 return IMFSample_SetUINT32(sample
->sample
, key
, value
);
1125 static HRESULT WINAPI
video_sample_SetUINT64(IMFSample
*iface
, REFGUID key
, UINT64 value
)
1127 struct video_sample
*sample
= impl_from_IMFSample(iface
);
1129 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), wine_dbgstr_longlong(value
));
1131 return IMFSample_SetUINT64(sample
->sample
, key
, value
);
1134 static HRESULT WINAPI
video_sample_SetDouble(IMFSample
*iface
, REFGUID key
, double value
)
1136 struct video_sample
*sample
= impl_from_IMFSample(iface
);
1138 TRACE("%p, %s, %f.\n", iface
, debugstr_guid(key
), value
);
1140 return IMFSample_SetDouble(sample
->sample
, key
, value
);
1143 static HRESULT WINAPI
video_sample_SetGUID(IMFSample
*iface
, REFGUID key
, REFGUID value
)
1145 struct video_sample
*sample
= impl_from_IMFSample(iface
);
1147 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), debugstr_guid(value
));
1149 return IMFSample_SetGUID(sample
->sample
, key
, value
);
1152 static HRESULT WINAPI
video_sample_SetString(IMFSample
*iface
, REFGUID key
, const WCHAR
*value
)
1154 struct video_sample
*sample
= impl_from_IMFSample(iface
);
1156 TRACE("%p, %s, %s.\n", iface
, debugstr_guid(key
), debugstr_w(value
));
1158 return IMFSample_SetString(sample
->sample
, key
, value
);
1161 static HRESULT WINAPI
video_sample_SetBlob(IMFSample
*iface
, REFGUID key
, const UINT8
*buf
, UINT32 size
)
1163 struct video_sample
*sample
= impl_from_IMFSample(iface
);
1165 TRACE("%p, %s, %p, %u.\n", iface
, debugstr_guid(key
), buf
, size
);
1167 return IMFSample_SetBlob(sample
->sample
, key
, buf
, size
);
1170 static HRESULT WINAPI
video_sample_SetUnknown(IMFSample
*iface
, REFGUID key
, IUnknown
*unknown
)
1172 struct video_sample
*sample
= impl_from_IMFSample(iface
);
1174 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(key
), unknown
);
1176 return IMFSample_SetUnknown(sample
->sample
, key
, unknown
);
1179 static HRESULT WINAPI
video_sample_LockStore(IMFSample
*iface
)
1181 struct video_sample
*sample
= impl_from_IMFSample(iface
);
1183 TRACE("%p.\n", iface
);
1185 return IMFSample_LockStore(sample
->sample
);
1188 static HRESULT WINAPI
video_sample_UnlockStore(IMFSample
*iface
)
1190 struct video_sample
*sample
= impl_from_IMFSample(iface
);
1192 TRACE("%p.\n", iface
);
1194 return IMFSample_UnlockStore(sample
->sample
);
1197 static HRESULT WINAPI
video_sample_GetCount(IMFSample
*iface
, UINT32
*count
)
1199 struct video_sample
*sample
= impl_from_IMFSample(iface
);
1201 TRACE("%p, %p.\n", iface
, count
);
1203 return IMFSample_GetCount(sample
->sample
, count
);
1206 static HRESULT WINAPI
video_sample_GetItemByIndex(IMFSample
*iface
, UINT32 index
, GUID
*key
, PROPVARIANT
*value
)
1208 struct video_sample
*sample
= impl_from_IMFSample(iface
);
1210 TRACE("%p, %u, %p, %p.\n", iface
, index
, key
, value
);
1212 return IMFSample_GetItemByIndex(sample
->sample
, index
, key
, value
);
1215 static HRESULT WINAPI
video_sample_CopyAllItems(IMFSample
*iface
, IMFAttributes
*dest
)
1217 struct video_sample
*sample
= impl_from_IMFSample(iface
);
1219 TRACE("%p, %p.\n", iface
, dest
);
1221 return IMFSample_CopyAllItems(sample
->sample
, dest
);
1224 static HRESULT WINAPI
video_sample_GetSampleFlags(IMFSample
*iface
, DWORD
*flags
)
1226 struct video_sample
*sample
= impl_from_IMFSample(iface
);
1228 TRACE("%p, %p.\n", iface
, flags
);
1230 return IMFSample_GetSampleFlags(sample
->sample
, flags
);
1233 static HRESULT WINAPI
video_sample_SetSampleFlags(IMFSample
*iface
, DWORD flags
)
1235 struct video_sample
*sample
= impl_from_IMFSample(iface
);
1237 TRACE("%p, %#lx.\n", iface
, flags
);
1239 return IMFSample_SetSampleFlags(sample
->sample
, flags
);
1242 static HRESULT WINAPI
video_sample_GetSampleTime(IMFSample
*iface
, LONGLONG
*timestamp
)
1244 struct video_sample
*sample
= impl_from_IMFSample(iface
);
1247 TRACE("%p, %p.\n", iface
, timestamp
);
1249 EnterCriticalSection(&sample
->cs
);
1250 if (sample
->flags
& SAMPLE_PROP_HAS_TIMESTAMP
)
1251 *timestamp
= sample
->timestamp
;
1253 hr
= MF_E_NO_SAMPLE_TIMESTAMP
;
1254 LeaveCriticalSection(&sample
->cs
);
1259 static HRESULT WINAPI
video_sample_SetSampleTime(IMFSample
*iface
, LONGLONG timestamp
)
1261 struct video_sample
*sample
= impl_from_IMFSample(iface
);
1263 TRACE("%p, %s.\n", iface
, debugstr_time(timestamp
));
1265 EnterCriticalSection(&sample
->cs
);
1266 sample
->timestamp
= timestamp
;
1267 sample
->flags
|= SAMPLE_PROP_HAS_TIMESTAMP
;
1268 LeaveCriticalSection(&sample
->cs
);
1273 static HRESULT WINAPI
video_sample_GetSampleDuration(IMFSample
*iface
, LONGLONG
*duration
)
1275 struct video_sample
*sample
= impl_from_IMFSample(iface
);
1278 TRACE("%p, %p.\n", iface
, duration
);
1280 EnterCriticalSection(&sample
->cs
);
1281 if (sample
->flags
& SAMPLE_PROP_HAS_DURATION
)
1282 *duration
= sample
->duration
;
1284 hr
= MF_E_NO_SAMPLE_DURATION
;
1285 LeaveCriticalSection(&sample
->cs
);
1290 static HRESULT WINAPI
video_sample_SetSampleDuration(IMFSample
*iface
, LONGLONG duration
)
1292 struct video_sample
*sample
= impl_from_IMFSample(iface
);
1294 TRACE("%p, %s.\n", iface
, debugstr_time(duration
));
1296 EnterCriticalSection(&sample
->cs
);
1297 sample
->duration
= duration
;
1298 sample
->flags
|= SAMPLE_PROP_HAS_DURATION
;
1299 LeaveCriticalSection(&sample
->cs
);
1304 static HRESULT WINAPI
video_sample_GetBufferCount(IMFSample
*iface
, DWORD
*count
)
1306 struct video_sample
*sample
= impl_from_IMFSample(iface
);
1308 TRACE("%p, %p.\n", iface
, count
);
1310 return IMFSample_GetBufferCount(sample
->sample
, count
);
1313 static HRESULT WINAPI
video_sample_GetBufferByIndex(IMFSample
*iface
, DWORD index
, IMFMediaBuffer
**buffer
)
1315 struct video_sample
*sample
= impl_from_IMFSample(iface
);
1317 TRACE("%p, %lu, %p.\n", iface
, index
, buffer
);
1319 return IMFSample_GetBufferByIndex(sample
->sample
, index
, buffer
);
1322 static HRESULT WINAPI
video_sample_ConvertToContiguousBuffer(IMFSample
*iface
, IMFMediaBuffer
**buffer
)
1324 TRACE("%p, %p.\n", iface
, buffer
);
1329 static HRESULT WINAPI
video_sample_AddBuffer(IMFSample
*iface
, IMFMediaBuffer
*buffer
)
1331 struct video_sample
*sample
= impl_from_IMFSample(iface
);
1333 TRACE("%p, %p.\n", iface
, buffer
);
1335 return IMFSample_AddBuffer(sample
->sample
, buffer
);
1338 static HRESULT WINAPI
video_sample_RemoveBufferByIndex(IMFSample
*iface
, DWORD index
)
1340 struct video_sample
*sample
= impl_from_IMFSample(iface
);
1342 TRACE("%p, %lu.\n", iface
, index
);
1344 return IMFSample_RemoveBufferByIndex(sample
->sample
, index
);
1347 static HRESULT WINAPI
video_sample_RemoveAllBuffers(IMFSample
*iface
)
1349 struct video_sample
*sample
= impl_from_IMFSample(iface
);
1351 TRACE("%p.\n", iface
);
1353 return IMFSample_RemoveAllBuffers(sample
->sample
);
1356 static HRESULT WINAPI
video_sample_GetTotalLength(IMFSample
*iface
, DWORD
*total_length
)
1358 TRACE("%p, %p.\n", iface
, total_length
);
1365 static HRESULT WINAPI
video_sample_CopyToBuffer(IMFSample
*iface
, IMFMediaBuffer
*buffer
)
1367 TRACE("%p, %p.\n", iface
, buffer
);
1372 static const IMFSampleVtbl video_sample_vtbl
=
1374 video_sample_QueryInterface
,
1375 video_sample_AddRef
,
1376 video_sample_Release
,
1377 video_sample_GetItem
,
1378 video_sample_GetItemType
,
1379 video_sample_CompareItem
,
1380 video_sample_Compare
,
1381 video_sample_GetUINT32
,
1382 video_sample_GetUINT64
,
1383 video_sample_GetDouble
,
1384 video_sample_GetGUID
,
1385 video_sample_GetStringLength
,
1386 video_sample_GetString
,
1387 video_sample_GetAllocatedString
,
1388 video_sample_GetBlobSize
,
1389 video_sample_GetBlob
,
1390 video_sample_GetAllocatedBlob
,
1391 video_sample_GetUnknown
,
1392 video_sample_SetItem
,
1393 video_sample_DeleteItem
,
1394 video_sample_DeleteAllItems
,
1395 video_sample_SetUINT32
,
1396 video_sample_SetUINT64
,
1397 video_sample_SetDouble
,
1398 video_sample_SetGUID
,
1399 video_sample_SetString
,
1400 video_sample_SetBlob
,
1401 video_sample_SetUnknown
,
1402 video_sample_LockStore
,
1403 video_sample_UnlockStore
,
1404 video_sample_GetCount
,
1405 video_sample_GetItemByIndex
,
1406 video_sample_CopyAllItems
,
1407 video_sample_GetSampleFlags
,
1408 video_sample_SetSampleFlags
,
1409 video_sample_GetSampleTime
,
1410 video_sample_SetSampleTime
,
1411 video_sample_GetSampleDuration
,
1412 video_sample_SetSampleDuration
,
1413 video_sample_GetBufferCount
,
1414 video_sample_GetBufferByIndex
,
1415 video_sample_ConvertToContiguousBuffer
,
1416 video_sample_AddBuffer
,
1417 video_sample_RemoveBufferByIndex
,
1418 video_sample_RemoveAllBuffers
,
1419 video_sample_GetTotalLength
,
1420 video_sample_CopyToBuffer
,
1423 static HRESULT WINAPI
tracked_video_sample_QueryInterface(IMFTrackedSample
*iface
, REFIID riid
, void **obj
)
1425 struct video_sample
*sample
= impl_from_IMFTrackedSample(iface
);
1426 return IMFSample_QueryInterface(&sample
->IMFSample_iface
, riid
, obj
);
1429 static ULONG WINAPI
tracked_video_sample_AddRef(IMFTrackedSample
*iface
)
1431 struct video_sample
*sample
= impl_from_IMFTrackedSample(iface
);
1432 return IMFSample_AddRef(&sample
->IMFSample_iface
);
1435 static ULONG WINAPI
tracked_video_sample_Release(IMFTrackedSample
*iface
)
1437 struct video_sample
*sample
= impl_from_IMFTrackedSample(iface
);
1438 return IMFSample_Release(&sample
->IMFSample_iface
);
1441 static HRESULT WINAPI
tracked_video_sample_SetAllocator(IMFTrackedSample
*iface
,
1442 IMFAsyncCallback
*sample_allocator
, IUnknown
*state
)
1444 struct video_sample
*sample
= impl_from_IMFTrackedSample(iface
);
1447 TRACE("%p, %p, %p.\n", iface
, sample_allocator
, state
);
1449 EnterCriticalSection(&sample
->cs
);
1450 if (sample
->tracked_result
)
1451 hr
= MF_E_NOTACCEPTING
;
1454 if (SUCCEEDED(hr
= create_async_result((IUnknown
*)iface
, sample_allocator
, state
, &sample
->tracked_result
)))
1456 /* Account for additional refcount brought by 'state' object. This threshold is used
1457 on Release() to invoke tracker callback. */
1458 sample
->tracked_refcount
= 1;
1459 if (state
== (IUnknown
*)&sample
->IMFTrackedSample_iface
||
1460 state
== (IUnknown
*)&sample
->IMFSample_iface
)
1462 ++sample
->tracked_refcount
;
1466 LeaveCriticalSection(&sample
->cs
);
1471 static const IMFTrackedSampleVtbl tracked_video_sample_vtbl
=
1473 tracked_video_sample_QueryInterface
,
1474 tracked_video_sample_AddRef
,
1475 tracked_video_sample_Release
,
1476 tracked_video_sample_SetAllocator
,
1479 static HRESULT WINAPI
desired_video_sample_QueryInterface(IMFDesiredSample
*iface
, REFIID riid
, void **obj
)
1481 struct video_sample
*sample
= impl_from_IMFDesiredSample(iface
);
1482 return IMFSample_QueryInterface(&sample
->IMFSample_iface
, riid
, obj
);
1485 static ULONG WINAPI
desired_video_sample_AddRef(IMFDesiredSample
*iface
)
1487 struct video_sample
*sample
= impl_from_IMFDesiredSample(iface
);
1488 return IMFSample_AddRef(&sample
->IMFSample_iface
);
1491 static ULONG WINAPI
desired_video_sample_Release(IMFDesiredSample
*iface
)
1493 struct video_sample
*sample
= impl_from_IMFDesiredSample(iface
);
1494 return IMFSample_Release(&sample
->IMFSample_iface
);
1497 static HRESULT WINAPI
desired_video_sample_GetDesiredSampleTimeAndDuration(IMFDesiredSample
*iface
,
1498 LONGLONG
*sample_time
, LONGLONG
*sample_duration
)
1500 struct video_sample
*sample
= impl_from_IMFDesiredSample(iface
);
1503 TRACE("%p, %p, %p.\n", iface
, sample_time
, sample_duration
);
1505 if (!sample_time
|| !sample_duration
)
1508 EnterCriticalSection(&sample
->cs
);
1509 if (sample
->flags
& SAMPLE_PROP_HAS_DESIRED_PROPS
)
1511 *sample_time
= sample
->desired_timestamp
;
1512 *sample_duration
= sample
->desired_duration
;
1515 hr
= MF_E_NOT_AVAILABLE
;
1516 LeaveCriticalSection(&sample
->cs
);
1521 static void WINAPI
desired_video_sample_SetDesiredSampleTimeAndDuration(IMFDesiredSample
*iface
,
1522 LONGLONG sample_time
, LONGLONG sample_duration
)
1524 struct video_sample
*sample
= impl_from_IMFDesiredSample(iface
);
1526 TRACE("%p, %s, %s.\n", iface
, debugstr_time(sample_time
), debugstr_time(sample_duration
));
1528 EnterCriticalSection(&sample
->cs
);
1529 sample
->flags
|= SAMPLE_PROP_HAS_DESIRED_PROPS
;
1530 sample
->desired_timestamp
= sample_time
;
1531 sample
->desired_duration
= sample_duration
;
1532 LeaveCriticalSection(&sample
->cs
);
1535 static void WINAPI
desired_video_sample_Clear(IMFDesiredSample
*iface
)
1537 struct video_sample
*sample
= impl_from_IMFDesiredSample(iface
);
1539 TRACE("%p.\n", iface
);
1541 EnterCriticalSection(&sample
->cs
);
1543 IMFSample_SetSampleFlags(sample
->sample
, 0);
1544 IMFSample_DeleteAllItems(sample
->sample
);
1545 LeaveCriticalSection(&sample
->cs
);
1548 static const IMFDesiredSampleVtbl desired_video_sample_vtbl
=
1550 desired_video_sample_QueryInterface
,
1551 desired_video_sample_AddRef
,
1552 desired_video_sample_Release
,
1553 desired_video_sample_GetDesiredSampleTimeAndDuration
,
1554 desired_video_sample_SetDesiredSampleTimeAndDuration
,
1555 desired_video_sample_Clear
,
1558 static HRESULT WINAPI
surface_buffer_QueryInterface(IMFMediaBuffer
*iface
, REFIID riid
, void **obj
)
1560 struct surface_buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
1562 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
1564 if (IsEqualIID(riid
, &IID_IMFMediaBuffer
) || IsEqualIID(riid
, &IID_IUnknown
))
1566 *obj
= &buffer
->IMFMediaBuffer_iface
;
1568 else if (IsEqualIID(riid
, &IID_IMFGetService
))
1570 *obj
= &buffer
->IMFGetService_iface
;
1574 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
1576 return E_NOINTERFACE
;
1579 IUnknown_AddRef((IUnknown
*)*obj
);
1583 static ULONG WINAPI
surface_buffer_AddRef(IMFMediaBuffer
*iface
)
1585 struct surface_buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
1586 ULONG refcount
= InterlockedIncrement(&buffer
->refcount
);
1588 TRACE("%p, refcount %lu.\n", iface
, refcount
);
1593 static ULONG WINAPI
surface_buffer_Release(IMFMediaBuffer
*iface
)
1595 struct surface_buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
1596 ULONG refcount
= InterlockedDecrement(&buffer
->refcount
);
1598 TRACE("%p, refcount %lu.\n", iface
, refcount
);
1602 IUnknown_Release(buffer
->surface
);
1609 static HRESULT WINAPI
surface_buffer_Lock(IMFMediaBuffer
*iface
, BYTE
**data
, DWORD
*maxlength
, DWORD
*length
)
1611 TRACE("%p, %p, %p, %p.\n", iface
, data
, maxlength
, length
);
1616 static HRESULT WINAPI
surface_buffer_Unlock(IMFMediaBuffer
*iface
)
1618 TRACE("%p.\n", iface
);
1623 static HRESULT WINAPI
surface_buffer_GetCurrentLength(IMFMediaBuffer
*iface
, DWORD
*length
)
1625 struct surface_buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
1627 TRACE("%p.\n", iface
);
1629 *length
= buffer
->length
;
1634 static HRESULT WINAPI
surface_buffer_SetCurrentLength(IMFMediaBuffer
*iface
, DWORD length
)
1636 struct surface_buffer
*buffer
= impl_from_IMFMediaBuffer(iface
);
1638 TRACE("%p.\n", iface
);
1640 buffer
->length
= length
;
1645 static HRESULT WINAPI
surface_buffer_GetMaxLength(IMFMediaBuffer
*iface
, DWORD
*length
)
1647 TRACE("%p.\n", iface
);
1652 static const IMFMediaBufferVtbl surface_buffer_vtbl
=
1654 surface_buffer_QueryInterface
,
1655 surface_buffer_AddRef
,
1656 surface_buffer_Release
,
1657 surface_buffer_Lock
,
1658 surface_buffer_Unlock
,
1659 surface_buffer_GetCurrentLength
,
1660 surface_buffer_SetCurrentLength
,
1661 surface_buffer_GetMaxLength
,
1664 static HRESULT WINAPI
surface_buffer_gs_QueryInterface(IMFGetService
*iface
, REFIID riid
, void **obj
)
1666 struct surface_buffer
*buffer
= impl_from_IMFGetService(iface
);
1667 return IMFMediaBuffer_QueryInterface(&buffer
->IMFMediaBuffer_iface
, riid
, obj
);
1670 static ULONG WINAPI
surface_buffer_gs_AddRef(IMFGetService
*iface
)
1672 struct surface_buffer
*buffer
= impl_from_IMFGetService(iface
);
1673 return IMFMediaBuffer_AddRef(&buffer
->IMFMediaBuffer_iface
);
1676 static ULONG WINAPI
surface_buffer_gs_Release(IMFGetService
*iface
)
1678 struct surface_buffer
*buffer
= impl_from_IMFGetService(iface
);
1679 return IMFMediaBuffer_Release(&buffer
->IMFMediaBuffer_iface
);
1682 static HRESULT WINAPI
surface_buffer_gs_GetService(IMFGetService
*iface
, REFGUID service
, REFIID riid
, void **obj
)
1684 struct surface_buffer
*buffer
= impl_from_IMFGetService(iface
);
1686 TRACE("%p, %s, %s, %p.\n", iface
, debugstr_guid(service
), debugstr_guid(riid
), obj
);
1688 if (IsEqualGUID(service
, &MR_BUFFER_SERVICE
))
1689 return IUnknown_QueryInterface(buffer
->surface
, riid
, obj
);
1691 return E_NOINTERFACE
;
1694 static const IMFGetServiceVtbl surface_buffer_gs_vtbl
=
1696 surface_buffer_gs_QueryInterface
,
1697 surface_buffer_gs_AddRef
,
1698 surface_buffer_gs_Release
,
1699 surface_buffer_gs_GetService
,
1702 static HRESULT
create_surface_buffer(IUnknown
*surface
, IMFMediaBuffer
**buffer
)
1704 struct surface_buffer
*object
;
1706 if (!(object
= calloc(1, sizeof(*object
))))
1707 return E_OUTOFMEMORY
;
1709 object
->IMFMediaBuffer_iface
.lpVtbl
= &surface_buffer_vtbl
;
1710 object
->IMFGetService_iface
.lpVtbl
= &surface_buffer_gs_vtbl
;
1711 object
->refcount
= 1;
1712 object
->surface
= surface
;
1713 IUnknown_AddRef(object
->surface
);
1715 *buffer
= &object
->IMFMediaBuffer_iface
;
1720 HRESULT WINAPI
MFCreateVideoSampleFromSurface(IUnknown
*surface
, IMFSample
**sample
)
1722 struct video_sample
*object
;
1723 IMFMediaBuffer
*buffer
= NULL
;
1726 TRACE("%p, %p.\n", surface
, sample
);
1728 if (!(object
= calloc(1, sizeof(*object
))))
1729 return E_OUTOFMEMORY
;
1731 object
->IMFSample_iface
.lpVtbl
= &video_sample_vtbl
;
1732 object
->IMFTrackedSample_iface
.lpVtbl
= &tracked_video_sample_vtbl
;
1733 object
->IMFDesiredSample_iface
.lpVtbl
= &desired_video_sample_vtbl
;
1734 object
->refcount
= 1;
1735 InitializeCriticalSection(&object
->cs
);
1737 if (FAILED(hr
= MFCreateSample(&object
->sample
)))
1743 if (surface
&& FAILED(hr
= create_surface_buffer(surface
, &buffer
)))
1745 IMFSample_Release(&object
->IMFSample_iface
);
1751 IMFSample_AddBuffer(object
->sample
, buffer
);
1752 IMFMediaBuffer_Release(buffer
);
1755 video_sample_create_tracking_thread();
1757 *sample
= &object
->IMFSample_iface
;