From 1c761196f709d4f06616750ad6403a459fac5dc0 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Fri, 24 Dec 2010 09:10:48 -0300 Subject: [PATCH] wrappercamerabinsrc: Refactor internal pipeline Instead of linking 3 src pads from tee to the ghostpads, use 2 srcpads and add an output-selector to completely split caps negotiation of video/image modes. I don't think there is an use case that would require image and video pads to be used at the same time. --- gst/camerabin2/gstwrappercamerabinsrc.c | 90 ++++++++++++++++++++----- gst/camerabin2/gstwrappercamerabinsrc.h | 10 +-- 2 files changed, 80 insertions(+), 20 deletions(-) diff --git a/gst/camerabin2/gstwrappercamerabinsrc.c b/gst/camerabin2/gstwrappercamerabinsrc.c index 19567ab625..353e733ca8 100644 --- a/gst/camerabin2/gstwrappercamerabinsrc.c +++ b/gst/camerabin2/gstwrappercamerabinsrc.c @@ -1,6 +1,7 @@ /* * GStreamer * Copyright (C) 2010 Texas Instruments, Inc + * Copyright (C) 2010 Thiago Santos * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -137,6 +138,10 @@ gst_wrapper_camera_bin_src_imgsrc_probe (GstPad * pad, GstBuffer * buffer, GstBaseCameraSrc *camerasrc = GST_BASE_CAMERA_SRC (data); gboolean ret = FALSE; + GST_LOG_OBJECT (self, "Image probe, mode %d, capture count %d, caps %" + GST_PTR_FORMAT, camerasrc->mode, self->image_capture_count, + GST_BUFFER_CAPS (buffer)); + g_mutex_lock (camerasrc->capturing_mutex); if (self->image_capture_count > 0) { ret = TRUE; @@ -162,6 +167,9 @@ gst_wrapper_camera_bin_src_vidsrc_probe (GstPad * pad, GstBuffer * buffer, GstBaseCameraSrc *camerasrc = GST_BASE_CAMERA_SRC_CAST (self); gboolean ret = FALSE; + GST_LOG_OBJECT (self, "Video probe, mode %d, capture status %d", + camerasrc->mode, self->video_rec_status); + /* TODO do we want to lock for every buffer? */ /* * Note that we can use gst_pad_push_event here because we are a buffer @@ -200,6 +208,9 @@ gst_wrapper_camera_bin_src_event (GstPad * pad, GstEvent * event) structure = gst_event_get_structure (event); if (structure && gst_structure_has_name (structure, "renegotiate")) { + GST_DEBUG_OBJECT (src, "Received renegotiate on pad %s", + GST_PAD_NAME (pad)); + if (pad == src->imgsrc) { src->image_renegotiate = TRUE; } else if (pad == src->vidsrc) { @@ -224,7 +235,11 @@ src_event_probe (GstPad * pad, GstEvent * event, gpointer user_data) * @bcamsrc: camerasrc object * * This function creates and links the elements of the camerasrc bin - * videosrc ! cspconv ! capsfilter ! crop ! scale ! capsfilter ! tee ! .. + * videosrc ! cspconv ! capsfilter ! crop ! scale ! capsfilter ! tee name=t ! + * t. ! ... (viewfinder pad) + * t. ! output-selector name=outsel + * outsel. ! (image pad) + * outsel. ! (video pad) * * Returns: TRUE, if elements were successfully created, FALSE otherwise */ @@ -236,6 +251,11 @@ gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) GstElement *tee; gboolean ret = FALSE; GstElement *videoscale; + GstPad *vf_pad; + GstPad *tee_capture_pad; + + if (self->elements_created) + return TRUE; GST_DEBUG_OBJECT (self, "constructing pipeline"); @@ -250,6 +270,7 @@ gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) } } + /* add a buffer probe to the src elemento to drop EOS from READY->NULL */ { GstPad *pad; pad = gst_element_get_static_pad (self->src_vid_src, "src"); @@ -279,8 +300,9 @@ gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) if (!(tee = gst_camerabin_create_and_add_element (cbin, "tee"))) goto done; - self->tee_vf_srcpad = gst_element_get_request_pad (tee, "src%d"); - g_object_set (tee, "alloc-pad", self->tee_vf_srcpad, NULL); + /* viewfinder pad */ + vf_pad = gst_element_get_request_pad (tee, "src%d"); + g_object_set (tee, "alloc-pad", vf_pad, NULL); /* the viewfinder should always work, so we add some converters to it */ if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace")) @@ -288,30 +310,56 @@ gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) if (!(videoscale = gst_camerabin_create_and_add_element (cbin, "videoscale"))) goto done; - gst_object_unref (self->tee_vf_srcpad); - self->tee_vf_srcpad = gst_element_get_static_pad (videoscale, "src"); + gst_object_unref (vf_pad); + vf_pad = gst_element_get_static_pad (videoscale, "src"); - self->tee_image_srcpad = gst_element_get_request_pad (tee, "src%d"); - self->tee_video_srcpad = gst_element_get_request_pad (tee, "src%d"); + /* image/video pad from tee */ + tee_capture_pad = gst_element_get_request_pad (tee, "src%d"); - gst_pad_add_buffer_probe (self->tee_image_srcpad, + self->output_selector = + gst_element_factory_make ("output-selector", "outsel"); + gst_bin_add (GST_BIN (self), self->output_selector); + { + GstPad *pad = gst_element_get_static_pad (self->output_selector, "sink"); + + /* check return TODO */ + gst_pad_link (tee_capture_pad, pad); + gst_object_unref (pad); + } + + /* Create the 2 output pads for video and image */ + self->outsel_vidpad = + gst_element_get_request_pad (self->output_selector, "src%d"); + self->outsel_imgpad = + gst_element_get_request_pad (self->output_selector, "src%d"); + + g_assert (self->outsel_vidpad != NULL); + g_assert (self->outsel_imgpad != NULL); + + gst_pad_add_buffer_probe (self->outsel_imgpad, G_CALLBACK (gst_wrapper_camera_bin_src_imgsrc_probe), self); - gst_pad_add_buffer_probe (self->tee_video_srcpad, + gst_pad_add_buffer_probe (self->outsel_vidpad, G_CALLBACK (gst_wrapper_camera_bin_src_vidsrc_probe), self); + gst_ghost_pad_set_target (GST_GHOST_PAD (self->imgsrc), self->outsel_imgpad); + gst_ghost_pad_set_target (GST_GHOST_PAD (self->vidsrc), self->outsel_vidpad); + if (bcamsrc->mode == MODE_IMAGE) { + g_object_set (self->output_selector, "active-pad", self->outsel_imgpad, + NULL); + } else { + g_object_set (self->output_selector, "active-pad", self->outsel_vidpad, + NULL); + } - /* hook-up the ghostpads */ - gst_ghost_pad_set_target (GST_GHOST_PAD (self->vfsrc), self->tee_vf_srcpad); - gst_ghost_pad_set_target (GST_GHOST_PAD (self->imgsrc), - self->tee_image_srcpad); - gst_ghost_pad_set_target (GST_GHOST_PAD (self->vidsrc), - self->tee_video_srcpad); + /* hook-up the vf ghostpads */ + gst_ghost_pad_set_target (GST_GHOST_PAD (self->vfsrc), vf_pad); gst_pad_set_active (self->vfsrc, TRUE); gst_pad_set_active (self->imgsrc, TRUE); /* XXX ??? */ gst_pad_set_active (self->vidsrc, TRUE); /* XXX ??? */ ret = TRUE; + self->elements_created = TRUE; done: return ret; } @@ -498,6 +546,16 @@ gst_wrapper_camera_bin_src_set_mode (GstBaseCameraSrc * bcamsrc, self->mode = mode; + if (self->output_selector) { + if (mode == MODE_IMAGE) { + g_object_set (self->output_selector, "active-pad", self->outsel_imgpad, + NULL); + } else { + g_object_set (self->output_selector, "active-pad", self->outsel_vidpad, + NULL); + } + } + if (photography) { if (g_object_class_find_property (G_OBJECT_GET_CLASS (photography), "capture-mode")) { @@ -775,8 +833,8 @@ gst_wrapper_camera_bin_src_start_capture (GstBaseCameraSrc * camerasrc) /* TODO shoud we access this directly? Maybe a macro is better? */ if (src->mode == MODE_IMAGE) { - src->image_capture_count = 1; start_image_capture (src); + src->image_capture_count = 1; } else if (src->mode == MODE_VIDEO) { g_mutex_unlock (camerasrc->capturing_mutex); gst_wrapper_camera_bin_reset_video_src_caps (src, NULL); diff --git a/gst/camerabin2/gstwrappercamerabinsrc.h b/gst/camerabin2/gstwrappercamerabinsrc.h index 22697b93aa..2813e8b4b2 100644 --- a/gst/camerabin2/gstwrappercamerabinsrc.h +++ b/gst/camerabin2/gstwrappercamerabinsrc.h @@ -1,6 +1,7 @@ /* * GStreamer * Copyright (C) 2010 Texas Instruments, Inc + * Copyright (C) 2010 Thiago Santos * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -75,13 +76,14 @@ struct _GstWrapperCameraBinSrc GstElement *src_zoom_crop; GstElement *src_zoom_scale; GstElement *src_zoom_filter; + GstElement *output_selector; + + gboolean elements_created; guint src_event_probe_id; - /* srcpads of tee */ - GstPad *tee_vf_srcpad; - GstPad *tee_image_srcpad; - GstPad *tee_video_srcpad; + GstPad *outsel_imgpad; + GstPad *outsel_vidpad; GstPadEventFunction srcpad_event_func;