Commit 16347299 authored by Paul Gofman's avatar Paul Gofman Committed by Alexandre Julliard

winegstreamer: Implement MFT_MESSAGE_COMMAND_DRAIN for the H264 decoder.

parent db2640d0
......@@ -3879,10 +3879,10 @@ static void test_h264_decoder(void)
hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
hr = IMFTransform_ProcessMessage(transform, MFT_MESSAGE_COMMAND_DRAIN, 0);
ok(hr == S_OK, "ProcessMessage returned %#lx\n", hr);
}
todo_wine
ok(i == 2, "got %lu iterations\n", i);
todo_wine
ok(h264_encoded_data_len == 2425, "got h264_encoded_data_len %lu\n", h264_encoded_data_len);
ok(hr == MF_E_TRANSFORM_STREAM_CHANGE, "ProcessOutput returned %#lx\n", hr);
ok(output_status == MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE, "got output[0].dwStatus %#lx\n", output_status);
......@@ -3981,6 +3981,7 @@ static void test_h264_decoder(void)
ok(ref == 1, "Release returned %ld\n", ref);
ret = check_mf_sample_collection(output_samples, &expect_output_sample_i420, L"i420frame.bmp");
todo_wine /* wg_transform_set_output_format() should convert already processed samples instead of dropping */
ok(ret == 0, "got %lu%% diff\n", ret);
IMFCollection_Release(output_samples);
......
......@@ -106,6 +106,7 @@ struct wg_transform *wg_transform_create(const struct wg_format *input_format,
void wg_transform_destroy(struct wg_transform *transform);
bool wg_transform_set_output_format(struct wg_transform *transform, struct wg_format *format);
bool wg_transform_get_status(struct wg_transform *transform, bool *accepts_input);
HRESULT wg_transform_drain(struct wg_transform *transform);
unsigned int wg_format_get_max_size(const struct wg_format *format);
......
......@@ -614,8 +614,9 @@ static HRESULT WINAPI transform_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_
TRACE("iface %p, message %#x, param %Ix.\n", iface, message, param);
if (message == MFT_MESSAGE_SET_D3D_MANAGER)
switch (message)
{
case MFT_MESSAGE_SET_D3D_MANAGER:
if (FAILED(hr = IMFVideoSampleAllocatorEx_SetDirectXManager(decoder->allocator, (IUnknown *)param)))
return hr;
......@@ -625,10 +626,14 @@ static HRESULT WINAPI transform_ProcessMessage(IMFTransform *iface, MFT_MESSAGE_
else
decoder->output_info.dwFlags &= ~MFT_OUTPUT_STREAM_PROVIDES_SAMPLES;
return S_OK;
}
FIXME("Ignoring message %#x.\n", message);
return S_OK;
case MFT_MESSAGE_COMMAND_DRAIN:
return wg_transform_drain(decoder->wg_transform);
default:
FIXME("Ignoring message %#x.\n", message);
return S_OK;
}
}
static HRESULT WINAPI transform_ProcessInput(IMFTransform *iface, DWORD id, IMFSample *sample, DWORD flags)
......
......@@ -426,6 +426,21 @@ bool wg_transform_set_output_format(struct wg_transform *transform, struct wg_fo
return !WINE_UNIX_CALL(unix_wg_transform_set_output_format, &params);
}
HRESULT wg_transform_drain(struct wg_transform *transform)
{
NTSTATUS status;
TRACE("transform %p.\n", transform);
if ((status = WINE_UNIX_CALL(unix_wg_transform_drain, transform)))
{
WARN("wg_transform_drain returned status %#lx\n", status);
return HRESULT_FROM_NT(status);
}
return S_OK;
}
#define ALIGN(n, alignment) (((n) + (alignment) - 1) & ~((alignment) - 1))
unsigned int wg_format_get_stride(const struct wg_format *format)
......
......@@ -53,6 +53,7 @@ extern NTSTATUS wg_transform_set_output_format(void *args) DECLSPEC_HIDDEN;
extern NTSTATUS wg_transform_push_data(void *args) DECLSPEC_HIDDEN;
extern NTSTATUS wg_transform_read_data(void *args) DECLSPEC_HIDDEN;
extern NTSTATUS wg_transform_get_status(void *args) DECLSPEC_HIDDEN;
extern NTSTATUS wg_transform_drain(void *args) DECLSPEC_HIDDEN;
/* wg_allocator.c */
......
......@@ -376,6 +376,7 @@ enum unix_funcs
unix_wg_transform_push_data,
unix_wg_transform_read_data,
unix_wg_transform_get_status,
unix_wg_transform_drain,
};
#endif /* __WINE_WINEGSTREAMER_UNIXLIB_H */
......@@ -1939,4 +1939,5 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
X(wg_transform_push_data),
X(wg_transform_read_data),
X(wg_transform_get_status),
X(wg_transform_drain),
};
......@@ -869,3 +869,38 @@ NTSTATUS wg_transform_get_status(void *args)
params->accepts_input = gst_atomic_queue_length(transform->input_queue) < transform->input_max_length;
return STATUS_SUCCESS;
}
NTSTATUS wg_transform_drain(void *args)
{
struct wg_transform *transform = args;
GstBuffer *input_buffer;
GstFlowReturn ret;
GstEvent *event;
GST_LOG("transform %p", transform);
while ((input_buffer = gst_atomic_queue_pop(transform->input_queue)))
{
if ((ret = gst_pad_push(transform->my_src, input_buffer)))
GST_WARNING("Failed to push transform input, error %d", ret);
}
if (!(event = gst_event_new_segment_done(GST_FORMAT_TIME, -1))
|| !gst_pad_push_event(transform->my_src, event))
goto error;
if (!(event = gst_event_new_eos())
|| !gst_pad_push_event(transform->my_src, event))
goto error;
if (!(event = gst_event_new_stream_start("stream"))
|| !gst_pad_push_event(transform->my_src, event))
goto error;
if (!(event = gst_event_new_segment(&transform->segment))
|| !gst_pad_push_event(transform->my_src, event))
goto error;
return STATUS_SUCCESS;
error:
GST_ERROR("Failed to drain transform %p.", transform);
return STATUS_UNSUCCESSFUL;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment