From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/aac_decoder.c | 2 +- dlls/winegstreamer/color_convert.c | 2 +- dlls/winegstreamer/gst_private.h | 9 +++- dlls/winegstreamer/main.c | 19 ++++++-- dlls/winegstreamer/resampler.c | 2 +- dlls/winegstreamer/unix_private.h | 1 + dlls/winegstreamer/unixlib.h | 8 +++- dlls/winegstreamer/video_decoder.c | 12 ++--- dlls/winegstreamer/video_processor.c | 3 +- dlls/winegstreamer/wg_parser.c | 19 +++++++- dlls/winegstreamer/wg_sample.c | 19 +++----- dlls/winegstreamer/wg_transform.c | 66 ++++++++++++++++++---------- dlls/winegstreamer/wma_decoder.c | 2 +- 13 files changed, 107 insertions(+), 57 deletions(-)
diff --git a/dlls/winegstreamer/aac_decoder.c b/dlls/winegstreamer/aac_decoder.c index 0d012fd710a..2cf605bc56c 100644 --- a/dlls/winegstreamer/aac_decoder.c +++ b/dlls/winegstreamer/aac_decoder.c @@ -521,7 +521,7 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, return hr;
if (SUCCEEDED(hr = wg_transform_read_mf(decoder->wg_transform, samples->pSample, - info.cbSize, NULL, &samples->dwStatus))) + info.cbSize, &samples->dwStatus))) wg_sample_queue_flush(decoder->wg_sample_queue, false); else samples->dwStatus = MFT_OUTPUT_DATA_BUFFER_NO_SAMPLE; diff --git a/dlls/winegstreamer/color_convert.c b/dlls/winegstreamer/color_convert.c index 949b85943d0..4b60628e8ba 100644 --- a/dlls/winegstreamer/color_convert.c +++ b/dlls/winegstreamer/color_convert.c @@ -582,7 +582,7 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, return hr;
if (SUCCEEDED(hr = wg_transform_read_mf(impl->wg_transform, samples->pSample, - info.cbSize, NULL, &samples->dwStatus))) + info.cbSize, &samples->dwStatus))) wg_sample_queue_flush(impl->wg_sample_queue, false);
return hr; diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index 85991c2efde..ba9064bc467 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -88,6 +88,7 @@ HRESULT wg_transform_create_mf(IMFMediaType *input_type, IMFMediaType *output_ty 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_get_output_format(wg_transform_t transform, struct wg_format *format); 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); HRESULT wg_transform_drain(wg_transform_t transform); @@ -146,10 +147,16 @@ HRESULT wg_transform_push_quartz(wg_transform_t transform, struct wg_sample *sam HRESULT wg_transform_push_dmo(wg_transform_t transform, IMediaBuffer *media_buffer, DWORD flags, REFERENCE_TIME time_stamp, REFERENCE_TIME time_length, struct wg_sample_queue *queue); HRESULT wg_transform_read_mf(wg_transform_t transform, IMFSample *sample, - DWORD sample_size, struct wg_format *format, DWORD *flags); + DWORD sample_size, DWORD *flags); HRESULT wg_transform_read_quartz(wg_transform_t transform, struct wg_sample *sample); HRESULT wg_transform_read_dmo(wg_transform_t transform, DMO_OUTPUT_DATA_BUFFER *buffer);
+/* These unixlib entry points should not be used directly, they assume samples + * to be queued and zero-copy support, use the helpers below instead. + */ +HRESULT wg_transform_push_data(wg_transform_t transform, struct wg_sample *sample); +HRESULT wg_transform_read_data(wg_transform_t transform, struct wg_sample *sample); + HRESULT gstreamer_byte_stream_handler_create(REFIID riid, void **obj);
unsigned int wg_format_get_stride(const struct wg_format *format); diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c index 220cc2cf52c..747479daf40 100644 --- a/dlls/winegstreamer/main.c +++ b/dlls/winegstreamer/main.c @@ -415,18 +415,16 @@ HRESULT wg_transform_push_data(wg_transform_t transform, struct wg_sample *sampl return params.result; }
-HRESULT wg_transform_read_data(wg_transform_t transform, struct wg_sample *sample, - struct wg_format *format) +HRESULT wg_transform_read_data(wg_transform_t transform, struct wg_sample *sample) { struct wg_transform_read_data_params params = { .transform = transform, .sample = sample, - .format = format, }; NTSTATUS status;
- TRACE("transform %#I64x, sample %p, format %p.\n", transform, sample, format); + TRACE("transform %#I64x, sample %p.\n", transform, sample);
if ((status = WINE_UNIX_CALL(unix_wg_transform_read_data, ¶ms))) return HRESULT_FROM_NT(status); @@ -450,6 +448,19 @@ bool wg_transform_get_status(wg_transform_t transform, bool *accepts_input) return true; }
+bool wg_transform_get_output_format(wg_transform_t transform, struct wg_format *format) +{ + struct wg_transform_get_output_format_params params = + { + .transform = transform, + .format = format, + }; + + TRACE("transform %#I64x, format %p.\n", transform, format); + + return !WINE_UNIX_CALL(unix_wg_transform_get_output_format, ¶ms); +} + bool wg_transform_set_output_format(wg_transform_t transform, struct wg_format *format) { struct wg_transform_set_output_format_params params = diff --git a/dlls/winegstreamer/resampler.c b/dlls/winegstreamer/resampler.c index 8df7eb32649..c1ce9897ef1 100644 --- a/dlls/winegstreamer/resampler.c +++ b/dlls/winegstreamer/resampler.c @@ -541,7 +541,7 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, return hr;
if (SUCCEEDED(hr = wg_transform_read_mf(impl->wg_transform, samples->pSample, - info.cbSize, NULL, &samples->dwStatus))) + info.cbSize, &samples->dwStatus))) wg_sample_queue_flush(impl->wg_sample_queue, false);
return hr; diff --git a/dlls/winegstreamer/unix_private.h b/dlls/winegstreamer/unix_private.h index bb2cb864735..6f01b3a5a69 100644 --- a/dlls/winegstreamer/unix_private.h +++ b/dlls/winegstreamer/unix_private.h @@ -56,6 +56,7 @@ extern GstCaps *wg_format_to_caps(const struct wg_format *format);
extern NTSTATUS wg_transform_create(void *args); extern NTSTATUS wg_transform_destroy(void *args); +extern NTSTATUS wg_transform_get_output_format(void *args); extern NTSTATUS wg_transform_set_output_format(void *args); extern NTSTATUS wg_transform_push_data(void *args); extern NTSTATUS wg_transform_read_data(void *args); diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h index 907cbb2c9b4..cf8cb0ca24c 100644 --- a/dlls/winegstreamer/unixlib.h +++ b/dlls/winegstreamer/unixlib.h @@ -325,10 +325,15 @@ struct wg_transform_read_data_params { wg_transform_t transform; struct wg_sample *sample; - struct wg_format *format; HRESULT result; };
+struct wg_transform_get_output_format_params +{ + wg_transform_t transform; + struct wg_format *format; +}; + struct wg_transform_set_output_format_params { wg_transform_t transform; @@ -410,6 +415,7 @@ enum unix_funcs
unix_wg_transform_create, unix_wg_transform_destroy, + unix_wg_transform_get_output_format, unix_wg_transform_set_output_format,
unix_wg_transform_push_data, diff --git a/dlls/winegstreamer/video_decoder.c b/dlls/winegstreamer/video_decoder.c index 22b21b94bb1..89fbe876fc1 100644 --- a/dlls/winegstreamer/video_decoder.c +++ b/dlls/winegstreamer/video_decoder.c @@ -845,14 +845,17 @@ static HRESULT output_sample(struct video_decoder *decoder, IMFSample **out, IMF return S_OK; }
-static HRESULT handle_stream_type_change(struct video_decoder *decoder, const struct wg_format *format) +static HRESULT handle_stream_type_change(struct video_decoder *decoder) { UINT64 frame_size, frame_rate; + struct wg_format format; HRESULT hr;
if (decoder->stream_type) IMFMediaType_Release(decoder->stream_type); - if (!(decoder->stream_type = mf_media_type_from_wg_format(format))) + if (!(wg_transform_get_output_format(decoder->wg_transform, &format))) + return E_FAIL; + if (!(decoder->stream_type = mf_media_type_from_wg_format(&format))) return E_OUTOFMEMORY;
if (SUCCEEDED(IMFMediaType_GetUINT64(decoder->output_type, &MF_MT_FRAME_RATE, &frame_rate)) @@ -872,7 +875,6 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, MFT_OUTPUT_DATA_BUFFER *samples, DWORD *status) { struct video_decoder *decoder = impl_from_IMFTransform(iface); - struct wg_format wg_format; UINT32 sample_size; LONGLONG duration; IMFSample *sample; @@ -922,7 +924,7 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, }
if (SUCCEEDED(hr = wg_transform_read_mf(decoder->wg_transform, sample, - sample_size, &wg_format, &samples->dwStatus))) + sample_size, &samples->dwStatus))) { wg_sample_queue_flush(decoder->wg_sample_queue, false);
@@ -941,7 +943,7 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, { samples[0].dwStatus |= MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE; *status |= MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE; - hr = handle_stream_type_change(decoder, &wg_format); + hr = handle_stream_type_change(decoder); }
if (decoder->output_info.dwFlags & MFT_OUTPUT_STREAM_PROVIDES_SAMPLES) diff --git a/dlls/winegstreamer/video_processor.c b/dlls/winegstreamer/video_processor.c index a27eebf020e..0bc9d4e10cb 100644 --- a/dlls/winegstreamer/video_processor.c +++ b/dlls/winegstreamer/video_processor.c @@ -692,8 +692,7 @@ static HRESULT WINAPI video_processor_ProcessOutput(IMFTransform *iface, DWORD f IMFSample_AddRef(output_sample); }
- if (FAILED(hr = wg_transform_read_mf(impl->wg_transform, output_sample, info.cbSize, - NULL, &samples->dwStatus))) + if (FAILED(hr = wg_transform_read_mf(impl->wg_transform, output_sample, info.cbSize, &samples->dwStatus))) goto done; wg_sample_queue_flush(impl->wg_sample_queue, false);
diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c index 431a8b74cb2..f9b76b12f8f 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -1889,6 +1889,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
X(wg_transform_create), X(wg_transform_destroy), + X(wg_transform_get_output_format), X(wg_transform_set_output_format),
X(wg_transform_push_data), @@ -2074,6 +2075,21 @@ NTSTATUS wow64_wg_transform_create(void *args) return ret; }
+NTSTATUS wow64_wg_transform_get_output_format(void *args) +{ + struct + { + wg_transform_t transform; + PTR32 format; + } *params32 = args; + struct wg_transform_get_output_format_params params = + { + .transform = params32->transform, + .format = ULongToPtr(params32->format), + }; + return wg_transform_get_output_format(¶ms); +} + NTSTATUS wow64_wg_transform_set_output_format(void *args) { struct @@ -2115,14 +2131,12 @@ NTSTATUS wow64_wg_transform_read_data(void *args) { wg_transform_t transform; PTR32 sample; - PTR32 format; HRESULT result; } *params32 = args; struct wg_transform_read_data_params params = { .transform = params32->transform, .sample = ULongToPtr(params32->sample), - .format = ULongToPtr(params32->format), }; NTSTATUS ret;
@@ -2240,6 +2254,7 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] =
X64(wg_transform_create), X(wg_transform_destroy), + X64(wg_transform_get_output_format), X64(wg_transform_set_output_format),
X64(wg_transform_push_data), diff --git a/dlls/winegstreamer/wg_sample.c b/dlls/winegstreamer/wg_sample.c index 9427dad0f93..116dbb1f3ec 100644 --- a/dlls/winegstreamer/wg_sample.c +++ b/dlls/winegstreamer/wg_sample.c @@ -303,13 +303,6 @@ void wg_sample_queue_destroy(struct wg_sample_queue *queue) free(queue); }
-/* These unixlib entry points should not be used directly, they assume samples - * to be queued and zero-copy support, use the helpers below instead. - */ -HRESULT wg_transform_push_data(wg_transform_t transform, struct wg_sample *sample); -HRESULT wg_transform_read_data(wg_transform_t transform, struct wg_sample *sample, - struct wg_format *format); - HRESULT wg_transform_push_mf(wg_transform_t transform, IMFSample *sample, struct wg_sample_queue *queue) { @@ -346,23 +339,21 @@ HRESULT wg_transform_push_mf(wg_transform_t transform, IMFSample *sample, }
HRESULT wg_transform_read_mf(wg_transform_t transform, IMFSample *sample, - DWORD sample_size, struct wg_format *format, DWORD *flags) + DWORD sample_size, DWORD *flags) { struct wg_sample *wg_sample; IMFMediaBuffer *buffer; HRESULT hr;
- TRACE_(mfplat)("transform %#I64x, sample %p, format %p, flags %p.\n", transform, sample, format, flags); + TRACE_(mfplat)("transform %#I64x, sample %p, flags %p.\n", transform, sample, flags);
if (FAILED(hr = wg_sample_create_mf(sample, &wg_sample))) return hr;
wg_sample->size = 0;
- if (FAILED(hr = wg_transform_read_data(transform, wg_sample, format))) + if (FAILED(hr = wg_transform_read_data(transform, wg_sample))) { - if (hr == MF_E_TRANSFORM_STREAM_CHANGE && !format) - FIXME("Unexpected stream format change!\n"); wg_sample_release(wg_sample); return hr; } @@ -430,7 +421,7 @@ HRESULT wg_transform_read_quartz(wg_transform_t transform, struct wg_sample *wg_
TRACE_(mfplat)("transform %#I64x, wg_sample %p.\n", transform, wg_sample);
- if (FAILED(hr = wg_transform_read_data(transform, wg_sample, NULL))) + if (FAILED(hr = wg_transform_read_data(transform, wg_sample))) { if (hr == MF_E_TRANSFORM_STREAM_CHANGE) FIXME("Unexpected stream format change!\n"); @@ -505,7 +496,7 @@ HRESULT wg_transform_read_dmo(wg_transform_t transform, DMO_OUTPUT_DATA_BUFFER * return hr; wg_sample->size = 0;
- if (FAILED(hr = wg_transform_read_data(transform, wg_sample, NULL))) + if (FAILED(hr = wg_transform_read_data(transform, wg_sample))) { if (hr == MF_E_TRANSFORM_STREAM_CHANGE) TRACE_(mfplat)("Stream format changed.\n"); diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c index ec08f1322c0..8352c15cd44 100644 --- a/dlls/winegstreamer/wg_transform.c +++ b/dlls/winegstreamer/wg_transform.c @@ -609,6 +609,48 @@ out: return status; }
+NTSTATUS wg_transform_get_output_format(void *args) +{ + struct wg_transform_get_output_format_params *params = args; + struct wg_transform *transform = get_transform(params->transform); + struct wg_format *format = params->format; + GstVideoInfo video_info; + GstCaps *output_caps; + + if (transform->output_sample) + output_caps = gst_sample_get_caps(transform->output_sample); + else + output_caps = transform->output_caps; + + GST_INFO("transform %p output caps %"GST_PTR_FORMAT, transform, output_caps); + + wg_format_from_caps(format, output_caps); + + if (stream_type_from_caps(output_caps) == GST_STREAM_TYPE_VIDEO + && gst_video_info_from_caps(&video_info, output_caps)) + { + gsize plane_align = transform->attrs.output_plane_align; + GstVideoAlignment align = {0}; + + /* set the desired output buffer alignment on the dest video info */ + align_video_info_planes(plane_align, &video_info, &align); + + GST_INFO("Returning video alignment left %u, top %u, right %u, bottom %u.", align.padding_left, + align.padding_top, align.padding_right, align.padding_bottom); + + format->u.video.padding.left = align.padding_left; + format->u.video.width += format->u.video.padding.left; + format->u.video.padding.right = align.padding_right; + format->u.video.width += format->u.video.padding.right; + format->u.video.padding.top = align.padding_top; + format->u.video.height += format->u.video.padding.top; + format->u.video.padding.bottom = align.padding_bottom; + format->u.video.height += format->u.video.padding.bottom; + } + + return STATUS_SUCCESS; +} + NTSTATUS wg_transform_set_output_format(void *args) { struct wg_transform_set_output_format_params *params = args; @@ -920,7 +962,6 @@ NTSTATUS wg_transform_read_data(void *args) struct wg_transform *transform = get_transform(params->transform); GstVideoInfo src_video_info, dst_video_info; struct wg_sample *sample = params->sample; - struct wg_format *format = params->format; GstVideoAlignment align = {0}; GstBuffer *output_buffer; GstCaps *output_caps; @@ -954,29 +995,6 @@ NTSTATUS wg_transform_read_data(void *args) if (GST_MINI_OBJECT_FLAG_IS_SET(transform->output_sample, GST_SAMPLE_FLAG_WG_CAPS_CHANGED)) { GST_MINI_OBJECT_FLAG_UNSET(transform->output_sample, GST_SAMPLE_FLAG_WG_CAPS_CHANGED); - - GST_INFO("transform %p output caps %"GST_PTR_FORMAT, transform, output_caps); - - if (format) - { - wg_format_from_caps(format, output_caps); - - if (format->major_type == WG_MAJOR_TYPE_VIDEO) - { - GST_INFO("Returning video alignment left %u, top %u, right %u, bottom %u.", align.padding_left, - align.padding_top, align.padding_right, align.padding_bottom); - - format->u.video.padding.left = align.padding_left; - format->u.video.width += format->u.video.padding.left; - format->u.video.padding.right = align.padding_right; - format->u.video.width += format->u.video.padding.right; - format->u.video.padding.top = align.padding_top; - format->u.video.height += format->u.video.padding.top; - format->u.video.padding.bottom = align.padding_bottom; - format->u.video.height += format->u.video.padding.bottom; - } - } - params->result = MF_E_TRANSFORM_STREAM_CHANGE; GST_INFO("Format changed detected, returning no output"); wg_allocator_release_sample(transform->allocator, sample, false); diff --git a/dlls/winegstreamer/wma_decoder.c b/dlls/winegstreamer/wma_decoder.c index 8aa55b9b137..14a48db9ae2 100644 --- a/dlls/winegstreamer/wma_decoder.c +++ b/dlls/winegstreamer/wma_decoder.c @@ -557,7 +557,7 @@ static HRESULT WINAPI transform_ProcessOutput(IMFTransform *iface, DWORD flags, return hr;
if (SUCCEEDED(hr = wg_transform_read_mf(decoder->wg_transform, samples->pSample, - info.cbSize, NULL, &samples->dwStatus))) + info.cbSize, &samples->dwStatus))) wg_sample_queue_flush(decoder->wg_sample_queue, false);
return hr;