rpicamsrc: Update properties dynamically where possible

Update camera and encoder properties at runtime
where possible

Fixes https://github.com/thaytan/gst-rpicamsrc/issues/19
and https://github.com/thaytan/gst-rpicamsrc/issues/23
This commit is contained in:
Jan Schmidt 2015-04-27 00:54:54 +10:00 committed by Tim-Philipp Müller
parent 1610030b40
commit 3b85ddd90e
4 changed files with 253 additions and 40 deletions

View file

@ -111,7 +111,7 @@ typedef struct
struct RASPIVID_STATE_T
{
RASPIVID_CONFIG *config;
RASPIVID_CONFIG config;
FILE *output_file;
@ -132,6 +132,8 @@ struct RASPIVID_STATE_T
int64_t base_time;
int64_t last_second;
RASPIPREVIEW_STATE preview_state;
};
@ -294,18 +296,23 @@ void raspicapture_default_config(RASPIVID_CONFIG *config)
*/
static void dump_state(RASPIVID_STATE *state)
{
RASPIVID_CONFIG *config;
if (!state)
{
vcos_assert(0);
return;
}
fprintf(stderr, "Width %d, Height %d\n", state->config->width, state->config->height);
fprintf(stderr, "bitrate %d, framerate %d/%d, time delay %d\n", state->config->bitrate, state->config->fps_n, state->config->fps_d, state->config->timeout);
//fprintf(stderr, "H264 Profile %s\n", raspicli_unmap_xref(state->config->profile, profile_map, profile_map_size));
config = &state->config;
raspipreview_dump_parameters(&state->config->preview_parameters);
raspicamcontrol_dump_parameters(&state->config->camera_parameters);
fprintf(stderr, "Width %d, Height %d\n", config->width, config->height);
fprintf(stderr, "bitrate %d, framerate %d/%d, time delay %d\n",
config->bitrate, config->fps_n, config->fps_d, config->timeout);
//fprintf(stderr, "H264 Profile %s\n", raspicli_unmap_xref(config->profile, profile_map, profile_map_size));
raspipreview_dump_parameters(&config->preview_parameters);
raspicamcontrol_dump_parameters(&config->camera_parameters);
}
#if 0
@ -623,7 +630,7 @@ static int parse_cmdline(int argc, const char **argv, RASPIVID_STATE *state)
case CommandIntraRefreshType:
{
state->config->intra_refresh_type = raspicli_map_xref(argv[i + 1], intra_refresh_map, intra_refresh_map_size);
state->config.intra_refresh_type = raspicli_map_xref(argv[i + 1], intra_refresh_map, intra_refresh_map_size);
i++;
break;
}
@ -843,7 +850,7 @@ static FILE *open_imv_filename(RASPIVID_STATE *pState)
*/
static void update_annotation_data(RASPIVID_STATE *state)
{
RASPIVID_CONFIG *config = state->config;
RASPIVID_CONFIG *config = &state->config;
// So, if we have asked for a application supplied string, set it to the H264 parameters
if (config->camera_parameters.enable_annotate & ANNOTATE_APP_TEXT)
@ -1000,7 +1007,7 @@ static MMAL_STATUS_T create_camera_component(RASPIVID_STATE *state)
{
MMAL_COMPONENT_T *camera = NULL;
MMAL_STATUS_T status;
RASPIVID_CONFIG *config = state->config;
RASPIVID_CONFIG *config = &state->config;
/* Create the component */
status = mmal_component_create(MMAL_COMPONENT_DEFAULT_CAMERA, &camera);
@ -1077,7 +1084,7 @@ raspi_capture_set_format_and_start(RASPIVID_STATE *state)
MMAL_STATUS_T status;
MMAL_ES_FORMAT_T *format;
MMAL_PORT_T *preview_port = NULL, *video_port = NULL, *still_port = NULL;
RASPIVID_CONFIG *config = state->config;
RASPIVID_CONFIG *config = &state->config;
// set up the camera configuration
@ -1294,7 +1301,7 @@ static MMAL_STATUS_T create_encoder_component(RASPIVID_STATE *state)
MMAL_PORT_T *encoder_input = NULL, *encoder_output = NULL;
MMAL_STATUS_T status;
MMAL_POOL_T *pool;
RASPIVID_CONFIG *config = state->config;
RASPIVID_CONFIG *config = &state->config;
status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_ENCODER, &encoder);
@ -1363,7 +1370,7 @@ static MMAL_STATUS_T create_encoder_component(RASPIVID_STATE *state)
if (config->intraperiod != -1)
{
MMAL_PARAMETER_UINT32_T param = {{ MMAL_PARAMETER_INTRAPERIOD, sizeof(param)}, state->config->intraperiod};
MMAL_PARAMETER_UINT32_T param = {{ MMAL_PARAMETER_INTRAPERIOD, sizeof(param)}, config->intraperiod};
status = mmal_port_parameter_set(encoder_output, &param.hdr);
if (status != MMAL_SUCCESS)
{
@ -1374,7 +1381,7 @@ static MMAL_STATUS_T create_encoder_component(RASPIVID_STATE *state)
if (config->quantisationParameter)
{
MMAL_PARAMETER_UINT32_T param = {{ MMAL_PARAMETER_VIDEO_ENCODE_INITIAL_QUANT, sizeof(param)}, state->config->quantisationParameter};
MMAL_PARAMETER_UINT32_T param = {{ MMAL_PARAMETER_VIDEO_ENCODE_INITIAL_QUANT, sizeof(param)}, config->quantisationParameter};
status = mmal_port_parameter_set(encoder_output, &param.hdr);
if (status != MMAL_SUCCESS)
{
@ -1587,7 +1594,7 @@ raspi_capture_setup(RASPIVID_CONFIG *config)
state = calloc(1, sizeof(RASPIVID_STATE));
/* Apply passed in config */
state->config = config;
state->config = *config;
/* Initialize timestamping */
state->base_time = state->last_second = -1;
@ -1604,7 +1611,7 @@ raspi_capture_setup(RASPIVID_CONFIG *config)
return NULL;
}
if ((status = raspipreview_create(&state->config->preview_parameters)) != MMAL_SUCCESS)
if ((status = raspipreview_create(&state->preview_state, &config->preview_parameters)) != MMAL_SUCCESS)
{
vcos_log_error("%s: Failed to create preview component", __func__);
destroy_camera_component(state);
@ -1620,6 +1627,8 @@ gboolean
raspi_capture_start(RASPIVID_STATE *state)
{
MMAL_STATUS_T status = MMAL_SUCCESS;
RASPIVID_CONFIG *config = &state->config;
MMAL_PORT_T *camera_preview_port = NULL;
MMAL_PORT_T *preview_input_port = NULL;
MMAL_PORT_T *encoder_input_port = NULL;
@ -1630,7 +1639,7 @@ raspi_capture_start(RASPIVID_STATE *state)
return FALSE;
}
if (state->config->verbose)
if (config->verbose)
{
dump_state(state);
}
@ -1639,20 +1648,20 @@ raspi_capture_start(RASPIVID_STATE *state)
return FALSE;
}
if (state->config->verbose)
if (state->config.verbose)
fprintf(stderr, "Starting component connection stage\n");
camera_preview_port = state->camera_component->output[MMAL_CAMERA_PREVIEW_PORT];
preview_input_port = state->config->preview_parameters.preview_component->input[0];
preview_input_port = state->preview_state.preview_component->input[0];
encoder_input_port = state->encoder_component->input[0];
state->camera_video_port = state->camera_component->output[MMAL_CAMERA_VIDEO_PORT];
state->camera_still_port = state->camera_component->output[MMAL_CAMERA_CAPTURE_PORT];
state->encoder_output_port = state->encoder_component->output[0];
if (state->config->preview_parameters.wantPreview )
if (config->preview_parameters.wantPreview )
{
if (state->config->verbose)
if (config->verbose)
{
fprintf(stderr, "Connecting camera preview port to preview input port\n");
fprintf(stderr, "Starting video preview\n");
@ -1667,14 +1676,14 @@ raspi_capture_start(RASPIVID_STATE *state)
}
}
if (state->config->verbose)
if (config->verbose)
fprintf(stderr, "Connecting camera stills port to encoder input port\n");
// Now connect the camera to the encoder
status = connect_ports(state->camera_video_port, encoder_input_port, &state->encoder_connection);
if (status != MMAL_SUCCESS)
{
if (state->config->preview_parameters.wantPreview )
if (config->preview_parameters.wantPreview )
mmal_connection_destroy(state->preview_connection);
vcos_log_error("%s: Failed to connect camera video port to encoder input", __func__);
return FALSE;
@ -1686,7 +1695,7 @@ raspi_capture_start(RASPIVID_STATE *state)
state->encoder_output_port->userdata = (struct MMAL_PORT_USERDATA_T *)&state->callback_data;
if (state->config->verbose)
if (config->verbose)
fprintf(stderr, "Enabling encoder output port\n");
// Enable the encoder output port and tell it its callback function
@ -1697,23 +1706,23 @@ raspi_capture_start(RASPIVID_STATE *state)
goto error;
}
if (state->config->demoMode)
if (config->demoMode)
{
// Run for the user specific time..
int num_iterations = state->config->timeout / state->config->demoInterval;
int num_iterations = config->timeout / config->demoInterval;
int i;
if (state->config->verbose)
if (config->verbose)
fprintf(stderr, "Running in demo mode\n");
for (i=0;state->config->timeout == 0 || i<num_iterations;i++)
for (i=0;config->timeout == 0 || i<num_iterations;i++)
{
raspicamcontrol_cycle_test(state->camera_component);
vcos_sleep(state->config->demoInterval);
vcos_sleep(state->config.demoInterval);
}
}
if (state->config->verbose)
if (config->verbose)
fprintf(stderr, "Starting video capture\n");
if (mmal_port_parameter_set_boolean(state->camera_video_port, MMAL_PARAMETER_CAPTURE, 1) != MMAL_SUCCESS)
@ -1743,14 +1752,14 @@ raspi_capture_start(RASPIVID_STATE *state)
// Going to check every ABORT_INTERVAL milliseconds
#if 0
for (wait = 0; state->config->timeout == 0 || wait < state->config->timeout; wait+= ABORT_INTERVAL)
for (wait = 0; config->timeout == 0 || wait < config->timeout; wait+= ABORT_INTERVAL)
{
vcos_sleep(ABORT_INTERVAL);
if (state->callback_data.abort)
break;
}
if (state->config->verbose)
if (config->verbose)
fprintf(stderr, "Finished capture\n");
#endif
@ -1770,10 +1779,12 @@ error:
void
raspi_capture_stop(RASPIVID_STATE *state)
{
if (state->config->verbose)
RASPIVID_CONFIG *config = &state->config;
if (config->verbose)
fprintf(stderr, "Closing down\n");
if (state->config->preview_parameters.wantPreview )
if (config->preview_parameters.wantPreview )
mmal_connection_destroy(state->preview_connection);
mmal_connection_destroy(state->encoder_connection);
@ -1790,6 +1801,8 @@ raspi_capture_stop(RASPIVID_STATE *state)
void
raspi_capture_free(RASPIVID_STATE *state)
{
RASPIVID_CONFIG *config = &state->config;
// Can now close our file. Note disabling ports may flush buffers which causes
// problems if we have already closed the file!
if (state->output_file && state->output_file != stdout)
@ -1799,14 +1812,14 @@ raspi_capture_free(RASPIVID_STATE *state)
if (state->encoder_component)
mmal_component_disable(state->encoder_component);
if (state->config->preview_parameters.preview_component)
mmal_component_disable(state->config->preview_parameters.preview_component);
if (state->preview_state.preview_component)
mmal_component_disable(state->preview_state.preview_component);
if (state->camera_component)
mmal_component_disable(state->camera_component);
destroy_encoder_component(state);
raspipreview_destroy(&state->config->preview_parameters);
raspipreview_destroy(&state->preview_state);
destroy_camera_component(state);
if (state->encoded_buffer_q) {
@ -1814,8 +1827,124 @@ raspi_capture_free(RASPIVID_STATE *state)
state->encoded_buffer_q = NULL;
}
if (state->config->verbose)
if (config->verbose)
fprintf(stderr, "Close down completed, all components disconnected, disabled and destroyed\n\n");
free(state);
}
void
raspi_capture_update_config (RASPIVID_STATE *state, RASPIVID_CONFIG *config)
{
MMAL_STATUS_T status;
RASPICAM_CAMERA_PARAMETERS *params = &config->camera_parameters;
MMAL_COMPONENT_T *camera = state->camera_component;
/* Store the new config */
state->config = *config;
if (config->change_flags & PROP_CHANGE_ENCODING) {
/* BITRATE or QUANT or KEY Interval, intra refresh */
MMAL_COMPONENT_T *encoder = state->encoder_component;
MMAL_PORT_T *encoder_output = encoder->output[0];
encoder_output->format->bitrate = config->bitrate;
status = mmal_port_format_commit(encoder_output);
if (status != MMAL_SUCCESS)
vcos_log_warn("Unable to change bitrate dynamically");
{
MMAL_PARAMETER_UINT32_T param = {{ MMAL_PARAMETER_INTRAPERIOD, sizeof(param)}, config->intraperiod};
status = mmal_port_parameter_set(encoder_output, &param.hdr);
if (status != MMAL_SUCCESS)
vcos_log_warn("Unable to change intraperiod dynamically");
}
{
MMAL_PARAMETER_UINT32_T param = {{ MMAL_PARAMETER_VIDEO_ENCODE_INITIAL_QUANT, sizeof(param)}, config->quantisationParameter};
status = mmal_port_parameter_set(encoder_output, &param.hdr);
if (status != MMAL_SUCCESS)
vcos_log_warn("Unable to change Initial Quantisation Parameter dynamically");
MMAL_PARAMETER_UINT32_T param2 = {{ MMAL_PARAMETER_VIDEO_ENCODE_MIN_QUANT, sizeof(param)}, config->quantisationParameter};
status = mmal_port_parameter_set(encoder_output, &param2.hdr);
if (status != MMAL_SUCCESS)
vcos_log_warn("Unable to change Minimum Quantisation Parameter dynamically");
MMAL_PARAMETER_UINT32_T param3 = {{ MMAL_PARAMETER_VIDEO_ENCODE_MAX_QUANT, sizeof(param)}, config->quantisationParameter};
status = mmal_port_parameter_set(encoder_output, &param3.hdr);
if (status != MMAL_SUCCESS)
vcos_log_warn("Unable to change Maximum Quantisation Parameter dynamically");
}
{
// Adaptive intra refresh settings
MMAL_PARAMETER_VIDEO_INTRA_REFRESH_T param;
param.hdr.id = MMAL_PARAMETER_VIDEO_INTRA_REFRESH;
param.hdr.size = sizeof(param);
// Get first so we don't overwrite anything unexpectedly
status = mmal_port_parameter_get(encoder_output, &param.hdr);
if (state != MMAL_SUCCESS) {
/* Need to memset, apparently mmal_port_parameter_get()
* doesn't retrieve all parameters, causing random failures
* when we set it. On older firmware the get fails.
*/
memset (&param, 0, sizeof (MMAL_PARAMETER_VIDEO_INTRA_REFRESH_T));
}
param.refresh_mode = config->intra_refresh_type;
status = mmal_port_parameter_set(encoder_output, &param.hdr);
if (status != MMAL_SUCCESS)
vcos_log_warn("Unable to set H264 intra-refresh values dynamically");
}
}
if (config->change_flags & PROP_CHANGE_PREVIEW) {
/* Preview settings or fullscreen */
status = raspipreview_update_config (&state->preview_state,
&config->preview_parameters);
if (status != MMAL_SUCCESS)
vcos_log_warn("Unable to change preview config dynamically");
}
if (config->change_flags & PROP_CHANGE_COLOURBALANCE) {
raspicamcontrol_set_saturation(camera, params->saturation);
raspicamcontrol_set_sharpness(camera, params->sharpness);
raspicamcontrol_set_contrast(camera, params->contrast);
raspicamcontrol_set_brightness(camera, params->brightness);
}
if (config->change_flags & PROP_CHANGE_SENSOR_SETTINGS) {
/* ISO, EXPOSURE, SHUTTER, DRC, Sensor Mode */
raspicamcontrol_set_ISO(camera, params->ISO);
raspicamcontrol_set_exposure_compensation(camera, params->exposureCompensation);
raspicamcontrol_set_exposure_mode(camera, params->exposureMode);
raspicamcontrol_set_metering_mode(camera, params->exposureMeterMode);
raspicamcontrol_set_shutter_speed(camera, params->shutter_speed);
raspicamcontrol_set_DRC(camera, params->drc_level);
/* Can we change sensor mode on the fly? Disable if not */
status = mmal_port_parameter_set_uint32(camera->control,
MMAL_PARAMETER_CAMERA_CUSTOM_SENSOR_CONFIG, config->sensor_mode);
if (status != MMAL_SUCCESS)
vcos_log_warn("Unable to change sensor mode dynamically");
}
if (config->change_flags & PROP_CHANGE_VIDEO_STABILISATION) {
raspicamcontrol_set_video_stabilisation(camera, params->videoStabilisation);
}
if (config->change_flags & PROP_CHANGE_AWB) {
raspicamcontrol_set_awb_mode(camera, params->awbMode);
raspicamcontrol_set_awb_gains(camera, params->awb_gains_r, params->awb_gains_b);
}
if (config->change_flags & PROP_CHANGE_IMAGE_COLOUR_EFFECT) {
raspicamcontrol_set_imageFX(camera, params->imageEffect);
raspicamcontrol_set_colourFX(camera, &params->colourEffects);
}
if (config->change_flags & PROP_CHANGE_ORIENTATION) {
raspicamcontrol_set_rotation(camera, params->rotation);
raspicamcontrol_set_flips(camera, params->hflip, params->vflip);
}
if (config->change_flags & PROP_CHANGE_ROI) {
raspicamcontrol_set_ROI(camera, params->roi);
}
if (config->change_flags & PROP_CHANGE_ANNOTATION)
update_annotation_data(state);
}

View file

@ -1,6 +1,6 @@
/*
* GStreamer
* Copyright (C) 2013 Jan Schmidt <jan@centricular.com>
* Copyright (C) 2013-2015 Jan Schmidt <jan@centricular.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@ -64,10 +64,26 @@ GST_DEBUG_CATEGORY_EXTERN (gst_rpi_cam_src_debug);
G_BEGIN_DECLS
typedef enum
{
PROP_CHANGE_ENCODING = (1 << 0), /* BITRATE or QUANT or KEY Interval, intra refresh */
PROP_CHANGE_PREVIEW = (1 << 1), /* Preview opacity or fullscreen */
PROP_CHANGE_COLOURBALANCE = (1 << 2),
PROP_CHANGE_SENSOR_SETTINGS = (1 << 3), /* ISO, EXPOSURE, SHUTTER, DRC, Sensor Mode */
PROP_CHANGE_VIDEO_STABILISATION = (1 << 4),
PROP_CHANGE_AWB = (1 << 5),
PROP_CHANGE_IMAGE_COLOUR_EFFECT = (1 << 6),
PROP_CHANGE_ORIENTATION = (1 << 7),
PROP_CHANGE_ROI = (1 << 8),
PROP_CHANGE_ANNOTATION = (1 << 9)
} RpiPropChangeFlags;
/** Structure containing all state information for the current run
*/
typedef struct
{
RpiPropChangeFlags change_flags;
int verbose; /// !0 if want detailed run information
int timeout; /// Time taken before frame is grabbed and app then shuts down. Units are milliseconds
@ -101,6 +117,7 @@ void raspicapture_init();
void raspicapture_default_config(RASPIVID_CONFIG *config);
RASPIVID_STATE *raspi_capture_setup(RASPIVID_CONFIG *config);
gboolean raspi_capture_start(RASPIVID_STATE *state);
void raspi_capture_update_config (RASPIVID_STATE *state, RASPIVID_CONFIG *config);
GstFlowReturn raspi_capture_fill_buffer(RASPIVID_STATE *state, GstBuffer **buf,
GstClock *clock, GstClockTime base_time);
void raspi_capture_stop(RASPIVID_STATE *state);

View file

@ -1,6 +1,6 @@
/*
* GStreamer
* Copyright (C) 2013-2014 Jan Schmidt <jan@centricular.com>
* Copyright (C) 2013-2015 Jan Schmidt <jan@centricular.com>
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
@ -186,6 +186,8 @@ static GstStaticPadTemplate video_src_template = GST_STATIC_PAD_TEMPLATE ("src",
#define gst_rpi_cam_src_parent_class parent_class
G_DEFINE_TYPE (GstRpiCamSrc, gst_rpi_cam_src, GST_TYPE_PUSH_SRC);
static void gst_rpi_cam_src_finalize (GObject *object);
static void gst_rpi_cam_src_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
static void gst_rpi_cam_src_get_property (GObject * object, guint prop_id,
@ -249,6 +251,8 @@ gst_rpi_cam_src_class_init (GstRpiCamSrcClass * klass)
gstelement_class = (GstElementClass *) klass;
basesrc_class = (GstBaseSrcClass *) klass;
pushsrc_class = (GstPushSrcClass *) klass;
gobject_class->finalize = gst_rpi_cam_src_finalize;
gobject_class->set_property = gst_rpi_cam_src_set_property;
gobject_class->get_property = gst_rpi_cam_src_get_property;
g_object_class_install_property (gobject_class, PROP_CAMERA_NUMBER,
@ -435,111 +439,152 @@ gst_rpi_cam_src_init (GstRpiCamSrc * src)
raspicapture_default_config (&src->capture_config);
src->capture_config.intraperiod = KEYFRAME_INTERVAL_DEFAULT;
src->capture_config.verbose = 1;
g_mutex_init (&src->config_lock);
/* Don't let basesrc set timestamps, we'll do it using
* buffer PTS and system times */
gst_base_src_set_do_timestamp (GST_BASE_SRC (src), FALSE);
}
static void
gst_rpi_cam_src_finalize (GObject *object)
{
GstRpiCamSrc *src = GST_RPICAMSRC (object);
g_mutex_clear (&src->config_lock);
G_OBJECT_CLASS (gst_rpi_cam_src_parent_class)->finalize (object);
}
static void
gst_rpi_cam_src_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec)
{
GstRpiCamSrc *src = GST_RPICAMSRC (object);
g_mutex_lock (&src->config_lock);
switch (prop_id) {
case PROP_CAMERA_NUMBER:
src->capture_config.cameraNum = g_value_get_int (value);
break;
case PROP_BITRATE:
src->capture_config.bitrate = g_value_get_int (value);
src->capture_config.change_flags |= PROP_CHANGE_ENCODING;
break;
case PROP_KEYFRAME_INTERVAL:
src->capture_config.intraperiod = g_value_get_int (value);
src->capture_config.change_flags |= PROP_CHANGE_ENCODING;
break;
case PROP_PREVIEW:
src->capture_config.preview_parameters.wantPreview =
g_value_get_boolean (value);
src->capture_config.change_flags |= PROP_CHANGE_PREVIEW;
break;
case PROP_PREVIEW_ENCODED:
src->capture_config.immutableInput = g_value_get_boolean (value);
src->capture_config.change_flags |= PROP_CHANGE_PREVIEW;
break;
case PROP_FULLSCREEN:
src->capture_config.preview_parameters.wantFullScreenPreview =
g_value_get_boolean (value);
src->capture_config.change_flags |= PROP_CHANGE_PREVIEW;
break;
case PROP_PREVIEW_OPACITY:
src->capture_config.preview_parameters.opacity = g_value_get_int (value);
src->capture_config.change_flags |= PROP_CHANGE_PREVIEW;
break;
case PROP_SHARPNESS:
src->capture_config.camera_parameters.sharpness = g_value_get_int (value);
src->capture_config.change_flags |= PROP_CHANGE_COLOURBALANCE;
break;
case PROP_CONTRAST:
src->capture_config.camera_parameters.contrast = g_value_get_int (value);
src->capture_config.change_flags |= PROP_CHANGE_COLOURBALANCE;
break;
case PROP_BRIGHTNESS:
src->capture_config.camera_parameters.brightness =
g_value_get_int (value);
src->capture_config.change_flags |= PROP_CHANGE_COLOURBALANCE;
break;
case PROP_SATURATION:
src->capture_config.camera_parameters.saturation =
g_value_get_int (value);
src->capture_config.change_flags |= PROP_CHANGE_COLOURBALANCE;
break;
case PROP_ISO:
src->capture_config.camera_parameters.ISO = g_value_get_int (value);
src->capture_config.change_flags |= PROP_CHANGE_SENSOR_SETTINGS;
break;
case PROP_VIDEO_STABILISATION:
src->capture_config.camera_parameters.videoStabilisation =
g_value_get_boolean (value);
src->capture_config.change_flags |= PROP_CHANGE_VIDEO_STABILISATION;
break;
case PROP_EXPOSURE_COMPENSATION:
src->capture_config.camera_parameters.exposureCompensation =
g_value_get_int (value);
src->capture_config.change_flags |= PROP_CHANGE_SENSOR_SETTINGS;
break;
case PROP_EXPOSURE_MODE:
src->capture_config.camera_parameters.exposureMode =
g_value_get_enum (value);
src->capture_config.change_flags |= PROP_CHANGE_SENSOR_SETTINGS;
break;
case PROP_EXPOSURE_METERING_MODE:
src->capture_config.camera_parameters.exposureMeterMode =
g_value_get_enum (value);
src->capture_config.change_flags |= PROP_CHANGE_SENSOR_SETTINGS;
break;
case PROP_ROTATION:
src->capture_config.camera_parameters.rotation = g_value_get_int (value);
break;
case PROP_AWB_MODE:
src->capture_config.camera_parameters.awbMode = g_value_get_enum (value);
src->capture_config.change_flags |= PROP_CHANGE_AWB;
break;
case PROP_AWB_GAIN_RED:
src->capture_config.camera_parameters.awb_gains_r =
g_value_get_float (value);
src->capture_config.change_flags |= PROP_CHANGE_AWB;
break;
case PROP_AWB_GAIN_BLUE:
src->capture_config.camera_parameters.awb_gains_b =
g_value_get_float (value);
src->capture_config.change_flags |= PROP_CHANGE_AWB;
break;
case PROP_IMAGE_EFFECT:
src->capture_config.camera_parameters.imageEffect =
g_value_get_enum (value);
src->capture_config.change_flags |= PROP_CHANGE_IMAGE_COLOUR_EFFECT;
break;
case PROP_HFLIP:
src->capture_config.camera_parameters.hflip = g_value_get_boolean (value);
src->capture_config.change_flags |= PROP_CHANGE_ORIENTATION;
break;
case PROP_VFLIP:
src->capture_config.camera_parameters.vflip = g_value_get_boolean (value);
src->capture_config.change_flags |= PROP_CHANGE_ORIENTATION;
break;
case PROP_ROI_X:
src->capture_config.camera_parameters.roi.x = g_value_get_float (value);
src->capture_config.change_flags |= PROP_CHANGE_ROI;
break;
case PROP_ROI_Y:
src->capture_config.camera_parameters.roi.y = g_value_get_float (value);
src->capture_config.change_flags |= PROP_CHANGE_ROI;
break;
case PROP_ROI_W:
src->capture_config.camera_parameters.roi.w = g_value_get_float (value);
src->capture_config.change_flags |= PROP_CHANGE_ROI;
break;
case PROP_ROI_H:
src->capture_config.camera_parameters.roi.h = g_value_get_float (value);
src->capture_config.change_flags |= PROP_CHANGE_ROI;
break;
case PROP_QUANTISATION_PARAMETER:
src->capture_config.quantisationParameter = g_value_get_int (value);
src->capture_config.change_flags |= PROP_CHANGE_ENCODING;
break;
case PROP_INLINE_HEADERS:
src->capture_config.bInlineHeaders = g_value_get_boolean (value);
@ -547,17 +592,21 @@ gst_rpi_cam_src_set_property (GObject * object, guint prop_id,
case PROP_SHUTTER_SPEED:
src->capture_config.camera_parameters.shutter_speed =
g_value_get_int (value);
src->capture_config.change_flags |= PROP_CHANGE_SENSOR_SETTINGS;
break;
case PROP_DRC:
src->capture_config.camera_parameters.drc_level =
g_value_get_enum (value);
src->capture_config.change_flags |= PROP_CHANGE_SENSOR_SETTINGS;
break;
case PROP_SENSOR_MODE:
src->capture_config.sensor_mode = g_value_get_enum (value);
src->capture_config.change_flags |= PROP_CHANGE_SENSOR_SETTINGS;
break;
case PROP_ANNOTATION_MODE:
src->capture_config.camera_parameters.enable_annotate =
g_value_get_flags (value);
src->capture_config.change_flags |= PROP_CHANGE_ANNOTATION;
break;
case PROP_ANNOTATION_TEXT:
strncpy (src->capture_config.camera_parameters.annotate_string,
@ -565,14 +614,18 @@ gst_rpi_cam_src_set_property (GObject * object, guint prop_id,
src->capture_config.
camera_parameters.annotate_string[MMAL_CAMERA_ANNOTATE_MAX_TEXT_LEN_V2
- 1] = '\0';
src->capture_config.change_flags |= PROP_CHANGE_ANNOTATION;
break;
case PROP_INTRA_REFRESH_TYPE:
src->capture_config.intra_refresh_type = g_value_get_enum (value);
src->capture_config.change_flags |= PROP_CHANGE_ENCODING;
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
g_mutex_unlock (&src->config_lock);
}
static void
@ -580,6 +633,8 @@ gst_rpi_cam_src_get_property (GObject * object, guint prop_id,
GValue * value, GParamSpec * pspec)
{
GstRpiCamSrc *src = GST_RPICAMSRC (object);
g_mutex_lock (&src->config_lock);
switch (prop_id) {
case PROP_CAMERA_NUMBER:
g_value_set_int (value, src->capture_config.cameraNum);
@ -704,6 +759,7 @@ gst_rpi_cam_src_get_property (GObject * object, guint prop_id,
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
}
g_mutex_unlock (&src->config_lock);
}
static gboolean
@ -711,7 +767,9 @@ gst_rpi_cam_src_start (GstBaseSrc * parent)
{
GstRpiCamSrc *src = GST_RPICAMSRC (parent);
GST_LOG_OBJECT (src, "In src_start()");
g_mutex_lock (&src->config_lock);
src->capture_state = raspi_capture_setup (&src->capture_config);
g_mutex_unlock (&src->config_lock);
if (src->capture_state == NULL)
return FALSE;
return TRUE;
@ -878,6 +936,13 @@ gst_rpi_cam_src_create (GstPushSrc * parent, GstBuffer ** buf)
base_time = GST_ELEMENT_CAST (src)->base_time;
GST_OBJECT_UNLOCK (src);
g_mutex_lock (&src->config_lock);
if (src->capture_config.change_flags) {
raspi_capture_update_config (src->capture_state, &src->capture_config);
src->capture_config.change_flags = 0;
}
g_mutex_unlock (&src->config_lock);
/* FIXME: Use custom allocator */
ret = raspi_capture_fill_buffer (src->capture_state, buf, clock, base_time);
if (*buf)

View file

@ -72,6 +72,8 @@ struct _GstRpiCamSrc
RASPIVID_CONFIG capture_config;
RASPIVID_STATE *capture_state;
gboolean started;
GMutex config_lock;
};
struct _GstRpiCamSrcClass