From 7dac3659c61feae9d076475a02a57e256282661b Mon Sep 17 00:00:00 2001 From: Teemu Katajisto Date: Wed, 28 Oct 2009 12:47:19 +0200 Subject: [PATCH] camerabin: add flags property. Fixes #573370 (partially) Adds flags property to enable runtime configuration of conversion and scaling elements. Also adds flag for disabling audio completely. --- gst/camerabin/Makefile.am | 6 +- gst/camerabin/camerabinimage.c | 32 +++- gst/camerabin/camerabinimage.h | 7 + gst/camerabin/camerabinvideo.c | 117 ++++++------ gst/camerabin/camerabinvideo.h | 7 + gst/camerabin/gstcamerabin-enum.c | 59 ++++++ gst/camerabin/gstcamerabin-enum.h | 60 +++++++ gst/camerabin/gstcamerabin.c | 286 ++++++++++++++++++------------ gst/camerabin/gstcamerabin.h | 8 +- 9 files changed, 400 insertions(+), 182 deletions(-) create mode 100644 gst/camerabin/gstcamerabin-enum.c create mode 100644 gst/camerabin/gstcamerabin-enum.h diff --git a/gst/camerabin/Makefile.am b/gst/camerabin/Makefile.am index 746817e33a..d46b6441bc 100644 --- a/gst/camerabin/Makefile.am +++ b/gst/camerabin/Makefile.am @@ -20,7 +20,8 @@ libgstcamerabin_la_SOURCES = gstcamerabin.c \ camerabinvideo.c \ camerabingeneral.c \ camerabinpreview.c \ - gstcamerabinphotography.c + gstcamerabinphotography.c \ + gstcamerabin-enum.c nodist_libgstcamerabin_la_SOURCES = $(built_sources) libgstcamerabin_la_CFLAGS = \ @@ -41,4 +42,5 @@ noinst_HEADERS = gstcamerabin.h \ camerabinvideo.h \ camerabingeneral.h \ camerabinpreview.h \ - gstcamerabinphotography.h + gstcamerabinphotography.h \ + gstcamerabin-enum.h diff --git a/gst/camerabin/camerabinimage.c b/gst/camerabin/camerabinimage.c index 25730ccdaa..0defb6367a 100644 --- a/gst/camerabin/camerabinimage.c +++ b/gst/camerabin/camerabinimage.c @@ -52,6 +52,7 @@ #include "camerabinimage.h" #include "camerabingeneral.h" +#include "gstcamerabin-enum.h" #include "string.h" @@ -60,6 +61,7 @@ #define DEFAULT_SINK "filesink" #define DEFAULT_ENC "jpegenc" #define DEFAULT_META_MUX "metadatamux" +#define DEFAULT_FLAGS GST_CAMERABIN_FLAG_IMAGE_COLOR_CONVERSION enum { @@ -157,6 +159,7 @@ gst_camerabin_image_init (GstCameraBinImage * img, gst_element_add_pad (GST_ELEMENT (img), img->sinkpad); img->elements_created = FALSE; + img->flags = DEFAULT_FLAGS; } static void @@ -425,17 +428,15 @@ gst_camerabin_image_create_elements (GstCameraBinImage * img) img_sinkpad = gst_element_get_static_pad (img->post, "sink"); } - /* Add colorspace converter */ - if (!(csp = - gst_camerabin_create_and_add_element (imgbin, "ffmpegcolorspace"))) { - goto done; - } - - /* Set up sink ghost pad for img bin */ - if (!img_sinkpad) { + if (img->flags & GST_CAMERABIN_FLAG_IMAGE_COLOR_CONVERSION) { + /* Add colorspace converter */ + if (!(csp = + gst_camerabin_create_and_add_element (imgbin, + "ffmpegcolorspace"))) { + goto done; + } img_sinkpad = gst_element_get_static_pad (csp, "sink"); } - gst_ghost_pad_set_target (GST_GHOST_PAD (img->sinkpad), img_sinkpad); /* Create image encoder */ if (img->user_enc) { @@ -471,6 +472,12 @@ gst_camerabin_image_create_elements (GstCameraBinImage * img) g_object_set (G_OBJECT (img->sink), "location", img->filename->str, "async", FALSE, "buffer-mode", 2, /* non buffered io */ NULL); + /* Set up sink ghost pad for image bin */ + if (!img_sinkpad) { + img_sinkpad = gst_element_get_static_pad (img->enc, "sink"); + } + gst_ghost_pad_set_target (GST_GHOST_PAD (img->sinkpad), img_sinkpad); + ret = TRUE; done: @@ -535,6 +542,13 @@ gst_camerabin_image_set_postproc (GstCameraBinImage * img, img->post = postproc; } +void +gst_camerabin_image_set_flags (GstCameraBinImage * img, GstCameraBinFlags flags) +{ + GST_DEBUG_OBJECT (img, "setting image flags: %d", flags); + img->flags = flags; +} + GstElement * gst_camerabin_image_get_encoder (GstCameraBinImage * img) { diff --git a/gst/camerabin/camerabinimage.h b/gst/camerabin/camerabinimage.h index 8214e9cbb5..4fc405f320 100644 --- a/gst/camerabin/camerabinimage.h +++ b/gst/camerabin/camerabinimage.h @@ -23,6 +23,8 @@ #include +#include "gstcamerabin-enum.h" + G_BEGIN_DECLS #define GST_TYPE_CAMERABIN_IMAGE (gst_camerabin_image_get_type()) #define GST_CAMERABIN_IMAGE_CAST(obj) ((GstCameraBinImage*)(obj)) @@ -53,6 +55,7 @@ struct _GstCameraBinImage GstElement *sink; gboolean elements_created; + GstCameraBinFlags flags; }; struct _GstCameraBinImageClass @@ -69,6 +72,10 @@ void gst_camerabin_image_set_postproc (GstCameraBinImage * img, GstElement * postproc); +void +gst_camerabin_image_set_flags (GstCameraBinImage * img, + GstCameraBinFlags flags); + GstElement *gst_camerabin_image_get_encoder (GstCameraBinImage * img); GstElement *gst_camerabin_image_get_postproc (GstCameraBinImage * img); diff --git a/gst/camerabin/camerabinvideo.c b/gst/camerabin/camerabinvideo.c index 0a72d23ad8..4796fc8353 100644 --- a/gst/camerabin/camerabinvideo.c +++ b/gst/camerabin/camerabinvideo.c @@ -71,7 +71,7 @@ #define DEFAULT_MUX "oggmux" #define DEFAULT_SINK "filesink" -#define USE_AUDIO_CONVERSION 1 +#define DEFAULT_FLAGS 0 enum { @@ -187,6 +187,7 @@ gst_camerabin_video_init (GstCameraBinVideo * vid, vid->pending_eos = NULL; vid->mute = ARG_DEFAULT_MUTE; + vid->flags = DEFAULT_FLAGS; vid->aud_src_probe_id = 0; vid->vid_src_probe_id = 0; @@ -571,6 +572,7 @@ gst_camerabin_video_create_elements (GstCameraBinVideo * vid) /* Add queue element for video */ vid->tee_video_srcpad = gst_element_get_request_pad (vid->tee, "src%d"); + if (!(vid->video_queue = gst_camerabin_create_and_add_element (vidbin, "queue"))) { goto error; @@ -610,57 +612,59 @@ gst_camerabin_video_create_elements (GstCameraBinVideo * vid) g_object_set (G_OBJECT (vid->sink), "location", vid->filename->str, "buffer-mode", 2, /* non buffered io */ NULL); - /* Add user set or default audio source element */ - if (!(vid->aud_src = gst_camerabin_setup_default_element (vidbin, - vid->user_aud_src, "autoaudiosrc", DEFAULT_AUDIOSRC))) { - vid->aud_src = NULL; - goto error; - } else { - if (!gst_camerabin_add_element (vidbin, vid->aud_src)) + if (!(vid->flags & GST_CAMERABIN_FLAG_DISABLE_AUDIO)) { + /* Add user set or default audio source element */ + if (!(vid->aud_src = gst_camerabin_setup_default_element (vidbin, + vid->user_aud_src, "autoaudiosrc", DEFAULT_AUDIOSRC))) { + vid->aud_src = NULL; goto error; - } + } else { + if (!gst_camerabin_add_element (vidbin, vid->aud_src)) + goto error; + } - /* Add queue element for audio */ - if (!(gst_camerabin_create_and_add_element (vidbin, "queue"))) { - goto error; - } - - /* Add optional audio conversion and volume elements and - raise no errors if adding them fails */ -#ifdef USE_AUDIO_CONVERSION - if (!gst_camerabin_try_add_element (vidbin, - gst_element_factory_make ("audioconvert", NULL))) { - GST_WARNING_OBJECT (vid, "unable to add audio conversion element"); - /* gst_camerabin_try_add_element() destroyed the element */ - } -#endif - vid->volume = gst_element_factory_make ("volume", NULL); - if (!gst_camerabin_try_add_element (vidbin, vid->volume)) { - GST_WARNING_OBJECT (vid, "unable to add volume element"); - /* gst_camerabin_try_add_element() destroyed the element */ - vid->volume = NULL; - } else { - g_object_set (vid->volume, "mute", vid->mute, NULL); - } - - /* Add user set or default audio encoder element */ - if (vid->user_aud_enc) { - vid->aud_enc = vid->user_aud_enc; - if (!gst_camerabin_add_element (vidbin, vid->aud_enc)) { + /* Add queue element for audio */ + if (!(gst_camerabin_create_and_add_element (vidbin, "queue"))) { goto error; } - } else if (!(vid->aud_enc = - gst_camerabin_create_and_add_element (vidbin, DEFAULT_AUD_ENC))) { - goto error; - } - /* Link audio part to the muxer */ - if (!gst_element_link (vid->aud_enc, vid->muxer)) { - GST_ELEMENT_ERROR (vid, CORE, NEGOTIATION, (NULL), - ("linking audio encoder and muxer failed")); - goto error; - } + /* Add optional audio conversion and volume elements and + raise no errors if adding them fails */ + if (vid->flags & GST_CAMERABIN_FLAG_AUDIO_CONVERSION) { + if (!gst_camerabin_try_add_element (vidbin, + gst_element_factory_make ("audioconvert", NULL))) { + GST_WARNING_OBJECT (vid, "unable to add audio conversion element"); + /* gst_camerabin_try_add_element() destroyed the element */ + } + } + vid->volume = gst_element_factory_make ("volume", NULL); + if (!gst_camerabin_try_add_element (vidbin, vid->volume)) { + GST_WARNING_OBJECT (vid, "unable to add volume element"); + /* gst_camerabin_try_add_element() destroyed the element */ + vid->volume = NULL; + } else { + g_object_set (vid->volume, "mute", vid->mute, NULL); + } + + /* Add user set or default audio encoder element */ + if (vid->user_aud_enc) { + vid->aud_enc = vid->user_aud_enc; + if (!gst_camerabin_add_element (vidbin, vid->aud_enc)) { + goto error; + } + } else if (!(vid->aud_enc = + gst_camerabin_create_and_add_element (vidbin, DEFAULT_AUD_ENC))) { + goto error; + } + + /* Link audio part to the muxer */ + if (!gst_element_link (vid->aud_enc, vid->muxer)) { + GST_ELEMENT_ERROR (vid, CORE, NEGOTIATION, (NULL), + ("linking audio encoder and muxer failed")); + goto error; + } + } /* Add queue leading out of the video bin and to view finder */ vid->tee_vf_srcpad = gst_element_get_request_pad (vid->tee, "src%d"); if (!(queue = gst_camerabin_create_and_add_element (vidbin, "queue"))) { @@ -678,11 +682,12 @@ gst_camerabin_video_create_elements (GstCameraBinVideo * vid) G_CALLBACK (gst_camerabin_drop_eos_probe), vid); gst_object_unref (vid_srcpad); - pad = gst_element_get_static_pad (vid->aud_src, "src"); - vid->aud_src_probe_id = gst_pad_add_buffer_probe (pad, - G_CALLBACK (camerabin_video_pad_aud_src_have_buffer), vid); - gst_object_unref (pad); - + if (!(vid->flags & GST_CAMERABIN_FLAG_DISABLE_AUDIO)) { + pad = gst_element_get_static_pad (vid->aud_src, "src"); + vid->aud_src_probe_id = gst_pad_add_buffer_probe (pad, + G_CALLBACK (camerabin_video_pad_aud_src_have_buffer), vid); + gst_object_unref (pad); + } GST_DEBUG ("created video elements"); return TRUE; @@ -841,6 +846,16 @@ gst_camerabin_video_set_audio_src (GstCameraBinVideo * vid, GST_OBJECT_UNLOCK (vid); } +void +gst_camerabin_video_set_flags (GstCameraBinVideo * vid, GstCameraBinFlags flags) +{ + GST_DEBUG_OBJECT (vid, "setting video flags: %d", flags); + GST_OBJECT_LOCK (vid); + vid->flags = flags; + GST_OBJECT_UNLOCK (vid); +} + + gboolean gst_camerabin_video_get_mute (GstCameraBinVideo * vid) { diff --git a/gst/camerabin/camerabinvideo.h b/gst/camerabin/camerabinvideo.h index 7b21be0b5f..511128d519 100644 --- a/gst/camerabin/camerabinvideo.h +++ b/gst/camerabin/camerabinvideo.h @@ -23,6 +23,8 @@ #include +#include "gstcamerabin-enum.h" + G_BEGIN_DECLS #define ARG_DEFAULT_MUTE FALSE #define GST_TYPE_CAMERABIN_VIDEO (gst_camerabin_video_get_type()) @@ -88,6 +90,7 @@ struct _GstCameraBinVideo gulong vid_sink_probe_id; gboolean mute; + GstCameraBinFlags flags; }; struct _GstCameraBinVideoClass @@ -120,6 +123,10 @@ void gst_camerabin_video_set_audio_src (GstCameraBinVideo * vid, GstElement * audio_src); +void +gst_camerabin_video_set_flags (GstCameraBinVideo * vid, + GstCameraBinFlags flags); + gboolean gst_camerabin_video_get_mute (GstCameraBinVideo * vid); diff --git a/gst/camerabin/gstcamerabin-enum.c b/gst/camerabin/gstcamerabin-enum.c new file mode 100644 index 0000000000..a116a0083c --- /dev/null +++ b/gst/camerabin/gstcamerabin-enum.c @@ -0,0 +1,59 @@ +/* + * GStreamer + * Copyright (C) 2009 Nokia Corporation + * + * 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 "gstcamerabin-enum.h" + +#define C_FLAGS(v) ((guint) v) + +static void +register_gst_camerabin_flags (GType * id) +{ + static const GFlagsValue values[] = { + {C_FLAGS (GST_CAMERABIN_FLAG_SOURCE_RESIZE), + "Enable source crop and scale", "source-resize"}, + {C_FLAGS (GST_CAMERABIN_FLAG_SOURCE_COLOR_CONVERSION), + "Enable colorspace conversion for video source", + "source-colorspace-conversion"}, + {C_FLAGS (GST_CAMERABIN_FLAG_VIEWFINDER_COLOR_CONVERSION), + "Enable colorspace conversion for viewfinder", + "viewfinder-colorspace-conversion"}, + {C_FLAGS (GST_CAMERABIN_FLAG_VIEWFINDER_SCALE), + "Enable scale for viewfinder", "viewfinder-scale"}, + {C_FLAGS (GST_CAMERABIN_FLAG_AUDIO_CONVERSION), + "Enable audio conversion for video capture", "audio-conversion"}, + {C_FLAGS (GST_CAMERABIN_FLAG_DISABLE_AUDIO), + "Disable audio elements for video capture", "disable-audio"}, + {C_FLAGS (GST_CAMERABIN_FLAG_IMAGE_COLOR_CONVERSION), + "Enable colorspace conversion for still image", + "image-colorspace-conversion"}, + {0, NULL, NULL} + }; + *id = g_flags_register_static ("GstCameraBinFlags", values); +} + +GType +gst_camerabin_flags_get_type (void) +{ + static GType id; + static GOnce once = G_ONCE_INIT; + + g_once (&once, (GThreadFunc) register_gst_camerabin_flags, &id); + return id; +} diff --git a/gst/camerabin/gstcamerabin-enum.h b/gst/camerabin/gstcamerabin-enum.h new file mode 100644 index 0000000000..8bbd2645f6 --- /dev/null +++ b/gst/camerabin/gstcamerabin-enum.h @@ -0,0 +1,60 @@ +/* + * GStreamer + * Copyright (C) 2009 Nokia Corporation + * + * 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. + */ + +#ifndef __GST_CAMERABIN_ENUM_H__ +#define __GST_CAMERABIN_ENUM_H__ + +#include + +G_BEGIN_DECLS +/** + * GstCameraBinFlags: + * @GST_CAMERABIN_FLAG_SOURCE_RESIZE: enable video crop and scale + * after capture + * @GST_CAMERABIN_FLAG_SOURCE_COLOR_CONVERSION: enable conversion + * of native video format by enabling ffmpegcolorspace + * @GST_CAMERABIN_FLAG_VIEWFINDER_COLOR_CONVERSION: enable color + * conversion for viewfinder element + * @GST_CAMERABIN_FLAG_VIEWFINDER_SCALE: enable scaling in + * viewfinder element retaining aspect ratio + * @GST_CAMERABIN_FLAG_AUDIO_CONVERSION: enable audioconvert and + * audioresample elements + * @GST_CAMERABIN_FLAG_DISABLE_AUDIO: disable audio elements + * @GST_CAMERABIN_FLAG_IMAGE_COLOR_CONVERSION: enable color + * conversion for image output element + * + * Extra flags to configure the behaviour of the sinks. + */ +typedef enum { + GST_CAMERABIN_FLAG_SOURCE_RESIZE = (1 << 0), + GST_CAMERABIN_FLAG_SOURCE_COLOR_CONVERSION = (1 << 1), + GST_CAMERABIN_FLAG_VIEWFINDER_COLOR_CONVERSION = (1 << 2), + GST_CAMERABIN_FLAG_VIEWFINDER_SCALE = (1 << 3), + GST_CAMERABIN_FLAG_AUDIO_CONVERSION = (1 << 4), + GST_CAMERABIN_FLAG_DISABLE_AUDIO = (1 << 5), + GST_CAMERABIN_FLAG_IMAGE_COLOR_CONVERSION = (1 << 6) +} GstCameraBinFlags; + +#define GST_TYPE_CAMERABIN_FLAGS (gst_camerabin_flags_get_type()) +GType gst_camerabin_flags_get_type (void); + +G_END_DECLS + +#endif /* #ifndef __GST_CAMERABIN_ENUM_H__ */ diff --git a/gst/camerabin/gstcamerabin.c b/gst/camerabin/gstcamerabin.c index 76a5585e1e..4982b06b27 100644 --- a/gst/camerabin/gstcamerabin.c +++ b/gst/camerabin/gstcamerabin.c @@ -190,6 +190,7 @@ enum ARG_0, ARG_FILENAME, ARG_MODE, + ARG_FLAGS, ARG_MUTE, ARG_ZOOM, ARG_IMAGE_POST, @@ -229,6 +230,10 @@ static guint camerabin_signals[LAST_SIGNAL]; #define CAMERABIN_MAX_VF_WIDTH 848 #define CAMERABIN_MAX_VF_HEIGHT 848 +#define DEFAULT_FLAGS GST_CAMERABIN_FLAG_SOURCE_RESIZE | \ + GST_CAMERABIN_FLAG_VIEWFINDER_SCALE | \ + GST_CAMERABIN_FLAG_IMAGE_COLOR_CONVERSION + /* Using "bilinear" as default zoom method */ #define CAMERABIN_DEFAULT_ZOOM_METHOD 1 @@ -239,10 +244,6 @@ static guint camerabin_signals[LAST_SIGNAL]; /* FIXME: this is v4l2camsrc specific */ #define DEFAULT_V4L2CAMSRC_DRIVER_NAME "omap3cam" -/* pipeline configuration */ -//#define USE_VIEWFINDER_COLOR_CONVERTER 1 -//#define USE_VIEWFINDER_SCALE 1 - /* message names */ #define PREVIEW_MESSAGE_NAME "preview-image" #define IMG_CAPTURED_MESSAGE_NAME "image-captured" @@ -267,6 +268,9 @@ static void camerabin_dispose_elements (GstCameraBin * camera); static void gst_camerabin_change_mode (GstCameraBin * camera, gint mode); +static void +gst_camerabin_set_flags (GstCameraBin * camera, GstCameraBinFlags flags); + static void gst_camerabin_change_filename (GstCameraBin * camera, const gchar * name); @@ -393,6 +397,7 @@ gst_camerabin_mode_get_type (void) return gtype; } + static gboolean gst_camerabin_iface_supported (GstImplementsInterface * iface, GType iface_type) { @@ -542,9 +547,10 @@ camerabin_setup_src_elements (GstCameraBin * camera) } /* Set default zoom method */ - g_object_set (camera->src_zoom_scale, "method", - CAMERABIN_DEFAULT_ZOOM_METHOD, NULL); - + if (camera->src_zoom_scale) { + g_object_set (camera->src_zoom_scale, "method", + CAMERABIN_DEFAULT_ZOOM_METHOD, NULL); + } /* we create new caps in any way and they take ownership of the structure st */ gst_caps_replace (&camera->view_finder_caps, new_caps); gst_caps_unref (new_caps); @@ -578,22 +584,24 @@ camerabin_create_src_elements (GstCameraBin * camera) if (!gst_camerabin_add_element (cbin, camera->src_vid_src)) goto done; } -#ifdef USE_COLOR_CONVERTER - if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace")) - goto done; -#endif + if (camera->flags & GST_CAMERABIN_FLAG_SOURCE_COLOR_CONVERSION) { + if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace")) + goto done; + } if (!(camera->src_filter = gst_camerabin_create_and_add_element (cbin, "capsfilter"))) goto done; - if (!(camera->src_zoom_crop = - gst_camerabin_create_and_add_element (cbin, "videocrop"))) - goto done; - if (!(camera->src_zoom_scale = - gst_camerabin_create_and_add_element (cbin, "videoscale"))) - goto done; - if (!(camera->src_zoom_filter = - gst_camerabin_create_and_add_element (cbin, "capsfilter"))) - goto done; + if (camera->flags & GST_CAMERABIN_FLAG_SOURCE_RESIZE) { + if (!(camera->src_zoom_crop = + gst_camerabin_create_and_add_element (cbin, "videocrop"))) + goto done; + if (!(camera->src_zoom_scale = + gst_camerabin_create_and_add_element (cbin, "videoscale"))) + goto done; + if (!(camera->src_zoom_filter = + gst_camerabin_create_and_add_element (cbin, "capsfilter"))) + goto done; + } if (!(camera->src_out_sel = gst_camerabin_create_and_add_element (cbin, "output-selector"))) goto done; @@ -671,24 +679,24 @@ camerabin_create_view_elements (GstCameraBin * camera) } camera->pad_view_src = GST_PAD (pads->data); -#ifdef USE_VIEWFINDER_CONVERTERS /* Add videoscale in case we need to downscale frame for view finder */ - if (!(camera->view_scale = - gst_camerabin_create_and_add_element (cbin, "videoscale"))) { - goto error; - } + if (camera->flags & GST_CAMERABIN_FLAG_VIEWFINDER_SCALE) { + if (!(camera->view_scale = + gst_camerabin_create_and_add_element (cbin, "videoscale"))) { + goto error; + } - /* Add capsfilter to maintain aspect ratio while scaling */ - if (!(camera->aspect_filter = - gst_camerabin_create_and_add_element (cbin, "capsfilter"))) { - goto error; + /* Add capsfilter to maintain aspect ratio while scaling */ + if (!(camera->aspect_filter = + gst_camerabin_create_and_add_element (cbin, "capsfilter"))) { + goto error; + } } -#endif -#ifdef USE_VIEWFINDER_COLOR_CONVERTER - if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace")) { - goto error; + if (camera->flags & GST_CAMERABIN_FLAG_VIEWFINDER_COLOR_CONVERSION) { + if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace")) { + goto error; + } } -#endif /* Add user set or default video sink element */ if (!(camera->view_sink = gst_camerabin_setup_default_element (cbin, camera->user_vf_sink, "autovideosink", DEFAULT_VIDEOSINK))) { @@ -982,6 +990,28 @@ gst_camerabin_change_mode (GstCameraBin * camera, gint mode) } } +/* + * gst_camerabin_set_flags: + * @camera: camerabin object + * @flags: flags for camerabin, videobin and imagebin + * + * Change camerabin capture flags. + */ +static void +gst_camerabin_set_flags (GstCameraBin * camera, GstCameraBinFlags flags) +{ + g_return_if_fail (camera != NULL); + + GST_DEBUG_OBJECT (camera, "setting flags: %d", flags); + + GST_OBJECT_LOCK (camera); + camera->flags = flags; + GST_OBJECT_UNLOCK (camera); + + gst_camerabin_video_set_flags (GST_CAMERABIN_VIDEO (camera->vidbin), flags); + gst_camerabin_image_set_flags (GST_CAMERABIN_IMAGE (camera->imgbin), flags); +} + /* * gst_camerabin_change_filename: * @camera: camerabin object @@ -1407,7 +1437,8 @@ gst_camerabin_set_capsfilter_caps (GstCameraBin * camera, GstCaps * new_caps) /* Update capsfilters */ g_object_set (G_OBJECT (camera->src_filter), "caps", new_caps, NULL); - g_object_set (G_OBJECT (camera->src_zoom_filter), "caps", new_caps, NULL); + if (camera->src_zoom_filter) + g_object_set (G_OBJECT (camera->src_zoom_filter), "caps", new_caps, NULL); gst_camerabin_update_aspect_filter (camera, new_caps); } @@ -1456,27 +1487,29 @@ gst_camerabin_adapt_video_resolution (GstCameraBin * camera, GstCaps * caps) /* Crop if requested aspect ratio differs from incoming frame aspect ratio */ /* Don't override original crop values in case we have zoom applied */ - g_object_get (G_OBJECT (camera->src_zoom_crop), "top", &top, "bottom", - &bottom, "left", &left, "right", &right, NULL); + if (camera->src_zoom_crop) { + g_object_get (G_OBJECT (camera->src_zoom_crop), "top", &top, "bottom", + &bottom, "left", &left, "right", &right, NULL); - ratio_w = (gdouble) width / camera->width; - ratio_h = (gdouble) height / camera->height; + ratio_w = (gdouble) width / camera->width; + ratio_h = (gdouble) height / camera->height; - if (ratio_w < ratio_h) { - crop = height - (camera->height * ratio_w); - top += crop / 2; - bottom += crop / 2; - } else { - crop = width - (camera->width * ratio_h); - left += crop / 2; - right += crop / 2; + if (ratio_w < ratio_h) { + crop = height - (camera->height * ratio_w); + top += crop / 2; + bottom += crop / 2; + } else { + crop = width - (camera->width * ratio_h); + left += crop / 2; + right += crop / 2; + } + + GST_INFO_OBJECT (camera, + "updating crop: left:%d, right:%d, top:%d, bottom:%d", left, right, top, + bottom); + g_object_set (G_OBJECT (camera->src_zoom_crop), "top", top, "bottom", + bottom, "left", left, "right", right, NULL); } - - GST_INFO_OBJECT (camera, - "updating crop: left:%d, right:%d, top:%d, bottom:%d", left, right, top, - bottom); - g_object_set (G_OBJECT (camera->src_zoom_crop), "top", top, "bottom", bottom, - "left", left, "right", right, NULL); } /* @@ -2227,79 +2260,79 @@ gst_camerabin_find_better_framerate (GstCameraBin * camera, GstStructure * st, static void gst_camerabin_update_aspect_filter (GstCameraBin * camera, GstCaps * new_caps) { -#ifdef USE_VIEWFINDER_SCALE - GstCaps *sink_caps, *ar_caps; - GstStructure *st; - gint in_w = 0, in_h = 0, sink_w = 0, sink_h = 0, target_w = 0, target_h = 0; - gdouble ratio_w, ratio_h; - GstPad *sink_pad; - const GValue *range; + if (camera->flags & GST_CAMERABIN_FLAG_VIEWFINDER_SCALE) { + GstCaps *sink_caps, *ar_caps; + GstStructure *st; + gint in_w = 0, in_h = 0, sink_w = 0, sink_h = 0, target_w = 0, target_h = 0; + gdouble ratio_w, ratio_h; + GstPad *sink_pad; + const GValue *range; - sink_pad = gst_element_get_static_pad (camera->view_sink, "sink"); + sink_pad = gst_element_get_static_pad (camera->view_sink, "sink"); - if (sink_pad) { - sink_caps = gst_pad_get_caps (sink_pad); - gst_object_unref (sink_pad); - if (sink_caps) { - if (!gst_caps_is_any (sink_caps)) { - GST_DEBUG_OBJECT (camera, "sink element caps %" GST_PTR_FORMAT, - sink_caps); - /* Get maximum resolution that view finder sink accepts */ - st = gst_caps_get_structure (sink_caps, 0); - if (gst_structure_has_field_typed (st, "width", GST_TYPE_INT_RANGE)) { - range = gst_structure_get_value (st, "width"); - sink_w = gst_value_get_int_range_max (range); - } - if (gst_structure_has_field_typed (st, "height", GST_TYPE_INT_RANGE)) { - range = gst_structure_get_value (st, "height"); - sink_h = gst_value_get_int_range_max (range); - } - GST_DEBUG_OBJECT (camera, "sink element accepts max %dx%d", sink_w, - sink_h); + if (sink_pad) { + sink_caps = gst_pad_get_caps (sink_pad); + gst_object_unref (sink_pad); + if (sink_caps) { + if (!gst_caps_is_any (sink_caps)) { + GST_DEBUG_OBJECT (camera, "sink element caps %" GST_PTR_FORMAT, + sink_caps); + /* Get maximum resolution that view finder sink accepts */ + st = gst_caps_get_structure (sink_caps, 0); + if (gst_structure_has_field_typed (st, "width", GST_TYPE_INT_RANGE)) { + range = gst_structure_get_value (st, "width"); + sink_w = gst_value_get_int_range_max (range); + } + if (gst_structure_has_field_typed (st, "height", GST_TYPE_INT_RANGE)) { + range = gst_structure_get_value (st, "height"); + sink_h = gst_value_get_int_range_max (range); + } + GST_DEBUG_OBJECT (camera, "sink element accepts max %dx%d", sink_w, + sink_h); - /* Get incoming frames' resolution */ - if (sink_h && sink_w) { - st = gst_caps_get_structure (new_caps, 0); - gst_structure_get_int (st, "width", &in_w); - gst_structure_get_int (st, "height", &in_h); - GST_DEBUG_OBJECT (camera, "new caps with %dx%d", in_w, in_h); + /* Get incoming frames' resolution */ + if (sink_h && sink_w) { + st = gst_caps_get_structure (new_caps, 0); + gst_structure_get_int (st, "width", &in_w); + gst_structure_get_int (st, "height", &in_h); + GST_DEBUG_OBJECT (camera, "new caps with %dx%d", in_w, in_h); + } } + gst_caps_unref (sink_caps); } - gst_caps_unref (sink_caps); } - } - /* If we get bigger frames than view finder sink accepts, then we scale. - If we scale we need to adjust aspect ratio capsfilter caps in order - to maintain aspect ratio while scaling. */ - if (in_w && in_h && (in_w > sink_w || in_h > sink_h)) { - ratio_w = (gdouble) sink_w / in_w; - ratio_h = (gdouble) sink_h / in_h; + /* If we get bigger frames than view finder sink accepts, then we scale. + If we scale we need to adjust aspect ratio capsfilter caps in order + to maintain aspect ratio while scaling. */ + if (in_w && in_h && (in_w > sink_w || in_h > sink_h)) { + ratio_w = (gdouble) sink_w / in_w; + ratio_h = (gdouble) sink_h / in_h; - if (ratio_w < ratio_h) { - target_w = sink_w; - target_h = (gint) (ratio_w * in_h); + if (ratio_w < ratio_h) { + target_w = sink_w; + target_h = (gint) (ratio_w * in_h); + } else { + target_w = (gint) (ratio_h * in_w); + target_h = sink_h; + } + + GST_DEBUG_OBJECT (camera, "setting %dx%d filter to maintain aspect ratio", + target_w, target_h); + ar_caps = gst_caps_copy (new_caps); + gst_caps_set_simple (ar_caps, "width", G_TYPE_INT, target_w, "height", + G_TYPE_INT, target_h, NULL); } else { - target_w = (gint) (ratio_h * in_w); - target_h = sink_h; + GST_DEBUG_OBJECT (camera, "no scaling"); + ar_caps = new_caps; } - GST_DEBUG_OBJECT (camera, "setting %dx%d filter to maintain aspect ratio", - target_w, target_h); - ar_caps = gst_caps_copy (new_caps); - gst_caps_set_simple (ar_caps, "width", G_TYPE_INT, target_w, "height", - G_TYPE_INT, target_h, NULL); - } else { - GST_DEBUG_OBJECT (camera, "no scaling"); - ar_caps = new_caps; + GST_DEBUG_OBJECT (camera, "aspect ratio filter caps %" GST_PTR_FORMAT, + ar_caps); + g_object_set (G_OBJECT (camera->aspect_filter), "caps", ar_caps, NULL); + if (ar_caps != new_caps) + gst_caps_unref (ar_caps); } - - GST_DEBUG_OBJECT (camera, "aspect ratio filter caps %" GST_PTR_FORMAT, - ar_caps); - g_object_set (G_OBJECT (camera->aspect_filter), "caps", ar_caps, NULL); - if (ar_caps != new_caps) - gst_caps_unref (ar_caps); -#endif } /* @@ -2315,9 +2348,11 @@ gst_camerabin_finish_image_capture (GstCameraBin * camera) if (camera->image_capture_caps) { /* If we used specific caps for image capture we need to restore the caps and zoom/crop for view finder mode */ - GST_DEBUG_OBJECT (camera, "resetting crop in camerabin"); - g_object_set (camera->src_zoom_crop, "left", 0, "right", 0, - "top", 0, "bottom", 0, NULL); + if (camera->src_zoom_crop) { + GST_DEBUG_OBJECT (camera, "resetting crop in camerabin"); + g_object_set (camera->src_zoom_crop, "left", 0, "right", 0, + "top", 0, "bottom", 0, NULL); + } gst_camerabin_set_capsfilter_caps (camera, camera->view_finder_caps); } } @@ -2385,6 +2420,16 @@ gst_camerabin_class_init (GstCameraBinClass * klass) GST_TYPE_CAMERABIN_MODE, DEFAULT_MODE, G_PARAM_READWRITE)); /** + * GstCameraBin:flags + * + * Control the behaviour of camerabin. + */ + g_object_class_install_property (gobject_class, ARG_FLAGS, + g_param_spec_flags ("flags", "Flags", "Flags to control behaviour", + GST_TYPE_CAMERABIN_FLAGS, DEFAULT_FLAGS, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** * GstCameraBin:mute: * * Mute audio in video recording mode. @@ -2708,6 +2753,7 @@ gst_camerabin_init (GstCameraBin * camera, GstCameraBinClass * gclass) camera->filename = g_string_new (""); camera->mode = DEFAULT_MODE; + camera->flags = DEFAULT_FLAGS; camera->stop_requested = FALSE; camera->paused = FALSE; camera->capturing = FALSE; @@ -2828,6 +2874,9 @@ gst_camerabin_set_property (GObject * object, guint prop_id, case ARG_MODE: gst_camerabin_change_mode (camera, g_value_get_enum (value)); break; + case ARG_FLAGS: + gst_camerabin_set_flags (camera, g_value_get_flags (value)); + break; case ARG_FILENAME: gst_camerabin_change_filename (camera, g_value_get_string (value)); break; @@ -2973,6 +3022,9 @@ gst_camerabin_get_property (GObject * object, guint prop_id, case ARG_MODE: g_value_set_enum (value, camera->mode); break; + case ARG_FLAGS: + g_value_set_flags (value, camera->flags); + break; case ARG_MUTE: g_value_set_boolean (value, gst_camerabin_video_get_mute (GST_CAMERABIN_VIDEO (camera->vidbin))); diff --git a/gst/camerabin/gstcamerabin.h b/gst/camerabin/gstcamerabin.h index 915d9b7bd3..ef8a9a122f 100644 --- a/gst/camerabin/gstcamerabin.h +++ b/gst/camerabin/gstcamerabin.h @@ -28,6 +28,7 @@ #include #include +#include "gstcamerabin-enum.h" #include "camerabinimage.h" #include "camerabinvideo.h" @@ -58,9 +59,10 @@ struct _GstCameraBin /* private */ GString *filename; - gint mode; /* MODE_IMAGE or MODE_VIDEO */ - gboolean stop_requested; /* TRUE if capturing stop needed */ - gboolean paused; /* TRUE if capturing paused */ + gint mode; /* MODE_IMAGE or MODE_VIDEO */ + GstCameraBinFlags flags; + gboolean stop_requested; /* TRUE if capturing stop needed */ + gboolean paused; /* TRUE if capturing paused */ /* resolution and frames per second of image captured by v4l2 device */ gint width;