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) ...@@ -7818,7 +7818,7 @@ static void test_h264_decoder(void)
todo_wine todo_wine
ok(hr == MF_E_TRANSFORM_STREAM_CHANGE, "ProcessOutput returned %#lx\n", hr); 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); hr = IMFTransform_ProcessInput(transform, 0, sample, 0);
ok(hr == S_OK, "ProcessInput returned %#lx\n", hr); ok(hr == S_OK, "ProcessInput returned %#lx\n", hr);
...@@ -7826,16 +7826,14 @@ static void test_h264_decoder(void) ...@@ -7826,16 +7826,14 @@ static void test_h264_decoder(void)
ok(ret <= 1, "Release returned %lu\n", ret); ok(ret <= 1, "Release returned %lu\n", ret);
sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len); sample = next_h264_sample(&h264_encoded_data, &h264_encoded_data_len);
hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status); 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(hr == MF_E_TRANSFORM_STREAM_CHANGE, "ProcessOutput returned %#lx\n", hr);
} }
ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID); ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
ok(!!output.pSample, "got pSample %p\n", output.pSample); 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.dwStatus == MFT_OUTPUT_DATA_BUFFER_FORMAT_CHANGE, "got dwStatus %#lx\n", output.dwStatus);
ok(!output.pEvents, "got pEvents %p\n", output.pEvents); ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
todo_wine
ok(status == MFT_PROCESS_OUTPUT_STATUS_NEW_STREAMS, "got status %#lx\n", status); ok(status == MFT_PROCESS_OUTPUT_STATUS_NEW_STREAMS, "got status %#lx\n", status);
hr = IMFSample_GetTotalLength(output.pSample, &length); hr = IMFSample_GetTotalLength(output.pSample, &length);
ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr); ok(hr == S_OK, "GetTotalLength returned %#lx\n", hr);
...@@ -7858,17 +7856,16 @@ static void test_h264_decoder(void) ...@@ -7858,17 +7856,16 @@ static void test_h264_decoder(void)
memset(&output, 0, sizeof(output)); memset(&output, 0, sizeof(output));
output.pSample = create_sample(NULL, actual_width * actual_height * 2); output.pSample = create_sample(NULL, actual_width * actual_height * 2);
hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status); hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
todo_wine
ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr); ok(hr == S_OK, "ProcessOutput returned %#lx\n", hr);
ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID); ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
ok(!!output.pSample, "got pSample %p\n", output.pSample); ok(!!output.pSample, "got pSample %p\n", output.pSample);
ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus); ok(output.dwStatus == 0, "got dwStatus %#lx\n", output.dwStatus);
ok(!output.pEvents, "got pEvents %p\n", output.pEvents); ok(!output.pEvents, "got pEvents %p\n", output.pEvents);
ok(status == 0, "got status %#lx\n", status); ok(status == 0, "got status %#lx\n", status);
if (hr != S_OK) goto skip_i420_tests;
hr = IMFSample_GetSampleTime(output.pSample, &time); hr = IMFSample_GetSampleTime(output.pSample, &time);
ok(hr == S_OK, "GetSampleTime returned %#lx\n", hr); 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); ok(time - 333666 <= 2, "got time %I64d\n", time);
duration = 0xdeadbeef; duration = 0xdeadbeef;
...@@ -7904,7 +7901,6 @@ static void test_h264_decoder(void) ...@@ -7904,7 +7901,6 @@ static void test_h264_decoder(void)
check_sample(output.pSample, i420_frame_data, output_file); check_sample(output.pSample, i420_frame_data, output_file);
skip_i420_tests:
ret = IMFSample_Release(output.pSample); ret = IMFSample_Release(output.pSample);
ok(ret == 0, "Release returned %lu\n", ret); ok(ret == 0, "Release returned %lu\n", ret);
...@@ -7915,6 +7911,7 @@ skip_i420_tests: ...@@ -7915,6 +7911,7 @@ skip_i420_tests:
memset(&output, 0, sizeof(output)); memset(&output, 0, sizeof(output));
output.pSample = create_sample(NULL, actual_width * actual_height * 2); output.pSample = create_sample(NULL, actual_width * actual_height * 2);
hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status); 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(hr == MF_E_TRANSFORM_NEED_MORE_INPUT, "ProcessOutput returned %#lx\n", hr);
ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID); ok(output.dwStreamID == 0, "got dwStreamID %lu\n", output.dwStreamID);
ok(!!output.pSample, "got pSample %p\n", output.pSample); 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, ...@@ -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, struct wg_transform *wg_transform_create(const struct wg_format *input_format,
const struct wg_format *output_format); const struct wg_format *output_format);
void wg_transform_destroy(struct wg_transform *transform); 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); 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 ...@@ -467,7 +467,28 @@ static HRESULT WINAPI transform_SetOutputType(IMFTransform *iface, DWORD id, IMF
IMFMediaType_Release(decoder->output_type); IMFMediaType_Release(decoder->output_type);
IMFMediaType_AddRef((decoder->output_type = 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); IMFMediaType_Release(decoder->output_type);
decoder->output_type = NULL; decoder->output_type = NULL;
......
...@@ -348,6 +348,19 @@ HRESULT wg_transform_read_data(struct wg_transform *transform, struct wg_sample ...@@ -348,6 +348,19 @@ HRESULT wg_transform_read_data(struct wg_transform *transform, struct wg_sample
return params.result; 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) BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, void *reserved)
{ {
if (reason == DLL_PROCESS_ATTACH) if (reason == DLL_PROCESS_ATTACH)
......
...@@ -34,6 +34,7 @@ extern GstCaps *wg_format_to_caps(const struct wg_format *format) DECLSPEC_HIDDE ...@@ -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_create(void *args) DECLSPEC_HIDDEN;
extern NTSTATUS wg_transform_destroy(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_push_data(void *args) DECLSPEC_HIDDEN;
extern NTSTATUS wg_transform_read_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 ...@@ -263,6 +263,12 @@ struct wg_transform_read_data_params
HRESULT result; HRESULT result;
}; };
struct wg_transform_set_output_format_params
{
struct wg_transform *transform;
const struct wg_format *format;
};
enum unix_funcs enum unix_funcs
{ {
unix_wg_parser_create, unix_wg_parser_create,
...@@ -291,6 +297,7 @@ enum unix_funcs ...@@ -291,6 +297,7 @@ enum unix_funcs
unix_wg_transform_create, unix_wg_transform_create,
unix_wg_transform_destroy, unix_wg_transform_destroy,
unix_wg_transform_set_output_format,
unix_wg_transform_push_data, unix_wg_transform_push_data,
unix_wg_transform_read_data, unix_wg_transform_read_data,
......
...@@ -1625,6 +1625,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] = ...@@ -1625,6 +1625,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
X(wg_transform_create), X(wg_transform_create),
X(wg_transform_destroy), X(wg_transform_destroy),
X(wg_transform_set_output_format),
X(wg_transform_push_data), X(wg_transform_push_data),
X(wg_transform_read_data), X(wg_transform_read_data),
......
...@@ -51,6 +51,7 @@ struct wg_transform ...@@ -51,6 +51,7 @@ struct wg_transform
GstPad *my_src, *my_sink; GstPad *my_src, *my_sink;
GstPad *their_sink, *their_src; GstPad *their_sink, *their_src;
GstSegment segment; GstSegment segment;
GstQuery *drain_query;
guint input_max_length; guint input_max_length;
GstAtomicQueue *input_queue; GstAtomicQueue *input_queue;
...@@ -175,6 +176,31 @@ static gboolean transform_sink_query_cb(GstPad *pad, GstObject *parent, GstQuery ...@@ -175,6 +176,31 @@ static gboolean transform_sink_query_cb(GstPad *pad, GstObject *parent, GstQuery
g_object_unref(pool); g_object_unref(pool);
return true; 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: default:
GST_WARNING("Ignoring \"%s\" query.", gst_query_type_get_name(query->type)); GST_WARNING("Ignoring \"%s\" query.", gst_query_type_get_name(query->type));
break; break;
...@@ -236,6 +262,7 @@ NTSTATUS wg_transform_destroy(void *args) ...@@ -236,6 +262,7 @@ NTSTATUS wg_transform_destroy(void *args)
g_object_unref(transform->container); g_object_unref(transform->container);
g_object_unref(transform->my_sink); g_object_unref(transform->my_sink);
g_object_unref(transform->my_src); g_object_unref(transform->my_src);
gst_query_unref(transform->drain_query);
gst_caps_unref(transform->output_caps); gst_caps_unref(transform->output_caps);
gst_atomic_queue_unref(transform->output_queue); gst_atomic_queue_unref(transform->output_queue);
free(transform); free(transform);
...@@ -344,6 +371,8 @@ NTSTATUS wg_transform_create(void *args) ...@@ -344,6 +371,8 @@ NTSTATUS wg_transform_create(void *args)
goto out; goto out;
if (!(transform->output_queue = gst_atomic_queue_new(8))) if (!(transform->output_queue = gst_atomic_queue_new(8)))
goto out; goto out;
if (!(transform->drain_query = gst_query_new_drain()))
goto out;
if (!(transform->allocator = wg_allocator_create(transform_request_sample, transform))) if (!(transform->allocator = wg_allocator_create(transform_request_sample, transform)))
goto out; goto out;
transform->input_max_length = 1; transform->input_max_length = 1;
...@@ -505,6 +534,8 @@ out: ...@@ -505,6 +534,8 @@ out:
gst_caps_unref(src_caps); gst_caps_unref(src_caps);
if (transform->allocator) if (transform->allocator)
wg_allocator_destroy(transform->allocator); wg_allocator_destroy(transform->allocator);
if (transform->drain_query)
gst_query_unref(transform->drain_query);
if (transform->output_queue) if (transform->output_queue)
gst_atomic_queue_unref(transform->output_queue); gst_atomic_queue_unref(transform->output_queue);
if (transform->input_queue) if (transform->input_queue)
...@@ -519,6 +550,59 @@ out: ...@@ -519,6 +550,59 @@ out:
return status; 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) static void wg_sample_free_notify(void *arg)
{ {
struct wg_sample *sample = 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