MMAL_STATUS_T nullsink_preview(RASPIPREVIEW_PARAMETERS *state) { MMAL_COMPONENT_T *preview = 0; MMAL_PORT_T *preview_port = NULL; MMAL_STATUS_T status; status = mmal_component_create("vc.null_sink", &preview); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to create null sink component"); goto error; } status = mmal_component_enable(preview); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to enable preview/null sink component (%u)", status); goto error; } state->preview_component = preview; return status; error: if (preview) mmal_component_destroy(preview); return status; }
void MmalStillCamera::createPreview() { MMAL_COMPONENT_T * preview = NULL; MMAL_STATUS_T status; try { status = mmal_component_create("vc.null_sink", &preview); //status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_RENDERER, &preview); if (status != MMAL_SUCCESS) { throw Exception("Error creating preview sink"); } status = mmal_component_enable(preview); if (status != MMAL_SUCCESS) { throw Exception("Error enabling preview"); } } catch (...) { if (preview != NULL) { mmal_component_destroy(preview); } throw; } m_preview = preview; }
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; }
/* A h264 encoder should have a non NULL src_port argument if the input to | the encoder will be callback connected to the src_port. If it will be | tunnel connected, src_port should be NULL. */ boolean h264_encoder_create(char *name, CameraObject *encoder, MMAL_PORT_T *src_port) { MMAL_PORT_T *in_port, *out_port; MMAL_STATUS_T status; char *msg = "mmal_component_create"; encoder->name = name; if ((status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_ENCODER, &encoder->component)) == MMAL_SUCCESS) { in_port = encoder->component->input[0]; out_port = encoder->component->output[0]; if (src_port) { /* The h264 encoder input will be fed buffers in an ARM side | callback, so ensure port formats will match. */ mmal_format_copy(in_port->format, src_port->format); in_port->buffer_size = src_port->buffer_size; msg = "mmal_port_format_commit(in_port)"; status = mmal_port_format_commit(in_port); } if (status == MMAL_SUCCESS) { out_port->buffer_num = MAX(out_port->buffer_num_recommended, out_port->buffer_num_min); out_port->buffer_size = MAX(out_port->buffer_size_recommended, out_port->buffer_size_min); mmal_format_copy(out_port->format, in_port->format); out_port->format->encoding = MMAL_ENCODING_H264; out_port->format->bitrate = pikrellcam.camera_adjust.video_bitrate; out_port->format->es->video.frame_rate.num = 0; /* why? */ out_port->format->es->video.frame_rate.den = 1; /* Enable inline motion vectors */ mmal_port_parameter_set_boolean(out_port, MMAL_PARAMETER_VIDEO_ENCODE_INLINE_VECTORS, MMAL_TRUE); msg = "mmal_port_format_commit"; if ((status = mmal_port_format_commit(out_port)) == MMAL_SUCCESS) { msg = "mmal_component_enable"; status = mmal_component_enable(encoder->component); } } /* Will be component enabled/disabled on demand */ } return component_create_check(encoder, status, msg); }
/* A jpeg encoder should have a non NULL src_port argument if the input to | the encoder will be callback connected to the src_port. If it will be | tunnel connected, this src_port should be NULL. */ boolean jpeg_encoder_create(char *name, CameraObject *encoder, MMAL_PORT_T *src_port, int quality) { MMAL_PORT_T *in_port, *out_port; MMAL_STATUS_T status; char *msg = "mmal_component_create"; encoder->name = name; status = mmal_component_create(MMAL_COMPONENT_DEFAULT_IMAGE_ENCODER, &encoder->component); if (status == MMAL_SUCCESS) { in_port = encoder->component->input[0]; out_port = encoder->component->output[0]; if (src_port) { /* The jpeg encoder input will be fed buffers in an ARM side | callback, so ensure port formats will match. */ mmal_format_copy(in_port->format, src_port->format); in_port->buffer_size = src_port->buffer_size; msg = "mmal_port_format_commit(in_port)"; status = mmal_port_format_commit(in_port); } if (status == MMAL_SUCCESS) { out_port->buffer_num = MAX(out_port->buffer_num_recommended, out_port->buffer_num_min); out_port->buffer_size = MAX(out_port->buffer_size_recommended, out_port->buffer_size_min); mmal_format_copy(out_port->format, in_port->format); out_port->format->encoding = MMAL_ENCODING_JPEG; msg = "mmal_port_format_commit(out_port)"; if ((status = mmal_port_format_commit(out_port)) == MMAL_SUCCESS) { mmal_port_parameter_set_uint32(out_port, MMAL_PARAMETER_JPEG_Q_FACTOR, quality); msg = "mmal_component_enable"; status = mmal_component_enable(encoder->component); } } } return component_create_check(encoder, status, msg); }
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; }
MMAL_STATUS_T raspipreview_create( RASPIPREVIEW_PARAMETERS *state ) { MMAL_COMPONENT_T *preview = 0; MMAL_PORT_T *preview_port = NULL; MMAL_STATUS_T status; // No preview required, so create a null sink component to take its place status = mmal_component_create("vc.null_sink", &preview); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to create null sink component"); goto error; } /* Enable component */ status = mmal_component_enable(preview); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to enable preview/null sink component (%u)", status); goto error; } state->preview_component = preview; return status; error: if (preview) mmal_component_destroy(preview); 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_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; }
/** * 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; }
MMAL_COMPONENT_T* CCamera::createCameraComponentAndSetupPorts() { 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 camera component status = mmal_component_create(MMAL_COMPONENT_DEFAULT_CAMERA, &camera); if (status != MMAL_SUCCESS) { printf("Failed to create camera component\n"); return NULL; } //check we have output ports if (!camera->output_num) { printf("Camera doesn't have output ports"); mmal_component_destroy(camera); return NULL; } //get the 3 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) { printf("Unable to enable control port : error %d", status); mmal_component_destroy(camera); return NULL; } // 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 = Width; cam_config.max_stills_h = Height; cam_config.stills_yuv422 = 0; cam_config.one_shot_stills = 0; cam_config.max_preview_video_w = Width; cam_config.max_preview_video_h = 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_RESET_STC; mmal_port_parameter_set(camera->control, &cam_config.hdr); } // setup preview port format - QUESTION: Needed if we aren't using preview? format = preview_port->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 = FrameRate; format->es->video.frame_rate.den = 1; status = mmal_port_format_commit(preview_port); if (status != MMAL_SUCCESS) { printf("Couldn't set preview port format : error %d", status); mmal_component_destroy(camera); return NULL; } //setup video port format format = video_port->format; 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 = 1; status = mmal_port_format_commit(video_port); if (status != MMAL_SUCCESS) { printf("Couldn't set video port format : error %d", status); mmal_component_destroy(camera); return NULL; } //setup still port format format = still_port->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(still_port); if (status != MMAL_SUCCESS) { printf("Couldn't set still port format : error %d", status); mmal_component_destroy(camera); return NULL; } //apply all camera parameters raspicamcontrol_set_all_parameters(camera, &CameraParameters); //enable the camera status = mmal_component_enable(camera); if (status != MMAL_SUCCESS) { printf("Couldn't enable camera\n"); mmal_component_destroy(camera); return NULL; } return camera; }
void MmalVideoCamera::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"); } MMAL_CHECK(mmal_port_parameter_set_uint32(camera->control, MMAL_PARAMETER_CAMERA_CUSTOM_SENSOR_CONFIG, MMAL_VIDEO_SENSOR_MODE)); preview_port = camera->output[MMAL_CAMERA_PREVIEW_PORT]; video_port = camera->output[MMAL_CAMERA_VIDEO_PORT]; still_port = camera->output[MMAL_CAMERA_CAPTURE_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 = 0; cameraConfig.max_preview_video_w = m_imagePreviewWidth; cameraConfig.max_preview_video_h = m_imagePreviewHeight; 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()"); } // // Setup the video port // format = video_port->format; 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 = m_frameRate; format->es->video.frame_rate.den = FULL_RES_VIDEO_FRAME_RATE_DEN; 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; } // 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"); } //int iso = 100; //MMAL_CHECK(mmal_port_parameter_set_uint32(camera->control, MMAL_PARAMETER_ISO, iso)); // MMAL_PARAM_EXPOSUREMODE_OFF //MMAL_PARAMETER_EXPOSUREMODE_T exp_mode = {{MMAL_PARAMETER_EXPOSURE_MODE, sizeof(exp_mode)}, MMAL_PARAM_EXPOSUREMODE_AUTO}; //MMAL_CHECK(mmal_port_parameter_set(camera->control, &exp_mode.hdr)); /* // AWB MODE { std::cout << "Disabling auto white balancing" << std::endl; MMAL_PARAMETER_AWBMODE_T param = {{MMAL_PARAMETER_AWB_MODE,sizeof(param)}, MMAL_PARAM_AWBMODE_OFF}; mmal_port_parameter_set(camera->control, ¶m.hdr); } // AWB GAIN { real redGain = 0.2; real blueGain = 1.0; std::cout << "Setting color gain, r=" << redGain << ", b=" << blueGain << std::endl; MMAL_PARAMETER_AWB_GAINS_T param = {{MMAL_PARAMETER_CUSTOM_AWB_GAINS,sizeof(param)}, {0,0}, {0,0}}; param.r_gain.num = (unsigned int)(redGain * 65536); param.b_gain.num = (unsigned int)(blueGain * 65536); param.r_gain.den = param.b_gain.den = 65536; mmal_port_parameter_set(camera->control, ¶m.hdr); } */ std::cout << "Camera Enabled..." << std::endl; } catch (...) { if (camera != NULL) { mmal_component_destroy(camera); } throw; } m_camera = camera; m_videoPort = video_port; m_stillPort = still_port; m_previewPort = preview_port; }
/** * 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; }
bool CMMALVideo::CreateDeinterlace(EINTERLACEMETHOD interlace_method) { MMAL_STATUS_T status; if (g_advancedSettings.CanLogComponent(LOGVIDEO)) CLog::Log(LOGDEBUG, "%s::%s method:%d", CLASSNAME, __func__, interlace_method); assert(!m_deint); assert(m_dec_output == m_dec->output[0]); status = mmal_port_disable(m_dec_output); if (status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to disable decoder output port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } /* Create deinterlace filter */ status = mmal_component_create("vc.ril.image_fx", &m_deint); if (status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to create deinterlace component (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } MMAL_PARAMETER_IMAGEFX_PARAMETERS_T imfx_param = {{MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS, sizeof(imfx_param)}, interlace_method == VS_INTERLACEMETHOD_MMAL_ADVANCED || interlace_method == VS_INTERLACEMETHOD_MMAL_ADVANCED_HALF ? MMAL_PARAM_IMAGEFX_DEINTERLACE_ADV : MMAL_PARAM_IMAGEFX_DEINTERLACE_FAST, 3, {3, 0, interlace_method == VS_INTERLACEMETHOD_MMAL_ADVANCED_HALF || interlace_method == VS_INTERLACEMETHOD_MMAL_BOB_HALF }}; status = mmal_port_parameter_set(m_deint->output[0], &imfx_param.hdr); if (status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to set deinterlace parameters (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } MMAL_PORT_T *m_deint_input = m_deint->input[0]; m_deint_input->userdata = (struct MMAL_PORT_USERDATA_T *)this; // Now connect the decoder output port to deinterlace input port status = mmal_connection_create(&m_deint_connection, m_dec->output[0], m_deint->input[0], MMAL_CONNECTION_FLAG_TUNNELLING | MMAL_CONNECTION_FLAG_ALLOCATION_ON_INPUT); if (status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to connect deinterlacer component %s (status=%x %s)", CLASSNAME, __func__, m_deint->name, status, mmal_status_to_string(status)); return false; } status = mmal_connection_enable(m_deint_connection); if (status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to enable connection %s (status=%x %s)", CLASSNAME, __func__, m_deint->name, status, mmal_status_to_string(status)); return false; } mmal_format_copy(m_deint->output[0]->format, m_es_format); status = mmal_port_format_commit(m_deint->output[0]); if (status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to commit deint output format (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } status = mmal_component_enable(m_deint); if (status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to enable deinterlacer component %s (status=%x %s)", CLASSNAME, __func__, m_deint->name, status, mmal_status_to_string(status)); return false; } m_deint->output[0]->buffer_size = m_deint->output[0]->buffer_size_min; m_deint->output[0]->buffer_num = m_deint->output[0]->buffer_num_recommended; m_deint->output[0]->userdata = (struct MMAL_PORT_USERDATA_T *)this; status = mmal_port_enable(m_deint->output[0], dec_output_port_cb_static); if (status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to enable decoder output port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } m_dec_output = m_deint->output[0]; m_interlace_method = interlace_method; return true; }
static picture_pool_t *vd_pool(vout_display_t *vd, unsigned count) { vout_display_sys_t *sys = vd->sys; picture_resource_t picture_res; picture_pool_configuration_t picture_pool_cfg; video_format_t fmt = vd->fmt; MMAL_STATUS_T status; unsigned i; if (sys->picture_pool) { if (sys->num_buffers < count) msg_Warn(vd, "Picture pool with %u pictures requested, but we already have one with %u pictures", count, sys->num_buffers); goto out; } if (sys->opaque) { if (count <= NUM_ACTUAL_OPAQUE_BUFFERS) count = NUM_ACTUAL_OPAQUE_BUFFERS; } if (count < sys->input->buffer_num_recommended) count = sys->input->buffer_num_recommended; #ifndef NDEBUG msg_Dbg(vd, "Creating picture pool with %u pictures", count); #endif sys->input->buffer_num = count; status = mmal_port_enable(sys->input, input_port_cb); if (status != MMAL_SUCCESS) { msg_Err(vd, "Failed to enable input port %s (status=%"PRIx32" %s)", sys->input->name, status, mmal_status_to_string(status)); goto out; } status = mmal_component_enable(sys->component); if (status != MMAL_SUCCESS) { msg_Err(vd, "Failed to enable component %s (status=%"PRIx32" %s)", sys->component->name, status, mmal_status_to_string(status)); goto out; } sys->num_buffers = count; sys->pool = mmal_pool_create(sys->num_buffers, sys->input->buffer_size); if (!sys->pool) { msg_Err(vd, "Failed to create MMAL pool for %u buffers of size %"PRIu32, count, sys->input->buffer_size); goto out; } memset(&picture_res, 0, sizeof(picture_resource_t)); sys->pictures = calloc(sys->num_buffers, sizeof(picture_t *)); for (i = 0; i < sys->num_buffers; ++i) { picture_res.p_sys = calloc(1, sizeof(picture_sys_t)); picture_res.p_sys->owner = (vlc_object_t *)vd; picture_res.p_sys->queue = sys->pool->queue; sys->pictures[i] = picture_NewFromResource(&fmt, &picture_res); if (!sys->pictures[i]) { msg_Err(vd, "Failed to create picture"); free(picture_res.p_sys); goto out; } sys->pictures[i]->i_planes = sys->i_planes; memcpy(sys->pictures[i]->p, sys->planes, sys->i_planes * sizeof(plane_t)); } memset(&picture_pool_cfg, 0, sizeof(picture_pool_configuration_t)); picture_pool_cfg.picture_count = sys->num_buffers; picture_pool_cfg.picture = sys->pictures; picture_pool_cfg.lock = mmal_picture_lock; picture_pool_cfg.unlock = mmal_picture_unlock; sys->picture_pool = picture_pool_NewExtended(&picture_pool_cfg); if (!sys->picture_pool) { msg_Err(vd, "Failed to create picture pool"); goto out; } out: return sys->picture_pool; }
/** * 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; }
/** * 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; }
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"); } */ }
bool CMMALVideo::Open(CDVDStreamInfo &hints, CDVDCodecOptions &options, MMALVideoPtr myself) { if (g_advancedSettings.CanLogComponent(LOGVIDEO)) CLog::Log(LOGDEBUG, "%s::%s usemmal:%d software:%d %dx%d", CLASSNAME, __func__, CSettings::Get().GetBool("videoplayer.usemmal"), hints.software, hints.width, hints.height); // we always qualify even if DVDFactoryCodec does this too. if (!CSettings::Get().GetBool("videoplayer.usemmal") || hints.software) return false; m_hints = hints; MMAL_STATUS_T status; MMAL_PARAMETER_BOOLEAN_T error_concealment; m_myself = myself; m_decoded_width = hints.width; m_decoded_height = hints.height; // use aspect in stream if available if (m_hints.forced_aspect) m_aspect_ratio = m_hints.aspect; else m_aspect_ratio = 0.0; switch (hints.codec) { case AV_CODEC_ID_H264: // H.264 m_codingType = MMAL_ENCODING_H264; m_pFormatName = "mmal-h264"; break; case AV_CODEC_ID_H263: case AV_CODEC_ID_MPEG4: // MPEG-4, DivX 4/5 and Xvid compatible m_codingType = MMAL_ENCODING_MP4V; m_pFormatName = "mmal-mpeg4"; break; case AV_CODEC_ID_MPEG1VIDEO: case AV_CODEC_ID_MPEG2VIDEO: // MPEG-2 m_codingType = MMAL_ENCODING_MP2V; m_pFormatName = "mmal-mpeg2"; break; case AV_CODEC_ID_VP6: // this form is encoded upside down // fall through case AV_CODEC_ID_VP6F: case AV_CODEC_ID_VP6A: // VP6 m_codingType = MMAL_ENCODING_VP6; m_pFormatName = "mmal-vp6"; break; case AV_CODEC_ID_VP8: // VP8 m_codingType = MMAL_ENCODING_VP8; m_pFormatName = "mmal-vp8"; break; case AV_CODEC_ID_THEORA: // theora m_codingType = MMAL_ENCODING_THEORA; m_pFormatName = "mmal-theora"; break; case AV_CODEC_ID_MJPEG: case AV_CODEC_ID_MJPEGB: // mjpg m_codingType = MMAL_ENCODING_MJPEG; m_pFormatName = "mmal-mjpg"; break; case AV_CODEC_ID_VC1: case AV_CODEC_ID_WMV3: // VC-1, WMV9 m_codingType = MMAL_ENCODING_WVC1; m_pFormatName = "mmal-vc1"; break; default: CLog::Log(LOGERROR, "%s::%s : Video codec unknown: %x", CLASSNAME, __func__, hints.codec); return false; break; } if ( (m_codingType == MMAL_ENCODING_MP2V && !g_RBP.GetCodecMpg2() ) || (m_codingType == MMAL_ENCODING_WVC1 && !g_RBP.GetCodecWvc1() ) ) { CLog::Log(LOGWARNING, "%s::%s Codec %s is not supported", CLASSNAME, __func__, m_pFormatName); return false; } // initialize mmal. status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, &m_dec); if (status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to create MMAL decoder component %s (status=%x %s)", CLASSNAME, __func__, MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, status, mmal_status_to_string(status)); return false; } m_dec->control->userdata = (struct MMAL_PORT_USERDATA_T *)this; status = mmal_port_enable(m_dec->control, dec_control_port_cb_static); if (status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to enable decoder control port %s (status=%x %s)", CLASSNAME, __func__, MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, status, mmal_status_to_string(status)); return false; } m_dec_input = m_dec->input[0]; m_dec_input->format->type = MMAL_ES_TYPE_VIDEO; m_dec_input->format->encoding = m_codingType; if (m_hints.width && m_hints.height) { m_dec_input->format->es->video.crop.width = m_hints.width; m_dec_input->format->es->video.crop.height = m_hints.height; m_dec_input->format->es->video.width = ALIGN_UP(m_hints.width, 32); m_dec_input->format->es->video.height = ALIGN_UP(m_hints.height, 16); } m_dec_input->format->flags |= MMAL_ES_FORMAT_FLAG_FRAMED; error_concealment.hdr.id = MMAL_PARAMETER_VIDEO_DECODE_ERROR_CONCEALMENT; error_concealment.hdr.size = sizeof(MMAL_PARAMETER_BOOLEAN_T); error_concealment.enable = MMAL_FALSE; status = mmal_port_parameter_set(m_dec_input, &error_concealment.hdr); if (status != MMAL_SUCCESS) CLog::Log(LOGERROR, "%s::%s Failed to disable error concealment on %s (status=%x %s)", CLASSNAME, __func__, m_dec_input->name, status, mmal_status_to_string(status)); status = mmal_port_parameter_set_uint32(m_dec_input, MMAL_PARAMETER_EXTRA_BUFFERS, NUM_BUFFERS); if (status != MMAL_SUCCESS) CLog::Log(LOGERROR, "%s::%s Failed to enable extra buffers on %s (status=%x %s)", CLASSNAME, __func__, m_dec_input->name, status, mmal_status_to_string(status)); status = mmal_port_format_commit(m_dec_input); if (status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to commit format for decoder input port %s (status=%x %s)", CLASSNAME, __func__, m_dec_input->name, status, mmal_status_to_string(status)); return false; } m_dec_input->buffer_size = m_dec_input->buffer_size_recommended; m_dec_input->buffer_num = m_dec_input->buffer_num_recommended; m_dec_input->userdata = (struct MMAL_PORT_USERDATA_T *)this; status = mmal_port_enable(m_dec_input, dec_input_port_cb); if (status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to enable decoder input port %s (status=%x %s)", CLASSNAME, __func__, m_dec_input->name, status, mmal_status_to_string(status)); return false; } m_dec_output = m_dec->output[0]; // set up initial decoded frame format - will likely change from this m_dec_output->format->encoding = MMAL_ENCODING_OPAQUE; mmal_format_copy(m_es_format, m_dec_output->format); status = mmal_port_format_commit(m_dec_output); if (status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to commit decoder output format (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } m_dec_output->buffer_size = m_dec_output->buffer_size_min; m_dec_output->buffer_num = m_dec_output->buffer_num_recommended; m_dec_output->userdata = (struct MMAL_PORT_USERDATA_T *)this; status = mmal_port_enable(m_dec_output, dec_output_port_cb_static); if (status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to enable decoder output port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } status = mmal_component_enable(m_dec); if (status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to enable decoder component %s (status=%x %s)", CLASSNAME, __func__, m_dec->name, status, mmal_status_to_string(status)); return false; } m_dec_input_pool = mmal_pool_create(m_dec_input->buffer_num, m_dec_input->buffer_size); if (!m_dec_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; } m_dec_output_pool = mmal_pool_create(m_dec_output->buffer_num, m_dec_output->buffer_size); if(!m_dec_output_pool) { CLog::Log(LOGERROR, "%s::%s Failed to create pool for decode output port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } if (!SendCodecConfigData()) return false; m_drop_state = false; m_startframe = 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(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 av_cold int ffmmal_init_decoder(AVCodecContext *avctx) { MMALDecodeContext *ctx = avctx->priv_data; MMAL_STATUS_T status; MMAL_ES_FORMAT_T *format_in; MMAL_COMPONENT_T *decoder; int ret = 0; bcm_host_init(); if (mmal_vc_init()) { av_log(avctx, AV_LOG_ERROR, "Cannot initialize MMAL VC driver!\n"); return AVERROR(ENOSYS); } if ((ret = ff_get_format(avctx, avctx->codec->pix_fmts)) < 0) return ret; avctx->pix_fmt = ret; if ((status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, &ctx->decoder))) goto fail; decoder = ctx->decoder; format_in = decoder->input[0]->format; format_in->type = MMAL_ES_TYPE_VIDEO; format_in->encoding = MMAL_ENCODING_H264; format_in->es->video.width = FFALIGN(avctx->width, 32); format_in->es->video.height = FFALIGN(avctx->height, 16); format_in->es->video.crop.width = avctx->width; format_in->es->video.crop.height = avctx->height; format_in->es->video.frame_rate.num = 24000; format_in->es->video.frame_rate.den = 1001; format_in->es->video.par.num = avctx->sample_aspect_ratio.num; format_in->es->video.par.den = avctx->sample_aspect_ratio.den; format_in->flags = MMAL_ES_FORMAT_FLAG_FRAMED; if (avctx->codec->id == AV_CODEC_ID_H264 && avctx->extradata && avctx->extradata[0] == 1) { uint8_t *dummy_p; int dummy_int; ctx->bsfc = av_bitstream_filter_init("h264_mp4toannexb"); if (!ctx->bsfc) { av_log(avctx, AV_LOG_ERROR, "Cannot open the h264_mp4toannexb BSF!\n"); ret = AVERROR(ENOSYS); goto fail; } av_bitstream_filter_filter(ctx->bsfc, avctx, NULL, &dummy_p, &dummy_int, NULL, 0, 0); } if (avctx->extradata_size) { if ((status = mmal_format_extradata_alloc(format_in, avctx->extradata_size))) goto fail; format_in->extradata_size = avctx->extradata_size; memcpy(format_in->extradata, avctx->extradata, format_in->extradata_size); } if ((status = mmal_port_format_commit(decoder->input[0]))) goto fail; decoder->input[0]->buffer_num = FFMAX(decoder->input[0]->buffer_num_min, 20); decoder->input[0]->buffer_size = FFMAX(decoder->input[0]->buffer_size_min, 512 * 1024); ctx->pool_in = mmal_pool_create(decoder->input[0]->buffer_num, 0); if (!ctx->pool_in) { ret = AVERROR(ENOMEM); goto fail; } if ((ret = ffmal_update_format(avctx)) < 0) goto fail; ctx->queue_decoded_frames = mmal_queue_create(); if (!ctx->queue_decoded_frames) goto fail; decoder->input[0]->userdata = (void*)avctx; decoder->output[0]->userdata = (void*)avctx; decoder->control->userdata = (void*)avctx; if ((status = mmal_port_enable(decoder->control, control_port_cb))) goto fail; if ((status = mmal_port_enable(decoder->input[0], input_callback))) goto fail; if ((status = mmal_port_enable(decoder->output[0], output_callback))) goto fail; if ((status = mmal_component_enable(decoder))) goto fail; return 0; fail: ffmmal_close_decoder(avctx); return ret < 0 ? ret : AVERROR_UNKNOWN; }
int main(int argc, char **argv) { MMAL_STATUS_T status = MMAL_EINVAL; MMAL_COMPONENT_T *decoder = 0; MMAL_POOL_T *pool_in = 0, *pool_out = 0; unsigned int count; if (argc < 2) { fprintf(stderr, "invalid arguments\n"); return -1; } #ifndef WIN32 // TODO verify that we dont really need to call bcm_host_init bcm_host_init(); #endif vcos_semaphore_create(&context.semaphore, "example", 1); SOURCE_OPEN(argv[1]); /* Create the decoder component. * This specific component exposes 2 ports (1 input and 1 output). Like most components * its expects the format of its input port to be set by the client in order for it to * know what kind of data it will be fed. */ status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, &decoder); CHECK_STATUS(status, "failed to create decoder"); /* Set format of video decoder input port */ MMAL_ES_FORMAT_T *format_in = decoder->input[0]->format; format_in->type = MMAL_ES_TYPE_VIDEO; format_in->encoding = MMAL_ENCODING_H264; format_in->es->video.width = 1280; format_in->es->video.height = 720; format_in->es->video.frame_rate.num = 30; format_in->es->video.frame_rate.den = 1; format_in->es->video.par.num = 1; format_in->es->video.par.den = 1; /* If the data is known to be framed then the following flag should be set: * format_in->flags |= MMAL_ES_FORMAT_FLAG_FRAMED; */ SOURCE_READ_CODEC_CONFIG_DATA(codec_header_bytes, codec_header_bytes_size); status = mmal_format_extradata_alloc(format_in, codec_header_bytes_size); CHECK_STATUS(status, "failed to allocate extradata"); format_in->extradata_size = codec_header_bytes_size; if (format_in->extradata_size) memcpy(format_in->extradata, codec_header_bytes, format_in->extradata_size); status = mmal_port_format_commit(decoder->input[0]); CHECK_STATUS(status, "failed to commit format"); /* Display the output port format */ MMAL_ES_FORMAT_T *format_out = decoder->output[0]->format; fprintf(stderr, "%s\n", decoder->output[0]->name); fprintf(stderr, " type: %i, fourcc: %4.4s\n", format_out->type, (char *)&format_out->encoding); fprintf(stderr, " bitrate: %i, framed: %i\n", format_out->bitrate, !!(format_out->flags & MMAL_ES_FORMAT_FLAG_FRAMED)); fprintf(stderr, " extra data: %i, %p\n", format_out->extradata_size, format_out->extradata); fprintf(stderr, " width: %i, height: %i, (%i,%i,%i,%i)\n", format_out->es->video.width, format_out->es->video.height, format_out->es->video.crop.x, format_out->es->video.crop.y, format_out->es->video.crop.width, format_out->es->video.crop.height); /* The format of both ports is now set so we can get their buffer requirements and create * our buffer headers. We use the buffer pool API to create these. */ decoder->input[0]->buffer_num = decoder->input[0]->buffer_num_min; decoder->input[0]->buffer_size = decoder->input[0]->buffer_size_min; decoder->output[0]->buffer_num = decoder->output[0]->buffer_num_min; decoder->output[0]->buffer_size = decoder->output[0]->buffer_size_min; pool_in = mmal_pool_create(decoder->input[0]->buffer_num, decoder->input[0]->buffer_size); pool_out = mmal_pool_create(decoder->output[0]->buffer_num, decoder->output[0]->buffer_size); /* Create a queue to store our decoded video frames. The callback we will get when * a frame has been decoded will put the frame into this queue. */ context.queue = mmal_queue_create(); /* Store a reference to our context in each port (will be used during callbacks) */ decoder->input[0]->userdata = (void *)&context; decoder->output[0]->userdata = (void *)&context; /* Enable all the input port and the output port. * The callback specified here is the function which will be called when the buffer header * we sent to the component has been processed. */ status = mmal_port_enable(decoder->input[0], input_callback); CHECK_STATUS(status, "failed to enable input port"); status = mmal_port_enable(decoder->output[0], output_callback); CHECK_STATUS(status, "failed to enable output port"); /* Component won't start processing data until it is enabled. */ status = mmal_component_enable(decoder); CHECK_STATUS(status, "failed to enable component"); /* Start decoding */ fprintf(stderr, "start decoding\n"); /* This is the main processing loop */ for (count = 0; count < 500; count++) { MMAL_BUFFER_HEADER_T *buffer; /* Wait for buffer headers to be available on either of the decoder ports */ vcos_semaphore_wait(&context.semaphore); /* Send data to decode to the input port of the video decoder */ if ((buffer = mmal_queue_get(pool_in->queue)) != NULL) { SOURCE_READ_DATA_INTO_BUFFER(buffer); if (!buffer->length) break; fprintf(stderr, "sending %i bytes\n", (int)buffer->length); status = mmal_port_send_buffer(decoder->input[0], buffer); CHECK_STATUS(status, "failed to send buffer"); } /* Get our decoded frames */ while ((buffer = mmal_queue_get(context.queue)) != NULL) { /* We have a frame, do something with it (why not display it for instance?). * Once we're done with it, we release it. It will automatically go back * to its original pool so it can be reused for a new video frame. */ fprintf(stderr, "decoded frame\n"); mmal_buffer_header_release(buffer); } /* Send empty buffers to the output port of the decoder */ while ((buffer = mmal_queue_get(pool_out->queue)) != NULL) { status = mmal_port_send_buffer(decoder->output[0], buffer); CHECK_STATUS(status, "failed to send buffer"); } } /* Stop decoding */ fprintf(stderr, "stop decoding\n"); /* Stop everything. Not strictly necessary since mmal_component_destroy() * will do that anyway */ mmal_port_disable(decoder->input[0]); mmal_port_disable(decoder->output[0]); mmal_component_disable(decoder); error: /* Cleanup everything */ if (decoder) mmal_component_destroy(decoder); if (pool_in) mmal_pool_destroy(pool_in); if (pool_out) mmal_pool_destroy(pool_out); if (context.queue) mmal_queue_destroy(context.queue); SOURCE_CLOSE(); vcos_semaphore_delete(&context.semaphore); return status == MMAL_SUCCESS ? 0 : -1; }
static MMAL_COMPONENT_T *mmalplay_component_create(MMALPLAY_T *ctx, const char *name, MMAL_STATUS_T *status) { MMALPLAY_COMPONENT_T *component = &ctx->component[ctx->component_num]; const char *component_name = name; LOG_TRACE("%p, %s", ctx, name); if (ctx->component_num >= MMAL_COUNTOF(ctx->component)) { *status = MMAL_ENOSPC; return NULL; } /* Decide whether we want an image decoder instead of a video_decoder */ if (ctx->is_still_image && !strcmp(name, MMAL_COMPONENT_DEFAULT_VIDEO_DECODER) && !ctx->options.component_video_decoder) ctx->options.component_video_decoder = MMAL_COMPONENT_DEFAULT_IMAGE_DECODER; /* Override name if requested by the user */ if (!strcmp(name, MMAL_COMPONENT_DEFAULT_VIDEO_DECODER) && ctx->options.component_video_decoder) component_name = ctx->options.component_video_decoder; else if (!strcmp(name, MMAL_COMPONENT_DEFAULT_SPLITTER) && ctx->options.component_splitter) component_name = ctx->options.component_splitter; else if (!strcmp(name, MMAL_COMPONENT_DEFAULT_VIDEO_RENDERER) && ctx->options.component_video_render) component_name = ctx->options.component_video_render; else if (!strcmp(name, MMAL_COMPONENT_DEFAULT_VIDEO_CONVERTER) && ctx->options.component_video_converter) component_name = ctx->options.component_video_converter; else if (!strcmp(name, MMAL_COMPONENT_DEFAULT_SCHEDULER) && ctx->options.component_video_scheduler) component_name = ctx->options.component_video_scheduler; else if (!strcmp(name, MMAL_COMPONENT_DEFAULT_AUDIO_DECODER) && ctx->options.component_audio_decoder) component_name = ctx->options.component_audio_decoder; else if (!strcmp(name, MMAL_COMPONENT_DEFAULT_AUDIO_RENDERER) && ctx->options.component_audio_render) component_name = ctx->options.component_audio_render; else if (!strcmp(name, MMAL_COMPONENT_DEFAULT_CONTAINER_READER) && ctx->options.component_container_reader) component_name = ctx->options.component_container_reader; component->comp = NULL; vcos_safe_strcpy(component->name, component_name, sizeof(component->name), 0); component->time_setup = vcos_getmicrosecs(); /* Create the component */ *status = mmal_component_create(component_name, &component->comp); if(*status != MMAL_SUCCESS) { LOG_ERROR("couldn't create %s", component_name); goto error; } if (!strcmp(name, MMAL_COMPONENT_DEFAULT_CONTAINER_READER)) *status = mmalplay_setup_container_reader(ctx, component->comp, ctx->uri); else if (!strcmp(name, MMAL_COMPONENT_DEFAULT_CONTAINER_WRITER)) *status = mmalplay_setup_container_writer(ctx, component->comp, ctx->options.output_uri); else if (!strcmp(name, MMAL_COMPONENT_DEFAULT_VIDEO_DECODER)) *status = mmalplay_setup_video_decoder(ctx, component->comp); else if (!strcmp(name, MMAL_COMPONENT_DEFAULT_SPLITTER)) *status = mmalplay_setup_splitter(ctx, component->comp); else if (!strcmp(name, MMAL_COMPONENT_DEFAULT_VIDEO_CONVERTER)) *status = mmalplay_setup_video_converter(ctx, component->comp); else if (!strcmp(name, MMAL_COMPONENT_DEFAULT_VIDEO_RENDERER)) *status = mmalplay_setup_video_render(ctx, component->comp); else if (!strcmp(name, MMAL_COMPONENT_DEFAULT_SCHEDULER)) *status = mmalplay_setup_video_scheduler(ctx, component->comp); else if (!strcmp(name, MMAL_COMPONENT_DEFAULT_AUDIO_DECODER)) *status = mmalplay_setup_audio_decoder(ctx, component->comp); else if (!strcmp(name, MMAL_COMPONENT_DEFAULT_AUDIO_RENDERER)) *status = mmalplay_setup_audio_render(ctx, component->comp); if (*status != MMAL_SUCCESS) goto error; /* Enable component */ *status = mmal_component_enable(component->comp); if(*status) { LOG_ERROR("%s couldn't be enabled", component_name); goto error; } /* Enable control port. The callback specified here is the function which * will be called when an empty buffer header comes back to the port. */ component->comp->control->userdata = (void *)ctx; *status = mmal_port_enable(component->comp->control, mmalplay_bh_control_cb); if (*status) { LOG_ERROR("control port couldn't be enabled"); goto error; } component->time_setup = vcos_getmicrosecs() - component->time_setup; ctx->component_num++; return component->comp; error: component->time_setup = vcos_getmicrosecs() - component->time_setup; if (component->comp) mmal_component_destroy(component->comp); return NULL; }
/** * 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; }
static int OpenDecoder(decoder_t *dec) { int ret = VLC_SUCCESS; decoder_sys_t *sys; MMAL_PARAMETER_UINT32_T extra_buffers; MMAL_STATUS_T status; if (dec->fmt_in.i_cat != VIDEO_ES) return VLC_EGENERIC; if (dec->fmt_in.i_codec != VLC_CODEC_MPGV && dec->fmt_in.i_codec != VLC_CODEC_H264) return VLC_EGENERIC; sys = calloc(1, sizeof(decoder_sys_t)); if (!sys) { ret = VLC_ENOMEM; goto out; } dec->p_sys = sys; dec->b_need_packetized = true; sys->opaque = var_InheritBool(dec, MMAL_OPAQUE_NAME); bcm_host_init(); status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, &sys->component); if (status != MMAL_SUCCESS) { msg_Err(dec, "Failed to create MMAL component %s (status=%"PRIx32" %s)", MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, status, mmal_status_to_string(status)); ret = VLC_EGENERIC; goto out; } sys->component->control->userdata = (struct MMAL_PORT_USERDATA_T *)dec; status = mmal_port_enable(sys->component->control, control_port_cb); if (status != MMAL_SUCCESS) { msg_Err(dec, "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 *)dec; if (dec->fmt_in.i_codec == VLC_CODEC_MPGV) sys->input->format->encoding = MMAL_ENCODING_MP2V; else sys->input->format->encoding = MMAL_ENCODING_H264; if (dec->fmt_in.i_codec == VLC_CODEC_H264) { if (dec->fmt_in.i_extra > 0) { status = mmal_format_extradata_alloc(sys->input->format, dec->fmt_in.i_extra); if (status == MMAL_SUCCESS) { memcpy(sys->input->format->extradata, dec->fmt_in.p_extra, dec->fmt_in.i_extra); sys->input->format->extradata_size = dec->fmt_in.i_extra; } else { msg_Err(dec, "Failed to allocate extra format data on input port %s (status=%"PRIx32" %s)", sys->input->name, status, mmal_status_to_string(status)); } } } status = mmal_port_format_commit(sys->input); if (status != MMAL_SUCCESS) { msg_Err(dec, "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; status = mmal_port_enable(sys->input, input_port_cb); if (status != MMAL_SUCCESS) { msg_Err(dec, "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 *)dec; if (sys->opaque) { extra_buffers.hdr.id = MMAL_PARAMETER_EXTRA_BUFFERS; extra_buffers.hdr.size = sizeof(MMAL_PARAMETER_UINT32_T); extra_buffers.value = NUM_EXTRA_BUFFERS; status = mmal_port_parameter_set(sys->output, &extra_buffers.hdr); if (status != MMAL_SUCCESS) { msg_Err(dec, "Failed to set MMAL_PARAMETER_EXTRA_BUFFERS on output port (status=%"PRIx32" %s)", status, mmal_status_to_string(status)); ret = VLC_EGENERIC; goto out; } msg_Dbg(dec, "Activate zero-copy for output port"); 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(dec, "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(dec, "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(dec, "Failed to enable component %s (status=%"PRIx32" %s)", sys->component->name, status, mmal_status_to_string(status)); ret = VLC_EGENERIC; goto out; } sys->input_pool = mmal_pool_create(sys->input->buffer_num, 0); sys->decoded_pictures = mmal_queue_create(); if (sys->opaque) { dec->fmt_out.i_codec = VLC_CODEC_MMAL_OPAQUE; dec->fmt_out.video.i_chroma = VLC_CODEC_MMAL_OPAQUE; } else { dec->fmt_out.i_codec = VLC_CODEC_I420; dec->fmt_out.video.i_chroma = VLC_CODEC_I420; } dec->fmt_out.i_cat = VIDEO_ES; dec->pf_decode_video = decode; vlc_mutex_init_recursive(&sys->mutex); vlc_sem_init(&sys->sem, 0); out: if (ret != VLC_SUCCESS) CloseDecoder(dec); return ret; }
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; }
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; }
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; }
/** * 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; }
static av_cold int ffmmal_init_decoder(AVCodecContext *avctx) { MMALDecodeContext *ctx = avctx->priv_data; MMAL_STATUS_T status; MMAL_ES_FORMAT_T *format_in; MMAL_COMPONENT_T *decoder; char tmp[32]; int ret = 0; bcm_host_init(); if (mmal_vc_init()) { av_log(avctx, AV_LOG_ERROR, "Cannot initialize MMAL VC driver!\n"); return AVERROR(ENOSYS); } if ((ret = ff_get_format(avctx, avctx->codec->pix_fmts)) < 0) return ret; avctx->pix_fmt = ret; if ((status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, &ctx->decoder))) goto fail; decoder = ctx->decoder; format_in = decoder->input[0]->format; format_in->type = MMAL_ES_TYPE_VIDEO; switch (avctx->codec_id) { case AV_CODEC_ID_MPEG2VIDEO: format_in->encoding = MMAL_ENCODING_MP2V; break; case AV_CODEC_ID_MPEG4: format_in->encoding = MMAL_ENCODING_MP4V; break; case AV_CODEC_ID_VC1: format_in->encoding = MMAL_ENCODING_WVC1; break; case AV_CODEC_ID_H264: default: format_in->encoding = MMAL_ENCODING_H264; break; } format_in->es->video.width = FFALIGN(avctx->width, 32); format_in->es->video.height = FFALIGN(avctx->height, 16); format_in->es->video.crop.width = avctx->width; format_in->es->video.crop.height = avctx->height; format_in->es->video.frame_rate.num = 24000; format_in->es->video.frame_rate.den = 1001; format_in->es->video.par.num = avctx->sample_aspect_ratio.num; format_in->es->video.par.den = avctx->sample_aspect_ratio.den; format_in->flags = MMAL_ES_FORMAT_FLAG_FRAMED; av_get_codec_tag_string(tmp, sizeof(tmp), format_in->encoding); av_log(avctx, AV_LOG_DEBUG, "Using MMAL %s encoding.\n", tmp); #if HAVE_MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS if (mmal_port_parameter_set_uint32(decoder->input[0], MMAL_PARAMETER_VIDEO_MAX_NUM_CALLBACKS, -1 - ctx->extra_decoder_buffers)) { av_log(avctx, AV_LOG_WARNING, "Could not set input buffering limit.\n"); } #endif if ((status = mmal_port_format_commit(decoder->input[0]))) goto fail; decoder->input[0]->buffer_num = FFMAX(decoder->input[0]->buffer_num_min, 20); decoder->input[0]->buffer_size = FFMAX(decoder->input[0]->buffer_size_min, 512 * 1024); ctx->pool_in = mmal_pool_create(decoder->input[0]->buffer_num, 0); if (!ctx->pool_in) { ret = AVERROR(ENOMEM); goto fail; } if ((ret = ffmal_update_format(avctx)) < 0) goto fail; ctx->queue_decoded_frames = mmal_queue_create(); if (!ctx->queue_decoded_frames) goto fail; decoder->input[0]->userdata = (void*)avctx; decoder->output[0]->userdata = (void*)avctx; decoder->control->userdata = (void*)avctx; if ((status = mmal_port_enable(decoder->control, control_port_cb))) goto fail; if ((status = mmal_port_enable(decoder->input[0], input_callback))) goto fail; if ((status = mmal_port_enable(decoder->output[0], output_callback))) goto fail; if ((status = mmal_component_enable(decoder))) goto fail; return 0; fail: ffmmal_close_decoder(avctx); return ret < 0 ? ret : AVERROR_UNKNOWN; }
/** * Create the camera 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_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) { 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 = 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); } // Now set up the port formats // Set the encode format on the Preview port // HW limitations mean we need the preview to be the same size as the required recorded output format = preview_port->format; format->encoding = MMAL_ENCODING_OPAQUE; format->encoding_variant = MMAL_ENCODING_I420; 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 = state->framerate; format->es->video.frame_rate.den = VIDEO_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 encode format on the video port format = video_port->format; format->encoding_variant = MMAL_ENCODING_I420; 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 = state->framerate; format->es->video.frame_rate.den = VIDEO_FRAME_RATE_DEN; 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; // 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 != 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; } raspicamcontrol_set_all_parameters(camera, &state->camera_parameters); state->camera_component = camera; if (state->verbose) fprintf(stderr, "Camera component done\n"); return status; error: if (camera) mmal_component_destroy(camera); return status; }