Since 1.20, gst_element_request_pad_simple is available and gst_element_get_request_pad is marked as deprecated.
-- v4: winegstreamer: Add MFMPEG4SinkClassFactory. mf/tests: Use h264 and aac in mp4 media sink tests. winegstreamer: Add codec data to h264 format. winegstreamer: Add push_event wrapper.
From: Ziqing Hui zhui@codeweavers.com
--- dlls/winegstreamer/unix_private.h | 1 + dlls/winegstreamer/unixlib.c | 14 ++++++++++++++ dlls/winegstreamer/wg_parser.c | 12 ++++++------ dlls/winegstreamer/wg_transform.c | 16 ++++++++-------- 4 files changed, 29 insertions(+), 14 deletions(-)
diff --git a/dlls/winegstreamer/unix_private.h b/dlls/winegstreamer/unix_private.h index db6bf3ebb2e..8bef7b2b2bd 100644 --- a/dlls/winegstreamer/unix_private.h +++ b/dlls/winegstreamer/unix_private.h @@ -39,6 +39,7 @@ extern GstElement *find_element(GstElementFactoryListType type, GstCaps *src_cap extern bool append_element(GstElement *container, GstElement *element, GstElement **first, GstElement **last) DECLSPEC_HIDDEN; extern bool link_src_to_element(GstPad *src_pad, GstElement *element) DECLSPEC_HIDDEN; extern bool link_element_to_sink(GstElement *element, GstPad *sink_pad) DECLSPEC_HIDDEN; +extern bool push_event(GstPad *pad, GstEvent *event) DECLSPEC_HIDDEN;
/* wg_format.c */
diff --git a/dlls/winegstreamer/unixlib.c b/dlls/winegstreamer/unixlib.c index 6ed38260536..7e5ef34c4d7 100644 --- a/dlls/winegstreamer/unixlib.c +++ b/dlls/winegstreamer/unixlib.c @@ -202,6 +202,20 @@ bool link_element_to_sink(GstElement *element, GstPad *sink_pad) return !ret; }
+bool push_event(GstPad *pad, GstEvent *event) +{ + if (!gst_pad_push_event(pad, event)) + { + const gchar *type_name = gst_event_type_get_name(GST_EVENT_TYPE(event)); + gchar *pad_name = gst_pad_get_name(pad); + + GST_ERROR("Failed to push %s event %p to pad %s.", type_name, event, pad_name); + g_free(pad_name); + return false; + } + return true; +} + NTSTATUS wg_init_gstreamer(void *arg) { char arg0[] = "wine"; diff --git a/dlls/winegstreamer/wg_parser.c b/dlls/winegstreamer/wg_parser.c index 298c05c6b88..5556b52829c 100644 --- a/dlls/winegstreamer/wg_parser.c +++ b/dlls/winegstreamer/wg_parser.c @@ -258,7 +258,7 @@ static NTSTATUS wg_parser_stream_enable(void *args) gst_util_set_object_arg(G_OBJECT(stream->flip), "method", flip ? "vertical-flip" : "none"); }
- gst_pad_push_event(stream->my_sink, gst_event_new_reconfigure()); + push_event(stream->my_sink, gst_event_new_reconfigure()); return S_OK; }
@@ -450,7 +450,7 @@ static NTSTATUS wg_parser_stream_seek(void *args) if ((stop_flags & AM_SEEKING_PositioningBitsMask) == AM_SEEKING_NoPositioning) stop_type = GST_SEEK_TYPE_NONE;
- if (!gst_pad_push_event(get_stream(params->stream)->my_sink, gst_event_new_seek(params->rate, GST_FORMAT_TIME, + if (!push_event(get_stream(params->stream)->my_sink, gst_event_new_seek(params->rate, GST_FORMAT_TIME, flags, start_type, params->start_pos * 100, stop_type, params->stop_pos * 100))) GST_ERROR("Failed to seek.\n");
@@ -480,7 +480,7 @@ static NTSTATUS wg_parser_stream_notify_qos(void *args) if (!(event = gst_event_new_qos(params->underflow ? GST_QOS_TYPE_UNDERFLOW : GST_QOS_TYPE_OVERFLOW, params->proportion, params->diff * 100, stream_time))) GST_ERROR("Failed to create QOS event.\n"); - gst_pad_push_event(stream->my_sink, event); + push_event(stream->my_sink, event);
return S_OK; } @@ -1292,7 +1292,7 @@ static void *push_data(void *arg)
gst_buffer_unref(buffer);
- gst_pad_push_event(parser->my_src, gst_event_new_eos()); + push_event(parser->my_src, gst_event_new_eos());
GST_DEBUG("Stopping push thread.");
@@ -1421,7 +1421,7 @@ static gboolean src_perform_seek(struct wg_parser *parser, GstEvent *event) { flush_event = gst_event_new_flush_start(); gst_event_set_seqnum(flush_event, seqnum); - gst_pad_push_event(parser->my_src, flush_event); + push_event(parser->my_src, flush_event); if (thread) gst_pad_set_active(parser->my_src, 1); } @@ -1433,7 +1433,7 @@ static gboolean src_perform_seek(struct wg_parser *parser, GstEvent *event) { flush_event = gst_event_new_flush_stop(TRUE); gst_event_set_seqnum(flush_event, seqnum); - gst_pad_push_event(parser->my_src, flush_event); + push_event(parser->my_src, flush_event); if (thread) gst_pad_set_active(parser->my_src, 1); } diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c index 775fed7a46c..38adf560892 100644 --- a/dlls/winegstreamer/wg_transform.c +++ b/dlls/winegstreamer/wg_transform.c @@ -443,10 +443,10 @@ NTSTATUS wg_transform_create(void *args) goto out;
if (!(event = gst_event_new_stream_start("stream")) - || !gst_pad_push_event(transform->my_src, event)) + || !push_event(transform->my_src, event)) goto out; if (!(event = gst_event_new_caps(src_caps)) - || !gst_pad_push_event(transform->my_src, event)) + || !push_event(transform->my_src, event)) goto out;
/* We need to use GST_FORMAT_TIME here because it's the only format @@ -455,7 +455,7 @@ NTSTATUS wg_transform_create(void *args) transform->segment.start = 0; transform->segment.stop = -1; if (!(event = gst_event_new_segment(&transform->segment)) - || !gst_pad_push_event(transform->my_src, event)) + || !push_event(transform->my_src, event)) goto out;
gst_caps_unref(src_caps); @@ -531,7 +531,7 @@ NTSTATUS wg_transform_set_output_format(void *args) value = "none"; gst_util_set_object_arg(G_OBJECT(transform->video_flip), "method", value); } - if (!gst_pad_push_event(transform->my_sink, gst_event_new_reconfigure())) + if (!push_event(transform->my_sink, gst_event_new_reconfigure())) { GST_ERROR("Failed to reconfigure transform %p.", transform); return STATUS_UNSUCCESSFUL; @@ -892,16 +892,16 @@ NTSTATUS wg_transform_drain(void *args) }
if (!(event = gst_event_new_segment_done(GST_FORMAT_TIME, -1)) - || !gst_pad_push_event(transform->my_src, event)) + || !push_event(transform->my_src, event)) goto error; if (!(event = gst_event_new_eos()) - || !gst_pad_push_event(transform->my_src, event)) + || !push_event(transform->my_src, event)) goto error; if (!(event = gst_event_new_stream_start("stream")) - || !gst_pad_push_event(transform->my_src, event)) + || !push_event(transform->my_src, event)) goto error; if (!(event = gst_event_new_segment(&transform->segment)) - || !gst_pad_push_event(transform->my_src, event)) + || !push_event(transform->my_src, event)) goto error;
return STATUS_SUCCESS;
From: Ziqing Hui zhui@codeweavers.com
--- dlls/winegstreamer/mfplat.c | 11 ++++++++++- dlls/winegstreamer/unixlib.h | 2 ++ dlls/winegstreamer/wg_format.c | 14 ++++++++++++++ 3 files changed, 26 insertions(+), 1 deletion(-)
diff --git a/dlls/winegstreamer/mfplat.c b/dlls/winegstreamer/mfplat.c index 7a37f25fcb2..d85568e5ecd 100644 --- a/dlls/winegstreamer/mfplat.c +++ b/dlls/winegstreamer/mfplat.c @@ -804,8 +804,9 @@ static void mf_media_type_to_wg_format_audio_wma(IMFMediaType *type, const GUID
static void mf_media_type_to_wg_format_video_h264(IMFMediaType *type, struct wg_format *format) { + UINT32 profile, level, codec_data_len; UINT64 frame_rate, frame_size; - UINT32 profile, level; + BYTE *codec_data;
memset(format, 0, sizeof(*format)); format->major_type = WG_MAJOR_TYPE_VIDEO_H264; @@ -832,6 +833,14 @@ static void mf_media_type_to_wg_format_video_h264(IMFMediaType *type, struct wg_
if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_MPEG2_LEVEL, &level))) format->u.video_h264.level = level; + + if (SUCCEEDED(IMFMediaType_GetAllocatedBlob(type, &MF_MT_MPEG_SEQUENCE_HEADER, &codec_data, &codec_data_len))) + { + assert(codec_data_len <= sizeof(format->u.video_h264.codec_data)); + format->u.video_h264.codec_data_len = codec_data_len; + memcpy(format->u.video_h264.codec_data, codec_data, codec_data_len); + CoTaskMemFree(codec_data); + } }
static void mf_media_type_to_wg_format_video_indeo(IMFMediaType *type, uint32_t version, struct wg_format *format) diff --git a/dlls/winegstreamer/unixlib.h b/dlls/winegstreamer/unixlib.h index 702bd7aa69b..15e0605fdde 100644 --- a/dlls/winegstreamer/unixlib.h +++ b/dlls/winegstreamer/unixlib.h @@ -148,6 +148,8 @@ struct wg_format uint32_t fps_n, fps_d; uint32_t profile; uint32_t level; + uint32_t codec_data_len; + unsigned char codec_data[64]; } video_h264; struct { diff --git a/dlls/winegstreamer/wg_format.c b/dlls/winegstreamer/wg_format.c index bd0ebf892c1..2353839bbc4 100644 --- a/dlls/winegstreamer/wg_format.c +++ b/dlls/winegstreamer/wg_format.c @@ -553,6 +553,7 @@ static GstCaps *wg_format_to_caps_audio_wma(const struct wg_format *format) static GstCaps *wg_format_to_caps_video_h264(const struct wg_format *format) { const char *profile, *level; + GstBuffer *buffer; GstCaps *caps;
if (!(caps = gst_caps_new_empty_simple("video/x-h264"))) @@ -609,6 +610,19 @@ static GstCaps *wg_format_to_caps_video_h264(const struct wg_format *format) if (level) gst_caps_set_simple(caps, "level", G_TYPE_STRING, level, NULL);
+ if (format->u.video_h264.codec_data_len) + { + if (!(buffer = gst_buffer_new_and_alloc(format->u.video_h264.codec_data_len))) + { + gst_caps_unref(caps); + return NULL; + } + + gst_buffer_fill(buffer, 0, format->u.video_h264.codec_data, format->u.video_h264.codec_data_len); + gst_caps_set_simple(caps, "codec_data", GST_TYPE_BUFFER, buffer, NULL); + gst_buffer_unref(buffer); + } + return caps; }
From: Ziqing Hui zhui@codeweavers.com
--- dlls/mf/tests/mf.c | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 4f4a282a9d8..3f1e288a967 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -81,6 +81,20 @@ HRESULT (WINAPI *pMFGetTopoNodeCurrentType)(IMFTopologyNode *node, DWORD stream, HRESULT (WINAPI *pMFCreateDXGIDeviceManager)(UINT *token, IMFDXGIDeviceManager **manager); BOOL has_video_processor;
+const static BYTE test_h264_sequence_header[] = +{ + 0x00, 0x00, 0x01, 0x67, 0x64, 0x00, 0x14, 0xac, 0xd9, 0x46, 0x36, 0xc0, + 0x5a, 0x83, 0x03, 0x03, 0x52, 0x80, 0x00, 0x00, 0x03, 0x00, 0x80, 0x00, + 0x00, 0x03, 0x01, 0x47, 0x8a, 0x14, 0xcb, 0x00, 0x00, 0x01, 0x68, 0xeb, + 0xec, 0xb2, 0x2c, +}; + +const static BYTE test_aac_codec_data[] = +{ + 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x12, 0x08, +}; + static BOOL is_vista(void) { return !pMFGetTopoNodeCurrentType; @@ -6756,7 +6770,7 @@ static void test_mpeg4_media_sink(void) { IMFMediaSink *sink = NULL, *sink2 = NULL, *sink_audio = NULL, *sink_video = NULL, *sink_empty = NULL; IMFByteStream *bytestream, *bytestream_audio, *bytestream_video, *bytestream_empty; - DWORD id, count, flags, width = 16, height = 16, fps = 10; + DWORD id, count, flags, width = 96, height = 96, fps = 1; IMFMediaType *audio_type, *video_type, *media_type; IMFMediaTypeHandler *type_handler = NULL; IMFPresentationClock *clock; @@ -6772,23 +6786,34 @@ static void test_mpeg4_media_sink(void)
hr = IMFMediaType_SetGUID(audio_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Audio); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - hr = IMFMediaType_SetGUID(audio_type, &MF_MT_SUBTYPE, &MFAudioFormat_PCM); + hr = IMFMediaType_SetGUID(audio_type, &MF_MT_SUBTYPE, &MFAudioFormat_AAC); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - hr = IMFMediaType_SetUINT32(audio_type, &MF_MT_AUDIO_NUM_CHANNELS, 2); + hr = IMFMediaType_SetUINT32(audio_type, &MF_MT_AUDIO_NUM_CHANNELS, 1); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - hr = IMFMediaType_SetUINT32(audio_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 48000); + hr = IMFMediaType_SetUINT32(audio_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, 16); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - hr = IMFMediaType_SetUINT32(audio_type, &MF_MT_AUDIO_BITS_PER_SAMPLE, 8); + hr = IMFMediaType_SetUINT32(audio_type, &MF_MT_AUDIO_SAMPLES_PER_SECOND, 44100); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFMediaType_SetUINT32(audio_type, &MF_MT_AUDIO_AVG_BYTES_PER_SECOND, 12000); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFMediaType_SetUINT32(audio_type, &MF_MT_AAC_AUDIO_PROFILE_LEVEL_INDICATION, 41); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFMediaType_SetUINT32(audio_type, &MF_MT_AAC_PAYLOAD_TYPE, 0); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFMediaType_SetBlob(audio_type, &MF_MT_USER_DATA, test_aac_codec_data, sizeof(test_aac_codec_data)); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaType_SetGUID(video_type, &MF_MT_MAJOR_TYPE, &MFMediaType_Video); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - hr = IMFMediaType_SetGUID(video_type, &MF_MT_SUBTYPE, &MFVideoFormat_RGB24); + hr = IMFMediaType_SetGUID(video_type, &MF_MT_SUBTYPE, &MFVideoFormat_H264); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IMFMediaType_SetUINT64(video_type, &MF_MT_FRAME_SIZE, ((UINT64)width << 32) | height); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IMFMediaType_SetUINT64(video_type, &MF_MT_FRAME_RATE, ((UINT64)fps << 32) | 1); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFMediaType_SetBlob(video_type, &MF_MT_MPEG_SEQUENCE_HEADER, + test_h264_sequence_header, sizeof(test_h264_sequence_header)); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = MFCreateTempFile(MF_ACCESSMODE_WRITE, MF_OPENMODE_DELETE_IF_EXIST, 0, &bytestream_audio); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
From: Ziqing Hui zhui@codeweavers.com
--- dlls/mf/tests/mf.c | 43 +++++++++----------- dlls/mfreadwrite/tests/mfplat.c | 13 +----- dlls/winegstreamer/main.c | 2 + dlls/winegstreamer/winegstreamer_classes.idl | 7 ++++ 4 files changed, 31 insertions(+), 34 deletions(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index 3f1e288a967..3e6b031f273 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -6825,58 +6825,39 @@ static void test_mpeg4_media_sink(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = MFCreateMPEG4MediaSink(NULL, NULL, NULL, NULL); - todo_wine ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr);
sink = (void *)0xdeadbeef; hr = MFCreateMPEG4MediaSink(NULL, NULL, NULL, &sink); - todo_wine ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); ok(sink == (void *)0xdeadbeef, "Unexpected pointer %p.\n", sink); sink = NULL;
hr = MFCreateMPEG4MediaSink(bytestream_empty, NULL, NULL, &sink_empty); - todo_wine ok(hr == S_OK || broken(hr == E_INVALIDARG), "Unexpected hr %#lx.\n", hr);
hr = MFCreateMPEG4MediaSink(bytestream_audio, NULL, audio_type, &sink_audio); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = MFCreateMPEG4MediaSink(bytestream_video, video_type, NULL, &sink_video); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = MFCreateMPEG4MediaSink(bytestream, video_type, audio_type, &sink); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
- if (!sink) - { - if (sink_video) - IMFMediaSink_Release(sink_video); - if (sink_audio) - IMFMediaSink_Release(sink_audio); - if (sink_empty) - IMFMediaSink_Release(sink_empty); - IMFByteStream_Release(bytestream); - IMFByteStream_Release(bytestream_empty); - IMFByteStream_Release(bytestream_video); - IMFByteStream_Release(bytestream_audio); - IMFMediaType_Release(video_type); - IMFMediaType_Release(audio_type); - return; - } - /* Test sink. */ + flags = 0xdeadbeef; hr = IMFMediaSink_GetCharacteristics(sink, &flags); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine ok(flags == MEDIASINK_RATELESS || broken(flags == (MEDIASINK_RATELESS | MEDIASINK_FIXED_STREAMS)), "Unexpected flags %#lx.\n", flags);
check_interface(sink, &IID_IMFMediaEventGenerator, TRUE); check_interface(sink, &IID_IMFFinalizableMediaSink, TRUE); check_interface(sink, &IID_IMFClockStateSink, TRUE); + todo_wine check_interface(sink, &IID_IMFGetService, TRUE);
/* Test sink stream count. */ @@ -6991,8 +6972,11 @@ static void test_mpeg4_media_sink(void) hr = MFCreatePresentationClock(&clock); ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); hr = IMFMediaSink_SetPresentationClock(sink, NULL); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine hr = IMFMediaSink_SetPresentationClock(sink, clock); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); IMFPresentationClock_Release(clock);
@@ -7011,13 +6995,18 @@ static void test_mpeg4_media_sink(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaTypeHandler_GetMajorType(type_handler, NULL); + todo_wine ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); hr = IMFMediaTypeHandler_GetMajorType(type_handler, &guid); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine ok(IsEqualGUID(&guid, &MFMediaType_Audio), "Unexpected major type.\n");
hr = IMFMediaTypeHandler_GetMediaTypeCount(type_handler, &count); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine ok(count == 1, "Unexpected count %lu.\n", count);
hr = IMFMediaTypeHandler_GetCurrentMediaType(type_handler, &media_type); @@ -7027,8 +7016,10 @@ static void test_mpeg4_media_sink(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaTypeHandler_SetCurrentMediaType(type_handler, NULL); + todo_wine ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); hr = IMFMediaTypeHandler_SetCurrentMediaType(type_handler, media_type); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
IMFMediaType_Release(media_type); @@ -7047,19 +7038,25 @@ static void test_mpeg4_media_sink(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
hr = IMFMediaTypeHandler_GetMajorType(type_handler, NULL); + todo_wine ok(hr == E_POINTER, "Unexpected hr %#lx.\n", hr); hr = IMFMediaTypeHandler_GetMajorType(type_handler, &guid); + todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr);
IMFStreamSink_Release(stream_sink);
hr = IMFMediaSink_AddStreamSink(sink, 0, audio_type, &stream_sink); + todo_wine ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr); hr = IMFMediaSink_GetStreamSinkByIndex(sink, 0, &stream_sink); + todo_wine ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr); hr = IMFMediaSink_GetStreamSinkById(sink, 0, &stream_sink); + todo_wine ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr); hr = IMFMediaSink_GetCharacteristics(sink, &flags); + todo_wine ok(hr == MF_E_SHUTDOWN, "Unexpected hr %#lx.\n", hr);
IMFMediaTypeHandler_Release(type_handler); diff --git a/dlls/mfreadwrite/tests/mfplat.c b/dlls/mfreadwrite/tests/mfplat.c index 3b54aa4ff4c..17e64fcc0bf 100644 --- a/dlls/mfreadwrite/tests/mfplat.c +++ b/dlls/mfreadwrite/tests/mfplat.c @@ -1468,44 +1468,35 @@ static void test_sink_writer_mp4(void) ok(!writer, "Unexpected pointer %p.\n", writer);
hr = MFCreateSinkWriterFromURL(NULL, stream, attr, &writer); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); if (hr == S_OK) IMFSinkWriter_Release(writer);
hr = MFCreateSinkWriterFromURL(tmp_file, NULL, NULL, &writer); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); if (hr == S_OK) IMFSinkWriter_Release(writer);
hr = MFCreateSinkWriterFromURL(tmp_file, NULL, attr, &writer); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); if (hr == S_OK) IMFSinkWriter_Release(writer);
hr = MFCreateSinkWriterFromURL(tmp_file, stream, NULL, &writer); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); if (hr == S_OK) IMFSinkWriter_Release(writer);
hr = MFCreateSinkWriterFromURL(tmp_file, stream, attr, &writer); - todo_wine ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); - if (hr != S_OK) - { - IMFByteStream_Release(stream); - IMFAttributes_Release(attr); - return; - }
/* Test GetServiceForStream. */ sink = (void *)0xdeadbeef; hr = IMFSinkWriter_GetServiceForStream(writer, MF_SINK_WRITER_MEDIASINK, &GUID_NULL, &IID_IMFMediaSink, (void **)&sink); + todo_wine ok(hr == MF_E_UNSUPPORTED_SERVICE, "Unexpected hr %#lx.\n", hr); + todo_wine ok(!sink, "Unexpected pointer %p.\n", sink);
DeleteFileW(tmp_file); diff --git a/dlls/winegstreamer/main.c b/dlls/winegstreamer/main.c index 9624c469314..c78d73537f7 100644 --- a/dlls/winegstreamer/main.c +++ b/dlls/winegstreamer/main.c @@ -649,6 +649,8 @@ HRESULT WINAPI DllGetClassObject(REFCLSID clsid, REFIID iid, void **out) factory = &color_convert_cf; else if (IsEqualGUID(clsid, &CLSID_MFMP3SinkClassFactory)) factory = &sink_class_factory_cf; + else if (IsEqualGUID(clsid, &CLSID_MFMPEG4SinkClassFactory)) + factory = &sink_class_factory_cf; else { FIXME("%s not implemented, returning CLASS_E_CLASSNOTAVAILABLE.\n", debugstr_guid(clsid)); diff --git a/dlls/winegstreamer/winegstreamer_classes.idl b/dlls/winegstreamer/winegstreamer_classes.idl index 2bc85e70b3a..3e9b19c90e9 100644 --- a/dlls/winegstreamer/winegstreamer_classes.idl +++ b/dlls/winegstreamer/winegstreamer_classes.idl @@ -117,3 +117,10 @@ coclass CColorConvertDMO {} uuid(11275a82-5e5a-47fd-a01c-3683c12fb196) ] coclass MFMP3SinkClassFactory {} + +[ + helpstring("MF MPEG4 Sink Class Factory"), + threading(both), + uuid(a22c4fc7-6e91-4e1d-89e9-53b2667b72ba) +] +coclass MFMPEG4SinkClassFactory {}
Rémi Bernon (@rbernon) commented about dlls/mf/tests/mf.c:
HRESULT (WINAPI *pMFCreateDXGIDeviceManager)(UINT *token, IMFDXGIDeviceManager **manager); BOOL has_video_processor;
+const static BYTE test_h264_sequence_header[] = +{
- 0x00, 0x00, 0x01, 0x67, 0x64, 0x00, 0x14, 0xac, 0xd9, 0x46, 0x36, 0xc0,
- 0x5a, 0x83, 0x03, 0x03, 0x52, 0x80, 0x00, 0x00, 0x03, 0x00, 0x80, 0x00,
- 0x00, 0x03, 0x01, 0x47, 0x8a, 0x14, 0xcb, 0x00, 0x00, 0x01, 0x68, 0xeb,
- 0xec, 0xb2, 0x2c,
+};
+const static BYTE test_aac_codec_data[] = +{
- 0x00, 0x00, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x12, 0x08,
+};
Fwiw I think it's important to have an easy way to reconstruct these.
For the AAC codec data, and this was the reason I added the AAC encoder tests, you can get it from the enumerated encoder media types. Maybe it should be shared between `transform.c` and `mf.c`, in `mf_test.h`?
For the H264 sequence header, I can't find where it is coming from. Is there a similar way to get it, which does not involve manual extraction from an H264 file? We can maybe have some basic H264 encoder tests if that would allow us to get the magic sequence out of it.
Zebediah Figura (@zfigura) commented about dlls/winegstreamer/mfplat.c:
if (SUCCEEDED(IMFMediaType_GetUINT32(type, &MF_MT_MPEG2_LEVEL, &level))) format->u.video_h264.level = level;
- if (SUCCEEDED(IMFMediaType_GetAllocatedBlob(type, &MF_MT_MPEG_SEQUENCE_HEADER, &codec_data, &codec_data_len)))
- {
assert(codec_data_len <= sizeof(format->u.video_h264.codec_data));
Should this really be an assert if it comes from user-supplied data? Would an FIXME/WARN/ERR be more appropriate?
On Thu Aug 24 12:12:53 2023 +0000, Rémi Bernon wrote:
Fwiw I think it's important to have an easy way to reconstruct these. For the AAC codec data, and this was the reason I added the AAC encoder tests, you can get it from the enumerated encoder media types. Maybe it should be shared between `transform.c` and `mf.c`, in `mf_test.h`? For the H264 sequence header, I can't find where it is coming from. Is there a similar way to get it, which does not involve manual extraction from an H264 file? We can maybe have some basic H264 encoder tests if that would allow us to get the magic sequence out of it.
It seems that we can extract the sequence header from output type of h264 encoder, see: https://learn.microsoft.com/en-us/windows/win32/medfound/h-264-video-encoder
Maybe it should be shared between `transform.c` and `mf.c`, in `mf_test.h`?
If I added the h264 encoder tests, which function should be shared between `transform.c` and `mf.c`? Or do you mean that the aac data array and the h264 data array should be shared?
On Thu Aug 24 22:52:05 2023 +0000, Zebediah Figura wrote:
Should this really be an assert if it comes from user-supplied data? Would an FIXME/WARN/ERR be more appropriate?
yep, that sounds reasonable.
On Fri Aug 25 03:15:23 2023 +0000, Ziqing Hui wrote:
It seems that we can extract the sequence header from output type of h264 encoder, see: https://learn.microsoft.com/en-us/windows/win32/medfound/h-264-video-encoder
Maybe it should be shared between `transform.c` and `mf.c`, in `mf_test.h`?
If I added the h264 encoder tests, which function should be shared between `transform.c` and `mf.c`? Or do you mean that the aac data array and the h264 data array should be shared?
Yeah I meant the data.