static MMAL_STATUS_T mmal_port_connection_enable(MMAL_PORT_T *port, MMAL_PORT_T *connected_port) { MMAL_PORT_T *output = port->type == MMAL_PORT_TYPE_OUTPUT ? port : connected_port; MMAL_PORT_T *input = connected_port->type == MMAL_PORT_TYPE_INPUT ? connected_port : port; MMAL_PORT_T *pool_port = (output->capabilities & MMAL_PORT_CAPABILITY_ALLOCATION) ? output : input; MMAL_PORT_PRIVATE_CORE_T *pool_core = pool_port->priv->core; uint32_t buffer_size, buffer_num; MMAL_POOL_T *pool; /* At this point both ports hold the connection lock */ /* Ensure that the buffer numbers and sizes used are the maxima between connected ports. */ buffer_num = MMAL_MAX(port->buffer_num, connected_port->buffer_num); buffer_size = MMAL_MAX(port->buffer_size, connected_port->buffer_size); port->buffer_num = connected_port->buffer_num = buffer_num; port->buffer_size = connected_port->buffer_size = buffer_size; if (output->capabilities & MMAL_PORT_CAPABILITY_PASSTHROUGH) buffer_size = 0; if (!port->priv->core->core_owns_connection) return MMAL_SUCCESS; pool = mmal_port_pool_create(pool_port, buffer_num, buffer_size); if (!pool) { LOG_ERROR("failed to create pool for connection"); return MMAL_ENOMEM; } pool_core->pool_for_connection = pool; mmal_pool_callback_set(pool, mmal_port_connected_pool_cb, output); return MMAL_SUCCESS; }
/* Connect two mmal components which will transer data via an ARM callback. | A components output data may be processed or altered before being | passed to a components input port. The camera out object will be passed | as userdata to the callback as it must have the callback_port_in and | callback_pool_in values. */ boolean ports_callback_connect(CameraObject *out, int port_num, CameraObject *in, void callback()) { MMAL_PORT_T *callback_port_in; MMAL_STATUS_T status; boolean result; if (!out->component || !in->component) return FALSE; callback_port_in = in->component->input[0]; /* Create the buffer pool and queue for the input port the callback | will send buffers to after processing. Input port is likely an encoder. */ out->callback_port_in = callback_port_in; out->callback_pool_in = mmal_port_pool_create(callback_port_in, callback_port_in->buffer_num, callback_port_in->buffer_size); if ((status = mmal_port_enable(callback_port_in, input_buffer_callback)) != MMAL_SUCCESS) { log_printf( "ports_callback_connect %s: mmal_port_enable failed. Status %s\n", in->name, mmal_status[status]); result = FALSE; } else result = out_port_callback(out, port_num, callback); return result; }
/* This is a camera path endpoint callback setup for GPU encoder data | to the ARM. The callback should handle final disposition of encoder data. */ boolean out_port_callback(CameraObject *obj, int port_num, void callback()) { MMAL_PORT_T *port; MMAL_STATUS_T status; char *msg = "mmal_port_enable"; int i, n; if (!obj->component) return FALSE; port = obj->component->output[port_num]; /* Create an initial queue of buffers for the output port. | FIXME? Can't handle callbacks for more than one splitter port | because I only have one pool_out per component. */ if (!obj->pool_out) { if ((obj->pool_out = mmal_port_pool_create(port, port->buffer_num, port->buffer_size)) == NULL) { log_printf("out_port_callback %s: mmal_port_pool_create failed.\n", obj->name); return FALSE; } } /* Connect the callback and initialize buffer pool of data that will | be sent to the callback. */ if ((status = mmal_port_enable(port, callback)) == MMAL_SUCCESS) { obj->port_out = port; port->userdata = (struct MMAL_PORT_USERDATA_T *) obj; /* Send all buffers in the created queue to the GPU output port. | These buffers will then be delivered back to the ARM with filled | GPU data via the above callback where we can process the data | and then resend the buffer back to the port to be refilled. */ msg = "mmal_port_send_buffer"; n = mmal_queue_length(obj->pool_out->queue); for (i = 0; i < n; ++i) { status = mmal_port_send_buffer(port, mmal_queue_get(obj->pool_out->queue)); if (status != MMAL_SUCCESS) break; } } if (status != MMAL_SUCCESS) { log_printf("out_port_callback %s: %s failed. Status %s\n", obj->name, msg, mmal_status[status]); return FALSE; } return TRUE; }
MMAL_POOL_T* CCameraOutput::EnablePortCallbackAndCreateBufferPool(MMAL_PORT_T* port, MMAL_PORT_BH_CB_T cb, int buffer_count) { MMAL_STATUS_T status; MMAL_POOL_T* buffer_pool = 0; //setup video port buffer and a pool to hold them port->buffer_num = buffer_count; port->buffer_size = port->buffer_size_recommended; printf("Creating pool with %d buffers of size %d\n", port->buffer_num, port->buffer_size); buffer_pool = mmal_port_pool_create(port, port->buffer_num, port->buffer_size); if (!buffer_pool) { printf("Couldn't create video buffer pool\n"); goto error; } //enable the port and hand it the callback port->userdata = (struct MMAL_PORT_USERDATA_T *)this; status = mmal_port_enable(port, cb); if (status != MMAL_SUCCESS) { printf("Failed to set video buffer callback\n"); goto error; } //send all the buffers in our pool to the video port ready for use { int num = mmal_queue_length(buffer_pool->queue); int q; for (q=0;q<num;q++) { MMAL_BUFFER_HEADER_T *buffer = mmal_queue_get(buffer_pool->queue); if (!buffer) { printf("Unable to get a required buffer %d from pool queue\n", q); goto error; } else if (mmal_port_send_buffer(port, buffer)!= MMAL_SUCCESS) { printf("Unable to send a buffer to port (%d)\n", q); goto error; } } } return buffer_pool; error: if(buffer_pool) mmal_port_pool_destroy(port,buffer_pool); return NULL; }
int Private_Impl_Still::createEncoder() { if ( mmal_component_create ( MMAL_COMPONENT_DEFAULT_IMAGE_ENCODER, &encoder ) ) { cout << API_NAME << ": Could not create encoder component.\n"; destroyEncoder(); return -1; } if ( !encoder->input_num || !encoder->output_num ) { cout << API_NAME << ": Encoder does not have input/output ports.\n"; destroyEncoder(); return -1; } encoder_input_port = encoder->input[0]; encoder_output_port = encoder->output[0]; mmal_format_copy ( encoder_output_port->format, encoder_input_port->format ); encoder_output_port->format->encoding = convertEncoding ( encoding ); // Set output encoding encoder_output_port->buffer_size = encoder_output_port->buffer_size_recommended; if ( encoder_output_port->buffer_size < encoder_output_port->buffer_size_min ) encoder_output_port->buffer_size = encoder_output_port->buffer_size_min; encoder_output_port->buffer_num = encoder_output_port->buffer_num_recommended; if ( encoder_output_port->buffer_num < encoder_output_port->buffer_num_min ) encoder_output_port->buffer_num = encoder_output_port->buffer_num_min; if ( mmal_port_format_commit ( encoder_output_port ) ) { cout << API_NAME << ": Could not set format on encoder output port.\n"; destroyEncoder(); return -1; } if ( mmal_component_enable ( encoder ) ) { cout << API_NAME << ": Could not enable encoder component.\n"; destroyEncoder(); return -1; } if ( ! ( encoder_pool = mmal_port_pool_create ( encoder_output_port, encoder_output_port->buffer_num, encoder_output_port->buffer_size ) ) ) { cout << API_NAME << ": Failed to create buffer header pool for encoder output port.\n"; destroyEncoder(); return -1; } return 0; }
void MmalVideoCamera::createBufferPool() { if (m_videoPort == NULL) { throw Exception("Target port is not set."); } // Create pool of buffer headers for the output port to consume m_videoPort->buffer_num = VIDEO_OUTPUT_BUFFERS_NUM; m_videoPort->buffer_size = m_videoPort->buffer_size_recommended; m_pool = mmal_port_pool_create(m_videoPort, MAX(m_videoPort->buffer_num, NUM_IMAGE_BUFFERS), m_videoPort->buffer_size); if (m_pool == NULL) { throw Exception("Failed to create buffer header pool for encoder output port"); } // Set the userdata m_callbackData->pool = m_pool; m_callbackData->acquire = false; m_videoPort->userdata = (struct MMAL_PORT_USERDATA_T *) m_callbackData; // Enable the encoder output port and tell it its callback function if (mmal_port_enable(m_videoPort, EncoderBufferCallback) != MMAL_SUCCESS) { throw Exception("Error enabling the encoder buffer callback"); } else { m_videoPortEnabled = true; } // Send all the buffers to the encoder output port sendBuffers(); // Start the capture if (mmal_port_parameter_set_boolean(m_videoPort, MMAL_PARAMETER_CAPTURE, 1) != MMAL_SUCCESS) { throw Exception("Error starting the camera capture"); } }
/** * Create the encoder component, set up its ports * * @param state Pointer to state control struct * * @return 0 if failed, pointer to component if successful * */ static MMAL_STATUS_T create_encoder_component(RASPIVID_STATE *state) { MMAL_COMPONENT_T *encoder = 0; MMAL_PORT_T *encoder_input = NULL, *encoder_output = NULL; MMAL_STATUS_T status; MMAL_POOL_T *pool; //printf("point1\n"); 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) { status = MMAL_ENOSYS; vcos_log_error("Video encoder doesn't have input/output ports"); goto error; } encoder_input = encoder->input[0]; encoder_output = encoder->output[0]; // We want same format on input and output mmal_format_copy(encoder_output->format, encoder_input->format); // Only supporting H264 at the moment encoder_output->format->encoding = MMAL_ENCODING_H264; encoder_output->format->bitrate = state->bitrate; encoder_output->buffer_size = encoder_output->buffer_size_recommended; if (encoder_output->buffer_size < encoder_output->buffer_size_min) encoder_output->buffer_size = encoder_output->buffer_size_min; encoder_output->buffer_num = encoder_output->buffer_num_recommended; if (encoder_output->buffer_num < encoder_output->buffer_num_min) encoder_output->buffer_num = encoder_output->buffer_num_min; // We need to set the frame rate on output to 0, to ensure it gets // 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.den = 1; // Commit the port changes to the output port status = mmal_port_format_commit(encoder_output); //printf("point2\n"); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set format on video encoder output port"); goto error; } // Set the rate control parameter if (0) { MMAL_PARAMETER_VIDEO_RATECONTROL_T param = {{ MMAL_PARAMETER_RATECONTROL, sizeof(param)}, MMAL_VIDEO_RATECONTROL_DEFAULT}; status = mmal_port_parameter_set(encoder_output, ¶m.hdr); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set ratecontrol"); goto error; } } if (state->intraperiod) { MMAL_PARAMETER_UINT32_T param = {{ MMAL_PARAMETER_INTRAPERIOD, sizeof(param)}, state->intraperiod}; status = mmal_port_parameter_set(encoder_output, ¶m.hdr); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set intraperiod"); goto error; } } if (state->quantisationParameter) { MMAL_PARAMETER_UINT32_T param = {{ MMAL_PARAMETER_VIDEO_ENCODE_INITIAL_QUANT, sizeof(param)}, state->quantisationParameter}; status = mmal_port_parameter_set(encoder_output, ¶m.hdr); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set initial QP"); goto error; } MMAL_PARAMETER_UINT32_T param2 = {{ MMAL_PARAMETER_VIDEO_ENCODE_MIN_QUANT, sizeof(param)}, state->quantisationParameter}; status = mmal_port_parameter_set(encoder_output, ¶m2.hdr); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set min QP"); goto error; } MMAL_PARAMETER_UINT32_T param3 = {{ MMAL_PARAMETER_VIDEO_ENCODE_MAX_QUANT, sizeof(param)}, state->quantisationParameter}; status = mmal_port_parameter_set(encoder_output, ¶m3.hdr); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set max QP"); goto error; } } { MMAL_PARAMETER_VIDEO_PROFILE_T param; param.hdr.id = MMAL_PARAMETER_PROFILE; param.hdr.size = sizeof(param); //param.profile[0].profile = state->profile; param.profile[0].profile = MMAL_VIDEO_PROFILE_H264_HIGH; param.profile[0].level = MMAL_VIDEO_LEVEL_H264_4; // This is the only value supported status = mmal_port_parameter_set(encoder_output, ¶m.hdr); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set H264 profile"); goto error; } } if (mmal_port_parameter_set_boolean(encoder_input, MMAL_PARAMETER_VIDEO_IMMUTABLE_INPUT, state->immutableInput) != MMAL_SUCCESS) { vcos_log_error("Unable to set immutable input flag"); // Continue rather than abort.. } //set INLINE HEADER flag to generate SPS and PPS for every IDR if requested if (mmal_port_parameter_set_boolean(encoder_output, MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER, state->bInlineHeaders) != MMAL_SUCCESS) { vcos_log_error("failed to set INLINE HEADER FLAG parameters"); // Continue rather than abort.. } //set INLINE VECTORS flag to request motion vector estimates if (mmal_port_parameter_set_boolean(encoder_output, MMAL_PARAMETER_VIDEO_ENCODE_INLINE_VECTORS, state->inlineMotionVectors) != MMAL_SUCCESS) { vcos_log_error("failed to set INLINE VECTORS parameters"); // Continue rather than abort.. } // Enable component status = mmal_component_enable(encoder); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to enable video encoder component"); 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); goto error; } state->encoder_pool = pool; state->encoder_component = encoder; /*if (state->verbose) fprintf(stderr, "Encoder component done\n"); */ return status; error: if (encoder) mmal_component_destroy(encoder); state->encoder_component = NULL; return status; }
int main(int argc, char **argv) { MMAL_COMPONENT_T *camera =0; MMAL_COMPONENT_T *preview=0; MMAL_COMPONENT_T *encoder=0; MMAL_CONNECTION_T *preview_conn=0; MMAL_CONNECTION_T *encoder_conn=0; USERDATA_T callback_data; // bcm should be initialized before any GPU call is made bcm_host_init(); setNonDefaultOptions(argc, argv); // Open file to save the video open_new_file_handle(&callback_data, output_file_name); fprintf(stderr, "Output Filename: %s\n", output_file_name); // Create Camera, set default values and enable it vcos_assert((mmal_component_create(MMAL_COMPONENT_DEFAULT_CAMERA, &camera) == MMAL_SUCCESS) && "Failed creating camera component"); vcos_assert((set_camera_component_defaults(camera)) == MMAL_SUCCESS && "Failed setting camera components default values"); vcos_assert((mmal_component_enable(camera) == MMAL_SUCCESS) && "Failed to enable camera component"); // Create Preview, set default values and enable it vcos_assert((mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_RENDERER, &preview) == MMAL_SUCCESS) && "Failed creating preview component"); vcos_assert((set_preview_component_defaults(preview) == MMAL_SUCCESS) && "Failed setting preview components default values"); vcos_assert((mmal_component_enable(preview) == MMAL_SUCCESS) && "Failed to enable camera component"); // Create Encoder, set defaults, enable it and create encoder pool vcos_assert((mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_ENCODER, &encoder) == MMAL_SUCCESS) && "Failed to create encoder component"); vcos_assert((encoder->input_num && encoder->output_num) && "Video encoder does not have input/output ports\n"); set_encoder_component_defaults(encoder); vcos_assert((mmal_component_enable(encoder) == MMAL_SUCCESS) && "Failed enabling encoder component"); callback_data.pool = (MMAL_POOL_T *)mmal_port_pool_create(encoder->output[0], encoder->output[0]->buffer_num, encoder->output[0]->buffer_size); vcos_assert(callback_data.pool && "Failed creating encoder pool\n"); // Setup connections vcos_assert((mmal_connection_create(&preview_conn, camera->output[0], preview->input[0], MMAL_CONNECTION_FLAG_TUNNELLING | MMAL_CONNECTION_FLAG_ALLOCATION_ON_INPUT) == MMAL_SUCCESS) && "Failed stablishing connection between camera output 0 and preview"); vcos_assert((mmal_connection_enable(preview_conn) == MMAL_SUCCESS) && "Failed enabling connection between camera output 0 and preview"); vcos_assert((mmal_connection_create(&encoder_conn, camera->output[1], encoder->input[0], // MMAL_CONNECTION_FLAG_TUNNELLING | MMAL_CONNECTION_FLAG_ALLOCATION_ON_INPUT) == MMAL_SUCCESS) MMAL_CONNECTION_FLAG_ALLOCATION_ON_INPUT) == MMAL_SUCCESS) && "Failed creating encoder connection to capture (camera output 1)"); vcos_assert((mmal_connection_enable(encoder_conn) == MMAL_SUCCESS) && "Failed enabling encoder connection to capture (campera output 1)"); encoder_conn->callback = connection_video2encoder_callback; // Set callback and enable encoder port encoder->output[0]->userdata = (struct MMAL_PORT_USERDATA_T *)&callback_data; vcos_assert(MMAL_SUCCESS == mmal_port_enable(encoder->output[0], encoder_callback)); // Send the buffer to encode output port MMAL_BUFFER_HEADER_T *buffer = mmal_queue_get(callback_data.pool->queue); vcos_assert((mmal_port_send_buffer(encoder->output[0], buffer)== MMAL_SUCCESS) && "Unable to send buffer to encoder output port"); vcos_assert((mmal_port_parameter_set_boolean(camera->output[1], MMAL_PARAMETER_CAPTURE, 1) == MMAL_SUCCESS) && "Unable to set camera->output[1] capture parameter"); consume_queue_on_connection(encoder_conn->out, encoder_conn->pool->queue); while(1) { vcos_sleep(1000); // wait for exit call if (exit_prog){ vcos_sleep(500); // exit called, wait for all buffers be flushed break; } } return 0; }
static int change_output_format(decoder_t *dec) { MMAL_PARAMETER_VIDEO_INTERLACE_TYPE_T interlace_type; decoder_sys_t *sys = dec->p_sys; MMAL_STATUS_T status; int pool_size; int ret = 0; if (atomic_load(&sys->started)) { mmal_format_full_copy(sys->output->format, sys->output_format); status = mmal_port_format_commit(sys->output); if (status != MMAL_SUCCESS) { msg_Err(dec, "Failed to commit output format (status=%"PRIx32" %s)", status, mmal_status_to_string(status)); ret = -1; goto port_reset; } goto apply_fmt; } port_reset: msg_Dbg(dec, "%s: Do full port reset", __func__); status = mmal_port_disable(sys->output); if (status != MMAL_SUCCESS) { msg_Err(dec, "Failed to disable output port (status=%"PRIx32" %s)", status, mmal_status_to_string(status)); ret = -1; goto out; } mmal_format_full_copy(sys->output->format, sys->output_format); status = mmal_port_format_commit(sys->output); if (status != MMAL_SUCCESS) { msg_Err(dec, "Failed to commit output format (status=%"PRIx32" %s)", status, mmal_status_to_string(status)); ret = -1; goto out; } if (sys->opaque) { sys->output->buffer_num = NUM_ACTUAL_OPAQUE_BUFFERS; pool_size = NUM_DECODER_BUFFER_HEADERS; } else { sys->output->buffer_num = __MAX(sys->output->buffer_num_recommended, MIN_NUM_BUFFERS_IN_TRANSIT); pool_size = sys->output->buffer_num; } sys->output->buffer_size = sys->output->buffer_size_recommended; status = mmal_port_enable(sys->output, output_port_cb); if (status != MMAL_SUCCESS) { msg_Err(dec, "Failed to enable output port (status=%"PRIx32" %s)", status, mmal_status_to_string(status)); ret = -1; goto out; } if (!atomic_load(&sys->started)) { if (!sys->opaque) { sys->output_pool = mmal_port_pool_create(sys->output, pool_size, 0); msg_Dbg(dec, "Created output pool with %d pictures", sys->output_pool->headers_num); } atomic_store(&sys->started, true); /* we need one picture from vout for each buffer header on the output * port */ dec->i_extra_picture_buffers = pool_size; /* remove what VLC core reserves as it is part of the pool_size * already */ if (dec->fmt_in.i_codec == VLC_CODEC_H264) dec->i_extra_picture_buffers -= 19; else dec->i_extra_picture_buffers -= 3; msg_Dbg(dec, "Request %d extra pictures", dec->i_extra_picture_buffers); } apply_fmt: dec->fmt_out.video.i_width = sys->output->format->es->video.width; dec->fmt_out.video.i_height = sys->output->format->es->video.height; dec->fmt_out.video.i_x_offset = sys->output->format->es->video.crop.x; dec->fmt_out.video.i_y_offset = sys->output->format->es->video.crop.y; dec->fmt_out.video.i_visible_width = sys->output->format->es->video.crop.width; dec->fmt_out.video.i_visible_height = sys->output->format->es->video.crop.height; dec->fmt_out.video.i_sar_num = sys->output->format->es->video.par.num; dec->fmt_out.video.i_sar_den = sys->output->format->es->video.par.den; dec->fmt_out.video.i_frame_rate = sys->output->format->es->video.frame_rate.num; dec->fmt_out.video.i_frame_rate_base = sys->output->format->es->video.frame_rate.den; /* Query interlaced type */ interlace_type.hdr.id = MMAL_PARAMETER_VIDEO_INTERLACE_TYPE; interlace_type.hdr.size = sizeof(MMAL_PARAMETER_VIDEO_INTERLACE_TYPE_T); status = mmal_port_parameter_get(sys->output, &interlace_type.hdr); if (status != MMAL_SUCCESS) { msg_Warn(dec, "Failed to query interlace type from decoder output port (status=%"PRIx32" %s)", status, mmal_status_to_string(status)); } else { sys->b_progressive = (interlace_type.eMode == MMAL_InterlaceProgressive); sys->b_top_field_first = sys->b_progressive ? true : (interlace_type.eMode == MMAL_InterlaceFieldsInterleavedUpperFirst); msg_Dbg(dec, "Detected %s%s video (%d)", sys->b_progressive ? "progressive" : "interlaced", sys->b_progressive ? "" : (sys->b_top_field_first ? " tff" : " bff"), interlace_type.eMode); } out: mmal_format_free(sys->output_format); sys->output_format = NULL; return ret; }
void ofxRaspicam::create_encoder_component() { ofLogVerbose() << "create_encoder_component START"; MMAL_STATUS_T status; MMAL_POOL_T *pool; status = mmal_component_create(MMAL_COMPONENT_DEFAULT_IMAGE_ENCODER, &encoder); if (status != MMAL_SUCCESS) { ofLogVerbose() << "create JPEG encoder component FAIL error: " << status; }else { ofLogVerbose() << "create JPEG encoder component PASS"; } if (!encoder->input_num || !encoder->output_num) { ofLogVerbose() << "JPEG encoder doesn't have input/output ports"; } encoder_input_port = encoder->input[0]; encoder_output_port = encoder->output[0]; // We want same format on input and output mmal_format_copy(encoder_output_port->format, encoder_input_port->format); // Specify out output format encoder_output_port->format->encoding = photo.encoding; encoder_output_port->buffer_size = encoder_output_port->buffer_size_recommended; if (encoder_output_port->buffer_size < encoder_output_port->buffer_size_min) { encoder_output_port->buffer_size = encoder_output_port->buffer_size_min; } encoder_output_port->buffer_num = encoder_output_port->buffer_num_recommended; if (encoder_output_port->buffer_num < encoder_output_port->buffer_num_min) { encoder_output_port->buffer_num = encoder_output_port->buffer_num_min; } // Commit the port changes to the output port status = mmal_port_format_commit(encoder_output_port); if (status != MMAL_SUCCESS) { ofLogVerbose() << "set format on video encoder output port FAIL, error: " << status; }else { ofLogVerbose() << "set format on video encoder output port PASS"; } // Set the JPEG quality level status = mmal_port_parameter_set_uint32(encoder_output_port, MMAL_PARAMETER_JPEG_Q_FACTOR, photo.quality); if (status != MMAL_SUCCESS) { ofLogVerbose() << "Set JPEG quality FAIL, error: " << status; }else { ofLogVerbose() << "Set JPEG quality PASS"; } // Enable component status = mmal_component_enable(encoder); if (status) { ofLogVerbose() << "Enable video encoder component FAIL, error: " << status; }else { ofLogVerbose() << "Enable video encoder component PASS"; } /* Create pool of buffer headers for the output port to consume */ pool = mmal_port_pool_create(encoder_output_port, encoder_output_port->buffer_num, encoder_output_port->buffer_size); if (!pool) { ofLogVerbose() << "Failed to create buffer header pool for encoder output port " << encoder_output_port->name; }else { ofLogVerbose() << "pool creation PASS"; } photo.encoder_pool = pool; photo.encoder_component = encoder; ofLogVerbose() << "Encoder component done"; }
/** * Create the encoder component, set up its ports * * @param state Pointer to state control struct. encoder_component member set to the created camera_component if successfull. * * @return a MMAL_STATUS, MMAL_SUCCESS if all OK, something else otherwise */ static MMAL_STATUS_T create_encoder_component(RASPISTILL_STATE *state) { MMAL_COMPONENT_T *encoder = 0; MMAL_PORT_T *encoder_input = NULL, *encoder_output = NULL; MMAL_STATUS_T status; MMAL_POOL_T *pool; status = mmal_component_create(MMAL_COMPONENT_DEFAULT_IMAGE_ENCODER, &encoder); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to create JPEG encoder component"); goto error; } if (!encoder->input_num || !encoder->output_num) { status = MMAL_ENOSYS; vcos_log_error("JPEG encoder doesn't have input/output ports"); goto error; } encoder_input = encoder->input[0]; encoder_output = encoder->output[0]; // We want same format on input and output mmal_format_copy(encoder_output->format, encoder_input->format); // Specify out output format encoder_output->format->encoding = state->encoding; encoder_output->buffer_size = encoder_output->buffer_size_recommended; if (encoder_output->buffer_size < encoder_output->buffer_size_min) encoder_output->buffer_size = encoder_output->buffer_size_min; encoder_output->buffer_num = encoder_output->buffer_num_recommended; if (encoder_output->buffer_num < encoder_output->buffer_num_min) encoder_output->buffer_num = encoder_output->buffer_num_min; // Commit the port changes to the output port status = mmal_port_format_commit(encoder_output); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set format on video encoder output port"); goto error; } // Set the JPEG quality level status = mmal_port_parameter_set_uint32(encoder_output, MMAL_PARAMETER_JPEG_Q_FACTOR, state->quality); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set JPEG quality"); goto error; } // Set up any required thumbnail { MMAL_PARAMETER_THUMBNAIL_CONFIG_T param_thumb = {{MMAL_PARAMETER_THUMBNAIL_CONFIGURATION, sizeof(MMAL_PARAMETER_THUMBNAIL_CONFIG_T)}, 0, 0, 0, 0}; if ( state->thumbnailConfig.width > 0 && state->thumbnailConfig.height > 0 ) { // Have a valid thumbnail defined param_thumb.enable = 1; param_thumb.width = state->thumbnailConfig.width; param_thumb.height = state->thumbnailConfig.height; param_thumb.quality = state->thumbnailConfig.quality; } status = mmal_port_parameter_set(encoder->control, ¶m_thumb.hdr); } // Enable component status = mmal_component_enable(encoder); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to enable video encoder component"); 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; if (state->verbose) fprintf(stderr, "Encoder component done\n"); return status; error: if (encoder) mmal_component_destroy(encoder); return status; }
bool CMMALRenderer::init_vout(ERenderFormat format) { CSingleLock lock(m_sharedSection); bool formatChanged = m_format != format; MMAL_STATUS_T status; CLog::Log(LOGDEBUG, "%s::%s configured:%d format:%d->%d", CLASSNAME, __func__, m_bConfigured, m_format, format); if (m_bMMALConfigured && formatChanged) UnInitMMAL(); if (m_bMMALConfigured) return true; m_format = format; if (m_format != RENDER_FMT_MMAL && m_format != RENDER_FMT_YUV420P) return true; /* Create video renderer */ status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_RENDERER, &m_vout); if(status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to create vout component (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } m_vout->control->userdata = (struct MMAL_PORT_USERDATA_T *)this; status = mmal_port_enable(m_vout->control, vout_control_port_cb); if(status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to enable vout control port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } m_vout_input = m_vout->input[0]; m_vout_input->userdata = (struct MMAL_PORT_USERDATA_T *)this; MMAL_ES_FORMAT_T *es_format = m_vout_input->format; es_format->type = MMAL_ES_TYPE_VIDEO; es_format->es->video.crop.width = m_sourceWidth; es_format->es->video.crop.height = m_sourceHeight; if (m_format == RENDER_FMT_MMAL) { es_format->encoding = MMAL_ENCODING_OPAQUE; es_format->es->video.width = m_sourceWidth; es_format->es->video.height = m_sourceHeight; } else if (m_format == RENDER_FMT_YUV420P) { const int pitch = ALIGN_UP(m_sourceWidth, 32); const int aligned_height = ALIGN_UP(m_sourceHeight, 16); es_format->encoding = MMAL_ENCODING_I420; es_format->es->video.width = pitch; es_format->es->video.height = aligned_height; if (CONF_FLAGS_YUVCOEF_MASK(m_iFlags) == CONF_FLAGS_YUVCOEF_BT709) es_format->es->video.color_space = MMAL_COLOR_SPACE_ITUR_BT709; else if (CONF_FLAGS_YUVCOEF_MASK(m_iFlags) == CONF_FLAGS_YUVCOEF_BT601) es_format->es->video.color_space = MMAL_COLOR_SPACE_ITUR_BT601; else if (CONF_FLAGS_YUVCOEF_MASK(m_iFlags) == CONF_FLAGS_YUVCOEF_240M) es_format->es->video.color_space = MMAL_COLOR_SPACE_SMPTE240M; } if (m_format == RENDER_FMT_MMAL) { status = mmal_port_parameter_set_boolean(m_vout_input, MMAL_PARAMETER_ZERO_COPY, MMAL_TRUE); if (status != MMAL_SUCCESS) CLog::Log(LOGERROR, "%s::%s Failed to enable zero copy mode on %s (status=%x %s)", CLASSNAME, __func__, m_vout_input->name, status, mmal_status_to_string(status)); } status = mmal_port_format_commit(m_vout_input); if (status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to commit vout input format (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } m_vout_input->buffer_num = std::max(m_vout_input->buffer_num_recommended, (uint32_t)m_NumYV12Buffers); m_vout_input->buffer_size = m_vout_input->buffer_size_recommended; status = mmal_port_enable(m_vout_input, vout_input_port_cb_static); if(status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to vout enable input port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } status = mmal_component_enable(m_vout); if(status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to enable vout component (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } m_vout_input_pool = mmal_port_pool_create(m_vout_input , m_vout_input->buffer_num, m_vout_input->buffer_size); if (!m_vout_input_pool) { CLog::Log(LOGERROR, "%s::%s Failed to create pool for decoder input port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } return true; }
/** * Create the camera component, set up its ports * * @param state Pointer to state control struct * * @return 0 if failed, pointer to component if successful * */ static MMAL_COMPONENT_T *create_camera_component(RASPIVID_STATE *state) { MMAL_COMPONENT_T *camera = 0; MMAL_ES_FORMAT_T *format; MMAL_PORT_T *preview_port = NULL, *video_port = NULL, *still_port = NULL; MMAL_STATUS_T status; /* Create the component */ status = mmal_component_create(MMAL_COMPONENT_DEFAULT_CAMERA, &camera); if (status != MMAL_SUCCESS) { vcos_log_error("Failed to create camera component"); goto error; } if (!camera->output_num) { vcos_log_error("Camera doesn't have output ports"); goto error; } video_port = camera->output[MMAL_CAMERA_VIDEO_PORT]; still_port = camera->output[MMAL_CAMERA_CAPTURE_PORT]; // set up the camera configuration { MMAL_PARAMETER_CAMERA_CONFIG_T cam_config = { { MMAL_PARAMETER_CAMERA_CONFIG, sizeof(cam_config) }, .max_stills_w = state->width, .max_stills_h = state->height, .stills_yuv422 = 0, .one_shot_stills = 0, .max_preview_video_w = state->width, .max_preview_video_h = state->height, .num_preview_video_frames = 3, .stills_capture_circular_buffer_height = 0, .fast_preview_resume = 0, .use_stc_timestamp = MMAL_PARAM_TIMESTAMP_MODE_RESET_STC }; mmal_port_parameter_set(camera->control, &cam_config.hdr); } // Set the encode format on the video port format = video_port->format; format->encoding_variant = MMAL_ENCODING_I420; format->encoding = MMAL_ENCODING_I420; format->es->video.width = state->width; format->es->video.height = state->height; format->es->video.crop.x = 0; format->es->video.crop.y = 0; format->es->video.crop.width = state->width; format->es->video.crop.height = state->height; format->es->video.frame_rate.num = state->framerate; format->es->video.frame_rate.den = VIDEO_FRAME_RATE_DEN; status = mmal_port_format_commit(video_port); if (status) { vcos_log_error("camera video format couldn't be set"); goto error; } // PR : plug the callback to the video port status = mmal_port_enable(video_port, video_buffer_callback); if (status) { vcos_log_error("camera video callback2 error"); goto error; } // Ensure there are enough buffers to avoid dropping frames if (video_port->buffer_num < VIDEO_OUTPUT_BUFFERS_NUM) video_port->buffer_num = VIDEO_OUTPUT_BUFFERS_NUM; // Set the encode format on the still port format = still_port->format; format->encoding = MMAL_ENCODING_OPAQUE; format->encoding_variant = MMAL_ENCODING_I420; format->es->video.width = state->width; format->es->video.height = state->height; format->es->video.crop.x = 0; format->es->video.crop.y = 0; format->es->video.crop.width = state->width; format->es->video.crop.height = state->height; format->es->video.frame_rate.num = 1; format->es->video.frame_rate.den = 1; status = mmal_port_format_commit(still_port); if (status) { vcos_log_error("camera still format couldn't be set"); goto error; } //PR : create pool of message on video port MMAL_POOL_T *pool; video_port->buffer_size = video_port->buffer_size_recommended; video_port->buffer_num = video_port->buffer_num_recommended; pool = mmal_port_pool_create(video_port, video_port->buffer_num, video_port->buffer_size); if (!pool) { vcos_log_error("Failed to create buffer header pool for video output port"); } state->video_pool = pool; /* Ensure there are enough buffers to avoid dropping frames */ if (still_port->buffer_num < VIDEO_OUTPUT_BUFFERS_NUM) still_port->buffer_num = VIDEO_OUTPUT_BUFFERS_NUM; /* Enable component */ status = mmal_component_enable(camera); if (status) { vcos_log_error("camera component couldn't be enabled"); goto error; } raspicamcontrol_set_all_parameters(camera, &state->camera_parameters); state->camera_component = camera; return camera; error: if (camera) mmal_component_destroy(camera); return 0; }
int setup_camera(PORT_USERDATA *userdata) { MMAL_STATUS_T status; MMAL_COMPONENT_T *camera = 0; MMAL_ES_FORMAT_T *format; MMAL_PORT_T * camera_preview_port; MMAL_PORT_T * camera_video_port; MMAL_PORT_T * camera_still_port; MMAL_POOL_T * camera_video_port_pool; status = mmal_component_create(MMAL_COMPONENT_DEFAULT_CAMERA, &camera); if (status != MMAL_SUCCESS) { fprintf(stderr, "Error: create camera %x\n", status); return -1; } userdata->camera = camera; userdata->camera_preview_port = camera->output[MMAL_CAMERA_PREVIEW_PORT]; userdata->camera_video_port = camera->output[MMAL_CAMERA_VIDEO_PORT]; userdata->camera_still_port = camera->output[MMAL_CAMERA_CAPTURE_PORT]; camera_preview_port = camera->output[MMAL_CAMERA_PREVIEW_PORT]; camera_video_port = camera->output[MMAL_CAMERA_VIDEO_PORT]; camera_still_port = camera->output[MMAL_CAMERA_CAPTURE_PORT]; { MMAL_PARAMETER_CAMERA_CONFIG_T cam_config = { { MMAL_PARAMETER_CAMERA_CONFIG, sizeof (cam_config)}, .max_stills_w = 1280, .max_stills_h = 720, .stills_yuv422 = 0, .one_shot_stills = 1, .max_preview_video_w = VIDEO_WIDTH, .max_preview_video_h = VIDEO_HEIGHT, .num_preview_video_frames = 3, .stills_capture_circular_buffer_height = 0, .fast_preview_resume = 0, .use_stc_timestamp = MMAL_PARAM_TIMESTAMP_MODE_RESET_STC }; mmal_port_parameter_set(camera->control, &cam_config.hdr); } // Setup camera preview port format format = camera_preview_port->format; format->encoding = MMAL_ENCODING_OPAQUE; format->encoding_variant = MMAL_ENCODING_I420; format->es->video.width = VIDEO_WIDTH; format->es->video.height = VIDEO_HEIGHT; format->es->video.crop.x = 0; format->es->video.crop.y = 0; format->es->video.crop.width = VIDEO_WIDTH; format->es->video.crop.height = VIDEO_HEIGHT; status = mmal_port_format_commit(camera_preview_port); if (status != MMAL_SUCCESS) { fprintf(stderr, "Error: camera viewfinder format couldn't be set\n"); return -1; } // Setup camera video port format mmal_format_copy(camera_video_port->format, camera_preview_port->format); format = camera_video_port->format; format->encoding = MMAL_ENCODING_I420; format->encoding_variant = MMAL_ENCODING_I420; format->es->video.width = VIDEO_WIDTH; format->es->video.height = VIDEO_HEIGHT; format->es->video.crop.x = 0; format->es->video.crop.y = 0; format->es->video.crop.width = VIDEO_WIDTH; format->es->video.crop.height = VIDEO_HEIGHT; format->es->video.frame_rate.num = VIDEO_FPS; format->es->video.frame_rate.den = 1; camera_video_port->buffer_size = format->es->video.width * format->es->video.height * 12 / 8; camera_video_port->buffer_num = 2; //fprintf(stderr, "INFO:camera video buffer_size = %d\n", camera_video_port->buffer_size); //fprintf(stderr, "INFO:camera video buffer_num = %d\n", camera_video_port->buffer_num); status = mmal_port_format_commit(camera_video_port); if (status != MMAL_SUCCESS) { fprintf(stderr, "Error: unable to commit camera video port format (%u)\n", status); return -1; } camera_video_port_pool = (MMAL_POOL_T *) mmal_port_pool_create(camera_video_port, camera_video_port->buffer_num, camera_video_port->buffer_size); userdata->camera_video_port_pool = camera_video_port_pool; camera_video_port->userdata = (struct MMAL_PORT_USERDATA_T *) userdata; status = mmal_port_enable(camera_video_port, camera_video_buffer_callback); if (status != MMAL_SUCCESS) { fprintf(stderr, "Error: unable to enable camera video port (%u)\n", status); return -1; } status = mmal_component_enable(camera); if (status != MMAL_SUCCESS) { fprintf(stderr, "Error: unable to enable camera (%u)\n", status); return -1; } fill_port_buffer(userdata->camera_video_port, userdata->camera_video_port_pool); if (mmal_port_parameter_set_boolean(camera_video_port, MMAL_PARAMETER_CAPTURE, 1) != MMAL_SUCCESS) { printf("%s: Failed to start capture\n", __func__); } //fprintf(stderr, "INFO: camera created\n"); return 0; }
int setup_encoder(PORT_USERDATA *userdata) { MMAL_STATUS_T status; MMAL_COMPONENT_T *encoder = 0; MMAL_PORT_T *preview_input_port = NULL; MMAL_PORT_T *encoder_input_port = NULL, *encoder_output_port = NULL; MMAL_POOL_T *encoder_input_port_pool; MMAL_POOL_T *encoder_output_port_pool; status = mmal_component_create(MMAL_COMPONENT_DEFAULT_IMAGE_ENCODER, &encoder); if (status != MMAL_SUCCESS) { fprintf(stderr, "Error: unable to create preview (%u)\n", status); return -1; } encoder_input_port = encoder->input[0]; encoder_output_port = encoder->output[0]; userdata->encoder_input_port = encoder_input_port; userdata->encoder_output_port = encoder_input_port; mmal_format_copy(encoder_input_port->format, userdata->camera_video_port->format); encoder_input_port->buffer_size = encoder_input_port->buffer_size_recommended; encoder_input_port->buffer_num = 2; mmal_format_copy(encoder_output_port->format, encoder_input_port->format); encoder_output_port->buffer_size = encoder_output_port->buffer_size_recommended; encoder_output_port->buffer_num = 2; // Commit the port changes to the input port status = mmal_port_format_commit(encoder_input_port); if (status != MMAL_SUCCESS) { fprintf(stderr, "Error: unable to commit encoder input port format (%u)\n", status); return -1; } encoder_output_port->format->encoding = MMAL_ENCODING_JPEG; encoder_output_port->buffer_size = encoder_output_port->buffer_size_recommended; if (encoder_output_port->buffer_size < encoder_output_port->buffer_size_min) { encoder_output_port->buffer_size = encoder_output_port->buffer_size_min; } encoder_output_port->buffer_num = encoder_output_port->buffer_num_recommended; if (encoder_output_port->buffer_num < encoder_output_port->buffer_num_min) { encoder_output_port->buffer_num = encoder_output_port->buffer_num_min; } // Commit the port changes to the output port status = mmal_port_format_commit(encoder_output_port); if (status != MMAL_SUCCESS) { fprintf(stderr, "Error: unable to commit encoder output port format (%u)\n", status); return -1; } //fprintf(stderr, " encoder input buffer_size = %d\n", encoder_input_port->buffer_size); //fprintf(stderr, " encoder input buffer_num = %d\n", encoder_input_port->buffer_num); //fprintf(stderr, " encoder output buffer_size = %d\n", encoder_output_port->buffer_size); //fprintf(stderr, " encoder output buffer_num = %d\n", encoder_output_port->buffer_num); encoder_input_port_pool = (MMAL_POOL_T *) mmal_port_pool_create(encoder_input_port, encoder_input_port->buffer_num, encoder_input_port->buffer_size); userdata->encoder_input_pool = encoder_input_port_pool; encoder_input_port->userdata = (struct MMAL_PORT_USERDATA_T *) userdata; status = mmal_port_enable(encoder_input_port, encoder_input_buffer_callback); if (status != MMAL_SUCCESS) { fprintf(stderr, "Error: unable to enable encoder input port (%u)\n", status); return -1; } //fprintf(stderr, "INFO:Encoder input pool has been created\n"); encoder_output_port_pool = (MMAL_POOL_T *) mmal_port_pool_create(encoder_output_port, encoder_output_port->buffer_num, encoder_output_port->buffer_size); userdata->encoder_output_pool = encoder_output_port_pool; encoder_output_port->userdata = (struct MMAL_PORT_USERDATA_T *) userdata; status = mmal_port_enable(encoder_output_port, encoder_output_buffer_callback); if (status != MMAL_SUCCESS) { fprintf(stderr, "Error: unable to enable encoder output port (%u)\n", status); return -1; } //fprintf(stderr, "INFO:Encoder output pool has been created\n"); fill_port_buffer(encoder_output_port, encoder_output_port_pool); //fprintf(stderr, "INFO:Encoder has been created\n"); return 0; }
/* Create Simple Video Player instance. */ SVP_T *svp_create(const char *uri, SVP_CALLBACKS_T *callbacks, const SVP_OPTS_T *opts) { SVP_T *svp; MMAL_STATUS_T st; VCOS_STATUS_T vst; MMAL_PORT_T *reader_output = NULL; MMAL_COMPONENT_T *video_decode = NULL; MMAL_PORT_T *video_output = NULL; LOG_TRACE("Creating player for %s", (uri ? uri : "camera preview")); vcos_assert(callbacks->video_frame_cb); vcos_assert(callbacks->stop_cb); svp = vcos_calloc(1, sizeof(*svp), "svp"); CHECK_STATUS((svp ? MMAL_SUCCESS : MMAL_ENOMEM), "Failed to allocate context"); svp->opts = *opts; svp->callbacks = *callbacks; /* Semaphore used for synchronising buffer handling for decoded frames */ vst = vcos_semaphore_create(&svp->sema, "svp-sem", 0); CHECK_STATUS((vst == VCOS_SUCCESS ? MMAL_SUCCESS : MMAL_ENOMEM), "Failed to create semaphore"); svp->created |= SVP_CREATED_SEM; vst = vcos_mutex_create(&svp->mutex, "svp-mutex"); CHECK_STATUS((vst == VCOS_SUCCESS ? MMAL_SUCCESS : MMAL_ENOMEM), "Failed to create mutex"); svp->created |= SVP_CREATED_MUTEX; vst = vcos_timer_create(&svp->timer, "svp-timer", svp_timer_cb, svp); CHECK_STATUS((vst == VCOS_SUCCESS ? MMAL_SUCCESS : MMAL_ENOMEM), "Failed to create timer"); svp->created |= SVP_CREATED_TIMER; vst = vcos_timer_create(&svp->wd_timer, "svp-wd-timer", svp_watchdog_cb, svp); CHECK_STATUS((vst == VCOS_SUCCESS ? MMAL_SUCCESS : MMAL_ENOMEM), "Failed to create timer"); svp->created |= SVP_CREATED_WD_TIMER; /* Create components */ svp->reader = NULL; svp->video_decode = NULL; svp->camera = NULL; svp->connection = NULL; if (uri) { /* Video from URI: setup container_reader -> video_decode */ /* Create and set up container reader */ st = mmal_component_create(MMAL_COMPONENT_DEFAULT_CONTAINER_READER, &svp->reader); CHECK_STATUS(st, "Failed to create container reader"); st = svp_setup_reader(svp->reader, uri, &reader_output); if (st != MMAL_SUCCESS) goto error; st = mmal_component_enable(svp->reader); CHECK_STATUS(st, "Failed to enable container reader"); st = svp_port_enable(svp, svp->reader->control, svp_bh_control_cb); CHECK_STATUS(st, "Failed to enable container reader control port"); /* Create and set up video decoder */ st = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, &svp->video_decode); CHECK_STATUS(st, "Failed to create video decoder"); video_decode = svp->video_decode; video_output = video_decode->output[0]; st = mmal_component_enable(video_decode); CHECK_STATUS(st, "Failed to enable video decoder"); st = svp_port_enable(svp, video_decode->control, svp_bh_control_cb); CHECK_STATUS(st, "Failed to enable video decoder control port"); } else { /* Camera preview */ MMAL_PARAMETER_CAMERA_CONFIG_T config; st = mmal_component_create(MMAL_COMPONENT_DEFAULT_CAMERA, &svp->camera); CHECK_STATUS(st, "Failed to create camera"); st = mmal_component_enable(svp->camera); CHECK_STATUS(st, "Failed to enable camera"); st = svp_port_enable(svp, svp->camera->control, svp_bh_control_cb); CHECK_STATUS(st, "Failed to enable camera control port"); video_output = svp->camera->output[0]; /* Preview port */ } st = mmal_port_parameter_set_boolean(video_output, MMAL_PARAMETER_ZERO_COPY, MMAL_TRUE); CHECK_STATUS((st == MMAL_ENOSYS ? MMAL_SUCCESS : st), "Failed to enable zero copy"); if (uri) { /* Create connection: container_reader -> video_decoder */ st = mmal_connection_create(&svp->connection, reader_output, video_decode->input[0], MMAL_CONNECTION_FLAG_TUNNELLING); CHECK_STATUS(st, "Failed to create connection"); } /* Set video output port format. * Opaque encoding ensures we get buffer data as handles to relocatable heap. */ video_output->format->encoding = MMAL_ENCODING_OPAQUE; if (!uri) { /* Set video format for camera preview */ MMAL_VIDEO_FORMAT_T *vfmt = &video_output->format->es->video; CHECK_STATUS((video_output->format->type == MMAL_ES_TYPE_VIDEO) ? MMAL_SUCCESS : MMAL_EINVAL, "Output port isn't video format"); vfmt->width = SVP_CAMERA_WIDTH; vfmt->height = SVP_CAMERA_HEIGHT; vfmt->crop.x = 0; vfmt->crop.y = 0; vfmt->crop.width = vfmt->width; vfmt->crop.height = vfmt->height; vfmt->frame_rate.num = SVP_CAMERA_FRAMERATE; vfmt->frame_rate.den = 1; } st = mmal_port_format_commit(video_output); CHECK_STATUS(st, "Failed to set output port format"); /* Finally, set buffer num/size. N.B. For container_reader/video_decode, must be after * connection created, in order for port format to propagate. * Don't enable video output port until want to produce frames. */ video_output->buffer_num = video_output->buffer_num_recommended; video_output->buffer_size = video_output->buffer_size_recommended; /* Pool + queue to hold decoded video frames */ svp->out_pool = mmal_port_pool_create(video_output, video_output->buffer_num, video_output->buffer_size); CHECK_STATUS((svp->out_pool ? MMAL_SUCCESS : MMAL_ENOMEM), "Error allocating pool"); svp->queue = mmal_queue_create(); CHECK_STATUS((svp ? MMAL_SUCCESS : MMAL_ENOMEM), "Error allocating queue"); svp->video_output = video_output; return svp; error: svp_destroy(svp); return NULL; }
/** * Reset the encoder component, set up its ports * * @param state Pointer to state control struct * * @return MMAL_SUCCESS if all OK, something else otherwise * */ MMAL_STATUS_T reset_encoder_component(RASPIVID_STATE *state) { MMAL_COMPONENT_T *encoder = 0; MMAL_PORT_T *encoder_input = NULL, *encoder_output = NULL; MMAL_STATUS_T status; MMAL_POOL_T *pool; // Get the encoder component if( state->encoder_component == NULL ) { vcos_log_error("Unable to get video encoder component"); goto error; } else { encoder = state->encoder_component; } #ifdef __NOT_REQURED__ if (!encoder->input_num || !encoder->output_num) { status = MMAL_ENOSYS; vcos_log_error("Video encoder doesn't have input/output ports"); goto error; } encoder_input = encoder->input[0]; encoder_output = encoder->output[0]; // We want same format on input and output mmal_format_copy(encoder_output->format, encoder_input->format); // Only supporting H264 at the moment encoder_output->format->encoding = state->encoding; encoder_output->format->bitrate = state->bitrate; if (state->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) encoder_output->buffer_size = encoder_output->buffer_size_min; encoder_output->buffer_num = encoder_output->buffer_num_recommended; if (encoder_output->buffer_num < encoder_output->buffer_num_min) encoder_output->buffer_num = encoder_output->buffer_num_min; // We need to set the frame rate on output to 0, to ensure it gets // 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.den = 1; // Commit the port changes to the output port status = mmal_port_format_commit(encoder_output); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set format on video encoder output port"); goto error; } if (state->encoding == MMAL_ENCODING_H264 && state->intraperiod != -1) { MMAL_PARAMETER_UINT32_T param = {{ MMAL_PARAMETER_INTRAPERIOD, sizeof(param)}, state->intraperiod}; status = mmal_port_parameter_set(encoder_output, ¶m.hdr); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set intraperiod"); goto error; } } if (state->encoding == MMAL_ENCODING_H264 && state->quantisationParameter) { MMAL_PARAMETER_UINT32_T param = {{ MMAL_PARAMETER_VIDEO_ENCODE_INITIAL_QUANT, sizeof(param)}, state->quantisationInitialParameter}; status = mmal_port_parameter_set(encoder_output, ¶m.hdr); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set initial QP"); goto error; } MMAL_PARAMETER_UINT32_T param2 = {{ MMAL_PARAMETER_VIDEO_ENCODE_MIN_QUANT, sizeof(param)}, state->quantisationMinParameter}; status = mmal_port_parameter_set(encoder_output, ¶m2.hdr); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set min QP"); goto error; } MMAL_PARAMETER_UINT32_T param3 = {{ MMAL_PARAMETER_VIDEO_ENCODE_MAX_QUANT, sizeof(param)}, state->quantisationMaxParameter}; status = mmal_port_parameter_set(encoder_output, ¶m3.hdr); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set max QP"); goto error; } } if (state->encoding == MMAL_ENCODING_H264) { MMAL_PARAMETER_VIDEO_PROFILE_T param; param.hdr.id = MMAL_PARAMETER_PROFILE; param.hdr.size = sizeof(param); param.profile[0].profile = state->profile; param.profile[0].level = MMAL_VIDEO_LEVEL_H264_4; // This is the only value supported status = mmal_port_parameter_set(encoder_output, ¶m.hdr); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set H264 profile"); goto error; } } if (mmal_port_parameter_set_boolean(encoder_input, MMAL_PARAMETER_VIDEO_IMMUTABLE_INPUT, state->immutableInput) != MMAL_SUCCESS) { vcos_log_error("Unable to set immutable input flag"); // Continue rather than abort.. } //set INLINE HEADER flag to generate SPS and PPS for every IDR if requested if (mmal_port_parameter_set_boolean(encoder_output, MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER, state->bInlineHeaders) != MMAL_SUCCESS) { vcos_log_error("failed to set INLINE HEADER FLAG parameters"); // Continue rather than abort.. } //set Encode SPS Timing if (mmal_port_parameter_set_boolean(encoder_output, MMAL_PARAMETER_VIDEO_ENCODE_SPS_TIMING, MMAL_TRUE) != MMAL_SUCCESS) { vcos_log_error("failed to set SPS TIMING HEADER FLAG parameters"); // Continue rather than abort.. } // set Minimise Fragmentation if (mmal_port_parameter_set_boolean(encoder_output, MMAL_PARAMETER_MINIMISE_FRAGMENTATION, MMAL_FALSE) != MMAL_SUCCESS) { vcos_log_error("failed to set SPS TIMING HEADER FLAG parameters"); // Continue rather than abort.. } // Adaptive intra refresh settings if (state->encoding == MMAL_ENCODING_H264 && state->intra_refresh_type != -1) { 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, ¶m.hdr); if (status != MMAL_SUCCESS) { vcos_log_warn("Unable to get existing H264 intra-refresh values. Please update your firmware"); // Set some defaults, don't just pass random stack data param.air_mbs = param.air_ref = param.cir_mbs = param.pir_mbs = 0; } param.refresh_mode = state->intra_refresh_type; //if (state->intra_refresh_type == MMAL_VIDEO_INTRA_REFRESH_CYCLIC_MROWS) // param.cir_mbs = 10; status = mmal_port_parameter_set(encoder_output, ¶m.hdr); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set H264 intra-refresh values"); goto error; } } #endif /* NOT_REQUIRED */ // Enable component status = mmal_component_enable(encoder); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to enable video encoder component"); goto error; } #ifdef __NOT_REQURED__ /* 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; #endif /* NOT_REQUIRED */ return status; error: if (encoder) mmal_component_destroy(encoder); state->encoder_component = NULL; return status; }
bool CMMALRenderer::init_vout(ERenderFormat format, bool opaque) { CSingleLock lock(m_sharedSection); bool formatChanged = m_format != format || m_opaque != opaque; MMAL_STATUS_T status; CLog::Log(LOGDEBUG, "%s::%s configured:%d format %d->%d opaque %d->%d", CLASSNAME, __func__, m_bConfigured, m_format, format, m_opaque, opaque); if (m_bMMALConfigured && formatChanged) UnInitMMAL(); if (m_bMMALConfigured || format != RENDER_FMT_MMAL) return true; m_format = format; m_opaque = opaque; /* Create video renderer */ status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_RENDERER, &m_vout); if(status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to create vout component (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } m_vout_input = m_vout->input[0]; m_vout_input->userdata = (struct MMAL_PORT_USERDATA_T *)this; MMAL_ES_FORMAT_T *es_format = m_vout_input->format; es_format->type = MMAL_ES_TYPE_VIDEO; if (CONF_FLAGS_YUVCOEF_MASK(m_iFlags) == CONF_FLAGS_YUVCOEF_BT709) es_format->es->video.color_space = MMAL_COLOR_SPACE_ITUR_BT709; else if (CONF_FLAGS_YUVCOEF_MASK(m_iFlags) == CONF_FLAGS_YUVCOEF_BT601) es_format->es->video.color_space = MMAL_COLOR_SPACE_ITUR_BT601; else if (CONF_FLAGS_YUVCOEF_MASK(m_iFlags) == CONF_FLAGS_YUVCOEF_240M) es_format->es->video.color_space = MMAL_COLOR_SPACE_SMPTE240M; es_format->es->video.crop.width = m_sourceWidth; es_format->es->video.crop.height = m_sourceHeight; es_format->es->video.width = m_sourceWidth; es_format->es->video.height = m_sourceHeight; es_format->encoding = m_opaque ? MMAL_ENCODING_OPAQUE : MMAL_ENCODING_I420; status = mmal_port_parameter_set_boolean(m_vout_input, MMAL_PARAMETER_ZERO_COPY, MMAL_TRUE); if (status != MMAL_SUCCESS) CLog::Log(LOGERROR, "%s::%s Failed to enable zero copy mode on %s (status=%x %s)", CLASSNAME, __func__, m_vout_input->name, status, mmal_status_to_string(status)); status = mmal_port_format_commit(m_vout_input); if (status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to commit vout input format (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } m_vout_input->buffer_num = std::max(m_vout_input->buffer_num_recommended, (uint32_t)m_NumYV12Buffers+(m_opaque?0:32)); m_vout_input->buffer_size = m_vout_input->buffer_size_recommended; status = mmal_port_enable(m_vout_input, vout_input_port_cb_static); if(status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to vout enable input port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } status = mmal_component_enable(m_vout); if(status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to enable vout component (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } CLog::Log(LOGDEBUG, "%s::%s Created pool of size %d x %d", CLASSNAME, __func__, m_vout_input->buffer_num, m_vout_input->buffer_size); m_vout_input_pool = mmal_port_pool_create(m_vout_input , m_vout_input->buffer_num, m_opaque ? m_vout_input->buffer_size:0); if (!m_vout_input_pool) { CLog::Log(LOGERROR, "%s::%s Failed to create pool for decoder input port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } if (!CSettings::GetInstance().GetBool("videoplayer.usedisplayasclock")) { m_queue = mmal_queue_create(); Create(); } return true; }
/** * Create the encoder component, set up its ports * * @param state Pointer to state control struct * * @return MMAL_SUCCESS if all OK, something else otherwise * */ static MMAL_STATUS_T create_encoder_component(RASPIVID_STATE *state) { MMAL_COMPONENT_T *encoder = 0; MMAL_PORT_T *encoder_input = NULL, *encoder_output = NULL; MMAL_STATUS_T status; MMAL_POOL_T *pool; 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) { status = MMAL_ENOSYS; vcos_log_error("Video encoder doesn't have input/output ports"); goto error; } encoder_input = encoder->input[0]; encoder_output = encoder->output[0]; // We want same format on input and output mmal_format_copy(encoder_output->format, encoder_input->format); // Only supporting H264 at the moment encoder_output->format->encoding = MMAL_ENCODING_H264; encoder_output->format->bitrate = state->bitrate; encoder_output->buffer_size = encoder_output->buffer_size_recommended; if (encoder_output->buffer_size < encoder_output->buffer_size_min) encoder_output->buffer_size = encoder_output->buffer_size_min; encoder_output->buffer_num = encoder_output->buffer_num_recommended; if (encoder_output->buffer_num < encoder_output->buffer_num_min) encoder_output->buffer_num = encoder_output->buffer_num_min; // Commit the port changes to the output port status = mmal_port_format_commit(encoder_output); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set format on video encoder output port"); goto error; } // Set the rate control parameter if (0) { MMAL_PARAMETER_VIDEO_RATECONTROL_T param = {{ MMAL_PARAMETER_RATECONTROL, sizeof(param)}, MMAL_VIDEO_RATECONTROL_DEFAULT}; status = mmal_port_parameter_set(encoder_output, ¶m.hdr); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set ratecontrol"); goto error; } } if (state->intraperiod) { MMAL_PARAMETER_UINT32_T param = {{ MMAL_PARAMETER_INTRAPERIOD, sizeof(param)}, state->intraperiod}; status = mmal_port_parameter_set(encoder_output, ¶m.hdr); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set intraperiod"); goto error; } } if (mmal_port_parameter_set_boolean(encoder_input, MMAL_PARAMETER_VIDEO_IMMUTABLE_INPUT, state->immutableInput) != MMAL_SUCCESS) { vcos_log_error("Unable to set immutable input flag"); // Continue rather than abort.. } // Enable component status = mmal_component_enable(encoder); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to enable video encoder component"); 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; if (state->verbose) fprintf(stderr, "Encoder component done\n"); return status; error: if (encoder) mmal_component_destroy(encoder); return status; }
MmalStillCamera::MmalStillCamera(int imageWidth, int imageHeight, bool enableBurstMode) : m_imageWidth(imageWidth), m_imageHeight(imageHeight), m_callbackData(NULL), m_cs(), m_camera(NULL), m_preview(NULL), m_encoder(NULL), m_pool(NULL), m_previewPort(NULL), m_videoPort(NULL), m_stillPort(NULL), m_targetPort(NULL) { m_callbackData = new MmalStillCallbackData(m_imageWidth, m_imageHeight, 3); createCameraComponent(); std::cout << "Created camera" << std::endl; createPreview(); std::cout << "Created preview" << std::endl; std::cout << "Target Image Width: " << VCOS_ALIGN_UP(m_imageWidth, 32) << std::endl; std::cout << "Target Image Height: " << VCOS_ALIGN_UP(m_imageHeight, 16) << std::endl; MMAL_STATUS_T status; m_targetPort = m_stillPort; // Create pool of buffer headers for the output port to consume m_pool = mmal_port_pool_create(m_targetPort, m_targetPort->buffer_num, m_targetPort->buffer_size); if (m_pool == NULL) { throw Exception("Failed to create buffer header pool for encoder output port"); } MMAL_CONNECTION_T *preview_connection = NULL; status = connect_ports(m_previewPort, m_preview->input[0], &preview_connection); if (status != MMAL_SUCCESS) { throw Exception("Error connecting preview port"); } m_targetPort->userdata = (struct MMAL_PORT_USERDATA_T *) m_callbackData; m_callbackData->image = NULL; m_callbackData->pool = m_pool; // Enable the encoder output port and tell it its callback function if (mmal_port_enable(m_targetPort, EncoderBufferCallback) != MMAL_SUCCESS) { std::cerr << "Error enabling the encoder buffer callback" << std::endl; } // Send all the buffers to the encoder output port int num = mmal_queue_length(m_pool->queue); for (int q = 0; q < num; q++) { MMAL_BUFFER_HEADER_T *buffer = mmal_queue_get(m_pool->queue); if (buffer == NULL) { std::cerr << "Unable to get buffer " << q << " from the pool" << std::endl; } if (mmal_port_send_buffer(m_targetPort, buffer)!= MMAL_SUCCESS) { std::cerr << "Unable to send a buffer " << q << " to encoder output port " << std::endl; } } // Enable burst mode if (enableBurstMode) { if (mmal_port_parameter_set_boolean(m_camera->control, MMAL_PARAMETER_CAMERA_BURST_CAPTURE, 1) != MMAL_SUCCESS) { std::cerr << "Error enabling burst mode" << std::endl; } std::cout << "Enabled burst mode for still images" << std::endl; } std::cout << "Initialized camera" << std::endl; }
PiCam::PiCam(unsigned int width, unsigned int height, std::function<void(cv::Mat)> callback) : width(width), height(height), callback(callback), videoPool(videoPool), cameraComponent(nullptr), previewPort(nullptr), videoPort(nullptr), stillPort(nullptr) { bcm_host_init(); std::cout << "BCM HOST INIT Finished" << std::endl; MMAL_STATUS_T status; status = mmal_component_create(MMAL_COMPONENT_DEFAULT_CAMERA, &cameraComponent); if(status != MMAL_SUCCESS) throw std::runtime_error("Couldn't create camera component."); if(!cameraComponent->output_num) throw std::runtime_error("Camera doesn't have output ports."); videoPort = cameraComponent->output[MMAL_CAMERA_VIDEO_PORT]; stillPort = cameraComponent->output[MMAL_CAMERA_CAPTURE_PORT]; { MMAL_PARAMETER_CAMERA_CONFIG_T cam_config = { { MMAL_PARAMETER_CAMERA_CONFIG, sizeof(cam_config) }, .max_stills_w = width, .max_stills_h = height, .stills_yuv422 = 0, .one_shot_stills = 0, .max_preview_video_w = width, .max_preview_video_h = height, .num_preview_video_frames = 3, .stills_capture_circular_buffer_height = 0, .fast_preview_resume = 0, .use_stc_timestamp = MMAL_PARAM_TIMESTAMP_MODE_RESET_STC }; mmal_port_parameter_set(cameraComponent->control, &cam_config.hdr); } // Setup format for the video port. MMAL_ES_FORMAT_T* format = videoPort->format; format->encoding = MMAL_ENCODING_BGR24; format->encoding_variant = MMAL_ENCODING_BGR24; //format->encoding = MMAL_ENCODING_I420; //format->encoding_variant = MMAL_ENCODING_I420; format->es->video.width = width; format->es->video.height = height; format->es->video.crop.x = 0; format->es->video.crop.y = 0; format->es->video.crop.width = width; format->es->video.crop.height = height; format->es->video.frame_rate.num = framerate; format->es->video.frame_rate.den = VIDEO_FRAME_RATE_DEN; status = mmal_port_format_commit(videoPort); if(status) throw std::runtime_error("Couldn't set video format."); status = mmal_port_enable(videoPort, PiCam::video_buffer_callback); if(status) throw std::runtime_error("Couldn't enable video buffer callback"); if (videoPort->buffer_num < VIDEO_OUTPUT_BUFFERS_NUM) videoPort->buffer_num = VIDEO_OUTPUT_BUFFERS_NUM; // Setup format for the still port. format = stillPort->format; format->encoding = MMAL_ENCODING_OPAQUE; format->encoding_variant = MMAL_ENCODING_I420; format->es->video.width = width; format->es->video.height = height; format->es->video.crop.x = 0; format->es->video.crop.y = 0; format->es->video.crop.width = width; format->es->video.crop.height = height; format->es->video.frame_rate.num = 1; format->es->video.frame_rate.den = 1; status = mmal_port_format_commit(stillPort); if(status) throw std::runtime_error("Couldn't set still format."); // Ensure there are enough buffers to avoid dropping frames. if (stillPort->buffer_num < VIDEO_OUTPUT_BUFFERS_NUM) stillPort->buffer_num = VIDEO_OUTPUT_BUFFERS_NUM; videoPort->buffer_size = videoPort->buffer_size_recommended; videoPort->buffer_num = videoPort->buffer_num_recommended; videoPool = mmal_port_pool_create(videoPort, videoPort->buffer_num, videoPort->buffer_size); if(!videoPool) throw std::runtime_error("Couldn't create buffer header pool for video output port"); MMAL_PARAMETER_EXPOSUREMODE_T exp_mode = {{MMAL_PARAMETER_EXPOSURE_MODE,sizeof(exp_mode)}, MMAL_PARAM_EXPOSUREMODE_FIXEDFPS}; status = mmal_port_parameter_set(cameraComponent->control, &exp_mode.hdr); status = mmal_component_enable(cameraComponent); // frame = cv::Mat(height, width, CV_8UC3); videoPort->userdata = (struct MMAL_PORT_USERDATA_T*)this; /* if (mmal_port_parameter_set_boolean(videoPort, MMAL_PARAMETER_CAPTURE, 1) != MMAL_SUCCESS) { throw std::runtime_error("Couldn't start video capture"); } int num = mmal_queue_length(videoPool->queue); int q; for (q=0;q<num;q++) { MMAL_BUFFER_HEADER_T *buffer = mmal_queue_get(videoPool->queue); // TODO: Add numbers to these error messages. if (!buffer) throw std::runtime_error("Unable to get a required buffer from pool queue"); if (mmal_port_send_buffer(videoPort, buffer)!= MMAL_SUCCESS) throw std::runtime_error("Unable to send a buffer to an encoder output port"); } */ }
MMAL_COMPONENT_T *Private_Impl::create_camera_component ( RASPIVID_STATE *state ) { MMAL_COMPONENT_T *camera = 0; MMAL_ES_FORMAT_T *format; MMAL_PORT_T *video_port = NULL; // MMAL_PORT_T *preview_port = NULL; // MMAL_PORT_T *still_port = NULL; MMAL_STATUS_T status; /* Create the component */ status = mmal_component_create ( MMAL_COMPONENT_DEFAULT_CAMERA, &camera ); if ( status != MMAL_SUCCESS ) { cerr << ( "Failed to create camera component" ); return 0; } if ( !camera->output_num ) { cerr << ( "Camera doesn't have output ports" ); mmal_component_destroy ( camera ); return 0; } video_port = camera->output[MMAL_CAMERA_VIDEO_PORT]; // preview_port=camera->output[MMAL_CAMERA_PREVIEW_PORT]; // still_port=camera->output[MMAL_CAMERA_CAPTURE_PORT]; // set up the camera configuration MMAL_PARAMETER_CAMERA_CONFIG_T cam_config; cam_config.hdr.id = MMAL_PARAMETER_CAMERA_CONFIG; cam_config.hdr.size = sizeof ( cam_config ); cam_config.max_stills_w = state->width; cam_config.max_stills_h = state->height; cam_config.stills_yuv422 = 0; cam_config.one_shot_stills = 0; cam_config.max_preview_video_w = state->width; cam_config.max_preview_video_h = state->height; cam_config.num_preview_video_frames = 3; cam_config.stills_capture_circular_buffer_height = 0; cam_config.fast_preview_resume = 0; cam_config.use_stc_timestamp = MMAL_PARAM_TIMESTAMP_MODE_RAW_STC; mmal_port_parameter_set ( camera->control, &cam_config.hdr ); /** * Set the ROI of the sensor to use for captures/preview * @param camera Pointer to camera component * @param rect Normalised coordinates of ROI rectangle * * */ MMAL_PARAMETER_INPUT_CROP_T crop = {{MMAL_PARAMETER_INPUT_CROP, sizeof(MMAL_PARAMETER_INPUT_CROP_T)}}; double x = state->roi.x; double y = state->roi.y; double w = state->roi.w; double h = state->roi.h; if (x + w > 1.0) w = 1 - x; if (y + h > 1.0) h = 1 - y; crop.rect.x = (65536 * x); crop.rect.y = (65536 * y); crop.rect.width = (65536 * w); crop.rect.height = (65536 * h); mmal_port_parameter_set(camera->control, &crop.hdr); // Set the encode format on the video port format = video_port->format; format->encoding_variant = convertFormat ( State.captureFtm ); format->encoding = convertFormat ( State.captureFtm ); format->es->video.width = VCOS_ALIGN_UP(state->width, 32); format->es->video.height = VCOS_ALIGN_UP(state->height, 16); format->es->video.crop.x = 0; format->es->video.crop.y = 0; format->es->video.crop.width = state->width; format->es->video.crop.height = state->height; format->es->video.frame_rate.num = state->framerate; format->es->video.frame_rate.den = VIDEO_FRAME_RATE_DEN; status = mmal_port_format_commit ( video_port ); if ( status ) { cerr << ( "camera video format couldn't be set" ); mmal_component_destroy ( camera ); return 0; } // Ensure there are enough buffers to avoid dropping frames if ( video_port->buffer_num < VIDEO_OUTPUT_BUFFERS_NUM ) video_port->buffer_num = VIDEO_OUTPUT_BUFFERS_NUM; video_port->buffer_size = video_port->buffer_size_recommended; //video_port->buffer_num = video_port->buffer_num_recommended; //PR : create pool of message on video port MMAL_POOL_T *pool; pool = mmal_port_pool_create ( video_port, video_port->buffer_num, video_port->buffer_size ); if ( !pool ) { cerr << ( "Failed to create buffer header pool for video output port" ); } state->video_pool = pool; // PR : plug the callback to the video port status = mmal_port_enable ( video_port, video_buffer_callback ); if ( status ) { cerr << ( "camera video callback2 error" ); mmal_component_destroy ( camera ); return 0; } /* Enable component */ status = mmal_component_enable ( camera ); if ( status ) { cerr << ( "camera component couldn't be enabled" ); mmal_component_destroy ( camera ); return 0; } state->camera_component = camera;//this needs to be before set_all_parameters return camera; }
/** * Create the camera component, set up its ports * * @param state Pointer to state control struct * * @return 0 if failed, pointer to component if successful * */ static MMAL_COMPONENT_T *create_camera_component(RASPISTILLYUV_STATE *state) { MMAL_COMPONENT_T *camera = 0; MMAL_ES_FORMAT_T *format; MMAL_PORT_T *preview_port = NULL, *video_port = NULL, *still_port = NULL; MMAL_STATUS_T status; MMAL_POOL_T *pool; /* Create the component */ status = mmal_component_create(MMAL_COMPONENT_DEFAULT_CAMERA, &camera); if (status != MMAL_SUCCESS) { vcos_log_error("Failed to create camera component"); goto error; } if (!camera->output_num) { vcos_log_error("Camera doesn't have output ports"); goto error; } preview_port = camera->output[MMAL_CAMERA_PREVIEW_PORT]; video_port = camera->output[MMAL_CAMERA_VIDEO_PORT]; still_port = camera->output[MMAL_CAMERA_CAPTURE_PORT]; // Enable the camera, and tell it its control callback function status = mmal_port_enable(camera->control, camera_control_callback); if (status) { vcos_log_error("Unable to enable control port : error %d", status); goto error; } // set up the camera configuration { MMAL_PARAMETER_CAMERA_CONFIG_T cam_config = { { MMAL_PARAMETER_CAMERA_CONFIG, sizeof(cam_config) }, .max_stills_w = state->width, .max_stills_h = state->height, .stills_yuv422 = 0, .one_shot_stills = 0, .max_preview_video_w = state->preview_parameters.previewWindow.width, .max_preview_video_h = state->preview_parameters.previewWindow.height, .num_preview_video_frames = 3, .stills_capture_circular_buffer_height = 0, .fast_preview_resume = 0, .use_stc_timestamp = MMAL_PARAM_TIMESTAMP_MODE_RESET_STC }; mmal_port_parameter_set(camera->control, &cam_config.hdr); } raspicamcontrol_set_all_parameters(camera, &state->camera_parameters); // Now set up the port formats format = preview_port->format; format->encoding = MMAL_ENCODING_OPAQUE; format->encoding_variant = MMAL_ENCODING_I420; format->es->video.width = state->preview_parameters.previewWindow.width; format->es->video.height = state->preview_parameters.previewWindow.height; format->es->video.crop.x = 0; format->es->video.crop.y = 0; format->es->video.crop.width = state->preview_parameters.previewWindow.width; format->es->video.crop.height = state->preview_parameters.previewWindow.height; format->es->video.frame_rate.num = PREVIEW_FRAME_RATE_NUM; format->es->video.frame_rate.den = PREVIEW_FRAME_RATE_DEN; status = mmal_port_format_commit(preview_port); if (status) { vcos_log_error("camera viewfinder format couldn't be set"); goto error; } // Set the same format on the video port (which we dont use here) mmal_format_full_copy(video_port->format, format); status = mmal_port_format_commit(video_port); if (status) { vcos_log_error("camera video format couldn't be set"); goto error; } // Ensure there are enough buffers to avoid dropping frames if (video_port->buffer_num < VIDEO_OUTPUT_BUFFERS_NUM) video_port->buffer_num = VIDEO_OUTPUT_BUFFERS_NUM; format = still_port->format; // Set our stills format on the stills port format->encoding = MMAL_ENCODING_I420; format->encoding_variant = MMAL_ENCODING_I420; format->es->video.width = state->width; format->es->video.height = state->height; format->es->video.crop.x = 0; format->es->video.crop.y = 0; format->es->video.crop.width = state->width; format->es->video.crop.height = state->height; format->es->video.frame_rate.num = STILLS_FRAME_RATE_NUM; format->es->video.frame_rate.den = STILLS_FRAME_RATE_DEN; if (still_port->buffer_size < still_port->buffer_size_min) still_port->buffer_size = still_port->buffer_size_min; still_port->buffer_num = still_port->buffer_num_recommended; status = mmal_port_format_commit(still_port); if (status) { vcos_log_error("camera still format couldn't be set"); goto error; } /* Enable component */ status = mmal_component_enable(camera); if (status) { vcos_log_error("camera component couldn't be enabled"); goto error; } /* Create pool of buffer headers for the output port to consume */ pool = mmal_port_pool_create(still_port, still_port->buffer_num, still_port->buffer_size); if (!pool) { vcos_log_error("Failed to create buffer header pool for camera still port %s", still_port->name); } state->camera_pool = pool; state->camera_component = camera; if (state->verbose) printf("Camera component done\n"); return camera; error: if (camera) mmal_component_destroy(camera); return 0; }
int Private_Impl_Still::createCamera() { if ( mmal_component_create ( MMAL_COMPONENT_DEFAULT_CAMERA, &camera ) ) { cout << API_NAME << ": Failed to create camera component.\n"; destroyCamera(); return -1; } if ( !camera->output_num ) { cout << API_NAME << ": Camera does not have output ports!\n"; destroyCamera(); return -1; } camera_still_port = camera->output[MMAL_CAMERA_CAPTURE_PORT]; // Enable the camera, and tell it its control callback function if ( mmal_port_enable ( camera->control, control_callback ) ) { cout << API_NAME << ": Could not enable control port.\n"; destroyCamera(); return -1; } MMAL_PARAMETER_CAMERA_CONFIG_T camConfig = { {MMAL_PARAMETER_CAMERA_CONFIG, sizeof ( camConfig ) }, width, // max_stills_w height, // max_stills_h 0, // stills_yuv422 1, // one_shot_stills width, // max_preview_video_w height, // max_preview_video_h 3, // num_preview_video_frames 0, // stills_capture_circular_buffer_height 0, // fast_preview_resume MMAL_PARAM_TIMESTAMP_MODE_RESET_STC // use_stc_timestamp }; if ( mmal_port_parameter_set ( camera->control, &camConfig.hdr ) != MMAL_SUCCESS ) cout << API_NAME << ": Could not set port parameters.\n"; commitParameters(); MMAL_ES_FORMAT_T * format = camera_still_port->format; format->encoding = MMAL_ENCODING_OPAQUE; format->es->video.width = width; format->es->video.height = height; format->es->video.crop.x = 0; format->es->video.crop.y = 0; format->es->video.crop.width = width; format->es->video.crop.height = height; format->es->video.frame_rate.num = STILLS_FRAME_RATE_NUM; format->es->video.frame_rate.den = STILLS_FRAME_RATE_DEN; if ( camera_still_port->buffer_size < camera_still_port->buffer_size_min ) camera_still_port->buffer_size = camera_still_port->buffer_size_min; camera_still_port->buffer_num = camera_still_port->buffer_num_recommended; if ( mmal_port_format_commit ( camera_still_port ) ) { cout << API_NAME << ": Camera still format could not be set.\n"; destroyCamera(); return -1; } if ( mmal_component_enable ( camera ) ) { cout << API_NAME << ": Camera component could not be enabled.\n"; destroyCamera(); return -1; } if ( ! ( encoder_pool = mmal_port_pool_create ( camera_still_port, camera_still_port->buffer_num, camera_still_port->buffer_size ) ) ) { cout << API_NAME << ": Failed to create buffer header pool for camera.\n"; destroyCamera(); return -1; } return 0; }
/* Registers a callback on the camera preview port to receive * notifications of new frames. * This must be called before rapitex_start and may not be called again * without calling raspitex_destroy first. * * @param state Pointer to the GL preview state. * @param port Pointer to the camera preview port * @return Zero if successful. */ int raspitex_configure_preview_port(RASPITEX_STATE *state, MMAL_PORT_T *preview_port) { MMAL_STATUS_T status; vcos_log_trace("%s port %p", VCOS_FUNCTION, preview_port); /* Enable ZERO_COPY mode on the preview port which instructs MMAL to only * pass the 4-byte opaque buffer handle instead of the contents of the opaque * buffer. * The opaque handle is resolved on VideoCore by the GL driver when the EGL * image is created. */ status = mmal_port_parameter_set_boolean(preview_port, MMAL_PARAMETER_ZERO_COPY, MMAL_TRUE); if (status != MMAL_SUCCESS) { vcos_log_error("Failed to enable zero copy on camera preview port"); goto end; } status = mmal_port_format_commit(preview_port); if (status != MMAL_SUCCESS) { vcos_log_error("camera viewfinder format couldn't be set"); goto end; } /* For GL a pool of opaque buffer handles must be allocated in the client. * These buffers are used to create the EGL images. */ state->preview_port = preview_port; preview_port->buffer_num = preview_port->buffer_num_recommended; preview_port->buffer_size = preview_port->buffer_size_recommended; vcos_log_trace("Creating buffer pool for GL renderer num %d size %d", preview_port->buffer_num, preview_port->buffer_size); /* Pool + queue to hold preview frames */ state->preview_pool = mmal_port_pool_create(preview_port, preview_port->buffer_num, preview_port->buffer_size); if (! state->preview_pool) { vcos_log_error("Error allocating pool"); status = MMAL_ENOMEM; goto end; } /* Place filled buffers from the preview port in a queue to render */ state->preview_queue = mmal_queue_create(); if (! state->preview_queue) { vcos_log_error("Error allocating queue"); status = MMAL_ENOMEM; goto end; } /* Enable preview port callback */ preview_port->userdata = (struct MMAL_PORT_USERDATA_T*) state; status = mmal_port_enable(preview_port, preview_output_cb); if (status != MMAL_SUCCESS) { vcos_log_error("Failed to camera preview port"); goto end; } end: return (status == MMAL_SUCCESS ? 0 : -1); }
int main (int argc, char* argv[]) { MMAL_STATUS_T status; int i, max, fd, length, cam_setting; unsigned long int cam_setting_long; char readbuf[20]; char *filename_temp, *filename_temp2, *cmd_temp; bcm_host_init(); // // read arguments // unsigned char of_set = 0; for(i=1; i<argc; i++) { if(strcmp(argv[i], "--version") == 0) { printf("RaspiMJPEG Version "); printf(VERSION); printf("\n"); exit(0); } else if(strcmp(argv[i], "-w") == 0) { i++; width = atoi(argv[i]); } else if(strcmp(argv[i], "-h") == 0) { i++; height = atoi(argv[i]); } else if(strcmp(argv[i], "-wp") == 0) { i++; width_pic = atoi(argv[i]); } else if(strcmp(argv[i], "-hp") == 0) { i++; height_pic = atoi(argv[i]); } else if(strcmp(argv[i], "-q") == 0) { i++; quality = atoi(argv[i]); } else if(strcmp(argv[i], "-d") == 0) { i++; divider = atoi(argv[i]); } else if(strcmp(argv[i], "-p") == 0) { mp4box = 1; } else if(strcmp(argv[i], "-ic") == 0) { i++; image2_cnt = atoi(argv[i]); } else if(strcmp(argv[i], "-vc") == 0) { i++; video_cnt = atoi(argv[i]); } else if(strcmp(argv[i], "-of") == 0) { i++; jpeg_filename = argv[i]; of_set = 1; } else if(strcmp(argv[i], "-if") == 0) { i++; jpeg2_filename = argv[i]; of_set = 1; } else if(strcmp(argv[i], "-cf") == 0) { i++; pipe_filename = argv[i]; } else if(strcmp(argv[i], "-vf") == 0) { i++; h264_filename = argv[i]; } else if(strcmp(argv[i], "-sf") == 0) { i++; status_filename = argv[i]; } else if(strcmp(argv[i], "-pa") == 0) { autostart = 0; idle = 1; } else if(strcmp(argv[i], "-md") == 0) { motion_detection = 1; } else if(strcmp(argv[i], "-fp") == 0) { preview_mode = RES_4_3; } else if(strcmp(argv[i], "-audio") == 0) { audio_mode = 1; } else error("Invalid arguments"); } if(!of_set) error("Output file not specified"); // // init // if(autostart) start_all(); if(motion_detection) { if(system("motion") == -1) error("Could not start Motion"); } // // run // if(autostart) { if(pipe_filename != 0) printf("MJPEG streaming, ready to receive commands\n"); else printf("MJPEG streaming\n"); } else { if(pipe_filename != 0) printf("MJPEG idle, ready to receive commands\n"); else printf("MJPEG idle\n"); } struct sigaction action; memset(&action, 0, sizeof(struct sigaction)); action.sa_handler = term; sigaction(SIGTERM, &action, NULL); sigaction(SIGINT, &action, NULL); if(status_filename != 0) { status_file = fopen(status_filename, "w"); if(!status_file) error("Could not open/create status-file"); if(autostart) { if(!motion_detection) { fprintf(status_file, "ready"); } else fprintf(status_file, "md_ready"); } else fprintf(status_file, "halted"); fclose(status_file); } while(running) { if(pipe_filename != 0) { fd = open(pipe_filename, O_RDONLY | O_NONBLOCK); if(fd < 0) error("Could not open PIPE"); fcntl(fd, F_SETFL, 0); length = read(fd, readbuf, 20); close(fd); if(length) { if((readbuf[0]=='p') && (readbuf[1]=='m')) { stop_all(); readbuf[0] = ' '; readbuf[1] = ' '; readbuf[length] = 0; if(strcmp(readbuf, " 4_3") == 0) preview_mode = RES_4_3; else if(strcmp(readbuf, " 16_9_STD") == 0) preview_mode = RES_16_9_STD; else if(strcmp(readbuf, " 16_9_WIDE") == 0) preview_mode = RES_16_9_WIDE; start_all(); printf("Changed preview mode\n"); if(status_filename != 0) { status_file = fopen(status_filename, "w"); fprintf(status_file, "ready"); fclose(status_file); } } else if((readbuf[0]=='c') && (readbuf[1]=='a')) { if(readbuf[3]=='1') { if(!capturing) { status = mmal_component_enable(h264encoder); if(status != MMAL_SUCCESS) error("Could not enable h264encoder"); pool_h264encoder = mmal_port_pool_create(h264encoder->output[0], h264encoder->output[0]->buffer_num, h264encoder->output[0]->buffer_size); if(!pool_h264encoder) error("Could not create pool"); status = mmal_connection_create(&con_cam_h264, camera->output[1], h264encoder->input[0], MMAL_CONNECTION_FLAG_TUNNELLING | MMAL_CONNECTION_FLAG_ALLOCATION_ON_INPUT); if(status != MMAL_SUCCESS) error("Could not create connecton camera -> video converter"); status = mmal_connection_enable(con_cam_h264); if(status != MMAL_SUCCESS) error("Could not enable connection camera -> video converter"); currTime = time(NULL); localTime = localtime (&currTime); if(mp4box) { asprintf(&filename_temp, h264_filename, video_cnt, localTime->tm_year+1900, localTime->tm_mon+1, localTime->tm_mday, localTime->tm_hour, localTime->tm_min, localTime->tm_sec); asprintf(&filename_temp2, "%s.h264", filename_temp); } else { asprintf(&filename_temp2, h264_filename, video_cnt, localTime->tm_year+1900, localTime->tm_mon+1, localTime->tm_mday, localTime->tm_hour, localTime->tm_min, localTime->tm_sec); } h264output_file = fopen(filename_temp2, "wb"); free(filename_temp2); if(mp4box) { if(audio_mode) { asprintf(&cmd_temp, "/usr/bin/arecord -q -D hw:1,0 -f S16_LE -t wav | /usr/bin/lame - %s.mp3 -S &", filename_temp); printf("Audio recording with \"%s\\n", cmd_temp); if(system(cmd_temp) == -1) error("Could not start audio recording"); } free(filename_temp); } if(!h264output_file) error("Could not open/create video-file"); status = mmal_port_enable(h264encoder->output[0], h264encoder_buffer_callback); if(status != MMAL_SUCCESS) error("Could not enable video port"); max = mmal_queue_length(pool_h264encoder->queue); for(i=0;i<max;i++) { MMAL_BUFFER_HEADER_T *h264buffer = mmal_queue_get(pool_h264encoder->queue); if(!h264buffer) error("Could not create video pool header"); status = mmal_port_send_buffer(h264encoder->output[0], h264buffer); if(status != MMAL_SUCCESS) error("Could not send buffers to video port"); } mmal_port_parameter_set_boolean(camera->output[1], MMAL_PARAMETER_CAPTURE, 1); if(status != MMAL_SUCCESS) error("Could not start capture"); printf("Capturing started\n"); if(status_filename != 0) { status_file = fopen(status_filename, "w"); if(!motion_detection) fprintf(status_file, "video"); else fprintf(status_file, "md_video"); fclose(status_file); } capturing = 1; } } else { if(capturing) { mmal_port_parameter_set_boolean(camera->output[1], MMAL_PARAMETER_CAPTURE, 0); if(status != MMAL_SUCCESS) error("Could not stop capture"); status = mmal_port_disable(h264encoder->output[0]); if(status != MMAL_SUCCESS) error("Could not disable video port"); status = mmal_connection_destroy(con_cam_h264); if(status != MMAL_SUCCESS) error("Could not destroy connection camera -> video encoder"); mmal_port_pool_destroy(h264encoder->output[0], pool_h264encoder); if(status != MMAL_SUCCESS) error("Could not destroy video buffer pool"); status = mmal_component_disable(h264encoder); if(status != MMAL_SUCCESS) error("Could not disable video converter"); fclose(h264output_file); h264output_file = NULL; printf("Capturing stopped\n"); if(mp4box) { printf("Boxing started\n"); status_file = fopen(status_filename, "w"); if(!motion_detection) fprintf(status_file, "boxing"); else fprintf(status_file, "md_boxing"); fclose(status_file); asprintf(&filename_temp, h264_filename, video_cnt, localTime->tm_year+1900, localTime->tm_mon+1, localTime->tm_mday, localTime->tm_hour, localTime->tm_min, localTime->tm_sec); if(audio_mode) { asprintf(&cmd_temp, "/usr/bin/killall arecord > /dev/null"); if(system(cmd_temp) == -1) error("Could not stop audio recording"); free(cmd_temp); asprintf(&cmd_temp, "MP4Box -fps 25 -add %s.h264 -add %s.mp3 %s > /dev/null", filename_temp, filename_temp, filename_temp); } else { asprintf(&cmd_temp, "MP4Box -fps 25 -add %s.h264 %s > /dev/null", filename_temp, filename_temp); } if(system(cmd_temp) == -1) error("Could not start MP4Box"); asprintf(&filename_temp2, "%s.h264", filename_temp); remove(filename_temp2); free(filename_temp2); if (audio_mode) { asprintf(&filename_temp2, "%s.mp3", filename_temp); remove(filename_temp2); free(filename_temp2); } free(filename_temp); free(cmd_temp); printf("Boxing stopped\n"); } video_cnt++; if(status_filename != 0) { status_file = fopen(status_filename, "w"); if(!motion_detection) fprintf(status_file, "ready"); else fprintf(status_file, "md_ready"); fclose(status_file); } capturing = 0; } } } else if((readbuf[0]=='i') && (readbuf[1]=='m')) { capt_img(); } else if((readbuf[0]=='t') && (readbuf[1]=='l')) { readbuf[0] = ' '; readbuf[1] = ' '; readbuf[length] = 0; time_between_pic = atoi(readbuf); if(time_between_pic) { if(status_filename != 0) { status_file = fopen(status_filename, "w"); fprintf(status_file, "timelapse"); fclose(status_file); } timelapse = 1; printf("Timelapse started\n"); } else { if(status_filename != 0) { status_file = fopen(status_filename, "w"); fprintf(status_file, "ready"); fclose(status_file); } timelapse = 0; printf("Timelapse stopped\n"); } } else if((readbuf[0]=='s') && (readbuf[1]=='h')) { readbuf[0] = ' '; readbuf[1] = ' '; readbuf[length] = 0; cam_setting = atoi(readbuf); MMAL_RATIONAL_T value = {cam_setting, 100}; status = mmal_port_parameter_set_rational(camera->control, MMAL_PARAMETER_SHARPNESS, value); if(status != MMAL_SUCCESS) error("Could not set sharpness"); printf("Sharpness: %d\n", cam_setting); } else if((readbuf[0]=='c') && (readbuf[1]=='o')) { readbuf[0] = ' '; readbuf[1] = ' '; readbuf[length] = 0; cam_setting = atoi(readbuf); MMAL_RATIONAL_T value = {cam_setting, 100}; status = mmal_port_parameter_set_rational(camera->control, MMAL_PARAMETER_CONTRAST, value); if(status != MMAL_SUCCESS) error("Could not set contrast"); printf("Contrast: %d\n", cam_setting); } else if((readbuf[0]=='b') && (readbuf[1]=='r')) { readbuf[0] = ' '; readbuf[1] = ' '; readbuf[length] = 0; cam_setting = atoi(readbuf); MMAL_RATIONAL_T value = {cam_setting, 100}; status = mmal_port_parameter_set_rational(camera->control, MMAL_PARAMETER_BRIGHTNESS, value); if(status != MMAL_SUCCESS) error("Could not set brightness"); printf("Brightness: %d\n", cam_setting); } else if((readbuf[0]=='s') && (readbuf[1]=='a')) { readbuf[0] = ' '; readbuf[1] = ' '; readbuf[length] = 0; cam_setting = atoi(readbuf); MMAL_RATIONAL_T value = {cam_setting, 100}; status = mmal_port_parameter_set_rational(camera->control, MMAL_PARAMETER_SATURATION, value); if(status != MMAL_SUCCESS) error("Could not set saturation"); printf("Saturation: %d\n", cam_setting); } else if((readbuf[0]=='i') && (readbuf[1]=='s')) { readbuf[0] = ' '; readbuf[1] = ' '; readbuf[length] = 0; cam_setting = atoi(readbuf); status = mmal_port_parameter_set_uint32(camera->control, MMAL_PARAMETER_ISO, cam_setting); if(status != MMAL_SUCCESS) error("Could not set ISO"); printf("ISO: %d\n", cam_setting); } else if((readbuf[0]=='v') && (readbuf[1]=='s')) { if(readbuf[3]=='1') { status = mmal_port_parameter_set_boolean(camera->control, MMAL_PARAMETER_VIDEO_STABILISATION, 1); printf("Video Stabilisation ON\n"); } else { status = mmal_port_parameter_set_boolean(camera->control, MMAL_PARAMETER_VIDEO_STABILISATION, 0); printf("Video Stabilisation OFF\n"); } if(status != MMAL_SUCCESS) error("Could not set video stabilisation"); } else if((readbuf[0]=='e') && (readbuf[1]=='c')) { readbuf[0] = ' '; readbuf[1] = ' '; readbuf[length] = 0; cam_setting = atoi(readbuf); status = mmal_port_parameter_set_int32(camera->control, MMAL_PARAMETER_EXPOSURE_COMP, cam_setting); if(status != MMAL_SUCCESS) error("Could not set exposure compensation"); printf("Exposure Compensation: %d\n", cam_setting); } else if((readbuf[0]=='e') && (readbuf[1]=='m')) { readbuf[0] = ' '; readbuf[1] = ' '; readbuf[length] = 0; MMAL_PARAM_EXPOSUREMODE_T mode = MMAL_PARAM_EXPOSUREMODE_OFF; if(strcmp(readbuf, " auto") == 0) mode = MMAL_PARAM_EXPOSUREMODE_AUTO; else if(strcmp(readbuf, " night") == 0) mode = MMAL_PARAM_EXPOSUREMODE_NIGHT; else if(strcmp(readbuf, " nightpreview") == 0) mode = MMAL_PARAM_EXPOSUREMODE_NIGHTPREVIEW; else if(strcmp(readbuf, " backlight") == 0) mode = MMAL_PARAM_EXPOSUREMODE_BACKLIGHT; else if(strcmp(readbuf, " spotlight") == 0) mode = MMAL_PARAM_EXPOSUREMODE_SPOTLIGHT; else if(strcmp(readbuf, " sports") == 0) mode = MMAL_PARAM_EXPOSUREMODE_SPORTS; else if(strcmp(readbuf, " snow") == 0) mode = MMAL_PARAM_EXPOSUREMODE_SNOW; else if(strcmp(readbuf, " beach") == 0) mode = MMAL_PARAM_EXPOSUREMODE_BEACH; else if(strcmp(readbuf, " verylong") == 0) mode = MMAL_PARAM_EXPOSUREMODE_VERYLONG; else if(strcmp(readbuf, " fixedfps") == 0) mode = MMAL_PARAM_EXPOSUREMODE_FIXEDFPS; else if(strcmp(readbuf, " antishake") == 0) mode = MMAL_PARAM_EXPOSUREMODE_ANTISHAKE; else if(strcmp(readbuf, " fireworks") == 0) mode = MMAL_PARAM_EXPOSUREMODE_FIREWORKS; MMAL_PARAMETER_EXPOSUREMODE_T exp_mode = {{MMAL_PARAMETER_EXPOSURE_MODE,sizeof(exp_mode)}, mode}; status = mmal_port_parameter_set(camera->control, &exp_mode.hdr); if(status != MMAL_SUCCESS) error("Could not set exposure mode"); printf("Exposure mode changed\n"); } else if((readbuf[0]=='w') && (readbuf[1]=='b')) { readbuf[0] = ' '; readbuf[1] = ' '; readbuf[length] = 0; MMAL_PARAM_AWBMODE_T awb_mode = MMAL_PARAM_AWBMODE_OFF; if(strcmp(readbuf, " auto") == 0) awb_mode = MMAL_PARAM_AWBMODE_AUTO; else if(strcmp(readbuf, " auto") == 0) awb_mode = MMAL_PARAM_AWBMODE_AUTO; else if(strcmp(readbuf, " sun") == 0) awb_mode = MMAL_PARAM_AWBMODE_SUNLIGHT; else if(strcmp(readbuf, " cloudy") == 0) awb_mode = MMAL_PARAM_AWBMODE_CLOUDY; else if(strcmp(readbuf, " shade") == 0) awb_mode = MMAL_PARAM_AWBMODE_SHADE; else if(strcmp(readbuf, " tungsten") == 0) awb_mode = MMAL_PARAM_AWBMODE_TUNGSTEN; else if(strcmp(readbuf, " fluorescent") == 0) awb_mode = MMAL_PARAM_AWBMODE_FLUORESCENT; else if(strcmp(readbuf, " incandescent") == 0) awb_mode = MMAL_PARAM_AWBMODE_INCANDESCENT; else if(strcmp(readbuf, " flash") == 0) awb_mode = MMAL_PARAM_AWBMODE_FLASH; else if(strcmp(readbuf, " horizon") == 0) awb_mode = MMAL_PARAM_AWBMODE_HORIZON; MMAL_PARAMETER_AWBMODE_T param = {{MMAL_PARAMETER_AWB_MODE,sizeof(param)}, awb_mode}; status = mmal_port_parameter_set(camera->control, ¶m.hdr); if(status != MMAL_SUCCESS) error("Could not set white balance"); printf("White balance changed\n"); } else if((readbuf[0]=='r') && (readbuf[1]=='o')) { readbuf[0] = ' '; readbuf[1] = ' '; readbuf[length] = 0; cam_setting = atoi(readbuf); status = mmal_port_parameter_set_int32(camera->output[0], MMAL_PARAMETER_ROTATION, cam_setting); if(status != MMAL_SUCCESS) error("Could not set rotation (0)"); status = mmal_port_parameter_set_int32(camera->output[1], MMAL_PARAMETER_ROTATION, cam_setting); if(status != MMAL_SUCCESS) error("Could not set rotation (1)"); status = mmal_port_parameter_set_int32(camera->output[2], MMAL_PARAMETER_ROTATION, cam_setting); if(status != MMAL_SUCCESS) error("Could not set rotation (2)"); printf("Rotation: %d\n", cam_setting); } else if((readbuf[0]=='q') && (readbuf[1]=='u')) { readbuf[0] = ' '; readbuf[1] = ' '; readbuf[length] = 0; cam_setting = atoi(readbuf); status = mmal_port_parameter_set_uint32(jpegencoder2->output[0], MMAL_PARAMETER_JPEG_Q_FACTOR, cam_setting); if(status != MMAL_SUCCESS) error("Could not set quality"); printf("Quality: %d\n", cam_setting); } else if((readbuf[0]=='b') && (readbuf[1]=='i')) { readbuf[0] = ' '; readbuf[1] = ' '; readbuf[length] = 0; cam_setting_long = strtoull(readbuf, NULL, 0); h264encoder->output[0]->format->bitrate = cam_setting_long; status = mmal_port_format_commit(h264encoder->output[0]); if(status != MMAL_SUCCESS) error("Could not set bitrate"); printf("Bitrate: %lu\n", cam_setting_long); } else if((readbuf[0]=='r') && (readbuf[1]=='u')) { if(readbuf[3]=='0') { stop_all(); idle = 1; printf("Stream halted\n"); if(status_filename != 0) { status_file = fopen(status_filename, "w"); fprintf(status_file, "halted"); fclose(status_file); } } else { start_all(); idle = 0; printf("Stream continued\n"); if(status_filename != 0) { status_file = fopen(status_filename, "w"); fprintf(status_file, "ready"); fclose(status_file); } } } else if((readbuf[0]=='m') && (readbuf[1]=='d')) { if(readbuf[3]=='0') { motion_detection = 0; if(system("killall motion") == -1) error("Could not stop Motion"); printf("Motion detection stopped\n"); if(status_filename != 0) { status_file = fopen(status_filename, "w"); fprintf(status_file, "ready"); fclose(status_file); } } else { motion_detection = 1; if(system("motion") == -1) error("Could not start Motion"); printf("Motion detection started\n"); if(status_filename != 0) { status_file = fopen(status_filename, "w"); fprintf(status_file, "md_ready"); fclose(status_file); } } } } } if(timelapse) { tl_cnt++; if(tl_cnt >= time_between_pic) { if(capturing == 0) { capt_img(); tl_cnt = 0; } } } usleep(100000); } printf("SIGINT/SIGTERM received, stopping\n"); // // tidy up // if(!idle) stop_all(); return 0; }
/** * Create the camera component, set up its ports * * @param state Pointer to state control struct * * @return 0 if failed, pointer to component if successful * */ static MMAL_STATUS_T create_camera_component(RASPISTILLYUV_STATE *state) { MMAL_COMPONENT_T *camera = 0; MMAL_ES_FORMAT_T *format; MMAL_PORT_T *preview_port = NULL, *video_port = NULL, *still_port = NULL; MMAL_STATUS_T status; MMAL_POOL_T *pool; /* Create the component */ status = mmal_component_create(MMAL_COMPONENT_DEFAULT_CAMERA, &camera); if (status != MMAL_SUCCESS) { vcos_log_error("Failed to create camera component"); goto error; } MMAL_PARAMETER_INT32_T camera_num = {{MMAL_PARAMETER_CAMERA_NUM, sizeof(camera_num)}, state->cameraNum}; status = mmal_port_parameter_set(camera->control, &camera_num.hdr); if (status != MMAL_SUCCESS) { vcos_log_error("Could not select camera : error %d", status); goto error; } if (!camera->output_num) { status = MMAL_ENOSYS; vcos_log_error("Camera doesn't have output ports"); goto error; } preview_port = camera->output[MMAL_CAMERA_PREVIEW_PORT]; video_port = camera->output[MMAL_CAMERA_VIDEO_PORT]; still_port = camera->output[MMAL_CAMERA_CAPTURE_PORT]; if (state->settings) { MMAL_PARAMETER_CHANGE_EVENT_REQUEST_T change_event_request = {{MMAL_PARAMETER_CHANGE_EVENT_REQUEST, sizeof(MMAL_PARAMETER_CHANGE_EVENT_REQUEST_T)}, MMAL_PARAMETER_CAMERA_SETTINGS, 1}; status = mmal_port_parameter_set(camera->control, &change_event_request.hdr); if ( status != MMAL_SUCCESS ) { vcos_log_error("No camera settings events"); } } // Enable the camera, and tell it its control callback function status = mmal_port_enable(camera->control, camera_control_callback); if (status != MMAL_SUCCESS ) { vcos_log_error("Unable to enable control port : error %d", status); goto error; } // set up the camera configuration { MMAL_PARAMETER_CAMERA_CONFIG_T cam_config = { { MMAL_PARAMETER_CAMERA_CONFIG, sizeof(cam_config) }, .max_stills_w = state->width, .max_stills_h = state->height, .stills_yuv422 = 0, .one_shot_stills = 1, .max_preview_video_w = state->preview_parameters.previewWindow.width, .max_preview_video_h = state->preview_parameters.previewWindow.height, .num_preview_video_frames = 3, .stills_capture_circular_buffer_height = 0, .fast_preview_resume = 0, .use_stc_timestamp = MMAL_PARAM_TIMESTAMP_MODE_RESET_STC }; if (state->fullResPreview) { cam_config.max_preview_video_w = state->width; cam_config.max_preview_video_h = state->height; } mmal_port_parameter_set(camera->control, &cam_config.hdr); } raspicamcontrol_set_all_parameters(camera, &state->camera_parameters); // Now set up the port formats format = preview_port->format; format->encoding = MMAL_ENCODING_OPAQUE; format->encoding_variant = MMAL_ENCODING_I420; if(state->camera_parameters.shutter_speed > 6000000) { MMAL_PARAMETER_FPS_RANGE_T fps_range = {{MMAL_PARAMETER_FPS_RANGE, sizeof(fps_range)}, { 50, 1000 }, {166, 1000}}; mmal_port_parameter_set(preview_port, &fps_range.hdr); } else if(state->camera_parameters.shutter_speed > 1000000) { MMAL_PARAMETER_FPS_RANGE_T fps_range = {{MMAL_PARAMETER_FPS_RANGE, sizeof(fps_range)}, { 166, 1000 }, {999, 1000}}; mmal_port_parameter_set(preview_port, &fps_range.hdr); } if (state->fullResPreview) { // In this mode we are forcing the preview to be generated from the full capture resolution. // This runs at a max of 15fps with the OV5647 sensor. format->es->video.width = VCOS_ALIGN_UP(state->width, 32); format->es->video.height = VCOS_ALIGN_UP(state->height, 16); format->es->video.crop.x = 0; format->es->video.crop.y = 0; format->es->video.crop.width = state->width; format->es->video.crop.height = state->height; format->es->video.frame_rate.num = FULL_RES_PREVIEW_FRAME_RATE_NUM; format->es->video.frame_rate.den = FULL_RES_PREVIEW_FRAME_RATE_DEN; } else { // Use a full FOV 4:3 mode format->es->video.width = VCOS_ALIGN_UP(state->preview_parameters.previewWindow.width, 32); format->es->video.height = VCOS_ALIGN_UP(state->preview_parameters.previewWindow.height, 16); format->es->video.crop.x = 0; format->es->video.crop.y = 0; format->es->video.crop.width = state->preview_parameters.previewWindow.width; format->es->video.crop.height = state->preview_parameters.previewWindow.height; format->es->video.frame_rate.num = PREVIEW_FRAME_RATE_NUM; format->es->video.frame_rate.den = PREVIEW_FRAME_RATE_DEN; } status = mmal_port_format_commit(preview_port); if (status != MMAL_SUCCESS ) { vcos_log_error("camera viewfinder format couldn't be set"); goto error; } // Set the same format on the video port (which we dont use here) mmal_format_full_copy(video_port->format, format); status = mmal_port_format_commit(video_port); if (status != MMAL_SUCCESS ) { vcos_log_error("camera video format couldn't be set"); goto error; } // Ensure there are enough buffers to avoid dropping frames if (video_port->buffer_num < VIDEO_OUTPUT_BUFFERS_NUM) video_port->buffer_num = VIDEO_OUTPUT_BUFFERS_NUM; format = still_port->format; if(state->camera_parameters.shutter_speed > 6000000) { MMAL_PARAMETER_FPS_RANGE_T fps_range = {{MMAL_PARAMETER_FPS_RANGE, sizeof(fps_range)}, { 50, 1000 }, {166, 1000}}; mmal_port_parameter_set(still_port, &fps_range.hdr); } else if(state->camera_parameters.shutter_speed > 1000000) { MMAL_PARAMETER_FPS_RANGE_T fps_range = {{MMAL_PARAMETER_FPS_RANGE, sizeof(fps_range)}, { 167, 1000 }, {999, 1000}}; mmal_port_parameter_set(still_port, &fps_range.hdr); } // Set our stills format on the stills port if (state->useRGB) { format->encoding = MMAL_ENCODING_BGR24; format->encoding_variant = MMAL_ENCODING_BGR24; } else { format->encoding = MMAL_ENCODING_I420; format->encoding_variant = MMAL_ENCODING_I420; } format->es->video.width = VCOS_ALIGN_UP(state->width, 32); format->es->video.height = VCOS_ALIGN_UP(state->height, 16); format->es->video.crop.x = 0; format->es->video.crop.y = 0; format->es->video.crop.width = state->width; format->es->video.crop.height = state->height; format->es->video.frame_rate.num = STILLS_FRAME_RATE_NUM; format->es->video.frame_rate.den = STILLS_FRAME_RATE_DEN; if (still_port->buffer_size < still_port->buffer_size_min) still_port->buffer_size = still_port->buffer_size_min; still_port->buffer_num = still_port->buffer_num_recommended; status = mmal_port_format_commit(still_port); if (status != MMAL_SUCCESS ) { vcos_log_error("camera still format couldn't be set"); goto error; } /* Enable component */ status = mmal_component_enable(camera); if (status != MMAL_SUCCESS ) { vcos_log_error("camera component couldn't be enabled"); goto error; } /* Create pool of buffer headers for the output port to consume */ pool = mmal_port_pool_create(still_port, still_port->buffer_num, still_port->buffer_size); if (!pool) { vcos_log_error("Failed to create buffer header pool for camera still port %s", still_port->name); } state->camera_pool = pool; state->camera_component = camera; if (state->verbose) fprintf(stderr, "Camera component done\n"); return status; error: if (camera) mmal_component_destroy(camera); return status; }
void MmalStillCamera::initialize(CameraMode cameraMode) { m_resolution = MmalUtil::get()->getClosestResolution(m_name, cameraMode); if (m_imageWidth != -1) { throw Exception("Camera is already initialized"); } m_imageWidth = m_resolution.width; m_imageHeight = m_resolution.height; m_callbackData = new MmalStillCallbackData(m_imageWidth, m_imageHeight, 3); // Handle the sensor properties real sensorWidth, sensorHeight, focalLength; MmalUtil::get()->getSensorProperties(m_name, sensorWidth, sensorHeight, focalLength); setSensorProperties(sensorWidth, sensorHeight, focalLength); createCameraComponent(); InfoLog << "Created camera" << Logger::ENDL; createPreview(); InfoLog << "Created preview" << Logger::ENDL; InfoLog << "Target Image Width: " << VCOS_ALIGN_UP(m_imageWidth, 32) << Logger::ENDL; InfoLog << "Target Image Height: " << VCOS_ALIGN_UP(m_imageHeight, 16) << Logger::ENDL; MMAL_STATUS_T status; m_targetPort = m_stillPort; // Create pool of buffer headers for the output port to consume m_pool = mmal_port_pool_create(m_targetPort, m_targetPort->buffer_num, m_targetPort->buffer_size); if (m_pool == NULL) { throw Exception("Failed to create buffer header pool for encoder output port"); } MMAL_CONNECTION_T *preview_connection = NULL; status = connect_ports(m_previewPort, m_preview->input[0], &preview_connection); if (status != MMAL_SUCCESS) { throw Exception("Error connecting preview port"); } m_targetPort->userdata = (struct MMAL_PORT_USERDATA_T *) m_callbackData; m_callbackData->image = NULL; m_callbackData->pool = m_pool; // Enable the encoder output port and tell it its callback function if (mmal_port_enable(m_targetPort, EncoderBufferCallback) != MMAL_SUCCESS) { ErrorLog << "Error enabling the encoder buffer callback" << Logger::ENDL; } // Send all the buffers to the encoder output port int num = mmal_queue_length(m_pool->queue); for (int q = 0; q < num; q++) { MMAL_BUFFER_HEADER_T *buffer = mmal_queue_get(m_pool->queue); if (buffer == NULL) { ErrorLog << "Unable to get buffer " << q << " from the pool" << Logger::ENDL; } if (mmal_port_send_buffer(m_targetPort, buffer) != MMAL_SUCCESS) { ErrorLog << "Unable to send a buffer " << q << " to encoder output port " << Logger::ENDL; } } // Enable burst mode if (m_burstModeEnabled) { if (mmal_port_parameter_set_boolean(m_camera->control, MMAL_PARAMETER_CAMERA_BURST_CAPTURE, 1) != MMAL_SUCCESS) { ErrorLog << "Error enabling burst mode" << Logger::ENDL; } InfoLog << "Enabled burst mode for still images" << Logger::ENDL; } InfoLog << "Initialized camera" << Logger::ENDL; }
/** * Create the encoder component, set up its ports * * @param state Pointer to state control struct * * @return 0 if failed, pointer to component if successful * */ static MMAL_COMPONENT_T *create_encoder_component(RASPISTILL_STATE *state) { MMAL_COMPONENT_T *encoder = 0; MMAL_PORT_T *encoder_input = NULL, *encoder_output = NULL; MMAL_STATUS_T status; MMAL_POOL_T *pool; status = mmal_component_create(MMAL_COMPONENT_DEFAULT_IMAGE_ENCODER, &encoder); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to create JPEG encoder component"); goto error; } if (!encoder->input_num || !encoder->output_num) { vcos_log_error("JPEG encoder doesn't have input/output ports"); goto error; } encoder_input = encoder->input[0]; encoder_output = encoder->output[0]; // We want same format on input and output mmal_format_copy(encoder_output->format, encoder_input->format); // Specify out output format encoder_output->format->encoding = state->encoding; encoder_output->buffer_size = encoder_output->buffer_size_recommended; if (encoder_output->buffer_size < encoder_output->buffer_size_min) encoder_output->buffer_size = encoder_output->buffer_size_min; encoder_output->buffer_num = encoder_output->buffer_num_recommended; if (encoder_output->buffer_num < encoder_output->buffer_num_min) encoder_output->buffer_num = encoder_output->buffer_num_min; // Commit the port changes to the output port status = mmal_port_format_commit(encoder_output); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set format on video encoder output port"); goto error; } // Set the JPEG quality level status = mmal_port_parameter_set_uint32(encoder_output, MMAL_PARAMETER_JPEG_Q_FACTOR, state->quality); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set JPEG quality"); goto error; } // Enable component status = mmal_component_enable(encoder); if (status) { vcos_log_error("Unable to enable video encoder component"); 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; if (state->verbose) fprintf(stderr, "Encoder component done\n"); return encoder; error: if (encoder) mmal_component_destroy(encoder); return 0; }
void start_all (void) { MMAL_STATUS_T status; MMAL_ES_FORMAT_T *format; int max, i; unsigned int video_width, video_height; // // get resolution // if(preview_mode == RES_16_9_STD) { video_width = 1920; video_height = 1080; } else if(preview_mode == RES_16_9_WIDE) { video_width = 1296; video_height = 730; } else { video_width = 1296; video_height = 976; } // // create camera // status = mmal_component_create(MMAL_COMPONENT_DEFAULT_CAMERA, &camera); if(status != MMAL_SUCCESS) error("Could not create camera"); status = mmal_port_enable(camera->control, camera_control_callback); if(status != MMAL_SUCCESS) error("Could not enable camera control port"); MMAL_PARAMETER_CAMERA_CONFIG_T cam_config = { {MMAL_PARAMETER_CAMERA_CONFIG, sizeof(cam_config)}, .max_stills_w = 2592, .max_stills_h = 1944, .stills_yuv422 = 0, .one_shot_stills = 1, .max_preview_video_w = video_width, .max_preview_video_h = video_height, .num_preview_video_frames = 3, .stills_capture_circular_buffer_height = 0, .fast_preview_resume = 0, .use_stc_timestamp = MMAL_PARAM_TIMESTAMP_MODE_RESET_STC }; mmal_port_parameter_set(camera->control, &cam_config.hdr); format = camera->output[0]->format; format->es->video.width = video_width; format->es->video.height = video_height; format->es->video.crop.x = 0; format->es->video.crop.y = 0; format->es->video.crop.width = video_width; format->es->video.crop.height = video_height; format->es->video.frame_rate.num = 0; format->es->video.frame_rate.den = 1; status = mmal_port_format_commit(camera->output[0]); if(status != MMAL_SUCCESS) error("Coult not set preview format"); format = camera->output[1]->format; format->encoding_variant = MMAL_ENCODING_I420; format->encoding = MMAL_ENCODING_OPAQUE; format->es->video.width = video_width; format->es->video.height = video_height; format->es->video.crop.x = 0; format->es->video.crop.y = 0; format->es->video.crop.width = video_width; format->es->video.crop.height = video_height; format->es->video.frame_rate.num = 25; format->es->video.frame_rate.den = 1; status = mmal_port_format_commit(camera->output[1]); if(status != MMAL_SUCCESS) error("Could not set video format"); if(camera->output[1]->buffer_num < 3) camera->output[1]->buffer_num = 3; format = camera->output[2]->format; format->encoding = MMAL_ENCODING_OPAQUE; format->es->video.width = 2592; format->es->video.height = 1944; format->es->video.crop.x = 0; format->es->video.crop.y = 0; format->es->video.crop.width = 2592; format->es->video.crop.height = 1944; format->es->video.frame_rate.num = 0; format->es->video.frame_rate.den = 1; status = mmal_port_format_commit(camera->output[2]); if(status != MMAL_SUCCESS) error("Could not set still format"); if(camera->output[2]->buffer_num < 3) camera->output[2]->buffer_num = 3; status = mmal_component_enable(camera); if(status != MMAL_SUCCESS) error("Could not enable camera"); // // create jpeg-encoder // status = mmal_component_create(MMAL_COMPONENT_DEFAULT_IMAGE_ENCODER, &jpegencoder); if(status != MMAL_SUCCESS && status != MMAL_ENOSYS) error("Could not create image encoder"); mmal_format_copy(jpegencoder->output[0]->format, jpegencoder->input[0]->format); jpegencoder->output[0]->format->encoding = MMAL_ENCODING_JPEG; jpegencoder->output[0]->buffer_size = jpegencoder->output[0]->buffer_size_recommended; if(jpegencoder->output[0]->buffer_size < jpegencoder->output[0]->buffer_size_min) jpegencoder->output[0]->buffer_size = jpegencoder->output[0]->buffer_size_min; jpegencoder->output[0]->buffer_num = jpegencoder->output[0]->buffer_num_recommended; if(jpegencoder->output[0]->buffer_num < jpegencoder->output[0]->buffer_num_min) jpegencoder->output[0]->buffer_num = jpegencoder->output[0]->buffer_num_min; status = mmal_port_format_commit(jpegencoder->output[0]); if(status != MMAL_SUCCESS) error("Could not set image format"); status = mmal_port_parameter_set_uint32(jpegencoder->output[0], MMAL_PARAMETER_JPEG_Q_FACTOR, quality); if(status != MMAL_SUCCESS) error("Could not set jpeg quality"); status = mmal_component_enable(jpegencoder); if(status != MMAL_SUCCESS) error("Could not enable image encoder"); pool_jpegencoder = mmal_port_pool_create(jpegencoder->output[0], jpegencoder->output[0]->buffer_num, jpegencoder->output[0]->buffer_size); if(!pool_jpegencoder) error("Could not create image buffer pool"); // // create second jpeg-encoder // status = mmal_component_create(MMAL_COMPONENT_DEFAULT_IMAGE_ENCODER, &jpegencoder2); if(status != MMAL_SUCCESS && status != MMAL_ENOSYS) error("Could not create image encoder 2"); mmal_format_copy(jpegencoder2->output[0]->format, jpegencoder2->input[0]->format); jpegencoder2->output[0]->format->encoding = MMAL_ENCODING_JPEG; jpegencoder2->output[0]->buffer_size = jpegencoder2->output[0]->buffer_size_recommended; if(jpegencoder2->output[0]->buffer_size < jpegencoder2->output[0]->buffer_size_min) jpegencoder2->output[0]->buffer_size = jpegencoder2->output[0]->buffer_size_min; jpegencoder2->output[0]->buffer_num = jpegencoder2->output[0]->buffer_num_recommended; if(jpegencoder2->output[0]->buffer_num < jpegencoder2->output[0]->buffer_num_min) jpegencoder2->output[0]->buffer_num = jpegencoder2->output[0]->buffer_num_min; status = mmal_port_format_commit(jpegencoder2->output[0]); if(status != MMAL_SUCCESS) error("Could not set image format 2"); status = mmal_port_parameter_set_uint32(jpegencoder2->output[0], MMAL_PARAMETER_JPEG_Q_FACTOR, 85); if(status != MMAL_SUCCESS) error("Could not set jpeg quality 2"); status = mmal_component_enable(jpegencoder2); if(status != MMAL_SUCCESS) error("Could not enable image encoder 2"); pool_jpegencoder2 = mmal_port_pool_create(jpegencoder2->output[0], jpegencoder2->output[0]->buffer_num, jpegencoder2->output[0]->buffer_size); if(!pool_jpegencoder2) error("Could not create image buffer pool 2"); // // create h264-encoder // status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_ENCODER, &h264encoder); if(status != MMAL_SUCCESS && status != MMAL_ENOSYS) error("Could not create video encoder"); mmal_format_copy(h264encoder->output[0]->format, h264encoder->input[0]->format); h264encoder->output[0]->format->encoding = MMAL_ENCODING_H264; h264encoder->output[0]->format->bitrate = 17000000; h264encoder->output[0]->buffer_size = h264encoder->output[0]->buffer_size_recommended; if(h264encoder->output[0]->buffer_size < h264encoder->output[0]->buffer_size_min) h264encoder->output[0]->buffer_size = h264encoder->output[0]->buffer_size_min; h264encoder->output[0]->buffer_num = h264encoder->output[0]->buffer_num_recommended; if(h264encoder->output[0]->buffer_num < h264encoder->output[0]->buffer_num_min) h264encoder->output[0]->buffer_num = h264encoder->output[0]->buffer_num_min; h264encoder->output[0]->format->es->video.frame_rate.num = 0; h264encoder->output[0]->format->es->video.frame_rate.den = 1; status = mmal_port_format_commit(h264encoder->output[0]); if(status != MMAL_SUCCESS) error("Could not set video format"); MMAL_PARAMETER_UINT32_T param2 = {{ MMAL_PARAMETER_VIDEO_ENCODE_INITIAL_QUANT, sizeof(param2)}, 25}; status = mmal_port_parameter_set(h264encoder->output[0], ¶m2.hdr); if(status != MMAL_SUCCESS) error("Could not set video quantisation"); MMAL_PARAMETER_UINT32_T param3 = {{ MMAL_PARAMETER_VIDEO_ENCODE_QP_P, sizeof(param3)}, 31}; status = mmal_port_parameter_set(h264encoder->output[0], ¶m3.hdr); if(status != MMAL_SUCCESS) error("Could not set video quantisation"); MMAL_PARAMETER_VIDEO_PROFILE_T param4; param4.hdr.id = MMAL_PARAMETER_PROFILE; param4.hdr.size = sizeof(param4); param4.profile[0].profile = MMAL_VIDEO_PROFILE_H264_HIGH; param4.profile[0].level = MMAL_VIDEO_LEVEL_H264_4; status = mmal_port_parameter_set(h264encoder->output[0], ¶m4.hdr); if(status != MMAL_SUCCESS) error("Could not set video port format"); status = mmal_port_parameter_set_boolean(h264encoder->input[0], MMAL_PARAMETER_VIDEO_IMMUTABLE_INPUT, 1); if(status != MMAL_SUCCESS) error("Could not set immutable flag"); status = mmal_port_parameter_set_boolean(h264encoder->output[0], MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER, 0); if(status != MMAL_SUCCESS) error("Could not set inline flag"); // // create image-resizer // status = mmal_component_create("vc.ril.resize", &resizer); if(status != MMAL_SUCCESS && status != MMAL_ENOSYS) error("Could not create image resizer"); format = resizer->output[0]->format; format->es->video.width = (preview_mode==RES_4_3) ? width_pic : width; format->es->video.height = (preview_mode==RES_4_3) ? height_pic : height; format->es->video.crop.x = 0; format->es->video.crop.y = 0; format->es->video.crop.width = (preview_mode==RES_4_3) ? width_pic : width; format->es->video.crop.height = (preview_mode==RES_4_3) ? height_pic : height; format->es->video.frame_rate.num = 30; format->es->video.frame_rate.den = 1; status = mmal_port_format_commit(resizer->output[0]); if(status != MMAL_SUCCESS) error("Could not set image resizer output"); status = mmal_component_enable(resizer); if(status != MMAL_SUCCESS) error("Could not enable image resizer"); // // connect // status = mmal_connection_create(&con_cam_res, camera->output[0], resizer->input[0], MMAL_CONNECTION_FLAG_TUNNELLING | MMAL_CONNECTION_FLAG_ALLOCATION_ON_INPUT); if(status != MMAL_SUCCESS) error("Could not create connection camera -> resizer"); status = mmal_connection_enable(con_cam_res); if(status != MMAL_SUCCESS) error("Could not enable connection camera -> resizer"); status = mmal_connection_create(&con_res_jpeg, resizer->output[0], jpegencoder->input[0], MMAL_CONNECTION_FLAG_TUNNELLING | MMAL_CONNECTION_FLAG_ALLOCATION_ON_INPUT); if(status != MMAL_SUCCESS) error("Could not create connection resizer -> encoder"); status = mmal_connection_enable(con_res_jpeg); if(status != MMAL_SUCCESS) error("Could not enable connection resizer -> encoder"); status = mmal_port_enable(jpegencoder->output[0], jpegencoder_buffer_callback); if(status != MMAL_SUCCESS) error("Could not enable jpeg port"); max = mmal_queue_length(pool_jpegencoder->queue); for(i=0;i<max;i++) { MMAL_BUFFER_HEADER_T *jpegbuffer = mmal_queue_get(pool_jpegencoder->queue); if(!jpegbuffer) error("Could not create jpeg buffer header"); status = mmal_port_send_buffer(jpegencoder->output[0], jpegbuffer); if(status != MMAL_SUCCESS) error("Could not send buffers to jpeg port"); } status = mmal_connection_create(&con_cam_jpeg, camera->output[2], jpegencoder2->input[0], MMAL_CONNECTION_FLAG_TUNNELLING | MMAL_CONNECTION_FLAG_ALLOCATION_ON_INPUT); if(status != MMAL_SUCCESS) error("Could not create connection camera -> encoder"); status = mmal_connection_enable(con_cam_jpeg); if(status != MMAL_SUCCESS) error("Could not enable connection camera -> encoder"); status = mmal_port_enable(jpegencoder2->output[0], jpegencoder2_buffer_callback); if(status != MMAL_SUCCESS) error("Could not enable jpeg port 2"); max = mmal_queue_length(pool_jpegencoder2->queue); for(i=0;i<max;i++) { MMAL_BUFFER_HEADER_T *jpegbuffer2 = mmal_queue_get(pool_jpegencoder2->queue); if(!jpegbuffer2) error("Could not create jpeg buffer header 2"); status = mmal_port_send_buffer(jpegencoder2->output[0], jpegbuffer2); if(status != MMAL_SUCCESS) error("Could not send buffers to jpeg port 2"); } }