2 * Copyright 2012 Austin English
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include "gst_private.h"
21 WINE_DEFAULT_DEBUG_CHANNEL(wmvcore
);
23 static struct wm_stream
*get_stream_by_output_number(struct wm_reader
*reader
, DWORD output
)
25 if (output
< reader
->stream_count
)
26 return &reader
->streams
[output
];
27 WARN("Invalid output number %lu.\n", output
);
33 IWMOutputMediaProps IWMOutputMediaProps_iface
;
39 static inline struct output_props
*impl_from_IWMOutputMediaProps(IWMOutputMediaProps
*iface
)
41 return CONTAINING_RECORD(iface
, struct output_props
, IWMOutputMediaProps_iface
);
44 static HRESULT WINAPI
output_props_QueryInterface(IWMOutputMediaProps
*iface
, REFIID iid
, void **out
)
46 struct output_props
*props
= impl_from_IWMOutputMediaProps(iface
);
48 TRACE("props %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
50 if (IsEqualGUID(iid
, &IID_IUnknown
) || IsEqualGUID(iid
, &IID_IWMOutputMediaProps
))
51 *out
= &props
->IWMOutputMediaProps_iface
;
55 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
59 IUnknown_AddRef((IUnknown
*)*out
);
63 static ULONG WINAPI
output_props_AddRef(IWMOutputMediaProps
*iface
)
65 struct output_props
*props
= impl_from_IWMOutputMediaProps(iface
);
66 ULONG refcount
= InterlockedIncrement(&props
->refcount
);
68 TRACE("%p increasing refcount to %lu.\n", props
, refcount
);
73 static ULONG WINAPI
output_props_Release(IWMOutputMediaProps
*iface
)
75 struct output_props
*props
= impl_from_IWMOutputMediaProps(iface
);
76 ULONG refcount
= InterlockedDecrement(&props
->refcount
);
78 TRACE("%p decreasing refcount to %lu.\n", props
, refcount
);
86 static HRESULT WINAPI
output_props_GetType(IWMOutputMediaProps
*iface
, GUID
*major_type
)
88 const struct output_props
*props
= impl_from_IWMOutputMediaProps(iface
);
90 TRACE("iface %p, major_type %p.\n", iface
, major_type
);
92 *major_type
= props
->mt
.majortype
;
96 static HRESULT WINAPI
output_props_GetMediaType(IWMOutputMediaProps
*iface
, WM_MEDIA_TYPE
*mt
, DWORD
*size
)
98 const struct output_props
*props
= impl_from_IWMOutputMediaProps(iface
);
99 const DWORD req_size
= *size
;
101 TRACE("iface %p, mt %p, size %p.\n", iface
, mt
, size
);
103 *size
= sizeof(*mt
) + props
->mt
.cbFormat
;
106 if (req_size
< *size
)
107 return ASF_E_BUFFERTOOSMALL
;
109 strmbase_dump_media_type(&props
->mt
);
111 memcpy(mt
, &props
->mt
, sizeof(*mt
));
112 memcpy(mt
+ 1, props
->mt
.pbFormat
, props
->mt
.cbFormat
);
113 mt
->pbFormat
= (BYTE
*)(mt
+ 1);
117 static HRESULT WINAPI
output_props_SetMediaType(IWMOutputMediaProps
*iface
, WM_MEDIA_TYPE
*mt
)
119 FIXME("iface %p, mt %p, stub!\n", iface
, mt
);
123 static HRESULT WINAPI
output_props_GetStreamGroupName(IWMOutputMediaProps
*iface
, WCHAR
*name
, WORD
*len
)
125 FIXME("iface %p, name %p, len %p, stub!\n", iface
, name
, len
);
129 static HRESULT WINAPI
output_props_GetConnectionName(IWMOutputMediaProps
*iface
, WCHAR
*name
, WORD
*len
)
131 FIXME("iface %p, name %p, len %p, stub!\n", iface
, name
, len
);
135 static const struct IWMOutputMediaPropsVtbl output_props_vtbl
=
137 output_props_QueryInterface
,
139 output_props_Release
,
140 output_props_GetType
,
141 output_props_GetMediaType
,
142 output_props_SetMediaType
,
143 output_props_GetStreamGroupName
,
144 output_props_GetConnectionName
,
147 static struct output_props
*unsafe_impl_from_IWMOutputMediaProps(IWMOutputMediaProps
*iface
)
151 assert(iface
->lpVtbl
== &output_props_vtbl
);
152 return impl_from_IWMOutputMediaProps(iface
);
155 static IWMOutputMediaProps
*output_props_create(const struct wg_format
*format
)
157 struct output_props
*object
;
159 if (!(object
= calloc(1, sizeof(*object
))))
161 object
->IWMOutputMediaProps_iface
.lpVtbl
= &output_props_vtbl
;
162 object
->refcount
= 1;
164 if (!amt_from_wg_format(&object
->mt
, format
, true))
170 TRACE("Created output properties %p.\n", object
);
171 return &object
->IWMOutputMediaProps_iface
;
176 INSSBuffer INSSBuffer_iface
;
179 DWORD size
, capacity
;
183 static struct buffer
*impl_from_INSSBuffer(INSSBuffer
*iface
)
185 return CONTAINING_RECORD(iface
, struct buffer
, INSSBuffer_iface
);
188 static HRESULT WINAPI
buffer_QueryInterface(INSSBuffer
*iface
, REFIID iid
, void **out
)
190 struct buffer
*buffer
= impl_from_INSSBuffer(iface
);
192 TRACE("buffer %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
194 if (IsEqualGUID(iid
, &IID_IUnknown
) || IsEqualGUID(iid
, &IID_INSSBuffer
))
195 *out
= &buffer
->INSSBuffer_iface
;
199 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
200 return E_NOINTERFACE
;
203 IUnknown_AddRef((IUnknown
*)*out
);
207 static ULONG WINAPI
buffer_AddRef(INSSBuffer
*iface
)
209 struct buffer
*buffer
= impl_from_INSSBuffer(iface
);
210 ULONG refcount
= InterlockedIncrement(&buffer
->refcount
);
212 TRACE("%p increasing refcount to %lu.\n", buffer
, refcount
);
217 static ULONG WINAPI
buffer_Release(INSSBuffer
*iface
)
219 struct buffer
*buffer
= impl_from_INSSBuffer(iface
);
220 ULONG refcount
= InterlockedDecrement(&buffer
->refcount
);
222 TRACE("%p decreasing refcount to %lu.\n", buffer
, refcount
);
230 static HRESULT WINAPI
buffer_GetLength(INSSBuffer
*iface
, DWORD
*size
)
232 FIXME("iface %p, size %p, stub!\n", iface
, size
);
236 static HRESULT WINAPI
buffer_SetLength(INSSBuffer
*iface
, DWORD size
)
238 struct buffer
*buffer
= impl_from_INSSBuffer(iface
);
240 TRACE("iface %p, size %lu.\n", buffer
, size
);
242 if (size
> buffer
->capacity
)
249 static HRESULT WINAPI
buffer_GetMaxLength(INSSBuffer
*iface
, DWORD
*size
)
251 struct buffer
*buffer
= impl_from_INSSBuffer(iface
);
253 TRACE("buffer %p, size %p.\n", buffer
, size
);
255 *size
= buffer
->capacity
;
259 static HRESULT WINAPI
buffer_GetBuffer(INSSBuffer
*iface
, BYTE
**data
)
261 struct buffer
*buffer
= impl_from_INSSBuffer(iface
);
263 TRACE("buffer %p, data %p.\n", buffer
, data
);
265 *data
= buffer
->data
;
269 static HRESULT WINAPI
buffer_GetBufferAndLength(INSSBuffer
*iface
, BYTE
**data
, DWORD
*size
)
271 struct buffer
*buffer
= impl_from_INSSBuffer(iface
);
273 TRACE("buffer %p, data %p, size %p.\n", buffer
, data
, size
);
275 *size
= buffer
->size
;
276 *data
= buffer
->data
;
280 static const INSSBufferVtbl buffer_vtbl
=
282 buffer_QueryInterface
,
289 buffer_GetBufferAndLength
,
294 IWMStreamConfig IWMStreamConfig_iface
;
295 IWMMediaProps IWMMediaProps_iface
;
298 const struct wm_stream
*stream
;
301 static struct stream_config
*impl_from_IWMStreamConfig(IWMStreamConfig
*iface
)
303 return CONTAINING_RECORD(iface
, struct stream_config
, IWMStreamConfig_iface
);
306 static HRESULT WINAPI
stream_config_QueryInterface(IWMStreamConfig
*iface
, REFIID iid
, void **out
)
308 struct stream_config
*config
= impl_from_IWMStreamConfig(iface
);
310 TRACE("config %p, iid %s, out %p.\n", config
, debugstr_guid(iid
), out
);
312 if (IsEqualGUID(iid
, &IID_IUnknown
) || IsEqualGUID(iid
, &IID_IWMStreamConfig
))
313 *out
= &config
->IWMStreamConfig_iface
;
314 else if (IsEqualGUID(iid
, &IID_IWMMediaProps
))
315 *out
= &config
->IWMMediaProps_iface
;
319 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
320 return E_NOINTERFACE
;
323 IUnknown_AddRef((IUnknown
*)*out
);
327 static ULONG WINAPI
stream_config_AddRef(IWMStreamConfig
*iface
)
329 struct stream_config
*config
= impl_from_IWMStreamConfig(iface
);
330 ULONG refcount
= InterlockedIncrement(&config
->refcount
);
332 TRACE("%p increasing refcount to %lu.\n", config
, refcount
);
337 static ULONG WINAPI
stream_config_Release(IWMStreamConfig
*iface
)
339 struct stream_config
*config
= impl_from_IWMStreamConfig(iface
);
340 ULONG refcount
= InterlockedDecrement(&config
->refcount
);
342 TRACE("%p decreasing refcount to %lu.\n", config
, refcount
);
346 IWMProfile3_Release(&config
->stream
->reader
->IWMProfile3_iface
);
353 static HRESULT WINAPI
stream_config_GetStreamType(IWMStreamConfig
*iface
, GUID
*type
)
355 struct stream_config
*config
= impl_from_IWMStreamConfig(iface
);
356 struct wm_reader
*reader
= config
->stream
->reader
;
359 TRACE("config %p, type %p.\n", config
, type
);
361 EnterCriticalSection(&reader
->cs
);
363 if (!amt_from_wg_format(&mt
, &config
->stream
->format
, true))
365 LeaveCriticalSection(&reader
->cs
);
366 return E_OUTOFMEMORY
;
369 *type
= mt
.majortype
;
372 LeaveCriticalSection(&reader
->cs
);
377 static HRESULT WINAPI
stream_config_GetStreamNumber(IWMStreamConfig
*iface
, WORD
*number
)
379 struct stream_config
*config
= impl_from_IWMStreamConfig(iface
);
381 TRACE("config %p, number %p.\n", config
, number
);
383 *number
= config
->stream
->index
+ 1;
387 static HRESULT WINAPI
stream_config_SetStreamNumber(IWMStreamConfig
*iface
, WORD number
)
389 FIXME("iface %p, number %u, stub!\n", iface
, number
);
393 static HRESULT WINAPI
stream_config_GetStreamName(IWMStreamConfig
*iface
, WCHAR
*name
, WORD
*len
)
395 FIXME("iface %p, name %p, len %p, stub!\n", iface
, name
, len
);
399 static HRESULT WINAPI
stream_config_SetStreamName(IWMStreamConfig
*iface
, const WCHAR
*name
)
401 FIXME("iface %p, name %s, stub!\n", iface
, debugstr_w(name
));
405 static HRESULT WINAPI
stream_config_GetConnectionName(IWMStreamConfig
*iface
, WCHAR
*name
, WORD
*len
)
407 FIXME("iface %p, name %p, len %p, stub!\n", iface
, name
, len
);
411 static HRESULT WINAPI
stream_config_SetConnectionName(IWMStreamConfig
*iface
, const WCHAR
*name
)
413 FIXME("iface %p, name %s, stub!\n", iface
, debugstr_w(name
));
417 static HRESULT WINAPI
stream_config_GetBitrate(IWMStreamConfig
*iface
, DWORD
*bitrate
)
419 FIXME("iface %p, bitrate %p, stub!\n", iface
, bitrate
);
423 static HRESULT WINAPI
stream_config_SetBitrate(IWMStreamConfig
*iface
, DWORD bitrate
)
425 FIXME("iface %p, bitrate %lu, stub!\n", iface
, bitrate
);
429 static HRESULT WINAPI
stream_config_GetBufferWindow(IWMStreamConfig
*iface
, DWORD
*window
)
431 FIXME("iface %p, window %p, stub!\n", iface
, window
);
435 static HRESULT WINAPI
stream_config_SetBufferWindow(IWMStreamConfig
*iface
, DWORD window
)
437 FIXME("iface %p, window %lu, stub!\n", iface
, window
);
441 static const IWMStreamConfigVtbl stream_config_vtbl
=
443 stream_config_QueryInterface
,
444 stream_config_AddRef
,
445 stream_config_Release
,
446 stream_config_GetStreamType
,
447 stream_config_GetStreamNumber
,
448 stream_config_SetStreamNumber
,
449 stream_config_GetStreamName
,
450 stream_config_SetStreamName
,
451 stream_config_GetConnectionName
,
452 stream_config_SetConnectionName
,
453 stream_config_GetBitrate
,
454 stream_config_SetBitrate
,
455 stream_config_GetBufferWindow
,
456 stream_config_SetBufferWindow
,
459 static struct stream_config
*impl_from_IWMMediaProps(IWMMediaProps
*iface
)
461 return CONTAINING_RECORD(iface
, struct stream_config
, IWMMediaProps_iface
);
464 static HRESULT WINAPI
stream_props_QueryInterface(IWMMediaProps
*iface
, REFIID iid
, void **out
)
466 struct stream_config
*config
= impl_from_IWMMediaProps(iface
);
467 return IWMStreamConfig_QueryInterface(&config
->IWMStreamConfig_iface
, iid
, out
);
470 static ULONG WINAPI
stream_props_AddRef(IWMMediaProps
*iface
)
472 struct stream_config
*config
= impl_from_IWMMediaProps(iface
);
473 return IWMStreamConfig_AddRef(&config
->IWMStreamConfig_iface
);
476 static ULONG WINAPI
stream_props_Release(IWMMediaProps
*iface
)
478 struct stream_config
*config
= impl_from_IWMMediaProps(iface
);
479 return IWMStreamConfig_Release(&config
->IWMStreamConfig_iface
);
482 static HRESULT WINAPI
stream_props_GetType(IWMMediaProps
*iface
, GUID
*major_type
)
484 FIXME("iface %p, major_type %p, stub!\n", iface
, major_type
);
488 static HRESULT WINAPI
stream_props_GetMediaType(IWMMediaProps
*iface
, WM_MEDIA_TYPE
*mt
, DWORD
*size
)
490 struct stream_config
*config
= impl_from_IWMMediaProps(iface
);
491 const DWORD req_size
= *size
;
492 AM_MEDIA_TYPE stream_mt
;
494 TRACE("iface %p, mt %p, size %p.\n", iface
, mt
, size
);
496 if (!amt_from_wg_format(&stream_mt
, &config
->stream
->format
, true))
497 return E_OUTOFMEMORY
;
499 *size
= sizeof(stream_mt
) + stream_mt
.cbFormat
;
502 if (req_size
< *size
)
503 return ASF_E_BUFFERTOOSMALL
;
505 strmbase_dump_media_type(&stream_mt
);
507 memcpy(mt
, &stream_mt
, sizeof(*mt
));
508 memcpy(mt
+ 1, stream_mt
.pbFormat
, stream_mt
.cbFormat
);
509 mt
->pbFormat
= (BYTE
*)(mt
+ 1);
513 static HRESULT WINAPI
stream_props_SetMediaType(IWMMediaProps
*iface
, WM_MEDIA_TYPE
*mt
)
515 FIXME("iface %p, mt %p, stub!\n", iface
, mt
);
519 static const IWMMediaPropsVtbl stream_props_vtbl
=
521 stream_props_QueryInterface
,
523 stream_props_Release
,
524 stream_props_GetType
,
525 stream_props_GetMediaType
,
526 stream_props_SetMediaType
,
529 static DWORD CALLBACK
read_thread(void *arg
)
531 struct wm_reader
*reader
= arg
;
532 IStream
*stream
= reader
->source_stream
;
533 HANDLE file
= reader
->file
;
534 size_t buffer_size
= 4096;
538 if (!(data
= malloc(buffer_size
)))
545 GetFileSizeEx(file
, &size
);
546 file_size
= size
.QuadPart
;
552 IStream_Stat(stream
, &stat
, STATFLAG_NONAME
);
553 file_size
= stat
.cbSize
.QuadPart
;
556 TRACE("Starting read thread for reader %p.\n", reader
);
558 while (!reader
->read_thread_shutdown
)
560 LARGE_INTEGER large_offset
;
566 if (!wg_parser_get_next_read_offset(reader
->wg_parser
, &offset
, &size
))
569 if (offset
>= file_size
)
571 else if (offset
+ size
>= file_size
)
572 size
= file_size
- offset
;
576 wg_parser_push_data(reader
->wg_parser
, data
, 0);
580 if (!array_reserve(&data
, &buffer_size
, size
, 1))
588 large_offset
.QuadPart
= offset
;
591 if (!SetFilePointerEx(file
, large_offset
, NULL
, FILE_BEGIN
)
592 || !ReadFile(file
, data
, size
, &ret_size
, NULL
))
594 ERR("Failed to read %u bytes at offset %I64u, error %lu.\n", size
, offset
, GetLastError());
595 wg_parser_push_data(reader
->wg_parser
, NULL
, 0);
601 if (SUCCEEDED(hr
= IStream_Seek(stream
, large_offset
, STREAM_SEEK_SET
, NULL
)))
602 hr
= IStream_Read(stream
, data
, size
, &ret_size
);
605 ERR("Failed to read %u bytes at offset %I64u, hr %#lx.\n", size
, offset
, hr
);
606 wg_parser_push_data(reader
->wg_parser
, NULL
, 0);
611 if (ret_size
!= size
)
612 ERR("Unexpected short read: requested %u bytes, got %lu.\n", size
, ret_size
);
613 wg_parser_push_data(reader
->wg_parser
, data
, ret_size
);
617 TRACE("Reader is shutting down; exiting.\n");
621 static struct wm_reader
*impl_from_IWMProfile3(IWMProfile3
*iface
)
623 return CONTAINING_RECORD(iface
, struct wm_reader
, IWMProfile3_iface
);
626 static HRESULT WINAPI
profile_QueryInterface(IWMProfile3
*iface
, REFIID iid
, void **out
)
628 struct wm_reader
*reader
= impl_from_IWMProfile3(iface
);
630 TRACE("reader %p, iid %s, out %p.\n", reader
, debugstr_guid(iid
), out
);
632 if (IsEqualIID(iid
, &IID_IWMHeaderInfo
)
633 || IsEqualIID(iid
, &IID_IWMHeaderInfo2
)
634 || IsEqualIID(iid
, &IID_IWMHeaderInfo3
))
636 *out
= &reader
->IWMHeaderInfo3_iface
;
638 else if (IsEqualIID(iid
, &IID_IWMLanguageList
))
640 *out
= &reader
->IWMLanguageList_iface
;
642 else if (IsEqualIID(iid
, &IID_IWMPacketSize
)
643 || IsEqualIID(iid
, &IID_IWMPacketSize2
))
645 *out
= &reader
->IWMPacketSize2_iface
;
647 else if (IsEqualIID(iid
, &IID_IUnknown
)
648 || IsEqualIID(iid
, &IID_IWMProfile
)
649 || IsEqualIID(iid
, &IID_IWMProfile2
)
650 || IsEqualIID(iid
, &IID_IWMProfile3
))
652 *out
= &reader
->IWMProfile3_iface
;
654 else if (IsEqualIID(iid
, &IID_IWMReaderPlaylistBurn
))
656 *out
= &reader
->IWMReaderPlaylistBurn_iface
;
658 else if (IsEqualIID(iid
, &IID_IWMReaderTimecode
))
660 *out
= &reader
->IWMReaderTimecode_iface
;
662 else if (!(*out
= reader
->ops
->query_interface(reader
, iid
)))
664 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
665 return E_NOINTERFACE
;
668 IUnknown_AddRef((IUnknown
*)*out
);
672 static ULONG WINAPI
profile_AddRef(IWMProfile3
*iface
)
674 struct wm_reader
*reader
= impl_from_IWMProfile3(iface
);
675 ULONG refcount
= InterlockedIncrement(&reader
->refcount
);
677 TRACE("%p increasing refcount to %lu.\n", reader
, refcount
);
682 static ULONG WINAPI
profile_Release(IWMProfile3
*iface
)
684 struct wm_reader
*reader
= impl_from_IWMProfile3(iface
);
685 ULONG refcount
= InterlockedDecrement(&reader
->refcount
);
687 TRACE("%p decreasing refcount to %lu.\n", reader
, refcount
);
690 reader
->ops
->destroy(reader
);
695 static HRESULT WINAPI
profile_GetVersion(IWMProfile3
*iface
, WMT_VERSION
*version
)
697 FIXME("iface %p, version %p, stub!\n", iface
, version
);
701 static HRESULT WINAPI
profile_GetName(IWMProfile3
*iface
, WCHAR
*name
, DWORD
*length
)
703 FIXME("iface %p, name %p, length %p, stub!\n", iface
, name
, length
);
707 static HRESULT WINAPI
profile_SetName(IWMProfile3
*iface
, const WCHAR
*name
)
709 FIXME("iface %p, name %s, stub!\n", iface
, debugstr_w(name
));
713 static HRESULT WINAPI
profile_GetDescription(IWMProfile3
*iface
, WCHAR
*description
, DWORD
*length
)
715 FIXME("iface %p, description %p, length %p, stub!\n", iface
, description
, length
);
719 static HRESULT WINAPI
profile_SetDescription(IWMProfile3
*iface
, const WCHAR
*description
)
721 FIXME("iface %p, description %s, stub!\n", iface
, debugstr_w(description
));
725 static HRESULT WINAPI
profile_GetStreamCount(IWMProfile3
*iface
, DWORD
*count
)
727 struct wm_reader
*reader
= impl_from_IWMProfile3(iface
);
729 TRACE("reader %p, count %p.\n", reader
, count
);
734 EnterCriticalSection(&reader
->cs
);
735 *count
= reader
->stream_count
;
736 LeaveCriticalSection(&reader
->cs
);
740 static HRESULT WINAPI
profile_GetStream(IWMProfile3
*iface
, DWORD index
, IWMStreamConfig
**config
)
742 struct wm_reader
*reader
= impl_from_IWMProfile3(iface
);
743 struct stream_config
*object
;
745 TRACE("reader %p, index %lu, config %p.\n", reader
, index
, config
);
747 EnterCriticalSection(&reader
->cs
);
749 if (index
>= reader
->stream_count
)
751 LeaveCriticalSection(&reader
->cs
);
752 WARN("Index %lu exceeds stream count %u; returning E_INVALIDARG.\n", index
, reader
->stream_count
);
756 if (!(object
= calloc(1, sizeof(*object
))))
758 LeaveCriticalSection(&reader
->cs
);
759 return E_OUTOFMEMORY
;
762 object
->IWMStreamConfig_iface
.lpVtbl
= &stream_config_vtbl
;
763 object
->IWMMediaProps_iface
.lpVtbl
= &stream_props_vtbl
;
764 object
->refcount
= 1;
765 object
->stream
= &reader
->streams
[index
];
766 IWMProfile3_AddRef(&reader
->IWMProfile3_iface
);
768 LeaveCriticalSection(&reader
->cs
);
770 TRACE("Created stream config %p.\n", object
);
771 *config
= &object
->IWMStreamConfig_iface
;
775 static HRESULT WINAPI
profile_GetStreamByNumber(IWMProfile3
*iface
, WORD stream_number
, IWMStreamConfig
**config
)
777 FIXME("iface %p, stream_number %u, config %p, stub!\n", iface
, stream_number
, config
);
781 static HRESULT WINAPI
profile_RemoveStream(IWMProfile3
*iface
, IWMStreamConfig
*config
)
783 FIXME("iface %p, config %p, stub!\n", iface
, config
);
787 static HRESULT WINAPI
profile_RemoveStreamByNumber(IWMProfile3
*iface
, WORD stream_number
)
789 FIXME("iface %p, stream_number %u, stub!\n", iface
, stream_number
);
793 static HRESULT WINAPI
profile_AddStream(IWMProfile3
*iface
, IWMStreamConfig
*config
)
795 FIXME("iface %p, config %p, stub!\n", iface
, config
);
799 static HRESULT WINAPI
profile_ReconfigStream(IWMProfile3
*iface
, IWMStreamConfig
*config
)
801 FIXME("iface %p, config %p, stub!\n", iface
, config
);
805 static HRESULT WINAPI
profile_CreateNewStream(IWMProfile3
*iface
, REFGUID type
, IWMStreamConfig
**config
)
807 FIXME("iface %p, type %s, config %p, stub!\n", iface
, debugstr_guid(type
), config
);
811 static HRESULT WINAPI
profile_GetMutualExclusionCount(IWMProfile3
*iface
, DWORD
*count
)
813 FIXME("iface %p, count %p, stub!\n", iface
, count
);
817 static HRESULT WINAPI
profile_GetMutualExclusion(IWMProfile3
*iface
, DWORD index
, IWMMutualExclusion
**excl
)
819 FIXME("iface %p, index %lu, excl %p, stub!\n", iface
, index
, excl
);
823 static HRESULT WINAPI
profile_RemoveMutualExclusion(IWMProfile3
*iface
, IWMMutualExclusion
*excl
)
825 FIXME("iface %p, excl %p, stub!\n", iface
, excl
);
829 static HRESULT WINAPI
profile_AddMutualExclusion(IWMProfile3
*iface
, IWMMutualExclusion
*excl
)
831 FIXME("iface %p, excl %p, stub!\n", iface
, excl
);
835 static HRESULT WINAPI
profile_CreateNewMutualExclusion(IWMProfile3
*iface
, IWMMutualExclusion
**excl
)
837 FIXME("iface %p, excl %p, stub!\n", iface
, excl
);
841 static HRESULT WINAPI
profile_GetProfileID(IWMProfile3
*iface
, GUID
*id
)
843 FIXME("iface %p, id %p, stub!\n", iface
, id
);
847 static HRESULT WINAPI
profile_GetStorageFormat(IWMProfile3
*iface
, WMT_STORAGE_FORMAT
*format
)
849 FIXME("iface %p, format %p, stub!\n", iface
, format
);
853 static HRESULT WINAPI
profile_SetStorageFormat(IWMProfile3
*iface
, WMT_STORAGE_FORMAT format
)
855 FIXME("iface %p, format %#x, stub!\n", iface
, format
);
859 static HRESULT WINAPI
profile_GetBandwidthSharingCount(IWMProfile3
*iface
, DWORD
*count
)
861 FIXME("iface %p, count %p, stub!\n", iface
, count
);
865 static HRESULT WINAPI
profile_GetBandwidthSharing(IWMProfile3
*iface
, DWORD index
, IWMBandwidthSharing
**sharing
)
867 FIXME("iface %p, index %lu, sharing %p, stub!\n", iface
, index
, sharing
);
871 static HRESULT WINAPI
profile_RemoveBandwidthSharing( IWMProfile3
*iface
, IWMBandwidthSharing
*sharing
)
873 FIXME("iface %p, sharing %p, stub!\n", iface
, sharing
);
877 static HRESULT WINAPI
profile_AddBandwidthSharing(IWMProfile3
*iface
, IWMBandwidthSharing
*sharing
)
879 FIXME("iface %p, sharing %p, stub!\n", iface
, sharing
);
883 static HRESULT WINAPI
profile_CreateNewBandwidthSharing( IWMProfile3
*iface
, IWMBandwidthSharing
**sharing
)
885 FIXME("iface %p, sharing %p, stub!\n", iface
, sharing
);
889 static HRESULT WINAPI
profile_GetStreamPrioritization(IWMProfile3
*iface
, IWMStreamPrioritization
**stream
)
891 FIXME("iface %p, stream %p, stub!\n", iface
, stream
);
895 static HRESULT WINAPI
profile_SetStreamPrioritization(IWMProfile3
*iface
, IWMStreamPrioritization
*stream
)
897 FIXME("iface %p, stream %p, stub!\n", iface
, stream
);
901 static HRESULT WINAPI
profile_RemoveStreamPrioritization(IWMProfile3
*iface
)
903 FIXME("iface %p, stub!\n", iface
);
907 static HRESULT WINAPI
profile_CreateNewStreamPrioritization(IWMProfile3
*iface
, IWMStreamPrioritization
**stream
)
909 FIXME("iface %p, stream %p, stub!\n", iface
, stream
);
913 static HRESULT WINAPI
profile_GetExpectedPacketCount(IWMProfile3
*iface
, QWORD duration
, QWORD
*count
)
915 FIXME("iface %p, duration %s, count %p, stub!\n", iface
, debugstr_time(duration
), count
);
919 static const IWMProfile3Vtbl profile_vtbl
=
921 profile_QueryInterface
,
927 profile_GetDescription
,
928 profile_SetDescription
,
929 profile_GetStreamCount
,
931 profile_GetStreamByNumber
,
932 profile_RemoveStream
,
933 profile_RemoveStreamByNumber
,
935 profile_ReconfigStream
,
936 profile_CreateNewStream
,
937 profile_GetMutualExclusionCount
,
938 profile_GetMutualExclusion
,
939 profile_RemoveMutualExclusion
,
940 profile_AddMutualExclusion
,
941 profile_CreateNewMutualExclusion
,
942 profile_GetProfileID
,
943 profile_GetStorageFormat
,
944 profile_SetStorageFormat
,
945 profile_GetBandwidthSharingCount
,
946 profile_GetBandwidthSharing
,
947 profile_RemoveBandwidthSharing
,
948 profile_AddBandwidthSharing
,
949 profile_CreateNewBandwidthSharing
,
950 profile_GetStreamPrioritization
,
951 profile_SetStreamPrioritization
,
952 profile_RemoveStreamPrioritization
,
953 profile_CreateNewStreamPrioritization
,
954 profile_GetExpectedPacketCount
,
957 static struct wm_reader
*impl_from_IWMHeaderInfo3(IWMHeaderInfo3
*iface
)
959 return CONTAINING_RECORD(iface
, struct wm_reader
, IWMHeaderInfo3_iface
);
962 static HRESULT WINAPI
header_info_QueryInterface(IWMHeaderInfo3
*iface
, REFIID iid
, void **out
)
964 struct wm_reader
*reader
= impl_from_IWMHeaderInfo3(iface
);
966 return IWMProfile3_QueryInterface(&reader
->IWMProfile3_iface
, iid
, out
);
969 static ULONG WINAPI
header_info_AddRef(IWMHeaderInfo3
*iface
)
971 struct wm_reader
*reader
= impl_from_IWMHeaderInfo3(iface
);
973 return IWMProfile3_AddRef(&reader
->IWMProfile3_iface
);
976 static ULONG WINAPI
header_info_Release(IWMHeaderInfo3
*iface
)
978 struct wm_reader
*reader
= impl_from_IWMHeaderInfo3(iface
);
980 return IWMProfile3_Release(&reader
->IWMProfile3_iface
);
983 static HRESULT WINAPI
header_info_GetAttributeCount(IWMHeaderInfo3
*iface
, WORD stream_number
, WORD
*count
)
985 FIXME("iface %p, stream_number %u, count %p, stub!\n", iface
, stream_number
, count
);
989 static HRESULT WINAPI
header_info_GetAttributeByIndex(IWMHeaderInfo3
*iface
, WORD index
, WORD
*stream_number
,
990 WCHAR
*name
, WORD
*name_len
, WMT_ATTR_DATATYPE
*type
, BYTE
*value
, WORD
*size
)
992 FIXME("iface %p, index %u, stream_number %p, name %p, name_len %p, type %p, value %p, size %p, stub!\n",
993 iface
, index
, stream_number
, name
, name_len
, type
, value
, size
);
997 static HRESULT WINAPI
header_info_GetAttributeByName(IWMHeaderInfo3
*iface
, WORD
*stream_number
,
998 const WCHAR
*name
, WMT_ATTR_DATATYPE
*type
, BYTE
*value
, WORD
*size
)
1000 struct wm_reader
*reader
= impl_from_IWMHeaderInfo3(iface
);
1001 const WORD req_size
= *size
;
1003 TRACE("reader %p, stream_number %p, name %s, type %p, value %p, size %u.\n",
1004 reader
, stream_number
, debugstr_w(name
), type
, value
, *size
);
1007 return E_INVALIDARG
;
1009 if (!wcscmp(name
, L
"Duration"))
1015 WARN("Requesting duration for stream %u, returning ASF_E_NOTFOUND.\n", *stream_number
);
1016 return ASF_E_NOTFOUND
;
1019 *size
= sizeof(QWORD
);
1022 *type
= WMT_TYPE_QWORD
;
1025 if (req_size
< *size
)
1026 return ASF_E_BUFFERTOOSMALL
;
1028 *type
= WMT_TYPE_QWORD
;
1029 EnterCriticalSection(&reader
->cs
);
1030 duration
= wg_parser_stream_get_duration(wg_parser_get_stream(reader
->wg_parser
, 0));
1031 LeaveCriticalSection(&reader
->cs
);
1032 TRACE("Returning duration %s.\n", debugstr_time(duration
));
1033 memcpy(value
, &duration
, sizeof(QWORD
));
1036 else if (!wcscmp(name
, L
"Seekable"))
1040 WARN("Requesting duration for stream %u, returning ASF_E_NOTFOUND.\n", *stream_number
);
1041 return ASF_E_NOTFOUND
;
1044 *size
= sizeof(BOOL
);
1047 *type
= WMT_TYPE_BOOL
;
1050 if (req_size
< *size
)
1051 return ASF_E_BUFFERTOOSMALL
;
1053 *type
= WMT_TYPE_BOOL
;
1054 *(BOOL
*)value
= TRUE
;
1059 FIXME("Unknown attribute %s.\n", debugstr_w(name
));
1060 return ASF_E_NOTFOUND
;
1064 static HRESULT WINAPI
header_info_SetAttribute(IWMHeaderInfo3
*iface
, WORD stream_number
,
1065 const WCHAR
*name
, WMT_ATTR_DATATYPE type
, const BYTE
*value
, WORD size
)
1067 FIXME("iface %p, stream_number %u, name %s, type %#x, value %p, size %u, stub!\n",
1068 iface
, stream_number
, debugstr_w(name
), type
, value
, size
);
1072 static HRESULT WINAPI
header_info_GetMarkerCount(IWMHeaderInfo3
*iface
, WORD
*count
)
1074 FIXME("iface %p, count %p, stub!\n", iface
, count
);
1078 static HRESULT WINAPI
header_info_GetMarker(IWMHeaderInfo3
*iface
,
1079 WORD index
, WCHAR
*name
, WORD
*len
, QWORD
*time
)
1081 FIXME("iface %p, index %u, name %p, len %p, time %p, stub!\n", iface
, index
, name
, len
, time
);
1085 static HRESULT WINAPI
header_info_AddMarker(IWMHeaderInfo3
*iface
, const WCHAR
*name
, QWORD time
)
1087 FIXME("iface %p, name %s, time %s, stub!\n", iface
, debugstr_w(name
), debugstr_time(time
));
1091 static HRESULT WINAPI
header_info_RemoveMarker(IWMHeaderInfo3
*iface
, WORD index
)
1093 FIXME("iface %p, index %u, stub!\n", iface
, index
);
1097 static HRESULT WINAPI
header_info_GetScriptCount(IWMHeaderInfo3
*iface
, WORD
*count
)
1099 FIXME("iface %p, count %p, stub!\n", iface
, count
);
1103 static HRESULT WINAPI
header_info_GetScript(IWMHeaderInfo3
*iface
, WORD index
, WCHAR
*type
,
1104 WORD
*type_len
, WCHAR
*command
, WORD
*command_len
, QWORD
*time
)
1106 FIXME("iface %p, index %u, type %p, type_len %p, command %p, command_len %p, time %p, stub!\n",
1107 iface
, index
, type
, type_len
, command
, command_len
, time
);
1111 static HRESULT WINAPI
header_info_AddScript(IWMHeaderInfo3
*iface
,
1112 const WCHAR
*type
, const WCHAR
*command
, QWORD time
)
1114 FIXME("iface %p, type %s, command %s, time %s, stub!\n",
1115 iface
, debugstr_w(type
), debugstr_w(command
), debugstr_time(time
));
1119 static HRESULT WINAPI
header_info_RemoveScript(IWMHeaderInfo3
*iface
, WORD index
)
1121 FIXME("iface %p, index %u, stub!\n", iface
, index
);
1125 static HRESULT WINAPI
header_info_GetCodecInfoCount(IWMHeaderInfo3
*iface
, DWORD
*count
)
1127 FIXME("iface %p, count %p, stub!\n", iface
, count
);
1131 static HRESULT WINAPI
header_info_GetCodecInfo(IWMHeaderInfo3
*iface
, DWORD index
, WORD
*name_len
,
1132 WCHAR
*name
, WORD
*desc_len
, WCHAR
*desc
, WMT_CODEC_INFO_TYPE
*type
, WORD
*size
, BYTE
*info
)
1134 FIXME("iface %p, index %lu, name_len %p, name %p, desc_len %p, desc %p, type %p, size %p, info %p, stub!\n",
1135 iface
, index
, name_len
, name
, desc_len
, desc
, type
, size
, info
);
1139 static HRESULT WINAPI
header_info_GetAttributeCountEx(IWMHeaderInfo3
*iface
, WORD stream_number
, WORD
*count
)
1141 FIXME("iface %p, stream_number %u, count %p, stub!\n", iface
, stream_number
, count
);
1145 static HRESULT WINAPI
header_info_GetAttributeIndices(IWMHeaderInfo3
*iface
, WORD stream_number
,
1146 const WCHAR
*name
, WORD
*lang_index
, WORD
*indices
, WORD
*count
)
1148 FIXME("iface %p, stream_number %u, name %s, lang_index %p, indices %p, count %p, stub!\n",
1149 iface
, stream_number
, debugstr_w(name
), lang_index
, indices
, count
);
1153 static HRESULT WINAPI
header_info_GetAttributeByIndexEx(IWMHeaderInfo3
*iface
,
1154 WORD stream_number
, WORD index
, WCHAR
*name
, WORD
*name_len
,
1155 WMT_ATTR_DATATYPE
*type
, WORD
*lang_index
, BYTE
*value
, DWORD
*size
)
1157 FIXME("iface %p, stream_number %u, index %u, name %p, name_len %p,"
1158 " type %p, lang_index %p, value %p, size %p, stub!\n",
1159 iface
, stream_number
, index
, name
, name_len
, type
, lang_index
, value
, size
);
1163 static HRESULT WINAPI
header_info_ModifyAttribute(IWMHeaderInfo3
*iface
, WORD stream_number
,
1164 WORD index
, WMT_ATTR_DATATYPE type
, WORD lang_index
, const BYTE
*value
, DWORD size
)
1166 FIXME("iface %p, stream_number %u, index %u, type %#x, lang_index %u, value %p, size %lu, stub!\n",
1167 iface
, stream_number
, index
, type
, lang_index
, value
, size
);
1171 static HRESULT WINAPI
header_info_AddAttribute(IWMHeaderInfo3
*iface
,
1172 WORD stream_number
, const WCHAR
*name
, WORD
*index
,
1173 WMT_ATTR_DATATYPE type
, WORD lang_index
, const BYTE
*value
, DWORD size
)
1175 FIXME("iface %p, stream_number %u, name %s, index %p, type %#x, lang_index %u, value %p, size %lu, stub!\n",
1176 iface
, stream_number
, debugstr_w(name
), index
, type
, lang_index
, value
, size
);
1180 static HRESULT WINAPI
header_info_DeleteAttribute(IWMHeaderInfo3
*iface
, WORD stream_number
, WORD index
)
1182 FIXME("iface %p, stream_number %u, index %u, stub!\n", iface
, stream_number
, index
);
1186 static HRESULT WINAPI
header_info_AddCodecInfo(IWMHeaderInfo3
*iface
, const WCHAR
*name
,
1187 const WCHAR
*desc
, WMT_CODEC_INFO_TYPE type
, WORD size
, BYTE
*info
)
1189 FIXME("iface %p, name %s, desc %s, type %#x, size %u, info %p, stub!\n",
1190 info
, debugstr_w(name
), debugstr_w(desc
), type
, size
, info
);
1194 static const IWMHeaderInfo3Vtbl header_info_vtbl
=
1196 header_info_QueryInterface
,
1198 header_info_Release
,
1199 header_info_GetAttributeCount
,
1200 header_info_GetAttributeByIndex
,
1201 header_info_GetAttributeByName
,
1202 header_info_SetAttribute
,
1203 header_info_GetMarkerCount
,
1204 header_info_GetMarker
,
1205 header_info_AddMarker
,
1206 header_info_RemoveMarker
,
1207 header_info_GetScriptCount
,
1208 header_info_GetScript
,
1209 header_info_AddScript
,
1210 header_info_RemoveScript
,
1211 header_info_GetCodecInfoCount
,
1212 header_info_GetCodecInfo
,
1213 header_info_GetAttributeCountEx
,
1214 header_info_GetAttributeIndices
,
1215 header_info_GetAttributeByIndexEx
,
1216 header_info_ModifyAttribute
,
1217 header_info_AddAttribute
,
1218 header_info_DeleteAttribute
,
1219 header_info_AddCodecInfo
,
1222 static struct wm_reader
*impl_from_IWMLanguageList(IWMLanguageList
*iface
)
1224 return CONTAINING_RECORD(iface
, struct wm_reader
, IWMLanguageList_iface
);
1227 static HRESULT WINAPI
language_list_QueryInterface(IWMLanguageList
*iface
, REFIID iid
, void **out
)
1229 struct wm_reader
*reader
= impl_from_IWMLanguageList(iface
);
1231 return IWMProfile3_QueryInterface(&reader
->IWMProfile3_iface
, iid
, out
);
1234 static ULONG WINAPI
language_list_AddRef(IWMLanguageList
*iface
)
1236 struct wm_reader
*reader
= impl_from_IWMLanguageList(iface
);
1238 return IWMProfile3_AddRef(&reader
->IWMProfile3_iface
);
1241 static ULONG WINAPI
language_list_Release(IWMLanguageList
*iface
)
1243 struct wm_reader
*reader
= impl_from_IWMLanguageList(iface
);
1245 return IWMProfile3_Release(&reader
->IWMProfile3_iface
);
1248 static HRESULT WINAPI
language_list_GetLanguageCount(IWMLanguageList
*iface
, WORD
*count
)
1250 FIXME("iface %p, count %p, stub!\n", iface
, count
);
1254 static HRESULT WINAPI
language_list_GetLanguageDetails(IWMLanguageList
*iface
,
1255 WORD index
, WCHAR
*lang
, WORD
*len
)
1257 FIXME("iface %p, index %u, lang %p, len %p, stub!\n", iface
, index
, lang
, len
);
1261 static HRESULT WINAPI
language_list_AddLanguageByRFC1766String(IWMLanguageList
*iface
,
1262 const WCHAR
*lang
, WORD
*index
)
1264 FIXME("iface %p, lang %s, index %p, stub!\n", iface
, debugstr_w(lang
), index
);
1268 static const IWMLanguageListVtbl language_list_vtbl
=
1270 language_list_QueryInterface
,
1271 language_list_AddRef
,
1272 language_list_Release
,
1273 language_list_GetLanguageCount
,
1274 language_list_GetLanguageDetails
,
1275 language_list_AddLanguageByRFC1766String
,
1278 static struct wm_reader
*impl_from_IWMPacketSize2(IWMPacketSize2
*iface
)
1280 return CONTAINING_RECORD(iface
, struct wm_reader
, IWMPacketSize2_iface
);
1283 static HRESULT WINAPI
packet_size_QueryInterface(IWMPacketSize2
*iface
, REFIID iid
, void **out
)
1285 struct wm_reader
*reader
= impl_from_IWMPacketSize2(iface
);
1287 return IWMProfile3_QueryInterface(&reader
->IWMProfile3_iface
, iid
, out
);
1290 static ULONG WINAPI
packet_size_AddRef(IWMPacketSize2
*iface
)
1292 struct wm_reader
*reader
= impl_from_IWMPacketSize2(iface
);
1294 return IWMProfile3_AddRef(&reader
->IWMProfile3_iface
);
1297 static ULONG WINAPI
packet_size_Release(IWMPacketSize2
*iface
)
1299 struct wm_reader
*reader
= impl_from_IWMPacketSize2(iface
);
1301 return IWMProfile3_Release(&reader
->IWMProfile3_iface
);
1304 static HRESULT WINAPI
packet_size_GetMaxPacketSize(IWMPacketSize2
*iface
, DWORD
*size
)
1306 FIXME("iface %p, size %p, stub!\n", iface
, size
);
1310 static HRESULT WINAPI
packet_size_SetMaxPacketSize(IWMPacketSize2
*iface
, DWORD size
)
1312 FIXME("iface %p, size %lu, stub!\n", iface
, size
);
1316 static HRESULT WINAPI
packet_size_GetMinPacketSize(IWMPacketSize2
*iface
, DWORD
*size
)
1318 FIXME("iface %p, size %p, stub!\n", iface
, size
);
1322 static HRESULT WINAPI
packet_size_SetMinPacketSize(IWMPacketSize2
*iface
, DWORD size
)
1324 FIXME("iface %p, size %lu, stub!\n", iface
, size
);
1328 static const IWMPacketSize2Vtbl packet_size_vtbl
=
1330 packet_size_QueryInterface
,
1332 packet_size_Release
,
1333 packet_size_GetMaxPacketSize
,
1334 packet_size_SetMaxPacketSize
,
1335 packet_size_GetMinPacketSize
,
1336 packet_size_SetMinPacketSize
,
1339 static struct wm_reader
*impl_from_IWMReaderPlaylistBurn(IWMReaderPlaylistBurn
*iface
)
1341 return CONTAINING_RECORD(iface
, struct wm_reader
, IWMReaderPlaylistBurn_iface
);
1344 static HRESULT WINAPI
playlist_QueryInterface(IWMReaderPlaylistBurn
*iface
, REFIID iid
, void **out
)
1346 struct wm_reader
*reader
= impl_from_IWMReaderPlaylistBurn(iface
);
1348 return IWMProfile3_QueryInterface(&reader
->IWMProfile3_iface
, iid
, out
);
1351 static ULONG WINAPI
playlist_AddRef(IWMReaderPlaylistBurn
*iface
)
1353 struct wm_reader
*reader
= impl_from_IWMReaderPlaylistBurn(iface
);
1355 return IWMProfile3_AddRef(&reader
->IWMProfile3_iface
);
1358 static ULONG WINAPI
playlist_Release(IWMReaderPlaylistBurn
*iface
)
1360 struct wm_reader
*reader
= impl_from_IWMReaderPlaylistBurn(iface
);
1362 return IWMProfile3_Release(&reader
->IWMProfile3_iface
);
1365 static HRESULT WINAPI
playlist_InitPlaylistBurn(IWMReaderPlaylistBurn
*iface
, DWORD count
,
1366 const WCHAR
**filenames
, IWMStatusCallback
*callback
, void *context
)
1368 FIXME("iface %p, count %lu, filenames %p, callback %p, context %p, stub!\n",
1369 iface
, count
, filenames
, callback
, context
);
1373 static HRESULT WINAPI
playlist_GetInitResults(IWMReaderPlaylistBurn
*iface
, DWORD count
, HRESULT
*hrs
)
1375 FIXME("iface %p, count %lu, hrs %p, stub!\n", iface
, count
, hrs
);
1379 static HRESULT WINAPI
playlist_Cancel(IWMReaderPlaylistBurn
*iface
)
1381 FIXME("iface %p, stub!\n", iface
);
1385 static HRESULT WINAPI
playlist_EndPlaylistBurn(IWMReaderPlaylistBurn
*iface
, HRESULT hr
)
1387 FIXME("iface %p, hr %#lx, stub!\n", iface
, hr
);
1391 static const IWMReaderPlaylistBurnVtbl playlist_vtbl
=
1393 playlist_QueryInterface
,
1396 playlist_InitPlaylistBurn
,
1397 playlist_GetInitResults
,
1399 playlist_EndPlaylistBurn
,
1402 static struct wm_reader
*impl_from_IWMReaderTimecode(IWMReaderTimecode
*iface
)
1404 return CONTAINING_RECORD(iface
, struct wm_reader
, IWMReaderTimecode_iface
);
1407 static HRESULT WINAPI
timecode_QueryInterface(IWMReaderTimecode
*iface
, REFIID iid
, void **out
)
1409 struct wm_reader
*reader
= impl_from_IWMReaderTimecode(iface
);
1411 return IWMProfile3_QueryInterface(&reader
->IWMProfile3_iface
, iid
, out
);
1414 static ULONG WINAPI
timecode_AddRef(IWMReaderTimecode
*iface
)
1416 struct wm_reader
*reader
= impl_from_IWMReaderTimecode(iface
);
1418 return IWMProfile3_AddRef(&reader
->IWMProfile3_iface
);
1421 static ULONG WINAPI
timecode_Release(IWMReaderTimecode
*iface
)
1423 struct wm_reader
*reader
= impl_from_IWMReaderTimecode(iface
);
1425 return IWMProfile3_Release(&reader
->IWMProfile3_iface
);
1428 static HRESULT WINAPI
timecode_GetTimecodeRangeCount(IWMReaderTimecode
*iface
,
1429 WORD stream_number
, WORD
*count
)
1431 FIXME("iface %p, stream_number %u, count %p, stub!\n", iface
, stream_number
, count
);
1435 static HRESULT WINAPI
timecode_GetTimecodeRangeBounds(IWMReaderTimecode
*iface
,
1436 WORD stream_number
, WORD index
, DWORD
*start
, DWORD
*end
)
1438 FIXME("iface %p, stream_number %u, index %u, start %p, end %p, stub!\n",
1439 iface
, stream_number
, index
, start
, end
);
1443 static const IWMReaderTimecodeVtbl timecode_vtbl
=
1445 timecode_QueryInterface
,
1448 timecode_GetTimecodeRangeCount
,
1449 timecode_GetTimecodeRangeBounds
,
1452 static HRESULT
init_stream(struct wm_reader
*reader
, QWORD file_size
)
1454 struct wg_parser
*wg_parser
;
1458 if (!(wg_parser
= wg_parser_create(WG_PARSER_DECODEBIN
, false)))
1459 return E_OUTOFMEMORY
;
1461 reader
->wg_parser
= wg_parser
;
1462 reader
->read_thread_shutdown
= false;
1463 if (!(reader
->read_thread
= CreateThread(NULL
, 0, read_thread
, reader
, 0, NULL
)))
1466 goto out_destroy_parser
;
1469 if (FAILED(hr
= wg_parser_connect(reader
->wg_parser
, file_size
)))
1471 ERR("Failed to connect parser, hr %#lx.\n", hr
);
1472 goto out_shutdown_thread
;
1475 reader
->stream_count
= wg_parser_get_stream_count(reader
->wg_parser
);
1477 if (!(reader
->streams
= calloc(reader
->stream_count
, sizeof(*reader
->streams
))))
1480 goto out_disconnect_parser
;
1483 for (i
= 0; i
< reader
->stream_count
; ++i
)
1485 struct wm_stream
*stream
= &reader
->streams
[i
];
1487 stream
->wg_stream
= wg_parser_get_stream(reader
->wg_parser
, i
);
1488 stream
->reader
= reader
;
1490 stream
->selection
= WMT_ON
;
1491 wg_parser_stream_get_preferred_format(stream
->wg_stream
, &stream
->format
);
1492 if (stream
->format
.major_type
== WG_MAJOR_TYPE_AUDIO
)
1494 /* R.U.S.E enumerates available audio types, picks the first one it
1495 * likes, and then sets the wrong stream to that type. libav might
1496 * give us WG_AUDIO_FORMAT_F32LE by default, which will result in
1497 * the game incorrectly interpreting float data as integer.
1498 * Therefore just match native and always set our default format to
1500 stream
->format
.u
.audio
.format
= WG_AUDIO_FORMAT_S16LE
;
1502 else if (stream
->format
.major_type
== WG_MAJOR_TYPE_VIDEO
)
1504 /* Call of Juarez: Bound in Blood breaks if I420 is enumerated.
1505 * Some native decoders output I420, but the msmpeg4v3 decoder
1508 * Shadowgrounds provides wmv3 video and assumes that the initial
1509 * video type will be BGR. */
1510 stream
->format
.u
.video
.format
= WG_VIDEO_FORMAT_BGR
;
1512 wg_parser_stream_enable(stream
->wg_stream
, &stream
->format
);
1515 /* We probably discarded events because streams weren't enabled yet.
1516 * Now that they're all enabled seek back to the start again. */
1517 wg_parser_stream_seek(reader
->streams
[0].wg_stream
, 1.0, 0, 0,
1518 AM_SEEKING_AbsolutePositioning
, AM_SEEKING_NoPositioning
);
1522 out_disconnect_parser
:
1523 wg_parser_disconnect(reader
->wg_parser
);
1525 out_shutdown_thread
:
1526 reader
->read_thread_shutdown
= true;
1527 WaitForSingleObject(reader
->read_thread
, INFINITE
);
1528 CloseHandle(reader
->read_thread
);
1529 reader
->read_thread
= NULL
;
1532 wg_parser_destroy(reader
->wg_parser
);
1533 reader
->wg_parser
= NULL
;
1538 HRESULT
wm_reader_open_stream(struct wm_reader
*reader
, IStream
*stream
)
1543 if (FAILED(hr
= IStream_Stat(stream
, &stat
, STATFLAG_NONAME
)))
1545 ERR("Failed to stat stream, hr %#lx.\n", hr
);
1549 EnterCriticalSection(&reader
->cs
);
1551 IStream_AddRef(reader
->source_stream
= stream
);
1552 if (FAILED(hr
= init_stream(reader
, stat
.cbSize
.QuadPart
)))
1554 IStream_Release(stream
);
1555 reader
->source_stream
= NULL
;
1558 LeaveCriticalSection(&reader
->cs
);
1562 HRESULT
wm_reader_open_file(struct wm_reader
*reader
, const WCHAR
*filename
)
1568 if ((file
= CreateFileW(filename
, GENERIC_READ
, FILE_SHARE_READ
, NULL
,
1569 OPEN_EXISTING
, 0, NULL
)) == INVALID_HANDLE_VALUE
)
1571 ERR("Failed to open %s, error %lu.\n", debugstr_w(filename
), GetLastError());
1572 return HRESULT_FROM_WIN32(GetLastError());
1575 if (!GetFileSizeEx(file
, &size
))
1577 ERR("Failed to get the size of %s, error %lu.\n", debugstr_w(filename
), GetLastError());
1579 return HRESULT_FROM_WIN32(GetLastError());
1582 EnterCriticalSection(&reader
->cs
);
1584 reader
->file
= file
;
1586 if (FAILED(hr
= init_stream(reader
, size
.QuadPart
)))
1587 reader
->file
= NULL
;
1589 LeaveCriticalSection(&reader
->cs
);
1593 HRESULT
wm_reader_close(struct wm_reader
*reader
)
1595 EnterCriticalSection(&reader
->cs
);
1597 if (!reader
->wg_parser
)
1599 LeaveCriticalSection(&reader
->cs
);
1600 return NS_E_INVALID_REQUEST
;
1603 wg_parser_disconnect(reader
->wg_parser
);
1605 reader
->read_thread_shutdown
= true;
1606 WaitForSingleObject(reader
->read_thread
, INFINITE
);
1607 CloseHandle(reader
->read_thread
);
1608 reader
->read_thread
= NULL
;
1610 if (reader
->callback_advanced
)
1611 IWMReaderCallbackAdvanced_Release(reader
->callback_advanced
);
1612 reader
->callback_advanced
= NULL
;
1614 wg_parser_destroy(reader
->wg_parser
);
1615 reader
->wg_parser
= NULL
;
1617 if (reader
->source_stream
)
1618 IStream_Release(reader
->source_stream
);
1619 reader
->source_stream
= NULL
;
1621 CloseHandle(reader
->file
);
1622 reader
->file
= NULL
;
1624 LeaveCriticalSection(&reader
->cs
);
1628 struct wm_stream
*wm_reader_get_stream_by_stream_number(struct wm_reader
*reader
, WORD stream_number
)
1630 if (stream_number
&& stream_number
<= reader
->stream_count
)
1631 return &reader
->streams
[stream_number
- 1];
1632 WARN("Invalid stream number %u.\n", stream_number
);
1636 HRESULT
wm_reader_get_output_props(struct wm_reader
*reader
, DWORD output
, IWMOutputMediaProps
**props
)
1638 struct wm_stream
*stream
;
1640 EnterCriticalSection(&reader
->cs
);
1642 if (!(stream
= get_stream_by_output_number(reader
, output
)))
1644 LeaveCriticalSection(&reader
->cs
);
1645 return E_INVALIDARG
;
1648 *props
= output_props_create(&stream
->format
);
1649 LeaveCriticalSection(&reader
->cs
);
1650 return *props
? S_OK
: E_OUTOFMEMORY
;
1653 static const enum wg_video_format video_formats
[] =
1655 /* Try to prefer YUV formats over RGB ones. Most decoders output in the
1656 * YUV color space, and it's generally much less expensive for
1657 * videoconvert to do YUV -> YUV transformations. */
1658 WG_VIDEO_FORMAT_NV12
,
1659 WG_VIDEO_FORMAT_YV12
,
1660 WG_VIDEO_FORMAT_YUY2
,
1661 WG_VIDEO_FORMAT_UYVY
,
1662 WG_VIDEO_FORMAT_YVYU
,
1663 WG_VIDEO_FORMAT_BGRx
,
1664 WG_VIDEO_FORMAT_BGR
,
1665 WG_VIDEO_FORMAT_RGB16
,
1666 WG_VIDEO_FORMAT_RGB15
,
1669 HRESULT
wm_reader_get_output_format_count(struct wm_reader
*reader
, DWORD output
, DWORD
*count
)
1671 struct wm_stream
*stream
;
1672 struct wg_format format
;
1674 EnterCriticalSection(&reader
->cs
);
1676 if (!(stream
= get_stream_by_output_number(reader
, output
)))
1678 LeaveCriticalSection(&reader
->cs
);
1679 return E_INVALIDARG
;
1682 wg_parser_stream_get_preferred_format(stream
->wg_stream
, &format
);
1683 switch (format
.major_type
)
1685 case WG_MAJOR_TYPE_VIDEO
:
1686 *count
= ARRAY_SIZE(video_formats
);
1689 case WG_MAJOR_TYPE_MPEG1_AUDIO
:
1690 case WG_MAJOR_TYPE_WMA
:
1691 case WG_MAJOR_TYPE_H264
:
1692 FIXME("Format %u not implemented!\n", format
.major_type
);
1694 case WG_MAJOR_TYPE_AUDIO
:
1695 case WG_MAJOR_TYPE_UNKNOWN
:
1700 LeaveCriticalSection(&reader
->cs
);
1704 HRESULT
wm_reader_get_output_format(struct wm_reader
*reader
, DWORD output
,
1705 DWORD index
, IWMOutputMediaProps
**props
)
1707 struct wm_stream
*stream
;
1708 struct wg_format format
;
1710 EnterCriticalSection(&reader
->cs
);
1712 if (!(stream
= get_stream_by_output_number(reader
, output
)))
1714 LeaveCriticalSection(&reader
->cs
);
1715 return E_INVALIDARG
;
1718 wg_parser_stream_get_preferred_format(stream
->wg_stream
, &format
);
1720 switch (format
.major_type
)
1722 case WG_MAJOR_TYPE_VIDEO
:
1723 if (index
>= ARRAY_SIZE(video_formats
))
1725 LeaveCriticalSection(&reader
->cs
);
1726 return NS_E_INVALID_OUTPUT_FORMAT
;
1728 format
.u
.video
.format
= video_formats
[index
];
1731 case WG_MAJOR_TYPE_AUDIO
:
1734 LeaveCriticalSection(&reader
->cs
);
1735 return NS_E_INVALID_OUTPUT_FORMAT
;
1737 format
.u
.audio
.format
= WG_AUDIO_FORMAT_S16LE
;
1740 case WG_MAJOR_TYPE_MPEG1_AUDIO
:
1741 case WG_MAJOR_TYPE_WMA
:
1742 case WG_MAJOR_TYPE_H264
:
1743 FIXME("Format %u not implemented!\n", format
.major_type
);
1745 case WG_MAJOR_TYPE_UNKNOWN
:
1749 LeaveCriticalSection(&reader
->cs
);
1751 *props
= output_props_create(&format
);
1752 return *props
? S_OK
: E_OUTOFMEMORY
;
1755 HRESULT
wm_reader_set_output_props(struct wm_reader
*reader
, DWORD output
,
1756 IWMOutputMediaProps
*props_iface
)
1758 struct output_props
*props
= unsafe_impl_from_IWMOutputMediaProps(props_iface
);
1759 struct wg_format format
, pref_format
;
1760 struct wm_stream
*stream
;
1762 strmbase_dump_media_type(&props
->mt
);
1764 if (!amt_to_wg_format(&props
->mt
, &format
))
1766 ERR("Failed to convert media type to winegstreamer format.\n");
1770 EnterCriticalSection(&reader
->cs
);
1772 if (!(stream
= get_stream_by_output_number(reader
, output
)))
1774 LeaveCriticalSection(&reader
->cs
);
1775 return E_INVALIDARG
;
1778 wg_parser_stream_get_preferred_format(stream
->wg_stream
, &pref_format
);
1779 if (pref_format
.major_type
!= format
.major_type
)
1781 /* R.U.S.E sets the type of the wrong stream, apparently by accident. */
1782 LeaveCriticalSection(&reader
->cs
);
1783 WARN("Major types don't match; returning NS_E_INCOMPATIBLE_FORMAT.\n");
1784 return NS_E_INCOMPATIBLE_FORMAT
;
1787 stream
->format
= format
;
1788 wg_parser_stream_enable(stream
->wg_stream
, &format
);
1790 /* Re-decode any buffers that might have been generated with the old format.
1792 * FIXME: Seeking in-place will cause some buffers to be dropped.
1793 * Unfortunately, we can't really store the last received PTS and seek there
1794 * either: since seeks are inexact and we aren't guaranteed to receive
1795 * samples in order, some buffers might be duplicated or dropped anyway.
1796 * In order to really seamlessly allow for format changes, we need
1797 * cooperation from each individual GStreamer stream, to be able to tell
1798 * upstream exactly which buffers they need resent...
1800 * In all likelihood this function is being called not mid-stream but rather
1801 * while setting the stream up, before consuming any events. Accordingly
1802 * let's just seek back to the beginning. */
1803 wg_parser_stream_seek(reader
->streams
[0].wg_stream
, 1.0, reader
->start_time
, 0,
1804 AM_SEEKING_AbsolutePositioning
, AM_SEEKING_NoPositioning
);
1806 LeaveCriticalSection(&reader
->cs
);
1810 static const char *get_major_type_string(enum wg_major_type type
)
1814 case WG_MAJOR_TYPE_AUDIO
:
1816 case WG_MAJOR_TYPE_VIDEO
:
1818 case WG_MAJOR_TYPE_UNKNOWN
:
1820 case WG_MAJOR_TYPE_MPEG1_AUDIO
:
1821 return "mpeg1-audio";
1822 case WG_MAJOR_TYPE_WMA
:
1824 case WG_MAJOR_TYPE_H264
:
1831 /* Find the earliest buffer by PTS.
1833 * Native seems to behave similarly to this with the async reader, although our
1834 * unit tests show that it's not entirely consistent—some frames are received
1835 * slightly out of order. It's possible that one stream is being manually offset
1836 * to account for decoding latency.
1838 * The behaviour with the synchronous reader, when stream 0 is requested, seems
1839 * consistent with this hypothesis, but with a much larger offset—the video
1840 * stream seems to be "behind" by about 150 ms.
1842 * The main reason for doing this is that the video and audio stream probably
1843 * don't have quite the same "frame rate", and we don't want to force one stream
1844 * to decode faster just to keep up with the other. Delivering samples in PTS
1845 * order should avoid that problem. */
1846 static WORD
get_earliest_buffer(struct wm_reader
*reader
, struct wg_parser_buffer
*ret_buffer
)
1848 struct wg_parser_buffer buffer
;
1849 QWORD earliest_pts
= UI64_MAX
;
1850 WORD stream_number
= 0;
1853 for (i
= 0; i
< reader
->stream_count
; ++i
)
1855 struct wm_stream
*stream
= &reader
->streams
[i
];
1857 if (stream
->selection
== WMT_OFF
)
1860 if (!wg_parser_stream_get_buffer(stream
->wg_stream
, &buffer
))
1863 if (buffer
.has_pts
&& buffer
.pts
< earliest_pts
)
1865 stream_number
= i
+ 1;
1866 earliest_pts
= buffer
.pts
;
1867 *ret_buffer
= buffer
;
1871 return stream_number
;
1874 HRESULT
wm_reader_get_stream_sample(struct wm_reader
*reader
, WORD stream_number
,
1875 INSSBuffer
**ret_sample
, QWORD
*pts
, QWORD
*duration
, DWORD
*flags
, WORD
*ret_stream_number
)
1877 IWMReaderCallbackAdvanced
*callback_advanced
= reader
->callback_advanced
;
1878 struct wg_parser_stream
*wg_stream
;
1879 struct wg_parser_buffer wg_buffer
;
1880 struct wm_stream
*stream
;
1881 DWORD size
, capacity
;
1890 if (!(stream_number
= get_earliest_buffer(reader
, &wg_buffer
)))
1892 /* All streams are disabled or EOS. */
1893 return NS_E_NO_MORE_SAMPLES
;
1896 stream
= wm_reader_get_stream_by_stream_number(reader
, stream_number
);
1897 wg_stream
= stream
->wg_stream
;
1901 if (!(stream
= wm_reader_get_stream_by_stream_number(reader
, stream_number
)))
1903 WARN("Invalid stream number %u; returning E_INVALIDARG.\n", stream_number
);
1904 return E_INVALIDARG
;
1906 wg_stream
= stream
->wg_stream
;
1908 if (stream
->selection
== WMT_OFF
)
1910 WARN("Stream %u is deselected; returning NS_E_INVALID_REQUEST.\n", stream_number
);
1911 return NS_E_INVALID_REQUEST
;
1915 return NS_E_NO_MORE_SAMPLES
;
1917 if (!wg_parser_stream_get_buffer(wg_stream
, &wg_buffer
))
1920 TRACE("End of stream.\n");
1921 return NS_E_NO_MORE_SAMPLES
;
1925 TRACE("Got buffer for '%s' stream %p.\n", get_major_type_string(stream
->format
.major_type
), stream
);
1927 if (callback_advanced
&& stream
->read_compressed
&& stream
->allocate_stream
)
1929 if (FAILED(hr
= IWMReaderCallbackAdvanced_AllocateForStream(callback_advanced
,
1930 stream
->index
+ 1, wg_buffer
.size
, &sample
, NULL
)))
1932 ERR("Failed to allocate stream sample of %u bytes, hr %#lx.\n", wg_buffer
.size
, hr
);
1933 wg_parser_stream_release_buffer(wg_stream
);
1937 else if (callback_advanced
&& !stream
->read_compressed
&& stream
->allocate_output
)
1939 if (FAILED(hr
= IWMReaderCallbackAdvanced_AllocateForOutput(callback_advanced
,
1940 stream
->index
, wg_buffer
.size
, &sample
, NULL
)))
1942 ERR("Failed to allocate output sample of %u bytes, hr %#lx.\n", wg_buffer
.size
, hr
);
1943 wg_parser_stream_release_buffer(wg_stream
);
1949 struct buffer
*object
;
1951 /* FIXME: Should these be pooled? */
1952 if (!(object
= calloc(1, offsetof(struct buffer
, data
[wg_buffer
.size
]))))
1954 wg_parser_stream_release_buffer(wg_stream
);
1955 return E_OUTOFMEMORY
;
1958 object
->INSSBuffer_iface
.lpVtbl
= &buffer_vtbl
;
1959 object
->refcount
= 1;
1960 object
->capacity
= wg_buffer
.size
;
1962 TRACE("Created buffer %p.\n", object
);
1963 sample
= &object
->INSSBuffer_iface
;
1966 if (FAILED(hr
= INSSBuffer_GetBufferAndLength(sample
, &data
, &size
)))
1967 ERR("Failed to get data pointer, hr %#lx.\n", hr
);
1968 if (FAILED(hr
= INSSBuffer_GetMaxLength(sample
, &capacity
)))
1969 ERR("Failed to get capacity, hr %#lx.\n", hr
);
1970 if (wg_buffer
.size
> capacity
)
1971 ERR("Returned capacity %lu is less than requested capacity %u.\n", capacity
, wg_buffer
.size
);
1973 if (!wg_parser_stream_copy_buffer(wg_stream
, data
, 0, wg_buffer
.size
))
1975 /* The GStreamer pin has been flushed. */
1976 INSSBuffer_Release(sample
);
1980 if (FAILED(hr
= INSSBuffer_SetLength(sample
, wg_buffer
.size
)))
1981 ERR("Failed to set size %u, hr %#lx.\n", wg_buffer
.size
, hr
);
1983 wg_parser_stream_release_buffer(wg_stream
);
1985 if (!wg_buffer
.has_pts
)
1986 FIXME("Missing PTS.\n");
1987 if (!wg_buffer
.has_duration
)
1988 FIXME("Missing duration.\n");
1990 *pts
= wg_buffer
.pts
;
1991 *duration
= wg_buffer
.duration
;
1993 if (wg_buffer
.discontinuity
)
1994 *flags
|= WM_SF_DISCONTINUITY
;
1995 if (!wg_buffer
.delta
)
1996 *flags
|= WM_SF_CLEANPOINT
;
1998 *ret_sample
= sample
;
1999 *ret_stream_number
= stream_number
;
2004 void wm_reader_seek(struct wm_reader
*reader
, QWORD start
, LONGLONG duration
)
2008 EnterCriticalSection(&reader
->cs
);
2010 reader
->start_time
= start
;
2012 wg_parser_stream_seek(reader
->streams
[0].wg_stream
, 1.0, start
, start
+ duration
,
2013 AM_SEEKING_AbsolutePositioning
, duration
? AM_SEEKING_AbsolutePositioning
: AM_SEEKING_NoPositioning
);
2015 for (i
= 0; i
< reader
->stream_count
; ++i
)
2016 reader
->streams
[i
].eos
= false;
2018 LeaveCriticalSection(&reader
->cs
);
2021 HRESULT
wm_reader_set_streams_selected(struct wm_reader
*reader
, WORD count
,
2022 const WORD
*stream_numbers
, const WMT_STREAM_SELECTION
*selections
)
2024 struct wm_stream
*stream
;
2028 return E_INVALIDARG
;
2030 EnterCriticalSection(&reader
->cs
);
2032 for (i
= 0; i
< count
; ++i
)
2034 if (!(stream
= wm_reader_get_stream_by_stream_number(reader
, stream_numbers
[i
])))
2036 LeaveCriticalSection(&reader
->cs
);
2037 WARN("Invalid stream number %u; returning NS_E_INVALID_REQUEST.\n", stream_numbers
[i
]);
2038 return NS_E_INVALID_REQUEST
;
2042 for (i
= 0; i
< count
; ++i
)
2044 stream
= wm_reader_get_stream_by_stream_number(reader
, stream_numbers
[i
]);
2045 stream
->selection
= selections
[i
];
2046 if (selections
[i
] == WMT_OFF
)
2048 TRACE("Disabling stream %u.\n", stream_numbers
[i
]);
2049 wg_parser_stream_disable(stream
->wg_stream
);
2051 else if (selections
[i
] == WMT_ON
)
2053 if (selections
[i
] != WMT_ON
)
2054 FIXME("Ignoring selection %#x for stream %u; treating as enabled.\n",
2055 selections
[i
], stream_numbers
[i
]);
2056 TRACE("Enabling stream %u.\n", stream_numbers
[i
]);
2057 wg_parser_stream_enable(stream
->wg_stream
, &stream
->format
);
2061 LeaveCriticalSection(&reader
->cs
);
2065 HRESULT
wm_reader_get_stream_selection(struct wm_reader
*reader
,
2066 WORD stream_number
, WMT_STREAM_SELECTION
*selection
)
2068 struct wm_stream
*stream
;
2070 EnterCriticalSection(&reader
->cs
);
2072 if (!(stream
= wm_reader_get_stream_by_stream_number(reader
, stream_number
)))
2074 LeaveCriticalSection(&reader
->cs
);
2075 return E_INVALIDARG
;
2078 *selection
= stream
->selection
;
2080 LeaveCriticalSection(&reader
->cs
);
2084 HRESULT
wm_reader_set_allocate_for_output(struct wm_reader
*reader
, DWORD output
, BOOL allocate
)
2086 struct wm_stream
*stream
;
2088 EnterCriticalSection(&reader
->cs
);
2090 if (!(stream
= get_stream_by_output_number(reader
, output
)))
2092 LeaveCriticalSection(&reader
->cs
);
2093 return E_INVALIDARG
;
2096 stream
->allocate_output
= !!allocate
;
2098 LeaveCriticalSection(&reader
->cs
);
2102 HRESULT
wm_reader_set_allocate_for_stream(struct wm_reader
*reader
, WORD stream_number
, BOOL allocate
)
2104 struct wm_stream
*stream
;
2106 EnterCriticalSection(&reader
->cs
);
2108 if (!(stream
= wm_reader_get_stream_by_stream_number(reader
, stream_number
)))
2110 LeaveCriticalSection(&reader
->cs
);
2111 return E_INVALIDARG
;
2114 stream
->allocate_stream
= !!allocate
;
2116 LeaveCriticalSection(&reader
->cs
);
2120 HRESULT
wm_reader_set_read_compressed(struct wm_reader
*reader
, WORD stream_number
, BOOL compressed
)
2122 struct wm_stream
*stream
;
2124 EnterCriticalSection(&reader
->cs
);
2126 if (!(stream
= wm_reader_get_stream_by_stream_number(reader
, stream_number
)))
2128 LeaveCriticalSection(&reader
->cs
);
2129 return E_INVALIDARG
;
2132 stream
->read_compressed
= compressed
;
2134 LeaveCriticalSection(&reader
->cs
);
2138 HRESULT
wm_reader_get_max_stream_size(struct wm_reader
*reader
, WORD stream_number
, DWORD
*size
)
2140 struct wm_stream
*stream
;
2142 EnterCriticalSection(&reader
->cs
);
2144 if (!(stream
= wm_reader_get_stream_by_stream_number(reader
, stream_number
)))
2146 LeaveCriticalSection(&reader
->cs
);
2147 return E_INVALIDARG
;
2150 *size
= wg_format_get_max_size(&stream
->format
);
2152 LeaveCriticalSection(&reader
->cs
);
2156 void wm_reader_init(struct wm_reader
*reader
, const struct wm_reader_ops
*ops
)
2158 reader
->IWMHeaderInfo3_iface
.lpVtbl
= &header_info_vtbl
;
2159 reader
->IWMLanguageList_iface
.lpVtbl
= &language_list_vtbl
;
2160 reader
->IWMPacketSize2_iface
.lpVtbl
= &packet_size_vtbl
;
2161 reader
->IWMProfile3_iface
.lpVtbl
= &profile_vtbl
;
2162 reader
->IWMReaderPlaylistBurn_iface
.lpVtbl
= &playlist_vtbl
;
2163 reader
->IWMReaderTimecode_iface
.lpVtbl
= &timecode_vtbl
;
2164 reader
->refcount
= 1;
2167 InitializeCriticalSection(&reader
->cs
);
2168 reader
->cs
.DebugInfo
->Spare
[0] = (DWORD_PTR
)(__FILE__
": wm_reader.cs");
2171 void wm_reader_cleanup(struct wm_reader
*reader
)
2173 reader
->cs
.DebugInfo
->Spare
[0] = 0;
2174 DeleteCriticalSection(&reader
->cs
);