From 7b3ac927dcedd21f5fa727ab315dae6b852f6097 Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Wed, 19 Feb 2020 18:06:26 -0300 Subject: [PATCH] ges: Add a method to retrieve the 'natural' size of VideoSource This way the user can easily know how the clip would look like if no scaling was applied to the clip, this is useful to be able to properly position the clips with the framepositionner element. --- ges/ges-image-source.c | 2 + ges/ges-internal.h | 6 +++ ges/ges-video-source.c | 29 +++++++++++++++ ges/ges-video-source.h | 3 ++ ges/ges-video-test-source.c | 16 +++++++- ges/ges-video-uri-source.c | 73 ++++++++++++++++++++++++++++++++++++- 6 files changed, 127 insertions(+), 2 deletions(-) diff --git a/ges/ges-image-source.c b/ges/ges-image-source.c index b4c3eb4eba..206e36a7cd 100644 --- a/ges/ges-image-source.c +++ b/ges/ges-image-source.c @@ -171,6 +171,8 @@ ges_image_source_class_init (GESImageSourceClass * klass) GES_TIMELINE_ELEMENT_CLASS (klass)->set_inpoint = NULL; source_class->create_source = ges_image_source_create_source; + source_class->ABI.abi.get_natural_size = + ges_video_uri_source_get_natural_size; } static void diff --git a/ges/ges-internal.h b/ges/ges-internal.h index 8afde95b8b..87323f3a37 100644 --- a/ges/ges-internal.h +++ b/ges/ges-internal.h @@ -459,6 +459,12 @@ typedef struct GESMultiFileURI G_GNUC_INTERNAL GESMultiFileURI * ges_multi_file_uri_new (const gchar * uri); +/****************************** + * GESUriSource internal API * + ******************************/ +G_GNUC_INTERNAL gboolean +ges_video_uri_source_get_natural_size(GESVideoSource* source, gint* width, gint* height); + /************************ * Our property masks * ************************/ diff --git a/ges/ges-video-source.c b/ges/ges-video-source.c index 63ae963ef5..3ba996c9d5 100644 --- a/ges/ges-video-source.c +++ b/ges/ges-video-source.c @@ -226,4 +226,33 @@ ges_video_source_init (GESVideoSource * self) self->priv = ges_video_source_get_instance_private (self); self->priv->positioner = NULL; self->priv->capsfilter = NULL; + +} + +/** + * ges_video_source_get_natural_size: + * @self: A #GESVideoSource + * @width: (out): The natural width of the underlying source + * @height: (out): The natural height of the underlying source + * + * Retrieves the natural size of the video stream. The natural size, is + * the size at which it will be displayed if no scaling is being applied. + * + * NOTE: The sources take into account the potential video rotation applied + * by the #videoflip element that is inside the source, effects applied on + * the clip which potentially also rotate the element are not taken into + * account. + * + * Returns: %TRUE if the object has a natural size, %FALSE otherwise. + */ +gboolean +ges_video_source_get_natural_size (GESVideoSource * self, gint * width, + gint * height) +{ + GESVideoSourceClass *klass = GES_VIDEO_SOURCE_GET_CLASS (self); + + if (!klass->ABI.abi.get_natural_size) + return FALSE; + + return klass->ABI.abi.get_natural_size (self, width, height); } diff --git a/ges/ges-video-source.h b/ges/ges-video-source.h index 1554cbd1c1..f626b1738e 100644 --- a/ges/ges-video-source.h +++ b/ges/ges-video-source.h @@ -85,12 +85,15 @@ struct _GESVideoSourceClass { struct { gboolean disable_scale_in_compositor; gboolean (*needs_converters)(GESVideoSource *self); + gboolean (*get_natural_size)(GESVideoSource* self, gint* width, gint* height); } abi; } ABI; }; GES_API GType ges_video_source_get_type (void); +GES_API +gboolean ges_video_source_get_natural_size(GESVideoSource* self, gint* width, gint* height); G_END_DECLS diff --git a/ges/ges-video-test-source.c b/ges/ges-video-test-source.c index a175dd59d9..ae9ae96a69 100644 --- a/ges/ges-video-test-source.c +++ b/ges/ges-video-test-source.c @@ -43,12 +43,22 @@ G_DEFINE_TYPE_WITH_PRIVATE (GESVideoTestSource, ges_video_test_source, static GstElement *ges_video_test_source_create_source (GESTrackElement * self); +static gboolean +get_natural_size (GESVideoSource * source, gint * width, gint * height) +{ + *width = DEFAULT_WIDTH; + *height = DEFAULT_HEIGHT; + + return TRUE; +} + static void ges_video_test_source_class_init (GESVideoTestSourceClass * klass) { GESVideoSourceClass *source_class = GES_VIDEO_SOURCE_CLASS (klass); source_class->create_source = ges_video_test_source_create_source; + source_class->ABI.abi.get_natural_size = get_natural_size; } static void @@ -76,7 +86,11 @@ ges_video_test_source_create_source (GESTrackElement * self) elements = g_ptr_array_new (); g_ptr_array_add (elements, capsfilter); - caps = gst_caps_new_empty_simple ("video/x-raw"); + caps = gst_caps_new_simple ("video/x-raw", + "width", G_TYPE_INT, DEFAULT_WIDTH, + "height", G_TYPE_INT, DEFAULT_HEIGHT, + "framerate", GST_TYPE_FRACTION, DEFAULT_FRAMERATE_N, DEFAULT_FRAMERATE_D, + NULL); g_object_set (capsfilter, "caps", caps, NULL); gst_caps_unref (caps); diff --git a/ges/ges-video-uri-source.c b/ges/ges-video-uri-source.c index 468b94b94a..b10b45814b 100644 --- a/ges/ges-video-uri-source.c +++ b/ges/ges-video-uri-source.c @@ -27,8 +27,9 @@ #include "config.h" #endif -#include +#include +#include #include "ges-utils.h" #include "ges-internal.h" #include "ges-track-element.h" @@ -113,6 +114,74 @@ ges_video_uri_source_needs_converters (GESVideoSource * source) return FALSE; } +gboolean +ges_video_uri_source_get_natural_size (GESVideoSource * source, gint * width, + gint * height) +{ + const GstTagList *tags = NULL; + gchar *rotation_info = NULL; + gint videoflip_method, rotate_angle; + GstDiscovererStreamInfo *info; + GESAsset *asset = ges_extractable_get_asset (GES_EXTRACTABLE (source)); + + g_assert (GES_IS_URI_SOURCE_ASSET (asset)); + info = ges_uri_source_asset_get_stream_info (GES_URI_SOURCE_ASSET (asset)); + + if (!GST_IS_DISCOVERER_VIDEO_INFO (info)) { + GST_ERROR_OBJECT (source, "Doesn't have a video info (%" GST_PTR_FORMAT + ")", info); + return FALSE; + } + + *width = + gst_discoverer_video_info_get_width (GST_DISCOVERER_VIDEO_INFO (info)); + *height = + gst_discoverer_video_info_get_height (GST_DISCOVERER_VIDEO_INFO (info)); + + if (!ges_timeline_element_lookup_child (GES_TIMELINE_ELEMENT (source), + "GstVideoFlip::video-direction", NULL, NULL)) + goto done; + + ges_timeline_element_get_child_properties (GES_TIMELINE_ELEMENT (source), + "GstVideoFlip::video-direction", &videoflip_method, NULL); + + /* Rotating 90 degrees, either way, rotate */ + if (videoflip_method == 1 || videoflip_method == 3) + goto rotate; + + if (videoflip_method != 8) + goto done; + + /* Rotation is automatic, we need to check if the media file is naturally + rotated */ + tags = + gst_discoverer_stream_info_get_tags (GST_DISCOVERER_STREAM_INFO (info)); + if (!tags) + goto done; + + if (!gst_tag_list_get_string (tags, GST_TAG_IMAGE_ORIENTATION, + &rotation_info)) + goto done; + + if (sscanf (rotation_info, "rotate-%d", &rotate_angle) == 1) { + if (rotate_angle == 90 || rotate_angle == 270) + goto rotate; + } + +done: + g_free (rotation_info); + return TRUE; + +rotate: + GST_INFO_OBJECT (self, "Stream is rotated, taking that into account"); + *width = + gst_discoverer_video_info_get_height (GST_DISCOVERER_VIDEO_INFO (info)); + *height = + gst_discoverer_video_info_get_width (GST_DISCOVERER_VIDEO_INFO (info)); + + goto done; +} + /* Extractable interface implementation */ static gchar * @@ -218,6 +287,8 @@ ges_video_uri_source_class_init (GESVideoUriSourceClass * klass) source_class->create_source = ges_video_uri_source_create_source; source_class->ABI.abi.needs_converters = ges_video_uri_source_needs_converters; + source_class->ABI.abi.get_natural_size = + ges_video_uri_source_get_natural_size; } static void