ges: Move TimeOverlayClip out of GESTestClip

This was complexifying the implementation for very little gain.
Each source type should ideally have its own API.

In that patch we make it so we do not have to subclass anything
but instead use GESAsset to pass information about how the pipeline
should look like.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-editing-services/-/merge_requests/175>
This commit is contained in:
Thibault Saunier 2020-04-22 13:39:21 -04:00 committed by GStreamer Merge Bot
parent b79e5e3508
commit 5e448921d8
19 changed files with 459 additions and 231 deletions

View file

@ -0,0 +1,201 @@
#### `alpha`
alpha of the stream
Value type: #gdouble
#### `background-color`
Background color to use (big-endian ARGB)
Value type: #guint
See #videotestsrc:background-color
#### `font-desc`
Pango font description of font to be used for rendering. See documentation of
pango_font_description_from_string for syntax.
Value type: #gchararray
See #timeoverlay:font-desc
#### `foreground-color`
Foreground color to use (big-endian ARGB)
Value type: #guint
See #videotestsrc:foreground-color
#### `freq`
Frequency of test signal. The sample rate needs to be at least 2 times higher.
Value type: #gdouble
See #audiotestsrc:freq
#### `halignment`
Horizontal alignment of the text
Valid values:
- **left** (0) left
- **center** (1) center
- **right** (2) right
- **position** (4) Absolute position clamped to canvas
- **absolute** (5) Absolute position
See #timeoverlay:halignment
#### `height`
height of the source
Value type: #gint
#### `mute`
mute channel
Value type: #gboolean
See #volume:mute
#### `pattern`
Type of test pattern to generate
Valid values:
- **SMPTE 100% color bars** (0) smpte
- **Random (television snow)** (1) snow
- **100% Black** (2) black
- **100% White** (3) white
- **Red** (4) red
- **Green** (5) green
- **Blue** (6) blue
- **Checkers 1px** (7) checkers-1
- **Checkers 2px** (8) checkers-2
- **Checkers 4px** (9) checkers-4
- **Checkers 8px** (10) checkers-8
- **Circular** (11) circular
- **Blink** (12) blink
- **SMPTE 75% color bars** (13) smpte75
- **Zone plate** (14) zone-plate
- **Gamut checkers** (15) gamut
- **Chroma zone plate** (16) chroma-zone-plate
- **Solid color** (17) solid-color
- **Moving ball** (18) ball
- **SMPTE 100% color bars** (19) smpte100
- **Bar** (20) bar
- **Pinwheel** (21) pinwheel
- **Spokes** (22) spokes
- **Gradient** (23) gradient
- **Colors** (24) colors
See #videotestsrc:pattern
#### `posx`
x position of the stream
Value type: #gint
#### `posy`
y position of the stream
Value type: #gint
#### `text-width`
Resulting width of font rendering
Value type: #guint
See #timeoverlay:text-width
#### `text-x`
Resulting X position of font rendering.
Value type: #gint
See #timeoverlay:text-x
#### `text-y`
Resulting X position of font rendering.
Value type: #gint
See #timeoverlay:text-y
#### `time-mode`
What time to show
Valid values:
- **buffer-time** (0) buffer-time
- **stream-time** (1) stream-time
- **running-time** (2) running-time
- **time-code** (3) time-code
See #timeoverlay:time-mode
#### `valignment`
Vertical alignment of the text
Valid values:
- **baseline** (0) baseline
- **bottom** (1) bottom
- **top** (2) top
- **position** (3) Absolute position clamped to canvas
- **center** (4) center
- **absolute** (5) Absolute position
See #timeoverlay:valignment
#### `video-direction`
Video direction: rotation and flipping
Valid values:
- **GST_VIDEO_ORIENTATION_IDENTITY** (0) identity
- **GST_VIDEO_ORIENTATION_90R** (1) 90r
- **GST_VIDEO_ORIENTATION_180** (2) 180
- **GST_VIDEO_ORIENTATION_90L** (3) 90l
- **GST_VIDEO_ORIENTATION_HORIZ** (4) horiz
- **GST_VIDEO_ORIENTATION_VERT** (5) vert
- **GST_VIDEO_ORIENTATION_UL_LR** (6) ul-lr
- **GST_VIDEO_ORIENTATION_UR_LL** (7) ur-ll
- **GST_VIDEO_ORIENTATION_AUTO** (8) auto
- **GST_VIDEO_ORIENTATION_CUSTOM** (9) custom
See #videoflip:video-direction
#### `volume`
Volume of test signal
Value type: #gdouble
See #audiotestsrc:volume
#### `volume`
volume factor, 1.0=100%
Value type: #gdouble
See #volume:volume
#### `width`
width of the source
Value type: #gint

