From: Alfred Agrell floating@muncher.se
--- dlls/winegstreamer/gst_private.h | 4 +- dlls/winegstreamer/quartz_transform.c | 54 +++++++++++++++++++++++---- dlls/winegstreamer/wg_sample.c | 8 +--- 3 files changed, 52 insertions(+), 14 deletions(-)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index 465a7074cbe..de05ad8ab37 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -130,6 +130,8 @@ HRESULT color_convert_create(IUnknown *outer, IUnknown **out); HRESULT mp3_sink_class_factory_create(IUnknown *outer, IUnknown **out); HRESULT mpeg4_sink_class_factory_create(IUnknown *outer, IUnknown **out);
+/* The wm parameter should be true if the caller is part of the Windows Media Format handlers (IWM* interfaces and WM* functions), + * and false for DirectShow. */ bool amt_from_wg_format(AM_MEDIA_TYPE *mt, const struct wg_format *format, bool wm); bool amt_to_wg_format(const AM_MEDIA_TYPE *mt, struct wg_format *format);
@@ -154,7 +156,7 @@ HRESULT wg_transform_push_dmo(wg_transform_t transform, IMediaBuffer *media_buff 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); -HRESULT wg_transform_read_quartz(wg_transform_t transform, struct wg_sample *sample); +HRESULT wg_transform_read_quartz(wg_transform_t transform, struct wg_sample *sample, struct wg_format *format); HRESULT wg_transform_read_dmo(wg_transform_t transform, DMO_OUTPUT_DATA_BUFFER *buffer);
HRESULT gstreamer_byte_stream_handler_create(REFIID riid, void **obj); diff --git a/dlls/winegstreamer/quartz_transform.c b/dlls/winegstreamer/quartz_transform.c index 0066cd7131c..2b2206ec12a 100644 --- a/dlls/winegstreamer/quartz_transform.c +++ b/dlls/winegstreamer/quartz_transform.c @@ -44,6 +44,7 @@ struct transform struct wg_sample_queue *sample_queue;
const struct transform_ops *ops; + BOOL send_new_format; };
struct transform_ops @@ -301,6 +302,7 @@ static HRESULT WINAPI transform_sink_receive(struct strmbase_sink *pin, IMediaSa { struct transform *filter = impl_from_strmbase_filter(pin->pin.filter); struct wg_sample *wg_sample; + struct wg_format wg_format; HRESULT hr;
/* We do not expect pin connection state to change while the filter is @@ -342,22 +344,60 @@ static HRESULT WINAPI transform_sink_receive(struct strmbase_sink *pin, IMediaSa return hr; }
- hr = wg_transform_read_quartz(filter->transform, wg_sample); + hr = wg_transform_read_quartz(filter->transform, wg_sample, &wg_format); wg_sample_release(wg_sample);
- if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) - { - IMediaSample_Release(output_sample); - break; - } if (FAILED(hr)) { IMediaSample_Release(output_sample); - return hr; + if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT) + { + break; + } + else if (hr == MF_E_TRANSFORM_STREAM_CHANGE) + { + AM_MEDIA_TYPE new_mt; + if (amt_from_wg_format(&new_mt, &wg_format, false)) + { + if (memcmp(&filter->source.pin.mt, &new_mt, offsetof(AM_MEDIA_TYPE, pbFormat)) + || memcmp(filter->source.pin.mt.pbFormat, new_mt.pbFormat, filter->source.pin.mt.cbFormat)) + { + FIXME("Changing media type - this is poorly tested\n"); + TRACE("Changing media type from\n"); + strmbase_dump_media_type(&filter->source.pin.mt); + TRACE("to\n"); + strmbase_dump_media_type(&new_mt); + FreeMediaType(&filter->source.pin.mt); + memcpy(&filter->source.pin.mt, &new_mt, sizeof(pin->pin.mt)); + filter->send_new_format = TRUE; + } + else + { + TRACE("Notified about media type change, but they're identical - not changing\n"); + /* probably some GStreamer-side change that AM_MEDIA_TYPE can't represent, for example colorimetry */ + FreeMediaType(&new_mt); + } + } + else + { + return E_OUTOFMEMORY; + } + continue; + } + else + { + return hr; + } }
wg_sample_queue_flush(filter->sample_queue, false);
+ if (filter->send_new_format) + { + filter->send_new_format = FALSE; + IMediaSample_SetMediaType(output_sample, &filter->source.pin.mt); + } + hr = IMemInputPin_Receive(filter->source.pMemInputPin, output_sample); if (FAILED(hr)) { diff --git a/dlls/winegstreamer/wg_sample.c b/dlls/winegstreamer/wg_sample.c index 4b02252174b..9bae076cba3 100644 --- a/dlls/winegstreamer/wg_sample.c +++ b/dlls/winegstreamer/wg_sample.c @@ -421,7 +421,7 @@ HRESULT wg_transform_push_quartz(wg_transform_t transform, struct wg_sample *wg_ return hr; }
-HRESULT wg_transform_read_quartz(wg_transform_t transform, struct wg_sample *wg_sample) +HRESULT wg_transform_read_quartz(wg_transform_t transform, struct wg_sample *wg_sample, struct wg_format *wg_format) { struct sample *sample = unsafe_quartz_from_wg_sample(wg_sample); REFERENCE_TIME start_time, end_time; @@ -430,12 +430,8 @@ 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 (hr == MF_E_TRANSFORM_STREAM_CHANGE) - FIXME("Unexpected stream format change!\n"); + if (FAILED(hr = wg_transform_read_data(transform, wg_sample, wg_format))) return hr; - }
if (FAILED(hr = IMediaSample_SetActualDataLength(sample->u.quartz.sample, wg_sample->size))) return hr;