1 /* Copyright 2022 RĂ©mi Bernon for CodeWeavers
3 * This library is free software; you can redistribute it and/or
4 * modify it under the terms of the GNU Lesser General Public
5 * License as published by the Free Software Foundation; either
6 * version 2.1 of the License, or (at your option) any later version.
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * Lesser General Public License for more details.
13 * You should have received a copy of the GNU Lesser General Public
14 * License along with this library; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18 #include "gst_private.h"
23 #include "mfobjects.h"
24 #include "mftransform.h"
25 #include "wmcodecdsp.h"
28 #include "wine/debug.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(mfplat
);
31 WINE_DECLARE_DEBUG_CHANNEL(winediag
);
33 extern const GUID MEDIASUBTYPE_VC1S
;
35 DEFINE_GUID(MEDIASUBTYPE_WMV_Unknown
, 0x7ce12ca9,0xbfbf,0x43d9,0x9d,0x00,0x82,0xb8,0xed,0x54,0x31,0x6b);
44 static const GUID
*const wmv_decoder_input_types
[] =
51 &MEDIASUBTYPE_WMV_Unknown
,
57 static const struct decoder_type wmv_decoder_output_types
[] =
59 { &MEDIASUBTYPE_NV12
, 12, MAKEFOURCC('N', 'V', '1', '2') },
60 { &MEDIASUBTYPE_YV12
, 12, MAKEFOURCC('Y', 'V', '1', '2') },
61 { &MEDIASUBTYPE_IYUV
, 12, MAKEFOURCC('I', 'Y', 'U', 'V') },
62 { &MEDIASUBTYPE_I420
, 12, MAKEFOURCC('I', '4', '2', '0') },
63 { &MEDIASUBTYPE_YUY2
, 16, MAKEFOURCC('Y', 'U', 'Y', '2') },
64 { &MEDIASUBTYPE_UYVY
, 16, MAKEFOURCC('U', 'Y', 'V', 'Y') },
65 { &MEDIASUBTYPE_YVYU
, 16, MAKEFOURCC('Y', 'V', 'Y', 'U') },
66 { &MEDIASUBTYPE_NV11
, 12, MAKEFOURCC('N', 'V', '1', '1') },
67 { &MEDIASUBTYPE_RGB32
, 32, BI_RGB
},
68 { &MEDIASUBTYPE_RGB24
, 24, BI_RGB
},
69 { &MEDIASUBTYPE_RGB565
, 16, BI_BITFIELDS
},
70 { &MEDIASUBTYPE_RGB555
, 16, BI_RGB
},
71 { &MEDIASUBTYPE_RGB8
, 8, BI_RGB
},
76 IUnknown IUnknown_inner
;
77 IMFTransform IMFTransform_iface
;
78 IMediaObject IMediaObject_iface
;
79 IPropertyBag IPropertyBag_iface
;
80 IPropertyStore IPropertyStore_iface
;
84 struct wg_format input_format
;
85 struct wg_format output_format
;
88 struct wg_transform
*wg_transform
;
89 struct wg_sample_queue
*wg_sample_queue
;
92 static bool wg_format_is_set(struct wg_format
*format
)
94 return format
->major_type
!= WG_MAJOR_TYPE_UNKNOWN
;
97 static inline struct wmv_decoder
*impl_from_IUnknown(IUnknown
*iface
)
99 return CONTAINING_RECORD(iface
, struct wmv_decoder
, IUnknown_inner
);
102 static HRESULT WINAPI
unknown_QueryInterface(IUnknown
*iface
, REFIID iid
, void **out
)
104 struct wmv_decoder
*impl
= impl_from_IUnknown(iface
);
106 TRACE("iface %p, iid %s, out %p.\n", iface
, debugstr_guid(iid
), out
);
108 if (IsEqualGUID(iid
, &IID_IUnknown
))
109 *out
= &impl
->IUnknown_inner
;
110 else if (IsEqualGUID(iid
, &IID_IMFTransform
))
111 *out
= &impl
->IMFTransform_iface
;
112 else if (IsEqualGUID(iid
, &IID_IMediaObject
))
113 *out
= &impl
->IMediaObject_iface
;
114 else if (IsEqualIID(iid
, &IID_IPropertyBag
))
115 *out
= &impl
->IPropertyBag_iface
;
116 else if (IsEqualIID(iid
, &IID_IPropertyStore
))
117 *out
= &impl
->IPropertyStore_iface
;
121 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid
));
122 return E_NOINTERFACE
;
125 IUnknown_AddRef((IUnknown
*)*out
);
129 static ULONG WINAPI
unknown_AddRef(IUnknown
*iface
)
131 struct wmv_decoder
*impl
= impl_from_IUnknown(iface
);
132 ULONG refcount
= InterlockedIncrement(&impl
->refcount
);
134 TRACE("iface %p increasing refcount to %lu.\n", iface
, refcount
);
139 static ULONG WINAPI
unknown_Release(IUnknown
*iface
)
141 struct wmv_decoder
*impl
= impl_from_IUnknown(iface
);
142 ULONG refcount
= InterlockedDecrement(&impl
->refcount
);
144 TRACE("iface %p decreasing refcount to %lu.\n", iface
, refcount
);
148 if (impl
->wg_transform
)
149 wg_transform_destroy(impl
->wg_transform
);
150 wg_sample_queue_destroy(impl
->wg_sample_queue
);
157 static const IUnknownVtbl unknown_vtbl
=
159 unknown_QueryInterface
,
164 static struct wmv_decoder
*impl_from_IMFTransform(IMFTransform
*iface
)
166 return CONTAINING_RECORD(iface
, struct wmv_decoder
, IMFTransform_iface
);
169 static HRESULT WINAPI
transform_QueryInterface(IMFTransform
*iface
, REFIID iid
, void **out
)
171 return IUnknown_QueryInterface(impl_from_IMFTransform(iface
)->outer
, iid
, out
);
174 static ULONG WINAPI
transform_AddRef(IMFTransform
*iface
)
176 return IUnknown_AddRef(impl_from_IMFTransform(iface
)->outer
);
179 static ULONG WINAPI
transform_Release(IMFTransform
*iface
)
181 return IUnknown_Release(impl_from_IMFTransform(iface
)->outer
);
184 static HRESULT WINAPI
transform_GetStreamLimits(IMFTransform
*iface
, DWORD
*input_minimum
,
185 DWORD
*input_maximum
, DWORD
*output_minimum
, DWORD
*output_maximum
)
187 TRACE("iface %p, input_minimum %p, input_maximum %p, output_minimum %p, output_maximum %p.\n",
188 iface
, input_minimum
, input_maximum
, output_minimum
, output_maximum
);
189 *input_minimum
= *input_maximum
= *output_minimum
= *output_maximum
= 1;
193 static HRESULT WINAPI
transform_GetStreamCount(IMFTransform
*iface
, DWORD
*inputs
, DWORD
*outputs
)
195 TRACE("iface %p, inputs %p, outputs %p.\n", iface
, inputs
, outputs
);
196 *inputs
= *outputs
= 1;
200 static HRESULT WINAPI
transform_GetStreamIDs(IMFTransform
*iface
, DWORD input_size
, DWORD
*inputs
,
201 DWORD output_size
, DWORD
*outputs
)
203 TRACE("iface %p, input_size %lu, inputs %p, output_size %lu, outputs %p.\n", iface
,
204 input_size
, inputs
, output_size
, outputs
);
208 static HRESULT WINAPI
transform_GetInputStreamInfo(IMFTransform
*iface
, DWORD id
, MFT_INPUT_STREAM_INFO
*info
)
210 FIXME("iface %p, id %#lx, info %p stub!\n", iface
, id
, info
);
214 static HRESULT WINAPI
transform_GetOutputStreamInfo(IMFTransform
*iface
, DWORD id
, MFT_OUTPUT_STREAM_INFO
*info
)
216 FIXME("iface %p, id %#lx, info %p stub!\n", iface
, id
, info
);
220 static HRESULT WINAPI
transform_GetAttributes(IMFTransform
*iface
, IMFAttributes
**attributes
)
222 FIXME("iface %p, attributes %p stub!\n", iface
, attributes
);
226 static HRESULT WINAPI
transform_GetInputStreamAttributes(IMFTransform
*iface
, DWORD id
, IMFAttributes
**attributes
)
228 TRACE("iface %p, id %#lx, attributes %p.\n", iface
, id
, attributes
);
232 static HRESULT WINAPI
transform_GetOutputStreamAttributes(IMFTransform
*iface
, DWORD id
, IMFAttributes
**attributes
)
234 FIXME("iface %p, id %#lx, attributes %p stub!\n", iface
, id
, attributes
);
238 static HRESULT WINAPI
transform_DeleteInputStream(IMFTransform
*iface
, DWORD id
)
240 TRACE("iface %p, id %#lx.\n", iface
, id
);
244 static HRESULT WINAPI
transform_AddInputStreams(IMFTransform
*iface
, DWORD streams
, DWORD
*ids
)
246 TRACE("iface %p, streams %lu, ids %p.\n", iface
, streams
, ids
);
250 static HRESULT WINAPI
transform_GetInputAvailableType(IMFTransform
*iface
, DWORD id
, DWORD index
,
253 FIXME("iface %p, id %#lx, index %lu, type %p stub!\n", iface
, id
, index
, type
);
257 static HRESULT WINAPI
transform_GetOutputAvailableType(IMFTransform
*iface
, DWORD id
, DWORD index
,
260 FIXME("iface %p, id %#lx, index %lu, type %p stub!\n", iface
, id
, index
, type
);
264 static HRESULT WINAPI
transform_SetInputType(IMFTransform
*iface
, DWORD id
, IMFMediaType
*type
, DWORD flags
)
266 FIXME("iface %p, id %#lx, type %p, flags %#lx stub!\n", iface
, id
, type
, flags
);
270 static HRESULT WINAPI
transform_SetOutputType(IMFTransform
*iface
, DWORD id
, IMFMediaType
*type
, DWORD flags
)
272 FIXME("iface %p, id %#lx, type %p, flags %#lx stub!\n", iface
, id
, type
, flags
);
276 static HRESULT WINAPI
transform_GetInputCurrentType(IMFTransform
*iface
, DWORD id
, IMFMediaType
**type
)
278 FIXME("iface %p, id %#lx, type %p stub!\n", iface
, id
, type
);
282 static HRESULT WINAPI
transform_GetOutputCurrentType(IMFTransform
*iface
, DWORD id
, IMFMediaType
**type
)
284 FIXME("iface %p, id %#lx, type %p stub!\n", iface
, id
, type
);
288 static HRESULT WINAPI
transform_GetInputStatus(IMFTransform
*iface
, DWORD id
, DWORD
*flags
)
290 FIXME("iface %p, id %#lx, flags %p stub!\n", iface
, id
, flags
);
294 static HRESULT WINAPI
transform_GetOutputStatus(IMFTransform
*iface
, DWORD
*flags
)
296 FIXME("iface %p, flags %p stub!\n", iface
, flags
);
300 static HRESULT WINAPI
transform_SetOutputBounds(IMFTransform
*iface
, LONGLONG lower
, LONGLONG upper
)
302 TRACE("iface %p, lower %I64d, upper %I64d.\n", iface
, lower
, upper
);
306 static HRESULT WINAPI
transform_ProcessEvent(IMFTransform
*iface
, DWORD id
, IMFMediaEvent
*event
)
308 FIXME("iface %p, id %#lx, event %p stub!\n", iface
, id
, event
);
312 static HRESULT WINAPI
transform_ProcessMessage(IMFTransform
*iface
, MFT_MESSAGE_TYPE message
, ULONG_PTR param
)
314 FIXME("iface %p, message %#x, param %#Ix stub!\n", iface
, message
, param
);
318 static HRESULT WINAPI
transform_ProcessInput(IMFTransform
*iface
, DWORD id
, IMFSample
*sample
, DWORD flags
)
320 FIXME("iface %p, id %#lx, sample %p, flags %#lx stub!\n", iface
, id
, sample
, flags
);
324 static HRESULT WINAPI
transform_ProcessOutput(IMFTransform
*iface
, DWORD flags
, DWORD count
,
325 MFT_OUTPUT_DATA_BUFFER
*samples
, DWORD
*status
)
327 FIXME("iface %p, flags %#lx, count %lu, samples %p, status %p stub!\n", iface
, flags
, count
, samples
, status
);
331 static const IMFTransformVtbl transform_vtbl
=
333 transform_QueryInterface
,
336 transform_GetStreamLimits
,
337 transform_GetStreamCount
,
338 transform_GetStreamIDs
,
339 transform_GetInputStreamInfo
,
340 transform_GetOutputStreamInfo
,
341 transform_GetAttributes
,
342 transform_GetInputStreamAttributes
,
343 transform_GetOutputStreamAttributes
,
344 transform_DeleteInputStream
,
345 transform_AddInputStreams
,
346 transform_GetInputAvailableType
,
347 transform_GetOutputAvailableType
,
348 transform_SetInputType
,
349 transform_SetOutputType
,
350 transform_GetInputCurrentType
,
351 transform_GetOutputCurrentType
,
352 transform_GetInputStatus
,
353 transform_GetOutputStatus
,
354 transform_SetOutputBounds
,
355 transform_ProcessEvent
,
356 transform_ProcessMessage
,
357 transform_ProcessInput
,
358 transform_ProcessOutput
,
361 static inline struct wmv_decoder
*impl_from_IMediaObject(IMediaObject
*iface
)
363 return CONTAINING_RECORD(iface
, struct wmv_decoder
, IMediaObject_iface
);
366 static HRESULT WINAPI
media_object_QueryInterface(IMediaObject
*iface
, REFIID iid
, void **obj
)
368 return IUnknown_QueryInterface(impl_from_IMediaObject(iface
)->outer
, iid
, obj
);
371 static ULONG WINAPI
media_object_AddRef(IMediaObject
*iface
)
373 return IUnknown_AddRef(impl_from_IMediaObject(iface
)->outer
);
376 static ULONG WINAPI
media_object_Release(IMediaObject
*iface
)
378 return IUnknown_Release(impl_from_IMediaObject(iface
)->outer
);
381 static HRESULT WINAPI
media_object_GetStreamCount(IMediaObject
*iface
, DWORD
*input
, DWORD
*output
)
383 TRACE("iface %p, input %p, output %p.\n", iface
, input
, output
);
385 if (!input
|| !output
)
388 *input
= *output
= 1;
393 static HRESULT WINAPI
media_object_GetInputStreamInfo(IMediaObject
*iface
, DWORD index
, DWORD
*flags
)
395 FIXME("iface %p, index %lu, flags %p stub!\n", iface
, index
, flags
);
399 static HRESULT WINAPI
media_object_GetOutputStreamInfo(IMediaObject
*iface
, DWORD index
, DWORD
*flags
)
401 FIXME("iface %p, index %lu, flags %p stub!\n", iface
, index
, flags
);
405 static HRESULT WINAPI
media_object_GetInputType(IMediaObject
*iface
, DWORD index
, DWORD type_index
,
406 DMO_MEDIA_TYPE
*type
)
408 TRACE("iface %p, index %lu, type_index %lu, type %p.\n", iface
, index
, type_index
, type
);
411 return DMO_E_INVALIDSTREAMINDEX
;
412 if (type_index
>= ARRAY_SIZE(wmv_decoder_input_types
))
413 return DMO_E_NO_MORE_ITEMS
;
417 memset(type
, 0, sizeof(*type
));
418 type
->majortype
= MFMediaType_Video
;
419 type
->subtype
= *wmv_decoder_input_types
[type_index
];
420 type
->bFixedSizeSamples
= FALSE
;
421 type
->bTemporalCompression
= TRUE
;
422 type
->lSampleSize
= 0;
427 static HRESULT WINAPI
media_object_GetOutputType(IMediaObject
*iface
, DWORD index
, DWORD type_index
,
428 DMO_MEDIA_TYPE
*type
)
430 struct wmv_decoder
*decoder
= impl_from_IMediaObject(iface
);
431 VIDEOINFOHEADER
*info
;
437 TRACE("iface %p, index %lu, type_index %lu, type %p.\n", iface
, index
, type_index
, type
);
440 return DMO_E_INVALIDSTREAMINDEX
;
441 if (type_index
>= ARRAY_SIZE(wmv_decoder_output_types
))
442 return DMO_E_NO_MORE_ITEMS
;
445 if (!wg_format_is_set(&decoder
->input_format
))
446 return DMO_E_TYPE_NOT_SET
;
448 width
= decoder
->input_format
.u
.video_wmv
.width
;
449 height
= abs(decoder
->input_format
.u
.video_wmv
.height
);
450 subtype
= wmv_decoder_output_types
[type_index
].subtype
;
451 if (FAILED(hr
= MFCalculateImageSize(subtype
, width
, height
, &image_size
)))
453 FIXME("Failed to get image size of subtype %s.\n", debugstr_guid(subtype
));
457 memset(type
, 0, sizeof(*type
));
458 type
->majortype
= MFMediaType_Video
;
459 type
->subtype
= *subtype
;
460 type
->bFixedSizeSamples
= TRUE
;
461 type
->bTemporalCompression
= FALSE
;
462 type
->lSampleSize
= image_size
;
463 type
->formattype
= FORMAT_VideoInfo
;
464 type
->cbFormat
= sizeof(VIDEOINFOHEADER
);
465 type
->pbFormat
= CoTaskMemAlloc(type
->cbFormat
);
466 memset(type
->pbFormat
, 0, type
->cbFormat
);
468 info
= (VIDEOINFOHEADER
*)type
->pbFormat
;
469 info
->rcSource
.right
= width
;
470 info
->rcSource
.bottom
= height
;
471 info
->rcTarget
.right
= width
;
472 info
->rcTarget
.bottom
= height
;
473 info
->bmiHeader
.biSize
= sizeof(info
->bmiHeader
);
474 info
->bmiHeader
.biWidth
= width
;
475 info
->bmiHeader
.biHeight
= height
;
476 info
->bmiHeader
.biPlanes
= 1;
477 info
->bmiHeader
.biBitCount
= wmv_decoder_output_types
[type_index
].bpp
;
478 info
->bmiHeader
.biCompression
= wmv_decoder_output_types
[type_index
].compression
;
479 info
->bmiHeader
.biSizeImage
= image_size
;
484 static HRESULT WINAPI
media_object_SetInputType(IMediaObject
*iface
, DWORD index
,
485 const DMO_MEDIA_TYPE
*type
, DWORD flags
)
487 struct wmv_decoder
*decoder
= impl_from_IMediaObject(iface
);
488 struct wg_format wg_format
;
491 TRACE("iface %p, index %lu, type %p, flags %#lx.\n", iface
, index
, type
, flags
);
494 return DMO_E_INVALIDSTREAMINDEX
;
498 if (flags
& DMO_SET_TYPEF_CLEAR
)
500 memset(&decoder
->input_format
, 0, sizeof(decoder
->input_format
));
501 if (decoder
->wg_transform
)
503 wg_transform_destroy(decoder
->wg_transform
);
504 decoder
->wg_transform
= NULL
;
508 return DMO_E_TYPE_NOT_ACCEPTED
;
511 if (!IsEqualGUID(&type
->majortype
, &MEDIATYPE_Video
))
512 return DMO_E_TYPE_NOT_ACCEPTED
;
514 for (i
= 0; i
< ARRAY_SIZE(wmv_decoder_input_types
); ++i
)
515 if (IsEqualGUID(&type
->subtype
, wmv_decoder_input_types
[i
]))
517 if (i
== ARRAY_SIZE(wmv_decoder_input_types
))
518 return DMO_E_TYPE_NOT_ACCEPTED
;
520 if (!amt_to_wg_format((const AM_MEDIA_TYPE
*)type
, &wg_format
))
521 return DMO_E_TYPE_NOT_ACCEPTED
;
522 assert(wg_format
.major_type
== WG_MAJOR_TYPE_VIDEO_WMV
);
523 wg_format
.u
.video_wmv
.fps_n
= 0;
524 wg_format
.u
.video_wmv
.fps_d
= 0;
526 if (flags
& DMO_SET_TYPEF_TEST_ONLY
)
529 decoder
->input_format
= wg_format
;
530 if (decoder
->wg_transform
)
532 wg_transform_destroy(decoder
->wg_transform
);
533 decoder
->wg_transform
= NULL
;
539 static HRESULT WINAPI
media_object_SetOutputType(IMediaObject
*iface
, DWORD index
,
540 const DMO_MEDIA_TYPE
*type
, DWORD flags
)
542 struct wmv_decoder
*decoder
= impl_from_IMediaObject(iface
);
543 struct wg_transform_attrs attrs
= {0};
544 struct wg_format wg_format
;
547 TRACE("iface %p, index %lu, type %p, flags %#lx,\n", iface
, index
, type
, flags
);
550 return DMO_E_INVALIDSTREAMINDEX
;
554 if (flags
& DMO_SET_TYPEF_CLEAR
)
556 memset(&decoder
->output_format
, 0, sizeof(decoder
->output_format
));
557 if (decoder
->wg_transform
)
559 wg_transform_destroy(decoder
->wg_transform
);
560 decoder
->wg_transform
= NULL
;
567 if (!wg_format_is_set(&decoder
->input_format
))
568 return DMO_E_TYPE_NOT_SET
;
570 if (!IsEqualGUID(&type
->majortype
, &MEDIATYPE_Video
))
571 return DMO_E_TYPE_NOT_ACCEPTED
;
573 for (i
= 0; i
< ARRAY_SIZE(wmv_decoder_output_types
); ++i
)
574 if (IsEqualGUID(&type
->subtype
, wmv_decoder_output_types
[i
].subtype
))
576 if (i
== ARRAY_SIZE(wmv_decoder_output_types
))
577 return DMO_E_TYPE_NOT_ACCEPTED
;
579 if (!amt_to_wg_format((const AM_MEDIA_TYPE
*)type
, &wg_format
))
580 return DMO_E_TYPE_NOT_ACCEPTED
;
581 assert(wg_format
.major_type
== WG_MAJOR_TYPE_VIDEO
);
582 wg_format
.u
.video
.fps_n
= 0;
583 wg_format
.u
.video
.fps_d
= 0;
585 if (flags
& DMO_SET_TYPEF_TEST_ONLY
)
588 decoder
->output_subtype
= type
->subtype
;
589 decoder
->output_format
= wg_format
;
591 /* Set up wg_transform. */
592 if (decoder
->wg_transform
)
594 wg_transform_destroy(decoder
->wg_transform
);
595 decoder
->wg_transform
= NULL
;
597 if (!(decoder
->wg_transform
= wg_transform_create(&decoder
->input_format
, &decoder
->output_format
, &attrs
)))
603 static HRESULT WINAPI
media_object_GetInputCurrentType(IMediaObject
*iface
, DWORD index
, DMO_MEDIA_TYPE
*type
)
605 FIXME("iface %p, index %lu, type %p stub!\n", iface
, index
, type
);
609 static HRESULT WINAPI
media_object_GetOutputCurrentType(IMediaObject
*iface
, DWORD index
, DMO_MEDIA_TYPE
*type
)
611 FIXME("iface %p, index %lu, type %p stub!\n", iface
, index
, type
);
615 static HRESULT WINAPI
media_object_GetInputSizeInfo(IMediaObject
*iface
, DWORD index
, DWORD
*size
,
616 DWORD
*lookahead
, DWORD
*alignment
)
618 FIXME("iface %p, index %lu, size %p, lookahead %p, alignment %p stub!\n", iface
, index
, size
,
619 lookahead
, alignment
);
623 static HRESULT WINAPI
media_object_GetOutputSizeInfo(IMediaObject
*iface
, DWORD index
, DWORD
*size
, DWORD
*alignment
)
625 struct wmv_decoder
*decoder
= impl_from_IMediaObject(iface
);
628 TRACE("iface %p, index %lu, size %p, alignment %p.\n", iface
, index
, size
, alignment
);
631 return DMO_E_INVALIDSTREAMINDEX
;
632 if (!wg_format_is_set(&decoder
->output_format
))
633 return DMO_E_TYPE_NOT_SET
;
635 if (FAILED(hr
= MFCalculateImageSize(&decoder
->output_subtype
,
636 decoder
->output_format
.u
.video
.width
, abs(decoder
->output_format
.u
.video
.height
), (UINT32
*)size
)))
638 FIXME("Failed to get image size of subtype %s.\n", debugstr_guid(&decoder
->output_subtype
));
646 static HRESULT WINAPI
media_object_GetInputMaxLatency(IMediaObject
*iface
, DWORD index
, REFERENCE_TIME
*latency
)
648 FIXME("iface %p, index %lu, latency %p stub!\n", iface
, index
, latency
);
652 static HRESULT WINAPI
media_object_SetInputMaxLatency(IMediaObject
*iface
, DWORD index
, REFERENCE_TIME latency
)
654 FIXME("iface %p, index %lu, latency %s stub!\n", iface
, index
, wine_dbgstr_longlong(latency
));
658 static HRESULT WINAPI
media_object_Flush(IMediaObject
*iface
)
660 FIXME("iface %p stub!\n", iface
);
664 static HRESULT WINAPI
media_object_Discontinuity(IMediaObject
*iface
, DWORD index
)
666 TRACE("iface %p, index %lu.\n", iface
, index
);
669 return DMO_E_INVALIDSTREAMINDEX
;
674 static HRESULT WINAPI
media_object_AllocateStreamingResources(IMediaObject
*iface
)
676 FIXME("iface %p stub!\n", iface
);
680 static HRESULT WINAPI
media_object_FreeStreamingResources(IMediaObject
*iface
)
682 FIXME("iface %p stub!\n", iface
);
686 static HRESULT WINAPI
media_object_GetInputStatus(IMediaObject
*iface
, DWORD index
, DWORD
*flags
)
688 TRACE("iface %p, index %lu, flags %p.\n", iface
, index
, flags
);
691 return DMO_E_INVALIDSTREAMINDEX
;
695 *flags
= DMO_INPUT_STATUSF_ACCEPT_DATA
;
700 static HRESULT WINAPI
media_object_ProcessInput(IMediaObject
*iface
, DWORD index
,
701 IMediaBuffer
*buffer
, DWORD flags
, REFERENCE_TIME timestamp
, REFERENCE_TIME timelength
)
703 struct wmv_decoder
*decoder
= impl_from_IMediaObject(iface
);
705 TRACE("iface %p, index %lu, buffer %p, flags %#lx, timestamp %s, timelength %s.\n", iface
,
706 index
, buffer
, flags
, wine_dbgstr_longlong(timestamp
), wine_dbgstr_longlong(timelength
));
708 if (!decoder
->wg_transform
)
709 return DMO_E_TYPE_NOT_SET
;
711 return wg_transform_push_dmo(decoder
->wg_transform
, buffer
, flags
, timestamp
, timelength
, decoder
->wg_sample_queue
);
714 static HRESULT WINAPI
media_object_ProcessOutput(IMediaObject
*iface
, DWORD flags
, DWORD count
,
715 DMO_OUTPUT_DATA_BUFFER
*buffers
, DWORD
*status
)
717 struct wmv_decoder
*decoder
= impl_from_IMediaObject(iface
);
720 TRACE("iface %p, flags %#lx, count %lu, buffers %p, status %p.\n", iface
, flags
, count
, buffers
, status
);
722 if (!decoder
->wg_transform
)
723 return DMO_E_TYPE_NOT_SET
;
725 if ((hr
= wg_transform_read_dmo(decoder
->wg_transform
, buffers
)) == MF_E_TRANSFORM_STREAM_CHANGE
)
726 hr
= wg_transform_read_dmo(decoder
->wg_transform
, buffers
);
729 wg_sample_queue_flush(decoder
->wg_sample_queue
, false);
734 static HRESULT WINAPI
media_object_Lock(IMediaObject
*iface
, LONG lock
)
736 FIXME("iface %p, lock %ld stub!\n", iface
, lock
);
740 static const IMediaObjectVtbl media_object_vtbl
=
742 media_object_QueryInterface
,
744 media_object_Release
,
745 media_object_GetStreamCount
,
746 media_object_GetInputStreamInfo
,
747 media_object_GetOutputStreamInfo
,
748 media_object_GetInputType
,
749 media_object_GetOutputType
,
750 media_object_SetInputType
,
751 media_object_SetOutputType
,
752 media_object_GetInputCurrentType
,
753 media_object_GetOutputCurrentType
,
754 media_object_GetInputSizeInfo
,
755 media_object_GetOutputSizeInfo
,
756 media_object_GetInputMaxLatency
,
757 media_object_SetInputMaxLatency
,
759 media_object_Discontinuity
,
760 media_object_AllocateStreamingResources
,
761 media_object_FreeStreamingResources
,
762 media_object_GetInputStatus
,
763 media_object_ProcessInput
,
764 media_object_ProcessOutput
,
768 static inline struct wmv_decoder
*impl_from_IPropertyBag(IPropertyBag
*iface
)
770 return CONTAINING_RECORD(iface
, struct wmv_decoder
, IPropertyBag_iface
);
773 static HRESULT WINAPI
property_bag_QueryInterface(IPropertyBag
*iface
, REFIID iid
, void **out
)
775 return IUnknown_QueryInterface(impl_from_IPropertyBag(iface
)->outer
, iid
, out
);
778 static ULONG WINAPI
property_bag_AddRef(IPropertyBag
*iface
)
780 return IUnknown_AddRef(impl_from_IPropertyBag(iface
)->outer
);
783 static ULONG WINAPI
property_bag_Release(IPropertyBag
*iface
)
785 return IUnknown_Release(impl_from_IPropertyBag(iface
)->outer
);
788 static HRESULT WINAPI
property_bag_Read(IPropertyBag
*iface
, const WCHAR
*prop_name
, VARIANT
*value
,
789 IErrorLog
*error_log
)
791 FIXME("iface %p, prop_name %s, value %p, error_log %p stub!\n", iface
, debugstr_w(prop_name
), value
, error_log
);
795 static HRESULT WINAPI
property_bag_Write(IPropertyBag
*iface
, const WCHAR
*prop_name
, VARIANT
*value
)
797 FIXME("iface %p, prop_name %s, value %p stub!\n", iface
, debugstr_w(prop_name
), value
);
801 static const IPropertyBagVtbl property_bag_vtbl
=
803 property_bag_QueryInterface
,
805 property_bag_Release
,
810 static inline struct wmv_decoder
*impl_from_IPropertyStore(IPropertyStore
*iface
)
812 return CONTAINING_RECORD(iface
, struct wmv_decoder
, IPropertyStore_iface
);
815 static HRESULT WINAPI
property_store_QueryInterface(IPropertyStore
*iface
, REFIID iid
, void **out
)
817 return IUnknown_QueryInterface(impl_from_IPropertyStore(iface
)->outer
, iid
, out
);
820 static ULONG WINAPI
property_store_AddRef(IPropertyStore
*iface
)
822 return IUnknown_AddRef(impl_from_IPropertyStore(iface
)->outer
);
825 static ULONG WINAPI
property_store_Release(IPropertyStore
*iface
)
827 return IUnknown_Release(impl_from_IPropertyStore(iface
)->outer
);
830 static HRESULT WINAPI
property_store_GetCount(IPropertyStore
*iface
, DWORD
*count
)
832 FIXME("iface %p, count %p stub!\n", iface
, count
);
836 static HRESULT WINAPI
property_store_GetAt(IPropertyStore
*iface
, DWORD index
, PROPERTYKEY
*key
)
838 FIXME("iface %p, index %lu, key %p stub!\n", iface
, index
, key
);
842 static HRESULT WINAPI
property_store_GetValue(IPropertyStore
*iface
, REFPROPERTYKEY key
, PROPVARIANT
*value
)
844 FIXME("iface %p, key %p, value %p stub!\n", iface
, key
, value
);
848 static HRESULT WINAPI
property_store_SetValue(IPropertyStore
*iface
, REFPROPERTYKEY key
, REFPROPVARIANT value
)
850 FIXME("iface %p, key %p, value %p stub!\n", iface
, key
, value
);
854 static HRESULT WINAPI
property_store_Commit(IPropertyStore
*iface
)
856 FIXME("iface %p stub!\n", iface
);
860 static const IPropertyStoreVtbl property_store_vtbl
=
862 property_store_QueryInterface
,
863 property_store_AddRef
,
864 property_store_Release
,
865 property_store_GetCount
,
866 property_store_GetAt
,
867 property_store_GetValue
,
868 property_store_SetValue
,
869 property_store_Commit
,
872 HRESULT
wmv_decoder_create(IUnknown
*outer
, IUnknown
**out
)
874 static const struct wg_format input_format
=
876 .major_type
= WG_MAJOR_TYPE_VIDEO_WMV
,
877 .u
.video_wmv
.format
= WG_WMV_VIDEO_FORMAT_WMV3
,
879 static const struct wg_format output_format
=
881 .major_type
= WG_MAJOR_TYPE_VIDEO
,
884 .format
= WG_VIDEO_FORMAT_NV12
,
889 struct wg_transform_attrs attrs
= {0};
890 struct wg_transform
*transform
;
891 struct wmv_decoder
*decoder
;
894 TRACE("outer %p, out %p.\n", outer
, out
);
896 if (!(transform
= wg_transform_create(&input_format
, &output_format
, &attrs
)))
898 ERR_(winediag
)("GStreamer doesn't support WMV decoding, please install appropriate plugins.\n");
901 wg_transform_destroy(transform
);
903 if (!(decoder
= calloc(1, sizeof(*decoder
))))
904 return E_OUTOFMEMORY
;
905 if (FAILED(hr
= wg_sample_queue_create(&decoder
->wg_sample_queue
)))
911 decoder
->IUnknown_inner
.lpVtbl
= &unknown_vtbl
;
912 decoder
->IMFTransform_iface
.lpVtbl
= &transform_vtbl
;
913 decoder
->IMediaObject_iface
.lpVtbl
= &media_object_vtbl
;
914 decoder
->IPropertyBag_iface
.lpVtbl
= &property_bag_vtbl
;
915 decoder
->IPropertyStore_iface
.lpVtbl
= &property_store_vtbl
;
916 decoder
->refcount
= 1;
917 decoder
->outer
= outer
? outer
: &decoder
->IUnknown_inner
;
919 *out
= &decoder
->IUnknown_inner
;
920 TRACE("Created %p\n", *out
);