gstreamer/tests/check/ges/project.c
Henry Wilkes 9e18e03939 track-element: use out-point for updating control bindings
The out-point, which is an internal time, is used instead of the
duration for determining the control binding value at the end of the
element.

Also, allow the user to switch off the auto-clamping of control sources
if they are not desired. And allow them to clamp specific control sources
individually.

Also, fix a lot of memory leaks related to control sources. In
particular, releasing the extra ref gained by source in
g_object_get (binding, "control-source", &source, NULL);

Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-editing-services/-/merge_requests/177>
2020-05-25 11:20:38 +01:00

776 lines
24 KiB
C

/* GStreamer Editing Services
*
* Copyright (C) <2012> Thibault Saunier <thibault.saunier@collabora.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., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#include "test-utils.h"
#include <ges/ges.h>
#include <gst/check/gstcheck.h>
#include <gst/controller/gstdirectcontrolbinding.h>
#include <gst/controller/gstinterpolationcontrolsource.h>
GMainLoop *mainloop;
static void
project_loaded_cb (GESProject * project, GESTimeline * timeline,
GMainLoop * mainloop)
{
g_main_loop_quit (mainloop);
}
GST_START_TEST (test_project_simple)
{
gchar *id;
GESProject *project;
GESTimeline *timeline;
ges_init ();
mainloop = g_main_loop_new (NULL, FALSE);
project = GES_PROJECT (ges_asset_request (GES_TYPE_TIMELINE, NULL, NULL));
fail_unless (GES_IS_PROJECT (project));
assert_equals_string (ges_asset_get_id (GES_ASSET (project)), "project-0");
g_signal_connect (project, "loaded", (GCallback) project_loaded_cb, mainloop);
timeline = GES_TIMELINE (ges_asset_extract (GES_ASSET (project), NULL));
g_main_loop_run (mainloop);
fail_unless (GES_IS_TIMELINE (timeline));
id = ges_extractable_get_id (GES_EXTRACTABLE (timeline));
assert_equals_string (id, "project-0");
ASSERT_OBJECT_REFCOUNT (timeline, "We own the only ref", 1);
g_free (id);
gst_object_unref (project);
gst_object_unref (timeline);
g_main_loop_unref (mainloop);
g_signal_handlers_disconnect_by_func (project, (GCallback) project_loaded_cb,
mainloop);
ges_deinit ();
}
GST_END_TEST;
static void
asset_removed_add_cb (GESProject * project, GESAsset * asset, gboolean * called)
{
*called = TRUE;
}
static void
asset_created_cb (GObject * source, GAsyncResult * res, GESAsset ** asset)
{
GError *error = NULL;
*asset = ges_asset_request_finish (res, &error);
fail_unless (error == NULL);
g_main_loop_quit (mainloop);
}
GST_START_TEST (test_project_add_assets)
{
GESProject *project;
GESAsset *asset;
gboolean added_cb_called = FALSE;
gboolean removed_cb_called = FALSE;
ges_init ();
mainloop = g_main_loop_new (NULL, FALSE);
project = GES_PROJECT (ges_asset_request (GES_TYPE_TIMELINE, NULL, NULL));
fail_unless (GES_IS_PROJECT (project));
g_signal_connect (project, "asset-added",
(GCallback) asset_removed_add_cb, &added_cb_called);
g_signal_connect (project, "asset-removed",
(GCallback) asset_removed_add_cb, &removed_cb_called);
ges_asset_request_async (GES_TYPE_TEST_CLIP, NULL, NULL,
(GAsyncReadyCallback) asset_created_cb, &asset);
g_main_loop_run (mainloop);
g_main_loop_unref (mainloop);
fail_unless (GES_IS_ASSET (asset));
fail_unless (ges_project_add_asset (project, asset));
fail_unless (added_cb_called);
ASSERT_OBJECT_REFCOUNT (project, "The project", 2);
ASSERT_OBJECT_REFCOUNT (asset, "The asset (1 for project and one for "
"us + 1 cache)", 3);
fail_unless (ges_project_remove_asset (project, asset));
fail_unless (removed_cb_called);
g_signal_handlers_disconnect_by_func (project,
(GCallback) asset_removed_add_cb, &added_cb_called);
g_signal_handlers_disconnect_by_func (project,
(GCallback) asset_removed_add_cb, &removed_cb_called);
gst_object_unref (asset);
gst_object_unref (project);
ASSERT_OBJECT_REFCOUNT (asset, "The asset (1 ref in cache)", 1);
ASSERT_OBJECT_REFCOUNT (project, "The project (1 ref in cache)", 1);
ges_deinit ();
}
GST_END_TEST;
static void
error_loading_asset_cb (GESProject * project, GError * error, gchar * id,
GType extractable_type, GMainLoop * mainloop)
{
fail_unless (g_error_matches (error, GST_PARSE_ERROR,
GST_PARSE_ERROR_NO_SUCH_ELEMENT));
g_main_loop_quit (mainloop);
}
GST_START_TEST (test_project_unexistant_effect)
{
GESProject *project;
gboolean added_cb_called = FALSE;
gboolean removed_cb_called = FALSE;
ges_init ();
project = GES_PROJECT (ges_asset_request (GES_TYPE_TIMELINE, NULL, NULL));
fail_unless (GES_IS_PROJECT (project));
mainloop = g_main_loop_new (NULL, FALSE);
g_signal_connect (project, "asset-added",
(GCallback) asset_removed_add_cb, &added_cb_called);
g_signal_connect (project, "asset-removed",
(GCallback) asset_removed_add_cb, &removed_cb_called);
g_signal_connect (project, "error-loading-asset",
(GCallback) error_loading_asset_cb, mainloop);
fail_unless (ges_project_create_asset (project, "nowaythiselementexists",
GES_TYPE_EFFECT));
g_main_loop_run (mainloop);
/* And.... try again! */
fail_if (ges_project_create_asset (project, "nowaythiselementexists",
GES_TYPE_EFFECT));
fail_if (added_cb_called);
fail_if (removed_cb_called);
ASSERT_OBJECT_REFCOUNT (project, "The project", 2);
gst_object_unref (project);
g_main_loop_unref (mainloop);
ASSERT_OBJECT_REFCOUNT (project, "The project (1 ref in cache)", 1);
ges_deinit ();
}
GST_END_TEST;
static void
asset_added_cb (GESProject * project, GESAsset * asset)
{
gchar *uri = ges_test_file_uri ("audio_video.ogg");
GstDiscovererInfo *info;
if (ges_asset_get_extractable_type (asset) == GES_TYPE_EFFECT) {
assert_equals_string (ges_asset_get_id (asset), "video agingtv");
} else {
info = ges_uri_clip_asset_get_info (GES_URI_CLIP_ASSET (asset));
fail_unless (GST_IS_DISCOVERER_INFO (info));
assert_equals_string (ges_asset_get_id (asset), uri);
}
g_free (uri);
}
static gchar *
_set_new_uri (GESProject * project, GError * error, GESAsset * wrong_asset)
{
fail_unless (!g_strcmp0 (ges_asset_get_id (wrong_asset),
"file:///test/not/exisiting"));
return ges_test_file_uri ("audio_video.ogg");
}
static void
_test_project (GESProject * project, GESTimeline * timeline)
{
guint a_meta;
gchar *media_uri;
GESTrack *track;
const GList *profiles;
GstEncodingContainerProfile *profile;
GList *tracks, *tmp, *tmptrackelement, *clips;
fail_unless (GES_IS_TIMELINE (timeline));
assert_equals_int (g_list_length (timeline->layers), 2);
assert_equals_string (ges_meta_container_get_string (GES_META_CONTAINER
(project), "name"), "Example project");
clips = ges_layer_get_clips (GES_LAYER (timeline->layers->data));
fail_unless (ges_meta_container_get_uint (GES_META_CONTAINER
(timeline->layers->data), "a", &a_meta));
assert_equals_int (a_meta, 3);
assert_equals_int (g_list_length (clips), 1);
media_uri = ges_test_file_uri ("audio_video.ogg");
assert_equals_string (ges_asset_get_id (ges_extractable_get_asset
(GES_EXTRACTABLE (clips->data))), media_uri);
g_free (media_uri);
g_list_free_full (clips, gst_object_unref);
/* Check tracks and the objects they contain */
tracks = ges_timeline_get_tracks (timeline);
assert_equals_int (g_list_length (tracks), 2);
for (tmp = tracks; tmp; tmp = tmp->next) {
GList *trackelements;
track = GES_TRACK (tmp->data);
trackelements = ges_track_get_elements (track);
GST_DEBUG_OBJECT (track, "Testing track");
switch (track->type) {
case GES_TRACK_TYPE_VIDEO:
assert_equals_int (g_list_length (trackelements), 2);
for (tmptrackelement = trackelements; tmptrackelement;
tmptrackelement = tmptrackelement->next) {
GESTrackElement *trackelement =
GES_TRACK_ELEMENT (tmptrackelement->data);
if (GES_IS_BASE_EFFECT (trackelement)) {
guint nb_scratch_lines;
ges_timeline_element_get_child_properties (tmptrackelement->data,
"scratch-lines", &nb_scratch_lines, NULL);
assert_equals_int (nb_scratch_lines, 12);
nle_object_check (ges_track_element_get_nleobject (trackelement),
0, 1000000000, 0, 1000000000, MIN_NLE_PRIO + TRANSITIONS_HEIGHT,
TRUE);
} else {
nle_object_check (ges_track_element_get_nleobject (trackelement),
0, 1000000000, 0, 1000000000,
MIN_NLE_PRIO + TRANSITIONS_HEIGHT + 1, TRUE);
}
}
break;
case GES_TRACK_TYPE_AUDIO:
assert_equals_int (g_list_length (trackelements), 2);
break;
default:
g_assert (1);
}
g_list_free_full (trackelements, gst_object_unref);
}
g_list_free_full (tracks, gst_object_unref);
/* Now test the encoding profile */
profiles = ges_project_list_encoding_profiles (project);
assert_equals_int (g_list_length ((GList *) profiles), 1);
profile = profiles->data;
fail_unless (GST_IS_ENCODING_CONTAINER_PROFILE (profile));
profiles = gst_encoding_container_profile_get_profiles (profile);
assert_equals_int (g_list_length ((GList *) profiles), 2);
}
static void
_add_properties (GESTimeline * timeline)
{
GList *tracks;
GList *tmp;
tracks = ges_timeline_get_tracks (timeline);
for (tmp = tracks; tmp; tmp = tmp->next) {
GESTrack *track;
GList *track_elements;
GList *tmp_tck;
track = GES_TRACK (tmp->data);
switch (track->type) {
case GES_TRACK_TYPE_VIDEO:
track_elements = ges_track_get_elements (track);
for (tmp_tck = track_elements; tmp_tck; tmp_tck = tmp_tck->next) {
GESTrackElement *element = GES_TRACK_ELEMENT (tmp_tck->data);
/* Adding keyframes */
if (GES_IS_EFFECT (element)) {
GstControlSource *source;
GstControlBinding *tmp_binding, *binding;
source = gst_interpolation_control_source_new ();
/* Check binding creation and replacement */
binding =
ges_track_element_get_control_binding (element,
"scratch-lines");
fail_unless (binding == NULL);
ges_track_element_set_control_source (element,
source, "scratch-lines", "direct");
tmp_binding =
ges_track_element_get_control_binding (element,
"scratch-lines");
fail_unless (tmp_binding != NULL);
ges_track_element_set_control_source (element,
source, "scratch-lines", "direct");
binding =
ges_track_element_get_control_binding (element,
"scratch-lines");
fail_unless (binding != tmp_binding);
g_object_set (source, "mode", GST_INTERPOLATION_MODE_LINEAR, NULL);
gst_timed_value_control_source_set (GST_TIMED_VALUE_CONTROL_SOURCE
(source), 0 * GST_SECOND, 0.);
gst_timed_value_control_source_set (GST_TIMED_VALUE_CONTROL_SOURCE
(source), 5 * GST_SECOND, 0.);
gst_timed_value_control_source_set (GST_TIMED_VALUE_CONTROL_SOURCE
(source), 10 * GST_SECOND, 1.);
gst_object_unref (source);
} else if (GES_IS_VIDEO_SOURCE (element)) {
/* Adding children properties */
gint64 posx = 42;
ges_timeline_element_set_child_properties (GES_TIMELINE_ELEMENT
(element), "posx", posx, NULL);
ges_timeline_element_get_child_properties (GES_TIMELINE_ELEMENT
(element), "posx", &posx, NULL);
fail_unless_equals_int64 (posx, 42);
}
}
g_list_free_full (track_elements, g_object_unref);
break;
default:
break;
}
}
g_list_free_full (tracks, g_object_unref);
}
static void
_check_properties (GESTimeline * timeline)
{
GList *tracks;
GList *tmp;
tracks = ges_timeline_get_tracks (timeline);
for (tmp = tracks; tmp; tmp = tmp->next) {
GESTrack *track;
GList *track_elements;
GList *tmp_tck;
track = GES_TRACK (tmp->data);
switch (track->type) {
case GES_TRACK_TYPE_VIDEO:
track_elements = ges_track_get_elements (track);
for (tmp_tck = track_elements; tmp_tck; tmp_tck = tmp_tck->next) {
GESTrackElement *element = GES_TRACK_ELEMENT (tmp_tck->data);
/* Checking keyframes */
if (GES_IS_EFFECT (element)) {
GstControlBinding *binding;
GstControlSource *source;
GList *timed_values, *tmpvalue;
GstTimedValue *value;
binding =
ges_track_element_get_control_binding (element,
"scratch-lines");
fail_unless (binding != NULL);
g_object_get (binding, "control-source", &source, NULL);
fail_unless (source != NULL);
/* Now check keyframe position */
tmpvalue = timed_values =
gst_timed_value_control_source_get_all
(GST_TIMED_VALUE_CONTROL_SOURCE (source));
value = tmpvalue->data;
fail_unless (value->value == 0.);
fail_unless (value->timestamp == 0 * GST_SECOND);
tmpvalue = tmpvalue->next;
value = tmpvalue->data;
fail_unless (value->value == 0.);
fail_unless (value->timestamp == 5 * GST_SECOND);
tmpvalue = tmpvalue->next;
value = tmpvalue->data;
fail_unless (value->value == 1.);
fail_unless (value->timestamp == 10 * GST_SECOND);
g_list_free (timed_values);
gst_object_unref (source);
}
/* Checking children properties */
else if (GES_IS_VIDEO_SOURCE (element)) {
/* Init 'posx' with a wrong value */
gint64 posx = 27;
ges_timeline_element_get_child_properties (GES_TIMELINE_ELEMENT
(element), "posx", &posx, NULL);
fail_unless_equals_int64 (posx, 42);
}
}
g_list_free_full (track_elements, g_object_unref);
break;
default:
break;
}
}
g_list_free_full (tracks, g_object_unref);
}
GST_START_TEST (test_project_add_properties)
{
GESProject *project;
GESTimeline *timeline;
gchar *uri;
ges_init ();
uri = ges_test_file_uri ("test-properties.xges");
project = ges_project_new (uri);
g_free (uri);
mainloop = g_main_loop_new (NULL, FALSE);
/* Connect the signals */
g_signal_connect (project, "loaded", (GCallback) project_loaded_cb, mainloop);
g_signal_connect (project, "missing-uri", (GCallback) _set_new_uri, NULL);
/* Now extract a timeline from it */
GST_LOG ("Loading project");
timeline = GES_TIMELINE (ges_asset_extract (GES_ASSET (project), NULL));
g_main_loop_run (mainloop);
GST_LOG ("Test first loading");
_add_properties (timeline);
uri = ges_test_get_tmp_uri ("test-properties-save.xges");
fail_unless (ges_project_save (project, timeline, uri, NULL, TRUE, NULL));
gst_object_unref (timeline);
gst_object_unref (project);
project = ges_project_new (uri);
g_free (uri);
ASSERT_OBJECT_REFCOUNT (project, "Our + cache", 2);
g_signal_connect (project, "loaded", (GCallback) project_loaded_cb, mainloop);
GST_LOG ("Loading saved project");
timeline = GES_TIMELINE (ges_asset_extract (GES_ASSET (project), NULL));
fail_unless (GES_IS_TIMELINE (timeline));
g_main_loop_run (mainloop);
_check_properties (timeline);
gst_object_unref (timeline);
gst_object_unref (project);
g_main_loop_unref (mainloop);
g_signal_handlers_disconnect_by_func (project, (GCallback) project_loaded_cb,
mainloop);
g_signal_handlers_disconnect_by_func (project, (GCallback) asset_added_cb,
NULL);
ges_deinit ();
}
GST_END_TEST;
GST_START_TEST (test_project_load_xges)
{
gboolean saved;
GESProject *loaded_project, *saved_project;
GESTimeline *timeline;
GESAsset *formatter_asset;
gchar *uri;
GList *tmp;
ges_init ();
uri = ges_test_file_uri ("test-project.xges");
loaded_project = ges_project_new (uri);
mainloop = g_main_loop_new (NULL, FALSE);
fail_unless (GES_IS_PROJECT (loaded_project));
/* Connect the signals */
g_signal_connect (loaded_project, "asset-added", (GCallback) asset_added_cb,
NULL);
g_signal_connect (loaded_project, "loaded", (GCallback) project_loaded_cb,
mainloop);
/* Make sure we update the project's dummy URL to some actual URL */
g_signal_connect (loaded_project, "missing-uri", (GCallback) _set_new_uri,
NULL);
/* Now extract a timeline from it */
GST_LOG ("Loading project");
timeline =
GES_TIMELINE (ges_asset_extract (GES_ASSET (loaded_project), NULL));
fail_unless (GES_IS_TIMELINE (timeline));
tmp = ges_project_get_loading_assets (loaded_project);
assert_equals_int (g_list_length (tmp), 1);
g_list_free_full (tmp, g_object_unref);
g_main_loop_run (mainloop);
GST_LOG ("Test first loading");
_test_project (loaded_project, timeline);
g_free (uri);
uri = ges_test_get_tmp_uri ("test-project_TMP.xges");
formatter_asset = ges_asset_request (GES_TYPE_FORMATTER, "ges", NULL);
saved =
ges_project_save (loaded_project, timeline, uri, formatter_asset, TRUE,
NULL);
fail_unless (saved);
gst_object_unref (timeline);
saved_project = ges_project_new (uri);
ASSERT_OBJECT_REFCOUNT (saved_project, "Our + cache", 2);
g_signal_connect (saved_project, "asset-added", (GCallback) asset_added_cb,
NULL);
g_signal_connect (saved_project, "loaded", (GCallback) project_loaded_cb,
mainloop);
GST_LOG ("Loading saved project");
timeline = GES_TIMELINE (ges_asset_extract (GES_ASSET (saved_project), NULL));
fail_unless (GES_IS_TIMELINE (timeline));
g_main_loop_run (mainloop);
_test_project (saved_project, timeline);
fail_unless (ges_meta_container_get_string (GES_META_CONTAINER
(loaded_project), GES_META_FORMAT_VERSION));
fail_unless_equals_string (ges_meta_container_get_string (GES_META_CONTAINER
(loaded_project), GES_META_FORMAT_VERSION),
ges_meta_container_get_string (GES_META_CONTAINER (loaded_project),
GES_META_FORMAT_VERSION));
gst_object_unref (timeline);
gst_object_unref (saved_project);
gst_object_unref (loaded_project);
g_free (uri);
ASSERT_OBJECT_REFCOUNT (saved_project, "Still 1 ref for asset cache", 1);
g_main_loop_unref (mainloop);
g_signal_handlers_disconnect_by_func (saved_project,
(GCallback) project_loaded_cb, mainloop);
g_signal_handlers_disconnect_by_func (saved_project,
(GCallback) asset_added_cb, NULL);
ges_deinit ();
}
GST_END_TEST;
GST_START_TEST (test_project_auto_transition)
{
GList *layers, *tmp;
GESProject *project;
GESTimeline *timeline;
GESLayer *layer = NULL;
GESAsset *formatter_asset;
gboolean saved;
gchar *tmpuri, *uri;
ges_init ();
uri = ges_test_file_uri ("test-auto-transition.xges");
project = ges_project_new (uri);
mainloop = g_main_loop_new (NULL, FALSE);
fail_unless (GES_IS_PROJECT (project));
/* Connect the signals */
g_signal_connect (project, "loaded", (GCallback) project_loaded_cb, mainloop);
g_signal_connect (project, "missing-uri", (GCallback) _set_new_uri, NULL);
/* Now extract a timeline from it */
GST_LOG ("Loading project");
timeline = GES_TIMELINE (ges_asset_extract (GES_ASSET (project), NULL));
g_main_loop_run (mainloop);
/* Check timeline and layers auto-transition, must be FALSE */
fail_if (ges_timeline_get_auto_transition (timeline));
layers = ges_timeline_get_layers (timeline);
for (tmp = layers; tmp; tmp = tmp->next) {
layer = tmp->data;
fail_if (ges_layer_get_auto_transition (layer));
}
g_list_free_full (layers, gst_object_unref);
g_free (uri);
/* Set timeline and layers auto-transition to TRUE */
ges_timeline_set_auto_transition (timeline, TRUE);
tmpuri = ges_test_get_tmp_uri ("test-auto-transition-save.xges");
formatter_asset = ges_asset_request (GES_TYPE_FORMATTER, "ges", NULL);
saved =
ges_project_save (project, timeline, tmpuri, formatter_asset, TRUE, NULL);
fail_unless (saved);
gst_object_unref (timeline);
gst_object_unref (project);
project = ges_project_new (tmpuri);
ASSERT_OBJECT_REFCOUNT (project, "Our + cache", 2);
g_signal_connect (project, "loaded", (GCallback) project_loaded_cb, mainloop);
GST_LOG ("Loading saved project");
timeline = GES_TIMELINE (ges_asset_extract (GES_ASSET (project), NULL));
fail_unless (GES_IS_TIMELINE (timeline));
g_main_loop_run (mainloop);
/* Check timeline and layers auto-transition, must be TRUE */
fail_unless (ges_timeline_get_auto_transition (timeline));
layers = ges_timeline_get_layers (timeline);
for (tmp = layers; tmp; tmp = tmp->next) {
layer = tmp->data;
fail_unless (ges_layer_get_auto_transition (layer));
}
g_list_free_full (layers, gst_object_unref);
gst_object_unref (timeline);
gst_object_unref (project);
g_free (tmpuri);
g_main_loop_unref (mainloop);
g_signal_handlers_disconnect_by_func (project, (GCallback) project_loaded_cb,
mainloop);
g_signal_handlers_disconnect_by_func (project, (GCallback) asset_added_cb,
NULL);
ges_deinit ();
}
GST_END_TEST;
/* FIXME This test does not pass for some bad reason */
#if 0
static void
project_loaded_now_play_cb (GESProject * project, GESTimeline * timeline)
{
GstBus *bus;
GstMessage *message;
gboolean carry_on = TRUE;
GESPipeline *pipeline = ges_pipeline_new ();
fail_unless (ges_pipeline_set_timeline (pipeline, timeline));
bus = gst_element_get_bus (GST_ELEMENT (pipeline));
fail_if (gst_element_set_state (GST_ELEMENT (pipeline),
GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE);
GST_DEBUG ("Let's poll the bus");
while (carry_on) {
message = gst_bus_poll (bus, GST_MESSAGE_ANY, GST_SECOND / 10);
if (message) {
GST_ERROR ("GOT MESSAGE: %" GST_PTR_FORMAT, message);
switch (GST_MESSAGE_TYPE (message)) {
case GST_MESSAGE_EOS:
/* we should check if we really finished here */
GST_WARNING ("Got an EOS, we did not even start!");
carry_on = FALSE;
fail_if (TRUE);
break;
case GST_MESSAGE_SEGMENT_START:
case GST_MESSAGE_SEGMENT_DONE:
/* We shouldn't see any segement messages, since we didn't do a segment seek */
GST_WARNING ("Saw a Segment start/stop");
fail_if (TRUE);
break;
case GST_MESSAGE_ERROR:
fail_error_message (message);
break;
case GST_MESSAGE_ASYNC_DONE:
GST_DEBUG ("prerolling done");
carry_on = FALSE;
break;
default:
break;
}
gst_mini_object_unref (GST_MINI_OBJECT (message));
}
}
fail_if (gst_element_set_state (GST_ELEMENT (pipeline),
GST_STATE_READY) == GST_STATE_CHANGE_FAILURE);
gst_object_unref (pipeline);
g_main_loop_quit (mainloop);
}
GST_START_TEST (test_load_xges_and_play)
{
GESProject *project;
GESTimeline *timeline;
gchar *uri = ges_test_file_uri ("test-project_TMP.xges");
project = ges_project_new (uri);
fail_unless (GES_IS_PROJECT (project));
mainloop = g_main_loop_new (NULL, FALSE);
/* Connect the signals */
g_signal_connect (project, "loaded", (GCallback) project_loaded_now_play_cb,
NULL);
/* Now extract a timeline from it */
timeline = GES_TIMELINE (ges_asset_extract (GES_ASSET (project), NULL));
fail_unless (GES_IS_TIMELINE (timeline));
g_main_loop_run (mainloop);
g_free (uri);
gst_object_unref (project);
gst_object_unref (timeline);
g_main_loop_unref (mainloop);
}
GST_END_TEST;
#endif
static Suite *
ges_suite (void)
{
Suite *s = suite_create ("ges-project");
TCase *tc_chain = tcase_create ("project");
suite_add_tcase (s, tc_chain);
tcase_add_test (tc_chain, test_project_simple);
tcase_add_test (tc_chain, test_project_add_assets);
tcase_add_test (tc_chain, test_project_load_xges);
tcase_add_test (tc_chain, test_project_add_properties);
tcase_add_test (tc_chain, test_project_auto_transition);
/*tcase_add_test (tc_chain, test_load_xges_and_play); */
tcase_add_test (tc_chain, test_project_unexistant_effect);
return s;
}
GST_CHECK_MAIN (ges);