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.
This commit is contained in:
Teemu Katajisto 2009-10-28 12:47:19 +02:00 committed by Stefan Kost
parent 7d65643656
commit 7dac3659c6
9 changed files with 400 additions and 182 deletions

View file

@ -20,7 +20,8 @@ libgstcamerabin_la_SOURCES = gstcamerabin.c \
camerabinvideo.c \ camerabinvideo.c \
camerabingeneral.c \ camerabingeneral.c \
camerabinpreview.c \ camerabinpreview.c \
gstcamerabinphotography.c gstcamerabinphotography.c \
gstcamerabin-enum.c
nodist_libgstcamerabin_la_SOURCES = $(built_sources) nodist_libgstcamerabin_la_SOURCES = $(built_sources)
libgstcamerabin_la_CFLAGS = \ libgstcamerabin_la_CFLAGS = \
@ -41,4 +42,5 @@ noinst_HEADERS = gstcamerabin.h \
camerabinvideo.h \ camerabinvideo.h \
camerabingeneral.h \ camerabingeneral.h \
camerabinpreview.h \ camerabinpreview.h \
gstcamerabinphotography.h gstcamerabinphotography.h \
gstcamerabin-enum.h

View file

@ -52,6 +52,7 @@
#include "camerabinimage.h" #include "camerabinimage.h"
#include "camerabingeneral.h" #include "camerabingeneral.h"
#include "gstcamerabin-enum.h"
#include "string.h" #include "string.h"
@ -60,6 +61,7 @@
#define DEFAULT_SINK "filesink" #define DEFAULT_SINK "filesink"
#define DEFAULT_ENC "jpegenc" #define DEFAULT_ENC "jpegenc"
#define DEFAULT_META_MUX "metadatamux" #define DEFAULT_META_MUX "metadatamux"
#define DEFAULT_FLAGS GST_CAMERABIN_FLAG_IMAGE_COLOR_CONVERSION
enum enum
{ {
@ -157,6 +159,7 @@ gst_camerabin_image_init (GstCameraBinImage * img,
gst_element_add_pad (GST_ELEMENT (img), img->sinkpad); gst_element_add_pad (GST_ELEMENT (img), img->sinkpad);
img->elements_created = FALSE; img->elements_created = FALSE;
img->flags = DEFAULT_FLAGS;
} }
static void static void
@ -425,17 +428,15 @@ gst_camerabin_image_create_elements (GstCameraBinImage * img)
img_sinkpad = gst_element_get_static_pad (img->post, "sink"); img_sinkpad = gst_element_get_static_pad (img->post, "sink");
} }
/* Add colorspace converter */ if (img->flags & GST_CAMERABIN_FLAG_IMAGE_COLOR_CONVERSION) {
if (!(csp = /* Add colorspace converter */
gst_camerabin_create_and_add_element (imgbin, "ffmpegcolorspace"))) { if (!(csp =
goto done; gst_camerabin_create_and_add_element (imgbin,
} "ffmpegcolorspace"))) {
goto done;
/* Set up sink ghost pad for img bin */ }
if (!img_sinkpad) {
img_sinkpad = gst_element_get_static_pad (csp, "sink"); img_sinkpad = gst_element_get_static_pad (csp, "sink");
} }
gst_ghost_pad_set_target (GST_GHOST_PAD (img->sinkpad), img_sinkpad);
/* Create image encoder */ /* Create image encoder */
if (img->user_enc) { 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 */ g_object_set (G_OBJECT (img->sink), "location", img->filename->str, "async", FALSE, "buffer-mode", 2, /* non buffered io */
NULL); 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; ret = TRUE;
done: done:
@ -535,6 +542,13 @@ gst_camerabin_image_set_postproc (GstCameraBinImage * img,
img->post = postproc; 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 * GstElement *
gst_camerabin_image_get_encoder (GstCameraBinImage * img) gst_camerabin_image_get_encoder (GstCameraBinImage * img)
{ {

View file

@ -23,6 +23,8 @@
#include <gst/gstbin.h> #include <gst/gstbin.h>
#include "gstcamerabin-enum.h"
G_BEGIN_DECLS G_BEGIN_DECLS
#define GST_TYPE_CAMERABIN_IMAGE (gst_camerabin_image_get_type()) #define GST_TYPE_CAMERABIN_IMAGE (gst_camerabin_image_get_type())
#define GST_CAMERABIN_IMAGE_CAST(obj) ((GstCameraBinImage*)(obj)) #define GST_CAMERABIN_IMAGE_CAST(obj) ((GstCameraBinImage*)(obj))
@ -53,6 +55,7 @@ struct _GstCameraBinImage
GstElement *sink; GstElement *sink;
gboolean elements_created; gboolean elements_created;
GstCameraBinFlags flags;
}; };
struct _GstCameraBinImageClass struct _GstCameraBinImageClass
@ -69,6 +72,10 @@ void
gst_camerabin_image_set_postproc (GstCameraBinImage * img, gst_camerabin_image_set_postproc (GstCameraBinImage * img,
GstElement * postproc); 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_encoder (GstCameraBinImage * img);
GstElement *gst_camerabin_image_get_postproc (GstCameraBinImage * img); GstElement *gst_camerabin_image_get_postproc (GstCameraBinImage * img);

View file

@ -71,7 +71,7 @@
#define DEFAULT_MUX "oggmux" #define DEFAULT_MUX "oggmux"
#define DEFAULT_SINK "filesink" #define DEFAULT_SINK "filesink"
#define USE_AUDIO_CONVERSION 1 #define DEFAULT_FLAGS 0
enum enum
{ {
@ -187,6 +187,7 @@ gst_camerabin_video_init (GstCameraBinVideo * vid,
vid->pending_eos = NULL; vid->pending_eos = NULL;
vid->mute = ARG_DEFAULT_MUTE; vid->mute = ARG_DEFAULT_MUTE;
vid->flags = DEFAULT_FLAGS;
vid->aud_src_probe_id = 0; vid->aud_src_probe_id = 0;
vid->vid_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 */ /* Add queue element for video */
vid->tee_video_srcpad = gst_element_get_request_pad (vid->tee, "src%d"); vid->tee_video_srcpad = gst_element_get_request_pad (vid->tee, "src%d");
if (!(vid->video_queue = if (!(vid->video_queue =
gst_camerabin_create_and_add_element (vidbin, "queue"))) { gst_camerabin_create_and_add_element (vidbin, "queue"))) {
goto error; 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 */ g_object_set (G_OBJECT (vid->sink), "location", vid->filename->str, "buffer-mode", 2, /* non buffered io */
NULL); NULL);
/* Add user set or default audio source element */ if (!(vid->flags & GST_CAMERABIN_FLAG_DISABLE_AUDIO)) {
if (!(vid->aud_src = gst_camerabin_setup_default_element (vidbin, /* Add user set or default audio source element */
vid->user_aud_src, "autoaudiosrc", DEFAULT_AUDIOSRC))) { if (!(vid->aud_src = gst_camerabin_setup_default_element (vidbin,
vid->aud_src = NULL; vid->user_aud_src, "autoaudiosrc", DEFAULT_AUDIOSRC))) {
goto error; vid->aud_src = NULL;
} else {
if (!gst_camerabin_add_element (vidbin, vid->aud_src))
goto error; goto error;
} } else {
if (!gst_camerabin_add_element (vidbin, vid->aud_src))
goto error;
}
/* Add queue element for audio */ /* Add queue element for audio */
if (!(gst_camerabin_create_and_add_element (vidbin, "queue"))) { 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)) {
goto error; 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 */ /* Add optional audio conversion and volume elements and
if (!gst_element_link (vid->aud_enc, vid->muxer)) { raise no errors if adding them fails */
GST_ELEMENT_ERROR (vid, CORE, NEGOTIATION, (NULL), if (vid->flags & GST_CAMERABIN_FLAG_AUDIO_CONVERSION) {
("linking audio encoder and muxer failed")); if (!gst_camerabin_try_add_element (vidbin,
goto error; 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 */ /* 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"); vid->tee_vf_srcpad = gst_element_get_request_pad (vid->tee, "src%d");
if (!(queue = gst_camerabin_create_and_add_element (vidbin, "queue"))) { 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); G_CALLBACK (gst_camerabin_drop_eos_probe), vid);
gst_object_unref (vid_srcpad); gst_object_unref (vid_srcpad);
pad = gst_element_get_static_pad (vid->aud_src, "src"); if (!(vid->flags & GST_CAMERABIN_FLAG_DISABLE_AUDIO)) {
vid->aud_src_probe_id = gst_pad_add_buffer_probe (pad, pad = gst_element_get_static_pad (vid->aud_src, "src");
G_CALLBACK (camerabin_video_pad_aud_src_have_buffer), vid); vid->aud_src_probe_id = gst_pad_add_buffer_probe (pad,
gst_object_unref (pad); G_CALLBACK (camerabin_video_pad_aud_src_have_buffer), vid);
gst_object_unref (pad);
}
GST_DEBUG ("created video elements"); GST_DEBUG ("created video elements");
return TRUE; return TRUE;
@ -841,6 +846,16 @@ gst_camerabin_video_set_audio_src (GstCameraBinVideo * vid,
GST_OBJECT_UNLOCK (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 gboolean
gst_camerabin_video_get_mute (GstCameraBinVideo * vid) gst_camerabin_video_get_mute (GstCameraBinVideo * vid)
{ {

View file

@ -23,6 +23,8 @@
#include <gst/gstbin.h> #include <gst/gstbin.h>
#include "gstcamerabin-enum.h"
G_BEGIN_DECLS G_BEGIN_DECLS
#define ARG_DEFAULT_MUTE FALSE #define ARG_DEFAULT_MUTE FALSE
#define GST_TYPE_CAMERABIN_VIDEO (gst_camerabin_video_get_type()) #define GST_TYPE_CAMERABIN_VIDEO (gst_camerabin_video_get_type())
@ -88,6 +90,7 @@ struct _GstCameraBinVideo
gulong vid_sink_probe_id; gulong vid_sink_probe_id;
gboolean mute; gboolean mute;
GstCameraBinFlags flags;
}; };
struct _GstCameraBinVideoClass struct _GstCameraBinVideoClass
@ -120,6 +123,10 @@ void
gst_camerabin_video_set_audio_src (GstCameraBinVideo * vid, gst_camerabin_video_set_audio_src (GstCameraBinVideo * vid,
GstElement * audio_src); GstElement * audio_src);
void
gst_camerabin_video_set_flags (GstCameraBinVideo * vid,
GstCameraBinFlags flags);
gboolean gst_camerabin_video_get_mute (GstCameraBinVideo * vid); gboolean gst_camerabin_video_get_mute (GstCameraBinVideo * vid);

View file

@ -0,0 +1,59 @@
/*
* GStreamer
* Copyright (C) 2009 Nokia Corporation <multimedia@maemo.org>
*
* 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;
}

View file

@ -0,0 +1,60 @@
/*
* GStreamer
* Copyright (C) 2009 Nokia Corporation <multimedia@maemo.org>
*
* 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 <gst/gst.h>
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__ */

View file

@ -190,6 +190,7 @@ enum
ARG_0, ARG_0,
ARG_FILENAME, ARG_FILENAME,
ARG_MODE, ARG_MODE,
ARG_FLAGS,
ARG_MUTE, ARG_MUTE,
ARG_ZOOM, ARG_ZOOM,
ARG_IMAGE_POST, ARG_IMAGE_POST,
@ -229,6 +230,10 @@ static guint camerabin_signals[LAST_SIGNAL];
#define CAMERABIN_MAX_VF_WIDTH 848 #define CAMERABIN_MAX_VF_WIDTH 848
#define CAMERABIN_MAX_VF_HEIGHT 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 */ /* Using "bilinear" as default zoom method */
#define CAMERABIN_DEFAULT_ZOOM_METHOD 1 #define CAMERABIN_DEFAULT_ZOOM_METHOD 1
@ -239,10 +244,6 @@ static guint camerabin_signals[LAST_SIGNAL];
/* FIXME: this is v4l2camsrc specific */ /* FIXME: this is v4l2camsrc specific */
#define DEFAULT_V4L2CAMSRC_DRIVER_NAME "omap3cam" #define DEFAULT_V4L2CAMSRC_DRIVER_NAME "omap3cam"
/* pipeline configuration */
//#define USE_VIEWFINDER_COLOR_CONVERTER 1
//#define USE_VIEWFINDER_SCALE 1
/* message names */ /* message names */
#define PREVIEW_MESSAGE_NAME "preview-image" #define PREVIEW_MESSAGE_NAME "preview-image"
#define IMG_CAPTURED_MESSAGE_NAME "image-captured" #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_change_mode (GstCameraBin * camera, gint mode);
static void
gst_camerabin_set_flags (GstCameraBin * camera, GstCameraBinFlags flags);
static void static void
gst_camerabin_change_filename (GstCameraBin * camera, const gchar * name); gst_camerabin_change_filename (GstCameraBin * camera, const gchar * name);
@ -393,6 +397,7 @@ gst_camerabin_mode_get_type (void)
return gtype; return gtype;
} }
static gboolean static gboolean
gst_camerabin_iface_supported (GstImplementsInterface * iface, GType iface_type) gst_camerabin_iface_supported (GstImplementsInterface * iface, GType iface_type)
{ {
@ -542,9 +547,10 @@ camerabin_setup_src_elements (GstCameraBin * camera)
} }
/* Set default zoom method */ /* Set default zoom method */
g_object_set (camera->src_zoom_scale, "method", if (camera->src_zoom_scale) {
CAMERABIN_DEFAULT_ZOOM_METHOD, NULL); 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 */ /* 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_replace (&camera->view_finder_caps, new_caps);
gst_caps_unref (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)) if (!gst_camerabin_add_element (cbin, camera->src_vid_src))
goto done; goto done;
} }
#ifdef USE_COLOR_CONVERTER if (camera->flags & GST_CAMERABIN_FLAG_SOURCE_COLOR_CONVERSION) {
if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace")) if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace"))
goto done; goto done;
#endif }
if (!(camera->src_filter = if (!(camera->src_filter =
gst_camerabin_create_and_add_element (cbin, "capsfilter"))) gst_camerabin_create_and_add_element (cbin, "capsfilter")))
goto done; goto done;
if (!(camera->src_zoom_crop = if (camera->flags & GST_CAMERABIN_FLAG_SOURCE_RESIZE) {
gst_camerabin_create_and_add_element (cbin, "videocrop"))) if (!(camera->src_zoom_crop =
goto done; gst_camerabin_create_and_add_element (cbin, "videocrop")))
if (!(camera->src_zoom_scale = goto done;
gst_camerabin_create_and_add_element (cbin, "videoscale"))) if (!(camera->src_zoom_scale =
goto done; gst_camerabin_create_and_add_element (cbin, "videoscale")))
if (!(camera->src_zoom_filter = goto done;
gst_camerabin_create_and_add_element (cbin, "capsfilter"))) if (!(camera->src_zoom_filter =
goto done; gst_camerabin_create_and_add_element (cbin, "capsfilter")))
goto done;
}
if (!(camera->src_out_sel = if (!(camera->src_out_sel =
gst_camerabin_create_and_add_element (cbin, "output-selector"))) gst_camerabin_create_and_add_element (cbin, "output-selector")))
goto done; goto done;
@ -671,24 +679,24 @@ camerabin_create_view_elements (GstCameraBin * camera)
} }
camera->pad_view_src = GST_PAD (pads->data); camera->pad_view_src = GST_PAD (pads->data);
#ifdef USE_VIEWFINDER_CONVERTERS
/* Add videoscale in case we need to downscale frame for view finder */ /* Add videoscale in case we need to downscale frame for view finder */
if (!(camera->view_scale = if (camera->flags & GST_CAMERABIN_FLAG_VIEWFINDER_SCALE) {
gst_camerabin_create_and_add_element (cbin, "videoscale"))) { if (!(camera->view_scale =
goto error; gst_camerabin_create_and_add_element (cbin, "videoscale"))) {
} goto error;
}
/* Add capsfilter to maintain aspect ratio while scaling */ /* Add capsfilter to maintain aspect ratio while scaling */
if (!(camera->aspect_filter = if (!(camera->aspect_filter =
gst_camerabin_create_and_add_element (cbin, "capsfilter"))) { gst_camerabin_create_and_add_element (cbin, "capsfilter"))) {
goto error; goto error;
}
} }
#endif if (camera->flags & GST_CAMERABIN_FLAG_VIEWFINDER_COLOR_CONVERSION) {
#ifdef USE_VIEWFINDER_COLOR_CONVERTER if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace")) {
if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace")) { goto error;
goto error; }
} }
#endif
/* Add user set or default video sink element */ /* Add user set or default video sink element */
if (!(camera->view_sink = gst_camerabin_setup_default_element (cbin, if (!(camera->view_sink = gst_camerabin_setup_default_element (cbin,
camera->user_vf_sink, "autovideosink", DEFAULT_VIDEOSINK))) { 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: * gst_camerabin_change_filename:
* @camera: camerabin object * @camera: camerabin object
@ -1407,7 +1437,8 @@ gst_camerabin_set_capsfilter_caps (GstCameraBin * camera, GstCaps * new_caps)
/* Update capsfilters */ /* Update capsfilters */
g_object_set (G_OBJECT (camera->src_filter), "caps", new_caps, NULL); 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); 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 */ /* Crop if requested aspect ratio differs from incoming frame aspect ratio */
/* Don't override original crop values in case we have zoom applied */ /* Don't override original crop values in case we have zoom applied */
g_object_get (G_OBJECT (camera->src_zoom_crop), "top", &top, "bottom", if (camera->src_zoom_crop) {
&bottom, "left", &left, "right", &right, NULL); 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_w = (gdouble) width / camera->width;
ratio_h = (gdouble) height / camera->height; ratio_h = (gdouble) height / camera->height;
if (ratio_w < ratio_h) { if (ratio_w < ratio_h) {
crop = height - (camera->height * ratio_w); crop = height - (camera->height * ratio_w);
top += crop / 2; top += crop / 2;
bottom += crop / 2; bottom += crop / 2;
} else { } else {
crop = width - (camera->width * ratio_h); crop = width - (camera->width * ratio_h);
left += crop / 2; left += crop / 2;
right += 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 static void
gst_camerabin_update_aspect_filter (GstCameraBin * camera, GstCaps * new_caps) gst_camerabin_update_aspect_filter (GstCameraBin * camera, GstCaps * new_caps)
{ {
#ifdef USE_VIEWFINDER_SCALE if (camera->flags & GST_CAMERABIN_FLAG_VIEWFINDER_SCALE) {
GstCaps *sink_caps, *ar_caps; GstCaps *sink_caps, *ar_caps;
GstStructure *st; GstStructure *st;
gint in_w = 0, in_h = 0, sink_w = 0, sink_h = 0, target_w = 0, target_h = 0; gint in_w = 0, in_h = 0, sink_w = 0, sink_h = 0, target_w = 0, target_h = 0;
gdouble ratio_w, ratio_h; gdouble ratio_w, ratio_h;
GstPad *sink_pad; GstPad *sink_pad;
const GValue *range; 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) { if (sink_pad) {
sink_caps = gst_pad_get_caps (sink_pad); sink_caps = gst_pad_get_caps (sink_pad);
gst_object_unref (sink_pad); gst_object_unref (sink_pad);
if (sink_caps) { if (sink_caps) {
if (!gst_caps_is_any (sink_caps)) { if (!gst_caps_is_any (sink_caps)) {
GST_DEBUG_OBJECT (camera, "sink element caps %" GST_PTR_FORMAT, GST_DEBUG_OBJECT (camera, "sink element caps %" GST_PTR_FORMAT,
sink_caps); sink_caps);
/* Get maximum resolution that view finder sink accepts */ /* Get maximum resolution that view finder sink accepts */
st = gst_caps_get_structure (sink_caps, 0); st = gst_caps_get_structure (sink_caps, 0);
if (gst_structure_has_field_typed (st, "width", GST_TYPE_INT_RANGE)) { if (gst_structure_has_field_typed (st, "width", GST_TYPE_INT_RANGE)) {
range = gst_structure_get_value (st, "width"); range = gst_structure_get_value (st, "width");
sink_w = gst_value_get_int_range_max (range); sink_w = gst_value_get_int_range_max (range);
} }
if (gst_structure_has_field_typed (st, "height", GST_TYPE_INT_RANGE)) { if (gst_structure_has_field_typed (st, "height", GST_TYPE_INT_RANGE)) {
range = gst_structure_get_value (st, "height"); range = gst_structure_get_value (st, "height");
sink_h = gst_value_get_int_range_max (range); sink_h = gst_value_get_int_range_max (range);
} }
GST_DEBUG_OBJECT (camera, "sink element accepts max %dx%d", sink_w, GST_DEBUG_OBJECT (camera, "sink element accepts max %dx%d", sink_w,
sink_h); sink_h);
/* Get incoming frames' resolution */ /* Get incoming frames' resolution */
if (sink_h && sink_w) { if (sink_h && sink_w) {
st = gst_caps_get_structure (new_caps, 0); st = gst_caps_get_structure (new_caps, 0);
gst_structure_get_int (st, "width", &in_w); gst_structure_get_int (st, "width", &in_w);
gst_structure_get_int (st, "height", &in_h); gst_structure_get_int (st, "height", &in_h);
GST_DEBUG_OBJECT (camera, "new caps with %dx%d", in_w, 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 get bigger frames than view finder sink accepts, then we scale.
If we scale we need to adjust aspect ratio capsfilter caps in order If we scale we need to adjust aspect ratio capsfilter caps in order
to maintain aspect ratio while scaling. */ to maintain aspect ratio while scaling. */
if (in_w && in_h && (in_w > sink_w || in_h > sink_h)) { if (in_w && in_h && (in_w > sink_w || in_h > sink_h)) {
ratio_w = (gdouble) sink_w / in_w; ratio_w = (gdouble) sink_w / in_w;
ratio_h = (gdouble) sink_h / in_h; ratio_h = (gdouble) sink_h / in_h;
if (ratio_w < ratio_h) { if (ratio_w < ratio_h) {
target_w = sink_w; target_w = sink_w;
target_h = (gint) (ratio_w * in_h); 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 { } else {
target_w = (gint) (ratio_h * in_w); GST_DEBUG_OBJECT (camera, "no scaling");
target_h = sink_h; ar_caps = new_caps;
} }
GST_DEBUG_OBJECT (camera, "setting %dx%d filter to maintain aspect ratio", GST_DEBUG_OBJECT (camera, "aspect ratio filter caps %" GST_PTR_FORMAT,
target_w, target_h); ar_caps);
ar_caps = gst_caps_copy (new_caps); g_object_set (G_OBJECT (camera->aspect_filter), "caps", ar_caps, NULL);
gst_caps_set_simple (ar_caps, "width", G_TYPE_INT, target_w, "height", if (ar_caps != new_caps)
G_TYPE_INT, target_h, NULL); gst_caps_unref (ar_caps);
} 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);
#endif
} }
/* /*
@ -2315,9 +2348,11 @@ gst_camerabin_finish_image_capture (GstCameraBin * camera)
if (camera->image_capture_caps) { if (camera->image_capture_caps) {
/* If we used specific caps for image capture we need to /* If we used specific caps for image capture we need to
restore the caps and zoom/crop for view finder mode */ restore the caps and zoom/crop for view finder mode */
GST_DEBUG_OBJECT (camera, "resetting crop in camerabin"); if (camera->src_zoom_crop) {
g_object_set (camera->src_zoom_crop, "left", 0, "right", 0, GST_DEBUG_OBJECT (camera, "resetting crop in camerabin");
"top", 0, "bottom", 0, NULL); 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); 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)); 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: * GstCameraBin:mute:
* *
* Mute audio in video recording mode. * Mute audio in video recording mode.
@ -2708,6 +2753,7 @@ gst_camerabin_init (GstCameraBin * camera, GstCameraBinClass * gclass)
camera->filename = g_string_new (""); camera->filename = g_string_new ("");
camera->mode = DEFAULT_MODE; camera->mode = DEFAULT_MODE;
camera->flags = DEFAULT_FLAGS;
camera->stop_requested = FALSE; camera->stop_requested = FALSE;
camera->paused = FALSE; camera->paused = FALSE;
camera->capturing = FALSE; camera->capturing = FALSE;
@ -2828,6 +2874,9 @@ gst_camerabin_set_property (GObject * object, guint prop_id,
case ARG_MODE: case ARG_MODE:
gst_camerabin_change_mode (camera, g_value_get_enum (value)); gst_camerabin_change_mode (camera, g_value_get_enum (value));
break; break;
case ARG_FLAGS:
gst_camerabin_set_flags (camera, g_value_get_flags (value));
break;
case ARG_FILENAME: case ARG_FILENAME:
gst_camerabin_change_filename (camera, g_value_get_string (value)); gst_camerabin_change_filename (camera, g_value_get_string (value));
break; break;
@ -2973,6 +3022,9 @@ gst_camerabin_get_property (GObject * object, guint prop_id,
case ARG_MODE: case ARG_MODE:
g_value_set_enum (value, camera->mode); g_value_set_enum (value, camera->mode);
break; break;
case ARG_FLAGS:
g_value_set_flags (value, camera->flags);
break;
case ARG_MUTE: case ARG_MUTE:
g_value_set_boolean (value, g_value_set_boolean (value,
gst_camerabin_video_get_mute (GST_CAMERABIN_VIDEO (camera->vidbin))); gst_camerabin_video_get_mute (GST_CAMERABIN_VIDEO (camera->vidbin)));

View file

@ -28,6 +28,7 @@
#include <gst/gstbin.h> #include <gst/gstbin.h>
#include <gst/interfaces/photography.h> #include <gst/interfaces/photography.h>
#include "gstcamerabin-enum.h"
#include "camerabinimage.h" #include "camerabinimage.h"
#include "camerabinvideo.h" #include "camerabinvideo.h"
@ -58,9 +59,10 @@ struct _GstCameraBin
/* private */ /* private */
GString *filename; GString *filename;
gint mode; /* MODE_IMAGE or MODE_VIDEO */ gint mode; /* MODE_IMAGE or MODE_VIDEO */
gboolean stop_requested; /* TRUE if capturing stop needed */ GstCameraBinFlags flags;
gboolean paused; /* TRUE if capturing paused */ 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 */ /* resolution and frames per second of image captured by v4l2 device */
gint width; gint width;