videoflip: handle tag list scopes

STREAM taglist can now overrides the orientation from the GLOBAL
taglist, but not the other way around.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/4377>
This commit is contained in:
Guillaume Desmottes 2023-04-13 14:06:19 +02:00
parent 96afec6253
commit c0fa04fcaf
3 changed files with 96 additions and 3 deletions

View file

@ -1787,11 +1787,24 @@ gst_video_flip_sink_event (GstBaseTransform * trans, GstEvent * event)
gst_event_parse_tag (event, &taglist);
if (gst_video_orientation_from_tag (taglist, &method)) {
gst_video_flip_set_method (vf, method, TRUE);
if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_STREAM) {
vf->got_orientation_stream_tag = TRUE;
}
if (gst_tag_list_get_scope (taglist) == GST_TAG_SCOPE_GLOBAL
&& vf->got_orientation_stream_tag) {
GST_DEBUG_OBJECT (vf,
"ignoring global tags as we received stream specific ones: %"
GST_PTR_FORMAT, taglist);
} else {
gst_video_flip_set_method (vf, method, TRUE);
}
}
break;
case GST_EVENT_STREAM_START:
GST_DEBUG_OBJECT (vf, "new stream, reset orientation from tags");
vf->got_orientation_stream_tag = FALSE;
gst_video_flip_set_method (vf, GST_VIDEO_ORIENTATION_IDENTITY, TRUE);
break;
default:

View file

@ -79,6 +79,8 @@ struct _GstVideoFlip {
GstVideoOrientationMethod method;
GstVideoOrientationMethod tag_method;
/* TRUE if we received orientation from tag event with GST_TAG_SCOPE_STREAM */
gboolean got_orientation_stream_tag;
GstVideoOrientationMethod proposed_method;
gboolean change_configuring_method;
GstVideoOrientationMethod configuring_method;

View file

@ -308,7 +308,8 @@ caps_update (GstHarness * flip, GstVideoInfo * in_info, gboolean rotate)
}
static void
send_orientation_tag (GstHarness * flip, const gchar * orientation)
send_orientation_tag (GstHarness * flip, const gchar * orientation,
GstTagScope scope)
{
GstTagList *tags;
gchar *tmp;
@ -323,6 +324,7 @@ send_orientation_tag (GstHarness * flip, const gchar * orientation)
tags = gst_tag_list_new_from_string (tmp);
g_free (tmp);
fail_unless (tags != NULL);
gst_tag_list_set_scope (tags, scope);
gst_harness_push_event (flip, gst_event_new_tag (tags));
e = gst_harness_pull_event (flip);
@ -364,7 +366,7 @@ GST_START_TEST (test_orientation_tag)
fail_unless_equals_int (GST_EVENT_TYPE (e), GST_EVENT_SEGMENT);
gst_event_unref (e);
send_orientation_tag (flip, "rotate-90");
send_orientation_tag (flip, "rotate-90", GST_TAG_SCOPE_STREAM);
// caps is updated as the frame is now rotated
caps_update (flip, &in_info, TRUE);
@ -383,6 +385,81 @@ GST_START_TEST (test_orientation_tag)
GST_END_TEST;
// send a buffer and ensure caps have not been updated
static void
caps_not_updated (GstHarness * flip, GstVideoInfo * in_info)
{
GstBuffer *buf;
GstEvent *e;
buf = create_test_video_buffer_rgba8 (in_info);
buf = gst_harness_push_and_pull (flip, buf);
fail_unless (buf != NULL);
gst_buffer_unref (buf);
// caps is not updated
e = gst_harness_try_pull_event (flip);
fail_unless (e == NULL);
}
// receive orientation updates from tags with the global and stream scopes
GST_START_TEST (test_orientation_tag_scopes)
{
GstHarness *flip = gst_harness_new ("videoflip");
GstVideoInfo in_info, out_info;
GstCaps *in_caps, *out_caps;
GstEvent *e;
g_object_set (flip->element, "video-direction", 8 /* auto */ , NULL);
// downstream accept any resolution
gst_harness_set_sink_caps_str (flip, "video/x-raw");
gst_video_info_set_format (&in_info, GST_VIDEO_FORMAT_RGBA, 4, 9);
in_caps = gst_video_info_to_caps (&in_info);
gst_harness_set_src_caps (flip, in_caps);
e = gst_harness_pull_event (flip);
fail_unless_equals_int (GST_EVENT_TYPE (e), GST_EVENT_STREAM_START);
gst_event_unref (e);
e = gst_harness_pull_event (flip);
fail_unless_equals_int (GST_EVENT_TYPE (e), GST_EVENT_CAPS);
gst_event_parse_caps (e, &out_caps);
fail_unless (gst_video_info_from_caps (&out_info, out_caps));
fail_unless_equals_int (GST_VIDEO_INFO_WIDTH (&in_info),
GST_VIDEO_INFO_WIDTH (&out_info));
fail_unless_equals_int (GST_VIDEO_INFO_HEIGHT (&in_info),
GST_VIDEO_INFO_HEIGHT (&out_info));
gst_event_unref (e);
e = gst_harness_pull_event (flip);
fail_unless_equals_int (GST_EVENT_TYPE (e), GST_EVENT_SEGMENT);
gst_event_unref (e);
// send orientation global tag (global: 90, stream: /)
send_orientation_tag (flip, "rotate-90", GST_TAG_SCOPE_GLOBAL);
// caps is updated as the frame is now rotated
caps_update (flip, &in_info, TRUE);
// send orientation stream tag, overriding the global one (global: 90, stream: 0)
send_orientation_tag (flip, "rotate-0", GST_TAG_SCOPE_STREAM);
// caps is updated as the frame is no longer rotated
caps_update (flip, &in_info, FALSE);
// resend orientation global tag, which won't change the orientation as the stream tag takes precedence (global: 90, stream: 0)
send_orientation_tag (flip, "rotate-90", GST_TAG_SCOPE_GLOBAL);
caps_not_updated (flip, &in_info);
// actually update the orientation with the stream tag (global: 90, stream: 90)
send_orientation_tag (flip, "rotate-90", GST_TAG_SCOPE_STREAM);
// caps is updated as the frame is now rotated
caps_update (flip, &in_info, TRUE);
gst_harness_teardown (flip);
}
GST_END_TEST;
static Suite *
videoflip_suite (void)
{
@ -396,6 +473,7 @@ videoflip_suite (void)
test_change_method_twice_same_caps_different_method);
tcase_add_test (tc_chain, test_stress_change_method);
tcase_add_test (tc_chain, test_orientation_tag);
tcase_add_test (tc_chain, test_orientation_tag_scopes);
return s;
}