From 6446cc4ae941775475d794928ebe5fe2b4c52600 Mon Sep 17 00:00:00 2001 From: Robert Swain Date: Thu, 29 Sep 2011 16:22:00 +0200 Subject: [PATCH 01/10] camerabin2: Fix potential loss of EOS event Setting the audio source to NULL just after pushing the EOS event on it could potentially cause loss of said EOS event. Instead, we can set the audio source to NULL when ready-for-capture is signalled and the boolean value is true as this indicates we are not currently capturing video. --- gst/camerabin2/gstcamerabin2.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index 5a227138e2..e990a95084 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -447,14 +447,6 @@ gst_camera_bin_stop_capture (GstCameraBin2 * camerabin) if (camerabin->mode == MODE_VIDEO && camerabin->audio_src) { camerabin->audio_drop_eos = FALSE; gst_element_send_event (camerabin->audio_src, gst_event_new_eos ()); - - /* FIXME We need to set audiosrc to null to make it resync the ringbuffer - * while bug https://bugzilla.gnome.org/show_bug.cgi?id=648359 isn't - * fixed. - * - * Also, we set to NULL here to stop capturing audio through to the next - * video mode start capture. */ - gst_element_set_state (camerabin->audio_src, GST_STATE_NULL); } } @@ -503,7 +495,16 @@ gst_camera_bin_src_notify_readyforcapture (GObject * obj, GParamSpec * pspec, gst_element_set_state (camera->video_encodebin, GST_STATE_PLAYING); gst_element_set_state (camera->videobin_capsfilter, GST_STATE_PLAYING); } - + } else { + if (camera->mode == MODE_VIDEO && camera->audio_src) { + /* FIXME We need to set audiosrc to null to make it resync the ringbuffer + * while bug https://bugzilla.gnome.org/show_bug.cgi?id=648359 isn't + * fixed. + * + * Also, we set to NULL here to stop capturing audio through to the next + * video mode start capture and to clear EOS. */ + gst_element_set_state (camera->audio_src, GST_STATE_NULL); + } } } From b03c7478d4df98ebcc3c1a53dfc2caaac0b52a34 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Tue, 27 Sep 2011 13:04:21 -0300 Subject: [PATCH 02/10] camerabin2: removing capsfilter from preview pipeline appsink already has a caps property, so we don't need the capsfilter here --- gst-libs/gst/basecamerabinsrc/gstcamerabinpreview.c | 13 +++---------- gst-libs/gst/basecamerabinsrc/gstcamerabinpreview.h | 1 - 2 files changed, 3 insertions(+), 11 deletions(-) diff --git a/gst-libs/gst/basecamerabinsrc/gstcamerabinpreview.c b/gst-libs/gst/basecamerabinsrc/gstcamerabinpreview.c index be42c98dc1..c221ed9e2a 100644 --- a/gst-libs/gst/basecamerabinsrc/gstcamerabinpreview.c +++ b/gst-libs/gst/basecamerabinsrc/gstcamerabinpreview.c @@ -135,13 +135,11 @@ gst_camerabin_create_preview_pipeline (GstElement * element, data->pipeline = gst_pipeline_new ("preview-pipeline"); data->appsrc = gst_element_factory_make ("appsrc", "preview-appsrc"); - data->capsfilter = gst_element_factory_make ("capsfilter", - "preview-capsfilter"); data->appsink = gst_element_factory_make ("appsink", "preview-appsink"); csp = gst_element_factory_make ("ffmpegcolorspace", "preview-csp"); vscale = gst_element_factory_make ("videoscale", "preview-vscale"); - if (!data->appsrc || !data->capsfilter || !data->appsink || !csp || !vscale) { + if (!data->appsrc || !data->appsink || !csp || !vscale) { goto error; } @@ -149,7 +147,7 @@ gst_camerabin_create_preview_pipeline (GstElement * element, g_object_set (data->appsink, "sync", FALSE, "enable-last-buffer", FALSE, NULL); - gst_bin_add_many (GST_BIN (data->pipeline), data->appsrc, data->capsfilter, + gst_bin_add_many (GST_BIN (data->pipeline), data->appsrc, data->appsink, csp, vscale, NULL); if (filter) gst_bin_add (GST_BIN (data->pipeline), gst_object_ref (filter)); @@ -173,9 +171,6 @@ gst_camerabin_create_preview_pipeline (GstElement * element, "sink", GST_PAD_LINK_CHECK_NOTHING)); linkfail |= GST_PAD_LINK_FAILED (gst_element_link_pads_full (csp, "src", - data->capsfilter, "sink", GST_PAD_LINK_CHECK_NOTHING)); - linkfail |= - GST_PAD_LINK_FAILED (gst_element_link_pads_full (data->capsfilter, "src", data->appsink, "sink", GST_PAD_LINK_CHECK_NOTHING)); if (linkfail) { @@ -212,8 +207,6 @@ error: gst_object_unref (vscale); if (data->appsrc) gst_object_unref (data->appsrc); - if (data->capsfilter) - gst_object_unref (data->capsfilter); if (data->appsink) gst_object_unref (data->appsink); } @@ -304,7 +297,7 @@ _gst_camerabin_preview_set_caps (GstCameraBinPreviewPipelineData * preview, pending = GST_STATE_VOID_PENDING; } gst_element_set_state (preview->pipeline, GST_STATE_NULL); - g_object_set (preview->capsfilter, "caps", caps, NULL); + g_object_set (preview->appsink, "caps", caps, NULL); if (pending != GST_STATE_VOID_PENDING) state = pending; gst_element_set_state (preview->pipeline, state); diff --git a/gst-libs/gst/basecamerabinsrc/gstcamerabinpreview.h b/gst-libs/gst/basecamerabinsrc/gstcamerabinpreview.h index ff5bc719e3..ef9cd96670 100644 --- a/gst-libs/gst/basecamerabinsrc/gstcamerabinpreview.h +++ b/gst-libs/gst/basecamerabinsrc/gstcamerabinpreview.h @@ -35,7 +35,6 @@ typedef struct GstElement *appsrc; GstElement *filter; - GstElement *capsfilter; GstElement *appsink; GstElement *element; From 379670e036e91c6f1e44051f8d5d1ab01a7faf19 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Thu, 29 Sep 2011 18:03:25 -0300 Subject: [PATCH 03/10] camerabin2: add location to preview image messages Makes camerabin2 intercept preview-image messages and add the filename corresponding to the message structure in the 'location' field. Makes easier for applications to track preview images --- gst/camerabin2/gstcamerabin2.c | 44 +++++++++++++++++++++++++++------- gst/camerabin2/gstcamerabin2.h | 3 +++ 2 files changed, 38 insertions(+), 9 deletions(-) diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index e990a95084..a91f109c76 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -363,7 +363,8 @@ static void gst_camera_bin_start_capture (GstCameraBin2 * camerabin) { const GstTagList *taglist; - + gint capture_index = camerabin->capture_index; + gchar *location = NULL; GST_DEBUG_OBJECT (camerabin, "Received start-capture"); /* check that we have a valid location */ @@ -376,6 +377,9 @@ gst_camera_bin_start_capture (GstCameraBin2 * camerabin) GST_CAMERA_BIN2_PROCESSING_INC (camerabin); + if (camerabin->location) + location = g_strdup_printf (camerabin->location, capture_index); + if (camerabin->mode == MODE_VIDEO) { if (camerabin->audio_src) { GstClock *clock = gst_pipeline_get_clock (GST_PIPELINE_CAST (camerabin)); @@ -396,16 +400,15 @@ gst_camera_bin_start_capture (GstCameraBin2 * camerabin) } } } else { - gchar *location = NULL; - /* store the next capture buffer filename */ - if (camerabin->location) - location = - g_strdup_printf (camerabin->location, camerabin->capture_index++); camerabin->image_location_list = - g_slist_append (camerabin->image_location_list, location); + g_slist_append (camerabin->image_location_list, g_strdup (location)); } + /* store the next preview filename */ + camerabin->preview_location_list = + g_slist_append (camerabin->preview_location_list, location); + g_signal_emit_by_name (camerabin->src, "start-capture", NULL); if (camerabin->mode == MODE_VIDEO && camerabin->audio_src) gst_element_set_state (camerabin->audio_src, GST_STATE_PLAYING); @@ -434,7 +437,6 @@ gst_camera_bin_start_capture (GstCameraBin2 * camerabin) gst_event_new_tag (gst_tag_list_copy (taglist))); gst_object_unref (active_pad); } - } static void @@ -482,7 +484,7 @@ gst_camera_bin_src_notify_readyforcapture (GObject * obj, GParamSpec * pspec, gst_element_set_state (camera->videosink, GST_STATE_NULL); gst_element_set_state (camera->video_encodebin, GST_STATE_NULL); gst_element_set_state (camera->videobin_capsfilter, GST_STATE_NULL); - location = g_strdup_printf (camera->location, camera->capture_index++); + location = g_strdup_printf (camera->location, camera->capture_index); GST_DEBUG_OBJECT (camera, "Switching videobin location to %s", location); g_object_set (camera->videosink, "location", location, NULL); g_free (location); @@ -495,6 +497,8 @@ gst_camera_bin_src_notify_readyforcapture (GObject * obj, GParamSpec * pspec, gst_element_set_state (camera->video_encodebin, GST_STATE_PLAYING); gst_element_set_state (camera->videobin_capsfilter, GST_STATE_PLAYING); } + + camera->capture_index++; } else { if (camera->mode == MODE_VIDEO && camera->audio_src) { /* FIXME We need to set audiosrc to null to make it resync the ringbuffer @@ -923,6 +927,8 @@ gst_video_capture_bin_post_video_done (GstCameraBin2 * camera) static void gst_camera_bin_handle_message (GstBin * bin, GstMessage * message) { + GstCameraBin2 *camerabin = GST_CAMERA_BIN2_CAST (bin); + switch (GST_MESSAGE_TYPE (message)) { case GST_MESSAGE_ELEMENT:{ const GstStructure *structure = gst_message_get_structure (message); @@ -937,6 +943,22 @@ gst_camera_bin_handle_message (GstBin * bin, GstMessage * message) gst_image_capture_bin_post_image_done (GST_CAMERA_BIN2_CAST (bin), filename); } + } else if (gst_structure_has_name (structure, "preview-image")) { + GValue *value; + gchar *location; + + location = camerabin->preview_location_list->data; + camerabin->preview_location_list = + g_slist_delete_link (camerabin->preview_location_list, + camerabin->preview_location_list); + GST_DEBUG_OBJECT (camerabin, "Adding preview location to preview " + "message '%s'", location); + + value = g_new0 (GValue, 1); + g_value_init (value, G_TYPE_STRING); + g_value_take_string (value, location); + gst_structure_take_value ((GstStructure *) structure, "location", + value); } } break; @@ -1703,6 +1725,10 @@ gst_camera_bin_change_state (GstElement * element, GstStateChange trans) g_slist_free (camera->image_location_list); camera->image_location_list = NULL; + g_slist_foreach (camera->preview_location_list, (GFunc) g_free, NULL); + g_slist_free (camera->preview_location_list); + camera->preview_location_list = NULL; + /* explicitly set to READY as they might be outside of the bin */ gst_element_set_state (camera->audio_volume, GST_STATE_READY); gst_element_set_state (camera->audio_capsfilter, GST_STATE_READY); diff --git a/gst/camerabin2/gstcamerabin2.h b/gst/camerabin2/gstcamerabin2.h index 46113d0372..05af34f4de 100644 --- a/gst/camerabin2/gstcamerabin2.h +++ b/gst/camerabin2/gstcamerabin2.h @@ -94,6 +94,9 @@ struct _GstCameraBin2 * each buffer capture */ GSList *image_location_list; + /* similar to above, but used for giving names to previews */ + GSList *preview_location_list; + gboolean video_profile_switch; gboolean image_profile_switch; From f6c0e2cd265dc1e9d0652cde7e1c4cd000287a19 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Thu, 29 Sep 2011 13:03:08 -0300 Subject: [PATCH 04/10] tests: camerabin2: adding tests to check for preview message filenames Preview messages now have filenames, add tests to check that they are correct --- tests/check/elements/camerabin2.c | 84 ++++++++++++++++++++----------- 1 file changed, 54 insertions(+), 30 deletions(-) diff --git a/tests/check/elements/camerabin2.c b/tests/check/elements/camerabin2.c index e824f29562..6e353bb4a7 100644 --- a/tests/check/elements/camerabin2.c +++ b/tests/check/elements/camerabin2.c @@ -166,8 +166,11 @@ static guint bus_source; static GMainLoop *main_loop; static gint capture_count = 0; guint32 test_id = 0; +static const gchar *image_filename; +static const gchar *video_filename; static GstBuffer *preview_buffer; +static gchar *preview_filename; static GstCaps *preview_caps; static GstTagList *tags_found; @@ -275,6 +278,8 @@ capture_bus_cb (GstBus * bus, GstMessage * message, gpointer data) if (preview_buffer) gst_buffer_unref (preview_buffer); preview_buffer = gst_buffer_ref (buf); + g_free (preview_filename); + preview_filename = g_strdup (gst_structure_get_string (st, "location")); } break; } @@ -282,8 +287,10 @@ capture_bus_cb (GstBus * bus, GstMessage * message, gpointer data) } static void -check_preview_image (GstElement * camera) +check_preview_image (GstElement * camera, const gchar * filename, gint index) { + gchar *prev_filename = NULL; + if (!preview_buffer && camera) { GstMessage *msg = wait_for_element_message (camera, GST_BASE_CAMERA_SRC_PREVIEW_MESSAGE_NAME, GST_CLOCK_TIME_NONE); @@ -291,11 +298,21 @@ check_preview_image (GstElement * camera) gst_message_unref (msg); } fail_unless (preview_buffer != NULL); + if (filename) { + if (index >= 0) { + prev_filename = g_strdup_printf (filename, index); + } else { + prev_filename = g_strdup (filename); + } + fail_unless (preview_filename != NULL); + fail_unless (strcmp (preview_filename, prev_filename) == 0); + } if (preview_caps) { fail_unless (GST_BUFFER_CAPS (preview_buffer) != NULL); fail_unless (gst_caps_can_intersect (GST_BUFFER_CAPS (preview_buffer), preview_caps)); } + g_free (prev_filename); } static void @@ -371,6 +388,8 @@ setup_wrappercamerabinsrc_videotestsrc (void) tags_found = NULL; capture_count = 0; + image_filename = make_test_file_name (IMAGE_FILENAME, -1); + video_filename = make_test_file_name (VIDEO_FILENAME, -1); GST_INFO ("init finished"); } @@ -399,6 +418,9 @@ teardown (void) gst_buffer_unref (preview_buffer); preview_buffer = NULL; + g_free (preview_filename); + preview_filename = NULL; + if (tags_found) gst_tag_list_free (tags_found); tags_found = NULL; @@ -569,6 +591,9 @@ wait_for_element_message (GstElement * camera, const gchar * name, if (preview_buffer) gst_buffer_unref (preview_buffer); preview_buffer = gst_buffer_ref (buf); + g_free (preview_filename); + preview_filename = + g_strdup (gst_structure_get_string (st, "location")); } if (gst_structure_has_name (st, name)) @@ -593,8 +618,7 @@ GST_START_TEST (test_single_image_capture) return; /* set still image mode */ - g_object_set (camera, "mode", 1, - "location", make_test_file_name (IMAGE_FILENAME, -1), NULL); + g_object_set (camera, "mode", 1, "location", image_filename, NULL); if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { @@ -614,7 +638,7 @@ GST_START_TEST (test_single_image_capture) gst_message_unref (msg); /* check that we got a preview image */ - check_preview_image (camera); + check_preview_image (camera, image_filename, 0); g_object_get (camera, "idle", &idle, NULL); fail_unless (idle); @@ -636,8 +660,7 @@ GST_START_TEST (test_multiple_image_captures) return; /* set still image mode */ - g_object_set (camera, "mode", 1, - "location", make_test_file_name (IMAGE_FILENAME, -1), NULL); + g_object_set (camera, "mode", 1, "location", image_filename, NULL); if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { @@ -667,7 +690,7 @@ GST_START_TEST (test_multiple_image_captures) fail_unless (msg != NULL); gst_message_unref (msg); - check_preview_image (camera); + check_preview_image (camera, image_filename, i); } g_object_get (camera, "idle", &idle, NULL); @@ -689,8 +712,7 @@ GST_START_TEST (test_single_video_recording) return; /* Set video recording mode */ - g_object_set (camera, "mode", 2, - "location", make_test_file_name (VIDEO_FILENAME, -1), NULL); + g_object_set (camera, "mode", 2, "location", video_filename, NULL); if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { @@ -716,7 +738,7 @@ GST_START_TEST (test_single_video_recording) g_signal_emit_by_name (camera, "stop-capture", NULL); - check_preview_image (camera); + check_preview_image (camera, video_filename, 0); msg = wait_for_element_message (camera, "video-done", GST_CLOCK_TIME_NONE); fail_unless (msg != NULL); @@ -743,7 +765,7 @@ GST_START_TEST (test_multiple_video_recordings) return; /* Set video recording mode */ - g_object_set (camera, "mode", 2, NULL); + g_object_set (camera, "mode", 2, "location", video_filename, NULL); if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { @@ -765,8 +787,7 @@ GST_START_TEST (test_multiple_video_recordings) widths[i], "height", G_TYPE_INT, heights[i], "framerate", GST_TYPE_FRACTION, fr[i], 1, NULL); - g_object_set (camera, "video-capture-caps", caps, - "location", make_test_file_name (VIDEO_FILENAME, i), NULL); + g_object_set (camera, "video-capture-caps", caps, NULL); gst_caps_unref (caps); @@ -784,7 +805,7 @@ GST_START_TEST (test_multiple_video_recordings) fail_unless (msg != NULL); gst_message_unref (msg); - check_preview_image (camera); + check_preview_image (camera, video_filename, i); g_object_get (camera, "idle", &idle, NULL); fail_unless (idle); @@ -818,25 +839,30 @@ GST_START_TEST (test_image_video_cycle) GST_INFO ("starting capture"); for (i = 0; i < 2; i++) { GstMessage *msg; + const gchar *img_filename; + const gchar *vid_filename; + g_object_get (camera, "idle", &idle, NULL); fail_unless (idle); + img_filename = make_test_file_name (IMAGE_FILENAME, i); + vid_filename = make_test_file_name (VIDEO_FILENAME, i); + /* take a picture */ g_object_set (camera, "mode", 1, NULL); - g_object_set (camera, "location", make_test_file_name (IMAGE_FILENAME, i), - NULL); + g_object_set (camera, "location", img_filename, NULL); g_signal_emit_by_name (camera, "start-capture", NULL); msg = wait_for_element_message (camera, "image-done", GST_CLOCK_TIME_NONE); fail_unless (msg != NULL); gst_message_unref (msg); - check_preview_image (camera); + check_preview_image (camera, img_filename, i); /* now go to video */ g_object_set (camera, "mode", 2, NULL); - g_object_set (camera, "location", make_test_file_name (VIDEO_FILENAME, i), - NULL); + g_object_set (camera, "location", vid_filename, NULL); + g_signal_emit_by_name (camera, "start-capture", NULL); g_timeout_add_seconds (VIDEO_DURATION, (GSourceFunc) g_main_loop_quit, main_loop); @@ -847,7 +873,7 @@ GST_START_TEST (test_image_video_cycle) fail_unless (msg != NULL); gst_message_unref (msg); - check_preview_image (camera); + check_preview_image (camera, vid_filename, i); /* wait for capture to finish */ g_usleep (G_USEC_PER_SEC); @@ -874,8 +900,7 @@ GST_START_TEST (test_image_capture_previews) return; /* set still image mode */ - g_object_set (camera, "mode", 1, - "location", make_test_file_name (IMAGE_FILENAME, -1), NULL); + g_object_set (camera, "mode", 1, "location", image_filename, NULL); if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { @@ -904,7 +929,7 @@ GST_START_TEST (test_image_capture_previews) fail_unless (msg != NULL); gst_message_unref (msg); - check_preview_image (camera); + check_preview_image (camera, image_filename, i); if (preview_buffer) gst_buffer_unref (preview_buffer); @@ -1123,8 +1148,7 @@ GST_START_TEST (test_idle_property) return; /* Set video recording mode */ - g_object_set (camera, "mode", 2, - "location", make_test_file_name (VIDEO_FILENAME, -1), NULL); + g_object_set (camera, "mode", 2, "location", video_filename, NULL); if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { @@ -1158,7 +1182,7 @@ GST_START_TEST (test_idle_property) fail_unless (msg != NULL); gst_message_unref (msg); - check_preview_image (camera); + check_preview_image (camera, video_filename, 0); g_object_get (camera, "idle", &idle, NULL); fail_unless (idle); @@ -1205,7 +1229,7 @@ GST_START_TEST (test_image_custom_filter) /* set still image mode and filters */ g_object_set (camera, "mode", 1, - "location", make_test_file_name (IMAGE_FILENAME, -1), + "location", image_filename, "viewfinder-filter", vf_filter, "image-filter", image_filter, "preview-filter", preview_filter, NULL); @@ -1228,7 +1252,7 @@ GST_START_TEST (test_image_custom_filter) g_main_loop_run (main_loop); /* check that we got a preview image */ - check_preview_image (camera); + check_preview_image (camera, image_filename, 0); gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); check_file_validity (IMAGE_FILENAME, 0, NULL, 0, 0, NO_AUDIO); @@ -1283,7 +1307,7 @@ GST_START_TEST (test_video_custom_filter) /* set still image mode and filters */ g_object_set (camera, "mode", 2, - "location", make_test_file_name (VIDEO_FILENAME, -1), + "location", video_filename, "viewfinder-filter", vf_filter, "video-filter", video_filter, "preview-filter", preview_filter, "audio-filter", audio_filter, NULL); @@ -1309,7 +1333,7 @@ GST_START_TEST (test_video_custom_filter) g_signal_emit_by_name (camera, "stop-capture", NULL); /* check that we got a preview image */ - check_preview_image (camera); + check_preview_image (camera, video_filename, 0); gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); check_file_validity (VIDEO_FILENAME, 0, NULL, 0, 0, WITH_AUDIO); From 009c440f44bb7f7d8188d948cf65dd4f89c154bc Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Thu, 29 Sep 2011 18:20:44 -0300 Subject: [PATCH 05/10] tests: camerabin2: Refactor tests a little Refactor camerabin2 tests a little --- tests/check/elements/camerabin2.c | 78 +++++++++++++++++-------------- 1 file changed, 43 insertions(+), 35 deletions(-) diff --git a/tests/check/elements/camerabin2.c b/tests/check/elements/camerabin2.c index 6e353bb4a7..2c1bbb1dbe 100644 --- a/tests/check/elements/camerabin2.c +++ b/tests/check/elements/camerabin2.c @@ -166,8 +166,8 @@ static guint bus_source; static GMainLoop *main_loop; static gint capture_count = 0; guint32 test_id = 0; -static const gchar *image_filename; -static const gchar *video_filename; +static gchar *image_filename; +static gchar *video_filename; static GstBuffer *preview_buffer; static gchar *preview_filename; @@ -199,24 +199,31 @@ validate_taglist_foreach (const GstTagList * list, const gchar * tag, /* helper function for filenames */ -static const gchar * +static gchar * make_test_file_name (const gchar * base_name, gint num) +{ + /* num == -1 means to keep the %d in the resulting string to be used on + * multifilesink like location */ + if (num == -1) { + return g_strdup_printf ("%s" G_DIR_SEPARATOR_S + "gstcamerabin2test_%s_%u_%%03d.cap", g_get_tmp_dir (), base_name, + test_id); + } else { + return g_strdup_printf ("%s" G_DIR_SEPARATOR_S + "gstcamerabin2test_%s_%u_%03d.cap", g_get_tmp_dir (), base_name, + test_id, num); + } +} + +static const gchar * +make_const_file_name (const gchar * filename, gint num) { static gchar file_name[1000]; /* num == -1 means to keep the %d in the resulting string to be used on * multifilesink like location */ - if (num == -1) { - g_snprintf (file_name, 999, "%s" G_DIR_SEPARATOR_S - "gstcamerabin2test_%s_%u_%%03d.cap", g_get_tmp_dir (), base_name, - test_id); - } else { - g_snprintf (file_name, 999, "%s" G_DIR_SEPARATOR_S - "gstcamerabin2test_%s_%u_%03d.cap", g_get_tmp_dir (), base_name, - test_id, num); - } + g_snprintf (file_name, 999, filename, num); - GST_INFO ("capturing to: %s", file_name); return file_name; } @@ -320,7 +327,7 @@ extract_jpeg_tags (const gchar * filename, gint num) { GstBus *bus; GMainLoop *loop = g_main_loop_new (NULL, FALSE); - const gchar *filepath = make_test_file_name (filename, num); + const gchar *filepath = make_const_file_name (filename, num); gchar *pipeline_str = g_strdup_printf ("filesrc location=%s ! " "jpegparse ! fakesink", filepath); GstElement *pipeline; @@ -425,6 +432,11 @@ teardown (void) gst_tag_list_free (tags_found); tags_found = NULL; + g_free (video_filename); + g_free (image_filename); + video_filename = NULL; + image_filename = NULL; + GST_INFO ("done"); } @@ -497,7 +509,7 @@ check_file_validity (const gchar * filename, gint num, GstTagList * taglist, GstElement *playbin = gst_element_factory_make ("playbin2", NULL); GstElement *fakevideo = gst_element_factory_make ("fakesink", NULL); GstElement *fakeaudio = gst_element_factory_make ("fakesink", NULL); - gchar *uri = g_strconcat ("file://", make_test_file_name (filename, num), + gchar *uri = g_strconcat ("file://", make_const_file_name (filename, num), NULL); GST_DEBUG ("checking uri: %s", uri); @@ -643,7 +655,7 @@ GST_START_TEST (test_single_image_capture) g_object_get (camera, "idle", &idle, NULL); fail_unless (idle); gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); - check_file_validity (IMAGE_FILENAME, 0, NULL, 0, 0, NO_AUDIO); + check_file_validity (image_filename, 0, NULL, 0, 0, NO_AUDIO); } GST_END_TEST; @@ -697,7 +709,7 @@ GST_START_TEST (test_multiple_image_captures) fail_unless (idle); gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); for (i = 0; i < 3; i++) { - check_file_validity (IMAGE_FILENAME, i, NULL, widths[i], heights[i], + check_file_validity (image_filename, i, NULL, widths[i], heights[i], NO_AUDIO); } } @@ -748,7 +760,7 @@ GST_START_TEST (test_single_video_recording) fail_unless (idle); gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); - check_file_validity (VIDEO_FILENAME, 0, NULL, 0, 0, WITH_AUDIO); + check_file_validity (video_filename, 0, NULL, 0, 0, WITH_AUDIO); } GST_END_TEST; @@ -813,7 +825,7 @@ GST_START_TEST (test_multiple_video_recordings) gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); for (i = 0; i < 3; i++) { - check_file_validity (VIDEO_FILENAME, i, NULL, widths[i], heights[i], + check_file_validity (video_filename, i, NULL, widths[i], heights[i], WITH_AUDIO); } } @@ -845,10 +857,8 @@ GST_START_TEST (test_image_video_cycle) g_object_get (camera, "idle", &idle, NULL); fail_unless (idle); - img_filename = make_test_file_name (IMAGE_FILENAME, i); - vid_filename = make_test_file_name (VIDEO_FILENAME, i); - /* take a picture */ + img_filename = make_const_file_name (image_filename, i); g_object_set (camera, "mode", 1, NULL); g_object_set (camera, "location", img_filename, NULL); g_signal_emit_by_name (camera, "start-capture", NULL); @@ -860,6 +870,7 @@ GST_START_TEST (test_image_video_cycle) check_preview_image (camera, img_filename, i); /* now go to video */ + vid_filename = make_const_file_name (video_filename, i); g_object_set (camera, "mode", 2, NULL); g_object_set (camera, "location", vid_filename, NULL); @@ -882,8 +893,8 @@ GST_START_TEST (test_image_video_cycle) /* validate all the files */ for (i = 0; i < 2; i++) { - check_file_validity (IMAGE_FILENAME, i, NULL, 0, 0, NO_AUDIO); - check_file_validity (VIDEO_FILENAME, i, NULL, 0, 0, WITH_AUDIO); + check_file_validity (image_filename, i, NULL, 0, 0, NO_AUDIO); + check_file_validity (video_filename, i, NULL, 0, 0, WITH_AUDIO); } } @@ -980,8 +991,7 @@ GST_START_TEST (test_image_capture_with_tags) GST_TAG_GEO_LOCATION_ELEVATION, 0.0, NULL); /* set still image mode */ - g_object_set (camera, "mode", 1, - "location", make_test_file_name (IMAGE_FILENAME, -1), NULL); + g_object_set (camera, "mode", 1, "location", image_filename, NULL); if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { @@ -1008,7 +1018,7 @@ GST_START_TEST (test_image_capture_with_tags) gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); for (i = 0; i < 3; i++) { - check_file_validity (IMAGE_FILENAME, i, taglists[i], 0, 0, NO_AUDIO); + check_file_validity (image_filename, i, taglists[i], 0, 0, NO_AUDIO); gst_tag_list_free (taglists[i]); } } @@ -1029,8 +1039,7 @@ GST_START_TEST (test_video_capture_with_tags) taglists[2] = gst_tag_list_new_full (GST_TAG_COMMENT, "test3", NULL); /* set video mode */ - g_object_set (camera, "mode", 2, - "location", make_test_file_name (VIDEO_FILENAME, -1), NULL); + g_object_set (camera, "mode", 2, "location", video_filename, NULL); /* set a profile that has xmp support for more tags being saved */ { @@ -1086,7 +1095,7 @@ GST_START_TEST (test_video_capture_with_tags) gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); for (i = 0; i < 3; i++) { - check_file_validity (VIDEO_FILENAME, i, taglists[i], 0, 0, NO_AUDIO); + check_file_validity (video_filename, i, taglists[i], 0, 0, NO_AUDIO); gst_tag_list_free (taglists[i]); } } @@ -1189,7 +1198,7 @@ GST_START_TEST (test_idle_property) gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); - check_file_validity (VIDEO_FILENAME, 0, NULL, 0, 0, WITH_AUDIO); + check_file_validity (video_filename, 0, NULL, 0, 0, WITH_AUDIO); } GST_END_TEST; @@ -1255,7 +1264,7 @@ GST_START_TEST (test_image_custom_filter) check_preview_image (camera, image_filename, 0); gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); - check_file_validity (IMAGE_FILENAME, 0, NULL, 0, 0, NO_AUDIO); + check_file_validity (image_filename, 0, NULL, 0, 0, NO_AUDIO); fail_unless (vf_probe_counter > 0); fail_unless (image_probe_counter == 1); @@ -1336,7 +1345,7 @@ GST_START_TEST (test_video_custom_filter) check_preview_image (camera, video_filename, 0); gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); - check_file_validity (VIDEO_FILENAME, 0, NULL, 0, 0, WITH_AUDIO); + check_file_validity (video_filename, 0, NULL, 0, 0, WITH_AUDIO); fail_unless (vf_probe_counter > 0); fail_unless (video_probe_counter > 0); @@ -1399,8 +1408,7 @@ GST_START_TEST (test_image_location_switching) g_object_get (camera, "camera-source", &src, NULL); for (i = 0; i < LOCATION_SWITCHING_FILENAMES_COUNT; i++) { - filenames[i] = - g_strdup (make_test_file_name ("image-switching-filename-test", i)); + filenames[i] = make_test_file_name ("image-switching-filename-test", i); } filenames[LOCATION_SWITCHING_FILENAMES_COUNT] = NULL; From 71f28c44a0632317bd6483941851d850c006b051 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Tue, 20 Sep 2011 15:21:53 +0100 Subject: [PATCH 06/10] mpegpsdemux: remove unused field https://bugzilla.gnome.org/show_bug.cgi?id=659485 --- gst/mpegdemux/gstmpegdemux.h | 1 - 1 file changed, 1 deletion(-) diff --git a/gst/mpegdemux/gstmpegdemux.h b/gst/mpegdemux/gstmpegdemux.h index a8822350a2..6cf7aed9ce 100644 --- a/gst/mpegdemux/gstmpegdemux.h +++ b/gst/mpegdemux/gstmpegdemux.h @@ -84,7 +84,6 @@ struct _GstFluPSStream gint id; gint type; - gint size_bound; GstClockTime segment_thresh; GstClockTime last_seg_start; From 49d1121101337a9dd60c94176a5f066c8a8e5718 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Wed, 21 Sep 2011 17:29:52 +0100 Subject: [PATCH 07/10] mpegdemux: answer position query with a stream time position https://bugzilla.gnome.org/show_bug.cgi?id=659485 --- gst/mpegdemux/gstmpegdemux.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gst/mpegdemux/gstmpegdemux.c b/gst/mpegdemux/gstmpegdemux.c index 205d381d5a..5b6b89c339 100644 --- a/gst/mpegdemux/gstmpegdemux.c +++ b/gst/mpegdemux/gstmpegdemux.c @@ -1247,6 +1247,7 @@ gst_flups_demux_src_query (GstPad * pad, GstQuery * query) switch (GST_QUERY_TYPE (query)) { case GST_QUERY_POSITION: { + GstClockTime pos; GstFormat format; gst_query_parse_position (query, &format, NULL); @@ -1257,10 +1258,9 @@ gst_flups_demux_src_query (GstPad * pad, GstQuery * query) goto not_supported; } - GST_LOG_OBJECT (demux, "Position at GStreamer Time:%" GST_TIME_FORMAT, - GST_TIME_ARGS (demux->src_segment.last_stop)); - - gst_query_set_position (query, format, demux->src_segment.last_stop); + pos = demux->src_segment.last_stop - demux->src_segment.start; + GST_LOG_OBJECT (demux, "Position %" GST_TIME_FORMAT, GST_TIME_ARGS (pos)); + gst_query_set_position (query, format, pos); res = TRUE; break; } From 46dd7941f32717f4fbd6dabe04fa3171de1c1d19 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Wed, 21 Sep 2011 14:53:01 +0100 Subject: [PATCH 08/10] mpegpsdemux: take into account SCR offset when seeking Since the seeking byte offset is chosen by linear interpolation from SCR values, we need to take that first SCR into account to end up near the correct offset. Otherwise, as the code does a linear search after that first seek, it will take a LOOOOOONG time to get there for streams which don't start at zero. https://bugzilla.gnome.org/show_bug.cgi?id=659485 --- gst/mpegdemux/gstmpegdemux.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gst/mpegdemux/gstmpegdemux.c b/gst/mpegdemux/gstmpegdemux.c index 5b6b89c339..a73f8f95f2 100644 --- a/gst/mpegdemux/gstmpegdemux.c +++ b/gst/mpegdemux/gstmpegdemux.c @@ -1042,8 +1042,9 @@ gst_flups_demux_do_seek (GstFluPSDemux * demux, GstSegment * seeksegment) GST_INFO_OBJECT (demux, "sink segment configured %" GST_SEGMENT_FORMAT ", trying to go at SCR: %" G_GUINT64_FORMAT, &demux->sink_segment, scr); - offset = MIN (gst_util_uint64_scale (scr, scr_rate_n, scr_rate_d), - demux->sink_segment.stop); + offset = + MIN (gst_util_uint64_scale (scr - demux->first_scr, scr_rate_n, + scr_rate_d), demux->sink_segment.stop); found = gst_flups_demux_scan_forward_ts (demux, &offset, SCAN_SCR, &fscr); if (!found) { From 12bb47343d970d7c4ceb625e30351fbba8db2c3e Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Sat, 1 Oct 2011 14:30:07 +0100 Subject: [PATCH 09/10] kate: fix race condition on PAUSED->READY state change https://bugzilla.gnome.org/show_bug.cgi?id=660630 --- ext/kate/gstkatetiger.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ext/kate/gstkatetiger.c b/ext/kate/gstkatetiger.c index 41da4db151..ca02c912de 100644 --- a/ext/kate/gstkatetiger.c +++ b/ext/kate/gstkatetiger.c @@ -571,6 +571,12 @@ gst_kate_tiger_kate_chain (GstPad * pad, GstBuffer * buf) GST_LOG_OBJECT (tiger, "Got kate buffer, caps %" GST_PTR_FORMAT, GST_BUFFER_CAPS (buf)); + /* Now that we have the lock, check if we're flushing */ + if (tiger->decoder.kate_flushing) { + GST_DEBUG_OBJECT (tiger, "Flushing, disregarding buffer"); + goto done; + } + /* Unfortunately, it can happen that the start of the stream is not sent, for instance if there's a stream selector upstream, which is switched from another Kate stream. If this happens, then we can fallback on the @@ -663,6 +669,7 @@ gst_kate_tiger_kate_chain (GstPad * pad, GstBuffer * buf) } } +done: GST_KATE_TIGER_MUTEX_UNLOCK (tiger); gst_object_unref (tiger); From fa3d6610833b4b92574a2ef8be870c93b527c5f1 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Thu, 29 Sep 2011 20:55:22 +0100 Subject: [PATCH 10/10] kate: avoid rendering when we know there is nothing to render https://bugzilla.gnome.org/show_bug.cgi?id=660528 --- ext/kate/gstkatetiger.c | 82 ++++++++++++++++++++++++----------------- 1 file changed, 48 insertions(+), 34 deletions(-) diff --git a/ext/kate/gstkatetiger.c b/ext/kate/gstkatetiger.c index ca02c912de..4dd7ef2395 100644 --- a/ext/kate/gstkatetiger.c +++ b/ext/kate/gstkatetiger.c @@ -725,6 +725,7 @@ gst_kate_tiger_video_chain (GstPad * pad, GstBuffer * buf) GstFlowReturn rflow = GST_FLOW_OK; unsigned char *ptr; int ret; + kate_float t; GST_KATE_TIGER_MUTEX_LOCK (tiger); @@ -743,45 +744,58 @@ gst_kate_tiger_video_chain (GstPad * pad, GstBuffer * buf) g_cond_broadcast (tiger->cond); } - /* draw on it */ + /* Update first with a dummy buffer pointer we cannot write to. If there is nothing + to draw, we will not have to make it writeable */ + ptr = GST_BUFFER_DATA (buf); + ret = + tiger_renderer_set_buffer (tiger->tr, ptr, tiger->video_width, + tiger->video_height, tiger->video_width * 4, tiger->swap_rgb); + if (G_UNLIKELY (ret < 0)) { + GST_WARNING_OBJECT (tiger, + "Tiger renderer failed to set buffer to video frame: %d", ret); + goto pass; + } + + /* update the renderer at the time of the video frame */ + t = gst_kate_tiger_get_time (tiger); + GST_LOG_OBJECT (tiger, "Video segment calc: last stop %ld, time %.3f", + (long) tiger->video_segment.last_stop, t); + ret = tiger_renderer_update (tiger->tr, t, 1); + if (G_UNLIKELY (ret < 0)) { + GST_WARNING_OBJECT (tiger, "Tiger renderer failed to update: %d", ret); + goto pass; + } + + /* if there nothing to draw, we can just push the video buffer as is */ + if (ret > 0) + goto pass; + + /* there is something to draw, so first make the buffer writable */ buf = gst_buffer_make_writable (buf); if (G_UNLIKELY (!buf)) { GST_WARNING_OBJECT (tiger, "Failed to make video buffer writable"); - } else { - ptr = GST_BUFFER_DATA (buf); - if (!ptr) { - GST_WARNING_OBJECT (tiger, - "Failed to get a pointer to video buffer data"); - } else { - ret = - tiger_renderer_set_buffer (tiger->tr, ptr, tiger->video_width, - tiger->video_height, tiger->video_width * 4, tiger->swap_rgb); - if (G_UNLIKELY (ret < 0)) { - GST_WARNING_OBJECT (tiger, - "Tiger renderer failed to set buffer to video frame: %d", ret); - } else { - kate_float t = gst_kate_tiger_get_time (tiger); - GST_LOG_OBJECT (tiger, "Video segment calc: last stop %ld, time %.3f", - (long) tiger->video_segment.last_stop, t); - - ret = tiger_renderer_update (tiger->tr, t, 1); - if (G_UNLIKELY (ret < 0)) { - GST_WARNING_OBJECT (tiger, "Tiger renderer failed to update: %d", - ret); - } else { - ret = tiger_renderer_render (tiger->tr); - if (G_UNLIKELY (ret < 0)) { - GST_WARNING_OBJECT (tiger, - "Tiger renderer failed to render to video frame: %d", ret); - } else { - GST_LOG_OBJECT (tiger, - "Tiger renderer rendered on video frame at %f", t); - } - } - } - } + goto pass; } + /* and setup that buffer before rendering */ + ptr = GST_BUFFER_DATA (buf); + ret = + tiger_renderer_set_buffer (tiger->tr, ptr, tiger->video_width, + tiger->video_height, tiger->video_width * 4, tiger->swap_rgb); + if (G_UNLIKELY (ret < 0)) { + GST_WARNING_OBJECT (tiger, + "Tiger renderer failed to set buffer to video frame: %d", ret); + goto pass; + } + ret = tiger_renderer_render (tiger->tr); + if (G_UNLIKELY (ret < 0)) { + GST_WARNING_OBJECT (tiger, + "Tiger renderer failed to render to video frame: %d", ret); + } else { + GST_LOG_OBJECT (tiger, "Tiger renderer rendered on video frame at %f", t); + } + +pass: GST_KATE_TIGER_MUTEX_UNLOCK (tiger); rflow = gst_pad_push (tiger->srcpad, buf);