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 5b4c01a3cd0..53036dc1c00 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 c12e9ee3397..b2ea5525ddc 100644 --- a/dlls/winegstreamer/quartz_parser.c +++ b/dlls/winegstreamer/quartz_parser.c @@ -763,11 +763,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 19629d12fd0..cf1564f16ce 100644 --- a/dlls/winegstreamer/unixlib.h +++ b/dlls/winegstreamer/unixlib.h @@ -130,6 +130,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 63f1e3931b5..fca11666ce1 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 b2ea5525ddc..a1baafdab68 100644 --- a/dlls/winegstreamer/quartz_parser.c +++ b/dlls/winegstreamer/quartz_parser.c @@ -725,8 +725,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) { @@ -759,8 +767,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 fca11666ce1..05e46d78560 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 65a34511284..ccdd90361fc 100644 --- a/dlls/winegstreamer/wg_transform.c +++ b/dlls/winegstreamer/wg_transform.c @@ -428,6 +428,7 @@ NTSTATUS wg_transform_create(void *args) case WG_MAJOR_TYPE_AUDIO_WMA: case WG_MAJOR_TYPE_VIDEO_CINEPAK: case WG_MAJOR_TYPE_VIDEO_INDEO: + 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)) { @@ -440,7 +441,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; @@ -469,6 +469,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; @@ -482,7 +483,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: case WG_MAJOR_TYPE_VIDEO_INDEO: 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;
Rémi Bernon (@rbernon) commented about dlls/winegstreamer/gst_private.h:
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);
You're adding these but they aren't used anywhere, so it's dead code. You should probably introduce these whenever you implement ProcessOutput / ProcessInput (maybe separately?).
The "format" field introduced in patch 2/4 seems redundant with the version. I.e. I would delete the "version" field and derive it from the "format" field.
Also, please don't put more than one C statement on the same line.
Wrt patch 3/4, where are you running into this? Also, why do you need to change both the frontend and backend? (It also looks suspicious that you ensure the denominator is always nonzero in the frontend, but then check the denominator for zero in the backend rather than the numerator.)
Also, please don't put more than one C statement on the same line.
Do you mean code like this:
`case WG_WMV_VIDEO_FORMAT_WMV1: wmv_format = "WMV1"; break;` ?
If do, I just follow the parttern in wg_format_to_caps_video_h264(). Should I put `wmv_format = "WMV1";` and `break;` into new lines?
On Thu Feb 23 01:37:16 2023 +0000, Ziqing Hui wrote:
Also, please don't put more than one C statement on the same line.
Do you mean code like this: `case WG_WMV_VIDEO_FORMAT_WMV1: wmv_format = "WMV1"; break;` ? If do, I just follow the parttern in wg_format_to_caps_video_h264(). Should I put `wmv_format = "WMV1";` and `break;` into new lines?
Wrt patch 3/4, where are you running into this?
In wmv_decoder: media_object_SetOutputType(), the AvgTimePerFrame passed in could be zero (it's legal to be zero on Windows), which will leads to the fps_d of input_format or output_format in wg_transform_create() to be zero.
Then in wg_format_to_caps_video_wmv(), we use gst_caps_set_simple() to set "framerate" to be fps_n/fps_d, then gstreamer will complain abount FRACTION's is zero. It happens in the WMV DMO decoder tests in mf/tests/transform.c
Also, why do you need to change both the frontend and backend?
I changed wg_format_to_caps_video() (do you mean this is backend?) because we now totally ignore framerate settings in this function. the gst_video_info_set_format() call here only set format, width, height to info. Then we convert info to caps. So the result caps don't have framerate. Therefore I set framerate to info to make the result caps hold framerate information.
It also looks suspicious that you ensure the denominator is always nonzero in the frontend, but then check the denominator for zero in the backend rather than the numerator.
You are right. I could just move the denominator checking in frontend to wg_format_to_caps_video_{h264|wmv|cinepak}.
Also, I think it's ok to have numerator be zero. Zero framerate means variable fps in gstreamer. See: https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/blob/discontinue...