From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/media_source.c | 82 +++++++++++++++++-------------- 1 file changed, 46 insertions(+), 36 deletions(-)
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c index 41271585454..970c75530b0 100644 --- a/dlls/winegstreamer/media_source.c +++ b/dlls/winegstreamer/media_source.c @@ -293,6 +293,32 @@ static IMFStreamDescriptor *stream_descriptor_from_id(IMFPresentationDescriptor return NULL; }
+static HRESULT stream_descriptor_set_tag(IMFStreamDescriptor *descriptor, struct wg_parser_stream *stream, + const GUID *attr, enum wg_parser_tag tag) +{ + WCHAR *strW; + HRESULT hr; + DWORD len; + char *str; + + if (!(str = wg_parser_stream_get_tag(stream, tag)) + || !(len = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0))) + hr = S_OK; + else if (!(strW = malloc(len * sizeof(*strW)))) + hr = E_OUTOFMEMORY; + else + { + if (MultiByteToWideChar(CP_UTF8, 0, str, -1, strW, len)) + hr = IMFStreamDescriptor_SetString(descriptor, attr, strW); + else + hr = E_FAIL; + free(strW); + } + + free(str); + return hr; +} + static BOOL enqueue_token(struct media_stream *stream, IUnknown *token) { if (stream->token_queue_count == stream->token_queue_cap) @@ -1476,6 +1502,25 @@ static const IMFMediaSourceVtbl IMFMediaSource_vtbl = media_source_Shutdown, };
+static void media_source_init_descriptors(struct media_source *source) +{ + HRESULT hr = S_OK; + UINT i; + + for (i = 0; i < source->stream_count; i++) + { + struct media_stream *stream = source->streams[i]; + IMFStreamDescriptor *descriptor = stream->descriptor; + + if (FAILED(hr = stream_descriptor_set_tag(descriptor, stream->wg_stream, + &MF_SD_LANGUAGE, WG_PARSER_TAG_LANGUAGE))) + WARN("Failed to set stream descriptor language, hr %#lx\n", hr); + if (FAILED(hr = stream_descriptor_set_tag(descriptor, stream->wg_stream, + &MF_SD_STREAM_NAME, WG_PARSER_TAG_NAME))) + WARN("Failed to set stream descriptor name, hr %#lx\n", hr); + } +} + static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_source **out_media_source) { unsigned int stream_count = UINT_MAX; @@ -1574,42 +1619,7 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_ object->stream_count++; }
- /* init presentation descriptor */ - - for (i = 0; i < object->stream_count; i++) - { - static const struct - { - enum wg_parser_tag tag; - const GUID *mf_attr; - } - tags[] = - { - {WG_PARSER_TAG_LANGUAGE, &MF_SD_LANGUAGE}, - {WG_PARSER_TAG_NAME, &MF_SD_STREAM_NAME}, - }; - unsigned int j; - WCHAR *strW; - DWORD len; - char *str; - - for (j = 0; j < ARRAY_SIZE(tags); ++j) - { - if (!(str = wg_parser_stream_get_tag(object->streams[i]->wg_stream, tags[j].tag))) - continue; - if (!(len = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0))) - { - free(str); - continue; - } - strW = malloc(len * sizeof(*strW)); - if (MultiByteToWideChar(CP_UTF8, 0, str, -1, strW, len)) - IMFStreamDescriptor_SetString(object->descriptors[i], tags[j].mf_attr, strW); - free(strW); - free(str); - } - } - + media_source_init_descriptors(object); object->state = SOURCE_STOPPED;
*out_media_source = object;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/media_source.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c index 970c75530b0..6cb7ffb315a 100644 --- a/dlls/winegstreamer/media_source.c +++ b/dlls/winegstreamer/media_source.c @@ -881,13 +881,12 @@ static const IMFMediaStreamVtbl media_stream_vtbl = };
static HRESULT media_stream_create(IMFMediaSource *source, DWORD id, - struct media_stream **out) + struct wg_parser_stream *wg_stream, struct media_stream **out) { - struct wg_parser *wg_parser = impl_from_IMFMediaSource(source)->wg_parser; struct media_stream *object; HRESULT hr;
- TRACE("source %p, id %lu.\n", source, id); + TRACE("source %p, id %lu, wg_stream %p.\n", source, id, wg_stream);
if (!(object = calloc(1, sizeof(*object)))) return E_OUTOFMEMORY; @@ -907,7 +906,7 @@ static HRESULT media_stream_create(IMFMediaSource *source, DWORD id,
object->active = TRUE; object->eos = FALSE; - object->wg_stream = wg_parser_get_stream(wg_parser, id); + object->wg_stream = wg_stream;
TRACE("Created stream object %p.\n", object);
@@ -1599,9 +1598,10 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_
for (i = 0; i < stream_count; ++i) { + struct wg_parser_stream *wg_stream = wg_parser_get_stream(object->wg_parser, i); struct media_stream *stream;
- if (FAILED(hr = media_stream_create(&object->IMFMediaSource_iface, i, &stream))) + if (FAILED(hr = media_stream_create(&object->IMFMediaSource_iface, i, wg_stream, &stream))) goto fail; if (FAILED(hr = media_stream_init_desc(stream))) { @@ -1612,7 +1612,7 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_ goto fail; }
- object->duration = max(object->duration, wg_parser_stream_get_duration(stream->wg_stream)); + object->duration = max(object->duration, wg_parser_stream_get_duration(wg_stream)); IMFStreamDescriptor_AddRef(stream->descriptor); object->descriptors[i] = stream->descriptor; object->streams[i] = stream;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/media_source.c | 31 +++++-------------------------- 1 file changed, 5 insertions(+), 26 deletions(-)
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c index 6cb7ffb315a..aae7df75e8e 100644 --- a/dlls/winegstreamer/media_source.c +++ b/dlls/winegstreamer/media_source.c @@ -925,6 +925,10 @@ static HRESULT media_stream_init_desc(struct media_stream *stream)
wg_parser_stream_get_preferred_format(stream->wg_stream, &format);
+ if (!(stream_types[0] = mf_media_type_from_wg_format(&format))) + return MF_E_INVALIDMEDIATYPE; + type_count = 1; + if (format.major_type == WG_MAJOR_TYPE_VIDEO) { /* Try to prefer YUV formats over RGB ones. Most decoders output in the @@ -937,20 +941,9 @@ static HRESULT media_stream_init_desc(struct media_stream *stream) WG_VIDEO_FORMAT_YUY2, WG_VIDEO_FORMAT_I420, }; - - IMFMediaType *base_type = mf_media_type_from_wg_format(&format); GUID base_subtype;
- if (!base_type) - { - hr = MF_E_INVALIDMEDIATYPE; - goto done; - } - - IMFMediaType_GetGUID(base_type, &MF_MT_SUBTYPE, &base_subtype); - - stream_types[0] = base_type; - type_count = 1; + IMFMediaType_GetGUID(stream_types[0], &MF_MT_SUBTYPE, &base_subtype);
for (i = 0; i < ARRAY_SIZE(video_formats); ++i) { @@ -990,9 +983,6 @@ static HRESULT media_stream_init_desc(struct media_stream *stream) WG_AUDIO_FORMAT_F32LE, };
- if ((stream_types[0] = mf_media_type_from_wg_format(&format))) - type_count = 1; - for (i = 0; i < ARRAY_SIZE(audio_types); i++) { struct wg_format new_format; @@ -1004,20 +994,9 @@ static HRESULT media_stream_init_desc(struct media_stream *stream) type_count++; } } - else - { - if ((stream_types[0] = mf_media_type_from_wg_format(&format))) - type_count = 1; - }
assert(type_count <= ARRAY_SIZE(stream_types));
- if (!type_count) - { - ERR("Failed to establish an IMFMediaType from any of the possible stream caps!\n"); - return E_FAIL; - } - if (FAILED(hr = MFCreateStreamDescriptor(stream->stream_id, type_count, stream_types, &stream->descriptor))) goto done;
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/media_source.c | 98 ++++++++++++++++++------------- 1 file changed, 57 insertions(+), 41 deletions(-)
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c index aae7df75e8e..abb539695d8 100644 --- a/dlls/winegstreamer/media_source.c +++ b/dlls/winegstreamer/media_source.c @@ -319,6 +319,61 @@ static HRESULT stream_descriptor_set_tag(IMFStreamDescriptor *descriptor, struct return hr; }
+static HRESULT init_video_media_types(struct wg_format *format, IMFMediaType *types[6], DWORD *types_count) +{ + /* Try to prefer YUV formats over RGB ones. Most decoders output in the + * YUV color space, and it's generally much less expensive for + * videoconvert to do YUV -> YUV transformations. */ + static const enum wg_video_format video_formats[] = + { + WG_VIDEO_FORMAT_NV12, + WG_VIDEO_FORMAT_YV12, + WG_VIDEO_FORMAT_YUY2, + WG_VIDEO_FORMAT_I420, + }; + UINT count = *types_count, i; + GUID base_subtype; + HRESULT hr; + + if (FAILED(hr = IMFMediaType_GetGUID(types[0], &MF_MT_SUBTYPE, &base_subtype))) + return hr; + + for (i = 0; i < ARRAY_SIZE(video_formats); ++i) + { + struct wg_format new_format = *format; + IMFMediaType *new_type; + + new_format.u.video.format = video_formats[i]; + + if (!(new_type = mf_media_type_from_wg_format(&new_format))) + { + hr = E_OUTOFMEMORY; + goto done; + } + types[count++] = new_type; + + if (video_formats[i] == WG_VIDEO_FORMAT_I420) + { + IMFMediaType *iyuv_type; + + if (FAILED(hr = MFCreateMediaType(&iyuv_type))) + goto done; + if (FAILED(hr = IMFMediaType_CopyAllItems(new_type, (IMFAttributes *)iyuv_type))) + goto done; + if (FAILED(hr = IMFMediaType_SetGUID(iyuv_type, &MF_MT_SUBTYPE, &MFVideoFormat_IYUV))) + goto done; + types[count++] = iyuv_type; + } + } + + *types_count = count; + +done: + while (FAILED(hr) && count--) + IMFMediaType_Release(types[count]); + return hr; +} + static BOOL enqueue_token(struct media_stream *stream, IUnknown *token) { if (stream->token_queue_count == stream->token_queue_cap) @@ -931,47 +986,8 @@ static HRESULT media_stream_init_desc(struct media_stream *stream)
if (format.major_type == WG_MAJOR_TYPE_VIDEO) { - /* Try to prefer YUV formats over RGB ones. Most decoders output in the - * YUV color space, and it's generally much less expensive for - * videoconvert to do YUV -> YUV transformations. */ - static const enum wg_video_format video_formats[] = - { - WG_VIDEO_FORMAT_NV12, - WG_VIDEO_FORMAT_YV12, - WG_VIDEO_FORMAT_YUY2, - WG_VIDEO_FORMAT_I420, - }; - GUID base_subtype; - - IMFMediaType_GetGUID(stream_types[0], &MF_MT_SUBTYPE, &base_subtype); - - for (i = 0; i < ARRAY_SIZE(video_formats); ++i) - { - struct wg_format new_format = format; - IMFMediaType *new_type; - - new_format.u.video.format = video_formats[i]; - - if (!(new_type = mf_media_type_from_wg_format(&new_format))) - { - hr = E_OUTOFMEMORY; - goto done; - } - stream_types[type_count++] = new_type; - - if (video_formats[i] == WG_VIDEO_FORMAT_I420) - { - IMFMediaType *iyuv_type; - - if (FAILED(hr = MFCreateMediaType(&iyuv_type))) - goto done; - if (FAILED(hr = IMFMediaType_CopyAllItems(new_type, (IMFAttributes *)iyuv_type))) - goto done; - if (FAILED(hr = IMFMediaType_SetGUID(iyuv_type, &MF_MT_SUBTYPE, &MFVideoFormat_IYUV))) - goto done; - stream_types[type_count++] = iyuv_type; - } - } + if (FAILED(hr = init_video_media_types(&format, stream_types, &type_count))) + return hr; } else if (format.major_type == WG_MAJOR_TYPE_AUDIO) {
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/media_source.c | 45 ++++++++++++++++++------------- 1 file changed, 27 insertions(+), 18 deletions(-)
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c index abb539695d8..14f2a7b6291 100644 --- a/dlls/winegstreamer/media_source.c +++ b/dlls/winegstreamer/media_source.c @@ -374,6 +374,31 @@ done: return hr; }
+static HRESULT init_audio_media_types(struct wg_format *format, IMFMediaType *types[6], DWORD *types_count) +{ + /* Expose at least one PCM and one floating point type for the + consumer to pick from. */ + static const enum wg_audio_format audio_types[] = + { + WG_AUDIO_FORMAT_S16LE, + WG_AUDIO_FORMAT_F32LE, + }; + UINT count = *types_count, i; + + for (i = 0; i < ARRAY_SIZE(audio_types); i++) + { + struct wg_format new_format = *format; + if (new_format.u.audio.format == audio_types[i]) + continue; + new_format.u.audio.format = audio_types[i]; + if ((types[count] = mf_media_type_from_wg_format(&new_format))) + count++; + } + + *types_count = count; + return S_OK; +} + static BOOL enqueue_token(struct media_stream *stream, IUnknown *token) { if (stream->token_queue_count == stream->token_queue_cap) @@ -991,24 +1016,8 @@ static HRESULT media_stream_init_desc(struct media_stream *stream) } else if (format.major_type == WG_MAJOR_TYPE_AUDIO) { - /* Expose at least one PCM and one floating point type for the - consumer to pick from. */ - static const enum wg_audio_format audio_types[] = - { - WG_AUDIO_FORMAT_S16LE, - WG_AUDIO_FORMAT_F32LE, - }; - - for (i = 0; i < ARRAY_SIZE(audio_types); i++) - { - struct wg_format new_format; - if (format.u.audio.format == audio_types[i]) - continue; - new_format = format; - new_format.u.audio.format = audio_types[i]; - if ((stream_types[type_count] = mf_media_type_from_wg_format(&new_format))) - type_count++; - } + if (FAILED(hr = init_audio_media_types(&format, stream_types, &type_count))) + return hr; }
assert(type_count <= ARRAY_SIZE(stream_types));
From: Rémi Bernon rbernon@codeweavers.com
--- dlls/winegstreamer/media_source.c | 115 ++++++++++++++---------------- 1 file changed, 53 insertions(+), 62 deletions(-)
diff --git a/dlls/winegstreamer/media_source.c b/dlls/winegstreamer/media_source.c index 14f2a7b6291..38bfbfa5a91 100644 --- a/dlls/winegstreamer/media_source.c +++ b/dlls/winegstreamer/media_source.c @@ -399,6 +399,47 @@ static HRESULT init_audio_media_types(struct wg_format *format, IMFMediaType *ty return S_OK; }
+static HRESULT stream_descriptor_create(UINT32 id, struct wg_format *format, IMFStreamDescriptor **out) +{ + IMFStreamDescriptor *descriptor; + IMFMediaTypeHandler *handler; + IMFMediaType *types[6]; + DWORD count = 0; + HRESULT hr; + + if (!(types[0] = mf_media_type_from_wg_format(format))) + return MF_E_INVALIDMEDIATYPE; + count = 1; + + if (format->major_type == WG_MAJOR_TYPE_VIDEO) + { + if (FAILED(hr = init_video_media_types(format, types, &count))) + return hr; + } + else if (format->major_type == WG_MAJOR_TYPE_AUDIO) + { + if (FAILED(hr = init_audio_media_types(format, types, &count))) + return hr; + } + + if (FAILED(hr = MFCreateStreamDescriptor(id, count, types, &descriptor))) + goto done; + + if (FAILED(hr = IMFStreamDescriptor_GetMediaTypeHandler(descriptor, &handler))) + IMFStreamDescriptor_Release(descriptor); + else + { + hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, types[0]); + IMFMediaTypeHandler_Release(handler); + } + +done: + while (count--) + IMFMediaType_Release(types[count]); + *out = SUCCEEDED(hr) ? descriptor : NULL; + return hr; +} + static BOOL enqueue_token(struct media_stream *stream, IUnknown *token) { if (stream->token_queue_count == stream->token_queue_cap) @@ -960,13 +1001,13 @@ static const IMFMediaStreamVtbl media_stream_vtbl = media_stream_RequestSample };
-static HRESULT media_stream_create(IMFMediaSource *source, DWORD id, +static HRESULT media_stream_create(IMFMediaSource *source, IMFStreamDescriptor *descriptor, struct wg_parser_stream *wg_stream, struct media_stream **out) { struct media_stream *object; HRESULT hr;
- TRACE("source %p, id %lu, wg_stream %p.\n", source, id, wg_stream); + TRACE("source %p, descriptor %p, wg_stream %p.\n", source, descriptor, wg_stream);
if (!(object = calloc(1, sizeof(*object)))) return E_OUTOFMEMORY; @@ -982,7 +1023,8 @@ static HRESULT media_stream_create(IMFMediaSource *source, DWORD id,
IMFMediaSource_AddRef(source); object->media_source = source; - object->stream_id = id; + IMFStreamDescriptor_AddRef(descriptor); + object->descriptor = descriptor;
object->active = TRUE; object->eos = FALSE; @@ -994,57 +1036,6 @@ static HRESULT media_stream_create(IMFMediaSource *source, DWORD id, return S_OK; }
-static HRESULT media_stream_init_desc(struct media_stream *stream) -{ - IMFMediaTypeHandler *type_handler = NULL; - IMFMediaType *stream_types[6]; - struct wg_format format; - DWORD type_count = 0; - unsigned int i; - HRESULT hr; - - wg_parser_stream_get_preferred_format(stream->wg_stream, &format); - - if (!(stream_types[0] = mf_media_type_from_wg_format(&format))) - return MF_E_INVALIDMEDIATYPE; - type_count = 1; - - if (format.major_type == WG_MAJOR_TYPE_VIDEO) - { - if (FAILED(hr = init_video_media_types(&format, stream_types, &type_count))) - return hr; - } - else if (format.major_type == WG_MAJOR_TYPE_AUDIO) - { - if (FAILED(hr = init_audio_media_types(&format, stream_types, &type_count))) - return hr; - } - - assert(type_count <= ARRAY_SIZE(stream_types)); - - if (FAILED(hr = MFCreateStreamDescriptor(stream->stream_id, type_count, stream_types, &stream->descriptor))) - goto done; - - if (FAILED(hr = IMFStreamDescriptor_GetMediaTypeHandler(stream->descriptor, &type_handler))) - { - IMFStreamDescriptor_Release(stream->descriptor); - goto done; - } - - if (FAILED(hr = IMFMediaTypeHandler_SetCurrentMediaType(type_handler, stream_types[0]))) - { - IMFStreamDescriptor_Release(stream->descriptor); - goto done; - } - -done: - if (type_handler) - IMFMediaTypeHandler_Release(type_handler); - for (i = 0; i < type_count; i++) - IMFMediaType_Release(stream_types[i]); - return hr; -} - static HRESULT WINAPI media_source_get_service_QueryInterface(IMFGetService *iface, REFIID riid, void **obj) { struct media_source *source = impl_from_IMFGetService(iface); @@ -1603,22 +1594,22 @@ static HRESULT media_source_constructor(IMFByteStream *bytestream, struct media_ for (i = 0; i < stream_count; ++i) { struct wg_parser_stream *wg_stream = wg_parser_get_stream(object->wg_parser, i); + IMFStreamDescriptor *descriptor; struct media_stream *stream; + struct wg_format format;
- if (FAILED(hr = media_stream_create(&object->IMFMediaSource_iface, i, wg_stream, &stream))) + wg_parser_stream_get_preferred_format(wg_stream, &format); + if (FAILED(hr = stream_descriptor_create(i, &format, &descriptor))) goto fail; - if (FAILED(hr = media_stream_init_desc(stream))) + if (FAILED(hr = media_stream_create(&object->IMFMediaSource_iface, descriptor, wg_stream, &stream))) { - ERR("Failed to finish initialization of media stream %p, hr %#lx.\n", stream, hr); - IMFMediaSource_Release(stream->media_source); - IMFMediaEventQueue_Release(stream->event_queue); - free(stream); + IMFStreamDescriptor_Release(descriptor); goto fail; }
object->duration = max(object->duration, wg_parser_stream_get_duration(wg_stream)); - IMFStreamDescriptor_AddRef(stream->descriptor); - object->descriptors[i] = stream->descriptor; + IMFStreamDescriptor_AddRef(descriptor); + object->descriptors[i] = descriptor; object->streams[i] = stream; object->stream_count++; }
Nikolay Sivov (@nsivov) commented about dlls/winegstreamer/media_source.c:
+{
- IMFStreamDescriptor *descriptor;
- IMFMediaTypeHandler *handler;
- IMFMediaType *types[6];
- DWORD count = 0;
- HRESULT hr;
- if (!(types[0] = mf_media_type_from_wg_format(format)))
return MF_E_INVALIDMEDIATYPE;
- count = 1;
- if (format->major_type == WG_MAJOR_TYPE_VIDEO)
- {
if (FAILED(hr = init_video_media_types(format, types, &count)))
return hr;
- }
Assertion for 'types' element count was removed, and now you have to assume that it's not exceeded by init_video_media_types().
Also, types[0] is leaked if init_video_media_types() fails.
On Mon Jun 5 21:17:08 2023 +0000, Nikolay Sivov wrote:
Assertion for 'types' element count was removed, and now you have to assume that it's not exceeded by init_video_media_types(). Also, types[0] is leaked if init_video_media_types() fails.
I initially removed the fake media types to only keep one, then changed my mind.
What do you think about doing that? The converters should then be automatically added if necessary, as native does it.
It's something I'd like to do ultimately but I don't know if everything is ready for that.