From: Conor McCarthy cmccarthy@codeweavers.com
H.264 uses a 16-pixel alignment, and the stream sink media type should have the aligned height after the session has started. --- dlls/mf/session.c | 67 +++++++++ dlls/mf/tests/mf.c | 225 +++++++++++++++++++++++++++++++ dlls/mf/tests/resource.rc | 11 ++ dlls/mf/tests/test-unaligned.mp4 | Bin 0 -> 3988 bytes include/wine/test.h | 2 +- 5 files changed, 304 insertions(+), 1 deletion(-) create mode 100644 dlls/mf/tests/test-unaligned.mp4
diff --git a/dlls/mf/session.c b/dlls/mf/session.c index 87af5b95eab..a6810e20e2d 100644 --- a/dlls/mf/session.c +++ b/dlls/mf/session.c @@ -1212,6 +1212,7 @@ static void session_set_paused(struct media_session *session, HRESULT status) or an attempt to pause from invalid initial state. To finalize failed transition in the former case, state is still forced to PAUSED, otherwise previous state is retained. */ session->state = SESSION_STATE_PAUSED; + FIXME("\n"); if (SUCCEEDED(status)) session_set_caps(session, session->caps & ~MFSESSIONCAP_PAUSE); session_command_complete_with_event(session, MESessionPaused, status, NULL); @@ -1220,6 +1221,7 @@ static void session_set_paused(struct media_session *session, HRESULT status) static void session_set_closed(struct media_session *session, HRESULT status) { session->state = SESSION_STATE_CLOSED; + FIXME("\n"); if (SUCCEEDED(status)) session_set_caps(session, session->caps & ~(MFSESSIONCAP_START | MFSESSIONCAP_SEEK)); session_command_complete_with_event(session, MESessionClosed, status, NULL); @@ -2056,6 +2058,7 @@ static HRESULT session_set_current_topology(struct media_session *session, IMFTo } }
+ FIXME("\n"); session_set_caps(session, caps);
return S_OK; @@ -3138,6 +3141,66 @@ static BOOL session_set_node_object_state(struct media_session *session, IUnknow return changed; }
+static void session_update_sink_input_types(struct media_session *session) +{ + struct topo_node *node, *up_node; + IMFMediaTypeHandler *handler; + IMFMediaType *output_type; + DWORD output; + HRESULT hr; + TRACE("\n"); + + LIST_FOR_EACH_ENTRY(node, &session->presentation.nodes, struct topo_node, entry) + { + if (node->type != MF_TOPOLOGY_OUTPUT_NODE) + continue; + + if (!(up_node = session_get_topo_node_input(session, node, 0, &output))) + WARN("Failed to get node %p/0 input\n", node); + if (up_node->type == MF_TOPOLOGY_TRANSFORM_NODE) + { + if (FAILED(hr = IMFTransform_GetOutputCurrentType(up_node->object.transform, output, &output_type))) + { + WARN("Failed to get output type, hr %#lx.\n", hr); + continue; + } + } + else if (up_node->type == MF_TOPOLOGY_SOURCESTREAM_NODE) + { + IMFStreamDescriptor *sd; + if (FAILED(hr = IMFMediaStream_GetStreamDescriptor(up_node->object.source_stream, &sd))) + continue; + if (SUCCEEDED(hr = IMFStreamDescriptor_GetMediaTypeHandler(sd, &handler))) + { + hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &output_type); + IMFMediaTypeHandler_Release(handler); + } + IMFStreamDescriptor_Release(sd); + if (FAILED(hr)) + { + WARN("Failed to get output type, hr %#lx.\n", hr); + continue; + } + } + else + { + FIXME("Unhandled node type %d.\n", up_node->type); + continue; + } + + if (FAILED(hr = IMFStreamSink_GetMediaTypeHandler(node->object.sink_stream, &handler))) + { + WARN("Failed to get type handler, hr %#lx.\n", hr); + IMFMediaType_Release(output_type); + continue; + } + if (FAILED(hr = IMFMediaTypeHandler_SetCurrentMediaType(handler, output_type))) + WARN("Failed to set type, hr %#lx.\n", hr); + IMFMediaTypeHandler_Release(handler); + IMFMediaType_Release(output_type); + } +} + static void session_set_source_object_state(struct media_session *session, IUnknown *object, MediaEventType event_type) { @@ -3202,6 +3265,7 @@ static void session_set_source_object_state(struct media_session *session, IUnkn }
session_set_presentation_clock(session); + session_update_sink_input_types(session);
if ((session->presentation.flags & SESSION_FLAG_NEEDS_PREROLL) && session_is_output_nodes_state(session, OBJ_STATE_STOPPED)) { @@ -3295,6 +3359,7 @@ static void session_set_source_object_state(struct media_session *session, IUnkn break;
session_flush_nodes(session); + FIXME("\n"); session_set_caps(session, session->caps & ~MFSESSIONCAP_PAUSE); session_set_stopped(session, MESessionStopped, S_OK); break; @@ -3303,6 +3368,7 @@ static void session_set_source_object_state(struct media_session *session, IUnkn break;
session_flush_nodes(session); + FIXME("\n"); session_set_caps(session, session->caps & ~MFSESSIONCAP_PAUSE); session_finalize_sinks(session); break; @@ -4194,6 +4260,7 @@ static void session_sink_stream_marker(struct media_session *session, IMFStreamS session_nodes_is_mask_set(session, MF_TOPOLOGY_OUTPUT_NODE, TOPO_NODE_END_OF_STREAM)) { session_set_topo_status(session, S_OK, MF_TOPOSTATUS_ENDED); + FIXME("\n"); session_set_caps(session, session->caps & ~MFSESSIONCAP_PAUSE);
IMFPresentationClock_GetTime(session->clock, &session->presentation.clock_stop_time); diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c index a02f2859f91..8ad1ed2aa22 100644 --- a/dlls/mf/tests/mf.c +++ b/dlls/mf/tests/mf.c @@ -3039,6 +3039,12 @@ static HRESULT WINAPI test_grabber_callback_OnProcessSample(IMFSampleGrabberSink HRESULT hr; DWORD res;
+ if (grabber->ready_event && !grabber->done_event) + { + SetEvent(grabber->ready_event); + return S_OK; + } + if (!grabber->ready_event) return E_NOTIMPL;
@@ -3189,6 +3195,7 @@ static ULONG WINAPI test_clock_sink_Release(IMFClockStateSink *iface)
static HRESULT WINAPI test_clock_sink_OnClockStart(IMFClockStateSink *iface, MFTIME system_time, LONGLONG offset) { + trace("test_clock_sink_OnClockStart\n"); return E_NOTIMPL; }
@@ -3204,6 +3211,7 @@ static HRESULT WINAPI test_clock_sink_OnClockPause(IMFClockStateSink *iface, MFT
static HRESULT WINAPI test_clock_sink_OnClockRestart(IMFClockStateSink *iface, MFTIME system_time) { + trace("test_clock_sink_OnClockRestart\n"); return E_NOTIMPL; }
@@ -8040,6 +8048,222 @@ static void test_media_session_seek(void) ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); }
+static IMFTransform *topology_get_transform(IMFTopology *topology) +{ + IMFTransform *transform; + IMFTopologyNode *node; + MF_TOPOLOGY_TYPE type; + HRESULT hr; + WORD count; + UINT i; + + hr = IMFTopology_GetNodeCount(topology, &count); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + for (i = 0; i < count; ++i) + { + hr = IMFTopology_GetNode(topology, i, &node); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFTopologyNode_GetNodeType(node, &type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + if (type == MF_TOPOLOGY_TRANSFORM_NODE) + { + hr = IMFTopologyNode_GetObject(node, (IUnknown **)&transform); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + IMFTopologyNode_Release(node); + return transform; + } + IMFTopologyNode_Release(node); + } + + return NULL; +} + +#define check_transform_output_type(a, b, c) check_transform_output_type_(__LINE__, a, b, c) +static void check_transform_output_type_(int line, IMFTransform *transform, UINT expected_w, UINT expected_h) +{ + IMFMediaType *output_type; + UINT64 frame_size; + HRESULT hr; + + if (!transform) + { + skip("Wine does not currently use a transform.\n"); + return; + } + hr = IMFTransform_GetOutputCurrentType(transform, 0, &output_type); + ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFMediaType_GetUINT64(output_type, &MF_MT_FRAME_SIZE, &frame_size); + ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine_if(expected_h > 72) + ok_(__FILE__, line)(frame_size == (((UINT64)expected_w << 32) | expected_h), "Unexpected frame size %#llx\n", frame_size); + IMFMediaType_Release(output_type); +} + +#define check_type_handler_output_type(a, b, c) check_type_handler_output_type_(__LINE__, a, b, c) +static void check_type_handler_output_type_(int line, IMFMediaTypeHandler *handler, UINT expected_w, UINT expected_h) +{ + IMFMediaType *output_type; + UINT64 frame_size; + HRESULT hr; + + hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &output_type); + ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFMediaType_GetUINT64(output_type, &MF_MT_FRAME_SIZE, &frame_size); + ok_(__FILE__, line)(hr == S_OK, "Unexpected hr %#lx.\n", hr); + todo_wine_if(expected_h > 72) + ok_(__FILE__, line)(frame_size == (((UINT64)expected_w << 32) | expected_h), "Unexpected frame size %#llx\n", frame_size); + IMFMediaType_Release(output_type); +} + +static void test_h264_output_alignment(void) +{ + media_type_desc video_nv12_desc = + { + ATTR_GUID(MF_MT_MAJOR_TYPE, MFMediaType_Video), + ATTR_GUID(MF_MT_SUBTYPE, MFVideoFormat_NV12), + }; + struct test_grabber_callback *grabber_callback; + IMFTopology *topology, *resolved_topology; + struct test_callback *test_callback; + IMFMediaTypeHandler *handler; + IMFActivate *sink_activate; + IMFTopoLoader *topo_loader; + IMFStreamSink *stream_sink; + IMFAsyncCallback *callback; + IMFMediaType *output_type; + MediaEventType event_type; + IMFMediaSession *session; + IMFMediaSink *media_sink; + IMFTransform *transform; + IMFMediaSource *source; + PROPVARIANT propvar; + UINT64 frame_size; + HANDLE objects[2]; + UINT32 status; + HRESULT hr; + DWORD ret; + + hr = MFStartup(MF_VERSION, MFSTARTUP_FULL); + ok(hr == S_OK, "Failed to start up, hr %#lx.\n", hr); + + if (!(source = create_media_source(L"test-unaligned.mp4", L"video/mp4"))) + { + todo_wine /* Gitlab CI Debian runner */ + win_skip("MP4 media source is not supported, skipping tests.\n"); + MFShutdown(); + return; + } + + grabber_callback = impl_from_IMFSampleGrabberSinkCallback(create_test_grabber_callback()); + grabber_callback->ready_event = CreateEventW(NULL, FALSE, FALSE, NULL); + ok(!!grabber_callback->ready_event, "CreateEventW failed, error %lu\n", GetLastError()); + + hr = MFCreateMediaType(&output_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + init_media_type(output_type, video_nv12_desc, -1); + hr = MFCreateSampleGrabberSinkActivate(output_type, &grabber_callback->IMFSampleGrabberSinkCallback_iface, &sink_activate); + ok(hr == S_OK, "Failed to create grabber sink, hr %#lx.\n", hr); + IMFMediaType_Release(output_type); + + IMFActivate_ActivateObject(sink_activate, &IID_IMFMediaSink, (void **)&media_sink); + hr = IMFMediaSink_GetStreamSinkByIndex(media_sink, 0, &stream_sink); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + IMFActivate_Release(sink_activate); + topology = create_test_topology_unk(source, (IUnknown *)stream_sink, NULL, NULL); + hr = MFCreateTopoLoader(&topo_loader); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFTopoLoader_Load(topo_loader, topology, &resolved_topology, NULL); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + IMFTopology_Release(topology); + IMFTopoLoader_Release(topo_loader); + + hr = IMFStreamSink_GetMediaTypeHandler(stream_sink, &handler); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFMediaTypeHandler_GetCurrentMediaType(handler, &output_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFMediaType_GetUINT64(output_type, &MF_MT_FRAME_SIZE, &frame_size); + ok(hr == MF_E_ATTRIBUTENOTFOUND, "Unexpected hr %#lx.\n", hr); + IMFMediaType_Release(output_type); + + hr = MFCreateMediaSession(NULL, &session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFMediaSession_SetTopology(session, 0, resolved_topology); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + transform = topology_get_transform(resolved_topology); + IMFTopology_Release(resolved_topology); + + callback = create_test_callback(TRUE); + hr = wait_media_event(session, callback, MESessionTopologySet, 1000, &propvar); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + test_callback = impl_from_IMFAsyncCallback(callback); + hr = wait_media_event(session, callback, MESessionTopologyStatus, 1000, &propvar); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFMediaEvent_GetUINT32(test_callback->media_event, &MF_EVENT_TOPOLOGY_STATUS, &status); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(status == MF_TOPOSTATUS_READY, "Unexpected status %d.\n", status); + + check_transform_output_type(transform, 64, 72); + check_type_handler_output_type(handler, 64, 72); + + propvar.vt = VT_EMPTY; + hr = IMFMediaSession_Start(session, &GUID_NULL, &propvar); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = wait_media_event(session, callback, MESessionTopologyStatus, 1000, &propvar); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFMediaEvent_GetUINT32(test_callback->media_event, &MF_EVENT_TOPOLOGY_STATUS, &status); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ok(status == MF_TOPOSTATUS_STARTED_SOURCE, "Unexpected status %d.\n", status); + check_transform_output_type(transform, 64, 72); + check_type_handler_output_type(handler, 64, 72); + + /* frame size change occurs before MESessionStarted and delivery of the first sample to the sink */ + objects[0] = test_callback->event; + objects[1] = grabber_callback->ready_event; + do + { + hr = IMFMediaEventGenerator_BeginGetEvent((IMFMediaEventGenerator *)session, + &test_callback->IMFAsyncCallback_iface, (IUnknown *)session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + ret = WaitForMultipleObjects(2, objects, FALSE, 5000); + ok(ret == WAIT_OBJECT_0 || ret == WAIT_OBJECT_0 + 1, "WaitForMultipleObjects returned %lu\n", ret); + if (ret == WAIT_OBJECT_0) + { + hr = IMFMediaEvent_GetType(test_callback->media_event, &event_type); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + } + } while (ret == WAIT_OBJECT_0 && event_type != MESessionStarted); + + check_transform_output_type(transform, 64, 80); + check_type_handler_output_type(handler, 64, 80); + + hr = IMFMediaSession_Stop(session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFMediaSession_Close(session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = wait_media_event(session, callback, MESessionClosed, 1000, &propvar); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + hr = IMFMediaSource_Shutdown(source); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + hr = IMFMediaSession_Shutdown(session); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); + + IMFMediaTypeHandler_Release(handler); + if (transform) + IMFTransform_Release(transform); + IMFAsyncCallback_Release(callback); + IMFMediaSession_Release(session); + IMFStreamSink_Release(stream_sink); + IMFMediaSink_Release(media_sink); + IMFSampleGrabberSinkCallback_Release(&grabber_callback->IMFSampleGrabberSinkCallback_iface); + IMFMediaSource_Release(source); + + hr = MFShutdown(); + ok(hr == S_OK, "Unexpected hr %#lx.\n", hr); +} + START_TEST(mf) { init_functions(); @@ -8078,4 +8302,5 @@ START_TEST(mf) test_media_session_source_shutdown(); test_media_session_thinning(); test_media_session_seek(); + test_h264_output_alignment(); } diff --git a/dlls/mf/tests/resource.rc b/dlls/mf/tests/resource.rc index dff5719dd3b..9b31188a187 100644 --- a/dlls/mf/tests/resource.rc +++ b/dlls/mf/tests/resource.rc @@ -185,3 +185,14 @@ rgb24frame.bmp RCDATA rgb24frame.bmp */ /* @makedep: test.mp4 */ test.mp4 RCDATA test.mp4 + +/* Generated with: + * gst-launch-1.0 videotestsrc num-buffers=60 pattern=smpte100 ! \ + * video/x-raw,format=I420,width=72,height=64,framerate=30000/1001 ! \ + * videoflip method=clockwise ! videoconvert ! \ + * x264enc ! mp4mux ! filesink location=dlls/mf/tests/test-unaligned.mp4 + */ +/* @makedep: test-unaligned.mp4 */ +test-unaligned.mp4 RCDATA test-unaligned.mp4 + +test.wmv RCDATA test.wmv diff --git a/dlls/mf/tests/test-unaligned.mp4 b/dlls/mf/tests/test-unaligned.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..5920da40daaf55dc69a5a02577891c70906fed94 GIT binary patch literal 3988 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 V7(l&F1_lOOsKKVB7|a1O7yw{rbdCT3
literal 0 HcmV?d00001
diff --git a/include/wine/test.h b/include/wine/test.h index 7a437fd8c78..0af4b0e4a08 100644 --- a/include/wine/test.h +++ b/include/wine/test.h @@ -218,7 +218,7 @@ static void winetest_print_context( const char *msgtype ) struct winetest_thread_data *data = winetest_get_thread_data(); unsigned int i;
- winetest_print_location( "%s", msgtype ); + winetest_print_location( "%04lx:%s", GetCurrentThreadId(), msgtype ); for (i = 0; i < data->context_count; ++i) winetest_printf( "%s: ", data->context[i] ); }