camerabin2: Avoid blocking in start-capture and send application tags later
authorLasse Laukkanen <lasse.laukkanen@digia.com>
Wed, 9 Nov 2011 12:41:44 +0000 (09:41 -0300)
committerThiago Santos <thiago.sousa.santos@collabora.com>
Wed, 9 Nov 2011 14:45:55 +0000 (11:45 -0300)
Tags are currently sent from start-capture, which is run in the
application thread. For images we can delay the tags pushing to the
buffer probe and push the tags with the location event and reduce
start-capture time.

gst/camerabin2/gstcamerabin2.c
gst/camerabin2/gstcamerabin2.h

index 62f29a1..8ba8a4e 100644 (file)
@@ -429,21 +429,27 @@ gst_camera_bin_start_capture (GstCameraBin2 * camerabin)
   if (taglist) {
     GstPad *active_pad;
 
-    GST_DEBUG_OBJECT (camerabin, "Pushing tags from application: %"
+    GST_DEBUG_OBJECT (camerabin, "Have tags from application: %"
         GST_PTR_FORMAT, taglist);
 
     if (camerabin->mode == MODE_IMAGE) {
-      active_pad = gst_element_get_static_pad (camerabin->src,
-          GST_BASE_CAMERA_SRC_IMAGE_PAD_NAME);
+      /* Store image tags in a list and push them later, this prevents
+         start_capture() from blocking in pad_push_event call */
+      g_mutex_lock (camerabin->image_tags_mutex);
+      camerabin->image_tags_list =
+          g_slist_append (camerabin->image_tags_list,
+          gst_tag_list_copy (taglist));
+      g_mutex_unlock (camerabin->image_tags_mutex);
     } else {
       active_pad = gst_element_get_static_pad (camerabin->src,
           GST_BASE_CAMERA_SRC_VIDEO_PAD_NAME);
-    }
+      gst_pad_push_event (active_pad,
+          gst_event_new_tag (gst_tag_list_copy (taglist)));
 
-    gst_pad_push_event (active_pad,
-        gst_event_new_tag (gst_tag_list_copy (taglist)));
-    gst_object_unref (active_pad);
+      gst_object_unref (active_pad);
+    }
   }
+  GST_DEBUG_OBJECT (camerabin, "Start-capture end");
 }
 
 static void
@@ -526,6 +532,7 @@ gst_camera_bin_dispose (GObject * object)
 
   g_free (camerabin->location);
   g_mutex_free (camerabin->preview_list_mutex);
+  g_mutex_free (camerabin->image_tags_mutex);
 
   if (camerabin->src_capture_notify_id)
     g_signal_handler_disconnect (camerabin->src,
@@ -882,6 +889,7 @@ gst_camera_bin_init (GstCameraBin2 * camera)
   camera->max_zoom = MAX_ZOOM;
   camera->flags = DEFAULT_FLAGS;
   camera->preview_list_mutex = g_mutex_new ();
+  camera->image_tags_mutex = g_mutex_new ();
 
   /* capsfilters are created here as we proxy their caps properties and
    * this way we avoid having to store the caps while on NULL state to 
@@ -1263,7 +1271,27 @@ gst_camera_bin_image_src_buffer_probe (GstPad * pad, GstBuffer * buf,
   GstEvent *evt;
   gchar *location = NULL;
   GstPad *peer;
+  GstTagList *tags;
+
+  /* Push pending image tags */
+  g_mutex_lock (camerabin->image_tags_mutex);
+  if (camerabin->image_tags_list) {
+    tags = camerabin->image_tags_list->data;
+    camerabin->image_tags_list =
+        g_slist_delete_link (camerabin->image_tags_list,
+        camerabin->image_tags_list);
+    g_mutex_unlock (camerabin->image_tags_mutex);
+    GST_DEBUG_OBJECT (camerabin, "Pushing tags from application: %"
+        GST_PTR_FORMAT, tags);
+    peer = gst_pad_get_peer (pad);
+    gst_pad_send_event (peer, gst_event_new_tag (tags));
+    gst_object_unref (peer);
+  } else {
+    g_mutex_unlock (camerabin->image_tags_mutex);
+    GST_DEBUG_OBJECT (camerabin, "No tags from application to send");
+  }
 
+  /* Push image location event */
   if (camerabin->image_location_list) {
     location = camerabin->image_location_list->data;
     camerabin->image_location_list =
@@ -1775,6 +1803,13 @@ gst_camera_bin_change_state (GstElement * element, GstStateChange trans)
       g_slist_free (camera->image_location_list);
       camera->image_location_list = NULL;
 
+      g_mutex_lock (camera->image_tags_mutex);
+      g_slist_foreach (camera->image_tags_list, (GFunc) gst_tag_list_free,
+          NULL);
+      g_slist_free (camera->image_tags_list);
+      camera->image_tags_list = NULL;
+      g_mutex_unlock (camera->image_tags_mutex);
+
       g_mutex_lock (camera->preview_list_mutex);
       g_slist_foreach (camera->preview_location_list, (GFunc) g_free, NULL);
       g_slist_free (camera->preview_location_list);
index 3b4c9c9..27115bd 100644 (file)
@@ -93,6 +93,9 @@ struct _GstCameraBin2
    * as file location change notifications, they are pushed before
    * each buffer capture */
   GSList *image_location_list;
+  /* Store also tags and push them before each captured image */
+  GMutex *image_tags_mutex;
+  GSList *image_tags_list;
 
   /*
    * Similar to above, but used for giving names to previews