20
docs/libs/document-children-props.py Executable file → Normal file
View file

@ -33,24 +33,32 @@ if __name__ == "__main__":
layer = tl.append_layer()
elements = []
def add_clip(c, add=True):
def add_clip(c, add=True, override_name=None):
c.props.duration = Gst.SECOND
c.props.start = layer.get_duration()
layer.add_clip(c)
if add:
elements.extend(c.children)
else:
if override_name:
elements.append((c, override_name))
else:
elements.append(c)
add_clip(GES.UriClipAsset.request_sync(Gst.filename_to_uri(os.path.join("../../", "tests/check/assets/audio_video.ogg"))).extract())
add_clip(GES.TestClip.new())
add_clip(GES.TitleClip.new())
transition = GES.TransitionClip.new_for_nick("crossfade")
add_clip(transition, False)
elements.append(transition)
add_clip(GES.SourceClip.new_time_overlay(), False, "GESTimeOverlaySourceClip")
add_clip(GES.TransitionClip.new_for_nick("crossfade"), False)
for element in elements:
gtype = element.__gtype__
if isinstance(element, tuple):
element, gtype = element
else:
gtype = element.__gtype__.name
print(gtype)
with open(gtype.name + '-children-props.md', 'w') as f:
with open(gtype + '-children-props.md', 'w') as f:
for prop in GES.TimelineElement.list_children_properties(element):
prefix = '#### `%s`\n\n' % (prop.name)

View file

@ -6,6 +6,7 @@ gi-index
ges-uri-clip.h
ges-title-clip.h
ges-test-clip.h
ges-time-overlay-clip.h
ges-effect-clip.h
ges-transition-clip.h
ges-pipeline.h

View file

