Commit e15af490 authored by Rémi Bernon's avatar Rémi Bernon Committed by Alexandre Julliard
parent bc270a54
......@@ -7818,7 +7818,7 @@ static void test_h264_decoder(void)
todo_wine
ok(hr == MF_E_TRANSFORM_STREAM_CHANGE, "ProcessOutput returned %#lx\n", hr);
if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT)
while (hr == MF_E_TRANSFORM_NEED_MORE_INPUT)
{
hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
......@@ -7826,16 +7826,14 @@ static void test_h264_decoder(void)
ok(ret <= 1, "Release returned %lu\n", ret);
sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
todo_wine
todo_wine_if(hr == MF_E_TRANSFORM_NEED_MORE_INPUT)
ok(hr == MF_E_TRANSFORM_STREAM_CHANGE, "ProcessOutput returned %#lx\n", hr);
}
ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
ok(!!output.pSample, "got pSample %p\n", output.pSample);
todo_wine
ok(output.dwStatus == MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE, "got dwStatus %#lx\n", output.dwStatus);
ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
todo_wine
ok(status == MFT_PROCESS_OUTPUT_STATUS_NEW_STREAMS, "got status %#lx\n", status);
hr = IMFSample_GetTotalLength(output.pSample, &length);
ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
......@@ -7858,17 +7856,16 @@ static void test_h264_decoder(void)
memset(&output, 0, sizeof(output));
output.pSample = create_sample(NULL, actual_width * actual_height * 2);
hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
todo_wine
ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
ok(!!output.pSample, "got pSample %p\n", output.pSample);
ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
ok(status == 0, "got status %#lx\n", status);
if (hr != S_OK) goto skip_i420_tests;
hr = IMFSample_GetSampleTime(output.pSample, &time);
ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr);
todo_wine_if(time == 1334666) /* when VA-API plugin is used */
ok(time - 333666 <= 2, "got time %I64d\n", time);
duration = 0xdeadbeef;
......@@ -7904,7 +7901,6 @@ static void test_h264_decoder(void)
check_sample(output.pSample, i420_frame_data, output_file);
skip_i420_tests:
ret = IMFSample_Release(output.pSample);
ok(ret == 0, "Release returned %lu\n", ret);
......@@ -7915,6 +7911,7 @@ skip_i420_tests:
memset(&output, 0, sizeof(output));
output.pSample = create_sample(NULL, actual_width * actual_height * 2);
hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
todo_wine_if(hr == S_OK) /* when VA-API plugin is used */
ok(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
ok(!!output.pSample, "got pSample %p\n", output.pSample);
......
......@@ -102,6 +102,7 @@ void wg_parser_stream_seek(struct wg_parser_stream *stream, double rate,
struct wg_transform *wg_transform_create(const struct wg_format *input_format,
const struct wg_format *output_format);
void wg_transform_destroy(struct wg_transform *transform);
bool wg_transform_set_output_format(struct wg_transform *transform, struct wg_format *format);
unsigned int wg_format_get_max_size(const struct wg_format *format);
......
......@@ -467,7 +467,28 @@ static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMF
IMFMediaType_Release(decoder->output_type);
IMFMediaType_AddRef((decoder->output_type = type));
if (FAILED(hr = try_create_wg_transform(decoder)))
if (decoder->wg_transform)
{
struct wg_format output_format;
mf_media_type_to_wg_format(decoder->output_type, &output_format);
/* Don't force any specific size, H264 streams already have the metadata for it
* and will generate a MF_E_TRANSFORM_STREAM_CHANGE result later.
*/
output_format.u.video.width = 0;
output_format.u.video.height = 0;
output_format.u.video.fps_d = 0;
output_format.u.video.fps_n = 0;
if (output_format.major_type == WG_MAJOR_TYPE_UNKNOWN
|| !wg_transform_set_output_format(decoder->wg_transform, &output_format))
{
IMFMediaType_Release(decoder->output_type);
decoder->output_type = NULL;
return MF_E_INVALIDMEDIATYPE;
}
}
else if (FAILED(hr = try_create_wg_transform(decoder)))
{
IMFMediaType_Release(decoder->output_type);
decoder->output_type = NULL;
......
......@@ -348,6 +348,19 @@ HRESULT wg_transform_read_data(struct wg_transform *transform, struct wg_sample
return params.result;
}
bool wg_transform_set_output_format(struct wg_transform *transform, struct wg_format *format)
{
struct wg_transform_set_output_format_params params =
{
.transform = transform,
.format = format,
};
TRACE("transform %p, format %p.\n", transform, format);
return !__wine_unix_call(unix_handle, unix_wg_transform_set_output_format, &params);
}
BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, void *reserved)
{
if (reason == DLL_PROCESS_ATTACH)
......
......@@ -34,6 +34,7 @@ extern GstCaps *wg_format_to_caps(const struct wg_format *format) DECLSPEC_HIDDE
extern NTSTATUS wg_transform_create(void *args) DECLSPEC_HIDDEN;
extern NTSTATUS wg_transform_destroy(void *args) DECLSPEC_HIDDEN;
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;
......
......@@ -263,6 +263,12 @@ struct wg_transform_read_data_params
HRESULT result;
};
struct wg_transform_set_output_format_params
{
struct wg_transform *transform;
const struct wg_format *format;
};
enum unix_funcs
{
unix_wg_parser_create,
......@@ -291,6 +297,7 @@ enum unix_funcs
unix_wg_transform_create,
unix_wg_transform_destroy,
unix_wg_transform_set_output_format,
unix_wg_transform_push_data,
unix_wg_transform_read_data,
......
......@@ -1625,6 +1625,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
X(wg_transform_create),
X(wg_transform_destroy),
X(wg_transform_set_output_format),
X(wg_transform_push_data),
X(wg_transform_read_data),
......
......@@ -51,6 +51,7 @@ struct wg_transform
GstPad *my_src, *my_sink;
GstPad *their_sink, *their_src;
GstSegment segment;
GstQuery *drain_query;
guint input_max_length;
GstAtomicQueue *input_queue;
......@@ -175,6 +176,31 @@ static gboolean transform_sink_query_cb(GstPad *pad, GstObject *parent, GstQuery
g_object_unref(pool);
return true;
}
case GST_QUERY_CAPS:
{
GstCaps *caps, *filter, *temp;
gchar *str;
gst_query_parse_caps(query, &filter);
caps = gst_caps_ref(transform->output_caps);
if (filter)
{
temp = gst_caps_intersect(caps, filter);
gst_caps_unref(caps);
caps = temp;
}
str = gst_caps_to_string(caps);
GST_INFO("Returning caps %s", str);
g_free(str);
gst_query_set_caps_result(query, caps);
gst_caps_unref(caps);
return true;
}
default:
GST_WARNING("Ignoring \"%s\" query.", gst_query_type_get_name(query->type));
break;
......@@ -236,6 +262,7 @@ NTSTATUS wg_transform_destroy(void *args)
g_object_unref(transform->container);
g_object_unref(transform->my_sink);
g_object_unref(transform->my_src);
gst_query_unref(transform->drain_query);
gst_caps_unref(transform->output_caps);
gst_atomic_queue_unref(transform->output_queue);
free(transform);
......@@ -344,6 +371,8 @@ NTSTATUS wg_transform_create(void *args)
goto out;
if (!(transform->output_queue = gst_atomic_queue_new(8)))
goto out;
if (!(transform->drain_query = gst_query_new_drain()))
goto out;
if (!(transform->allocator = wg_allocator_create(transform_request_sample, transform)))
goto out;
transform->input_max_length = 1;
......@@ -505,6 +534,8 @@ out:
gst_caps_unref(src_caps);
if (transform->allocator)
wg_allocator_destroy(transform->allocator);
if (transform->drain_query)
gst_query_unref(transform->drain_query);
if (transform->output_queue)
gst_atomic_queue_unref(transform->output_queue);
if (transform->input_queue)
......@@ -519,6 +550,59 @@ out:
return status;
}
NTSTATUS wg_transform_set_output_format(void *args)
{
struct wg_transform_set_output_format_params *params = args;
struct wg_transform *transform = params->transform;
const struct wg_format *format = params->format;
GstSample *sample;
GstCaps *caps;
gchar *str;
if (!(caps = wg_format_to_caps(format)))
{
GST_ERROR("Failed to convert format %p to caps.", format);
return STATUS_UNSUCCESSFUL;
}
if (gst_caps_is_always_compatible(transform->output_caps, caps))
{
gst_caps_unref(caps);
return STATUS_SUCCESS;
}
if (!gst_pad_peer_query(transform->my_src, transform->drain_query))
{
GST_ERROR("Failed to drain transform %p.", transform);
return STATUS_UNSUCCESSFUL;
}
gst_caps_unref(transform->output_caps);
transform->output_caps = caps;
if (!gst_pad_push_event(transform->my_sink, gst_event_new_reconfigure()))
{
GST_ERROR("Failed to reconfigure transform %p.", transform);
return STATUS_UNSUCCESSFUL;
}
str = gst_caps_to_string(caps);
GST_INFO("Configured new caps %s.", str);
g_free(str);
/* Ideally and to be fully compatible with native transform, the queued
* output buffers will need to be converted to the new output format and
* kept queued.
*/
if (transform->output_sample)
gst_sample_unref(transform->output_sample);
while ((sample = gst_atomic_queue_pop(transform->output_queue)))
gst_sample_unref(sample);
transform->output_sample = NULL;
return STATUS_SUCCESS;
}
static void wg_sample_free_notify(void *arg)
{
struct wg_sample *sample = arg;
......
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