rpicamsrc: First attempt at implementing MJPEG and raw video support
This commit is contained in:
parent
0a38642214
commit
da86cec40e
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2015 Jan Schmidt <jan@centricular.com>
|
* Copyright (c) 2013-2016 Jan Schmidt <jan@centricular.com>
|
||||||
Portions:
|
Portions:
|
||||||
Copyright (c) 2013, Broadcom Europe Ltd
|
Copyright (c) 2013, Broadcom Europe Ltd
|
||||||
Copyright (c) 2013, James Hughes
|
Copyright (c) 2013, James Hughes
|
||||||
@ -269,6 +269,7 @@ void raspicapture_default_config(RASPIVID_CONFIG *config)
|
|||||||
config->demoInterval = 250; // ms
|
config->demoInterval = 250; // ms
|
||||||
config->immutableInput = 1;
|
config->immutableInput = 1;
|
||||||
config->profile = MMAL_VIDEO_PROFILE_H264_HIGH;
|
config->profile = MMAL_VIDEO_PROFILE_H264_HIGH;
|
||||||
|
config->encoding = MMAL_ENCODING_H264;
|
||||||
|
|
||||||
config->bInlineHeaders = 0;
|
config->bInlineHeaders = 0;
|
||||||
|
|
||||||
@ -1119,9 +1120,6 @@ raspi_capture_set_format_and_start(RASPIVID_STATE *state)
|
|||||||
|
|
||||||
format = preview_port->format;
|
format = preview_port->format;
|
||||||
|
|
||||||
format->encoding = MMAL_ENCODING_OPAQUE;
|
|
||||||
format->encoding_variant = MMAL_ENCODING_I420;
|
|
||||||
|
|
||||||
if(config->camera_parameters.shutter_speed > 6000000)
|
if(config->camera_parameters.shutter_speed > 6000000)
|
||||||
{
|
{
|
||||||
MMAL_PARAMETER_FPS_RANGE_T fps_range = {{MMAL_PARAMETER_FPS_RANGE, sizeof(fps_range)},
|
MMAL_PARAMETER_FPS_RANGE_T fps_range = {{MMAL_PARAMETER_FPS_RANGE, sizeof(fps_range)},
|
||||||
@ -1147,6 +1145,8 @@ raspi_capture_set_format_and_start(RASPIVID_STATE *state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
format->encoding = MMAL_ENCODING_OPAQUE;
|
format->encoding = MMAL_ENCODING_OPAQUE;
|
||||||
|
format->encoding_variant = MMAL_ENCODING_I420;
|
||||||
|
|
||||||
format->es->video.width = VCOS_ALIGN_UP(config->width, 32);
|
format->es->video.width = VCOS_ALIGN_UP(config->width, 32);
|
||||||
format->es->video.height = VCOS_ALIGN_UP(config->height, 16);
|
format->es->video.height = VCOS_ALIGN_UP(config->height, 16);
|
||||||
format->es->video.crop.x = 0;
|
format->es->video.crop.x = 0;
|
||||||
@ -1165,9 +1165,7 @@ raspi_capture_set_format_and_start(RASPIVID_STATE *state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Set the encode format on the video port
|
// Set the encode format on the video port
|
||||||
|
|
||||||
format = video_port->format;
|
format = video_port->format;
|
||||||
format->encoding_variant = MMAL_ENCODING_I420;
|
|
||||||
|
|
||||||
if(config->camera_parameters.shutter_speed > 6000000)
|
if(config->camera_parameters.shutter_speed > 6000000)
|
||||||
{
|
{
|
||||||
@ -1182,7 +1180,16 @@ raspi_capture_set_format_and_start(RASPIVID_STATE *state)
|
|||||||
mmal_port_parameter_set(video_port, &fps_range.hdr);
|
mmal_port_parameter_set(video_port, &fps_range.hdr);
|
||||||
}
|
}
|
||||||
|
|
||||||
format->encoding = MMAL_ENCODING_OPAQUE;
|
/* If encoding, set opaque tunneling format */
|
||||||
|
if (state->encoder_component) {
|
||||||
|
format->encoding = MMAL_ENCODING_OPAQUE;
|
||||||
|
format->encoding_variant = MMAL_ENCODING_I420;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
format->encoding = config->encoding;
|
||||||
|
format->encoding_variant = config->encoding;
|
||||||
|
}
|
||||||
|
|
||||||
format->es->video.width = VCOS_ALIGN_UP(config->width, 32);
|
format->es->video.width = VCOS_ALIGN_UP(config->width, 32);
|
||||||
format->es->video.height = VCOS_ALIGN_UP(config->height, 16);
|
format->es->video.height = VCOS_ALIGN_UP(config->height, 16);
|
||||||
format->es->video.crop.x = 0;
|
format->es->video.crop.x = 0;
|
||||||
@ -1279,6 +1286,10 @@ gboolean raspi_capture_request_i_frame(RASPIVID_STATE *state)
|
|||||||
MMAL_PORT_T *encoder_output = NULL;
|
MMAL_PORT_T *encoder_output = NULL;
|
||||||
MMAL_STATUS_T status;
|
MMAL_STATUS_T status;
|
||||||
MMAL_PARAMETER_BOOLEAN_T param = {{ MMAL_PARAMETER_VIDEO_REQUEST_I_FRAME, sizeof(param)}, 1};
|
MMAL_PARAMETER_BOOLEAN_T param = {{ MMAL_PARAMETER_VIDEO_REQUEST_I_FRAME, sizeof(param)}, 1};
|
||||||
|
|
||||||
|
if (state->encoder_component)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
encoder_output = state->encoder_component->output[0];
|
encoder_output = state->encoder_component->output[0];
|
||||||
status = mmal_port_parameter_set(encoder_output, ¶m.hdr);
|
status = mmal_port_parameter_set(encoder_output, ¶m.hdr);
|
||||||
if (status != MMAL_SUCCESS)
|
if (status != MMAL_SUCCESS)
|
||||||
@ -1302,15 +1313,24 @@ static MMAL_STATUS_T create_encoder_component(RASPIVID_STATE *state)
|
|||||||
MMAL_COMPONENT_T *encoder = 0;
|
MMAL_COMPONENT_T *encoder = 0;
|
||||||
MMAL_PORT_T *encoder_input = NULL, *encoder_output = NULL;
|
MMAL_PORT_T *encoder_input = NULL, *encoder_output = NULL;
|
||||||
MMAL_STATUS_T status;
|
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);
|
gboolean encoded_format =
|
||||||
|
(config->encoding == MMAL_ENCODING_H264 ||
|
||||||
|
config->encoding == MMAL_ENCODING_MJPEG ||
|
||||||
|
config->encoding == MMAL_ENCODING_JPEG);
|
||||||
|
|
||||||
if (status != MMAL_SUCCESS)
|
if (!encoded_format)
|
||||||
{
|
return MMAL_SUCCESS;
|
||||||
vcos_log_error("Unable to create video encoder component");
|
|
||||||
goto error;
|
if (config->encoding == MMAL_ENCODING_JPEG)
|
||||||
|
status = mmal_component_create(MMAL_COMPONENT_DEFAULT_IMAGE_ENCODER, &encoder);
|
||||||
|
else
|
||||||
|
status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_ENCODER, &encoder);
|
||||||
|
|
||||||
|
if (status != MMAL_SUCCESS) {
|
||||||
|
vcos_log_error("Unable to create video encoder component");
|
||||||
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!encoder->input_num || !encoder->output_num)
|
if (!encoder->input_num || !encoder->output_num)
|
||||||
@ -1326,23 +1346,27 @@ static MMAL_STATUS_T create_encoder_component(RASPIVID_STATE *state)
|
|||||||
// We want same format on input and output
|
// We want same format on input and output
|
||||||
mmal_format_copy(encoder_output->format, encoder_input->format);
|
mmal_format_copy(encoder_output->format, encoder_input->format);
|
||||||
|
|
||||||
// Only supporting H264 at the moment
|
// Configure desired encoding
|
||||||
encoder_output->format->encoding = MMAL_ENCODING_H264;
|
encoder_output->format->encoding = config->encoding;
|
||||||
|
|
||||||
encoder_output->format->bitrate = config->bitrate;
|
encoder_output->format->bitrate = config->bitrate;
|
||||||
|
|
||||||
encoder_output->buffer_size = encoder_output->buffer_size_recommended;
|
if (config->encoding == MMAL_ENCODING_H264)
|
||||||
|
encoder_output->buffer_size = encoder_output->buffer_size_recommended;
|
||||||
|
else
|
||||||
|
encoder_output->buffer_size = 256<<10;
|
||||||
|
|
||||||
if (encoder_output->buffer_size < encoder_output->buffer_size_min)
|
if (encoder_output->buffer_size < encoder_output->buffer_size_min)
|
||||||
encoder_output->buffer_size = encoder_output->buffer_size_min;
|
encoder_output->buffer_size = encoder_output->buffer_size_min;
|
||||||
|
|
||||||
GST_DEBUG ("encoder buffer size is %u", (guint)encoder_output->buffer_size);
|
|
||||||
|
|
||||||
encoder_output->buffer_num = encoder_output->buffer_num_recommended;
|
encoder_output->buffer_num = encoder_output->buffer_num_recommended;
|
||||||
|
|
||||||
if (encoder_output->buffer_num < encoder_output->buffer_num_min)
|
if (encoder_output->buffer_num < encoder_output->buffer_num_min)
|
||||||
encoder_output->buffer_num = encoder_output->buffer_num_min;
|
encoder_output->buffer_num = encoder_output->buffer_num_min;
|
||||||
|
|
||||||
|
GST_DEBUG ("encoder wants %d buffers of size %u",
|
||||||
|
(guint)encoder_output->buffer_num, (guint)encoder_output->buffer_size);
|
||||||
|
|
||||||
// We need to set the frame rate on output to 0, to ensure it gets
|
// We need to set the frame rate on output to 0, to ensure it gets
|
||||||
// updated correctly from the input framerate when port connected
|
// updated correctly from the input framerate when port connected
|
||||||
encoder_output->format->es->video.frame_rate.num = 0;
|
encoder_output->format->es->video.frame_rate.num = 0;
|
||||||
@ -1350,9 +1374,7 @@ static MMAL_STATUS_T create_encoder_component(RASPIVID_STATE *state)
|
|||||||
|
|
||||||
// Commit the port changes to the output port
|
// Commit the port changes to the output port
|
||||||
status = mmal_port_format_commit(encoder_output);
|
status = mmal_port_format_commit(encoder_output);
|
||||||
|
if (status != MMAL_SUCCESS) {
|
||||||
if (status != MMAL_SUCCESS)
|
|
||||||
{
|
|
||||||
vcos_log_error("Unable to set format on video encoder output port");
|
vcos_log_error("Unable to set format on video encoder output port");
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
@ -1370,7 +1392,7 @@ static MMAL_STATUS_T create_encoder_component(RASPIVID_STATE *state)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config->intraperiod != -1)
|
if (config->encoding == MMAL_ENCODING_H264 && config->intraperiod != -1)
|
||||||
{
|
{
|
||||||
MMAL_PARAMETER_UINT32_T param = {{ MMAL_PARAMETER_INTRAPERIOD, sizeof(param)}, config->intraperiod};
|
MMAL_PARAMETER_UINT32_T param = {{ MMAL_PARAMETER_INTRAPERIOD, sizeof(param)}, config->intraperiod};
|
||||||
status = mmal_port_parameter_set(encoder_output, ¶m.hdr);
|
status = mmal_port_parameter_set(encoder_output, ¶m.hdr);
|
||||||
@ -1381,7 +1403,7 @@ static MMAL_STATUS_T create_encoder_component(RASPIVID_STATE *state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config->quantisationParameter)
|
if (config->encoding == MMAL_ENCODING_H264 && config->quantisationParameter)
|
||||||
{
|
{
|
||||||
MMAL_PARAMETER_UINT32_T param = {{ MMAL_PARAMETER_VIDEO_ENCODE_INITIAL_QUANT, sizeof(param)}, config->quantisationParameter};
|
MMAL_PARAMETER_UINT32_T param = {{ MMAL_PARAMETER_VIDEO_ENCODE_INITIAL_QUANT, sizeof(param)}, config->quantisationParameter};
|
||||||
status = mmal_port_parameter_set(encoder_output, ¶m.hdr);
|
status = mmal_port_parameter_set(encoder_output, ¶m.hdr);
|
||||||
@ -1409,6 +1431,7 @@ static MMAL_STATUS_T create_encoder_component(RASPIVID_STATE *state)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config->encoding == MMAL_ENCODING_H264)
|
||||||
{
|
{
|
||||||
MMAL_PARAMETER_VIDEO_PROFILE_T param;
|
MMAL_PARAMETER_VIDEO_PROFILE_T param;
|
||||||
param.hdr.id = MMAL_PARAMETER_PROFILE;
|
param.hdr.id = MMAL_PARAMETER_PROFILE;
|
||||||
@ -1440,14 +1463,16 @@ static MMAL_STATUS_T create_encoder_component(RASPIVID_STATE *state)
|
|||||||
}
|
}
|
||||||
|
|
||||||
//set INLINE VECTORS flag to request motion vector estimates
|
//set INLINE VECTORS flag to request motion vector estimates
|
||||||
if (mmal_port_parameter_set_boolean(encoder_output, MMAL_PARAMETER_VIDEO_ENCODE_INLINE_VECTORS, config->inlineMotionVectors) != MMAL_SUCCESS)
|
if (config->encoding == MMAL_ENCODING_H264 &&
|
||||||
|
mmal_port_parameter_set_boolean(encoder_output, MMAL_PARAMETER_VIDEO_ENCODE_INLINE_VECTORS, config->inlineMotionVectors) != MMAL_SUCCESS)
|
||||||
{
|
{
|
||||||
vcos_log_error("failed to set INLINE VECTORS parameters");
|
vcos_log_error("failed to set INLINE VECTORS parameters");
|
||||||
// Continue rather than abort..
|
// Continue rather than abort..
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adaptive intra refresh settings
|
// Adaptive intra refresh settings
|
||||||
if (config->intra_refresh_type != -1)
|
if (config->encoding == MMAL_ENCODING_H264 &&
|
||||||
|
config->intra_refresh_type != -1)
|
||||||
{
|
{
|
||||||
MMAL_PARAMETER_VIDEO_INTRA_REFRESH_T param;
|
MMAL_PARAMETER_VIDEO_INTRA_REFRESH_T param;
|
||||||
|
|
||||||
@ -1476,6 +1501,23 @@ static MMAL_STATUS_T create_encoder_component(RASPIVID_STATE *state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (config->encoding == MMAL_ENCODING_JPEG)
|
||||||
|
{
|
||||||
|
status = mmal_port_parameter_set_uint32(encoder_output, MMAL_PARAMETER_JPEG_Q_FACTOR, config->jpegQuality);
|
||||||
|
if (status != MMAL_SUCCESS) {
|
||||||
|
vcos_log_error("Unable to set JPEG quality");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef MMAL_PARAMETER_JPEG_RESTART_INTERVAL
|
||||||
|
status = mmal_port_parameter_set_uint32(encoder_output, MMAL_PARAMETER_JPEG_RESTART_INTERVAL, config->jpegRestartInterval);
|
||||||
|
if (status != MMAL_SUCCESS) {
|
||||||
|
vcos_log_error("Unable to set JPEG restart interval");
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
// Enable component
|
// Enable component
|
||||||
status = mmal_component_enable(encoder);
|
status = mmal_component_enable(encoder);
|
||||||
|
|
||||||
@ -1485,15 +1527,6 @@ static MMAL_STATUS_T create_encoder_component(RASPIVID_STATE *state)
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Create pool of buffer headers for the output port to consume */
|
|
||||||
pool = mmal_port_pool_create(encoder_output, encoder_output->buffer_num, encoder_output->buffer_size);
|
|
||||||
|
|
||||||
if (!pool)
|
|
||||||
{
|
|
||||||
vcos_log_error("Failed to create buffer header pool for encoder output port %s", encoder_output->name);
|
|
||||||
}
|
|
||||||
|
|
||||||
state->encoder_pool = pool;
|
|
||||||
state->encoder_component = encoder;
|
state->encoder_component = encoder;
|
||||||
|
|
||||||
if (config->verbose)
|
if (config->verbose)
|
||||||
@ -1635,10 +1668,11 @@ raspi_capture_start(RASPIVID_STATE *state)
|
|||||||
MMAL_PORT_T *preview_input_port = NULL;
|
MMAL_PORT_T *preview_input_port = NULL;
|
||||||
MMAL_PORT_T *encoder_input_port = NULL;
|
MMAL_PORT_T *encoder_input_port = NULL;
|
||||||
|
|
||||||
if ((status = create_encoder_component(state)) != MMAL_SUCCESS)
|
MMAL_POOL_T *pool;
|
||||||
{
|
|
||||||
vcos_log_error("%s: Failed to create encode component", __func__);
|
if ((status = create_encoder_component(state)) != MMAL_SUCCESS) {
|
||||||
return FALSE;
|
vcos_log_error("%s: Failed to create encode component", __func__);
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config->verbose)
|
if (config->verbose)
|
||||||
@ -1646,21 +1680,38 @@ raspi_capture_start(RASPIVID_STATE *state)
|
|||||||
dump_state(state);
|
dump_state(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
state->camera_video_port = state->camera_component->output[MMAL_CAMERA_VIDEO_PORT];
|
||||||
|
state->camera_still_port = state->camera_component->output[MMAL_CAMERA_CAPTURE_PORT];
|
||||||
|
camera_preview_port = state->camera_component->output[MMAL_CAMERA_PREVIEW_PORT];
|
||||||
|
preview_input_port = state->preview_state.preview_component->input[0];
|
||||||
|
|
||||||
|
if (state->encoder_component) {
|
||||||
|
encoder_input_port = state->encoder_component->input[0];
|
||||||
|
state->encoder_output_port = state->encoder_component->output[0];
|
||||||
|
} else {
|
||||||
|
state->encoder_output_port = state->camera_video_port;
|
||||||
|
}
|
||||||
|
|
||||||
if ((status = raspi_capture_set_format_and_start(state)) != MMAL_SUCCESS) {
|
if ((status = raspi_capture_set_format_and_start(state)) != MMAL_SUCCESS) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GST_DEBUG ("Creating pool of %d buffers of size %d",
|
||||||
|
state->encoder_output_port->buffer_num, state->encoder_output_port->buffer_size);
|
||||||
|
/* Create pool of buffer headers for the output port to consume */
|
||||||
|
pool = mmal_port_pool_create(state->encoder_output_port,
|
||||||
|
state->encoder_output_port->buffer_num, state->encoder_output_port->buffer_size);
|
||||||
|
if (!pool)
|
||||||
|
{
|
||||||
|
vcos_log_error("Failed to create buffer header pool for encoder output port %s",
|
||||||
|
state->encoder_output_port->name);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
state->encoder_pool = pool;
|
||||||
|
|
||||||
if (state->config.verbose)
|
if (state->config.verbose)
|
||||||
fprintf(stderr, "Starting component connection stage\n");
|
fprintf(stderr, "Starting component connection stage\n");
|
||||||
|
|
||||||
camera_preview_port = state->camera_component->output[MMAL_CAMERA_PREVIEW_PORT];
|
|
||||||
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 (config->preview_parameters.wantPreview )
|
if (config->preview_parameters.wantPreview )
|
||||||
{
|
{
|
||||||
if (config->verbose)
|
if (config->verbose)
|
||||||
@ -1678,17 +1729,19 @@ raspi_capture_start(RASPIVID_STATE *state)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config->verbose)
|
if (state->encoder_component) {
|
||||||
fprintf(stderr, "Connecting camera stills port to encoder input port\n");
|
if (config->verbose)
|
||||||
|
fprintf(stderr, "Connecting camera video port to encoder input port\n");
|
||||||
|
|
||||||
// Now connect the camera to the encoder
|
// Now connect the camera to the encoder
|
||||||
status = connect_ports(state->camera_video_port, encoder_input_port, &state->encoder_connection);
|
status = connect_ports(state->camera_video_port, encoder_input_port, &state->encoder_connection);
|
||||||
if (status != MMAL_SUCCESS)
|
if (status != MMAL_SUCCESS)
|
||||||
{
|
{
|
||||||
if (config->preview_parameters.wantPreview )
|
if (config->preview_parameters.wantPreview )
|
||||||
mmal_connection_destroy(state->preview_connection);
|
mmal_connection_destroy(state->preview_connection);
|
||||||
vcos_log_error("%s: Failed to connect camera video port to encoder input", __func__);
|
vcos_log_error("%s: Failed to connect camera video port to encoder input", __func__);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up our userdata - this is passed though to the callback where we need the information.
|
// Set up our userdata - this is passed though to the callback where we need the information.
|
||||||
@ -1788,13 +1841,13 @@ raspi_capture_stop(RASPIVID_STATE *state)
|
|||||||
|
|
||||||
if (config->preview_parameters.wantPreview )
|
if (config->preview_parameters.wantPreview )
|
||||||
mmal_connection_destroy(state->preview_connection);
|
mmal_connection_destroy(state->preview_connection);
|
||||||
mmal_connection_destroy(state->encoder_connection);
|
|
||||||
|
|
||||||
// Disable all our ports that are not handled by connections
|
// Disable all our ports that are not handled by connections
|
||||||
check_disable_port(state->camera_still_port);
|
check_disable_port(state->camera_still_port);
|
||||||
check_disable_port(state->encoder_output_port);
|
check_disable_port(state->encoder_output_port);
|
||||||
|
|
||||||
if (state->encoder_component) {
|
if (state->encoder_component) {
|
||||||
|
mmal_connection_destroy(state->encoder_connection);
|
||||||
mmal_component_disable(state->encoder_component);
|
mmal_component_disable(state->encoder_component);
|
||||||
destroy_encoder_component(state);
|
destroy_encoder_component(state);
|
||||||
}
|
}
|
||||||
@ -1847,7 +1900,7 @@ raspi_capture_update_config (RASPIVID_STATE *state, RASPIVID_CONFIG *config, gbo
|
|||||||
if (!dynamic)
|
if (!dynamic)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (config->change_flags & PROP_CHANGE_ENCODING) {
|
if (state->encoder_component && config->change_flags & PROP_CHANGE_ENCODING) {
|
||||||
/* BITRATE or QUANT or KEY Interval, intra refresh */
|
/* BITRATE or QUANT or KEY Interval, intra refresh */
|
||||||
MMAL_COMPONENT_T *encoder = state->encoder_component;
|
MMAL_COMPONENT_T *encoder = state->encoder_component;
|
||||||
MMAL_PORT_T *encoder_output = encoder->output[0];
|
MMAL_PORT_T *encoder_output = encoder->output[0];
|
||||||
|
@ -111,6 +111,11 @@ typedef struct
|
|||||||
int settings; /// Request settings from the camera
|
int settings; /// Request settings from the camera
|
||||||
int sensor_mode; /// Sensor mode. 0=auto. Check docs/forum for modes selected by other values.
|
int sensor_mode; /// Sensor mode. 0=auto. Check docs/forum for modes selected by other values.
|
||||||
int intra_refresh_type; /// What intra refresh type to use. -1 to not set.
|
int intra_refresh_type; /// What intra refresh type to use. -1 to not set.
|
||||||
|
|
||||||
|
MMAL_FOURCC_T encoding; // Which encoding to use
|
||||||
|
|
||||||
|
int jpegQuality;
|
||||||
|
int jpegRestartInterval;
|
||||||
} RASPIVID_CONFIG;
|
} RASPIVID_CONFIG;
|
||||||
|
|
||||||
typedef struct RASPIVID_STATE_T RASPIVID_STATE;
|
typedef struct RASPIVID_STATE_T RASPIVID_STATE;
|
||||||
|
@ -57,8 +57,6 @@
|
|||||||
#ifdef HAVE_CONFIG_H
|
#ifdef HAVE_CONFIG_H
|
||||||
# include <config.h>
|
# include <config.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <gst/gst.h>
|
|
||||||
#include <gst/video/video.h>
|
#include <gst/video/video.h>
|
||||||
|
|
||||||
#include "gstrpicamsrc.h"
|
#include "gstrpicamsrc.h"
|
||||||
@ -135,8 +133,9 @@ enum
|
|||||||
PROP_ANNOTATION_TEXT_BG_COLOUR,
|
PROP_ANNOTATION_TEXT_BG_COLOUR,
|
||||||
PROP_INTRA_REFRESH_TYPE,
|
PROP_INTRA_REFRESH_TYPE,
|
||||||
#ifdef GST_RPI_CAM_SRC_ENABLE_VIDEO_DIRECTION
|
#ifdef GST_RPI_CAM_SRC_ENABLE_VIDEO_DIRECTION
|
||||||
PROP_VIDEO_DIRECTION
|
PROP_VIDEO_DIRECTION,
|
||||||
#endif
|
#endif
|
||||||
|
PROP_JPEG_QUALITY
|
||||||
};
|
};
|
||||||
|
|
||||||
#define CAMERA_DEFAULT 0
|
#define CAMERA_DEFAULT 0
|
||||||
@ -158,6 +157,8 @@ enum
|
|||||||
#define EXPOSURE_MODE_DEFAULT GST_RPI_CAM_SRC_EXPOSURE_MODE_AUTO
|
#define EXPOSURE_MODE_DEFAULT GST_RPI_CAM_SRC_EXPOSURE_MODE_AUTO
|
||||||
#define EXPOSURE_METERING_MODE_DEFAULT GST_RPI_CAM_SRC_EXPOSURE_METERING_MODE_AVERAGE
|
#define EXPOSURE_METERING_MODE_DEFAULT GST_RPI_CAM_SRC_EXPOSURE_METERING_MODE_AVERAGE
|
||||||
|
|
||||||
|
#define DEFAULT_JPEG_QUALITY 50
|
||||||
|
|
||||||
/*
|
/*
|
||||||
params->exposureMode = MMAL_PARAM_EXPOSUREMODE_AUTO;
|
params->exposureMode = MMAL_PARAM_EXPOSUREMODE_AUTO;
|
||||||
params->exposureMeterMode = MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE;
|
params->exposureMeterMode = MMAL_PARAM_EXPOSUREMETERINGMODE_AVERAGE;
|
||||||
@ -172,8 +173,7 @@ enum
|
|||||||
params->roi.w = params->roi.h = 1.0;
|
params->roi.w = params->roi.h = 1.0;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define RAW_AND_JPEG_CAPS \
|
#define JPEG_CAPS \
|
||||||
GST_VIDEO_CAPS_MAKE (GST_VIDEO_FORMATS_ALL) ";" \
|
|
||||||
"image/jpeg," \
|
"image/jpeg," \
|
||||||
"width = " GST_VIDEO_SIZE_RANGE "," \
|
"width = " GST_VIDEO_SIZE_RANGE "," \
|
||||||
"height = " GST_VIDEO_SIZE_RANGE "," \
|
"height = " GST_VIDEO_SIZE_RANGE "," \
|
||||||
@ -186,6 +186,8 @@ enum
|
|||||||
"stream-format = (string) byte-stream, " \
|
"stream-format = (string) byte-stream, " \
|
||||||
"alignment = (string) nal, " \
|
"alignment = (string) nal, " \
|
||||||
"profile = (string) { baseline, main, high }"
|
"profile = (string) { baseline, main, high }"
|
||||||
|
#define RAW_CAPS \
|
||||||
|
GST_VIDEO_CAPS_MAKE ("{ I420, RGB, BGR, RGBA }") /* FIXME: Map more raw formats */
|
||||||
|
|
||||||
#ifdef GST_RPI_CAM_SRC_ENABLE_VIDEO_DIRECTION
|
#ifdef GST_RPI_CAM_SRC_ENABLE_VIDEO_DIRECTION
|
||||||
#define gst_rpi_cam_src_reset_custom_orientation(src) { src->orientation = GST_VIDEO_ORIENTATION_CUSTOM; }
|
#define gst_rpi_cam_src_reset_custom_orientation(src) { src->orientation = GST_VIDEO_ORIENTATION_CUSTOM; }
|
||||||
@ -196,7 +198,7 @@ enum
|
|||||||
static GstStaticPadTemplate video_src_template = GST_STATIC_PAD_TEMPLATE ("src",
|
static GstStaticPadTemplate video_src_template = GST_STATIC_PAD_TEMPLATE ("src",
|
||||||
GST_PAD_SRC,
|
GST_PAD_SRC,
|
||||||
GST_PAD_ALWAYS,
|
GST_PAD_ALWAYS,
|
||||||
GST_STATIC_CAPS ( /*RAW_AND_JPEG_CAPS "; " */ H264_CAPS)
|
GST_STATIC_CAPS ( H264_CAPS "; " JPEG_CAPS "; " RAW_CAPS)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
@ -297,6 +299,10 @@ gst_rpi_cam_src_class_init (GstRpiCamSrcClass * klass)
|
|||||||
"Bitrate for encoding. 0 for VBR using quantisation-parameter", 0,
|
"Bitrate for encoding. 0 for VBR using quantisation-parameter", 0,
|
||||||
BITRATE_HIGHEST, BITRATE_DEFAULT,
|
BITRATE_HIGHEST, BITRATE_DEFAULT,
|
||||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
|
g_object_class_install_property (gobject_class, PROP_JPEG_QUALITY,
|
||||||
|
g_param_spec_int ("jpeg-quality", "JPEG Quality",
|
||||||
|
"Quality setting for JPEG encode", 1, 100, DEFAULT_JPEG_QUALITY,
|
||||||
|
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||||
g_object_class_install_property (gobject_class, PROP_KEYFRAME_INTERVAL,
|
g_object_class_install_property (gobject_class, PROP_KEYFRAME_INTERVAL,
|
||||||
g_param_spec_int ("keyframe-interval", "Keyframe Interface",
|
g_param_spec_int ("keyframe-interval", "Keyframe Interface",
|
||||||
"Interval (in frames) between I frames. -1 = automatic, 0 = single-keyframe",
|
"Interval (in frames) between I frames. -1 = automatic, 0 = single-keyframe",
|
||||||
@ -804,6 +810,10 @@ gst_rpi_cam_src_set_property (GObject * object, guint prop_id,
|
|||||||
src->capture_config.bitrate = g_value_get_int (value);
|
src->capture_config.bitrate = g_value_get_int (value);
|
||||||
src->capture_config.change_flags |= PROP_CHANGE_ENCODING;
|
src->capture_config.change_flags |= PROP_CHANGE_ENCODING;
|
||||||
break;
|
break;
|
||||||
|
case PROP_JPEG_QUALITY:
|
||||||
|
src->capture_config.jpegQuality = g_value_get_int (value);
|
||||||
|
src->capture_config.change_flags |= PROP_CHANGE_ENCODING;
|
||||||
|
break;
|
||||||
case PROP_KEYFRAME_INTERVAL:
|
case PROP_KEYFRAME_INTERVAL:
|
||||||
src->capture_config.intraperiod = g_value_get_int (value);
|
src->capture_config.intraperiod = g_value_get_int (value);
|
||||||
src->capture_config.change_flags |= PROP_CHANGE_ENCODING;
|
src->capture_config.change_flags |= PROP_CHANGE_ENCODING;
|
||||||
@ -1013,6 +1023,9 @@ gst_rpi_cam_src_get_property (GObject * object, guint prop_id,
|
|||||||
case PROP_BITRATE:
|
case PROP_BITRATE:
|
||||||
g_value_set_int (value, src->capture_config.bitrate);
|
g_value_set_int (value, src->capture_config.bitrate);
|
||||||
break;
|
break;
|
||||||
|
case PROP_JPEG_QUALITY:
|
||||||
|
g_value_set_int (value, src->capture_config.jpegQuality);
|
||||||
|
break;
|
||||||
case PROP_KEYFRAME_INTERVAL:
|
case PROP_KEYFRAME_INTERVAL:
|
||||||
g_value_set_int (value, src->capture_config.intraperiod);
|
g_value_set_int (value, src->capture_config.intraperiod);
|
||||||
break;
|
break;
|
||||||
@ -1267,16 +1280,41 @@ gst_rpi_cam_src_set_caps (GstBaseSrc * bsrc, GstCaps * caps)
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
structure = gst_caps_get_structure (caps, 0);
|
structure = gst_caps_get_structure (caps, 0);
|
||||||
profile_str = gst_structure_get_string (structure, "profile");
|
if (gst_structure_has_name (structure, "video/x-h264")) {
|
||||||
if (profile_str) {
|
src->capture_config.encoding = MMAL_ENCODING_H264;
|
||||||
if (g_str_equal (profile_str, "baseline"))
|
profile_str = gst_structure_get_string (structure, "profile");
|
||||||
src->capture_config.profile = MMAL_VIDEO_PROFILE_H264_BASELINE;
|
if (profile_str) {
|
||||||
else if (g_str_equal (profile_str, "main"))
|
if (g_str_equal (profile_str, "baseline"))
|
||||||
src->capture_config.profile = MMAL_VIDEO_PROFILE_H264_MAIN;
|
src->capture_config.profile = MMAL_VIDEO_PROFILE_H264_BASELINE;
|
||||||
else if (g_str_equal (profile_str, "high"))
|
else if (g_str_equal (profile_str, "main"))
|
||||||
src->capture_config.profile = MMAL_VIDEO_PROFILE_H264_HIGH;
|
src->capture_config.profile = MMAL_VIDEO_PROFILE_H264_MAIN;
|
||||||
else
|
else if (g_str_equal (profile_str, "high"))
|
||||||
g_warning ("Unknown profile string in rpicamsrc caps: %s", profile_str);
|
src->capture_config.profile = MMAL_VIDEO_PROFILE_H264_HIGH;
|
||||||
|
else
|
||||||
|
g_warning ("Unknown profile string in rpicamsrc caps: %s", profile_str);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (gst_structure_has_name (structure, "image/jpeg")) {
|
||||||
|
src->capture_config.encoding = MMAL_ENCODING_MJPEG;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Raw caps */
|
||||||
|
switch (GST_VIDEO_INFO_FORMAT(&info)) {
|
||||||
|
case GST_VIDEO_FORMAT_I420:
|
||||||
|
src->capture_config.encoding = MMAL_ENCODING_I420;
|
||||||
|
break;
|
||||||
|
case GST_VIDEO_FORMAT_RGB:
|
||||||
|
src->capture_config.encoding = MMAL_ENCODING_RGB24;
|
||||||
|
break;
|
||||||
|
case GST_VIDEO_FORMAT_BGR:
|
||||||
|
src->capture_config.encoding = MMAL_ENCODING_BGR24;
|
||||||
|
break;
|
||||||
|
case GST_VIDEO_FORMAT_RGBA:
|
||||||
|
src->capture_config.encoding = MMAL_ENCODING_RGBA;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
src->capture_config.width = info.width;
|
src->capture_config.width = info.width;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user