From: Ziqing Hui zhui@codeweavers.com
--- dlls/mf/tests/transform.c | 145 +++++++++++++++++++++++++++++++++++++- 1 file changed, 143 insertions(+), 2 deletions(-)
diff --git a/dlls/mf/tests/transform.c b/dlls/mf/tests/transform.c index f1d7ffbc071..8e3827409e1 100644 --- a/dlls/mf/tests/transform.c +++ b/dlls/mf/tests/transform.c @@ -55,6 +55,105 @@ DEFINE_GUID(MFVideoFormat_WMV_Unknown,0x7ce12ca9,0xbfbf,0x43d9,0x9d,0x00,0x82,0x
DEFINE_GUID(mft_output_sample_incomplete,0xffffff,0xffff,0xffff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff);
+struct buffer_impl +{ + IMediaBuffer IMediaBuffer_iface; + LONG refcount; + BYTE *data; + DWORD length; + DWORD max_length; +}; + +static inline struct buffer_impl *impl_from_IMediaBuffer(IMediaBuffer *iface) +{ + return CONTAINING_RECORD(iface, struct buffer_impl, IMediaBuffer_iface); +} + +static HRESULT WINAPI buffer_impl_QueryInterface(IMediaBuffer *iface, REFIID iid, void **obj) +{ + if (IsEqualIID(iid, &IID_IMediaBuffer) + || IsEqualIID(iid, &IID_IUnknown)) + { + *obj = iface; + return S_OK; + } + return E_NOINTERFACE; +} + +static ULONG WINAPI buffer_impl_AddRef(IMediaBuffer *iface) +{ + struct buffer_impl *buffer = impl_from_IMediaBuffer(iface); + return InterlockedIncrement(&buffer->refcount); +} + +static ULONG WINAPI buffer_impl_Release(IMediaBuffer *iface) +{ + struct buffer_impl *buffer = impl_from_IMediaBuffer(iface); + ULONG ref = InterlockedDecrement(&buffer->refcount); + if (!ref) + { + free(buffer->data); + free(buffer); + } + return ref; +} + +static HRESULT WINAPI buffer_impl_SetLength(IMediaBuffer *iface, DWORD length) +{ + struct buffer_impl *buffer = impl_from_IMediaBuffer(iface); + if (length > buffer->max_length) + return E_INVALIDARG; + buffer->length = length; + return S_OK; +} + +static HRESULT WINAPI buffer_impl_GetMaxLength(IMediaBuffer *iface, DWORD *max_length) +{ + struct buffer_impl *buffer = impl_from_IMediaBuffer(iface); + if (!max_length) + return E_POINTER; + *max_length = buffer->max_length; + return S_OK; +} + +static HRESULT WINAPI buffer_impl_GetBufferAndLength(IMediaBuffer *iface, BYTE **data, DWORD *length) +{ + struct buffer_impl *buffer = impl_from_IMediaBuffer(iface); + if (!data || ! length) + return E_POINTER; + *data = buffer->data; + *length = buffer->length; + return S_OK; +} + +static IMediaBufferVtbl buffer_impl_vtbl = { + buffer_impl_QueryInterface, + buffer_impl_AddRef, + buffer_impl_Release, + buffer_impl_SetLength, + buffer_impl_GetMaxLength, + buffer_impl_GetBufferAndLength, +}; + +HRESULT buffer_impl_create(DWORD max_length, struct buffer_impl **ret) +{ + struct buffer_impl *buffer; + + if (!(buffer = calloc(1, sizeof(*buffer)))) + return E_OUTOFMEMORY; + if (!(buffer->data = calloc(max_length, sizeof(*buffer->data)))) + { + free(buffer); + return E_OUTOFMEMORY; + } + buffer->IMediaBuffer_iface.lpVtbl = &buffer_impl_vtbl; + buffer->refcount = 1; + buffer->length = 0; + buffer->max_length = max_length; + *ret = buffer; + return S_OK; +} + static BOOL is_compressed_subtype(const GUID *subtype) { if (IsEqualGUID(subtype, &MEDIASUBTYPE_WMV1) @@ -332,6 +431,7 @@ static void init_dmo_media_type_video(DMO_MEDIA_TYPE *media_type, header->bmiHeader.biSize = sizeof(header->bmiHeader); header->bmiHeader.biWidth = width; header->bmiHeader.biHeight = height; + header->bmiHeader.biPlanes = 1; header->bmiHeader.biBitCount = subtype_to_bpp(subtype); header->bmiHeader.biCompression = subtype_to_compression(subtype);
@@ -1523,7 +1623,6 @@ static void check_dmo_set_output_type(IMediaObject *media_object, const GUID *su } }
- static HRESULT WINAPI test_unk_QueryInterface(IUnknown *iface, REFIID riid, void **obj) { if (IsEqualIID(riid, &IID_IUnknown)) @@ -5058,10 +5157,14 @@ static void test_wmv_decoder_media_object(void) {MFMediaType_Video, MEDIASUBTYPE_RGB555, TRUE, FALSE, 512, FORMAT_VideoInfo, NULL, 88, (BYTE *)&expected_output_info[11]}, {MFMediaType_Video, MEDIASUBTYPE_RGB8, TRUE, FALSE, 256, FORMAT_VideoInfo, NULL, 1112, (BYTE *)&expected_output_info[12]}, }; + const DWORD data_width = 96, data_height = 96; const POINT test_size[] = {{16, 16}, {96, 96}, {320, 240}}; - DWORD in_count, out_count, size, expected_size, alignment; + DWORD in_count, out_count, size, expected_size, alignment, wmv_data_length, status; + struct buffer_impl *input_media_buffer, *output_media_buffer; + DMO_OUTPUT_DATA_BUFFER output_data_buffer; DMO_MEDIA_TYPE media_type, *type; IMediaObject *media_object; + const BYTE *wmv_data; char buffer[1024]; ULONG ret, i, j; HRESULT hr; @@ -5185,6 +5288,44 @@ static void test_wmv_decoder_media_object(void) winetest_pop_context(); }
+ /* Test ProcessInput. */ + load_resource(L"wmvencdata.bin", &wmv_data, &wmv_data_length); + wmv_data_length = *((DWORD *)wmv_data); + wmv_data += sizeof(DWORD); + hr = buffer_impl_create(wmv_data_length, &input_media_buffer); + ok(hr == S_OK, "Failed to create input media buffer.\n"); + memcpy(input_media_buffer->data, wmv_data, wmv_data_length); + input_media_buffer->length = wmv_data_length; + + init_dmo_media_type_video(type, &MEDIASUBTYPE_WMV1, data_width, data_height); + hr = IMediaObject_SetInputType(media_object, 0, type, 0); + ok(hr == S_OK, "SetInputType returned %#lx.\n", hr); + init_dmo_media_type_video(type, &MEDIASUBTYPE_NV12, data_width, data_height); + hr = IMediaObject_SetOutputType(media_object, 0, type, 0); + ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr); + + hr = IMediaObject_ProcessInput(media_object, 0, &input_media_buffer->IMediaBuffer_iface, 0, 0, 0); + todo_wine + ok(hr == S_OK, "ProcessInput returned %#lx.\n", hr); + + /* Test ProcessOutput. */ + hr = IMediaObject_GetOutputSizeInfo(media_object, 0, &size, &alignment); + ok(hr == S_OK, "GetOutputSizeInfo returned %#lx.\n", hr); + hr = buffer_impl_create(size, &output_media_buffer); + ok(hr == S_OK, "Failed to create output media buffer.\n"); + output_data_buffer.pBuffer = &output_media_buffer->IMediaBuffer_iface; + output_data_buffer.dwStatus = 0xdeadbeef; + output_data_buffer.rtTimestamp = 0xdeadbeef; + output_data_buffer.rtTimelength = 0xdeadbeef; + hr = IMediaObject_ProcessOutput(media_object, 0, 1, &output_data_buffer, &status); + todo_wine + ok(hr == S_OK, "ProcessOutput returned %#lx.\n", hr); + + ret = IMediaBuffer_Release(&output_media_buffer->IMediaBuffer_iface); + ok(ret == 0, "Release returned %lu\n", ret); + ret = IMediaBuffer_Release(&input_media_buffer->IMediaBuffer_iface); + ok(ret == 0, "Release returned %lu\n", ret); + ret = IMediaObject_Release(media_object); ok(ret == 0, "Release returned %lu\n", ret); CoUninitialize();
From: Ziqing Hui zhui@codeweavers.com
--- dlls/mf/tests/transform.c | 72 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 70 insertions(+), 2 deletions(-)
diff --git a/dlls/mf/tests/transform.c b/dlls/mf/tests/transform.c index 8e3827409e1..96e6b2fb5dc 100644 --- a/dlls/mf/tests/transform.c +++ b/dlls/mf/tests/transform.c @@ -55,6 +55,12 @@ DEFINE_GUID(MFVideoFormat_WMV_Unknown,0x7ce12ca9,0xbfbf,0x43d9,0x9d,0x00,0x82,0x
DEFINE_GUID(mft_output_sample_incomplete,0xffffff,0xffff,0xffff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff);
+/* Shorter aliases for flags. */ +#define O_SYNCPOINT DMO_OUTPUT_DATA_BUFFERF_SYNCPOINT +#define O_TIME DMO_OUTPUT_DATA_BUFFERF_TIME +#define O_TIMELENGTH DMO_OUTPUT_DATA_BUFFERF_TIMELENGTH +#define O_INCOMPLETE DMO_OUTPUT_DATA_BUFFERF_INCOMPLETE + struct buffer_impl { IMediaBuffer IMediaBuffer_iface; @@ -1623,6 +1629,50 @@ static void check_dmo_set_output_type(IMediaObject *media_object, const GUID *su } }
+#define check_dmo_output_data_buffer(a, b, c) check_dmo_output_data_buffer_(__LINE__, a, b, c) +static DWORD check_dmo_output_data_buffer_(int line, DMO_OUTPUT_DATA_BUFFER *output_data_buffer, + const struct sample_desc *sample_desc, const WCHAR *expect_data_filename) +{ + const struct buffer_desc *buffer_desc = &sample_desc->buffers[0]; + DWORD diff, data_length, buffer_length, expect_length; + BYTE *data, *buffer; + HRESULT hr; + + if (output_data_buffer->dwStatus & DMO_OUTPUT_DATA_BUFFERF_TIME) + ok_(__FILE__, line)(output_data_buffer->rtTimestamp == sample_desc->sample_time, + "Unexpected time %I64d, expected %I64d.\n", + output_data_buffer->rtTimestamp, sample_desc->sample_time); + if (output_data_buffer->dwStatus & DMO_OUTPUT_DATA_BUFFERF_TIMELENGTH) + ok_(__FILE__, line)(output_data_buffer->rtTimelength == sample_desc->sample_duration, + "Unexpected duration %I64d, expected %I64d.\n", + output_data_buffer->rtTimelength, sample_desc->sample_duration); + + load_resource(expect_data_filename, (const BYTE **)&data, &data_length); + + expect_length = buffer_desc->length; + if (expect_length == -1) + { + expect_length = *(DWORD *)data; + data += sizeof(DWORD); + data_length = data_length - sizeof(DWORD); + } + + hr = IMediaBuffer_GetBufferAndLength(output_data_buffer->pBuffer, &buffer, &buffer_length); + ok(hr == S_OK, "GetBufferAndLength returned %#lx.\n", hr); + ok_(__FILE__, line)(buffer_length == expect_length, "Unexpected length %#lx, expected %#lx\n", buffer_length, expect_length); + + diff = 0; + if (data_length < buffer_length) + ok_(__FILE__, line)(0, "Missing %#lx bytes\n", buffer_length - data_length); + else if (!buffer_desc->compare) + diff = compare_bytes(buffer, &buffer_length, NULL, data); + else + diff = buffer_desc->compare(buffer, &buffer_length, &buffer_desc->rect, data); + + return diff; +} + + static HRESULT WINAPI test_unk_QueryInterface(IUnknown *iface, REFIID riid, void **obj) { if (IsEqualIID(riid, &IID_IUnknown)) @@ -5159,7 +5209,17 @@ static void test_wmv_decoder_media_object(void) }; const DWORD data_width = 96, data_height = 96; const POINT test_size[] = {{16, 16}, {96, 96}, {320, 240}}; - DWORD in_count, out_count, size, expected_size, alignment, wmv_data_length, status; + const struct buffer_desc output_buffer_desc_nv12 = + { + .length = data_width * data_height * 3 / 2, + .compare = compare_nv12, .dump = dump_nv12, .rect = {.right = 82, .bottom = 84}, + }; + const struct sample_desc output_sample_desc_nv12 = + { + .sample_time = 0, .sample_duration = 333333, + .buffer_count = 1, .buffers = &output_buffer_desc_nv12, + }; + DWORD in_count, out_count, size, expected_size, alignment, wmv_data_length, status, diff; struct buffer_impl *input_media_buffer, *output_media_buffer; DMO_OUTPUT_DATA_BUFFER output_data_buffer; DMO_MEDIA_TYPE media_type, *type; @@ -5304,7 +5364,7 @@ static void test_wmv_decoder_media_object(void) hr = IMediaObject_SetOutputType(media_object, 0, type, 0); ok(hr == S_OK, "SetOutputType returned %#lx.\n", hr);
- hr = IMediaObject_ProcessInput(media_object, 0, &input_media_buffer->IMediaBuffer_iface, 0, 0, 0); + hr = IMediaObject_ProcessInput(media_object, 0, &input_media_buffer->IMediaBuffer_iface, 0, 0, 333333); todo_wine ok(hr == S_OK, "ProcessInput returned %#lx.\n", hr);
@@ -5320,6 +5380,14 @@ static void test_wmv_decoder_media_object(void) hr = IMediaObject_ProcessOutput(media_object, 0, 1, &output_data_buffer, &status); todo_wine ok(hr == S_OK, "ProcessOutput returned %#lx.\n", hr); + todo_wine + ok(output_data_buffer.dwStatus == (O_SYNCPOINT | O_TIME | O_TIMELENGTH), + "Got unexpected dwStatus %#lx.\n", output_data_buffer.dwStatus); + if (hr == S_OK) + { + diff = check_dmo_output_data_buffer(&output_data_buffer, &output_sample_desc_nv12, L"nv12frame.bmp"); + ok(diff == 0, "Got %lu%% diff.\n", diff); + }
ret = IMediaBuffer_Release(&output_media_buffer->IMediaBuffer_iface); ok(ret == 0, "Release returned %lu\n", ret);
From: Ziqing Hui zhui@codeweavers.com
--- dlls/winegstreamer/gst_private.h | 4 + dlls/winegstreamer/wg_sample.c | 131 +++++++++++++++++++++++++++++++ 2 files changed, 135 insertions(+)
diff --git a/dlls/winegstreamer/gst_private.h b/dlls/winegstreamer/gst_private.h index 1e4aad32f44..2bea172cb9e 100644 --- a/dlls/winegstreamer/gst_private.h +++ b/dlls/winegstreamer/gst_private.h @@ -132,15 +132,19 @@ void mf_media_type_to_wg_format(IMFMediaType *type, struct wg_format *format);
HRESULT wg_sample_create_mf(IMFSample *sample, struct wg_sample **out); HRESULT wg_sample_create_quartz(IMediaSample *sample, struct wg_sample **out); +HRESULT wg_sample_create_dmo(IMediaBuffer *media_buffer, struct wg_sample **out); void wg_sample_release(struct wg_sample *wg_sample);
HRESULT wg_transform_push_mf(struct wg_transform *transform, IMFSample *sample, struct wg_sample_queue *queue); HRESULT wg_transform_push_quartz(struct wg_transform *transform, struct wg_sample *sample, struct wg_sample_queue *queue); +HRESULT wg_transform_push_dmo(struct wg_transform *transform, IMediaBuffer *media_buffer, + DWORD flags, REFERENCE_TIME time_stamp, REFERENCE_TIME time_length, struct wg_sample_queue *queue); HRESULT wg_transform_read_mf(struct wg_transform *transform, IMFSample *sample, DWORD sample_size, struct wg_format *format, DWORD *flags); HRESULT wg_transform_read_quartz(struct wg_transform *transform, struct wg_sample *sample); +HRESULT wg_transform_read_dmo(struct wg_transform *transform, DMO_OUTPUT_DATA_BUFFER *buffer, struct wg_format *format);
HRESULT winegstreamer_stream_handler_create(REFIID riid, void **obj);
diff --git a/dlls/winegstreamer/wg_sample.c b/dlls/winegstreamer/wg_sample.c index eb4af86c381..56933a32d55 100644 --- a/dlls/winegstreamer/wg_sample.c +++ b/dlls/winegstreamer/wg_sample.c @@ -57,6 +57,10 @@ struct sample { IMediaSample *sample; } quartz; + struct + { + IMediaBuffer *buffer; + } dmo; } u; };
@@ -165,6 +169,60 @@ HRESULT wg_sample_create_quartz(IMediaSample *media_sample, struct wg_sample **o return S_OK; }
+static const struct wg_sample_ops dmo_sample_ops; + +static inline struct sample *unsafe_dmo_from_wg_sample(struct wg_sample *wg_sample) +{ + struct sample *sample = CONTAINING_RECORD(wg_sample, struct sample, wg_sample); + if (sample->ops != &dmo_sample_ops) return NULL; + return sample; +} + +static void dmo_sample_destroy(struct wg_sample *wg_sample) +{ + struct sample *sample = unsafe_dmo_from_wg_sample(wg_sample); + + TRACE_(mfplat)("wg_sample %p.\n", wg_sample); + + IMediaBuffer_Release(sample->u.dmo.buffer); +} + +static const struct wg_sample_ops dmo_sample_ops = +{ + dmo_sample_destroy, +}; + +HRESULT wg_sample_create_dmo(IMediaBuffer *media_buffer, struct wg_sample **out) +{ + DWORD length, max_length; + struct sample *sample; + BYTE *buffer; + HRESULT hr; + + if (!(sample = calloc(1, sizeof(*sample)))) + return E_OUTOFMEMORY; + if (FAILED(hr = IMediaBuffer_GetBufferAndLength(media_buffer, &buffer, &length))) + goto fail; + if (FAILED(hr = IMediaBuffer_GetMaxLength(media_buffer, &max_length))) + goto fail; + + IMediaBuffer_AddRef((sample->u.dmo.buffer = media_buffer)); + sample->wg_sample.data = buffer; + sample->wg_sample.size = length; + sample->wg_sample.max_size = max_length; + sample->ops = &dmo_sample_ops; + + *out = &sample->wg_sample; + TRACE_(mfplat)("Created wg_sample %p for IMediaBuffer %p.\n", *out, media_buffer); + return S_OK; + +fail: + if (sample->u.dmo.buffer) + IMediaBuffer_Release(sample->u.dmo.buffer); + free(sample); + return hr; +} + void wg_sample_release(struct wg_sample *wg_sample) { struct sample *sample = CONTAINING_RECORD(wg_sample, struct sample, wg_sample); @@ -408,3 +466,76 @@ HRESULT wg_transform_read_quartz(struct wg_transform *transform, struct wg_sampl
return S_OK; } + +HRESULT wg_transform_push_dmo(struct wg_transform *transform, IMediaBuffer *media_buffer, + DWORD flags, REFERENCE_TIME time_stamp, REFERENCE_TIME time_length, struct wg_sample_queue *queue) +{ + struct wg_sample *wg_sample; + HRESULT hr; + + TRACE_(mfplat)("transform %p, media_buffer %p, flags %#lx, time_stamp %s, time_length %s, queue %p.\n", + transform, media_buffer, flags, wine_dbgstr_longlong(time_stamp), wine_dbgstr_longlong(time_length), queue); + + if (FAILED(hr = wg_sample_create_dmo(media_buffer, &wg_sample))) + return hr; + + if (flags & DMO_INPUT_DATA_BUFFERF_SYNCPOINT) + wg_sample->flags |= WG_SAMPLE_FLAG_SYNC_POINT; + if (flags & DMO_INPUT_DATA_BUFFERF_TIME) + { + wg_sample->flags |= WG_SAMPLE_FLAG_HAS_PTS; + wg_sample->pts = time_stamp; + } + if (flags & DMO_INPUT_DATA_BUFFERF_TIMELENGTH) + { + wg_sample->flags |= WG_SAMPLE_FLAG_HAS_DURATION; + wg_sample->pts = time_length; + } + + wg_sample_queue_begin_append(queue, wg_sample); + hr = wg_transform_push_data(transform, wg_sample); + wg_sample_queue_end_append(queue, wg_sample); + + return hr; +} + +HRESULT wg_transform_read_dmo(struct wg_transform *transform, DMO_OUTPUT_DATA_BUFFER *buffer, struct wg_format *format) +{ + struct wg_sample *wg_sample; + HRESULT hr; + + TRACE_(mfplat)("transform %p, buffer %p, format %p.\n", transform, buffer, format); + + if (FAILED(hr = wg_sample_create_dmo(buffer->pBuffer, &wg_sample))) + return hr; + wg_sample->size = 0; + + if (FAILED(hr = wg_transform_read_data(transform, wg_sample, format))) + { + if (hr == MF_E_TRANSFORM_STREAM_CHANGE && !format) + FIXME("Unexpected stream format change!\n"); + wg_sample_release(wg_sample); + return hr; + } + + buffer->dwStatus = 0; + if (wg_sample->flags & WG_SAMPLE_FLAG_INCOMPLETE) + buffer->dwStatus |= DMO_OUTPUT_DATA_BUFFERF_INCOMPLETE; + if (wg_sample->flags & WG_SAMPLE_FLAG_HAS_PTS) + { + buffer->dwStatus |= DMO_OUTPUT_DATA_BUFFERF_TIME; + buffer->rtTimestamp = wg_sample->pts; + } + if (wg_sample->flags & WG_SAMPLE_FLAG_HAS_DURATION) + { + buffer->dwStatus |= DMO_OUTPUT_DATA_BUFFERF_TIMELENGTH; + buffer->rtTimelength = wg_sample->duration; + } + if (wg_sample->flags & WG_SAMPLE_FLAG_SYNC_POINT) + buffer->dwStatus |= DMO_OUTPUT_DATA_BUFFERF_SYNCPOINT; + + IMediaBuffer_SetLength(buffer->pBuffer, wg_sample->size); + + wg_sample_release(wg_sample); + return hr; +}
From: Ziqing Hui zhui@codeweavers.com
Wrong plugins will be selected for WMV decoder if we don't set format field. --- dlls/winegstreamer/quartz_parser.c | 14 ++++++++++++++ dlls/winegstreamer/unixlib.h | 9 +++++++++ dlls/winegstreamer/wg_format.c | 18 ++++++++++++++++++ 3 files changed, 41 insertions(+)
diff --git a/dlls/winegstreamer/quartz_parser.c b/dlls/winegstreamer/quartz_parser.c index 5561b106327..11fd0804ecc 100644 --- a/dlls/winegstreamer/quartz_parser.c +++ b/dlls/winegstreamer/quartz_parser.c @@ -761,11 +761,25 @@ static bool amt_to_wg_format_video_wmv(const AM_MEDIA_TYPE *mt, struct wg_format format->u.video_wmv.fps_d = video_format->AvgTimePerFrame;
if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMV1)) + { format->u.video_wmv.version = 1; + format->u.video_wmv.format = WG_WMV_VIDEO_FORMAT_WMV1; + } else if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMV2)) + { format->u.video_wmv.version = 2; + format->u.video_wmv.format = WG_WMV_VIDEO_FORMAT_WMV2; + } else + { format->u.video_wmv.version = 3; + if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMVA)) + format->u.video_wmv.format = WG_WMV_VIDEO_FORMAT_WMVA; + else if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WVC1)) + format->u.video_wmv.format = WG_WMV_VIDEO_FORMAT_WVC1; + else + format->u.video_wmv.format = WG_WMV_VIDEO_FORMAT_WMV3; + }
return true; } diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h index 5c55fbfe229..09805abd14b 100644 --- a/dlls/winegstreamer/unixlib.h +++ b/dlls/winegstreamer/unixlib.h @@ -129,6 +129,15 @@ struct wg_format } video_h264; struct { + enum wg_wmv_video_format + { + WG_WMV_VIDEO_FORMAT_UNKNOWN, + WG_WMV_VIDEO_FORMAT_WMV1, + WG_WMV_VIDEO_FORMAT_WMV2, + WG_WMV_VIDEO_FORMAT_WMV3, + WG_WMV_VIDEO_FORMAT_WMVA, + WG_WMV_VIDEO_FORMAT_WVC1, + } format; int32_t width, height; uint32_t fps_n, fps_d; uint32_t version; diff --git a/dlls/winegstreamer/wg_format.c b/dlls/winegstreamer/wg_format.c index a7876977d6c..8bc28978c9b 100644 --- a/dlls/winegstreamer/wg_format.c +++ b/dlls/winegstreamer/wg_format.c @@ -556,11 +556,29 @@ static GstCaps *wg_format_to_caps_video_h264(const struct wg_format *format)
static GstCaps *wg_format_to_caps_video_wmv(const struct wg_format *format) { + const char *wmv_format; GstCaps *caps;
if (!(caps = gst_caps_new_empty_simple("video/x-wmv"))) return NULL;
+ switch (format->u.video_wmv.format) + { + case WG_WMV_VIDEO_FORMAT_WMV1: wmv_format = "WMV1"; break; + case WG_WMV_VIDEO_FORMAT_WMV2: wmv_format = "WMV2"; break; + case WG_WMV_VIDEO_FORMAT_WMV3: wmv_format = "WMV3"; break; + case WG_WMV_VIDEO_FORMAT_WMVA: wmv_format = "WMVA"; break; + case WG_WMV_VIDEO_FORMAT_WVC1: wmv_format = "WVC1"; break; + default: + GST_WARNING("Unknown WMV format %u.", format->u.video_wmv.format); + /* fallthrough */ + case WG_WMV_VIDEO_FORMAT_UNKNOWN: + wmv_format = NULL; + break; + } + if (wmv_format) + gst_caps_set_simple(caps, "format", G_TYPE_STRING, wmv_format, NULL); + if (format->u.video_wmv.width) gst_caps_set_simple(caps, "width", G_TYPE_INT, format->u.video_wmv.width, NULL); if (format->u.video_wmv.height)
From: Ziqing Hui zhui@codeweavers.com
Framerate is fps_n / fps_d. So fps_d should not be zero. --- dlls/winegstreamer/quartz_parser.c | 24 ++++++++++++++++++++---- dlls/winegstreamer/wg_format.c | 13 +++++++++---- 2 files changed, 29 insertions(+), 8 deletions(-)
diff --git a/dlls/winegstreamer/quartz_parser.c b/dlls/winegstreamer/quartz_parser.c index 11fd0804ecc..79d2f0791ef 100644 --- a/dlls/winegstreamer/quartz_parser.c +++ b/dlls/winegstreamer/quartz_parser.c @@ -723,8 +723,16 @@ static bool amt_to_wg_format_video(const AM_MEDIA_TYPE *mt, struct wg_format *fo format->major_type = WG_MAJOR_TYPE_VIDEO; format->u.video.width = video_format->bmiHeader.biWidth; format->u.video.height = video_format->bmiHeader.biHeight; - format->u.video.fps_n = 10000000; - format->u.video.fps_d = video_format->AvgTimePerFrame; + if (video_format->AvgTimePerFrame) + { + format->u.video.fps_n = 10000000; + format->u.video.fps_d = video_format->AvgTimePerFrame; + } + else + { + format->u.video.fps_n = 0; + format->u.video.fps_d = 1; + }
for (i = 0; i < ARRAY_SIZE(format_map); ++i) { @@ -757,8 +765,16 @@ static bool amt_to_wg_format_video_wmv(const AM_MEDIA_TYPE *mt, struct wg_format format->major_type = WG_MAJOR_TYPE_VIDEO_WMV; format->u.video_wmv.width = video_format->bmiHeader.biWidth; format->u.video_wmv.height = video_format->bmiHeader.biHeight; - format->u.video_wmv.fps_n = 10000000; - format->u.video_wmv.fps_d = video_format->AvgTimePerFrame; + if (video_format->AvgTimePerFrame) + { + format->u.video.fps_n = 10000000; + format->u.video.fps_d = video_format->AvgTimePerFrame; + } + else + { + format->u.video.fps_n = 0; + format->u.video.fps_d = 1; + }
if (IsEqualGUID(&mt->subtype, &MEDIASUBTYPE_WMV1)) { diff --git a/dlls/winegstreamer/wg_format.c b/dlls/winegstreamer/wg_format.c index 8bc28978c9b..7cb12863bce 100644 --- a/dlls/winegstreamer/wg_format.c +++ b/dlls/winegstreamer/wg_format.c @@ -422,6 +422,11 @@ static GstCaps *wg_format_to_caps_video(const struct wg_format *format) return NULL;
gst_video_info_set_format(&info, video_format, format->u.video.width, abs(format->u.video.height)); + if (format->u.video.fps_d) + { + GST_VIDEO_INFO_FPS_N(&info) = format->u.video.fps_n; + GST_VIDEO_INFO_FPS_D(&info) = format->u.video.fps_d; + } if ((caps = gst_video_info_to_caps(&info))) { for (i = 0; i < gst_caps_get_size(caps); ++i) @@ -430,7 +435,7 @@ static GstCaps *wg_format_to_caps_video(const struct wg_format *format) gst_structure_remove_fields(gst_caps_get_structure(caps, i), "width", NULL); if (!format->u.video.height) gst_structure_remove_fields(gst_caps_get_structure(caps, i), "height", NULL); - if (!format->u.video.fps_d && !format->u.video.fps_n) + if (!format->u.video.fps_d) gst_structure_remove_fields(gst_caps_get_structure(caps, i), "framerate", NULL); } } @@ -448,7 +453,7 @@ static GstCaps *wg_format_to_caps_video_cinepak(const struct wg_format *format) gst_caps_set_simple(caps, "width", G_TYPE_INT, format->u.video_cinepak.width, NULL); if (format->u.video_cinepak.height) gst_caps_set_simple(caps, "height", G_TYPE_INT, format->u.video_cinepak.height, NULL); - if (format->u.video_cinepak.fps_d || format->u.video_cinepak.fps_n) + if (format->u.video_cinepak.fps_d) gst_caps_set_simple(caps, "framerate", GST_TYPE_FRACTION, format->u.video_cinepak.fps_n, format->u.video_cinepak.fps_d, NULL);
return caps; @@ -505,7 +510,7 @@ static GstCaps *wg_format_to_caps_video_h264(const struct wg_format *format) gst_caps_set_simple(caps, "width", G_TYPE_INT, format->u.video_h264.width, NULL); if (format->u.video_h264.height) gst_caps_set_simple(caps, "height", G_TYPE_INT, format->u.video_h264.height, NULL); - if (format->u.video_h264.fps_n || format->u.video_h264.fps_d) + if (format->u.video_h264.fps_d) gst_caps_set_simple(caps, "framerate", GST_TYPE_FRACTION, format->u.video_h264.fps_n, format->u.video_h264.fps_d, NULL);
switch (format->u.video_h264.profile) @@ -583,7 +588,7 @@ static GstCaps *wg_format_to_caps_video_wmv(const struct wg_format *format) gst_caps_set_simple(caps, "width", G_TYPE_INT, format->u.video_wmv.width, NULL); if (format->u.video_wmv.height) gst_caps_set_simple(caps, "height", G_TYPE_INT, format->u.video_wmv.height, NULL); - if (format->u.video_wmv.fps_d || format->u.video_wmv.fps_n) + if (format->u.video_wmv.fps_d) gst_caps_set_simple(caps, "framerate", GST_TYPE_FRACTION, format->u.video_wmv.fps_n, format->u.video_wmv.fps_d, NULL); if (format->u.video_wmv.version) gst_caps_set_simple(caps, "wmvversion", G_TYPE_INT, format->u.video_wmv.version, NULL);
From: Ziqing Hui zhui@codeweavers.com
--- dlls/winegstreamer/wg_transform.c | 4 +-- dlls/winegstreamer/wmv_decoder.c | 52 ++++++++++++++++++++++++++++--- 2 files changed, 49 insertions(+), 7 deletions(-)
diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c index f4244708a8f..cb7d917634c 100644 --- a/dlls/winegstreamer/wg_transform.c +++ b/dlls/winegstreamer/wg_transform.c @@ -427,6 +427,7 @@ NTSTATUS wg_transform_create(void *args) case WG_MAJOR_TYPE_AUDIO_MPEG4: case WG_MAJOR_TYPE_AUDIO_WMA: case WG_MAJOR_TYPE_VIDEO_CINEPAK: + case WG_MAJOR_TYPE_VIDEO_WMV: if (!(element = transform_find_element(GST_ELEMENT_FACTORY_TYPE_DECODER, src_caps, raw_caps)) || !transform_append_element(transform, element, &first, &last)) { @@ -439,7 +440,6 @@ NTSTATUS wg_transform_create(void *args) case WG_MAJOR_TYPE_VIDEO: break; case WG_MAJOR_TYPE_UNKNOWN: - case WG_MAJOR_TYPE_VIDEO_WMV: GST_FIXME("Format %u not implemented!", input_format.major_type); gst_caps_unref(raw_caps); goto out; @@ -468,6 +468,7 @@ NTSTATUS wg_transform_create(void *args) break;
case WG_MAJOR_TYPE_VIDEO: + case WG_MAJOR_TYPE_VIDEO_WMV: if (!(element = create_element("videoconvert", "base")) || !transform_append_element(transform, element, &first, &last)) goto out; @@ -481,7 +482,6 @@ NTSTATUS wg_transform_create(void *args) case WG_MAJOR_TYPE_VIDEO_CINEPAK: case WG_MAJOR_TYPE_VIDEO_H264: case WG_MAJOR_TYPE_UNKNOWN: - case WG_MAJOR_TYPE_VIDEO_WMV: GST_FIXME("Format %u not implemented!", output_format.major_type); goto out; } diff --git a/dlls/winegstreamer/wmv_decoder.c b/dlls/winegstreamer/wmv_decoder.c index 473fabab867..e92b7c49d40 100644 --- a/dlls/winegstreamer/wmv_decoder.c +++ b/dlls/winegstreamer/wmv_decoder.c @@ -83,6 +83,9 @@ struct wmv_decoder struct wg_format input_format; struct wg_format output_format; GUID output_subtype; + + struct wg_transform *wg_transform; + struct wg_sample_queue *wg_sample_queue; };
static bool wg_format_is_set(struct wg_format *format) @@ -140,7 +143,12 @@ static ULONG WINAPI unknown_Release(IUnknown *iface) 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; } @@ -489,6 +497,11 @@ 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)); + if (decoder->wg_transform) + { + wg_transform_destroy(decoder->wg_transform); + decoder->wg_transform = NULL; + } return S_OK; } return DMO_E_TYPE_NOT_ACCEPTED; @@ -506,8 +519,15 @@ static HRESULT WINAPI media_object_SetInputType(IMediaObject *iface, DWORD index if (!amt_to_wg_format((const AM_MEDIA_TYPE *)type, &wg_format)) return DMO_E_TYPE_NOT_ACCEPTED;
- if (!(flags & DMO_SET_TYPEF_TEST_ONLY)) - decoder->input_format = wg_format; + if (flags & DMO_SET_TYPEF_TEST_ONLY) + return S_OK; + + decoder->input_format = wg_format; + if (decoder->wg_transform) + { + wg_transform_destroy(decoder->wg_transform); + decoder->wg_transform = NULL; + }
return S_OK; } @@ -529,6 +549,11 @@ 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)); + if (decoder->wg_transform) + { + wg_transform_destroy(decoder->wg_transform); + decoder->wg_transform = NULL; + } return S_OK; } return E_POINTER; @@ -549,10 +574,21 @@ static HRESULT WINAPI media_object_SetOutputType(IMediaObject *iface, DWORD inde if (!amt_to_wg_format((const AM_MEDIA_TYPE *)type, &wg_format)) return DMO_E_TYPE_NOT_ACCEPTED;
- if (!(flags & DMO_SET_TYPEF_TEST_ONLY)) + if (flags & DMO_SET_TYPEF_TEST_ONLY) + return S_OK; + + decoder->output_subtype = type->subtype; + decoder->output_format = wg_format; + /* Set up wg_transform. */ + if (decoder->wg_transform) { - decoder->output_subtype = type->subtype; - decoder->output_format = wg_format; + if (!wg_transform_set_output_format(decoder->wg_transform, &decoder->output_format)) + return E_FAIL; + } + else + { + if (!(decoder->wg_transform = wg_transform_create(&decoder->input_format, &decoder->output_format))) + return E_FAIL; }
return S_OK; @@ -799,11 +835,17 @@ static const IPropertyStoreVtbl property_store_vtbl = HRESULT wmv_decoder_create(IUnknown *outer, IUnknown **out) { struct wmv_decoder *impl; + HRESULT hr;
TRACE("outer %p, out %p.\n", outer, out);
if (!(impl = calloc(1, sizeof(*impl)))) return E_OUTOFMEMORY; + if (FAILED(hr = wg_sample_queue_create(&impl->wg_sample_queue))) + { + free(impl); + return hr; + }
impl->IUnknown_inner.lpVtbl = &unknown_vtbl; impl->IMFTransform_iface.lpVtbl = &transform_vtbl;
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=129240
Your paranoid android.
=== w8 (32 bit report) ===
mf: transform.c:1465: Test failed: wmvdec: in 3: SetInputType returned 0x80040205 for flag 0.transform.c:1465: Test failed: wmvdec: in 3: SetInputType returned 0x80040205 for flag 0x4.transform.c:1465: Test failed: wmvdec: in 3: SetInputType returned 0x80040205 for flag 0x2.transform.c:1479: Test failed: wmvdec: in 3: SetInputType returned 0x80040205. transform.c:1465: Test failed: wmvdec: in 7: SetInputType returned 0x80040205 for flag 0.transform.c:1465: Test failed: wmvdec: in 7: SetInputType returned 0x80040205 for flag 0x4.transform.c:1465: Test failed: wmvdec: in 7: SetInputType returned 0x80040205 for flag 0x2.transform.c:1479: Test failed: wmvdec: in 7: SetInputType returned 0x80040205.
=== w8adm (32 bit report) ===
mf: transform.c:1465: Test failed: wmvdec: in 3: SetInputType returned 0x80040205 for flag 0.transform.c:1465: Test failed: wmvdec: in 3: SetInputType returned 0x80040205 for flag 0x4.transform.c:1465: Test failed: wmvdec: in 3: SetInputType returned 0x80040205 for flag 0x2.transform.c:1479: Test failed: wmvdec: in 3: SetInputType returned 0x80040205. transform.c:1465: Test failed: wmvdec: in 7: SetInputType returned 0x80040205 for flag 0.transform.c:1465: Test failed: wmvdec: in 7: SetInputType returned 0x80040205 for flag 0x4.transform.c:1465: Test failed: wmvdec: in 7: SetInputType returned 0x80040205 for flag 0x2.transform.c:1479: Test failed: wmvdec: in 7: SetInputType returned 0x80040205.
=== w864 (32 bit report) ===
mf: transform.c:1465: Test failed: wmvdec: in 3: SetInputType returned 0x80040205 for flag 0.transform.c:1465: Test failed: wmvdec: in 3: SetInputType returned 0x80040205 for flag 0x4.transform.c:1465: Test failed: wmvdec: in 3: SetInputType returned 0x80040205 for flag 0x2.transform.c:1479: Test failed: wmvdec: in 3: SetInputType returned 0x80040205. transform.c:1465: Test failed: wmvdec: in 7: SetInputType returned 0x80040205 for flag 0.transform.c:1465: Test failed: wmvdec: in 7: SetInputType returned 0x80040205 for flag 0x4.transform.c:1465: Test failed: wmvdec: in 7: SetInputType returned 0x80040205 for flag 0x2.transform.c:1479: Test failed: wmvdec: in 7: SetInputType returned 0x80040205.
=== w1064v1507 (32 bit report) ===
mf: transform.c:1465: Test failed: wmvdec: in 3: SetInputType returned 0x80040205 for flag 0.transform.c:1465: Test failed: wmvdec: in 3: SetInputType returned 0x80040205 for flag 0x4.transform.c:1465: Test failed: wmvdec: in 3: SetInputType returned 0x80040205 for flag 0x2.transform.c:1479: Test failed: wmvdec: in 3: SetInputType returned 0x80040205. transform.c:1465: Test failed: wmvdec: in 7: SetInputType returned 0x80040205 for flag 0.transform.c:1465: Test failed: wmvdec: in 7: SetInputType returned 0x80040205 for flag 0x4.transform.c:1465: Test failed: wmvdec: in 7: SetInputType returned 0x80040205 for flag 0x2.transform.c:1479: Test failed: wmvdec: in 7: SetInputType returned 0x80040205.
=== w1064_tsign (32 bit report) ===
mf: transform.c:1465: Test failed: wmvdec: in 3: SetInputType returned 0x80040205 for flag 0.transform.c:1465: Test failed: wmvdec: in 3: SetInputType returned 0x80040205 for flag 0x4.transform.c:1465: Test failed: wmvdec: in 3: SetInputType returned 0x80040205 for flag 0x2.transform.c:1479: Test failed: wmvdec: in 3: SetInputType returned 0x80040205. transform.c:1465: Test failed: wmvdec: in 7: SetInputType returned 0x80040205 for flag 0.transform.c:1465: Test failed: wmvdec: in 7: SetInputType returned 0x80040205 for flag 0x4.transform.c:1465: Test failed: wmvdec: in 7: SetInputType returned 0x80040205 for flag 0x2.transform.c:1479: Test failed: wmvdec: in 7: SetInputType returned 0x80040205.
Looks like I should fix the test failure first. Also, I'd like to split the tests and implementations into different MRs. So I'll close this MR now.
This merge request was closed by Ziqing Hui.