diff --git a/gst/droidcamsrc/gstdroidcamsrcdev.c b/gst/droidcamsrc/gstdroidcamsrcdev.c index a53fb367..308352a4 100644 --- a/gst/droidcamsrc/gstdroidcamsrcdev.c +++ b/gst/droidcamsrc/gstdroidcamsrcdev.c @@ -48,6 +48,7 @@ GST_DEBUG_CATEGORY_EXTERN (gst_droid_camsrc_debug); struct _GstDroidCamSrcImageCaptureState { + gboolean running; gboolean image_preview_sent; gboolean image_start_sent; }; @@ -542,6 +543,8 @@ gst_droidcamsrc_dev_new (GstDroidCamSrcPad * vfsrc, dev->viewfinder_format = GST_VIDEO_FORMAT_UNKNOWN; + dev->task_pool = gst_task_pool_new (); + return dev; } @@ -646,6 +649,9 @@ gst_droidcamsrc_dev_destroy (GstDroidCamSrcDev * dev) gst_droidcamsrc_recorder_destroy (dev->recorder); + gst_task_pool_cleanup (dev->task_pool); // Just in case + gst_object_unref (dev->task_pool); + g_slice_free (GstDroidCamSrcImageCaptureState, dev->img); g_slice_free (GstDroidCamSrcVideoCaptureState, dev->vid); g_slice_free (GstDroidCamSrcDev, dev); @@ -655,6 +661,8 @@ gst_droidcamsrc_dev_destroy (GstDroidCamSrcDev * dev) gboolean gst_droidcamsrc_dev_init (GstDroidCamSrcDev * dev) { + GError *err = NULL; + GST_DEBUG ("dev init"); g_rec_mutex_lock (dev->lock); @@ -690,6 +698,13 @@ gst_droidcamsrc_dev_init (GstDroidCamSrcDev * dev) g_rec_mutex_unlock (dev->lock); + gst_task_pool_prepare (dev->task_pool, &err); + if (err != NULL) { + GST_ERROR ("Failed to prepare thread pool: %s", err->message); + g_error_free (err); + return FALSE; + } + return TRUE; } @@ -706,6 +721,8 @@ gst_droidcamsrc_dev_deinit (GstDroidCamSrcDev * dev) } g_rec_mutex_unlock (dev->lock); + + gst_task_pool_cleanup (dev->task_pool); } gboolean @@ -832,22 +849,58 @@ gst_droidcamsrc_dev_set_params (GstDroidCamSrcDev * dev) return ret; } +static void +_take_picture (gpointer user_data) +{ + GstDroidCamSrcDev *dev = (GstDroidCamSrcDev *) user_data; + GstDroidCamSrc *src = GST_DROIDCAMSRC (GST_PAD_PARENT (dev->imgsrc->pad)); + + const int msg_type = dev->c.CAMERA_MSG_SHUTTER | dev->c.CAMERA_MSG_RAW_IMAGE + | dev->c.CAMERA_MSG_POSTVIEW_FRAME | dev->c.CAMERA_MSG_COMPRESSED_IMAGE; + + GST_DEBUG ("really calling droid_media_camera_take_picture"); + + g_rec_mutex_lock (dev->lock); + + if (!droid_media_camera_take_picture (dev->cam, msg_type)) { + GST_ERROR ("error capturing image"); + GST_ELEMENT_ERROR (src, LIBRARY, FAILED, (NULL), ("take_picture fails")); + } + + dev->img->running = FALSE; + + g_rec_mutex_unlock (dev->lock); +} + gboolean gst_droidcamsrc_dev_capture_image (GstDroidCamSrcDev * dev) { gboolean ret = FALSE; - int msg_type = dev->c.CAMERA_MSG_SHUTTER | dev->c.CAMERA_MSG_RAW_IMAGE - | dev->c.CAMERA_MSG_POSTVIEW_FRAME | dev->c.CAMERA_MSG_COMPRESSED_IMAGE; + GError *err = NULL; GST_DEBUG ("dev capture image"); g_rec_mutex_lock (dev->lock); + if (dev->img->running) { + GST_ERROR ("another capture is already in progress (?)"); + goto out; + } + + dev->img->running = TRUE; dev->img->image_preview_sent = FALSE; dev->img->image_start_sent = FALSE; - if (!droid_media_camera_take_picture (dev->cam, msg_type)) { - GST_ERROR ("error capturing image"); + /* + * Call droid_media_camera_take_picture from another thread. take_picture + * call in HAL sometimes need to read information from preview frames for + * e.g. auto exposure when using flash. If the calling thread also handles + * pulling preview frames, this will create a deadlock. + */ + gst_task_pool_push (dev->task_pool, _take_picture, dev, &err); + if (err) { + GST_ERROR ("Failed to start take_picture task: %s", err->message); + g_error_free (err); goto out; } diff --git a/gst/droidcamsrc/gstdroidcamsrcdev.h b/gst/droidcamsrc/gstdroidcamsrcdev.h index 62fff332..de504096 100644 --- a/gst/droidcamsrc/gstdroidcamsrcdev.h +++ b/gst/droidcamsrc/gstdroidcamsrcdev.h @@ -58,6 +58,8 @@ struct _GstDroidCamSrcDev gboolean use_recorder; GstDroidCamSrcRecorder *recorder; + + GstTaskPool *task_pool; }; GstDroidCamSrcDev *gst_droidcamsrc_dev_new (GstDroidCamSrcPad *vfsrc,