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 \
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

View file

@ -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)
{

View file

@ -23,6 +23,8 @@
#include <gst/gstbin.h>
#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);

View file

@ -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)
{

View file

@ -23,6 +23,8 @@
#include <gst/gstbin.h>
#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);

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_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)));

View file

@ -28,6 +28,7 @@
#include <gst/gstbin.h>
#include <gst/interfaces/photography.h>
#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;