based on !5541
-- v4: winegstreamer/video_decoder: Use video_decoder to implement wmv decoder.
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/mf/tests/transform.c | 20 ++++++++++---------- dlls/winegstreamer/mfplat.c | 4 ++++ dlls/winegstreamer/video_decoder.c | 16 ++++++++++++++++ 3 files changed, 30 insertions(+), 10 deletions(-)
diff --git a/dlls/mf/tests/transform.c b/dlls/mf/tests/transform.c index 6a4653cccee..d1d52d62458 100644 --- a/dlls/mf/tests/transform.c +++ b/dlls/mf/tests/transform.c @@ -4090,8 +4090,8 @@ static void test_h264_decoder(void) ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1), ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1), ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16), - ATTR_BLOB(MF_MT_GEOMETRIC_APERTURE, &actual_aperture, 16, .todo = TRUE), - ATTR_BLOB(MF_MT_PAN_SCAN_APERTURE, &actual_aperture, 16, .todo = TRUE), + ATTR_BLOB(MF_MT_GEOMETRIC_APERTURE, &actual_aperture, 16), + ATTR_BLOB(MF_MT_PAN_SCAN_APERTURE, &actual_aperture, 16), }, { ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), @@ -4106,8 +4106,8 @@ static void test_h264_decoder(void) ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1), ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1), ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16), - ATTR_BLOB(MF_MT_GEOMETRIC_APERTURE, &actual_aperture, 16, .todo = TRUE), - ATTR_BLOB(MF_MT_PAN_SCAN_APERTURE, &actual_aperture, 16, .todo = TRUE), + ATTR_BLOB(MF_MT_GEOMETRIC_APERTURE, &actual_aperture, 16), + ATTR_BLOB(MF_MT_PAN_SCAN_APERTURE, &actual_aperture, 16), }, { ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), @@ -4122,8 +4122,8 @@ static void test_h264_decoder(void) ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1), ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1), ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16), - ATTR_BLOB(MF_MT_GEOMETRIC_APERTURE, &actual_aperture, 16, .todo = TRUE), - ATTR_BLOB(MF_MT_PAN_SCAN_APERTURE, &actual_aperture, 16, .todo = TRUE), + ATTR_BLOB(MF_MT_GEOMETRIC_APERTURE, &actual_aperture, 16), + ATTR_BLOB(MF_MT_PAN_SCAN_APERTURE, &actual_aperture, 16), }, { ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), @@ -4138,8 +4138,8 @@ static void test_h264_decoder(void) ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1), ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1), ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16), - ATTR_BLOB(MF_MT_GEOMETRIC_APERTURE, &actual_aperture, 16, .todo = TRUE), - ATTR_BLOB(MF_MT_PAN_SCAN_APERTURE, &actual_aperture, 16, .todo = TRUE), + ATTR_BLOB(MF_MT_GEOMETRIC_APERTURE, &actual_aperture, 16), + ATTR_BLOB(MF_MT_PAN_SCAN_APERTURE, &actual_aperture, 16), }, { ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), @@ -4154,8 +4154,8 @@ static void test_h264_decoder(void) ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1), ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1), ATTR_BLOB(MF_MT_MINIMUM_DISPLAY_APERTURE, &actual_aperture, 16), - ATTR_BLOB(MF_MT_GEOMETRIC_APERTURE, &actual_aperture, 16, .todo = TRUE), - ATTR_BLOB(MF_MT_PAN_SCAN_APERTURE, &actual_aperture, 16, .todo = TRUE), + ATTR_BLOB(MF_MT_GEOMETRIC_APERTURE, &actual_aperture, 16), + ATTR_BLOB(MF_MT_PAN_SCAN_APERTURE, &actual_aperture, 16), }, }; const MFT_OUTPUT_STREAM_INFO initial_output_info = diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c index 2344e22b12b..bba5df5e1b7 100644 --- a/dlls/winegstreamer/mfplat.c +++ b/dlls/winegstreamer/mfplat.c @@ -545,6 +545,10 @@ static IMFMediaType *mf_media_type_from_wg_format_video(const struct wg_format *
IMFMediaType_SetBlob(type, &MF_MT_MINIMUM_DISPLAY_APERTURE, (BYTE *)&aperture, sizeof(aperture)); + IMFMediaType_SetBlob(type, &MF_MT_GEOMETRIC_APERTURE, + (BYTE *)&aperture, sizeof(aperture)); + IMFMediaType_SetBlob(type, &MF_MT_PAN_SCAN_APERTURE, + (BYTE *)&aperture, sizeof(aperture)); }
return type; diff --git a/dlls/winegstreamer/video_decoder.c b/dlls/winegstreamer/video_decoder.c index 8cdab7cdb8b..676f3336b91 100644 --- a/dlls/winegstreamer/video_decoder.c +++ b/dlls/winegstreamer/video_decoder.c @@ -186,6 +186,22 @@ static HRESULT create_output_media_type(struct video_decoder *decoder, const GUI goto done; }
+ if (SUCCEEDED(IMFMediaType_GetBlob(stream_type, &MF_MT_GEOMETRIC_APERTURE, + (BYTE *)&aperture, sizeof(aperture), &value))) + { + if (FAILED(hr = IMFVideoMediaType_SetBlob(video_type, &MF_MT_GEOMETRIC_APERTURE, + (BYTE *)&aperture, sizeof(aperture)))) + goto done; + } + + if (SUCCEEDED(IMFMediaType_GetBlob(stream_type, &MF_MT_PAN_SCAN_APERTURE, + (BYTE *)&aperture, sizeof(aperture), &value))) + { + if (FAILED(hr = IMFVideoMediaType_SetBlob(video_type, &MF_MT_PAN_SCAN_APERTURE, + (BYTE *)&aperture, sizeof(aperture)))) + goto done; + } + done: if (SUCCEEDED(hr)) *media_type = (IMFMediaType *)video_type;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/video_decoder.c | 38 +++++++++++++----------------- 1 file changed, 16 insertions(+), 22 deletions(-)
diff --git a/dlls/winegstreamer/video_decoder.c b/dlls/winegstreamer/video_decoder.c index 676f3336b91..9184a86b7f4 100644 --- a/dlls/winegstreamer/video_decoder.c +++ b/dlls/winegstreamer/video_decoder.c @@ -122,9 +122,9 @@ static HRESULT create_output_media_type(struct video_decoder *decoder, const GUI IMFMediaType *output_type, IMFMediaType **media_type) { IMFMediaType *default_type = decoder->output_type, *stream_type = output_type ? output_type : decoder->stream_type; + MFVideoArea default_aperture = {{0}}, aperture; IMFVideoMediaType *video_type; UINT32 value, width, height; - MFVideoArea aperture; UINT64 ratio; HRESULT hr;
@@ -138,6 +138,9 @@ static HRESULT create_output_media_type(struct video_decoder *decoder, const GUI width = ratio >> 32; height = ratio;
+ default_aperture.Area.cx = width; + default_aperture.Area.cy = height; + if (FAILED(IMFMediaType_GetUINT64(stream_type, &MF_MT_FRAME_RATE, &ratio))) ratio = (UINT64)30000 << 32 | 1001; if (FAILED(hr = IMFVideoMediaType_SetUINT64(video_type, &MF_MT_FRAME_RATE, ratio))) @@ -178,29 +181,20 @@ static HRESULT create_output_media_type(struct video_decoder *decoder, const GUI if (FAILED(hr = IMFVideoMediaType_SetUINT32(video_type, &MF_MT_FIXED_SIZE_SAMPLES, value))) goto done;
- if (SUCCEEDED(IMFMediaType_GetBlob(stream_type, &MF_MT_MINIMUM_DISPLAY_APERTURE, - (BYTE *)&aperture, sizeof(aperture), &value))) - { - if (FAILED(hr = IMFVideoMediaType_SetBlob(video_type, &MF_MT_MINIMUM_DISPLAY_APERTURE, - (BYTE *)&aperture, sizeof(aperture)))) - goto done; - } + if (FAILED(IMFMediaType_GetBlob(stream_type, &MF_MT_MINIMUM_DISPLAY_APERTURE, (BYTE *)&aperture, sizeof(aperture), &value))) + aperture = default_aperture; + if (FAILED(hr = IMFVideoMediaType_SetBlob(video_type, &MF_MT_MINIMUM_DISPLAY_APERTURE, (BYTE *)&aperture, sizeof(aperture)))) + goto done;
- if (SUCCEEDED(IMFMediaType_GetBlob(stream_type, &MF_MT_GEOMETRIC_APERTURE, - (BYTE *)&aperture, sizeof(aperture), &value))) - { - if (FAILED(hr = IMFVideoMediaType_SetBlob(video_type, &MF_MT_GEOMETRIC_APERTURE, - (BYTE *)&aperture, sizeof(aperture)))) - goto done; - } + if (FAILED(IMFMediaType_GetBlob(stream_type, &MF_MT_GEOMETRIC_APERTURE, (BYTE *)&aperture, sizeof(aperture), &value))) + aperture = default_aperture; + if (FAILED(hr = IMFVideoMediaType_SetBlob(video_type, &MF_MT_GEOMETRIC_APERTURE, (BYTE *)&aperture, sizeof(aperture)))) + goto done;
- if (SUCCEEDED(IMFMediaType_GetBlob(stream_type, &MF_MT_PAN_SCAN_APERTURE, - (BYTE *)&aperture, sizeof(aperture), &value))) - { - if (FAILED(hr = IMFVideoMediaType_SetBlob(video_type, &MF_MT_PAN_SCAN_APERTURE, - (BYTE *)&aperture, sizeof(aperture)))) - goto done; - } + if (FAILED(IMFMediaType_GetBlob(stream_type, &MF_MT_PAN_SCAN_APERTURE, (BYTE *)&aperture, sizeof(aperture), &value))) + aperture = default_aperture; + if (FAILED(hr = IMFVideoMediaType_SetBlob(video_type, &MF_MT_PAN_SCAN_APERTURE, (BYTE *)&aperture, sizeof(aperture)))) + goto done;
done: if (SUCCEEDED(hr))
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/gst_private.h | 2 ++ dlls/winegstreamer/main.c | 15 +++++++++++++++ dlls/winegstreamer/quartz_transform.c | 13 +++---------- 3 files changed, 20 insertions(+), 10 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index 4bdef90e045..92805818ff4 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -83,6 +83,8 @@ void wg_parser_stream_seek(wg_parser_stream_t stream, double rate,
wg_transform_t wg_transform_create(const struct wg_format *input_format, const struct wg_format *output_format, const struct wg_transform_attrs *attrs); +HRESULT wg_transform_create_quartz(const AM_MEDIA_TYPE *input_format, const AM_MEDIA_TYPE *output_format, + const struct wg_transform_attrs *attrs, wg_transform_t *transform); void wg_transform_destroy(wg_transform_t transform); bool wg_transform_set_output_format(wg_transform_t transform, struct wg_format *format); bool wg_transform_get_status(wg_transform_t transform, bool *accepts_input); diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c index 4d38a2bf66c..8c5ad931e83 100644 --- a/dlls/winegstreamer/main.c +++ b/dlls/winegstreamer/main.c @@ -357,6 +357,21 @@ wg_transform_t wg_transform_create(const struct wg_format *input_format, return params.transform; }
+HRESULT wg_transform_create_quartz(const AM_MEDIA_TYPE *input_type, const AM_MEDIA_TYPE *output_type, + const struct wg_transform_attrs *attrs, wg_transform_t *transform) +{ + struct wg_format input_format, output_format; + + if (!amt_to_wg_format(input_type, &input_format)) + return E_FAIL; + if (!amt_to_wg_format(output_type, &output_format)) + return E_FAIL; + + if (!(*transform = wg_transform_create(&input_format, &output_format, attrs))) + return E_FAIL; + return S_OK; +} + void wg_transform_destroy(wg_transform_t transform) { TRACE("transform %#I64x.\n", transform); diff --git a/dlls/winegstreamer/quartz_transform.c b/dlls/winegstreamer/quartz_transform.c index ad0c3077733..b85b24f4278 100644 --- a/dlls/winegstreamer/quartz_transform.c +++ b/dlls/winegstreamer/quartz_transform.c @@ -98,26 +98,19 @@ static HRESULT transform_query_interface(struct strmbase_filter *iface, REFIID i static HRESULT transform_init_stream(struct strmbase_filter *iface) { struct transform *filter = impl_from_strmbase_filter(iface); - struct wg_format input_format, output_format; struct wg_transform_attrs attrs = {0}; HRESULT hr;
if (filter->source.pin.peer) { - if (!amt_to_wg_format(&filter->sink.pin.mt, &input_format)) - return E_FAIL; - - if (!amt_to_wg_format(&filter->source.pin.mt, &output_format)) - return E_FAIL; - if (FAILED(hr = wg_sample_queue_create(&filter->sample_queue))) return hr;
- filter->transform = wg_transform_create(&input_format, &output_format, &attrs); - if (!filter->transform) + if (FAILED(hr = wg_transform_create_quartz(&filter->sink.pin.mt, &filter->source.pin.mt, + &attrs, &filter->transform))) { wg_sample_queue_destroy(filter->sample_queue); - return E_FAIL; + return hr; }
hr = IMemAllocator_Commit(filter->source.pAllocator);
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/wmv_decoder.c | 80 +++++++++++++++++++------------- 1 file changed, 47 insertions(+), 33 deletions(-)
diff --git a/dlls/winegstreamer/wmv_decoder.c b/dlls/winegstreamer/wmv_decoder.c index ea8b4b19eb6..b8c952da070 100644 --- a/dlls/winegstreamer/wmv_decoder.c +++ b/dlls/winegstreamer/wmv_decoder.c @@ -81,19 +81,14 @@ struct wmv_decoder IUnknown *outer; LONG refcount;
- struct wg_format input_format; - struct wg_format output_format; + DMO_MEDIA_TYPE input_type; + DMO_MEDIA_TYPE output_type; GUID output_subtype;
wg_transform_t wg_transform; struct wg_sample_queue *wg_sample_queue; };
-static bool wg_format_is_set(struct wg_format *format) -{ - return format->major_type != WG_MAJOR_TYPE_UNKNOWN; -} - static inline struct wmv_decoder *impl_from_IUnknown(IUnknown *iface) { return CONTAINING_RECORD(iface, struct wmv_decoder, IUnknown_inner); @@ -428,6 +423,8 @@ static HRESULT WINAPI media_object_GetOutputType(IMediaObject *iface, DWORD inde DMO_MEDIA_TYPE *type) { struct wmv_decoder *decoder = impl_from_IMediaObject(iface); + UINT64 frame_size, frame_rate; + IMFMediaType *media_type; VIDEOINFOHEADER *info; const GUID *subtype; LONG width, height; @@ -442,15 +439,25 @@ static HRESULT WINAPI media_object_GetOutputType(IMediaObject *iface, DWORD inde return DMO_E_NO_MORE_ITEMS; if (!type) return S_OK; - if (!wg_format_is_set(&decoder->input_format)) + if (IsEqualGUID(&decoder->input_type.majortype, &GUID_NULL)) return DMO_E_TYPE_NOT_SET;
- width = decoder->input_format.u.video.width; - height = abs(decoder->input_format.u.video.height); + if (FAILED(hr = MFCreateMediaTypeFromRepresentation(AM_MEDIA_TYPE_REPRESENTATION, + &decoder->input_type, &media_type))) + return hr; + + if (FAILED(IMFMediaType_GetUINT64(media_type, &MF_MT_FRAME_SIZE, &frame_size))) + frame_size = 0; + if (FAILED(IMFMediaType_GetUINT64(media_type, &MF_MT_FRAME_RATE, &frame_rate))) + frame_rate = (UINT64)1 << 32 | 1; + + width = frame_size >> 32; + height = (UINT32)frame_size; subtype = wmv_decoder_output_types[type_index].subtype; if (FAILED(hr = MFCalculateImageSize(subtype, width, height, &image_size))) { FIXME("Failed to get image size of subtype %s.\n", debugstr_guid(subtype)); + IMFMediaType_Release(media_type); return hr; }
@@ -470,8 +477,7 @@ static HRESULT WINAPI media_object_GetOutputType(IMediaObject *iface, DWORD inde info->rcSource.bottom = height; info->rcTarget.right = width; info->rcTarget.bottom = height; - info->AvgTimePerFrame = MulDiv(10000000, decoder->input_format.u.video.fps_d, - decoder->input_format.u.video.fps_n); + info->AvgTimePerFrame = MulDiv(10000000, frame_rate >> 32, (UINT32)frame_rate); info->bmiHeader.biSize = sizeof(info->bmiHeader); info->bmiHeader.biWidth = width; info->bmiHeader.biHeight = height; @@ -480,6 +486,7 @@ static HRESULT WINAPI media_object_GetOutputType(IMediaObject *iface, DWORD inde info->bmiHeader.biCompression = wmv_decoder_output_types[type_index].compression; info->bmiHeader.biSizeImage = image_size;
+ IMFMediaType_Release(media_type); return S_OK; }
@@ -487,7 +494,7 @@ static HRESULT WINAPI media_object_SetInputType(IMediaObject *iface, DWORD index const DMO_MEDIA_TYPE *type, DWORD flags) { struct wmv_decoder *decoder = impl_from_IMediaObject(iface); - struct wg_format wg_format; + IMFMediaType *media_type; unsigned int i;
TRACE("iface %p, index %lu, type %p, flags %#lx.\n", iface, index, type, flags); @@ -499,7 +506,8 @@ static HRESULT WINAPI media_object_SetInputType(IMediaObject *iface, DWORD index { if (flags & DMO_SET_TYPEF_CLEAR) { - memset(&decoder->input_format, 0, sizeof(decoder->input_format)); + FreeMediaType(&decoder->input_type); + memset(&decoder->input_type, 0, sizeof(decoder->input_type)); if (decoder->wg_transform) { wg_transform_destroy(decoder->wg_transform); @@ -519,14 +527,16 @@ static HRESULT WINAPI media_object_SetInputType(IMediaObject *iface, DWORD index if (i == ARRAY_SIZE(wmv_decoder_input_types)) return DMO_E_TYPE_NOT_ACCEPTED;
- if (!amt_to_wg_format((const AM_MEDIA_TYPE *)type, &wg_format)) + if (FAILED(MFCreateMediaTypeFromRepresentation(AM_MEDIA_TYPE_REPRESENTATION, + (void *)type, &media_type))) return DMO_E_TYPE_NOT_ACCEPTED; - assert(wg_format.major_type == WG_MAJOR_TYPE_VIDEO_WMV); + IMFMediaType_Release(media_type);
if (flags & DMO_SET_TYPEF_TEST_ONLY) return S_OK;
- decoder->input_format = wg_format; + FreeMediaType(&decoder->input_type); + CopyMediaType(&decoder->input_type, type); if (decoder->wg_transform) { wg_transform_destroy(decoder->wg_transform); @@ -541,8 +551,9 @@ static HRESULT WINAPI media_object_SetOutputType(IMediaObject *iface, DWORD inde { struct wmv_decoder *decoder = impl_from_IMediaObject(iface); struct wg_transform_attrs attrs = {0}; - struct wg_format wg_format; + IMFMediaType *media_type; unsigned int i; + HRESULT hr;
TRACE("iface %p, index %lu, type %p, flags %#lx,\n", iface, index, type, flags);
@@ -553,7 +564,8 @@ static HRESULT WINAPI media_object_SetOutputType(IMediaObject *iface, DWORD inde { if (flags & DMO_SET_TYPEF_CLEAR) { - memset(&decoder->output_format, 0, sizeof(decoder->output_format)); + FreeMediaType(&decoder->output_type); + memset(&decoder->output_type, 0, sizeof(decoder->output_type)); if (decoder->wg_transform) { wg_transform_destroy(decoder->wg_transform); @@ -564,7 +576,7 @@ static HRESULT WINAPI media_object_SetOutputType(IMediaObject *iface, DWORD inde return E_POINTER; }
- if (!wg_format_is_set(&decoder->input_format)) + if (IsEqualGUID(&decoder->input_type.majortype, &GUID_NULL)) return DMO_E_TYPE_NOT_SET;
if (!IsEqualGUID(&type->majortype, &MEDIATYPE_Video)) @@ -576,15 +588,16 @@ static HRESULT WINAPI media_object_SetOutputType(IMediaObject *iface, DWORD inde if (i == ARRAY_SIZE(wmv_decoder_output_types)) return DMO_E_TYPE_NOT_ACCEPTED;
- if (!amt_to_wg_format((const AM_MEDIA_TYPE *)type, &wg_format)) + if (FAILED(MFCreateMediaTypeFromRepresentation(AM_MEDIA_TYPE_REPRESENTATION, + (void *)type, &media_type))) return DMO_E_TYPE_NOT_ACCEPTED; - assert(wg_format.major_type == WG_MAJOR_TYPE_VIDEO); + IMFMediaType_Release(media_type);
if (flags & DMO_SET_TYPEF_TEST_ONLY) return S_OK;
- decoder->output_subtype = type->subtype; - decoder->output_format = wg_format; + FreeMediaType(&decoder->output_type); + CopyMediaType(&decoder->output_type, type);
/* Set up wg_transform. */ if (decoder->wg_transform) @@ -592,8 +605,9 @@ static HRESULT WINAPI media_object_SetOutputType(IMediaObject *iface, DWORD inde wg_transform_destroy(decoder->wg_transform); decoder->wg_transform = 0; } - if (!(decoder->wg_transform = wg_transform_create(&decoder->input_format, &decoder->output_format, &attrs))) - return E_FAIL; + if (FAILED(hr = wg_transform_create_quartz(&decoder->input_type, type, + &attrs, &decoder->wg_transform))) + return hr;
return S_OK; } @@ -621,22 +635,22 @@ static HRESULT WINAPI media_object_GetInputSizeInfo(IMediaObject *iface, DWORD i static HRESULT WINAPI media_object_GetOutputSizeInfo(IMediaObject *iface, DWORD index, DWORD *size, DWORD *alignment) { struct wmv_decoder *decoder = impl_from_IMediaObject(iface); + IMFMediaType *media_type; HRESULT hr;
TRACE("iface %p, index %lu, size %p, alignment %p.\n", iface, index, size, alignment);
if (index > 0) return DMO_E_INVALIDSTREAMINDEX; - if (!wg_format_is_set(&decoder->output_format)) + if (IsEqualGUID(&decoder->output_type.majortype, &GUID_NULL)) return DMO_E_TYPE_NOT_SET;
- if (FAILED(hr = MFCalculateImageSize(&decoder->output_subtype, - decoder->output_format.u.video.width, abs(decoder->output_format.u.video.height), (UINT32 *)size))) - { - FIXME("Failed to get image size of subtype %s.\n", debugstr_guid(&decoder->output_subtype)); + if (FAILED(hr = MFCreateMediaType(&media_type))) return hr; - } - *alignment = 1; + if (SUCCEEDED(hr = MFInitMediaTypeFromAMMediaType(media_type, &decoder->output_type)) + && SUCCEEDED(hr = IMFMediaType_GetUINT32(media_type, &MF_MT_SAMPLE_SIZE, (UINT32 *)size))) + *alignment = 1; + IMFMediaType_Release(media_type);
return S_OK; }
From: Ziqing Hui zhui@codeweavers.com
--- dlls/winegstreamer/mfplat.c | 65 ++++++++++++++++++++++++++++++++ dlls/winegstreamer/wmv_decoder.c | 3 +- 2 files changed, 66 insertions(+), 2 deletions(-)
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c index bba5df5e1b7..1bf70561df0 100644 --- a/dlls/winegstreamer/mfplat.c +++ b/dlls/winegstreamer/mfplat.c @@ -40,6 +40,7 @@ DEFINE_GUID(DMOVideoFormat_RGB8,D3DFMT_P8,0x524f,0x11ce,0x9f,0x53,0x00,0x20,0xaf DEFINE_MEDIATYPE_GUID(MFAudioFormat_RAW_AAC,WAVE_FORMAT_RAW_AAC1); DEFINE_MEDIATYPE_GUID(MFVideoFormat_VC1S,MAKEFOURCC('V','C','1','S')); DEFINE_MEDIATYPE_GUID(MFVideoFormat_IV50,MAKEFOURCC('I','V','5','0')); +DEFINE_GUID(MEDIASUBTYPE_WMV_Unknown, 0x7ce12ca9,0xbfbf,0x43d9,0x9d,0x00,0x82,0xb8,0xed,0x54,0x31,0x6b);
struct class_factory { @@ -867,6 +868,60 @@ static void mf_media_type_to_wg_format_video_indeo(IMFMediaType *type, uint32_t format->u.video.version = version; }
+static void mf_media_type_to_wg_format_video_wmv(IMFMediaType *type, const GUID *subtype, struct wg_format *format) +{ + UINT64 frame_rate, frame_size; + UINT32 codec_data_len; + BYTE *codec_data; + + memset(format, 0, sizeof(*format)); + format->major_type = WG_MAJOR_TYPE_VIDEO_WMV; + + if (SUCCEEDED(IMFMediaType_GetUINT64(type, &MF_MT_FRAME_SIZE, &frame_size))) + { + format->u.video.width = frame_size >> 32; + format->u.video.height = (UINT32)frame_size; + } + + if (SUCCEEDED(IMFMediaType_GetUINT64(type, &MF_MT_FRAME_RATE, &frame_rate)) && (UINT32)frame_rate) + { + format->u.video.fps_n = frame_rate >> 32; + format->u.video.fps_d = (UINT32)frame_rate; + } + else + { + format->u.video.fps_n = 1; + format->u.video.fps_d = 1; + } + + if (IsEqualGUID(subtype, &MEDIASUBTYPE_WMV1)) + format->u.video.format = WG_VIDEO_FORMAT_WMV1; + else if (IsEqualGUID(subtype, &MEDIASUBTYPE_WMV2)) + format->u.video.format = WG_VIDEO_FORMAT_WMV2; + else if (IsEqualGUID(subtype, &MEDIASUBTYPE_WMV3)) + format->u.video.format = WG_VIDEO_FORMAT_WMV3; + else if (IsEqualGUID(subtype, &MEDIASUBTYPE_WMVA)) + format->u.video.format = WG_VIDEO_FORMAT_WMVA; + else if (IsEqualGUID(subtype, &MEDIASUBTYPE_WVC1)) + format->u.video.format = WG_VIDEO_FORMAT_WVC1; + else + format->u.video.format = WG_VIDEO_FORMAT_UNKNOWN; + + if (SUCCEEDED(IMFMediaType_GetAllocatedBlob(type, &MF_MT_USER_DATA, &codec_data, &codec_data_len))) + { + if (codec_data_len <= sizeof(format->u.video.codec_data)) + { + format->u.video.codec_data_len = codec_data_len; + memcpy(format->u.video.codec_data, codec_data, codec_data_len); + } + else + { + WARN("Codec data buffer too small, codec data size %u.\n", codec_data_len); + } + CoTaskMemFree(codec_data); + } +} + void mf_media_type_to_wg_format(IMFMediaType *type, struct wg_format *format) { GUID major_type, subtype; @@ -902,6 +957,16 @@ void mf_media_type_to_wg_format(IMFMediaType *type, struct wg_format *format) mf_media_type_to_wg_format_video_h264(type, format); else if (IsEqualGUID(&subtype, &MFVideoFormat_IV50)) mf_media_type_to_wg_format_video_indeo(type, 5, format); + else if (IsEqualGUID(&subtype, &MEDIASUBTYPE_WMV1) + || IsEqualGUID(&subtype, &MEDIASUBTYPE_WMV2) + || IsEqualGUID(&subtype, &MEDIASUBTYPE_WMVA) + || IsEqualGUID(&subtype, &MEDIASUBTYPE_WMVP) + || IsEqualGUID(&subtype, &MEDIASUBTYPE_WVP2) + || IsEqualGUID(&subtype, &MEDIASUBTYPE_WMV_Unknown) + || IsEqualGUID(&subtype, &MEDIASUBTYPE_WVC1) + || IsEqualGUID(&subtype, &MEDIASUBTYPE_WMV3) + || IsEqualGUID(&subtype, &MFVideoFormat_VC1S)) + mf_media_type_to_wg_format_video_wmv(type, &subtype, format); else mf_media_type_to_wg_format_video(type, &subtype, format); } diff --git a/dlls/winegstreamer/wmv_decoder.c b/dlls/winegstreamer/wmv_decoder.c index b8c952da070..446641f0298 100644 --- a/dlls/winegstreamer/wmv_decoder.c +++ b/dlls/winegstreamer/wmv_decoder.c @@ -31,8 +31,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(mfplat); WINE_DECLARE_DEBUG_CHANNEL(winediag);
extern const GUID MEDIASUBTYPE_VC1S; - -DEFINE_GUID(MEDIASUBTYPE_WMV_Unknown, 0x7ce12ca9,0xbfbf,0x43d9,0x9d,0x00,0x82,0xb8,0xed,0x54,0x31,0x6b); +extern const GUID MEDIASUBTYPE_WMV_Unknown;
struct decoder_type {
From: Ziqing Hui zhui@codeweavers.com
--- dlls/winegstreamer/video_decoder.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-)
diff --git a/dlls/winegstreamer/video_decoder.c b/dlls/winegstreamer/video_decoder.c index 9184a86b7f4..61ae579686e 100644 --- a/dlls/winegstreamer/video_decoder.c +++ b/dlls/winegstreamer/video_decoder.c @@ -831,13 +831,6 @@ static HRESULT video_decoder_create_with_types(const GUID *const *input_types, U decoder->output_type_count = output_type_count; decoder->output_types = output_types;
- decoder->input_info.dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER - | MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE; - decoder->input_info.cbSize = 0x1000; - decoder->output_info.dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER - | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE; - decoder->output_info.cbSize = 1920 * 1088 * 2; - if (FAILED(hr = MFCreateMediaType(&decoder->stream_type))) goto failed; if (FAILED(hr = MFCreateAttributes(&decoder->attributes, 16))) @@ -897,6 +890,7 @@ HRESULT h264_decoder_create(REFIID riid, void **out) }; static const struct wg_format input_format = {.major_type = WG_MAJOR_TYPE_VIDEO_H264}; struct wg_transform_attrs attrs = {0}; + struct video_decoder *decoder; wg_transform_t transform; IMFTransform *iface; HRESULT hr; @@ -913,6 +907,14 @@ HRESULT h264_decoder_create(REFIID riid, void **out) if (FAILED(hr = video_decoder_create_with_types(h264_decoder_input_types, ARRAY_SIZE(h264_decoder_input_types), video_decoder_output_types, ARRAY_SIZE(video_decoder_output_types), &iface))) return hr; + decoder = impl_from_IMFTransform(iface); + + decoder->input_info.dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER + | MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE; + decoder->input_info.cbSize = 0x1000; + decoder->output_info.dwFlags = MFT_OUTPUT_STREAM_WHOLE_SAMPLES | MFT_OUTPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER + | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE; + decoder->output_info.cbSize = 1920 * 1088 * 2;
hr = IMFTransform_QueryInterface(iface, riid, out); IMFTransform_Release(iface);
From: Ziqing Hui zhui@codeweavers.com
--- dlls/mf/tests/transform.c | 4 ++-- dlls/winegstreamer/video_decoder.c | 16 +++++++++++----- 2 files changed, 13 insertions(+), 7 deletions(-)
diff --git a/dlls/mf/tests/transform.c b/dlls/mf/tests/transform.c index d1d52d62458..2a90c49f96e 100644 --- a/dlls/mf/tests/transform.c +++ b/dlls/mf/tests/transform.c @@ -3932,9 +3932,9 @@ static void test_h264_decoder(void) static const struct attribute_desc expect_transform_attributes[] = { ATTR_UINT32(MF_LOW_LATENCY, 0), - ATTR_UINT32(MF_SA_D3D_AWARE, 1, .todo = TRUE), + ATTR_UINT32(MF_SA_D3D_AWARE, 1), ATTR_UINT32(MF_SA_D3D11_AWARE, 1), - ATTR_UINT32(MFT_DECODER_EXPOSE_OUTPUT_TYPES_IN_NATIVE_ORDER, 0, .todo = TRUE), + ATTR_UINT32(MFT_DECODER_EXPOSE_OUTPUT_TYPES_IN_NATIVE_ORDER, 0), /* more H264 decoder specific attributes from CODECAPI */ ATTR_UINT32(AVDecVideoAcceleration_H264, 1), {0}, diff --git a/dlls/winegstreamer/video_decoder.c b/dlls/winegstreamer/video_decoder.c index 61ae579686e..2aedbdf1402 100644 --- a/dlls/winegstreamer/video_decoder.c +++ b/dlls/winegstreamer/video_decoder.c @@ -835,11 +835,11 @@ static HRESULT video_decoder_create_with_types(const GUID *const *input_types, U goto failed; if (FAILED(hr = MFCreateAttributes(&decoder->attributes, 16))) goto failed; - if (FAILED(hr = IMFAttributes_SetUINT32(decoder->attributes, &MF_LOW_LATENCY, 0))) - goto failed; - if (FAILED(hr = IMFAttributes_SetUINT32(decoder->attributes, &MF_SA_D3D11_AWARE, TRUE))) - goto failed; - if (FAILED(hr = IMFAttributes_SetUINT32(decoder->attributes, &AVDecVideoAcceleration_H264, TRUE))) + if (FAILED(hr = IMFAttributes_SetUINT32(decoder->attributes, &MF_LOW_LATENCY, FALSE)) + || FAILED(hr = IMFAttributes_SetUINT32(decoder->attributes, &MF_SA_D3D_AWARE, TRUE)) + || FAILED(hr = IMFAttributes_SetUINT32(decoder->attributes, &MF_SA_D3D11_AWARE, TRUE)) + || FAILED(hr = IMFAttributes_SetUINT32(decoder->attributes, + &MFT_DECODER_EXPOSE_OUTPUT_TYPES_IN_NATIVE_ORDER, FALSE))) goto failed;
if (FAILED(hr = MFCreateAttributes(&decoder->output_attributes, 0))) @@ -909,6 +909,12 @@ HRESULT h264_decoder_create(REFIID riid, void **out) return hr; decoder = impl_from_IMFTransform(iface);
+ if (FAILED(hr = IMFAttributes_SetUINT32(decoder->attributes, &AVDecVideoAcceleration_H264, TRUE))) + { + IMFTransform_Release(iface); + return hr; + } + decoder->input_info.dwFlags = MFT_INPUT_STREAM_WHOLE_SAMPLES | MFT_INPUT_STREAM_SINGLE_SAMPLE_PER_BUFFER | MFT_INPUT_STREAM_FIXED_SAMPLE_SIZE; decoder->input_info.cbSize = 0x1000;
From: Ziqing Hui zhui@codeweavers.com
--- dlls/winegstreamer/video_decoder.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/dlls/winegstreamer/video_decoder.c b/dlls/winegstreamer/video_decoder.c index 2aedbdf1402..065f2608ef8 100644 --- a/dlls/winegstreamer/video_decoder.c +++ b/dlls/winegstreamer/video_decoder.c @@ -64,6 +64,7 @@ struct video_decoder IMFMediaType *stream_type;
wg_transform_t wg_transform; + struct wg_transform_attrs wg_transform_attrs; struct wg_sample_queue *wg_sample_queue;
IMFVideoSampleAllocatorEx *allocator; @@ -84,12 +85,6 @@ static HRESULT try_create_wg_transform(struct video_decoder *decoder) * transform to be able to queue its input buffers. We need to use a buffer list * to match its expectations. */ - struct wg_transform_attrs attrs = - { - .output_plane_align = 15, - .input_queue_length = 15, - .allow_size_change = TRUE, - }; struct wg_format input_format; struct wg_format output_format; UINT32 low_latency; @@ -107,9 +102,9 @@ static HRESULT try_create_wg_transform(struct video_decoder *decoder) return MF_E_INVALIDMEDIATYPE;
if (SUCCEEDED(IMFAttributes_GetUINT32(decoder->attributes, &MF_LOW_LATENCY, &low_latency))) - attrs.low_latency = !!low_latency; + decoder->wg_transform_attrs.low_latency = !!low_latency;
- if (!(decoder->wg_transform = wg_transform_create(&input_format, &output_format, &attrs))) + if (!(decoder->wg_transform = wg_transform_create(&input_format, &output_format, &decoder->wg_transform_attrs))) { ERR("Failed to create transform with input major_type %u.\n", input_format.major_type); return E_FAIL; @@ -851,6 +846,9 @@ static HRESULT video_decoder_create_with_types(const GUID *const *input_types, U if (FAILED(hr = MFCreateSampleCopierMFT(&decoder->copier))) goto failed;
+ decoder->wg_transform_attrs.output_plane_align = 15; + decoder->wg_transform_attrs.input_queue_length = 15; + *ret = &decoder->IMFTransform_iface; TRACE("Created decoder %p\n", *ret); return S_OK; @@ -922,6 +920,8 @@ HRESULT h264_decoder_create(REFIID riid, void **out) | MFT_OUTPUT_STREAM_FIXED_SAMPLE_SIZE; decoder->output_info.cbSize = 1920 * 1088 * 2;
+ decoder->wg_transform_attrs.allow_size_change = TRUE; + hr = IMFTransform_QueryInterface(iface, riid, out); IMFTransform_Release(iface); return hr;
From: Ziqing Hui zhui@codeweavers.com
--- dlls/winegstreamer/video_decoder.c | 134 ++++++++++++++++++----------- 1 file changed, 83 insertions(+), 51 deletions(-)
diff --git a/dlls/winegstreamer/video_decoder.c b/dlls/winegstreamer/video_decoder.c index 065f2608ef8..4824e317174 100644 --- a/dlls/winegstreamer/video_decoder.c +++ b/dlls/winegstreamer/video_decoder.c @@ -45,7 +45,9 @@ static const GUID *const video_decoder_output_types[] =
struct video_decoder { + IUnknown IUnknown_inner; IMFTransform IMFTransform_iface; + IUnknown *outer; LONG refcount;
IMFAttributes *attributes; @@ -73,6 +75,79 @@ struct video_decoder IMFMediaBuffer *temp_buffer; };
+static inline struct video_decoder *impl_from_IUnknown(IUnknown *iface) +{ + return CONTAINING_RECORD(iface, struct video_decoder, IUnknown_inner); +} + +static HRESULT WINAPI unknown_QueryInterface(IUnknown *iface, REFIID iid, void **out) +{ + struct video_decoder *decoder = impl_from_IUnknown(iface); + + TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); + + if (IsEqualGUID(iid, &IID_IUnknown)) + *out = &decoder->IUnknown_inner; + else if (IsEqualGUID(iid, &IID_IMFTransform)) + *out = &decoder->IMFTransform_iface; + else + { + *out = NULL; + WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); + return E_NOINTERFACE; + } + + IUnknown_AddRef((IUnknown *)*out); + return S_OK; +} + +static ULONG WINAPI unknown_AddRef(IUnknown *iface) +{ + struct video_decoder *decoder = impl_from_IUnknown(iface); + ULONG refcount = InterlockedIncrement(&decoder->refcount); + + TRACE("iface %p increasing refcount to %lu.\n", decoder, refcount); + + return refcount; +} + +static ULONG WINAPI unknown_Release(IUnknown *iface) +{ + struct video_decoder *decoder = impl_from_IUnknown(iface); + ULONG refcount = InterlockedDecrement(&decoder->refcount); + + TRACE("iface %p decreasing refcount to %lu.\n", decoder, refcount); + + if (!refcount) + { + IMFTransform_Release(decoder->copier); + IMFVideoSampleAllocatorEx_Release(decoder->allocator); + if (decoder->temp_buffer) + IMFMediaBuffer_Release(decoder->temp_buffer); + if (decoder->wg_transform) + wg_transform_destroy(decoder->wg_transform); + if (decoder->input_type) + IMFMediaType_Release(decoder->input_type); + if (decoder->output_type) + IMFMediaType_Release(decoder->output_type); + if (decoder->output_attributes) + IMFAttributes_Release(decoder->output_attributes); + if (decoder->attributes) + IMFAttributes_Release(decoder->attributes); + wg_sample_queue_destroy(decoder->wg_sample_queue); + free(decoder); + } + + return refcount; +} + +static const IUnknownVtbl unknown_vtbl = +{ + unknown_QueryInterface, + unknown_AddRef, + unknown_Release, +}; + static struct video_decoder *impl_from_IMFTransform(IMFTransform *iface) { return CONTAINING_RECORD(iface, struct video_decoder, IMFTransform_iface); @@ -230,62 +305,17 @@ static void uninit_allocator(struct video_decoder *decoder)
static HRESULT WINAPI transform_QueryInterface(IMFTransform *iface, REFIID iid, void **out) { - struct video_decoder *decoder = impl_from_IMFTransform(iface); - - TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); - - if (IsEqualGUID(iid, &IID_IUnknown) || - IsEqualGUID(iid, &IID_IMFTransform)) - *out = &decoder->IMFTransform_iface; - else - { - *out = NULL; - WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); - return E_NOINTERFACE; - } - - IUnknown_AddRef((IUnknown *)*out); - return S_OK; + return IUnknown_QueryInterface(impl_from_IMFTransform(iface)->outer, iid, out); }
static ULONG WINAPI transform_AddRef(IMFTransform *iface) { - struct video_decoder *decoder = impl_from_IMFTransform(iface); - ULONG refcount = InterlockedIncrement(&decoder->refcount); - - TRACE("iface %p increasing refcount to %lu.\n", decoder, refcount); - - return refcount; + return IUnknown_AddRef(impl_from_IMFTransform(iface)->outer); }
static ULONG WINAPI transform_Release(IMFTransform *iface) { - struct video_decoder *decoder = impl_from_IMFTransform(iface); - ULONG refcount = InterlockedDecrement(&decoder->refcount); - - TRACE("iface %p decreasing refcount to %lu.\n", decoder, refcount); - - if (!refcount) - { - IMFTransform_Release(decoder->copier); - IMFVideoSampleAllocatorEx_Release(decoder->allocator); - if (decoder->temp_buffer) - IMFMediaBuffer_Release(decoder->temp_buffer); - if (decoder->wg_transform) - wg_transform_destroy(decoder->wg_transform); - if (decoder->input_type) - IMFMediaType_Release(decoder->input_type); - if (decoder->output_type) - IMFMediaType_Release(decoder->output_type); - if (decoder->output_attributes) - IMFAttributes_Release(decoder->output_attributes); - if (decoder->attributes) - IMFAttributes_Release(decoder->attributes); - wg_sample_queue_destroy(decoder->wg_sample_queue); - free(decoder); - } - - return refcount; + return IUnknown_Release(impl_from_IMFTransform(iface)->outer); }
static HRESULT WINAPI transform_GetStreamLimits(IMFTransform *iface, DWORD *input_minimum, @@ -810,7 +840,7 @@ static const IMFTransformVtbl transform_vtbl = };
static HRESULT video_decoder_create_with_types(const GUID *const *input_types, UINT input_type_count, - const GUID *const *output_types, UINT output_type_count, IMFTransform **ret) + const GUID *const *output_types, UINT output_type_count, IUnknown *outer, IMFTransform **ret) { struct video_decoder *decoder; HRESULT hr; @@ -818,8 +848,10 @@ static HRESULT video_decoder_create_with_types(const GUID *const *input_types, U if (!(decoder = calloc(1, sizeof(*decoder)))) return E_OUTOFMEMORY;
+ decoder->IUnknown_inner.lpVtbl = &unknown_vtbl; decoder->IMFTransform_iface.lpVtbl = &transform_vtbl; decoder->refcount = 1; + decoder->outer = outer ? outer : &decoder->IUnknown_inner;
decoder->input_type_count = input_type_count; decoder->input_types = input_types; @@ -903,7 +935,7 @@ HRESULT h264_decoder_create(REFIID riid, void **out) wg_transform_destroy(transform);
if (FAILED(hr = video_decoder_create_with_types(h264_decoder_input_types, ARRAY_SIZE(h264_decoder_input_types), - video_decoder_output_types, ARRAY_SIZE(video_decoder_output_types), &iface))) + video_decoder_output_types, ARRAY_SIZE(video_decoder_output_types), NULL, &iface))) return hr; decoder = impl_from_IMFTransform(iface);
@@ -953,5 +985,5 @@ HRESULT WINAPI winegstreamer_create_video_decoder(IMFTransform **out) return E_FAIL;
return video_decoder_create_with_types(iv50_decoder_input_types, ARRAY_SIZE(iv50_decoder_input_types), - iv50_decoder_output_types, ARRAY_SIZE(iv50_decoder_output_types), out); + iv50_decoder_output_types, ARRAY_SIZE(iv50_decoder_output_types), NULL, out); }
From: Ziqing Hui zhui@codeweavers.com
--- dlls/mf/tests/transform.c | 69 ++- dlls/winegstreamer/Makefile.in | 3 +- dlls/winegstreamer/video_decoder.c | 750 ++++++++++++++++++++++- dlls/winegstreamer/wmv_decoder.c | 942 ----------------------------- 4 files changed, 793 insertions(+), 971 deletions(-) delete mode 100644 dlls/winegstreamer/wmv_decoder.c
diff --git a/dlls/mf/tests/transform.c b/dlls/mf/tests/transform.c index 2a90c49f96e..8fdc81605b6 100644 --- a/dlls/mf/tests/transform.c +++ b/dlls/mf/tests/transform.c @@ -681,6 +681,7 @@ static void check_mft_set_input_type_required_(int line, IMFTransform *transform hr = IMFMediaType_DeleteItem(media_type, attr->key); ok_(__FILE__, line)(hr == S_OK, "DeleteItem returned %#lx\n", hr); hr = IMFTransform_SetInputType(transform, 0, media_type, MFT_SET_TYPE_TEST_ONLY); + todo_wine_if(attr->todo) ok_(__FILE__, line)(FAILED(hr) == attr->required, "SetInputType returned %#lx.\n", hr); hr = IMFMediaType_SetItem(media_type, attr->key, &attr->value); ok_(__FILE__, line)(hr == S_OK, "SetItem returned %#lx\n", hr); @@ -1285,7 +1286,7 @@ static DWORD check_mf_sample_(const char *file, int line, IMFSample *sample, con timestamp = 0xdeadbeef; hr = IMFSample_GetSampleDuration(sample, ×tamp); ok_(file, line)(hr == S_OK, "GetSampleDuration returned %#lx\n", hr); - todo_wine_if(expect->todo_duration && expect->todo_duration == timestamp) + todo_wine_if(expect->todo_duration) ok_(file, line)(llabs(timestamp - expect->sample_duration) <= 1, "got sample duration %I64d\n", timestamp);
@@ -5602,7 +5603,7 @@ static void test_wmv_decoder(void) ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1), ATTR_UINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1), ATTR_UINT32(MF_MT_FIXED_SIZE_SAMPLES, 1), - ATTR_UINT32(MF_MT_INTERLACE_MODE, 2), + ATTR_UINT32(MF_MT_INTERLACE_MODE, 2, .todo_value = TRUE), {0}, }; const media_type_desc expect_available_outputs[] = @@ -5714,7 +5715,7 @@ static void test_wmv_decoder(void) { ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video, .required = TRUE), ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV1, .required = TRUE), - ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE), + ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height, .required = TRUE, .todo = TRUE), {0}, }; const struct attribute_desc output_type_desc[] = @@ -5760,7 +5761,7 @@ static void test_wmv_decoder(void) ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_WMV1), ATTR_RATIO(MF_MT_FRAME_SIZE, actual_width, actual_height), - ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1), + ATTR_RATIO(MF_MT_PIXEL_ASPECT_RATIO, 1, 1, .todo = TRUE), {0}, }; const struct attribute_desc expect_output_type_desc[] = @@ -5828,6 +5829,7 @@ static void test_wmv_decoder(void) .cbSize = 0x9000, .cbAlignment = 1, }; + const MFT_INPUT_STREAM_INFO empty_input_info = {0};
const struct attribute_desc output_sample_attributes[] = { @@ -5849,12 +5851,21 @@ static void test_wmv_decoder(void) .attributes = output_sample_attributes, .sample_time = 0, .sample_duration = 333333, .buffer_count = 1, .buffers = &output_buffer_desc_nv12, + .todo_duration = TRUE, + }; + const struct sample_desc output_sample_desc_nv12_todo_time = + { + .attributes = output_sample_attributes, + .sample_time = 0, .sample_duration = 333333, + .buffer_count = 1, .buffers = &output_buffer_desc_nv12, + .todo_time = TRUE, .todo_duration = TRUE, }; const struct sample_desc output_sample_desc_rgb = { .attributes = output_sample_attributes, .sample_time = 0, .sample_duration = 333333, .buffer_count = 1, .buffers = &output_buffer_desc_rgb, + .todo_time = TRUE, .todo_duration = TRUE, };
const struct transform_desc @@ -5886,7 +5897,7 @@ static void test_wmv_decoder(void) .expect_output_type_desc = expect_output_type_desc, .expect_input_info = &expect_input_info, .expect_output_info = &expect_output_info, - .output_sample_desc = &output_sample_desc_nv12, + .output_sample_desc = &output_sample_desc_nv12_todo_time, .result_bitmap = L"nv12frame.bmp", .delta = 0, }, @@ -5929,6 +5940,8 @@ static void test_wmv_decoder(void) MFT_REGISTER_TYPE_INFO output_type = {MFMediaType_Video, MFVideoFormat_NV12}; MFT_REGISTER_TYPE_INFO input_type = {MFMediaType_Video, MFVideoFormat_WMV1}; IMFSample *input_sample, *output_sample; + MFT_OUTPUT_STREAM_INFO output_info; + MFT_INPUT_STREAM_INFO input_info; IMFCollection *output_samples; IMFMediaType *media_type; IMFTransform *transform; @@ -5965,13 +5978,27 @@ static void test_wmv_decoder(void)
check_mft_optional_methods(transform, 1); check_mft_get_attributes(transform, expect_attributes, TRUE); + + memset(&input_info, 0xcd, sizeof(input_info)); + hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info); todo_wine - check_mft_get_input_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, NULL); + ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetInputStreamInfo returned %#lx\n", hr); + check_member(input_info, empty_input_info, "%I64d", hnsMaxLatency); + check_member(input_info, empty_input_info, "%#lx", dwFlags); + check_member(input_info, empty_input_info, "%#lx", cbSize); + check_member(input_info, empty_input_info, "%#lx", cbMaxLookahead); + check_member(input_info, empty_input_info, "%#lx", cbAlignment); + + memset(&output_info, 0xcd, sizeof(output_info)); + hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info); todo_wine - check_mft_get_output_stream_info(transform, MF_E_TRANSFORM_TYPE_NOT_SET, &empty_output_info); + ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputStreamInfo returned %#lx\n", hr); + todo_wine + check_member(output_info, empty_output_info, "%#lx", dwFlags); + check_member(output_info, empty_output_info, "%#lx", cbSize); + check_member(output_info, empty_output_info, "%#lx", cbAlignment);
hr = IMFTransform_GetOutputAvailableType(transform, 0, 0, &media_type); - todo_wine ok(hr == MF_E_TRANSFORM_TYPE_NOT_SET, "GetOutputAvailableType returned %#lx\n", hr);
i = -1; @@ -5985,9 +6012,7 @@ static void test_wmv_decoder(void) ok(!ret, "Release returned %lu\n", ret); winetest_pop_context(); } - todo_wine ok(hr == MF_E_NO_MORE_TYPES, "GetInputAvailableType returned %#lx\n", hr); - todo_wine ok(i == ARRAY_SIZE(expect_available_inputs), "%lu input media types\n", i);
if (hr == E_NOTIMPL) @@ -6021,10 +6046,28 @@ static void test_wmv_decoder(void)
check_mft_set_output_type_required(transform, transform_tests[j].output_type_desc); check_mft_set_output_type(transform, transform_tests[j].output_type_desc, S_OK); - check_mft_get_output_current_type_(__LINE__, transform, transform_tests[j].expect_output_type_desc, FALSE, FALSE); + check_mft_get_output_current_type_(__LINE__, transform, transform_tests[j].expect_output_type_desc, FALSE, TRUE);
- check_mft_get_input_stream_info(transform, S_OK, transform_tests[j].expect_input_info); - check_mft_get_output_stream_info(transform, S_OK, transform_tests[j].expect_output_info); + memset(&input_info, 0xcd, sizeof(input_info)); + hr = IMFTransform_GetInputStreamInfo(transform, 0, &input_info); + ok(hr == S_OK, "GetInputStreamInfo returned %#lx\n", hr); + check_member(input_info, *transform_tests[j].expect_input_info, "%I64d", hnsMaxLatency); + check_member(input_info, *transform_tests[j].expect_input_info, "%#lx", dwFlags); + todo_wine + check_member(input_info, *transform_tests[j].expect_input_info, "%#lx", cbSize); + check_member(input_info, *transform_tests[j].expect_input_info, "%#lx", cbMaxLookahead); + todo_wine + check_member(input_info, *transform_tests[j].expect_input_info, "%#lx", cbAlignment); + + memset(&output_info, 0xcd, sizeof(output_info)); + hr = IMFTransform_GetOutputStreamInfo(transform, 0, &output_info); + ok(hr == S_OK, "GetOutputStreamInfo returned %#lx\n", hr); + todo_wine + check_member(output_info, *transform_tests[j].expect_output_info, "%#lx", dwFlags); + todo_wine_if(transform_tests[j].expect_output_info == &expect_output_info) + check_member(output_info, *transform_tests[j].expect_output_info, "%#lx", cbSize); + todo_wine + check_member(output_info, *transform_tests[j].expect_output_info, "%#lx", cbAlignment);
load_resource(L"wmvencdata.bin", &wmvenc_data, &wmvenc_data_len);
diff --git a/dlls/winegstreamer/Makefile.in b/dlls/winegstreamer/Makefile.in index 410bbd1dc03..abf3d82d6a8 100644 --- a/dlls/winegstreamer/Makefile.in +++ b/dlls/winegstreamer/Makefile.in @@ -28,5 +28,4 @@ SOURCES = \ wg_transform.c \ winegstreamer_classes.idl \ wm_reader.c \ - wma_decoder.c \ - wmv_decoder.c + wma_decoder.c diff --git a/dlls/winegstreamer/video_decoder.c b/dlls/winegstreamer/video_decoder.c index 4824e317174..5b5d0ec6d97 100644 --- a/dlls/winegstreamer/video_decoder.c +++ b/dlls/winegstreamer/video_decoder.c @@ -24,6 +24,8 @@ #include "mferror.h" #include "mfobjects.h" #include "mftransform.h" +#include "mediaerr.h" +#include "wmcodecdsp.h"
#include "wine/debug.h"
@@ -34,6 +36,35 @@ WINE_DEFAULT_DEBUG_CHANNEL(mfplat); WINE_DECLARE_DEBUG_CHANNEL(winediag);
+struct subtype_info +{ + const GUID *subtype; + WORD bpp; + DWORD compression; +}; + +static const struct subtype_info subtype_info_list[] = +{ + { &MFVideoFormat_NV12, 12, MAKEFOURCC('N', 'V', '1', '2') }, + { &MFVideoFormat_YV12, 12, MAKEFOURCC('Y', 'V', '1', '2') }, + { &MFVideoFormat_IYUV, 12, MAKEFOURCC('I', 'Y', 'U', 'V') }, + { &MFVideoFormat_I420, 12, MAKEFOURCC('I', '4', '2', '0') }, + { &MFVideoFormat_YUY2, 16, MAKEFOURCC('Y', 'U', 'Y', '2') }, + { &MFVideoFormat_UYVY, 16, MAKEFOURCC('U', 'Y', 'V', 'Y') }, + { &MFVideoFormat_YVYU, 16, MAKEFOURCC('Y', 'V', 'Y', 'U') }, + { &MFVideoFormat_NV11, 12, MAKEFOURCC('N', 'V', '1', '1') }, + { &MFVideoFormat_RGB8, 8, BI_RGB }, + { &MFVideoFormat_RGB555, 16, BI_RGB }, + { &MFVideoFormat_RGB565, 16, BI_BITFIELDS }, + { &MFVideoFormat_RGB24, 24, BI_RGB }, + { &MFVideoFormat_RGB32, 32, BI_RGB }, + { &MEDIASUBTYPE_RGB8, 8, BI_RGB }, + { &MEDIASUBTYPE_RGB555, 16, BI_RGB }, + { &MEDIASUBTYPE_RGB565, 16, BI_BITFIELDS }, + { &MEDIASUBTYPE_RGB24, 24, BI_RGB }, + { &MEDIASUBTYPE_RGB32, 32, BI_RGB }, +}; + static const GUID *const video_decoder_output_types[] = { &MFVideoFormat_NV12, @@ -47,6 +78,9 @@ struct video_decoder { IUnknown IUnknown_inner; IMFTransform IMFTransform_iface; + IMediaObject IMediaObject_iface; + IPropertyBag IPropertyBag_iface; + IPropertyStore IPropertyStore_iface; IUnknown *outer; LONG refcount;
@@ -73,6 +107,9 @@ struct video_decoder BOOL allocator_initialized; IMFTransform *copier; IMFMediaBuffer *temp_buffer; + + DMO_MEDIA_TYPE dmo_input_type; + DMO_MEDIA_TYPE dmo_output_type; };
static inline struct video_decoder *impl_from_IUnknown(IUnknown *iface) @@ -90,6 +127,12 @@ static HRESULT WINAPI unknown_QueryInterface(IUnknown *iface, REFIID iid, void * *out = &decoder->IUnknown_inner; else if (IsEqualGUID(iid, &IID_IMFTransform)) *out = &decoder->IMFTransform_iface; + else if (IsEqualGUID(iid, &IID_IMediaObject) && decoder->IMediaObject_iface.lpVtbl) + *out = &decoder->IMediaObject_iface; + else if (IsEqualGUID(iid, &IID_IPropertyBag) && decoder->IPropertyBag_iface.lpVtbl) + *out = &decoder->IPropertyBag_iface; + else if (IsEqualGUID(iid, &IID_IPropertyStore) && decoder->IPropertyStore_iface.lpVtbl) + *out = &decoder->IPropertyStore_iface; else { *out = NULL; @@ -148,6 +191,48 @@ static const IUnknownVtbl unknown_vtbl = unknown_Release, };
+static WORD get_subtype_bpp(const GUID *subtype) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(subtype_info_list); ++i) + { + if (IsEqualGUID(subtype, subtype_info_list[i].subtype)) + return subtype_info_list[i].bpp; + } + + return 0; +} + +static DWORD get_subtype_compression(const GUID *subtype) +{ + unsigned int i; + + for (i = 0; i < ARRAY_SIZE(subtype_info_list); ++i) + { + if (IsEqualGUID(subtype, subtype_info_list[i].subtype)) + return subtype_info_list[i].compression; + } + + return 0; +} + +static const GUID *get_dmo_subtype(const GUID *subtype) +{ + if (IsEqualGUID(subtype, &MFVideoFormat_RGB8)) + return &MEDIASUBTYPE_RGB8; + else if (IsEqualGUID(subtype, &MFVideoFormat_RGB555)) + return &MEDIASUBTYPE_RGB555; + else if (IsEqualGUID(subtype, &MFVideoFormat_RGB565)) + return &MEDIASUBTYPE_RGB565; + else if (IsEqualGUID(subtype, &MFVideoFormat_RGB24)) + return &MEDIASUBTYPE_RGB24; + else if (IsEqualGUID(subtype, &MFVideoFormat_RGB32)) + return &MEDIASUBTYPE_RGB32; + else + return subtype; +} + static struct video_decoder *impl_from_IMFTransform(IMFTransform *iface) { return CONTAINING_RECORD(iface, struct video_decoder, IMFTransform_iface); @@ -194,6 +279,7 @@ static HRESULT create_output_media_type(struct video_decoder *decoder, const GUI IMFMediaType *default_type = decoder->output_type, *stream_type = output_type ? output_type : decoder->stream_type; MFVideoArea default_aperture = {{0}}, aperture; IMFVideoMediaType *video_type; + LONG default_stride, stride; UINT32 value, width, height; UINT64 ratio; HRESULT hr; @@ -226,9 +312,20 @@ static HRESULT create_output_media_type(struct video_decoder *decoder, const GUI if (FAILED(hr) || FAILED(hr = IMFVideoMediaType_SetUINT32(video_type, &MF_MT_SAMPLE_SIZE, value))) goto done;
- if (!output_type || FAILED(IMFMediaType_GetUINT32(output_type, &MF_MT_DEFAULT_STRIDE, &value))) - hr = MFGetStrideForBitmapInfoHeader(subtype->Data1, width, (LONG *)&value); - if (FAILED(hr) || FAILED(hr = IMFVideoMediaType_SetUINT32(video_type, &MF_MT_DEFAULT_STRIDE, value))) + /* WMV decoder uses positive stride by default, and enforces it for YUV formats, + * accepts negative stride for RGB if specified */ + if (FAILED(hr = MFGetStrideForBitmapInfoHeader(subtype->Data1, width, &default_stride))) + goto done; + if (!output_type || FAILED(IMFMediaType_GetUINT32(output_type, &MF_MT_DEFAULT_STRIDE, (UINT32 *)&stride))) + stride = abs(default_stride); + else if (default_stride > 0) + stride = abs(stride); + if (FAILED(hr) || FAILED(hr = IMFVideoMediaType_SetUINT32(video_type, &MF_MT_DEFAULT_STRIDE, stride))) + goto done; + + if (!output_type || FAILED(IMFMediaType_GetUINT32(output_type, &MF_MT_VIDEO_NOMINAL_RANGE, (UINT32 *)&value))) + value = MFNominalRange_Wide; + if (FAILED(hr = IMFVideoMediaType_SetUINT32(video_type, &MF_MT_VIDEO_NOMINAL_RANGE, value))) goto done;
if (!default_type || FAILED(IMFMediaType_GetUINT32(default_type, &MF_MT_INTERLACE_MODE, &value))) @@ -839,8 +936,547 @@ static const IMFTransformVtbl transform_vtbl = transform_ProcessOutput, };
+static inline struct video_decoder *impl_from_IMediaObject(IMediaObject *iface) +{ + return CONTAINING_RECORD(iface, struct video_decoder, IMediaObject_iface); +} + +static HRESULT WINAPI media_object_QueryInterface(IMediaObject *iface, REFIID iid, void **obj) +{ + return IUnknown_QueryInterface(impl_from_IMediaObject(iface)->outer, iid, obj); +} + +static ULONG WINAPI media_object_AddRef(IMediaObject *iface) +{ + return IUnknown_AddRef(impl_from_IMediaObject(iface)->outer); +} + +static ULONG WINAPI media_object_Release(IMediaObject *iface) +{ + return IUnknown_Release(impl_from_IMediaObject(iface)->outer); +} + +static HRESULT WINAPI media_object_GetStreamCount(IMediaObject *iface, DWORD *input, DWORD *output) +{ + TRACE("iface %p, input %p, output %p.\n", iface, input, output); + + if (!input || !output) + return E_POINTER; + + *input = *output = 1; + + return S_OK; +} + +static HRESULT WINAPI media_object_GetInputStreamInfo(IMediaObject *iface, DWORD index, DWORD *flags) +{ + FIXME("iface %p, index %lu, flags %p stub!\n", iface, index, flags); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_GetOutputStreamInfo(IMediaObject *iface, DWORD index, DWORD *flags) +{ + FIXME("iface %p, index %lu, flags %p stub!\n", iface, index, flags); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_GetInputType(IMediaObject *iface, DWORD index, DWORD type_index, + DMO_MEDIA_TYPE *type) +{ + struct video_decoder *decoder = impl_from_IMediaObject(iface); + + TRACE("iface %p, index %lu, type_index %lu, type %p.\n", iface, index, type_index, type); + + if (index > 0) + return DMO_E_INVALIDSTREAMINDEX; + if (type_index >= decoder->input_type_count) + return DMO_E_NO_MORE_ITEMS; + if (!type) + return S_OK; + + memset(type, 0, sizeof(*type)); + type->majortype = MFMediaType_Video; + type->subtype = *get_dmo_subtype(decoder->input_types[type_index]); + type->bFixedSizeSamples = FALSE; + type->bTemporalCompression = TRUE; + type->lSampleSize = 0; + + return S_OK; +} + +static HRESULT WINAPI media_object_GetOutputType(IMediaObject *iface, DWORD index, DWORD type_index, + DMO_MEDIA_TYPE *type) +{ + struct video_decoder *decoder = impl_from_IMediaObject(iface); + UINT64 frame_size, frame_rate; + IMFMediaType *media_type; + VIDEOINFOHEADER *info; + const GUID *subtype; + LONG width, height; + UINT32 image_size; + HRESULT hr; + + TRACE("iface %p, index %lu, type_index %lu, type %p.\n", iface, index, type_index, type); + + if (index > 0) + return DMO_E_INVALIDSTREAMINDEX; + if (type_index >= decoder->output_type_count) + return DMO_E_NO_MORE_ITEMS; + if (!type) + return S_OK; + if (IsEqualGUID(&decoder->dmo_input_type.majortype, &GUID_NULL)) + return DMO_E_TYPE_NOT_SET; + + if (FAILED(hr = MFCreateMediaTypeFromRepresentation(AM_MEDIA_TYPE_REPRESENTATION, + &decoder->dmo_input_type, &media_type))) + return hr; + + if (FAILED(IMFMediaType_GetUINT64(media_type, &MF_MT_FRAME_SIZE, &frame_size))) + frame_size = 0; + if (FAILED(IMFMediaType_GetUINT64(media_type, &MF_MT_FRAME_RATE, &frame_rate))) + frame_rate = (UINT64)1 << 32 | 1; + + width = frame_size >> 32; + height = (UINT32)frame_size; + subtype = get_dmo_subtype(decoder->output_types[type_index]); + if (FAILED(hr = MFCalculateImageSize(subtype, width, height, &image_size))) + { + FIXME("Failed to get image size of subtype %s.\n", debugstr_guid(subtype)); + IMFMediaType_Release(media_type); + return hr; + } + + memset(type, 0, sizeof(*type)); + type->majortype = MFMediaType_Video; + type->subtype = *subtype; + type->bFixedSizeSamples = TRUE; + type->bTemporalCompression = FALSE; + type->lSampleSize = image_size; + type->formattype = FORMAT_VideoInfo; + type->cbFormat = sizeof(VIDEOINFOHEADER); + type->pbFormat = CoTaskMemAlloc(type->cbFormat); + memset(type->pbFormat, 0, type->cbFormat); + + info = (VIDEOINFOHEADER *)type->pbFormat; + info->rcSource.right = width; + info->rcSource.bottom = height; + info->rcTarget.right = width; + info->rcTarget.bottom = height; + if (frame_rate) + MFFrameRateToAverageTimePerFrame(frame_rate >> 32, frame_rate, (UINT64 *)&info->AvgTimePerFrame); + info->bmiHeader.biSize = sizeof(info->bmiHeader); + info->bmiHeader.biWidth = width; + info->bmiHeader.biHeight = height; + info->bmiHeader.biPlanes = 1; + info->bmiHeader.biBitCount = get_subtype_bpp(subtype); + info->bmiHeader.biCompression = get_subtype_compression(subtype); + info->bmiHeader.biSizeImage = image_size; + + IMFMediaType_Release(media_type); + return S_OK; +} + +static HRESULT WINAPI media_object_SetInputType(IMediaObject *iface, DWORD index, + const DMO_MEDIA_TYPE *type, DWORD flags) +{ + struct video_decoder *decoder = impl_from_IMediaObject(iface); + IMFMediaType *media_type; + unsigned int i; + + TRACE("iface %p, index %lu, type %p, flags %#lx.\n", iface, index, type, flags); + + if (index > 0) + return DMO_E_INVALIDSTREAMINDEX; + + if (!type) + { + if (flags & DMO_SET_TYPEF_CLEAR) + { + FreeMediaType(&decoder->dmo_input_type); + memset(&decoder->dmo_input_type, 0, sizeof(decoder->dmo_input_type)); + if (decoder->wg_transform) + { + wg_transform_destroy(decoder->wg_transform); + decoder->wg_transform = 0; + } + return S_OK; + } + return DMO_E_TYPE_NOT_ACCEPTED; + } + + if (!IsEqualGUID(&type->majortype, &MEDIATYPE_Video)) + return DMO_E_TYPE_NOT_ACCEPTED; + + for (i = 0; i < decoder->input_type_count; ++i) + if (IsEqualGUID(&type->subtype, get_dmo_subtype(decoder->input_types[i]))) + break; + if (i == decoder->input_type_count) + return DMO_E_TYPE_NOT_ACCEPTED; + + if (FAILED(MFCreateMediaTypeFromRepresentation(AM_MEDIA_TYPE_REPRESENTATION, + (void *)type, &media_type))) + return DMO_E_TYPE_NOT_ACCEPTED; + IMFMediaType_Release(media_type); + + if (flags & DMO_SET_TYPEF_TEST_ONLY) + return S_OK; + + FreeMediaType(&decoder->dmo_input_type); + CopyMediaType(&decoder->dmo_input_type, type); + if (decoder->wg_transform) + { + wg_transform_destroy(decoder->wg_transform); + decoder->wg_transform = 0; + } + + return S_OK; +} + +static HRESULT WINAPI media_object_SetOutputType(IMediaObject *iface, DWORD index, + const DMO_MEDIA_TYPE *type, DWORD flags) +{ + struct video_decoder *decoder = impl_from_IMediaObject(iface); + IMFMediaType *media_type; + unsigned int i; + HRESULT hr; + + TRACE("iface %p, index %lu, type %p, flags %#lx,\n", iface, index, type, flags); + + if (index > 0) + return DMO_E_INVALIDSTREAMINDEX; + + if (!type) + { + if (flags & DMO_SET_TYPEF_CLEAR) + { + FreeMediaType(&decoder->dmo_output_type); + memset(&decoder->dmo_output_type, 0, sizeof(decoder->dmo_output_type)); + if (decoder->wg_transform) + { + wg_transform_destroy(decoder->wg_transform); + decoder->wg_transform = 0; + } + return S_OK; + } + return E_POINTER; + } + + if (IsEqualGUID(&decoder->dmo_input_type.majortype, &GUID_NULL)) + return DMO_E_TYPE_NOT_SET; + + if (!IsEqualGUID(&type->majortype, &MEDIATYPE_Video)) + return DMO_E_TYPE_NOT_ACCEPTED; + + for (i = 0; i < decoder->output_type_count; ++i) + if (IsEqualGUID(&type->subtype, get_dmo_subtype(decoder->output_types[i]))) + break; + if (i == decoder->output_type_count) + return DMO_E_TYPE_NOT_ACCEPTED; + + if (FAILED(MFCreateMediaTypeFromRepresentation(AM_MEDIA_TYPE_REPRESENTATION, + (void *)type, &media_type))) + return DMO_E_TYPE_NOT_ACCEPTED; + IMFMediaType_Release(media_type); + + if (flags & DMO_SET_TYPEF_TEST_ONLY) + return S_OK; + + FreeMediaType(&decoder->dmo_output_type); + CopyMediaType(&decoder->dmo_output_type, type); + + /* Set up wg_transform. */ + if (decoder->wg_transform) + { + wg_transform_destroy(decoder->wg_transform); + decoder->wg_transform = 0; + } + if (FAILED(hr = wg_transform_create_quartz(&decoder->dmo_input_type, type, + &decoder->wg_transform_attrs, &decoder->wg_transform))) + return hr; + + return S_OK; +} + +static HRESULT WINAPI media_object_GetInputCurrentType(IMediaObject *iface, DWORD index, DMO_MEDIA_TYPE *type) +{ + FIXME("iface %p, index %lu, type %p stub!\n", iface, index, type); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_GetOutputCurrentType(IMediaObject *iface, DWORD index, DMO_MEDIA_TYPE *type) +{ + FIXME("iface %p, index %lu, type %p stub!\n", iface, index, type); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_GetInputSizeInfo(IMediaObject *iface, DWORD index, DWORD *size, + DWORD *lookahead, DWORD *alignment) +{ + FIXME("iface %p, index %lu, size %p, lookahead %p, alignment %p stub!\n", iface, index, size, + lookahead, alignment); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_GetOutputSizeInfo(IMediaObject *iface, DWORD index, DWORD *size, DWORD *alignment) +{ + struct video_decoder *decoder = impl_from_IMediaObject(iface); + IMFMediaType *media_type; + HRESULT hr; + + TRACE("iface %p, index %lu, size %p, alignment %p.\n", iface, index, size, alignment); + + if (index > 0) + return DMO_E_INVALIDSTREAMINDEX; + if (IsEqualGUID(&decoder->dmo_output_type.majortype, &GUID_NULL)) + return DMO_E_TYPE_NOT_SET; + + if (FAILED(hr = MFCreateMediaType(&media_type))) + return hr; + if (SUCCEEDED(hr = MFInitMediaTypeFromAMMediaType(media_type, &decoder->dmo_output_type)) + && SUCCEEDED(hr = IMFMediaType_GetUINT32(media_type, &MF_MT_SAMPLE_SIZE, (UINT32 *)size))) + *alignment = 1; + IMFMediaType_Release(media_type); + + return S_OK; +} + +static HRESULT WINAPI media_object_GetInputMaxLatency(IMediaObject *iface, DWORD index, REFERENCE_TIME *latency) +{ + FIXME("iface %p, index %lu, latency %p stub!\n", iface, index, latency); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_SetInputMaxLatency(IMediaObject *iface, DWORD index, REFERENCE_TIME latency) +{ + FIXME("iface %p, index %lu, latency %s stub!\n", iface, index, wine_dbgstr_longlong(latency)); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_Flush(IMediaObject *iface) +{ + struct video_decoder *decoder = impl_from_IMediaObject(iface); + HRESULT hr; + + TRACE("iface %p.\n", iface); + + if (FAILED(hr = wg_transform_flush(decoder->wg_transform))) + return hr; + + wg_sample_queue_flush(decoder->wg_sample_queue, TRUE); + + return S_OK; +} + +static HRESULT WINAPI media_object_Discontinuity(IMediaObject *iface, DWORD index) +{ + TRACE("iface %p, index %lu.\n", iface, index); + + if (index > 0) + return DMO_E_INVALIDSTREAMINDEX; + + return S_OK; +} + +static HRESULT WINAPI media_object_AllocateStreamingResources(IMediaObject *iface) +{ + FIXME("iface %p stub!\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_FreeStreamingResources(IMediaObject *iface) +{ + FIXME("iface %p stub!\n", iface); + return E_NOTIMPL; +} + +static HRESULT WINAPI media_object_GetInputStatus(IMediaObject *iface, DWORD index, DWORD *flags) +{ + TRACE("iface %p, index %lu, flags %p.\n", iface, index, flags); + + if (index > 0) + return DMO_E_INVALIDSTREAMINDEX; + if (!flags) + return E_POINTER; + + *flags = DMO_INPUT_STATUSF_ACCEPT_DATA; + + return S_OK; +} + +static HRESULT WINAPI media_object_ProcessInput(IMediaObject *iface, DWORD index, + IMediaBuffer *buffer, DWORD flags, REFERENCE_TIME timestamp, REFERENCE_TIME timelength) +{ + struct video_decoder *decoder = impl_from_IMediaObject(iface); + + TRACE("iface %p, index %lu, buffer %p, flags %#lx, timestamp %s, timelength %s.\n", iface, + index, buffer, flags, wine_dbgstr_longlong(timestamp), wine_dbgstr_longlong(timelength)); + + if (!decoder->wg_transform) + return DMO_E_TYPE_NOT_SET; + + return wg_transform_push_dmo(decoder->wg_transform, buffer, flags, timestamp, timelength, decoder->wg_sample_queue); +} + +static HRESULT WINAPI media_object_ProcessOutput(IMediaObject *iface, DWORD flags, DWORD count, + DMO_OUTPUT_DATA_BUFFER *buffers, DWORD *status) +{ + struct video_decoder *decoder = impl_from_IMediaObject(iface); + HRESULT hr; + + TRACE("iface %p, flags %#lx, count %lu, buffers %p, status %p.\n", iface, flags, count, buffers, status); + + if (!decoder->wg_transform) + return DMO_E_TYPE_NOT_SET; + + if ((hr = wg_transform_read_dmo(decoder->wg_transform, buffers)) == MF_E_TRANSFORM_STREAM_CHANGE) + hr = wg_transform_read_dmo(decoder->wg_transform, buffers); + + if (SUCCEEDED(hr)) + wg_sample_queue_flush(decoder->wg_sample_queue, false); + + return hr; +} + +static HRESULT WINAPI media_object_Lock(IMediaObject *iface, LONG lock) +{ + FIXME("iface %p, lock %ld stub!\n", iface, lock); + return E_NOTIMPL; +} + +static const IMediaObjectVtbl media_object_vtbl = +{ + media_object_QueryInterface, + media_object_AddRef, + media_object_Release, + media_object_GetStreamCount, + media_object_GetInputStreamInfo, + media_object_GetOutputStreamInfo, + media_object_GetInputType, + media_object_GetOutputType, + media_object_SetInputType, + media_object_SetOutputType, + media_object_GetInputCurrentType, + media_object_GetOutputCurrentType, + media_object_GetInputSizeInfo, + media_object_GetOutputSizeInfo, + media_object_GetInputMaxLatency, + media_object_SetInputMaxLatency, + media_object_Flush, + media_object_Discontinuity, + media_object_AllocateStreamingResources, + media_object_FreeStreamingResources, + media_object_GetInputStatus, + media_object_ProcessInput, + media_object_ProcessOutput, + media_object_Lock, +}; + +static inline struct video_decoder *impl_from_IPropertyBag(IPropertyBag *iface) +{ + return CONTAINING_RECORD(iface, struct video_decoder, IPropertyBag_iface); +} + +static HRESULT WINAPI property_bag_QueryInterface(IPropertyBag *iface, REFIID iid, void **out) +{ + return IUnknown_QueryInterface(impl_from_IPropertyBag(iface)->outer, iid, out); +} + +static ULONG WINAPI property_bag_AddRef(IPropertyBag *iface) +{ + return IUnknown_AddRef(impl_from_IPropertyBag(iface)->outer); +} + +static ULONG WINAPI property_bag_Release(IPropertyBag *iface) +{ + return IUnknown_Release(impl_from_IPropertyBag(iface)->outer); +} + +static HRESULT WINAPI property_bag_Read(IPropertyBag *iface, const WCHAR *prop_name, VARIANT *value, + IErrorLog *error_log) +{ + FIXME("iface %p, prop_name %s, value %p, error_log %p stub!\n", iface, debugstr_w(prop_name), value, error_log); + return E_NOTIMPL; +} + +static HRESULT WINAPI property_bag_Write(IPropertyBag *iface, const WCHAR *prop_name, VARIANT *value) +{ + FIXME("iface %p, prop_name %s, value %p stub!\n", iface, debugstr_w(prop_name), value); + return S_OK; +} + +static const IPropertyBagVtbl property_bag_vtbl = +{ + property_bag_QueryInterface, + property_bag_AddRef, + property_bag_Release, + property_bag_Read, + property_bag_Write, +}; + +static inline struct video_decoder *impl_from_IPropertyStore(IPropertyStore *iface) +{ + return CONTAINING_RECORD(iface, struct video_decoder, IPropertyStore_iface); +} + +static HRESULT WINAPI property_store_QueryInterface(IPropertyStore *iface, REFIID iid, void **out) +{ + return IUnknown_QueryInterface(impl_from_IPropertyStore(iface)->outer, iid, out); +} + +static ULONG WINAPI property_store_AddRef(IPropertyStore *iface) +{ + return IUnknown_AddRef(impl_from_IPropertyStore(iface)->outer); +} + +static ULONG WINAPI property_store_Release(IPropertyStore *iface) +{ + return IUnknown_Release(impl_from_IPropertyStore(iface)->outer); +} + +static HRESULT WINAPI property_store_GetCount(IPropertyStore *iface, DWORD *count) +{ + FIXME("iface %p, count %p stub!\n", iface, count); + return E_NOTIMPL; +} + +static HRESULT WINAPI property_store_GetAt(IPropertyStore *iface, DWORD index, PROPERTYKEY *key) +{ + FIXME("iface %p, index %lu, key %p stub!\n", iface, index, key); + return E_NOTIMPL; +} + +static HRESULT WINAPI property_store_GetValue(IPropertyStore *iface, REFPROPERTYKEY key, PROPVARIANT *value) +{ + FIXME("iface %p, key %p, value %p stub!\n", iface, key, value); + return E_NOTIMPL; +} + +static HRESULT WINAPI property_store_SetValue(IPropertyStore *iface, REFPROPERTYKEY key, REFPROPVARIANT value) +{ + FIXME("iface %p, key %p, value %p stub!\n", iface, key, value); + return E_NOTIMPL; +} + +static HRESULT WINAPI property_store_Commit(IPropertyStore *iface) +{ + FIXME("iface %p stub!\n", iface); + return E_NOTIMPL; +} + +static const IPropertyStoreVtbl property_store_vtbl = +{ + property_store_QueryInterface, + property_store_AddRef, + property_store_Release, + property_store_GetCount, + property_store_GetAt, + property_store_GetValue, + property_store_SetValue, + property_store_Commit, +}; + static HRESULT video_decoder_create_with_types(const GUID *const *input_types, UINT input_type_count, - const GUID *const *output_types, UINT output_type_count, IUnknown *outer, IMFTransform **ret) + const GUID *const *output_types, UINT output_type_count, IUnknown *outer, struct video_decoder **out) { struct video_decoder *decoder; HRESULT hr; @@ -881,8 +1517,8 @@ static HRESULT video_decoder_create_with_types(const GUID *const *input_types, U decoder->wg_transform_attrs.output_plane_align = 15; decoder->wg_transform_attrs.input_queue_length = 15;
- *ret = &decoder->IMFTransform_iface; - TRACE("Created decoder %p\n", *ret); + *out = decoder; + TRACE("Created decoder %p\n", decoder); return S_OK;
failed: @@ -922,7 +1558,6 @@ HRESULT h264_decoder_create(REFIID riid, void **out) struct wg_transform_attrs attrs = {0}; struct video_decoder *decoder; wg_transform_t transform; - IMFTransform *iface; HRESULT hr;
TRACE("riid %s, out %p.\n", debugstr_guid(riid), out); @@ -935,13 +1570,12 @@ HRESULT h264_decoder_create(REFIID riid, void **out) wg_transform_destroy(transform);
if (FAILED(hr = video_decoder_create_with_types(h264_decoder_input_types, ARRAY_SIZE(h264_decoder_input_types), - video_decoder_output_types, ARRAY_SIZE(video_decoder_output_types), NULL, &iface))) + video_decoder_output_types, ARRAY_SIZE(video_decoder_output_types), NULL, &decoder))) return hr; - decoder = impl_from_IMFTransform(iface);
if (FAILED(hr = IMFAttributes_SetUINT32(decoder->attributes, &AVDecVideoAcceleration_H264, TRUE))) { - IMFTransform_Release(iface); + IMFTransform_Release(&decoder->IMFTransform_iface); return hr; }
@@ -954,8 +1588,10 @@ HRESULT h264_decoder_create(REFIID riid, void **out)
decoder->wg_transform_attrs.allow_size_change = TRUE;
- hr = IMFTransform_QueryInterface(iface, riid, out); - IMFTransform_Release(iface); + TRACE("Created h264 transform %p.\n", &decoder->IMFTransform_iface); + + hr = IMFTransform_QueryInterface(&decoder->IMFTransform_iface, riid, out); + IMFTransform_Release(&decoder->IMFTransform_iface); return hr; }
@@ -979,11 +1615,97 @@ static const GUID *const iv50_decoder_output_types[] =
HRESULT WINAPI winegstreamer_create_video_decoder(IMFTransform **out) { + struct video_decoder *decoder; + HRESULT hr; + TRACE("out %p.\n", out);
if (!init_gstreamer()) return E_FAIL;
- return video_decoder_create_with_types(iv50_decoder_input_types, ARRAY_SIZE(iv50_decoder_input_types), - iv50_decoder_output_types, ARRAY_SIZE(iv50_decoder_output_types), NULL, out); + if (FAILED(hr = video_decoder_create_with_types(iv50_decoder_input_types, ARRAY_SIZE(iv50_decoder_input_types), + iv50_decoder_output_types, ARRAY_SIZE(iv50_decoder_output_types), NULL, &decoder))) + return hr; + + TRACE("Created iv50 transform %p.\n", &decoder->IMFTransform_iface); + + *out = &decoder->IMFTransform_iface; + return S_OK; +} + +extern const GUID MEDIASUBTYPE_VC1S; +extern const GUID MEDIASUBTYPE_WMV_Unknown; +static const GUID *const wmv_decoder_input_types[] = +{ + &MEDIASUBTYPE_WMV1, + &MEDIASUBTYPE_WMV2, + &MEDIASUBTYPE_WMVA, + &MEDIASUBTYPE_WMVP, + &MEDIASUBTYPE_WVP2, + &MEDIASUBTYPE_WMV_Unknown, + &MEDIASUBTYPE_WVC1, + &MEDIASUBTYPE_WMV3, + &MEDIASUBTYPE_VC1S, +}; +static const GUID *const wmv_decoder_output_types[] = +{ + &MFVideoFormat_NV12, + &MFVideoFormat_YV12, + &MFVideoFormat_IYUV, + &MFVideoFormat_I420, + &MFVideoFormat_YUY2, + &MFVideoFormat_UYVY, + &MFVideoFormat_YVYU, + &MFVideoFormat_NV11, + &MFVideoFormat_RGB32, + &MFVideoFormat_RGB24, + &MFVideoFormat_RGB565, + &MFVideoFormat_RGB555, + &MFVideoFormat_RGB8, +}; + +HRESULT wmv_decoder_create(IUnknown *outer, IUnknown **out) +{ + static const struct wg_format input_format = + { + .major_type = WG_MAJOR_TYPE_VIDEO_WMV, + .u.video.format = WG_VIDEO_FORMAT_WMV3, + }; + static const struct wg_format output_format = + { + .major_type = WG_MAJOR_TYPE_VIDEO, + .u.video = + { + .format = WG_VIDEO_FORMAT_NV12, + .width = 1920, + .height = 1080, + }, + }; + struct wg_transform_attrs attrs = {0}; + struct video_decoder *decoder; + wg_transform_t transform; + HRESULT hr; + + TRACE("outer %p, out %p.\n", outer, out); + + if (!(transform = wg_transform_create(&input_format, &output_format, &attrs))) + { + ERR_(winediag)("GStreamer doesn't support WMV decoding, please install appropriate plugins.\n"); + return E_FAIL; + } + wg_transform_destroy(transform); + + if (FAILED(hr = video_decoder_create_with_types(wmv_decoder_input_types, ARRAY_SIZE(wmv_decoder_input_types), + wmv_decoder_output_types, ARRAY_SIZE(wmv_decoder_output_types), outer, &decoder))) + return hr; + + decoder->IMediaObject_iface.lpVtbl = &media_object_vtbl; + decoder->IPropertyBag_iface.lpVtbl = &property_bag_vtbl; + decoder->IPropertyStore_iface.lpVtbl = &property_store_vtbl; + + TRACE("Created wmv transform %p, media object %p.\n", + &decoder->IMFTransform_iface, &decoder->IMediaObject_iface); + + *out = &decoder->IUnknown_inner; + return S_OK; } diff --git a/dlls/winegstreamer/wmv_decoder.c b/dlls/winegstreamer/wmv_decoder.c deleted file mode 100644 index 446641f0298..00000000000 --- a/dlls/winegstreamer/wmv_decoder.c +++ /dev/null @@ -1,942 +0,0 @@ -/* Copyright 2022 Rémi Bernon for CodeWeavers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include "gst_private.h" - -#include "mfapi.h" -#include "mferror.h" -#include "mediaerr.h" -#include "mfobjects.h" -#include "mftransform.h" -#include "wmcodecdsp.h" -#include "initguid.h" - -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(mfplat); -WINE_DECLARE_DEBUG_CHANNEL(winediag); - -extern const GUID MEDIASUBTYPE_VC1S; -extern const GUID MEDIASUBTYPE_WMV_Unknown; - -struct decoder_type -{ - const GUID *subtype; - WORD bpp; - DWORD compression; -}; - -static const GUID *const wmv_decoder_input_types[] = -{ - &MEDIASUBTYPE_WMV1, - &MEDIASUBTYPE_WMV2, - &MEDIASUBTYPE_WMVA, - &MEDIASUBTYPE_WMVP, - &MEDIASUBTYPE_WVP2, - &MEDIASUBTYPE_WMV_Unknown, - &MEDIASUBTYPE_WVC1, - &MEDIASUBTYPE_WMV3, - &MEDIASUBTYPE_VC1S, -}; - -static const struct decoder_type wmv_decoder_output_types[] = -{ - { &MEDIASUBTYPE_NV12, 12, MAKEFOURCC('N', 'V', '1', '2') }, - { &MEDIASUBTYPE_YV12, 12, MAKEFOURCC('Y', 'V', '1', '2') }, - { &MEDIASUBTYPE_IYUV, 12, MAKEFOURCC('I', 'Y', 'U', 'V') }, - { &MEDIASUBTYPE_I420, 12, MAKEFOURCC('I', '4', '2', '0') }, - { &MEDIASUBTYPE_YUY2, 16, MAKEFOURCC('Y', 'U', 'Y', '2') }, - { &MEDIASUBTYPE_UYVY, 16, MAKEFOURCC('U', 'Y', 'V', 'Y') }, - { &MEDIASUBTYPE_YVYU, 16, MAKEFOURCC('Y', 'V', 'Y', 'U') }, - { &MEDIASUBTYPE_NV11, 12, MAKEFOURCC('N', 'V', '1', '1') }, - { &MEDIASUBTYPE_RGB32, 32, BI_RGB }, - { &MEDIASUBTYPE_RGB24, 24, BI_RGB }, - { &MEDIASUBTYPE_RGB565, 16, BI_BITFIELDS }, - { &MEDIASUBTYPE_RGB555, 16, BI_RGB }, - { &MEDIASUBTYPE_RGB8, 8, BI_RGB }, -}; - -struct wmv_decoder -{ - IUnknown IUnknown_inner; - IMFTransform IMFTransform_iface; - IMediaObject IMediaObject_iface; - IPropertyBag IPropertyBag_iface; - IPropertyStore IPropertyStore_iface; - IUnknown *outer; - LONG refcount; - - DMO_MEDIA_TYPE input_type; - DMO_MEDIA_TYPE output_type; - GUID output_subtype; - - wg_transform_t wg_transform; - struct wg_sample_queue *wg_sample_queue; -}; - -static inline struct wmv_decoder *impl_from_IUnknown(IUnknown *iface) -{ - return CONTAINING_RECORD(iface, struct wmv_decoder, IUnknown_inner); -} - -static HRESULT WINAPI unknown_QueryInterface(IUnknown *iface, REFIID iid, void **out) -{ - struct wmv_decoder *impl = impl_from_IUnknown(iface); - - TRACE("iface %p, iid %s, out %p.\n", iface, debugstr_guid(iid), out); - - if (IsEqualGUID(iid, &IID_IUnknown)) - *out = &impl->IUnknown_inner; - else if (IsEqualGUID(iid, &IID_IMFTransform)) - *out = &impl->IMFTransform_iface; - else if (IsEqualGUID(iid, &IID_IMediaObject)) - *out = &impl->IMediaObject_iface; - else if (IsEqualIID(iid, &IID_IPropertyBag)) - *out = &impl->IPropertyBag_iface; - else if (IsEqualIID(iid, &IID_IPropertyStore)) - *out = &impl->IPropertyStore_iface; - else - { - *out = NULL; - WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(iid)); - return E_NOINTERFACE; - } - - IUnknown_AddRef((IUnknown *)*out); - return S_OK; -} - -static ULONG WINAPI unknown_AddRef(IUnknown *iface) -{ - struct wmv_decoder *impl = impl_from_IUnknown(iface); - ULONG refcount = InterlockedIncrement(&impl->refcount); - - TRACE("iface %p increasing refcount to %lu.\n", iface, refcount); - - return refcount; -} - -static ULONG WINAPI unknown_Release(IUnknown *iface) -{ - struct wmv_decoder *impl = impl_from_IUnknown(iface); - ULONG refcount = InterlockedDecrement(&impl->refcount); - - TRACE("iface %p decreasing refcount to %lu.\n", iface, refcount); - - if (!refcount) - { - if (impl->wg_transform) - wg_transform_destroy(impl->wg_transform); - wg_sample_queue_destroy(impl->wg_sample_queue); - free(impl); - } - - return refcount; -} - -static const IUnknownVtbl unknown_vtbl = -{ - unknown_QueryInterface, - unknown_AddRef, - unknown_Release, -}; - -static struct wmv_decoder *impl_from_IMFTransform(IMFTransform *iface) -{ - return CONTAINING_RECORD(iface, struct wmv_decoder, IMFTransform_iface); -} - -static HRESULT WINAPI transform_QueryInterface(IMFTransform *iface, REFIID iid, void **out) -{ - return IUnknown_QueryInterface(impl_from_IMFTransform(iface)->outer, iid, out); -} - -static ULONG WINAPI transform_AddRef(IMFTransform *iface) -{ - return IUnknown_AddRef(impl_from_IMFTransform(iface)->outer); -} - -static ULONG WINAPI transform_Release(IMFTransform *iface) -{ - return IUnknown_Release(impl_from_IMFTransform(iface)->outer); -} - -static HRESULT WINAPI transform_GetStreamLimits(IMFTransform *iface, DWORD *input_minimum, - DWORD *input_maximum, DWORD *output_minimum, DWORD *output_maximum) -{ - TRACE("iface %p, input_minimum %p, input_maximum %p, output_minimum %p, output_maximum %p.\n", - iface, input_minimum, input_maximum, output_minimum, output_maximum); - *input_minimum = *input_maximum = *output_minimum = *output_maximum = 1; - return S_OK; -} - -static HRESULT WINAPI transform_GetStreamCount(IMFTransform *iface, DWORD *inputs, DWORD *outputs) -{ - TRACE("iface %p, inputs %p, outputs %p.\n", iface, inputs, outputs); - *inputs = *outputs = 1; - return S_OK; -} - -static HRESULT WINAPI transform_GetStreamIDs(IMFTransform *iface, DWORD input_size, DWORD *inputs, - DWORD output_size, DWORD *outputs) -{ - TRACE("iface %p, input_size %lu, inputs %p, output_size %lu, outputs %p.\n", iface, - input_size, inputs, output_size, outputs); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_GetInputStreamInfo(IMFTransform *iface, DWORD id, MFT_INPUT_STREAM_INFO *info) -{ - FIXME("iface %p, id %#lx, info %p stub!\n", iface, id, info); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_GetOutputStreamInfo(IMFTransform *iface, DWORD id, MFT_OUTPUT_STREAM_INFO *info) -{ - FIXME("iface %p, id %#lx, info %p stub!\n", iface, id, info); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_GetAttributes(IMFTransform *iface, IMFAttributes **attributes) -{ - FIXME("iface %p, attributes %p stub!\n", iface, attributes); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_GetInputStreamAttributes(IMFTransform *iface, DWORD id, IMFAttributes **attributes) -{ - TRACE("iface %p, id %#lx, attributes %p.\n", iface, id, attributes); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_GetOutputStreamAttributes(IMFTransform *iface, DWORD id, IMFAttributes **attributes) -{ - FIXME("iface %p, id %#lx, attributes %p stub!\n", iface, id, attributes); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_DeleteInputStream(IMFTransform *iface, DWORD id) -{ - TRACE("iface %p, id %#lx.\n", iface, id); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_AddInputStreams(IMFTransform *iface, DWORD streams, DWORD *ids) -{ - TRACE("iface %p, streams %lu, ids %p.\n", iface, streams, ids); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_GetInputAvailableType(IMFTransform *iface, DWORD id, DWORD index, - IMFMediaType **type) -{ - FIXME("iface %p, id %#lx, index %lu, type %p stub!\n", iface, id, index, type); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_GetOutputAvailableType(IMFTransform *iface, DWORD id, DWORD index, - IMFMediaType **type) -{ - FIXME("iface %p, id %#lx, index %lu, type %p stub!\n", iface, id, index, type); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_SetInputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags) -{ - FIXME("iface %p, id %#lx, type %p, flags %#lx stub!\n", iface, id, type, flags); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMFMediaType *type, DWORD flags) -{ - FIXME("iface %p, id %#lx, type %p, flags %#lx stub!\n", iface, id, type, flags); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_GetInputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type) -{ - FIXME("iface %p, id %#lx, type %p stub!\n", iface, id, type); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_GetOutputCurrentType(IMFTransform *iface, DWORD id, IMFMediaType **type) -{ - FIXME("iface %p, id %#lx, type %p stub!\n", iface, id, type); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_GetInputStatus(IMFTransform *iface, DWORD id, DWORD *flags) -{ - FIXME("iface %p, id %#lx, flags %p stub!\n", iface, id, flags); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_GetOutputStatus(IMFTransform *iface, DWORD *flags) -{ - FIXME("iface %p, flags %p stub!\n", iface, flags); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_SetOutputBounds(IMFTransform *iface, LONGLONG lower, LONGLONG upper) -{ - TRACE("iface %p, lower %I64d, upper %I64d.\n", iface, lower, upper); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_ProcessEvent(IMFTransform *iface, DWORD id, IMFMediaEvent *event) -{ - FIXME("iface %p, id %#lx, event %p stub!\n", iface, id, event); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_TYPE message, ULONG_PTR param) -{ - FIXME("iface %p, message %#x, param %#Ix stub!\n", iface, message, param); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags) -{ - FIXME("iface %p, id %#lx, sample %p, flags %#lx stub!\n", iface, id, sample, flags); - return E_NOTIMPL; -} - -static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, DWORD count, - MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status) -{ - FIXME("iface %p, flags %#lx, count %lu, samples %p, status %p stub!\n", iface, flags, count, samples, status); - return E_NOTIMPL; -} - -static const IMFTransformVtbl transform_vtbl = -{ - transform_QueryInterface, - transform_AddRef, - transform_Release, - transform_GetStreamLimits, - transform_GetStreamCount, - transform_GetStreamIDs, - transform_GetInputStreamInfo, - transform_GetOutputStreamInfo, - transform_GetAttributes, - transform_GetInputStreamAttributes, - transform_GetOutputStreamAttributes, - transform_DeleteInputStream, - transform_AddInputStreams, - transform_GetInputAvailableType, - transform_GetOutputAvailableType, - transform_SetInputType, - transform_SetOutputType, - transform_GetInputCurrentType, - transform_GetOutputCurrentType, - transform_GetInputStatus, - transform_GetOutputStatus, - transform_SetOutputBounds, - transform_ProcessEvent, - transform_ProcessMessage, - transform_ProcessInput, - transform_ProcessOutput, -}; - -static inline struct wmv_decoder *impl_from_IMediaObject(IMediaObject *iface) -{ - return CONTAINING_RECORD(iface, struct wmv_decoder, IMediaObject_iface); -} - -static HRESULT WINAPI media_object_QueryInterface(IMediaObject *iface, REFIID iid, void **obj) -{ - return IUnknown_QueryInterface(impl_from_IMediaObject(iface)->outer, iid, obj); -} - -static ULONG WINAPI media_object_AddRef(IMediaObject *iface) -{ - return IUnknown_AddRef(impl_from_IMediaObject(iface)->outer); -} - -static ULONG WINAPI media_object_Release(IMediaObject *iface) -{ - return IUnknown_Release(impl_from_IMediaObject(iface)->outer); -} - -static HRESULT WINAPI media_object_GetStreamCount(IMediaObject *iface, DWORD *input, DWORD *output) -{ - TRACE("iface %p, input %p, output %p.\n", iface, input, output); - - if (!input || !output) - return E_POINTER; - - *input = *output = 1; - - return S_OK; -} - -static HRESULT WINAPI media_object_GetInputStreamInfo(IMediaObject *iface, DWORD index, DWORD *flags) -{ - FIXME("iface %p, index %lu, flags %p stub!\n", iface, index, flags); - return E_NOTIMPL; -} - -static HRESULT WINAPI media_object_GetOutputStreamInfo(IMediaObject *iface, DWORD index, DWORD *flags) -{ - FIXME("iface %p, index %lu, flags %p stub!\n", iface, index, flags); - return E_NOTIMPL; -} - -static HRESULT WINAPI media_object_GetInputType(IMediaObject *iface, DWORD index, DWORD type_index, - DMO_MEDIA_TYPE *type) -{ - TRACE("iface %p, index %lu, type_index %lu, type %p.\n", iface, index, type_index, type); - - if (index > 0) - return DMO_E_INVALIDSTREAMINDEX; - if (type_index >= ARRAY_SIZE(wmv_decoder_input_types)) - return DMO_E_NO_MORE_ITEMS; - if (!type) - return S_OK; - - memset(type, 0, sizeof(*type)); - type->majortype = MFMediaType_Video; - type->subtype = *wmv_decoder_input_types[type_index]; - type->bFixedSizeSamples = FALSE; - type->bTemporalCompression = TRUE; - type->lSampleSize = 0; - - return S_OK; -} - -static HRESULT WINAPI media_object_GetOutputType(IMediaObject *iface, DWORD index, DWORD type_index, - DMO_MEDIA_TYPE *type) -{ - struct wmv_decoder *decoder = impl_from_IMediaObject(iface); - UINT64 frame_size, frame_rate; - IMFMediaType *media_type; - VIDEOINFOHEADER *info; - const GUID *subtype; - LONG width, height; - UINT32 image_size; - HRESULT hr; - - TRACE("iface %p, index %lu, type_index %lu, type %p.\n", iface, index, type_index, type); - - if (index > 0) - return DMO_E_INVALIDSTREAMINDEX; - if (type_index >= ARRAY_SIZE(wmv_decoder_output_types)) - return DMO_E_NO_MORE_ITEMS; - if (!type) - return S_OK; - if (IsEqualGUID(&decoder->input_type.majortype, &GUID_NULL)) - return DMO_E_TYPE_NOT_SET; - - if (FAILED(hr = MFCreateMediaTypeFromRepresentation(AM_MEDIA_TYPE_REPRESENTATION, - &decoder->input_type, &media_type))) - return hr; - - if (FAILED(IMFMediaType_GetUINT64(media_type, &MF_MT_FRAME_SIZE, &frame_size))) - frame_size = 0; - if (FAILED(IMFMediaType_GetUINT64(media_type, &MF_MT_FRAME_RATE, &frame_rate))) - frame_rate = (UINT64)1 << 32 | 1; - - width = frame_size >> 32; - height = (UINT32)frame_size; - subtype = wmv_decoder_output_types[type_index].subtype; - if (FAILED(hr = MFCalculateImageSize(subtype, width, height, &image_size))) - { - FIXME("Failed to get image size of subtype %s.\n", debugstr_guid(subtype)); - IMFMediaType_Release(media_type); - return hr; - } - - memset(type, 0, sizeof(*type)); - type->majortype = MFMediaType_Video; - type->subtype = *subtype; - type->bFixedSizeSamples = TRUE; - type->bTemporalCompression = FALSE; - type->lSampleSize = image_size; - type->formattype = FORMAT_VideoInfo; - type->cbFormat = sizeof(VIDEOINFOHEADER); - type->pbFormat = CoTaskMemAlloc(type->cbFormat); - memset(type->pbFormat, 0, type->cbFormat); - - info = (VIDEOINFOHEADER *)type->pbFormat; - info->rcSource.right = width; - info->rcSource.bottom = height; - info->rcTarget.right = width; - info->rcTarget.bottom = height; - info->AvgTimePerFrame = MulDiv(10000000, frame_rate >> 32, (UINT32)frame_rate); - info->bmiHeader.biSize = sizeof(info->bmiHeader); - info->bmiHeader.biWidth = width; - info->bmiHeader.biHeight = height; - info->bmiHeader.biPlanes = 1; - info->bmiHeader.biBitCount = wmv_decoder_output_types[type_index].bpp; - info->bmiHeader.biCompression = wmv_decoder_output_types[type_index].compression; - info->bmiHeader.biSizeImage = image_size; - - IMFMediaType_Release(media_type); - return S_OK; -} - -static HRESULT WINAPI media_object_SetInputType(IMediaObject *iface, DWORD index, - const DMO_MEDIA_TYPE *type, DWORD flags) -{ - struct wmv_decoder *decoder = impl_from_IMediaObject(iface); - IMFMediaType *media_type; - unsigned int i; - - TRACE("iface %p, index %lu, type %p, flags %#lx.\n", iface, index, type, flags); - - if (index > 0) - return DMO_E_INVALIDSTREAMINDEX; - - if (!type) - { - if (flags & DMO_SET_TYPEF_CLEAR) - { - FreeMediaType(&decoder->input_type); - memset(&decoder->input_type, 0, sizeof(decoder->input_type)); - if (decoder->wg_transform) - { - wg_transform_destroy(decoder->wg_transform); - decoder->wg_transform = 0; - } - return S_OK; - } - return DMO_E_TYPE_NOT_ACCEPTED; - } - - if (!IsEqualGUID(&type->majortype, &MEDIATYPE_Video)) - return DMO_E_TYPE_NOT_ACCEPTED; - - for (i = 0; i < ARRAY_SIZE(wmv_decoder_input_types); ++i) - if (IsEqualGUID(&type->subtype, wmv_decoder_input_types[i])) - break; - if (i == ARRAY_SIZE(wmv_decoder_input_types)) - return DMO_E_TYPE_NOT_ACCEPTED; - - if (FAILED(MFCreateMediaTypeFromRepresentation(AM_MEDIA_TYPE_REPRESENTATION, - (void *)type, &media_type))) - return DMO_E_TYPE_NOT_ACCEPTED; - IMFMediaType_Release(media_type); - - if (flags & DMO_SET_TYPEF_TEST_ONLY) - return S_OK; - - FreeMediaType(&decoder->input_type); - CopyMediaType(&decoder->input_type, type); - if (decoder->wg_transform) - { - wg_transform_destroy(decoder->wg_transform); - decoder->wg_transform = 0; - } - - return S_OK; -} - -static HRESULT WINAPI media_object_SetOutputType(IMediaObject *iface, DWORD index, - const DMO_MEDIA_TYPE *type, DWORD flags) -{ - struct wmv_decoder *decoder = impl_from_IMediaObject(iface); - struct wg_transform_attrs attrs = {0}; - IMFMediaType *media_type; - unsigned int i; - HRESULT hr; - - TRACE("iface %p, index %lu, type %p, flags %#lx,\n", iface, index, type, flags); - - if (index > 0) - return DMO_E_INVALIDSTREAMINDEX; - - if (!type) - { - if (flags & DMO_SET_TYPEF_CLEAR) - { - FreeMediaType(&decoder->output_type); - memset(&decoder->output_type, 0, sizeof(decoder->output_type)); - if (decoder->wg_transform) - { - wg_transform_destroy(decoder->wg_transform); - decoder->wg_transform = 0; - } - return S_OK; - } - return E_POINTER; - } - - if (IsEqualGUID(&decoder->input_type.majortype, &GUID_NULL)) - return DMO_E_TYPE_NOT_SET; - - if (!IsEqualGUID(&type->majortype, &MEDIATYPE_Video)) - return DMO_E_TYPE_NOT_ACCEPTED; - - for (i = 0; i < ARRAY_SIZE(wmv_decoder_output_types); ++i) - if (IsEqualGUID(&type->subtype, wmv_decoder_output_types[i].subtype)) - break; - if (i == ARRAY_SIZE(wmv_decoder_output_types)) - return DMO_E_TYPE_NOT_ACCEPTED; - - if (FAILED(MFCreateMediaTypeFromRepresentation(AM_MEDIA_TYPE_REPRESENTATION, - (void *)type, &media_type))) - return DMO_E_TYPE_NOT_ACCEPTED; - IMFMediaType_Release(media_type); - - if (flags & DMO_SET_TYPEF_TEST_ONLY) - return S_OK; - - FreeMediaType(&decoder->output_type); - CopyMediaType(&decoder->output_type, type); - - /* Set up wg_transform. */ - if (decoder->wg_transform) - { - wg_transform_destroy(decoder->wg_transform); - decoder->wg_transform = 0; - } - if (FAILED(hr = wg_transform_create_quartz(&decoder->input_type, type, - &attrs, &decoder->wg_transform))) - return hr; - - return S_OK; -} - -static HRESULT WINAPI media_object_GetInputCurrentType(IMediaObject *iface, DWORD index, DMO_MEDIA_TYPE *type) -{ - FIXME("iface %p, index %lu, type %p stub!\n", iface, index, type); - return E_NOTIMPL; -} - -static HRESULT WINAPI media_object_GetOutputCurrentType(IMediaObject *iface, DWORD index, DMO_MEDIA_TYPE *type) -{ - FIXME("iface %p, index %lu, type %p stub!\n", iface, index, type); - return E_NOTIMPL; -} - -static HRESULT WINAPI media_object_GetInputSizeInfo(IMediaObject *iface, DWORD index, DWORD *size, - DWORD *lookahead, DWORD *alignment) -{ - FIXME("iface %p, index %lu, size %p, lookahead %p, alignment %p stub!\n", iface, index, size, - lookahead, alignment); - return E_NOTIMPL; -} - -static HRESULT WINAPI media_object_GetOutputSizeInfo(IMediaObject *iface, DWORD index, DWORD *size, DWORD *alignment) -{ - struct wmv_decoder *decoder = impl_from_IMediaObject(iface); - IMFMediaType *media_type; - HRESULT hr; - - TRACE("iface %p, index %lu, size %p, alignment %p.\n", iface, index, size, alignment); - - if (index > 0) - return DMO_E_INVALIDSTREAMINDEX; - if (IsEqualGUID(&decoder->output_type.majortype, &GUID_NULL)) - return DMO_E_TYPE_NOT_SET; - - if (FAILED(hr = MFCreateMediaType(&media_type))) - return hr; - if (SUCCEEDED(hr = MFInitMediaTypeFromAMMediaType(media_type, &decoder->output_type)) - && SUCCEEDED(hr = IMFMediaType_GetUINT32(media_type, &MF_MT_SAMPLE_SIZE, (UINT32 *)size))) - *alignment = 1; - IMFMediaType_Release(media_type); - - return S_OK; -} - -static HRESULT WINAPI media_object_GetInputMaxLatency(IMediaObject *iface, DWORD index, REFERENCE_TIME *latency) -{ - FIXME("iface %p, index %lu, latency %p stub!\n", iface, index, latency); - return E_NOTIMPL; -} - -static HRESULT WINAPI media_object_SetInputMaxLatency(IMediaObject *iface, DWORD index, REFERENCE_TIME latency) -{ - FIXME("iface %p, index %lu, latency %s stub!\n", iface, index, wine_dbgstr_longlong(latency)); - return E_NOTIMPL; -} - -static HRESULT WINAPI media_object_Flush(IMediaObject *iface) -{ - struct wmv_decoder *decoder = impl_from_IMediaObject(iface); - HRESULT hr; - - TRACE("iface %p.\n", iface); - - if (FAILED(hr = wg_transform_flush(decoder->wg_transform))) - return hr; - - wg_sample_queue_flush(decoder->wg_sample_queue, TRUE); - - return S_OK; -} - -static HRESULT WINAPI media_object_Discontinuity(IMediaObject *iface, DWORD index) -{ - TRACE("iface %p, index %lu.\n", iface, index); - - if (index > 0) - return DMO_E_INVALIDSTREAMINDEX; - - return S_OK; -} - -static HRESULT WINAPI media_object_AllocateStreamingResources(IMediaObject *iface) -{ - FIXME("iface %p stub!\n", iface); - return E_NOTIMPL; -} - -static HRESULT WINAPI media_object_FreeStreamingResources(IMediaObject *iface) -{ - FIXME("iface %p stub!\n", iface); - return E_NOTIMPL; -} - -static HRESULT WINAPI media_object_GetInputStatus(IMediaObject *iface, DWORD index, DWORD *flags) -{ - TRACE("iface %p, index %lu, flags %p.\n", iface, index, flags); - - if (index > 0) - return DMO_E_INVALIDSTREAMINDEX; - if (!flags) - return E_POINTER; - - *flags = DMO_INPUT_STATUSF_ACCEPT_DATA; - - return S_OK; -} - -static HRESULT WINAPI media_object_ProcessInput(IMediaObject *iface, DWORD index, - IMediaBuffer *buffer, DWORD flags, REFERENCE_TIME timestamp, REFERENCE_TIME timelength) -{ - struct wmv_decoder *decoder = impl_from_IMediaObject(iface); - - TRACE("iface %p, index %lu, buffer %p, flags %#lx, timestamp %s, timelength %s.\n", iface, - index, buffer, flags, wine_dbgstr_longlong(timestamp), wine_dbgstr_longlong(timelength)); - - if (!decoder->wg_transform) - return DMO_E_TYPE_NOT_SET; - - return wg_transform_push_dmo(decoder->wg_transform, buffer, flags, timestamp, timelength, decoder->wg_sample_queue); -} - -static HRESULT WINAPI media_object_ProcessOutput(IMediaObject *iface, DWORD flags, DWORD count, - DMO_OUTPUT_DATA_BUFFER *buffers, DWORD *status) -{ - struct wmv_decoder *decoder = impl_from_IMediaObject(iface); - HRESULT hr; - - TRACE("iface %p, flags %#lx, count %lu, buffers %p, status %p.\n", iface, flags, count, buffers, status); - - if (!decoder->wg_transform) - return DMO_E_TYPE_NOT_SET; - - if ((hr = wg_transform_read_dmo(decoder->wg_transform, buffers)) == MF_E_TRANSFORM_STREAM_CHANGE) - hr = wg_transform_read_dmo(decoder->wg_transform, buffers); - - if (SUCCEEDED(hr)) - wg_sample_queue_flush(decoder->wg_sample_queue, false); - - return hr; -} - -static HRESULT WINAPI media_object_Lock(IMediaObject *iface, LONG lock) -{ - FIXME("iface %p, lock %ld stub!\n", iface, lock); - return E_NOTIMPL; -} - -static const IMediaObjectVtbl media_object_vtbl = -{ - media_object_QueryInterface, - media_object_AddRef, - media_object_Release, - media_object_GetStreamCount, - media_object_GetInputStreamInfo, - media_object_GetOutputStreamInfo, - media_object_GetInputType, - media_object_GetOutputType, - media_object_SetInputType, - media_object_SetOutputType, - media_object_GetInputCurrentType, - media_object_GetOutputCurrentType, - media_object_GetInputSizeInfo, - media_object_GetOutputSizeInfo, - media_object_GetInputMaxLatency, - media_object_SetInputMaxLatency, - media_object_Flush, - media_object_Discontinuity, - media_object_AllocateStreamingResources, - media_object_FreeStreamingResources, - media_object_GetInputStatus, - media_object_ProcessInput, - media_object_ProcessOutput, - media_object_Lock, -}; - -static inline struct wmv_decoder *impl_from_IPropertyBag(IPropertyBag *iface) -{ - return CONTAINING_RECORD(iface, struct wmv_decoder, IPropertyBag_iface); -} - -static HRESULT WINAPI property_bag_QueryInterface(IPropertyBag *iface, REFIID iid, void **out) -{ - return IUnknown_QueryInterface(impl_from_IPropertyBag(iface)->outer, iid, out); -} - -static ULONG WINAPI property_bag_AddRef(IPropertyBag *iface) -{ - return IUnknown_AddRef(impl_from_IPropertyBag(iface)->outer); -} - -static ULONG WINAPI property_bag_Release(IPropertyBag *iface) -{ - return IUnknown_Release(impl_from_IPropertyBag(iface)->outer); -} - -static HRESULT WINAPI property_bag_Read(IPropertyBag *iface, const WCHAR *prop_name, VARIANT *value, - IErrorLog *error_log) -{ - FIXME("iface %p, prop_name %s, value %p, error_log %p stub!\n", iface, debugstr_w(prop_name), value, error_log); - return E_NOTIMPL; -} - -static HRESULT WINAPI property_bag_Write(IPropertyBag *iface, const WCHAR *prop_name, VARIANT *value) -{ - FIXME("iface %p, prop_name %s, value %p stub!\n", iface, debugstr_w(prop_name), value); - return S_OK; -} - -static const IPropertyBagVtbl property_bag_vtbl = -{ - property_bag_QueryInterface, - property_bag_AddRef, - property_bag_Release, - property_bag_Read, - property_bag_Write, -}; - -static inline struct wmv_decoder *impl_from_IPropertyStore(IPropertyStore *iface) -{ - return CONTAINING_RECORD(iface, struct wmv_decoder, IPropertyStore_iface); -} - -static HRESULT WINAPI property_store_QueryInterface(IPropertyStore *iface, REFIID iid, void **out) -{ - return IUnknown_QueryInterface(impl_from_IPropertyStore(iface)->outer, iid, out); -} - -static ULONG WINAPI property_store_AddRef(IPropertyStore *iface) -{ - return IUnknown_AddRef(impl_from_IPropertyStore(iface)->outer); -} - -static ULONG WINAPI property_store_Release(IPropertyStore *iface) -{ - return IUnknown_Release(impl_from_IPropertyStore(iface)->outer); -} - -static HRESULT WINAPI property_store_GetCount(IPropertyStore *iface, DWORD *count) -{ - FIXME("iface %p, count %p stub!\n", iface, count); - return E_NOTIMPL; -} - -static HRESULT WINAPI property_store_GetAt(IPropertyStore *iface, DWORD index, PROPERTYKEY *key) -{ - FIXME("iface %p, index %lu, key %p stub!\n", iface, index, key); - return E_NOTIMPL; -} - -static HRESULT WINAPI property_store_GetValue(IPropertyStore *iface, REFPROPERTYKEY key, PROPVARIANT *value) -{ - FIXME("iface %p, key %p, value %p stub!\n", iface, key, value); - return E_NOTIMPL; -} - -static HRESULT WINAPI property_store_SetValue(IPropertyStore *iface, REFPROPERTYKEY key, REFPROPVARIANT value) -{ - FIXME("iface %p, key %p, value %p stub!\n", iface, key, value); - return E_NOTIMPL; -} - -static HRESULT WINAPI property_store_Commit(IPropertyStore *iface) -{ - FIXME("iface %p stub!\n", iface); - return E_NOTIMPL; -} - -static const IPropertyStoreVtbl property_store_vtbl = -{ - property_store_QueryInterface, - property_store_AddRef, - property_store_Release, - property_store_GetCount, - property_store_GetAt, - property_store_GetValue, - property_store_SetValue, - property_store_Commit, -}; - -HRESULT wmv_decoder_create(IUnknown *outer, IUnknown **out) -{ - static const struct wg_format input_format = - { - .major_type = WG_MAJOR_TYPE_VIDEO_WMV, - .u.video.format = WG_VIDEO_FORMAT_WMV3, - }; - static const struct wg_format output_format = - { - .major_type = WG_MAJOR_TYPE_VIDEO, - .u.video = - { - .format = WG_VIDEO_FORMAT_NV12, - .width = 1920, - .height = 1080, - }, - }; - struct wg_transform_attrs attrs = {0}; - wg_transform_t transform; - struct wmv_decoder *decoder; - HRESULT hr; - - TRACE("outer %p, out %p.\n", outer, out); - - if (!(transform = wg_transform_create(&input_format, &output_format, &attrs))) - { - ERR_(winediag)("GStreamer doesn't support WMV decoding, please install appropriate plugins.\n"); - return E_FAIL; - } - wg_transform_destroy(transform); - - if (!(decoder = calloc(1, sizeof(*decoder)))) - return E_OUTOFMEMORY; - if (FAILED(hr = wg_sample_queue_create(&decoder->wg_sample_queue))) - { - free(decoder); - return hr; - } - - decoder->IUnknown_inner.lpVtbl = &unknown_vtbl; - decoder->IMFTransform_iface.lpVtbl = &transform_vtbl; - decoder->IMediaObject_iface.lpVtbl = &media_object_vtbl; - decoder->IPropertyBag_iface.lpVtbl = &property_bag_vtbl; - decoder->IPropertyStore_iface.lpVtbl = &property_store_vtbl; - decoder->refcount = 1; - decoder->outer = outer ? outer : &decoder->IUnknown_inner; - - *out = &decoder->IUnknown_inner; - TRACE("Created %p\n", *out); - return S_OK; -}
This merge request was approved by Rémi Bernon.