3 * Copyright 2014 Austin English
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #define NONAMELESSUNION
36 #include "mfreadwrite.h"
38 #include "wine/debug.h"
39 #include "wine/heap.h"
41 WINE_DEFAULT_DEBUG_CHANNEL(mfplat
);
43 static HINSTANCE mfinstance
;
45 BOOL WINAPI
DllMain(HINSTANCE instance
, DWORD reason
, LPVOID reserved
)
49 case DLL_WINE_PREATTACH
:
50 return FALSE
; /* prefer native version */
51 case DLL_PROCESS_ATTACH
:
52 mfinstance
= instance
;
53 DisableThreadLibraryCalls(instance
);
60 HRESULT WINAPI
DllCanUnloadNow(void)
65 HRESULT WINAPI
DllRegisterServer(void)
67 return __wine_register_resources( mfinstance
);
70 HRESULT WINAPI
DllUnregisterServer(void)
72 return __wine_unregister_resources( mfinstance
);
77 IMFMediaStream
*stream
;
78 IMFMediaType
*current
;
82 typedef struct source_reader
84 IMFSourceReader IMFSourceReader_iface
;
85 IMFAsyncCallback source_events_callback
;
86 IMFAsyncCallback stream_events_callback
;
88 IMFMediaSource
*source
;
89 IMFPresentationDescriptor
*descriptor
;
90 DWORD first_audio_stream_index
;
91 DWORD first_video_stream_index
;
92 IMFSourceReaderCallback
*async_callback
;
93 BOOL shutdown_on_release
;
94 struct media_stream
*streams
;
101 IMFSinkWriter IMFSinkWriter_iface
;
105 static inline srcreader
*impl_from_IMFSourceReader(IMFSourceReader
*iface
)
107 return CONTAINING_RECORD(iface
, srcreader
, IMFSourceReader_iface
);
110 static struct source_reader
*impl_from_source_callback_IMFAsyncCallback(IMFAsyncCallback
*iface
)
112 return CONTAINING_RECORD(iface
, struct source_reader
, source_events_callback
);
115 static struct source_reader
*impl_from_stream_callback_IMFAsyncCallback(IMFAsyncCallback
*iface
)
117 return CONTAINING_RECORD(iface
, struct source_reader
, stream_events_callback
);
120 static inline struct sink_writer
*impl_from_IMFSinkWriter(IMFSinkWriter
*iface
)
122 return CONTAINING_RECORD(iface
, struct sink_writer
, IMFSinkWriter_iface
);
125 static HRESULT WINAPI
source_reader_source_events_callback_QueryInterface(IMFAsyncCallback
*iface
,
126 REFIID riid
, void **obj
)
128 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), obj
);
130 if (IsEqualIID(riid
, &IID_IMFAsyncCallback
) ||
131 IsEqualIID(riid
, &IID_IUnknown
))
134 IMFAsyncCallback_AddRef(iface
);
138 WARN("Unsupported %s.\n", debugstr_guid(riid
));
140 return E_NOINTERFACE
;
143 static ULONG WINAPI
source_reader_source_events_callback_AddRef(IMFAsyncCallback
*iface
)
145 struct source_reader
*reader
= impl_from_source_callback_IMFAsyncCallback(iface
);
146 return IMFSourceReader_AddRef(&reader
->IMFSourceReader_iface
);
149 static ULONG WINAPI
source_reader_source_events_callback_Release(IMFAsyncCallback
*iface
)
151 struct source_reader
*reader
= impl_from_source_callback_IMFAsyncCallback(iface
);
152 return IMFSourceReader_Release(&reader
->IMFSourceReader_iface
);
155 static HRESULT WINAPI
source_reader_source_events_callback_GetParameters(IMFAsyncCallback
*iface
,
156 DWORD
*flags
, DWORD
*queue
)
161 static HRESULT
source_reader_new_stream_handler(struct source_reader
*reader
, IMFMediaEvent
*event
)
163 IMFStreamDescriptor
*sd
;
164 IMFMediaStream
*stream
;
170 PropVariantInit(&value
);
171 if (FAILED(hr
= IMFMediaEvent_GetValue(event
, &value
)))
173 WARN("Failed to get event value, hr %#x.\n", hr
);
177 if (value
.vt
!= VT_UNKNOWN
|| !value
.u
.punkVal
)
179 WARN("Unexpected value type %d.\n", value
.vt
);
180 PropVariantClear(&value
);
184 hr
= IUnknown_QueryInterface(value
.u
.punkVal
, &IID_IMFMediaStream
, (void **)&stream
);
185 PropVariantClear(&value
);
188 WARN("Unexpected object type.\n");
192 TRACE("Got new stream %p.\n", stream
);
194 if (SUCCEEDED(hr
= IMFMediaStream_GetStreamDescriptor(stream
, &sd
)))
196 hr
= IMFStreamDescriptor_GetStreamIdentifier(sd
, &id
);
197 IMFStreamDescriptor_Release(sd
);
202 WARN("Unidentified stream %p, hr %#x.\n", stream
, hr
);
203 IMFMediaStream_Release(stream
);
207 for (i
= 0; i
< reader
->stream_count
; ++i
)
209 if (id
== reader
->streams
[i
].id
)
211 if (!InterlockedCompareExchangePointer((void **)&reader
->streams
[i
].stream
, stream
, NULL
))
213 IMFMediaStream_AddRef(reader
->streams
[i
].stream
);
214 if (FAILED(hr
= IMFMediaStream_BeginGetEvent(stream
, &reader
->stream_events_callback
,
215 (IUnknown
*)stream
)))
217 WARN("Failed to subscribe to stream events, hr %#x.\n", hr
);
224 if (i
== reader
->stream_count
)
225 WARN("Stream with id %#x was not present in presentation descriptor.\n", id
);
227 IMFMediaStream_Release(stream
);
232 static HRESULT WINAPI
source_reader_source_events_callback_Invoke(IMFAsyncCallback
*iface
, IMFAsyncResult
*result
)
234 struct source_reader
*reader
= impl_from_source_callback_IMFAsyncCallback(iface
);
235 MediaEventType event_type
;
236 IMFMediaSource
*source
;
237 IMFMediaEvent
*event
;
240 TRACE("%p, %p.\n", iface
, result
);
242 source
= (IMFMediaSource
*)IMFAsyncResult_GetStateNoAddRef(result
);
244 if (FAILED(hr
= IMFMediaSource_EndGetEvent(source
, result
, &event
)))
247 IMFMediaEvent_GetType(event
, &event_type
);
249 TRACE("Got event %u.\n", event_type
);
254 hr
= source_reader_new_stream_handler(reader
, event
);
261 WARN("Failed while handling %d event, hr %#x.\n", event_type
, hr
);
263 IMFMediaEvent_Release(event
);
265 IMFMediaSource_BeginGetEvent(source
, iface
, (IUnknown
*)source
);
270 static const IMFAsyncCallbackVtbl source_events_callback_vtbl
=
272 source_reader_source_events_callback_QueryInterface
,
273 source_reader_source_events_callback_AddRef
,
274 source_reader_source_events_callback_Release
,
275 source_reader_source_events_callback_GetParameters
,
276 source_reader_source_events_callback_Invoke
,
279 static ULONG WINAPI
source_reader_stream_events_callback_AddRef(IMFAsyncCallback
*iface
)
281 struct source_reader
*reader
= impl_from_stream_callback_IMFAsyncCallback(iface
);
282 return IMFSourceReader_AddRef(&reader
->IMFSourceReader_iface
);
285 static ULONG WINAPI
source_reader_stream_events_callback_Release(IMFAsyncCallback
*iface
)
287 struct source_reader
*reader
= impl_from_stream_callback_IMFAsyncCallback(iface
);
288 return IMFSourceReader_Release(&reader
->IMFSourceReader_iface
);
291 static HRESULT WINAPI
source_reader_stream_events_callback_Invoke(IMFAsyncCallback
*iface
, IMFAsyncResult
*result
)
293 MediaEventType event_type
;
294 IMFMediaStream
*stream
;
295 IMFMediaEvent
*event
;
298 TRACE("%p, %p.\n", iface
, result
);
300 stream
= (IMFMediaStream
*)IMFAsyncResult_GetStateNoAddRef(result
);
302 if (FAILED(hr
= IMFMediaStream_EndGetEvent(stream
, result
, &event
)))
305 IMFMediaEvent_GetType(event
, &event_type
);
307 TRACE("Got event %u.\n", event_type
);
309 IMFMediaEvent_Release(event
);
311 IMFMediaStream_BeginGetEvent(stream
, iface
, (IUnknown
*)stream
);
316 static const IMFAsyncCallbackVtbl stream_events_callback_vtbl
=
318 source_reader_source_events_callback_QueryInterface
,
319 source_reader_stream_events_callback_AddRef
,
320 source_reader_stream_events_callback_Release
,
321 source_reader_source_events_callback_GetParameters
,
322 source_reader_stream_events_callback_Invoke
,
325 static HRESULT WINAPI
src_reader_QueryInterface(IMFSourceReader
*iface
, REFIID riid
, void **out
)
327 srcreader
*This
= impl_from_IMFSourceReader(iface
);
329 TRACE("(%p)->(%s %p)\n", This
, debugstr_guid(riid
), out
);
331 if(IsEqualGUID(riid
, &IID_IUnknown
) ||
332 IsEqualGUID(riid
, &IID_IMFSourceReader
))
334 *out
= &This
->IMFSourceReader_iface
;
338 FIXME("(%s, %p)\n", debugstr_guid(riid
), out
);
340 return E_NOINTERFACE
;
343 IUnknown_AddRef((IUnknown
*)*out
);
347 static ULONG WINAPI
src_reader_AddRef(IMFSourceReader
*iface
)
349 srcreader
*This
= impl_from_IMFSourceReader(iface
);
350 ULONG ref
= InterlockedIncrement(&This
->refcount
);
352 TRACE("(%p) ref=%u\n", This
, ref
);
357 static ULONG WINAPI
src_reader_Release(IMFSourceReader
*iface
)
359 struct source_reader
*reader
= impl_from_IMFSourceReader(iface
);
360 ULONG refcount
= InterlockedDecrement(&reader
->refcount
);
363 TRACE("%p, refcount %d.\n", iface
, refcount
);
367 if (reader
->async_callback
)
368 IMFSourceReaderCallback_Release(reader
->async_callback
);
369 if (reader
->shutdown_on_release
)
370 IMFMediaSource_Shutdown(reader
->source
);
371 if (reader
->descriptor
)
372 IMFPresentationDescriptor_Release(reader
->descriptor
);
373 IMFMediaSource_Release(reader
->source
);
375 for (i
= 0; i
< reader
->stream_count
; ++i
)
377 if (reader
->streams
[i
].stream
)
378 IMFMediaStream_Release(reader
->streams
[i
].stream
);
379 if (reader
->streams
[i
].current
)
380 IMFMediaType_Release(reader
->streams
[i
].current
);
382 heap_free(reader
->streams
);
383 DeleteCriticalSection(&reader
->cs
);
390 static HRESULT WINAPI
src_reader_GetStreamSelection(IMFSourceReader
*iface
, DWORD index
, BOOL
*selected
)
392 struct source_reader
*reader
= impl_from_IMFSourceReader(iface
);
393 IMFStreamDescriptor
*sd
;
395 TRACE("%p, %#x, %p.\n", iface
, index
, selected
);
399 case MF_SOURCE_READER_FIRST_VIDEO_STREAM
:
400 index
= reader
->first_video_stream_index
;
402 case MF_SOURCE_READER_FIRST_AUDIO_STREAM
:
403 index
= reader
->first_audio_stream_index
;
409 if (FAILED(IMFPresentationDescriptor_GetStreamDescriptorByIndex(reader
->descriptor
, index
, selected
, &sd
)))
410 return MF_E_INVALIDSTREAMNUMBER
;
411 IMFStreamDescriptor_Release(sd
);
416 static HRESULT WINAPI
src_reader_SetStreamSelection(IMFSourceReader
*iface
, DWORD index
, BOOL selected
)
418 struct source_reader
*reader
= impl_from_IMFSourceReader(iface
);
422 TRACE("%p, %#x, %d.\n", iface
, index
, selected
);
426 case MF_SOURCE_READER_FIRST_VIDEO_STREAM
:
427 index
= reader
->first_video_stream_index
;
429 case MF_SOURCE_READER_FIRST_AUDIO_STREAM
:
430 index
= reader
->first_audio_stream_index
;
432 case MF_SOURCE_READER_ALL_STREAMS
:
433 if (FAILED(hr
= IMFPresentationDescriptor_GetStreamDescriptorCount(reader
->descriptor
, &count
)))
436 for (index
= 0; index
< count
; ++index
)
439 IMFPresentationDescriptor_SelectStream(reader
->descriptor
, index
);
441 IMFPresentationDescriptor_DeselectStream(reader
->descriptor
, index
);
450 hr
= IMFPresentationDescriptor_SelectStream(reader
->descriptor
, index
);
452 hr
= IMFPresentationDescriptor_DeselectStream(reader
->descriptor
, index
);
455 return MF_E_INVALIDSTREAMNUMBER
;
460 static HRESULT WINAPI
src_reader_GetNativeMediaType(IMFSourceReader
*iface
, DWORD index
, DWORD type_index
,
463 struct source_reader
*reader
= impl_from_IMFSourceReader(iface
);
464 IMFMediaTypeHandler
*handler
;
465 IMFStreamDescriptor
*sd
;
469 TRACE("%p, %#x, %#x, %p.\n", iface
, index
, type_index
, type
);
473 case MF_SOURCE_READER_FIRST_VIDEO_STREAM
:
474 index
= reader
->first_video_stream_index
;
476 case MF_SOURCE_READER_FIRST_AUDIO_STREAM
:
477 index
= reader
->first_audio_stream_index
;
483 if (FAILED(IMFPresentationDescriptor_GetStreamDescriptorByIndex(reader
->descriptor
, index
, &selected
, &sd
)))
484 return MF_E_INVALIDSTREAMNUMBER
;
486 hr
= IMFStreamDescriptor_GetMediaTypeHandler(sd
, &handler
);
487 IMFStreamDescriptor_Release(sd
);
491 if (type_index
== MF_SOURCE_READER_CURRENT_TYPE_INDEX
)
492 hr
= IMFMediaTypeHandler_GetCurrentMediaType(handler
, type
);
494 hr
= IMFMediaTypeHandler_GetMediaTypeByIndex(handler
, type_index
, type
);
495 IMFMediaTypeHandler_Release(handler
);
500 static HRESULT WINAPI
src_reader_GetCurrentMediaType(IMFSourceReader
*iface
, DWORD index
, IMFMediaType
**type
)
502 struct source_reader
*reader
= impl_from_IMFSourceReader(iface
);
505 TRACE("%p, %#x, %p.\n", iface
, index
, type
);
509 case MF_SOURCE_READER_FIRST_VIDEO_STREAM
:
510 index
= reader
->first_video_stream_index
;
512 case MF_SOURCE_READER_FIRST_AUDIO_STREAM
:
513 index
= reader
->first_audio_stream_index
;
519 if (index
>= reader
->stream_count
)
520 return MF_E_INVALIDSTREAMNUMBER
;
522 if (FAILED(hr
= MFCreateMediaType(type
)))
525 EnterCriticalSection(&reader
->cs
);
527 hr
= IMFMediaType_CopyAllItems(reader
->streams
[index
].current
, (IMFAttributes
*)*type
);
529 LeaveCriticalSection(&reader
->cs
);
534 static HRESULT WINAPI
src_reader_SetCurrentMediaType(IMFSourceReader
*iface
, DWORD index
, DWORD
*reserved
,
537 struct source_reader
*reader
= impl_from_IMFSourceReader(iface
);
540 TRACE("%p, %#x, %p, %p.\n", iface
, index
, reserved
, type
);
544 case MF_SOURCE_READER_FIRST_VIDEO_STREAM
:
545 index
= reader
->first_video_stream_index
;
547 case MF_SOURCE_READER_FIRST_AUDIO_STREAM
:
548 index
= reader
->first_audio_stream_index
;
554 if (index
>= reader
->stream_count
)
555 return MF_E_INVALIDSTREAMNUMBER
;
557 /* FIXME: validate passed type and current presentation state. */
559 EnterCriticalSection(&reader
->cs
);
561 hr
= IMFMediaType_CopyAllItems(type
, (IMFAttributes
*)reader
->streams
[index
].current
);
563 LeaveCriticalSection(&reader
->cs
);
568 static HRESULT WINAPI
src_reader_SetCurrentPosition(IMFSourceReader
*iface
, REFGUID format
, REFPROPVARIANT position
)
570 struct source_reader
*reader
= impl_from_IMFSourceReader(iface
);
574 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(format
), position
);
576 /* FIXME: fail if we got pending samples. */
578 if (FAILED(hr
= IMFMediaSource_GetCharacteristics(reader
->source
, &flags
)))
581 if (!(flags
& MFMEDIASOURCE_CAN_SEEK
))
582 return MF_E_INVALIDREQUEST
;
584 return IMFMediaSource_Start(reader
->source
, reader
->descriptor
, format
, position
);
587 static HRESULT WINAPI
src_reader_ReadSample(IMFSourceReader
*iface
, DWORD index
,
588 DWORD flags
, DWORD
*actualindex
, DWORD
*sampleflags
, LONGLONG
*timestamp
,
591 srcreader
*This
= impl_from_IMFSourceReader(iface
);
592 FIXME("%p, 0x%08x, 0x%08x, %p, %p, %p, %p\n", This
, index
, flags
, actualindex
,
593 sampleflags
, timestamp
, sample
);
597 static HRESULT WINAPI
src_reader_Flush(IMFSourceReader
*iface
, DWORD index
)
599 srcreader
*This
= impl_from_IMFSourceReader(iface
);
600 FIXME("%p, 0x%08x\n", This
, index
);
604 static HRESULT WINAPI
src_reader_GetServiceForStream(IMFSourceReader
*iface
, DWORD index
, REFGUID service
,
605 REFIID riid
, void **object
)
607 struct source_reader
*reader
= impl_from_IMFSourceReader(iface
);
608 IUnknown
*obj
= NULL
;
611 TRACE("%p, %#x, %s, %s, %p\n", iface
, index
, debugstr_guid(service
), debugstr_guid(riid
), object
);
615 case MF_SOURCE_READER_MEDIASOURCE
:
616 obj
= (IUnknown
*)reader
->source
;
619 FIXME("Unsupported index %#x.\n", index
);
623 if (IsEqualGUID(service
, &GUID_NULL
))
625 hr
= IUnknown_QueryInterface(obj
, riid
, object
);
631 hr
= IUnknown_QueryInterface(obj
, &IID_IMFGetService
, (void **)&gs
);
634 hr
= IMFGetService_GetService(gs
, service
, riid
, object
);
635 IMFGetService_Release(gs
);
642 static HRESULT WINAPI
src_reader_GetPresentationAttribute(IMFSourceReader
*iface
, DWORD index
,
643 REFGUID guid
, PROPVARIANT
*value
)
645 struct source_reader
*reader
= impl_from_IMFSourceReader(iface
);
646 IMFStreamDescriptor
*sd
;
650 TRACE("%p, %#x, %s, %p.\n", iface
, index
, debugstr_guid(guid
), value
);
654 case MF_SOURCE_READER_MEDIASOURCE
:
655 if (IsEqualGUID(guid
, &MF_SOURCE_READER_MEDIASOURCE_CHARACTERISTICS
))
659 if (FAILED(hr
= IMFMediaSource_GetCharacteristics(reader
->source
, &flags
)))
663 value
->u
.ulVal
= flags
;
668 return IMFPresentationDescriptor_GetItem(reader
->descriptor
, guid
, value
);
671 case MF_SOURCE_READER_FIRST_VIDEO_STREAM
:
672 index
= reader
->first_video_stream_index
;
674 case MF_SOURCE_READER_FIRST_AUDIO_STREAM
:
675 index
= reader
->first_audio_stream_index
;
681 if (FAILED(hr
= IMFPresentationDescriptor_GetStreamDescriptorByIndex(reader
->descriptor
, index
, &selected
, &sd
)))
684 hr
= IMFStreamDescriptor_GetItem(sd
, guid
, value
);
685 IMFStreamDescriptor_Release(sd
);
690 struct IMFSourceReaderVtbl srcreader_vtbl
=
692 src_reader_QueryInterface
,
695 src_reader_GetStreamSelection
,
696 src_reader_SetStreamSelection
,
697 src_reader_GetNativeMediaType
,
698 src_reader_GetCurrentMediaType
,
699 src_reader_SetCurrentMediaType
,
700 src_reader_SetCurrentPosition
,
701 src_reader_ReadSample
,
703 src_reader_GetServiceForStream
,
704 src_reader_GetPresentationAttribute
707 static DWORD
reader_get_first_stream_index(IMFPresentationDescriptor
*descriptor
, const GUID
*major
)
709 unsigned int count
, i
;
714 if (FAILED(IMFPresentationDescriptor_GetStreamDescriptorCount(descriptor
, &count
)))
715 return MF_SOURCE_READER_INVALID_STREAM_INDEX
;
717 for (i
= 0; i
< count
; ++i
)
719 IMFMediaTypeHandler
*handler
;
720 IMFStreamDescriptor
*sd
;
722 if (SUCCEEDED(IMFPresentationDescriptor_GetStreamDescriptorByIndex(descriptor
, i
, &selected
, &sd
)))
724 hr
= IMFStreamDescriptor_GetMediaTypeHandler(sd
, &handler
);
725 IMFStreamDescriptor_Release(sd
);
728 hr
= IMFMediaTypeHandler_GetMajorType(handler
, &guid
);
729 IMFMediaTypeHandler_Release(handler
);
730 if (SUCCEEDED(hr
) && IsEqualGUID(&guid
, major
))
738 return MF_SOURCE_READER_INVALID_STREAM_INDEX
;
741 static HRESULT
create_source_reader_from_source(IMFMediaSource
*source
, IMFAttributes
*attributes
,
742 BOOL shutdown_on_release
, REFIID riid
, void **out
)
744 struct source_reader
*object
;
748 object
= heap_alloc_zero(sizeof(*object
));
750 return E_OUTOFMEMORY
;
752 object
->IMFSourceReader_iface
.lpVtbl
= &srcreader_vtbl
;
753 object
->source_events_callback
.lpVtbl
= &source_events_callback_vtbl
;
754 object
->stream_events_callback
.lpVtbl
= &stream_events_callback_vtbl
;
755 object
->refcount
= 1;
756 object
->source
= source
;
757 IMFMediaSource_AddRef(object
->source
);
758 InitializeCriticalSection(&object
->cs
);
760 if (FAILED(hr
= IMFMediaSource_CreatePresentationDescriptor(object
->source
, &object
->descriptor
)))
763 if (FAILED(hr
= IMFPresentationDescriptor_GetStreamDescriptorCount(object
->descriptor
, &object
->stream_count
)))
766 if (!(object
->streams
= heap_alloc_zero(object
->stream_count
* sizeof(*object
->streams
))))
772 /* Set initial current media types. */
773 for (i
= 0; i
< object
->stream_count
; ++i
)
775 IMFMediaTypeHandler
*handler
;
776 IMFStreamDescriptor
*sd
;
777 IMFMediaType
*src_type
;
780 if (FAILED(hr
= MFCreateMediaType(&object
->streams
[i
].current
)))
783 if (FAILED(hr
= IMFPresentationDescriptor_GetStreamDescriptorByIndex(object
->descriptor
, i
, &selected
, &sd
)))
786 if (FAILED(hr
= IMFStreamDescriptor_GetStreamIdentifier(sd
, &object
->streams
[i
].id
)))
787 WARN("Failed to get stream identifier, hr %#x.\n", hr
);
789 hr
= IMFStreamDescriptor_GetMediaTypeHandler(sd
, &handler
);
790 IMFStreamDescriptor_Release(sd
);
794 hr
= IMFMediaTypeHandler_GetMediaTypeByIndex(handler
, 0, &src_type
);
795 IMFMediaTypeHandler_Release(handler
);
799 hr
= IMFMediaType_CopyAllItems(src_type
, (IMFAttributes
*)object
->streams
[i
].current
);
800 IMFMediaType_Release(src_type
);
808 /* At least one major type has to be set. */
809 object
->first_audio_stream_index
= reader_get_first_stream_index(object
->descriptor
, &MFMediaType_Audio
);
810 object
->first_video_stream_index
= reader_get_first_stream_index(object
->descriptor
, &MFMediaType_Video
);
812 if (object
->first_audio_stream_index
== MF_SOURCE_READER_INVALID_STREAM_INDEX
&&
813 object
->first_video_stream_index
== MF_SOURCE_READER_INVALID_STREAM_INDEX
)
815 hr
= MF_E_ATTRIBUTENOTFOUND
;
818 if (FAILED(hr
= IMFMediaSource_BeginGetEvent(object
->source
, &object
->source_events_callback
,
819 (IUnknown
*)object
->source
)))
826 IMFAttributes_GetUnknown(attributes
, &MF_SOURCE_READER_ASYNC_CALLBACK
, &IID_IMFSourceReaderCallback
,
827 (void **)&object
->async_callback
);
828 if (object
->async_callback
)
829 TRACE("Using async callback %p.\n", object
->async_callback
);
832 hr
= IMFSourceReader_QueryInterface(&object
->IMFSourceReader_iface
, riid
, out
);
835 IMFSourceReader_Release(&object
->IMFSourceReader_iface
);
839 static HRESULT
bytestream_get_url_hint(IMFByteStream
*stream
, WCHAR
const **url
)
841 static const UINT8 asfmagic
[] = {0x30,0x26,0xb2,0x75,0x8e,0x66,0xcf,0x11,0xa6,0xd9,0x00,0xaa,0x00,0x62,0xce,0x6c};
842 static const UINT8 wavmagic
[] = { 'R', 'I', 'F', 'F',0x00,0x00,0x00,0x00, 'W', 'A', 'V', 'E', 'f', 'm', 't', ' '};
843 static const UINT8 wavmask
[] = {0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
844 static const WCHAR asfW
[] = {'.','a','s','f',0};
845 static const WCHAR wavW
[] = {'.','w','a','v',0};
846 static const struct stream_content_url_hint
855 { asfmagic
, sizeof(asfmagic
), asfW
},
856 { wavmagic
, sizeof(wavmagic
), wavW
, wavmask
},
858 UINT8 buffer
[4 * sizeof(unsigned int)];
859 IMFAttributes
*attributes
;
868 if (SUCCEEDED(IMFByteStream_QueryInterface(stream
, &IID_IMFAttributes
, (void **)&attributes
)))
870 IMFAttributes_GetStringLength(attributes
, &MF_BYTESTREAM_CONTENT_TYPE
, &length
);
871 IMFAttributes_Release(attributes
);
877 if (FAILED(hr
= IMFByteStream_GetCapabilities(stream
, &caps
)))
880 if (!(caps
& MFBYTESTREAM_IS_SEEKABLE
))
883 if (FAILED(hr
= IMFByteStream_GetCurrentPosition(stream
, &position
)))
886 hr
= IMFByteStream_Read(stream
, buffer
, sizeof(buffer
), &length
);
887 IMFByteStream_SetCurrentPosition(stream
, position
);
891 if (length
< sizeof(buffer
))
894 for (i
= 0; i
< ARRAY_SIZE(url_hints
); ++i
)
896 if (url_hints
[i
].mask
)
898 unsigned int *mask
= (unsigned int *)url_hints
[i
].mask
;
899 unsigned int *data
= (unsigned int *)buffer
;
901 for (j
= 0; j
< sizeof(buffer
) / sizeof(unsigned int); ++j
)
905 if (!memcmp(buffer
, url_hints
[i
].magic
, min(url_hints
[i
].magic_len
, length
)))
907 *url
= url_hints
[i
].url
;
913 WARN("Unrecognized content type %s.\n", debugstr_an((char *)buffer
, length
));
918 static HRESULT
create_source_reader_from_stream(IMFByteStream
*stream
, IMFAttributes
*attributes
,
919 REFIID riid
, void **out
)
921 IPropertyStore
*props
= NULL
;
922 IMFSourceResolver
*resolver
;
923 MF_OBJECT_TYPE obj_type
;
924 IMFMediaSource
*source
;
928 /* If stream does not have content type set, try to guess from starting byte sequence. */
929 if (FAILED(hr
= bytestream_get_url_hint(stream
, &url
)))
932 if (FAILED(hr
= MFCreateSourceResolver(&resolver
)))
936 IMFAttributes_GetUnknown(attributes
, &MF_SOURCE_READER_MEDIASOURCE_CONFIG
, &IID_IPropertyStore
,
939 hr
= IMFSourceResolver_CreateObjectFromByteStream(resolver
, stream
, url
, MF_RESOLUTION_MEDIASOURCE
, props
,
940 &obj_type
, (IUnknown
**)&source
);
941 IMFSourceResolver_Release(resolver
);
943 IPropertyStore_Release(props
);
947 hr
= create_source_reader_from_source(source
, attributes
, TRUE
, riid
, out
);
948 IMFMediaSource_Release(source
);
952 static HRESULT
create_source_reader_from_url(const WCHAR
*url
, IMFAttributes
*attributes
, REFIID riid
, void **out
)
954 IPropertyStore
*props
= NULL
;
955 IMFSourceResolver
*resolver
;
956 IUnknown
*object
= NULL
;
957 MF_OBJECT_TYPE obj_type
;
958 IMFMediaSource
*source
;
961 if (FAILED(hr
= MFCreateSourceResolver(&resolver
)))
965 IMFAttributes_GetUnknown(attributes
, &MF_SOURCE_READER_MEDIASOURCE_CONFIG
, &IID_IPropertyStore
,
968 hr
= IMFSourceResolver_CreateObjectFromURL(resolver
, url
, MF_RESOLUTION_MEDIASOURCE
, props
, &obj_type
,
974 case MF_OBJECT_BYTESTREAM
:
975 hr
= IMFSourceResolver_CreateObjectFromByteStream(resolver
, (IMFByteStream
*)object
, NULL
,
976 MF_RESOLUTION_MEDIASOURCE
, props
, &obj_type
, (IUnknown
**)&source
);
978 case MF_OBJECT_MEDIASOURCE
:
979 source
= (IMFMediaSource
*)object
;
980 IMFMediaSource_AddRef(source
);
983 WARN("Unknown object type %d.\n", obj_type
);
986 IUnknown_Release(object
);
989 IMFSourceResolver_Release(resolver
);
991 IPropertyStore_Release(props
);
995 hr
= create_source_reader_from_source(source
, attributes
, TRUE
, riid
, out
);
996 IMFMediaSource_Release(source
);
1000 static HRESULT WINAPI
sink_writer_QueryInterface(IMFSinkWriter
*iface
, REFIID riid
, void **out
)
1002 TRACE("%p, %s, %p.\n", iface
, debugstr_guid(riid
), out
);
1004 if (IsEqualIID(riid
, &IID_IMFSinkWriter
) ||
1005 IsEqualIID(riid
, &IID_IUnknown
))
1008 IMFSinkWriter_AddRef(iface
);
1012 WARN("Unsupported %s.\n", debugstr_guid(riid
));
1014 return E_NOINTERFACE
;
1017 static ULONG WINAPI
sink_writer_AddRef(IMFSinkWriter
*iface
)
1019 struct sink_writer
*writer
= impl_from_IMFSinkWriter(iface
);
1020 ULONG refcount
= InterlockedIncrement(&writer
->refcount
);
1022 TRACE("%p, %u.\n", iface
, refcount
);
1027 static ULONG WINAPI
sink_writer_Release(IMFSinkWriter
*iface
)
1029 struct sink_writer
*writer
= impl_from_IMFSinkWriter(iface
);
1030 ULONG refcount
= InterlockedDecrement(&writer
->refcount
);
1032 TRACE("%p, %u.\n", iface
, refcount
);
1042 static HRESULT WINAPI
sink_writer_AddStream(IMFSinkWriter
*iface
, IMFMediaType
*type
, DWORD
*index
)
1044 FIXME("%p, %p, %p.\n", iface
, type
, index
);
1049 static HRESULT WINAPI
sink_writer_SetInputMediaType(IMFSinkWriter
*iface
, DWORD index
, IMFMediaType
*type
,
1050 IMFAttributes
*parameters
)
1052 FIXME("%p, %u, %p, %p.\n", iface
, index
, type
, parameters
);
1057 static HRESULT WINAPI
sink_writer_BeginWriting(IMFSinkWriter
*iface
)
1059 FIXME("%p.\n", iface
);
1064 static HRESULT WINAPI
sink_writer_WriteSample(IMFSinkWriter
*iface
, DWORD index
, IMFSample
*sample
)
1066 FIXME("%p, %u, %p.\n", iface
, index
, sample
);
1071 static HRESULT WINAPI
sink_writer_SendStreamTick(IMFSinkWriter
*iface
, DWORD index
, LONGLONG timestamp
)
1073 FIXME("%p, %u, %s.\n", iface
, index
, wine_dbgstr_longlong(timestamp
));
1078 static HRESULT WINAPI
sink_writer_PlaceMarker(IMFSinkWriter
*iface
, DWORD index
, void *context
)
1080 FIXME("%p, %u, %p.\n", iface
, index
, context
);
1085 static HRESULT WINAPI
sink_writer_NotifyEndOfSegment(IMFSinkWriter
*iface
, DWORD index
)
1087 FIXME("%p, %u.\n", iface
, index
);
1092 static HRESULT WINAPI
sink_writer_Flush(IMFSinkWriter
*iface
, DWORD index
)
1094 FIXME("%p, %u.\n", iface
, index
);
1099 static HRESULT WINAPI
sink_writer_Finalize(IMFSinkWriter
*iface
)
1101 FIXME("%p.\n", iface
);
1106 static HRESULT WINAPI
sink_writer_GetServiceForStream(IMFSinkWriter
*iface
, DWORD index
, REFGUID service
,
1107 REFIID riid
, void **object
)
1109 FIXME("%p, %u, %s, %s, %p.\n", iface
, index
, debugstr_guid(service
), debugstr_guid(riid
), object
);
1114 static HRESULT WINAPI
sink_writer_GetStatistics(IMFSinkWriter
*iface
, DWORD index
, MF_SINK_WRITER_STATISTICS
*stats
)
1116 FIXME("%p, %u, %p.\n", iface
, index
, stats
);
1121 static const IMFSinkWriterVtbl sink_writer_vtbl
=
1123 sink_writer_QueryInterface
,
1125 sink_writer_Release
,
1126 sink_writer_AddStream
,
1127 sink_writer_SetInputMediaType
,
1128 sink_writer_BeginWriting
,
1129 sink_writer_WriteSample
,
1130 sink_writer_SendStreamTick
,
1131 sink_writer_PlaceMarker
,
1132 sink_writer_NotifyEndOfSegment
,
1134 sink_writer_Finalize
,
1135 sink_writer_GetServiceForStream
,
1136 sink_writer_GetStatistics
,
1139 static HRESULT
create_sink_writer_from_sink(IMFMediaSink
*sink
, IMFAttributes
*attributes
,
1140 REFIID riid
, void **out
)
1142 struct sink_writer
*object
;
1145 object
= heap_alloc(sizeof(*object
));
1147 return E_OUTOFMEMORY
;
1149 object
->IMFSinkWriter_iface
.lpVtbl
= &sink_writer_vtbl
;
1150 object
->refcount
= 1;
1152 hr
= IMFSinkWriter_QueryInterface(&object
->IMFSinkWriter_iface
, riid
, out
);
1153 IMFSinkWriter_Release(&object
->IMFSinkWriter_iface
);
1157 static HRESULT
create_sink_writer_from_stream(IMFByteStream
*stream
, IMFAttributes
*attributes
,
1158 REFIID riid
, void **out
)
1160 struct sink_writer
*object
;
1163 object
= heap_alloc(sizeof(*object
));
1165 return E_OUTOFMEMORY
;
1167 object
->IMFSinkWriter_iface
.lpVtbl
= &sink_writer_vtbl
;
1168 object
->refcount
= 1;
1170 hr
= IMFSinkWriter_QueryInterface(&object
->IMFSinkWriter_iface
, riid
, out
);
1171 IMFSinkWriter_Release(&object
->IMFSinkWriter_iface
);
1175 /***********************************************************************
1176 * MFCreateSinkWriterFromMediaSink (mfreadwrite.@)
1178 HRESULT WINAPI
MFCreateSinkWriterFromMediaSink(IMFMediaSink
*sink
, IMFAttributes
*attributes
, IMFSinkWriter
**writer
)
1180 TRACE("%p, %p, %p.\n", sink
, attributes
, writer
);
1182 return create_sink_writer_from_sink(sink
, attributes
, &IID_IMFSinkWriter
, (void **)writer
);
1185 static HRESULT
create_source_reader_from_object(IUnknown
*unk
, IMFAttributes
*attributes
, REFIID riid
, void **out
)
1187 IMFMediaSource
*source
= NULL
;
1188 IMFByteStream
*stream
= NULL
;
1191 hr
= IUnknown_QueryInterface(unk
, &IID_IMFMediaSource
, (void **)&source
);
1193 hr
= IUnknown_QueryInterface(unk
, &IID_IMFByteStream
, (void **)&stream
);
1197 UINT32 disconnect
= 0;
1200 IMFAttributes_GetUINT32(attributes
, &MF_SOURCE_READER_DISCONNECT_MEDIASOURCE_ON_SHUTDOWN
, &disconnect
);
1201 hr
= create_source_reader_from_source(source
, attributes
, !disconnect
, riid
, out
);
1204 hr
= create_source_reader_from_stream(stream
, attributes
, riid
, out
);
1207 IMFMediaSource_Release(source
);
1209 IMFByteStream_Release(stream
);
1214 /***********************************************************************
1215 * MFCreateSourceReaderFromByteStream (mfreadwrite.@)
1217 HRESULT WINAPI
MFCreateSourceReaderFromByteStream(IMFByteStream
*stream
, IMFAttributes
*attributes
,
1218 IMFSourceReader
**reader
)
1220 TRACE("%p, %p, %p.\n", stream
, attributes
, reader
);
1222 return create_source_reader_from_object((IUnknown
*)stream
, attributes
, &IID_IMFSourceReader
, (void **)reader
);
1225 /***********************************************************************
1226 * MFCreateSourceReaderFromMediaSource (mfreadwrite.@)
1228 HRESULT WINAPI
MFCreateSourceReaderFromMediaSource(IMFMediaSource
*source
, IMFAttributes
*attributes
,
1229 IMFSourceReader
**reader
)
1231 TRACE("%p, %p, %p.\n", source
, attributes
, reader
);
1233 return create_source_reader_from_object((IUnknown
*)source
, attributes
, &IID_IMFSourceReader
, (void **)reader
);
1236 /***********************************************************************
1237 * MFCreateSourceReaderFromURL (mfreadwrite.@)
1239 HRESULT WINAPI
MFCreateSourceReaderFromURL(const WCHAR
*url
, IMFAttributes
*attributes
, IMFSourceReader
**reader
)
1241 TRACE("%s, %p, %p.\n", debugstr_w(url
), attributes
, reader
);
1243 return create_source_reader_from_url(url
, attributes
, &IID_IMFSourceReader
, (void **)reader
);
1246 static HRESULT WINAPI
readwrite_factory_QueryInterface(IMFReadWriteClassFactory
*iface
, REFIID riid
, void **out
)
1248 if (IsEqualIID(riid
, &IID_IMFReadWriteClassFactory
) ||
1249 IsEqualIID(riid
, &IID_IUnknown
))
1252 IMFReadWriteClassFactory_AddRef(iface
);
1256 WARN("Unsupported interface %s.\n", debugstr_guid(riid
));
1258 return E_NOINTERFACE
;
1261 static ULONG WINAPI
readwrite_factory_AddRef(IMFReadWriteClassFactory
*iface
)
1266 static ULONG WINAPI
readwrite_factory_Release(IMFReadWriteClassFactory
*iface
)
1271 static HRESULT WINAPI
readwrite_factory_CreateInstanceFromURL(IMFReadWriteClassFactory
*iface
, REFCLSID clsid
,
1272 const WCHAR
*url
, IMFAttributes
*attributes
, REFIID riid
, void **out
)
1274 TRACE("%s, %s, %p, %s, %p.\n", debugstr_guid(clsid
), debugstr_w(url
), attributes
, debugstr_guid(riid
), out
);
1276 if (IsEqualGUID(clsid
, &CLSID_MFSourceReader
))
1278 return create_source_reader_from_url(url
, attributes
, &IID_IMFSourceReader
, out
);
1281 FIXME("Unsupported %s.\n", debugstr_guid(clsid
));
1286 static HRESULT WINAPI
readwrite_factory_CreateInstanceFromObject(IMFReadWriteClassFactory
*iface
, REFCLSID clsid
,
1287 IUnknown
*unk
, IMFAttributes
*attributes
, REFIID riid
, void **out
)
1291 TRACE("%s, %p, %p, %s, %p.\n", debugstr_guid(clsid
), unk
, attributes
, debugstr_guid(riid
), out
);
1293 if (IsEqualGUID(clsid
, &CLSID_MFSourceReader
))
1295 return create_source_reader_from_object(unk
, attributes
, riid
, out
);
1297 else if (IsEqualGUID(clsid
, &CLSID_MFSinkWriter
))
1299 IMFByteStream
*stream
= NULL
;
1300 IMFMediaSink
*sink
= NULL
;
1302 hr
= IUnknown_QueryInterface(unk
, &IID_IMFByteStream
, (void **)&stream
);
1304 hr
= IUnknown_QueryInterface(unk
, &IID_IMFMediaSink
, (void **)&sink
);
1307 hr
= create_sink_writer_from_stream(stream
, attributes
, riid
, out
);
1309 hr
= create_sink_writer_from_sink(sink
, attributes
, riid
, out
);
1312 IMFMediaSink_Release(sink
);
1314 IMFByteStream_Release(stream
);
1320 WARN("Unsupported class %s.\n", debugstr_guid(clsid
));
1326 static const IMFReadWriteClassFactoryVtbl readwrite_factory_vtbl
=
1328 readwrite_factory_QueryInterface
,
1329 readwrite_factory_AddRef
,
1330 readwrite_factory_Release
,
1331 readwrite_factory_CreateInstanceFromURL
,
1332 readwrite_factory_CreateInstanceFromObject
,
1335 static IMFReadWriteClassFactory readwrite_factory
= { &readwrite_factory_vtbl
};
1337 static HRESULT WINAPI
classfactory_QueryInterface(IClassFactory
*iface
, REFIID riid
, void **out
)
1339 TRACE("%s, %p.\n", debugstr_guid(riid
), out
);
1341 if (IsEqualGUID(riid
, &IID_IClassFactory
) ||
1342 IsEqualGUID(riid
, &IID_IUnknown
))
1344 IClassFactory_AddRef(iface
);
1349 WARN("interface %s not implemented\n", debugstr_guid(riid
));
1351 return E_NOINTERFACE
;
1354 static ULONG WINAPI
classfactory_AddRef(IClassFactory
*iface
)
1359 static ULONG WINAPI
classfactory_Release(IClassFactory
*iface
)
1364 static HRESULT WINAPI
classfactory_CreateInstance(IClassFactory
*iface
, IUnknown
*outer
, REFIID riid
, void **out
)
1366 TRACE("%p, %s, %p.\n", outer
, debugstr_guid(riid
), out
);
1371 return CLASS_E_NOAGGREGATION
;
1373 return IMFReadWriteClassFactory_QueryInterface(&readwrite_factory
, riid
, out
);
1376 static HRESULT WINAPI
classfactory_LockServer(IClassFactory
*iface
, BOOL dolock
)
1378 FIXME("%d.\n", dolock
);
1382 static const struct IClassFactoryVtbl classfactoryvtbl
=
1384 classfactory_QueryInterface
,
1385 classfactory_AddRef
,
1386 classfactory_Release
,
1387 classfactory_CreateInstance
,
1388 classfactory_LockServer
,
1391 static IClassFactory classfactory
= { &classfactoryvtbl
};
1393 HRESULT WINAPI
DllGetClassObject(REFCLSID clsid
, REFIID riid
, void **out
)
1395 TRACE("%s, %s, %p.\n", debugstr_guid(clsid
), debugstr_guid(riid
), out
);
1397 if (IsEqualGUID(clsid
, &CLSID_MFReadWriteClassFactory
))
1398 return IClassFactory_QueryInterface(&classfactory
, riid
, out
);
1400 WARN("Unsupported class %s.\n", debugstr_guid(clsid
));
1402 return CLASS_E_CLASSNOTAVAILABLE
;