@ -501,9 +501,11 @@ ges_video_uri_source_get_natural_size(GESVideoSource* source, gint* width, gint*
/**********************************
* GESTestClipAsset internal API *
**********************************/
G_GNUC_INTERNAL gboolean ges_test_clip_asset_get_natural_size(GESAsset *self,
gint *width,
gint *height);
G_GNUC_INTERNAL gboolean ges_test_clip_asset_get_natural_size (GESAsset *self,
gint *width,
gint *height);
G_GNUC_INTERNAL gchar *ges_test_source_asset_check_id (GType type, const gchar *id,
GError **error);
/************************
* Our property masks *

View file

@ -53,10 +53,52 @@ enum
PROP_0,
};
static GESExtractableInterface *parent_extractable_iface = NULL;
static gchar *
extractable_check_id (GType type, const gchar * id, GError ** error)
{
if (type == GES_TYPE_SOURCE_CLIP) {
g_set_error (error, GES_ERROR, GES_ERROR_ASSET_WRONG_ID,
"Only `time-overlay` is supported as an ID for type: `GESSourceClip`,"
" got: '%s'", id);
return NULL;
}
return parent_extractable_iface->check_id (type, id, error);
}
static GType
extractable_get_real_extractable_type (GType wanted_type, const gchar * id)
{
GstStructure *structure;
if (!id || (wanted_type != GES_TYPE_SOURCE_CLIP
&& wanted_type != GES_TYPE_TEST_CLIP))
return wanted_type;
structure = gst_structure_new_from_string (id);
if (!structure)
return wanted_type;
if (gst_structure_has_name (structure, "time-overlay"))
/* Just reusing TestClip to create a GESTimeOverlayClip
* as it already does the job! */
wanted_type = GES_TYPE_TEST_CLIP;
gst_structure_free (structure);
return wanted_type;
}
static void
extractable_interface_init (GESExtractableInterface * iface)
{
iface->asset_type = GES_TYPE_SOURCE_CLIP_ASSET;
iface->get_real_extractable_type = extractable_get_real_extractable_type;
iface->check_id = extractable_check_id;
parent_extractable_iface = g_type_interface_peek_parent (iface);
}
G_DEFINE_TYPE_WITH_CODE (GESSourceClip, ges_source_clip,

View file

@ -1,6 +1,8 @@
/* GStreamer Editing Services
* Copyright (C) 2009 Edward Hervey <edward.hervey@collabora.co.uk>
* 2009 Nokia Corporation
* Copyright (C) 2020 Igalia S.L
* Author: 2020 Thibault Saunier <tsaunier@igalia.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@ -28,7 +30,7 @@
* ## Asset
*
* The default asset ID is GESTestClip, but the framerate and video
* size can be overriden using an ID of the form:
* size can be overridden using an ID of the form:
*
* ```
* framerate=60/1, width=1920, height=1080, max-duration=5.0
@ -167,15 +169,21 @@ typedef struct
GType type;
} ValidField;
static gchar *
ges_extractable_check_id (GType type, const gchar * id, GError ** error)
gchar *
ges_test_source_asset_check_id (GType type, const gchar * id, GError ** error)
{
if (id && g_strcmp0 (id, g_type_name (type))) {
gchar *struct_str = g_strdup_printf ("%s,%s", g_type_name (type), id);
gchar *res = NULL;
GstStructure *structure = gst_structure_from_string (struct_str, NULL);
GstStructure *structure = gst_structure_from_string (id, NULL);
GST_DEBUG ("Structure is %s %" GST_PTR_FORMAT, struct_str, structure);
if (!structure) {
gchar *struct_str = g_strdup_printf ("%s,%s", g_type_name (type), id);
structure = gst_structure_from_string (struct_str, NULL);
g_free (struct_str);
}
GST_INFO ("Test source ID: %" GST_PTR_FORMAT, structure);
if (!structure) {
g_set_error (error, GES_ERROR, GES_ERROR_ASSET_WRONG_ID,
"GESTestClipAsset ID should be in the form: `framerate=30/1, "
@ -186,6 +194,7 @@ ges_extractable_check_id (GType type, const gchar * id, GError ** error)
{"height", G_TYPE_INT},
{"framerate", G_TYPE_NONE}, /* GST_TYPE_FRACTION is not constant */
{"max-duration", GST_TYPE_CLOCK_TIME},
{"disable-timecodestamper", G_TYPE_BOOLEAN},
};
gint i;
@ -209,7 +218,6 @@ ges_extractable_check_id (GType type, const gchar * id, GError ** error)
field.name)), g_type_name (type));
gst_structure_free (structure);
g_free (struct_str);
return FALSE;
}
@ -219,7 +227,6 @@ ges_extractable_check_id (GType type, const gchar * id, GError ** error)
gst_structure_free (structure);
}
g_free (struct_str);
return res;
}
@ -230,7 +237,7 @@ static void
ges_extractable_interface_init (GESExtractableInterface * iface)
{
iface->asset_type = GES_TYPE_TEST_CLIP_ASSET;
iface->check_id = ges_extractable_check_id;
iface->check_id = ges_test_source_asset_check_id;
}
G_DEFINE_TYPE_WITH_CODE (GESTestClip, ges_test_clip, GES_TYPE_SOURCE_CLIP,
@ -517,7 +524,25 @@ ges_test_clip_create_track_element (GESClip * clip, GESTrackType type)
ges_track_type_name (type));
if (type == GES_TRACK_TYPE_VIDEO) {
res = (GESTrackElement *) ges_video_test_source_new ();
gchar *id = NULL;
GESAsset *videoasset;
if (asset) {
GstStructure *structure =
gst_structure_from_string (ges_asset_get_id (asset), NULL);
if (structure) {
id = g_strdup (gst_structure_get_name (structure));
gst_structure_free (structure);
}
}
/* Our asset ID has been verified and thus this should not fail ever */
videoasset = ges_asset_request (GES_TYPE_VIDEO_TEST_SOURCE, id, NULL);
g_assert (videoasset);
g_free (id);
res = (GESTrackElement *) ges_asset_extract (videoasset, NULL);
gst_object_unref (videoasset);
ges_video_test_source_set_pattern (
(GESVideoTestSource *) res, priv->vpattern);
} else if (type == GES_TRACK_TYPE_AUDIO) {

View file

@ -1,6 +1,8 @@
/* GStreamer Editing Services
* Copyright (C) 2009 Brandon Lewis <brandon.lewis@collabora.co.uk>
* 2009 Nokia Corporation
* Copyright (C) 2020 Igalia S.L
* Author: 2020 Thibault Saunier <tsaunier@igalia.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public

View file

@ -0,0 +1,53 @@
/**
* SECTION:gestimeoverlayclip
* @title: GESTimeOverlayClip
* @short_description: Source with a time overlay on top
* @symbols:
* - ges_source_clip_new_time_overlay
*
* A #GESSourceClip that overlays timing information on top.
*
* ## Asset
*
* The default asset ID is "time-overlay" (of type #GES_TYPE_SOURCE_CLIP),
* but the framerate and video size can be overridden using an ID of the form:
*
* ```
* time-overlay, framerate=60/1, width=1920, height=1080, max-duration=5.0
* ```
*
* ## Children properties
*
* {{ libs/GESTimeOverlayClip-children-props.md }}
*
* ## Symbols
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include "ges-asset.h"
#include "ges-time-overlay-clip.h"
/**
* ges_source_clip_new_time_overlay:
*
* Creates a new #GESSourceClip that renders a time overlay on top
*
* Returns: (transfer floating) (nullable): The newly created #GESSourceClip,
* or %NULL if there was an error.
*/
GESSourceClip *
ges_source_clip_new_time_overlay (void)
{
GESSourceClip *new_clip;
GESAsset *asset = ges_asset_request (GES_TYPE_SOURCE_CLIP,
"time-overlay", NULL);
new_clip = GES_SOURCE_CLIP (ges_asset_extract (asset, NULL));
gst_object_unref (asset);
return new_clip;
}

View file

@ -0,0 +1,30 @@
/* GStreamer Editing Services
* Copyright (C) 2020 Igalia S.L
* Author: 2020 Thibault Saunier <tsaunier@igalia.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#pragma once
#include "ges-source-clip.h"
G_BEGIN_DECLS
GES_API
GESSourceClip* ges_source_clip_new_time_overlay (void);
G_END_DECLS

View file

@ -63,6 +63,8 @@ static void
ges_extractable_interface_init (GESExtractableInterface * iface)
{
iface->set_asset = ges_video_source_set_asset;
parent_extractable_iface = g_type_interface_peek_parent (iface);
}
G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GESVideoSource, ges_video_source,
@ -233,16 +235,6 @@ ges_video_source_class_init (GESVideoSourceClass * klass)
static void
ges_video_source_init (GESVideoSource * self)
{
if (g_once_init_enter (&parent_extractable_iface)) {
GESExtractableInterface *iface, *parent_iface;
iface =
G_TYPE_INSTANCE_GET_INTERFACE (self, GES_TYPE_EXTRACTABLE,
GESExtractableInterface);
parent_iface = g_type_interface_peek_parent (iface);
g_once_init_leave (&parent_extractable_iface, parent_iface);
}
self->priv = ges_video_source_get_instance_private (self);
self->priv->positioner = NULL;
self->priv->capsfilter = NULL;

View file

@ -1,6 +1,8 @@
/* GStreamer Editing Services
* Copyright (C) 2010 Brandon Lewis <brandon.lewis@collabora.co.uk>
* 2010 Nokia Corporation
* Copyright (C) 2020 Igalia S.L
* Author: 2020 Thibault Saunier <tsaunier@igalia.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@ -38,18 +40,30 @@ struct _GESVideoTestSourcePrivate
{
GESVideoTestPattern pattern;
gboolean use_overlay;
GstElement *overlay;
GstPad *is_passthrough_pad;
GstPad *os_passthrough_pad;
GstPad *is_overlay_pad;
GstPad *os_overlay_pad;
GstElement *capsfilter;
};
G_DEFINE_TYPE_WITH_PRIVATE (GESVideoTestSource, ges_video_test_source,
GES_TYPE_VIDEO_SOURCE);
static void
ges_extractable_interface_init (GESExtractableInterface * iface)
{
iface->check_id = ges_test_source_asset_check_id;
iface->asset_type = GES_TYPE_TRACK_ELEMENT_ASSET;
}
static GstStructure *
ges_video_test_source_asset_get_config (GESAsset * asset)
{
const gchar *id = ges_asset_get_id (asset);
if (g_strcmp0 (id, g_type_name (ges_asset_get_extractable_type (asset))))
return gst_structure_from_string (ges_asset_get_id (asset), NULL);
return NULL;
}
G_DEFINE_TYPE_WITH_CODE (GESVideoTestSource, ges_video_test_source,
GES_TYPE_VIDEO_SOURCE, G_ADD_PRIVATE (GESVideoTestSource)
G_IMPLEMENT_INTERFACE (GES_TYPE_EXTRACTABLE,
ges_extractable_interface_init));
static GstElement *ges_video_test_source_create_source (GESTrackElement * self);
@ -74,101 +88,6 @@ get_natural_size (GESVideoSource * source, gint * width, gint * height)
return TRUE;
}
enum
{
PROP_0,
PROP_USE_TIME_OVERLAY,
PROP_LAST
};
static GParamSpec *properties[PROP_LAST];
static void
get_property (GObject * object, guint property_id,
GValue * value, GParamSpec * pspec)
{
GESVideoTestSource *self = GES_VIDEO_TEST_SOURCE (object);
switch (property_id) {
case PROP_USE_TIME_OVERLAY:
g_value_set_boolean (value, self->priv->use_overlay);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
set_property (GObject * object, guint property_id,
const GValue * value, GParamSpec * pspec)
{
GESVideoTestSource *self = GES_VIDEO_TEST_SOURCE (object);
switch (property_id) {
case PROP_USE_TIME_OVERLAY:
{
GstElement *os, *is;
gboolean used_overlay = self->priv->use_overlay;
if (!self->priv->overlay) {
GST_ERROR_OBJECT (object, "Overlaying is disabled, you are probably"
"missing some GStreamer plugin");
return;
}
self->priv->use_overlay = g_value_get_boolean (value);
if (used_overlay == self->priv->use_overlay)
return;
is = GST_ELEMENT (gst_object_get_parent (GST_OBJECT (self->
priv->is_overlay_pad)));
if (!is)
return;
os = GST_ELEMENT (gst_object_get_parent (GST_OBJECT (self->
priv->os_overlay_pad)));
if (!os) {
gst_object_unref (is);
return;
}
g_object_set (is, "active-pad",
self->priv->use_overlay ? self->priv->is_overlay_pad : self->
priv->is_passthrough_pad, NULL);
g_object_set (os, "active-pad",
self->priv->use_overlay ? self->priv->os_overlay_pad : self->
priv->os_passthrough_pad, NULL);
gst_object_unref (is);
gst_object_unref (os);
break;
}
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
}
static void
_set_child_property (GESTimelineElement * self, GObject * child,
GParamSpec * pspec, GValue * value)
{
GstElementFactory *f =
GST_IS_ELEMENT (child) ? gst_element_get_factory (GST_ELEMENT (child)) :
NULL;
if (!f || g_strcmp0 (GST_OBJECT_NAME (f), "timeoverlay"))
goto done;
GST_INFO_OBJECT (self, "Activating time overlay as time mode is being set");
g_object_set (self, "use-time-overlay", TRUE, NULL);
done:
GES_TIMELINE_ELEMENT_CLASS (ges_video_test_source_parent_class)
->set_child_property (self, child, pspec, value);
}
static gboolean
_set_parent (GESTimelineElement * element, GESTimelineElement * parent)
{
@ -231,13 +150,6 @@ _get_natural_framerate (GESTimelineElement * element, gint * fps_n,
static void
dispose (GObject * object)
{
GESVideoTestSourcePrivate *priv = GES_VIDEO_TEST_SOURCE (object)->priv;
gst_clear_object (&priv->is_overlay_pad);
gst_clear_object (&priv->is_passthrough_pad);
gst_clear_object (&priv->os_overlay_pad);
gst_clear_object (&priv->os_passthrough_pad);
G_OBJECT_CLASS (ges_video_test_source_parent_class)->dispose (object);
}
@ -250,33 +162,11 @@ ges_video_test_source_class_init (GESVideoTestSourceClass * klass)
source_class->create_source = ges_video_test_source_create_source;
source_class->ABI.abi.get_natural_size = get_natural_size;
/**
* GESVideoTestSource:use-overlay:
*
* Whether to overlay the test video source with a clock time.
* This property is also registered as a child property for the video
* test source, so you can set it like any other child property.
*
* The properties of the corresponding #timeoverlay are also registered
* as children properties. If you set any child property from the underlying
* `timeoverlay`, this property will be set to %TRUE by default.
*/
properties[PROP_USE_TIME_OVERLAY] =
g_param_spec_boolean ("use-time-overlay", "Use-time-overlay",
"Use time overlay, setting a child property corresponding to"
" GstTimeOverlay will switch this on by default.", FALSE,
G_PARAM_READWRITE);
object_class->get_property = get_property;
object_class->set_property = set_property;
object_class->dispose = dispose;
GES_TIMELINE_ELEMENT_CLASS (klass)->set_child_property = _set_child_property;
GES_TIMELINE_ELEMENT_CLASS (klass)->set_parent = _set_parent;
GES_TIMELINE_ELEMENT_CLASS (klass)->get_natural_framerate =
_get_natural_framerate;
g_object_class_install_properties (object_class, PROP_LAST, properties);
}
static void
@ -287,63 +177,40 @@ ges_video_test_source_init (GESVideoTestSource * self)
self->priv->pattern = DEFAULT_VPATTERN;
}
#define CREATE_ELEMENT(var, ename) \
if (!(var = gst_element_factory_make(ename, NULL))) { \
GST_ERROR_OBJECT(self, "Could not create %s", ename); \
goto done; \
} \
gst_object_ref(var);
static GstStructure *
ges_video_test_source_get_config (GESVideoTestSource * self)
{
GESAsset *asset = ges_extractable_get_asset (GES_EXTRACTABLE (self));
if (asset)
return ges_video_test_source_asset_get_config (asset);
return NULL;
}
static GstElement *
ges_video_test_source_create_overlay (GESVideoTestSource * self)
{
GstElement *bin = NULL, *os = NULL, *is = NULL, *toverlay = NULL, *tcstamper =
NULL;
GstPad *tmppad;
const gchar *bindesc = NULL;
GstStructure *config = ges_video_test_source_get_config (self);
CREATE_ELEMENT (os, "output-selector");
gst_util_set_object_arg (G_OBJECT (os), "pad-negotiation-mode", "active");
CREATE_ELEMENT (is, "input-selector");
CREATE_ELEMENT (tcstamper, "timecodestamper");
CREATE_ELEMENT (toverlay, "timeoverlay");
if (!config)
return NULL;
bin = gst_bin_new (NULL);
if (gst_structure_has_name (config, "time-overlay")) {
gboolean disable_timecodestamper;
gst_bin_add_many (GST_BIN (bin), os, is, tcstamper, toverlay, NULL);
self->priv->os_passthrough_pad = gst_element_get_request_pad (os, "src_%u");
self->priv->is_passthrough_pad = gst_element_get_request_pad (is, "sink_%u");
if (gst_structure_get_boolean (config, "disable-timecodestamper",
&disable_timecodestamper))
bindesc = "timeoverlay";
else
bindesc = "timecodestamper ! timeoverlay";
}
gst_structure_free (config);
gst_pad_link_full (self->priv->os_passthrough_pad,
self->priv->is_passthrough_pad, GST_PAD_LINK_CHECK_NOTHING);
gst_element_link (tcstamper, toverlay);
if (!bindesc)
return NULL;
self->priv->os_overlay_pad = gst_element_get_request_pad (os, "src_%u");
tmppad = gst_element_get_static_pad (tcstamper, "sink");
gst_pad_link_full (self->priv->os_overlay_pad, tmppad,
GST_PAD_LINK_CHECK_NOTHING);
gst_object_unref (tmppad);
tmppad = gst_element_get_static_pad (toverlay, "src");
self->priv->is_overlay_pad = gst_element_get_request_pad (is, "sink_%u");
gst_pad_link_full (tmppad, self->priv->is_overlay_pad,
GST_PAD_LINK_CHECK_NOTHING);
gst_object_unref (tmppad);
tmppad = gst_element_get_static_pad (os, "sink");
gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("sink", tmppad));
gst_object_unref (tmppad);
tmppad = gst_element_get_static_pad (is, "src");
gst_element_add_pad (GST_ELEMENT (bin), gst_ghost_pad_new ("src", tmppad));
gst_object_unref (tmppad);
done:
gst_clear_object (&os);
gst_clear_object (&is);
gst_clear_object (&tcstamper);
gst_clear_object (&toverlay);
return bin;
return gst_parse_bin_from_description (bindesc, TRUE, NULL);
}
static GstElement *
@ -352,6 +219,7 @@ ges_video_test_source_create_source (GESTrackElement * element)
GstCaps *caps;
gint pattern;
GstElement *testsrc, *res;
GstElement *overlay;
const gchar *props[] =
{ "pattern", "background-color", "foreground-color", NULL };
GPtrArray *elements;
@ -374,18 +242,16 @@ ges_video_test_source_create_source (GESTrackElement * element)
g_object_set (self->priv->capsfilter, "caps", caps, NULL);
gst_caps_unref (caps);
self->priv->overlay = ges_video_test_source_create_overlay (self);
if (self->priv->overlay) {
overlay = ges_video_test_source_create_overlay (self);
if (overlay) {
const gchar *overlay_props[] =
{ "time-mode", "text-y", "text-x", "text-width", "test-height",
"halignment", "valignment", "font-desc", NULL
};
ges_track_element_add_children_props (element, self->priv->overlay, NULL,
ges_track_element_add_children_props (element, overlay, NULL,
NULL, overlay_props);
ges_timeline_element_add_child_property (GES_TIMELINE_ELEMENT (self),
properties[PROP_USE_TIME_OVERLAY], G_OBJECT (self));
g_ptr_array_add (elements, self->priv->overlay);
g_ptr_array_add (elements, overlay);
}
ges_track_element_add_children_props (element, testsrc, NULL, NULL, props);
@ -440,7 +306,8 @@ ges_video_test_source_get_pattern (GESVideoTestSource * source)
return g_value_get_enum (&val);
}
/* ges_video_test_source_new:
/**
* ges_video_test_source_new:
*
* Creates a new #GESVideoTestSource.
*

View file

@ -1,6 +1,8 @@
/* GStreamer Editing Services
* Copyright (C) 2010 Brandon Lewis <brandon.lewis@collabora.co.uk>
* 2010 Nokia Corporation
* Copyright (C) 2020 Igalia S.L
* Author: 2020 Thibault Saunier <tsaunier@igalia.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public

View file

@ -33,6 +33,7 @@
#include <ges/ges-clip.h>
#include <ges/ges-pipeline.h>
#include <ges/ges-source-clip.h>
#include <ges/ges-time-overlay-clip.h>
#include <ges/ges-test-clip.h>
#include <ges/ges-title-clip.h>
#include <ges/ges-operation-clip.h>

View file

@ -14,6 +14,7 @@ ges_sources = files([
'ges-operation-clip.c',
'ges-base-transition-clip.c',
'ges-transition-clip.c',
'ges-time-overlay-clip.c',
'ges-test-clip.c',
'ges-title-clip.c',
'ges-overlay-clip.c',
@ -86,6 +87,7 @@ ges_headers = files([
'ges-base-transition-clip.h',
'ges-transition-clip.h',
'ges-test-clip.h',
'ges-time-overlay-clip.h',
'ges-title-clip.h',
'ges-overlay-clip.h',
'ges-text-overlay-clip.h',

View file

@ -3999,7 +3999,7 @@ GST_START_TEST (test_copy_paste_children_properties)
timeline = ges_timeline_new_audio_video ();
layer = ges_timeline_append_layer (timeline);
clip = GES_TIMELINE_ELEMENT (ges_test_clip_new ());
clip = GES_TIMELINE_ELEMENT (ges_source_clip_new_time_overlay ());
assert_set_duration (clip, 50);
fail_unless (ges_layer_add_clip (layer, GES_CLIP (clip)));

View file

@ -5,7 +5,7 @@ description, handles-states=true,
"--videosink=fakesink"\
}
add-clip, name=clip, asset-id="framerate=120/1", layer-priority=0, type=GESTestClip, pattern=blue, duration=f240, inpoint=f100
add-clip, name=clip, asset-id="time-overlay,framerate=120/1", layer-priority=0, type=GESSourceClip, pattern=blue, duration=f240, inpoint=f100
set-child-properties, element-name=clip, time-mode=time-code
pause

View file

@ -12,11 +12,11 @@ meta,
"$(validateflow), pad=videosink:sink, record-buffers=true, ignored-fields=\"stream-start={stream-id,group-id,stream}\"",
}
add-clip, name=c0, asset-id=GESTestClip, layer-priority=0, type=GESTestClip, start=0, duration=1.0
set-child-properties, element-name=c0, pattern=blue, time-mode=time-code, valignment=center, halignment=center
add-clip, name=c0, asset-id=time-overlay, layer-priority=0, type=GESSourceClip, start=0, duration=1.0
set-child-properties, element-name=c0, pattern=blue, valignment=center, halignment=center, time-mode=time-code
add-clip, name=c1, asset-id=GESTestClip, layer-priority=0, type=GESTestClip, start=1.0, duration=1.0
set-child-properties, element-name=c1, pattern=red, time-mode=time-code, valignment=center, halignment=center
add-clip, name=c1, asset-id=time-overlay, layer-priority=0, type=GESSourceClip, start=1.0, duration=1.0
set-child-properties, element-name=c1, pattern=red, valignment=center, halignment=center, time-mode=time-code
commit;
play

View file

@ -12,11 +12,11 @@ meta,
"$(validateflow), pad=videosink:sink, record-buffers=true, ignored-fields=\"stream-start={stream-id,group-id,stream}\"",
}
add-clip, name=c0, asset-id=GESTestClip, layer-priority=0, type=GESTestClip, start=0, duration=1.0
set-child-properties, element-name=c0, pattern=blue, time-mode=time-code, valignment=center, halignment=center
add-clip, name=c0, asset-id=time-overlay, layer-priority=0, type=GESSourceClip, start=0, duration=1.0
set-child-properties, element-name=c0, pattern=blue, valignment=center, halignment=center, time-mode=time-code
add-clip, name=c1, asset-id=GESTestClip, layer-priority=0, type=GESTestClip, start=1.0, duration=1.0
set-child-properties, element-name=c1, pattern=red, time-mode=time-code, valignment=center, halignment=center
add-clip, name=c1, asset-id=time-overlay, layer-priority=0, type=GESSourceClip, start=1.0, duration=1.0
set-child-properties, element-name=c1, pattern=red, valignment=center, halignment=center, time-mode=time-code
commit;
play

View file

@ -11,11 +11,11 @@ meta,
"$(validateflow), pad=audiosink:sink, record-buffers=true, ignored-fields=\"stream-start={stream-id,group-id,stream}, segment={position,}\"",
}
add-clip, name=c0, asset-id=GESTestClip, layer-priority=0, type=GESTestClip, start=0, duration=1.0
set-child-properties, element-name=c0, pattern=blue, time-mode=time-code, valignment=center, halignment=center
add-clip, name=c0, asset-id=time-overlay, layer-priority=0, type=GESSourceClip, start=0, duration=1.0
set-child-properties, element-name=c0, pattern=blue, valignment=center, halignment=center, time-mode=time-code
add-clip, name=c1, asset-id=GESTestClip, layer-priority=0, type=GESTestClip, start=1.0, duration=1.0
set-child-properties, element-name=c1, pattern=red, time-mode=time-code, valignment=center, halignment=center
add-clip, name=c1, asset-id=time-overlay, layer-priority=0, type=GESSourceClip, start=1.0, duration=1.0
set-child-properties, element-name=c1, pattern=red, valignment=center, halignment=center, time-mode=time-code
pause
seek, start=0.0, stop=0.5, flags=accurate+flush