bool CMMALRenderer::init_vout(MMAL_ES_FORMAT_T *format) { MMAL_STATUS_T status; CLog::Log(LOGDEBUG, "%s::%s", CLASSNAME, __func__); /* 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_format_full_copy(m_vout_input->format, format); 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; } if (m_format == RENDER_FMT_YUV420P) { m_vout_input_pool = mmal_pool_create(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; }
/** Connected output port buffer callback */ static void mmal_port_connected_output_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) { MMAL_PORT_T* connected_port = port->priv->core->connected_port; MMAL_STATUS_T status; LOG_TRACE("buffer %p from connected output port %p: data %p, alloc_size %u, length %u", buffer, port, buffer->data, buffer->alloc_size, buffer->length); if (buffer->cmd) { MMAL_EVENT_FORMAT_CHANGED_T *event = mmal_event_format_changed_get(buffer); /* Handle format changed events */ if (event) { /* Apply the change */ status = mmal_format_full_copy(port->format, event->format); if (status == MMAL_SUCCESS) status = mmal_port_format_commit(port); if (status != MMAL_SUCCESS) LOG_ERROR("format commit failed on port %s (%i)", port->name, status); /* Forward to the connected port */ if (status == MMAL_SUCCESS) status = mmal_port_send_buffer(connected_port, buffer); if (status != MMAL_SUCCESS) { mmal_event_error_send(port->component, status); mmal_buffer_header_release(buffer); } return; /* Event handled */ } /* FIXME Release other event buffers for now, until we can deal with shared memory issues */ mmal_buffer_header_release(buffer); } else { if (port->is_enabled) { /* Forward data buffers to the connected input port */ status = mmal_port_send_buffer(connected_port, buffer); if (status != MMAL_SUCCESS) { LOG_ERROR("%s could not send buffer on port %s (%s)", port->name, connected_port->name, mmal_status_to_string(status)); mmal_buffer_header_release(buffer); } } else { /* This port is disabled. Buffer will be a flushed buffer, so * return to the pool rather than delivering it. */ mmal_buffer_header_release(buffer); } } }
static void output_port_cb(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer) { decoder_t *dec = (decoder_t *)port->userdata; decoder_sys_t *sys = dec->p_sys; picture_t *picture; MMAL_EVENT_FORMAT_CHANGED_T *fmt; MMAL_ES_FORMAT_T *format; if (buffer->cmd == 0) { if (buffer->length > 0) { mmal_queue_put(sys->decoded_pictures, buffer); } else { picture = (picture_t *)buffer->user_data; picture_Release(picture); if (sys->output_pool) { buffer->user_data = NULL; buffer->alloc_size = 0; buffer->data = NULL; mmal_buffer_header_release(buffer); } } atomic_fetch_sub(&sys->output_in_transit, 1); vlc_sem_post(&sys->sem); } else if (buffer->cmd == MMAL_EVENT_FORMAT_CHANGED) { fmt = mmal_event_format_changed_get(buffer); format = mmal_format_alloc(); mmal_format_full_copy(format, fmt->format); if (sys->opaque) format->encoding = MMAL_ENCODING_OPAQUE; sys->output_format = format; mmal_buffer_header_release(buffer); } else { mmal_buffer_header_release(buffer); } }
/** Set format on a port */ static MMAL_STATUS_T splitter_port_format_commit(MMAL_PORT_T *port) { MMAL_COMPONENT_T *component = port->component; MMAL_STATUS_T status; unsigned int i; /* Sanity check */ if (port->type == MMAL_PORT_TYPE_OUTPUT) { LOG_ERROR("output port is read-only"); return MMAL_EINVAL; } /* Commit the format on all output ports */ for (i = 0; i < component->output_num; i++) { status = mmal_format_full_copy(component->output[i]->format, port->format); if (status != MMAL_SUCCESS) return status; } return MMAL_SUCCESS; }
/** * 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; }
static int Open(filter_t *filter) { int32_t frame_duration = filter->fmt_in.video.i_frame_rate != 0 ? (int64_t)1000000 * filter->fmt_in.video.i_frame_rate_base / filter->fmt_in.video.i_frame_rate : 0; MMAL_PARAMETER_IMAGEFX_PARAMETERS_T imfx_param = { { MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS, sizeof(imfx_param) }, MMAL_PARAM_IMAGEFX_DEINTERLACE_ADV, 2, { 3, frame_duration } }; int ret = VLC_SUCCESS; MMAL_STATUS_T status; filter_sys_t *sys; msg_Dbg(filter, "Try to open mmal_deinterlace filter. frame_duration: %d!", frame_duration); if (filter->fmt_in.video.i_chroma != VLC_CODEC_MMAL_OPAQUE) return VLC_EGENERIC; if (filter->fmt_out.video.i_chroma != VLC_CODEC_MMAL_OPAQUE) return VLC_EGENERIC; sys = calloc(1, sizeof(filter_sys_t)); if (!sys) return VLC_ENOMEM; filter->p_sys = sys; bcm_host_init(); status = mmal_component_create(MMAL_COMPONENT_DEFAULT_DEINTERLACE, &sys->component); if (status != MMAL_SUCCESS) { msg_Err(filter, "Failed to create MMAL component %s (status=%"PRIx32" %s)", MMAL_COMPONENT_DEFAULT_DEINTERLACE, status, mmal_status_to_string(status)); ret = VLC_EGENERIC; goto out; } status = mmal_port_parameter_set(sys->component->output[0], &imfx_param.hdr); if (status != MMAL_SUCCESS) { msg_Err(filter, "Failed to configure MMAL component %s (status=%"PRIx32" %s)", MMAL_COMPONENT_DEFAULT_DEINTERLACE, status, mmal_status_to_string(status)); ret = VLC_EGENERIC; goto out; } sys->component->control->userdata = (struct MMAL_PORT_USERDATA_T *)filter; status = mmal_port_enable(sys->component->control, control_port_cb); if (status != MMAL_SUCCESS) { msg_Err(filter, "Failed to enable control port %s (status=%"PRIx32" %s)", sys->component->control->name, status, mmal_status_to_string(status)); ret = VLC_EGENERIC; goto out; } sys->input = sys->component->input[0]; sys->input->userdata = (struct MMAL_PORT_USERDATA_T *)filter; if (filter->fmt_in.i_codec == VLC_CODEC_MMAL_OPAQUE) sys->input->format->encoding = MMAL_ENCODING_OPAQUE; sys->input->format->es->video.width = filter->fmt_in.video.i_width; sys->input->format->es->video.height = filter->fmt_in.video.i_height; sys->input->format->es->video.crop.x = 0; sys->input->format->es->video.crop.y = 0; sys->input->format->es->video.crop.width = filter->fmt_in.video.i_width; sys->input->format->es->video.crop.height = filter->fmt_in.video.i_height; sys->input->format->es->video.par.num = filter->fmt_in.video.i_sar_num; sys->input->format->es->video.par.den = filter->fmt_in.video.i_sar_den; es_format_Copy(&filter->fmt_out, &filter->fmt_in); filter->fmt_out.video.i_frame_rate *= 2; status = mmal_port_format_commit(sys->input); if (status != MMAL_SUCCESS) { msg_Err(filter, "Failed to commit format for input port %s (status=%"PRIx32" %s)", sys->input->name, status, mmal_status_to_string(status)); ret = VLC_EGENERIC; goto out; } sys->input->buffer_size = sys->input->buffer_size_recommended; sys->input->buffer_num = sys->input->buffer_num_recommended; if (filter->fmt_in.i_codec == VLC_CODEC_MMAL_OPAQUE) { MMAL_PARAMETER_BOOLEAN_T zero_copy = { { MMAL_PARAMETER_ZERO_COPY, sizeof(MMAL_PARAMETER_BOOLEAN_T) }, 1 }; status = mmal_port_parameter_set(sys->input, &zero_copy.hdr); if (status != MMAL_SUCCESS) { msg_Err(filter, "Failed to set zero copy on port %s (status=%"PRIx32" %s)", sys->input->name, status, mmal_status_to_string(status)); goto out; } } status = mmal_port_enable(sys->input, input_port_cb); if (status != MMAL_SUCCESS) { msg_Err(filter, "Failed to enable input port %s (status=%"PRIx32" %s)", sys->input->name, status, mmal_status_to_string(status)); ret = VLC_EGENERIC; goto out; } sys->output = sys->component->output[0]; sys->output->userdata = (struct MMAL_PORT_USERDATA_T *)filter; mmal_format_full_copy(sys->output->format, sys->input->format); status = mmal_port_format_commit(sys->output); if (status != MMAL_SUCCESS) { msg_Err(filter, "Failed to commit format for output port %s (status=%"PRIx32" %s)", sys->input->name, status, mmal_status_to_string(status)); ret = VLC_EGENERIC; goto out; } sys->output->buffer_num = 3; if (filter->fmt_in.i_codec == VLC_CODEC_MMAL_OPAQUE) { MMAL_PARAMETER_BOOLEAN_T zero_copy = { { MMAL_PARAMETER_ZERO_COPY, sizeof(MMAL_PARAMETER_BOOLEAN_T) }, 1 }; status = mmal_port_parameter_set(sys->output, &zero_copy.hdr); if (status != MMAL_SUCCESS) { msg_Err(filter, "Failed to set zero copy on port %s (status=%"PRIx32" %s)", sys->output->name, status, mmal_status_to_string(status)); goto out; } } status = mmal_port_enable(sys->output, output_port_cb); if (status != MMAL_SUCCESS) { msg_Err(filter, "Failed to enable output port %s (status=%"PRIx32" %s)", sys->output->name, status, mmal_status_to_string(status)); ret = VLC_EGENERIC; goto out; } status = mmal_component_enable(sys->component); if (status != MMAL_SUCCESS) { msg_Err(filter, "Failed to enable component %s (status=%"PRIx32" %s)", sys->component->name, status, mmal_status_to_string(status)); ret = VLC_EGENERIC; goto out; } sys->filtered_pictures = mmal_queue_create(); filter->pf_video_filter = deinterlace; filter->pf_video_flush = flush; vlc_mutex_init_recursive(&sys->mutex); vlc_mutex_init(&sys->buffer_cond_mutex); vlc_cond_init(&sys->buffer_cond); out: if (ret != VLC_SUCCESS) Close(filter); return ret; }
/** * Create the camera component, set up its ports * * @param state Pointer to state control struct. camera_component member set to the created camera_component if successfull. * * @return MMAL_SUCCESS if all OK, something else otherwise * */ static MMAL_STATUS_T create_camera_component(RASPISTILL_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) { 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]; // 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->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 = 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 = FULL_RES_PREVIEW_FRAME_RATE_NUM; format->es->video.frame_rate.den = FULL_RES_PREVIEW_FRAME_RATE_DEN; } else { // use our normal preview mode - probably 1080p30 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 != 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; // Set our stills format on the stills (for encoder) port format->encoding = MMAL_ENCODING_OPAQUE; 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; status = mmal_port_format_commit(still_port); if (status != MMAL_SUCCESS) { vcos_log_error("camera still format couldn't be set"); goto error; } /* 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 != MMAL_SUCCESS) { vcos_log_error("camera component couldn't be enabled"); goto error; } state->camera_component = camera; if (state->verbose) fprintf(stderr, "Camera component done\n"); return status; error: if (camera) mmal_component_destroy(camera); return status; }
/** * 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; }
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 MmalStillCamera::createCameraComponent() { 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; try { status = mmal_component_create(MMAL_COMPONENT_DEFAULT_CAMERA, &camera); if (status != MMAL_SUCCESS) { throw Exception("Failed to create camera component"); } if (camera->output_num == 0) { status = MMAL_ENOSYS; throw Exception("Camera doesn't have output ports"); } 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, CameraControlCallback); if (status != MMAL_SUCCESS) { throw Exception("Unable to enable control port"); } // Populate the camera configuration struct MMAL_PARAMETER_CAMERA_CONFIG_T cameraConfig; cameraConfig.hdr.id = MMAL_PARAMETER_CAMERA_CONFIG; cameraConfig.hdr.size = sizeof(cameraConfig); cameraConfig.max_stills_w = m_imageWidth; cameraConfig.max_stills_h = m_imageHeight; cameraConfig.stills_yuv422 = 0; cameraConfig.one_shot_stills = 1; cameraConfig.max_preview_video_w = VCOS_ALIGN_UP(FULL_FOV_PREVIEW_4x3_X, 32); cameraConfig.max_preview_video_h = VCOS_ALIGN_UP(FULL_FOV_PREVIEW_4x3_Y, 16); cameraConfig.num_preview_video_frames = 3; cameraConfig.stills_capture_circular_buffer_height = 0; cameraConfig.fast_preview_resume = 0; cameraConfig.use_stc_timestamp = MMAL_PARAM_TIMESTAMP_MODE_RESET_STC; if (mmal_port_parameter_set(camera->control, &cameraConfig.hdr) != MMAL_SUCCESS) { throw Exception("Error calling mmal_port_parameter_set()"); } format = preview_port->format; format->encoding = MMAL_ENCODING_OPAQUE; format->encoding_variant = MMAL_ENCODING_I420; format->es->video.width = VCOS_ALIGN_UP(FULL_FOV_PREVIEW_4x3_X, 32); format->es->video.height = VCOS_ALIGN_UP(FULL_FOV_PREVIEW_4x3_Y, 16); format->es->video.crop.x = 0; format->es->video.crop.y = 0; format->es->video.crop.width = FULL_FOV_PREVIEW_4x3_X; format->es->video.crop.height = FULL_FOV_PREVIEW_4x3_Y; format->es->video.frame_rate.num = FULL_RES_PREVIEW_FRAME_RATE_NUM; format->es->video.frame_rate.den = FULL_RES_PREVIEW_FRAME_RATE_DEN; status = mmal_port_format_commit(preview_port); if (status != MMAL_SUCCESS) { throw Exception("Failure to setup camera preview port"); } // We must also setup the video port even though this is an image acquisition mmal_format_full_copy(video_port->format, format); status = mmal_port_format_commit(video_port); if (status != MMAL_SUCCESS) { throw Exception("Failure to setup camera video port"); } // Make sure we have enough video buffers if (video_port->buffer_num < VIDEO_OUTPUT_BUFFERS_NUM) { video_port->buffer_num = VIDEO_OUTPUT_BUFFERS_NUM; } // Use the video format for images as well format = still_port->format; // Set our stills format on the stills (for encoder) port format->encoding = MMAL_ENCODING_BGR24; format->encoding_variant = MMAL_ENCODING_BGR24; format->es->video.width = VCOS_ALIGN_UP(m_imageWidth, 32); format->es->video.height = VCOS_ALIGN_UP(m_imageHeight, 16); format->es->video.crop.x = 0; format->es->video.crop.y = 0; format->es->video.crop.width = m_imageWidth; format->es->video.crop.height = m_imageHeight; format->es->video.frame_rate.num = STILLS_FRAME_RATE_NUM; format->es->video.frame_rate.den = STILLS_FRAME_RATE_DEN; status = mmal_port_format_commit(still_port); if (status != MMAL_SUCCESS) { throw Exception("Failure to setup camera image port"); } // Verify number of buffers if (still_port->buffer_num < VIDEO_OUTPUT_BUFFERS_NUM) { still_port->buffer_num = VIDEO_OUTPUT_BUFFERS_NUM; } // Flip the image MMAL_PARAMETER_MIRROR_T mirror = {{MMAL_PARAMETER_MIRROR, sizeof(MMAL_PARAMETER_MIRROR_T)}, MMAL_PARAM_MIRROR_NONE}; mirror.value = MMAL_PARAM_MIRROR_BOTH; mmal_port_parameter_set(preview_port, &mirror.hdr); mmal_port_parameter_set(video_port, &mirror.hdr); mmal_port_parameter_set(still_port, &mirror.hdr); // Enable component status = mmal_component_enable(camera); if (status != MMAL_SUCCESS) { throw Exception("camera component couldn't be enabled"); } } catch (...) { if (camera != NULL) { mmal_component_destroy(camera); } throw; } m_camera = camera; m_previewPort = preview_port; m_videoPort = video_port; m_stillPort = still_port; }