RaspiCamCvCapture * raspiCamCvCreateCameraCapture2(int index, RASPIVID_CONFIG* config) { RaspiCamCvCapture * capture = (RaspiCamCvCapture*)malloc(sizeof(RaspiCamCvCapture)); // Our main data storage vessel.. RASPIVID_STATE * state = (RASPIVID_STATE*)malloc(sizeof(RASPIVID_STATE)); capture->pState = state; MMAL_STATUS_T status = -1; MMAL_PORT_T *camera_video_port = NULL; MMAL_PORT_T *camera_still_port = NULL; bcm_host_init(); default_status(state); if (config != NULL) { if (config->width != 0) state->width = config->width; if (config->height != 0) state->height = config->height; if (config->bitrate != 0) state->bitrate = config->bitrate; if (config->framerate != 0) state->framerate = config->framerate; if (config->monochrome != 0) state->monochrome = config->monochrome; } int w = state->width; int h = state->height; int pixelSize = state->monochrome ? 1 : 3; state->dstImage = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, pixelSize); // final picture to display vcos_semaphore_create(&state->capture_sem, "Capture-Sem", 0); vcos_semaphore_create(&state->capture_done_sem, "Capture-Done-Sem", 0); // create camera if (!create_camera_component(state)) { vcos_log_error("%s: Failed to create camera component", __func__); raspiCamCvReleaseCapture(&capture); return NULL; } camera_video_port = state->camera_component->output[MMAL_CAMERA_VIDEO_PORT]; camera_still_port = state->camera_component->output[MMAL_CAMERA_CAPTURE_PORT]; // assign data to use for callback camera_video_port->userdata = (struct MMAL_PORT_USERDATA_T *)state; // start capture if (mmal_port_parameter_set_boolean(camera_video_port, MMAL_PARAMETER_CAPTURE, 1) != MMAL_SUCCESS) { vcos_log_error("%s: Failed to start capture", __func__); raspiCamCvReleaseCapture(&capture); return NULL; } // Send all the buffers to the video port int num = mmal_queue_length(state->video_pool->queue); int q; for (q = 0; q < num; q++) { MMAL_BUFFER_HEADER_T *buffer = mmal_queue_get(state->video_pool->queue); if (!buffer) vcos_log_error("Unable to get a required buffer %d from pool queue", q); if (mmal_port_send_buffer(camera_video_port, buffer)!= MMAL_SUCCESS) vcos_log_error("Unable to send a buffer to encoder output port (%d)", q); } //mmal_status_to_int(status); // Disable all our ports that are not handled by connections //check_disable_port(camera_still_port); //if (status != 0) // raspicamcontrol_check_configuration(128); vcos_semaphore_wait(&state->capture_done_sem); return capture; }
/** * main */ int main(int argc, const char **argv) { // *** MODIFICATION: OpenCV modifications. // Load previous image. IplImage* prevImage = cvLoadImage("motion1.jpg", CV_LOAD_IMAGE_COLOR); // Create two arrays with the same number of channels than the original one. avg1 = cvCreateMat(prevImage->height,prevImage->width,CV_32FC3); avg2 = cvCreateMat(prevImage->height,prevImage->width,CV_32FC3); // Create image of 32 bits. IplImage* image32 = cvCreateImage(cvSize(prevImage->width,prevImage->height), 32,3); // Convert image to 32 bits. cvConvertScale(prevImage,image32,1/255,0); // Set data from previous image into arrays. cvSetData(avg1,image32->imageData,image32->widthStep); cvSetData(avg2,image32->imageData,image32->widthStep); // *** MODIFICATION end // Our main data storage vessel.. RASPISTILL_STATE state; MMAL_STATUS_T status = MMAL_SUCCESS; MMAL_PORT_T *camera_preview_port = NULL; MMAL_PORT_T *camera_video_port = NULL; MMAL_PORT_T *camera_still_port = NULL; MMAL_PORT_T *preview_input_port = NULL; MMAL_PORT_T *encoder_input_port = NULL; MMAL_PORT_T *encoder_output_port = NULL; bcm_host_init(); // Register our application with the logging system vcos_log_register("fast", VCOS_LOG_CATEGORY); signal(SIGINT, signal_handler); default_status(&state); if (state.verbose) { fprintf(stderr, "\n%s Camera App %s\n\n", basename(argv[0]), VERSION_STRING); } // OK, we have a nice set of parameters. Now set up our components // We have three components. Camera, Preview and encoder. // Camera and encoder are different in stills/video, but preview // is the same so handed off to a separate module if ((status = create_camera_component(&state)) != MMAL_SUCCESS) { vcos_log_error("%s: Failed to create camera component", __func__); } else if ((status = raspipreview_create(&state.preview_parameters)) != MMAL_SUCCESS) { vcos_log_error("%s: Failed to create preview component", __func__); destroy_camera_component(&state); } else if ((status = create_encoder_component(&state)) != MMAL_SUCCESS) { vcos_log_error("%s: Failed to create encode component", __func__); raspipreview_destroy(&state.preview_parameters); destroy_camera_component(&state); } else { PORT_USERDATA callback_data; if (state.verbose) fprintf(stderr, "Starting component connection stage\n"); camera_preview_port = state.camera_component->output[MMAL_CAMERA_PREVIEW_PORT]; camera_video_port = state.camera_component->output[MMAL_CAMERA_VIDEO_PORT]; camera_still_port = state.camera_component->output[MMAL_CAMERA_CAPTURE_PORT]; preview_input_port = state.preview_parameters.preview_component->input[0]; encoder_input_port = state.encoder_component->input[0]; encoder_output_port = state.encoder_component->output[0]; if (state.preview_parameters.wantPreview ) { if (state.verbose) { fprintf(stderr, "Connecting camera preview port to preview input port\n"); fprintf(stderr, "Starting video preview\n"); } // *** USER: remove preview // Connect camera to preview //status = connect_ports(camera_preview_port, preview_input_port, &state.preview_connection); } else { status = MMAL_SUCCESS; } if (status == MMAL_SUCCESS) { VCOS_STATUS_T vcos_status; if (state.verbose) fprintf(stderr, "Connecting camera stills port to encoder input port\n"); // Now connect the camera to the encoder status = connect_ports(camera_still_port, encoder_input_port, &state.encoder_connection); if (status != MMAL_SUCCESS) { vcos_log_error("%s: Failed to connect camera video port to encoder input", __func__); goto error; } // Set up our userdata - this is passed though to the callback where we need the information. // Null until we open our filename callback_data.file_handle = NULL; callback_data.pstate = &state; vcos_status = vcos_semaphore_create(&callback_data.complete_semaphore, "RaspiStill-sem", 0); vcos_assert(vcos_status == VCOS_SUCCESS); if (status != MMAL_SUCCESS) { vcos_log_error("Failed to setup encoder output"); goto error; } FILE *output_file = NULL; int frame = 1; // Enable the encoder output port encoder_output_port->userdata = (struct MMAL_PORT_USERDATA_T *)&callback_data; if (state.verbose) fprintf(stderr, "Enabling encoder output port\n"); // Enable the encoder output port and tell it its callback function status = mmal_port_enable(encoder_output_port, encoder_buffer_callback); // Create an empty matrix with the size of the buffer. CvMat* buf = cvCreateMat(1,60000,CV_8UC1); // Keep buffer that gets frames from queue. MMAL_BUFFER_HEADER_T *buffer; // Image to be displayed. IplImage* image; // Keep number of buffers and index for the loop. int num, q; while(1) { // Send all the buffers to the encoder output port num = mmal_queue_length(state.encoder_pool->queue); for (q=0;q<num;q++) { buffer = mmal_queue_get(state.encoder_pool->queue); if (!buffer) vcos_log_error("Unable to get a required buffer %d from pool queue", q); if (mmal_port_send_buffer(encoder_output_port, buffer)!= MMAL_SUCCESS) vcos_log_error("Unable to send a buffer to encoder output port (%d)", q); } // for if (mmal_port_parameter_set_boolean(camera_still_port, MMAL_PARAMETER_CAPTURE, 1) != MMAL_SUCCESS) vcos_log_error("%s: Failed to start capture", __func__); else { // Wait for capture to complete // For some reason using vcos_semaphore_wait_timeout sometimes returns immediately with bad parameter error // even though it appears to be all correct, so reverting to untimed one until figure out why its erratic vcos_semaphore_wait(&callback_data.complete_semaphore); if (state.verbose) fprintf(stderr, "Finished capture %d\n", frame); } // else // Copy buffer from camera to matrix. buf->data.ptr = buffer->data; // This workaround is needed for the code to work // *** TODO: investigate why. printf("Until here works\n"); // Decode the image and display it. image = cvDecodeImage(buf, CV_LOAD_IMAGE_COLOR); // Destinations CvMat* res1 = cvCreateMat(image->height,image->width,CV_8UC3); CvMat* res2 = cvCreateMat(image->height,image->width,CV_8UC3); // Update running averages and then scale, calculate absolute values // and convert the result 8-bit. // *** USER:change the value of the weight. cvRunningAvg(image,avg2,0.0001, NULL); cvConvertScaleAbs(avg2, res2, 1,0); cvRunningAvg(image,avg1,0.1, NULL); cvConvertScaleAbs(avg1, res1, 1,0); // Show images cvShowImage("img",image); cvShowImage("avg1",res1); cvShowImage("avg2",res2); cvWaitKey(20); // Update previous image. cvSaveImage("motion1.jpg", image, 0); } // end while vcos_semaphore_delete(&callback_data.complete_semaphore); } else { mmal_status_to_int(status); vcos_log_error("%s: Failed to connect camera to preview", __func__); } error: mmal_status_to_int(status); if (state.verbose) fprintf(stderr, "Closing down\n"); // Disable all our ports that are not handled by connections check_disable_port(camera_video_port); check_disable_port(encoder_output_port); if (state.preview_parameters.wantPreview ) mmal_connection_destroy(state.preview_connection); mmal_connection_destroy(state.encoder_connection); /* Disable components */ if (state.encoder_component) mmal_component_disable(state.encoder_component); if (state.preview_parameters.preview_component) mmal_component_disable(state.preview_parameters.preview_component); if (state.camera_component) mmal_component_disable(state.camera_component); destroy_encoder_component(&state); raspipreview_destroy(&state.preview_parameters); destroy_camera_component(&state); if (state.verbose) fprintf(stderr, "Close down completed, all components disconnected, disabled and destroyed\n\n"); } if (status != MMAL_SUCCESS) raspicamcontrol_check_configuration(128); 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; } } { MMAL_PARAMETER_VIDEO_PROFILE_T param; param.hdr.id = MMAL_PARAMETER_PROFILE; param.hdr.size = sizeof(param); param.profile[0].profile = state->profile; param.profile[0].level = MMAL_VIDEO_LEVEL_H264_4; // This is the only value supported status = mmal_port_parameter_set(encoder_output, ¶m.hdr); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set H264 profile"); goto error; } } if (mmal_port_parameter_set_boolean(encoder_input, MMAL_PARAMETER_VIDEO_IMMUTABLE_INPUT, state->immutableInput) != MMAL_SUCCESS) { vcos_log_error("Unable to set immutable input flag"); // Continue rather than abort.. } // Enable component status = mmal_component_enable(encoder); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to enable video encoder component"); goto error; } /* Create pool of buffer headers for the output port to consume */ pool = mmal_port_pool_create(encoder_output, encoder_output->buffer_num, encoder_output->buffer_size); if (!pool) { vcos_log_error("Failed to create buffer header pool for encoder output port %s", encoder_output->name); } state->encoder_pool = pool; state->encoder_component = encoder; if (state->verbose) fprintf(stderr, "Encoder component done\n"); return status; error: if (encoder) mmal_component_destroy(encoder); return status; }
MmalStillCamera::MmalStillCamera(int imageWidth, int imageHeight, bool enableBurstMode) : m_imageWidth(imageWidth), m_imageHeight(imageHeight), m_callbackData(NULL), m_cs(), m_camera(NULL), m_preview(NULL), m_encoder(NULL), m_pool(NULL), m_previewPort(NULL), m_videoPort(NULL), m_stillPort(NULL), m_targetPort(NULL) { m_callbackData = new MmalStillCallbackData(m_imageWidth, m_imageHeight, 3); createCameraComponent(); std::cout << "Created camera" << std::endl; createPreview(); std::cout << "Created preview" << std::endl; std::cout << "Target Image Width: " << VCOS_ALIGN_UP(m_imageWidth, 32) << std::endl; std::cout << "Target Image Height: " << VCOS_ALIGN_UP(m_imageHeight, 16) << std::endl; MMAL_STATUS_T status; m_targetPort = m_stillPort; // Create pool of buffer headers for the output port to consume m_pool = mmal_port_pool_create(m_targetPort, m_targetPort->buffer_num, m_targetPort->buffer_size); if (m_pool == NULL) { throw Exception("Failed to create buffer header pool for encoder output port"); } MMAL_CONNECTION_T *preview_connection = NULL; status = connect_ports(m_previewPort, m_preview->input[0], &preview_connection); if (status != MMAL_SUCCESS) { throw Exception("Error connecting preview port"); } m_targetPort->userdata = (struct MMAL_PORT_USERDATA_T *) m_callbackData; m_callbackData->image = NULL; m_callbackData->pool = m_pool; // Enable the encoder output port and tell it its callback function if (mmal_port_enable(m_targetPort, EncoderBufferCallback) != MMAL_SUCCESS) { std::cerr << "Error enabling the encoder buffer callback" << std::endl; } // Send all the buffers to the encoder output port int num = mmal_queue_length(m_pool->queue); for (int q = 0; q < num; q++) { MMAL_BUFFER_HEADER_T *buffer = mmal_queue_get(m_pool->queue); if (buffer == NULL) { std::cerr << "Unable to get buffer " << q << " from the pool" << std::endl; } if (mmal_port_send_buffer(m_targetPort, buffer)!= MMAL_SUCCESS) { std::cerr << "Unable to send a buffer " << q << " to encoder output port " << std::endl; } } // Enable burst mode if (enableBurstMode) { if (mmal_port_parameter_set_boolean(m_camera->control, MMAL_PARAMETER_CAMERA_BURST_CAPTURE, 1) != MMAL_SUCCESS) { std::cerr << "Error enabling burst mode" << std::endl; } std::cout << "Enabled burst mode for still images" << std::endl; } std::cout << "Initialized camera" << std::endl; }
/** * Create the encoder component, set up its ports * * @param state Pointer to state control struct * * @return 0 if failed, pointer to component if successful * */ static MMAL_STATUS_T create_encoder_component(RASPIVID_STATE *state) { MMAL_COMPONENT_T *encoder = 0; MMAL_PORT_T *encoder_input = NULL, *encoder_output = NULL; MMAL_STATUS_T status; MMAL_POOL_T *pool; //printf("point1\n"); status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_ENCODER, &encoder); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to create video encoder component"); goto error; } if (!encoder->input_num || !encoder->output_num) { status = MMAL_ENOSYS; vcos_log_error("Video encoder doesn't have input/output ports"); goto error; } encoder_input = encoder->input[0]; encoder_output = encoder->output[0]; // We want same format on input and output mmal_format_copy(encoder_output->format, encoder_input->format); // Only supporting H264 at the moment encoder_output->format->encoding = MMAL_ENCODING_H264; encoder_output->format->bitrate = state->bitrate; encoder_output->buffer_size = encoder_output->buffer_size_recommended; if (encoder_output->buffer_size < encoder_output->buffer_size_min) encoder_output->buffer_size = encoder_output->buffer_size_min; encoder_output->buffer_num = encoder_output->buffer_num_recommended; if (encoder_output->buffer_num < encoder_output->buffer_num_min) encoder_output->buffer_num = encoder_output->buffer_num_min; // We need to set the frame rate on output to 0, to ensure it gets // updated correctly from the input framerate when port connected encoder_output->format->es->video.frame_rate.num = 0; encoder_output->format->es->video.frame_rate.den = 1; // Commit the port changes to the output port status = mmal_port_format_commit(encoder_output); //printf("point2\n"); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set format on video encoder output port"); goto error; } // Set the rate control parameter if (0) { MMAL_PARAMETER_VIDEO_RATECONTROL_T param = {{ MMAL_PARAMETER_RATECONTROL, sizeof(param)}, MMAL_VIDEO_RATECONTROL_DEFAULT}; status = mmal_port_parameter_set(encoder_output, ¶m.hdr); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set ratecontrol"); goto error; } } if (state->intraperiod) { MMAL_PARAMETER_UINT32_T param = {{ MMAL_PARAMETER_INTRAPERIOD, sizeof(param)}, state->intraperiod}; status = mmal_port_parameter_set(encoder_output, ¶m.hdr); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set intraperiod"); goto error; } } if (state->quantisationParameter) { MMAL_PARAMETER_UINT32_T param = {{ MMAL_PARAMETER_VIDEO_ENCODE_INITIAL_QUANT, sizeof(param)}, state->quantisationParameter}; status = mmal_port_parameter_set(encoder_output, ¶m.hdr); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set initial QP"); goto error; } MMAL_PARAMETER_UINT32_T param2 = {{ MMAL_PARAMETER_VIDEO_ENCODE_MIN_QUANT, sizeof(param)}, state->quantisationParameter}; status = mmal_port_parameter_set(encoder_output, ¶m2.hdr); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set min QP"); goto error; } MMAL_PARAMETER_UINT32_T param3 = {{ MMAL_PARAMETER_VIDEO_ENCODE_MAX_QUANT, sizeof(param)}, state->quantisationParameter}; status = mmal_port_parameter_set(encoder_output, ¶m3.hdr); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set max QP"); goto error; } } { MMAL_PARAMETER_VIDEO_PROFILE_T param; param.hdr.id = MMAL_PARAMETER_PROFILE; param.hdr.size = sizeof(param); //param.profile[0].profile = state->profile; param.profile[0].profile = MMAL_VIDEO_PROFILE_H264_HIGH; param.profile[0].level = MMAL_VIDEO_LEVEL_H264_4; // This is the only value supported status = mmal_port_parameter_set(encoder_output, ¶m.hdr); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set H264 profile"); goto error; } } if (mmal_port_parameter_set_boolean(encoder_input, MMAL_PARAMETER_VIDEO_IMMUTABLE_INPUT, state->immutableInput) != MMAL_SUCCESS) { vcos_log_error("Unable to set immutable input flag"); // Continue rather than abort.. } //set INLINE HEADER flag to generate SPS and PPS for every IDR if requested if (mmal_port_parameter_set_boolean(encoder_output, MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER, state->bInlineHeaders) != MMAL_SUCCESS) { vcos_log_error("failed to set INLINE HEADER FLAG parameters"); // Continue rather than abort.. } //set INLINE VECTORS flag to request motion vector estimates if (mmal_port_parameter_set_boolean(encoder_output, MMAL_PARAMETER_VIDEO_ENCODE_INLINE_VECTORS, state->inlineMotionVectors) != MMAL_SUCCESS) { vcos_log_error("failed to set INLINE VECTORS parameters"); // Continue rather than abort.. } // Enable component status = mmal_component_enable(encoder); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to enable video encoder component"); goto error; } /* Create pool of buffer headers for the output port to consume */ pool = mmal_port_pool_create(encoder_output, encoder_output->buffer_num, encoder_output->buffer_size); if (!pool) { vcos_log_error("Failed to create buffer header pool for encoder output port %s", encoder_output->name); goto error; } state->encoder_pool = pool; state->encoder_component = encoder; /*if (state->verbose) fprintf(stderr, "Encoder component done\n"); */ return status; error: if (encoder) mmal_component_destroy(encoder); state->encoder_component = NULL; return status; }
int setup_camera(PORT_USERDATA *userdata) { MMAL_STATUS_T status; MMAL_COMPONENT_T *camera = 0; MMAL_ES_FORMAT_T *format; MMAL_PORT_T * camera_preview_port; MMAL_PORT_T * camera_video_port; MMAL_PORT_T * camera_still_port; MMAL_POOL_T * camera_video_port_pool; status = mmal_component_create(MMAL_COMPONENT_DEFAULT_CAMERA, &camera); if (status != MMAL_SUCCESS) { fprintf(stderr, "Error: create camera %x\n", status); return -1; } userdata->camera = camera; userdata->camera_preview_port = camera->output[MMAL_CAMERA_PREVIEW_PORT]; userdata->camera_video_port = camera->output[MMAL_CAMERA_VIDEO_PORT]; userdata->camera_still_port = camera->output[MMAL_CAMERA_CAPTURE_PORT]; camera_preview_port = camera->output[MMAL_CAMERA_PREVIEW_PORT]; camera_video_port = camera->output[MMAL_CAMERA_VIDEO_PORT]; camera_still_port = camera->output[MMAL_CAMERA_CAPTURE_PORT]; { MMAL_PARAMETER_CAMERA_CONFIG_T cam_config = { { MMAL_PARAMETER_CAMERA_CONFIG, sizeof (cam_config)}, .max_stills_w = 1280, .max_stills_h = 720, .stills_yuv422 = 0, .one_shot_stills = 1, .max_preview_video_w = VIDEO_WIDTH, .max_preview_video_h = VIDEO_HEIGHT, .num_preview_video_frames = 3, .stills_capture_circular_buffer_height = 0, .fast_preview_resume = 0, .use_stc_timestamp = MMAL_PARAM_TIMESTAMP_MODE_RESET_STC }; mmal_port_parameter_set(camera->control, &cam_config.hdr); } // Setup camera preview port format format = camera_preview_port->format; format->encoding = MMAL_ENCODING_OPAQUE; format->encoding_variant = MMAL_ENCODING_I420; format->es->video.width = VIDEO_WIDTH; format->es->video.height = VIDEO_HEIGHT; format->es->video.crop.x = 0; format->es->video.crop.y = 0; format->es->video.crop.width = VIDEO_WIDTH; format->es->video.crop.height = VIDEO_HEIGHT; status = mmal_port_format_commit(camera_preview_port); if (status != MMAL_SUCCESS) { fprintf(stderr, "Error: camera viewfinder format couldn't be set\n"); return -1; } // Setup camera video port format mmal_format_copy(camera_video_port->format, camera_preview_port->format); format = camera_video_port->format; format->encoding = MMAL_ENCODING_I420; format->encoding_variant = MMAL_ENCODING_I420; format->es->video.width = VIDEO_WIDTH; format->es->video.height = VIDEO_HEIGHT; format->es->video.crop.x = 0; format->es->video.crop.y = 0; format->es->video.crop.width = VIDEO_WIDTH; format->es->video.crop.height = VIDEO_HEIGHT; format->es->video.frame_rate.num = VIDEO_FPS; format->es->video.frame_rate.den = 1; camera_video_port->buffer_size = format->es->video.width * format->es->video.height * 12 / 8; camera_video_port->buffer_num = 2; //fprintf(stderr, "INFO:camera video buffer_size = %d\n", camera_video_port->buffer_size); //fprintf(stderr, "INFO:camera video buffer_num = %d\n", camera_video_port->buffer_num); status = mmal_port_format_commit(camera_video_port); if (status != MMAL_SUCCESS) { fprintf(stderr, "Error: unable to commit camera video port format (%u)\n", status); return -1; } camera_video_port_pool = (MMAL_POOL_T *) mmal_port_pool_create(camera_video_port, camera_video_port->buffer_num, camera_video_port->buffer_size); userdata->camera_video_port_pool = camera_video_port_pool; camera_video_port->userdata = (struct MMAL_PORT_USERDATA_T *) userdata; status = mmal_port_enable(camera_video_port, camera_video_buffer_callback); if (status != MMAL_SUCCESS) { fprintf(stderr, "Error: unable to enable camera video port (%u)\n", status); return -1; } status = mmal_component_enable(camera); if (status != MMAL_SUCCESS) { fprintf(stderr, "Error: unable to enable camera (%u)\n", status); return -1; } fill_port_buffer(userdata->camera_video_port, userdata->camera_video_port_pool); if (mmal_port_parameter_set_boolean(camera_video_port, MMAL_PARAMETER_CAPTURE, 1) != MMAL_SUCCESS) { printf("%s: Failed to start capture\n", __func__); } //fprintf(stderr, "INFO: camera created\n"); return 0; }
bool CCamera::Init(int width, int height, int framerate, int num_levels, bool do_argb_conversion) { //init broadcom host - QUESTION: can this be called more than once?? bcm_host_init(); //store basic parameters Width = width; Height = height; FrameRate = framerate; // Set up the camera_parameters to default raspicamcontrol_set_defaults(&CameraParameters); MMAL_COMPONENT_T *camera = 0; MMAL_COMPONENT_T *splitter = 0; MMAL_CONNECTION_T* vid_to_split_connection = 0; MMAL_PORT_T *video_port = NULL; MMAL_STATUS_T status; CCameraOutput* outputs[4]; memset(outputs,0,sizeof(outputs)); //create the camera component camera = CreateCameraComponentAndSetupPorts(); if (!camera) goto error; //get the video port video_port = camera->output[MMAL_CAMERA_VIDEO_PORT]; video_port->buffer_num = 3; //if all we want is a single output with the raw data, don't need to make a splitter if(num_levels == 1 && !do_argb_conversion) { outputs[0] = new CCameraOutput(); if(!outputs[0]->Init(Width,Height,camera,MMAL_CAMERA_VIDEO_PORT,false)) { printf("Failed to initialize output\n"); goto error; } } else { //create the splitter component splitter = CreateSplitterComponentAndSetupPorts(video_port); if(!splitter) goto error; //create and enable a connection between the video output and the resizer input status = mmal_connection_create(&vid_to_split_connection, video_port, splitter->input[0], MMAL_CONNECTION_FLAG_TUNNELLING | MMAL_CONNECTION_FLAG_ALLOCATION_ON_INPUT); if (status != MMAL_SUCCESS) { printf("Failed to create connection\n"); goto error; } status = mmal_connection_enable(vid_to_split_connection); if (status != MMAL_SUCCESS) { printf("Failed to enable connection\n"); goto error; } //setup all the outputs for(int i = 0; i < num_levels; i++) { outputs[i] = new CCameraOutput(); if(!outputs[i]->Init(Width >> i,Height >> i,splitter,i,do_argb_conversion)) { printf("Failed to initialize output %d\n",i); goto error; } } } //begin capture if (mmal_port_parameter_set_boolean(video_port, MMAL_PARAMETER_CAPTURE, 1) != MMAL_SUCCESS) { printf("Failed to start capture\n"); goto error; } //store created info CameraComponent = camera; SplitterComponent = splitter; VidToSplitConn = vid_to_split_connection; memcpy(Outputs,outputs,sizeof(outputs)); //return success printf("Camera successfully created\n"); return true; error: if(vid_to_split_connection) mmal_connection_destroy(vid_to_split_connection); if(camera) mmal_component_destroy(camera); if(splitter) mmal_component_destroy(splitter); for(int i = 0; i < 4; i++) { if(outputs[i]) { outputs[i]->Release(); delete outputs[i]; } } return false; }
void MmalStillCamera::initialize(CameraMode cameraMode) { m_resolution = MmalUtil::get()->getClosestResolution(m_name, cameraMode); if (m_imageWidth != -1) { throw Exception("Camera is already initialized"); } m_imageWidth = m_resolution.width; m_imageHeight = m_resolution.height; m_callbackData = new MmalStillCallbackData(m_imageWidth, m_imageHeight, 3); // Handle the sensor properties real sensorWidth, sensorHeight, focalLength; MmalUtil::get()->getSensorProperties(m_name, sensorWidth, sensorHeight, focalLength); setSensorProperties(sensorWidth, sensorHeight, focalLength); createCameraComponent(); InfoLog << "Created camera" << Logger::ENDL; createPreview(); InfoLog << "Created preview" << Logger::ENDL; InfoLog << "Target Image Width: " << VCOS_ALIGN_UP(m_imageWidth, 32) << Logger::ENDL; InfoLog << "Target Image Height: " << VCOS_ALIGN_UP(m_imageHeight, 16) << Logger::ENDL; MMAL_STATUS_T status; m_targetPort = m_stillPort; // Create pool of buffer headers for the output port to consume m_pool = mmal_port_pool_create(m_targetPort, m_targetPort->buffer_num, m_targetPort->buffer_size); if (m_pool == NULL) { throw Exception("Failed to create buffer header pool for encoder output port"); } MMAL_CONNECTION_T *preview_connection = NULL; status = connect_ports(m_previewPort, m_preview->input[0], &preview_connection); if (status != MMAL_SUCCESS) { throw Exception("Error connecting preview port"); } m_targetPort->userdata = (struct MMAL_PORT_USERDATA_T *) m_callbackData; m_callbackData->image = NULL; m_callbackData->pool = m_pool; // Enable the encoder output port and tell it its callback function if (mmal_port_enable(m_targetPort, EncoderBufferCallback) != MMAL_SUCCESS) { ErrorLog << "Error enabling the encoder buffer callback" << Logger::ENDL; } // Send all the buffers to the encoder output port int num = mmal_queue_length(m_pool->queue); for (int q = 0; q < num; q++) { MMAL_BUFFER_HEADER_T *buffer = mmal_queue_get(m_pool->queue); if (buffer == NULL) { ErrorLog << "Unable to get buffer " << q << " from the pool" << Logger::ENDL; } if (mmal_port_send_buffer(m_targetPort, buffer) != MMAL_SUCCESS) { ErrorLog << "Unable to send a buffer " << q << " to encoder output port " << Logger::ENDL; } } // Enable burst mode if (m_burstModeEnabled) { if (mmal_port_parameter_set_boolean(m_camera->control, MMAL_PARAMETER_CAMERA_BURST_CAPTURE, 1) != MMAL_SUCCESS) { ErrorLog << "Error enabling burst mode" << Logger::ENDL; } InfoLog << "Enabled burst mode for still images" << Logger::ENDL; } InfoLog << "Initialized camera" << Logger::ENDL; }
void ofxRaspicam::takePhoto() { ofFile myFile; FILE *output_file = NULL; vcos_sleep(photo.timeout); // Open the file string fileName = ofToDataPath("photos/"+ ofGetTimestampString()+".jpg", true); char *toChar = const_cast<char*> ( fileName.c_str() ); photo.filename = toChar; ofLogVerbose() << "Opening output file" << fileName; output_file = fopen(photo.filename, "wb"); if (!output_file) { // Notify user, carry on but discarding encoded output buffers ofLogVerbose() << "Error opening output file"; } photo.add_exif_tags(); callback_data.file_handle = output_file; // We only capture if a filename was specified and it opened if (output_file) { // Send all the buffers to the encoder output port int num = mmal_queue_length(photo.encoder_pool->queue); int q; for (q=0;q<num;q++) { MMAL_BUFFER_HEADER_T *buffer = mmal_queue_get(photo.encoder_pool->queue); if (!buffer) { ofLogVerbose() << "Unable to get a required buffer " << q << " from pool queue"; } if (mmal_port_send_buffer(encoder_output_port, buffer)!= MMAL_SUCCESS) { ofLogVerbose() << "Unable to send a buffer to encoder output port " << q; } } ofLogVerbose() << "Starting capture"; if (mmal_port_parameter_set_boolean(camera_still_port, MMAL_PARAMETER_CAPTURE, 1) != MMAL_SUCCESS) { ofLogVerbose() << "Failed to start capture"; } else { // Wait for capture to complete // For some reason using vcos_semaphore_wait_timeout sometimes returns immediately with bad parameter error // even though it appears to be all correct, so reverting to untimed one until figure out why its erratic vcos_semaphore_wait(&callback_data.complete_semaphore); ofLogVerbose() << "Finished capture " << fileName; lastImage.loadImage(callback_data.photo->filename); } // Ensure we don't die if get callback with no open file callback_data.file_handle = NULL; fclose(output_file); } vcos_semaphore_delete(&callback_data.complete_semaphore); }
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; MMAL_BOOL_T eos_sent = MMAL_FALSE, eos_received = MMAL_FALSE; unsigned int count; if (argc < 2) { fprintf(stderr, "invalid arguments\n"); return -1; } 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"); /* Enable control port so we can receive events from the component */ decoder->control->userdata = (void *)&context; status = mmal_port_enable(decoder->control, control_callback); CHECK_STATUS(status, "failed to enable control port"); /* Get statistics on the input port */ MMAL_PARAMETER_CORE_STATISTICS_T stats = {{0}}; stats.hdr.id = MMAL_PARAMETER_CORE_STATISTICS; stats.hdr.size = sizeof(MMAL_PARAMETER_CORE_STATISTICS_T); status = mmal_port_parameter_get(decoder->input[0], &stats.hdr); CHECK_STATUS(status, "failed to get stats"); fprintf(stderr, "stats: %i, %i", stats.stats.buffer_count, stats.stats.max_delay); /* Set the zero-copy parameter on the input port */ MMAL_PARAMETER_BOOLEAN_T zc = {{MMAL_PARAMETER_ZERO_COPY, sizeof(zc)}, MMAL_TRUE}; status = mmal_port_parameter_set(decoder->input[0], &zc.hdr); fprintf(stderr, "status: %i\n", status); /* Set the zero-copy parameter on the output port */ status = mmal_port_parameter_set_boolean(decoder->output[0], MMAL_PARAMETER_ZERO_COPY, MMAL_TRUE); fprintf(stderr, "status: %i\n", status); /* 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"); /* Our decoder can do internal colour conversion, ask for a conversion to RGB565 */ MMAL_ES_FORMAT_T *format_out = decoder->output[0]->format; format_out->encoding = MMAL_ENCODING_RGB16; status = mmal_port_format_commit(decoder->output[0]); CHECK_STATUS(status, "failed to commit format"); /* Display the output port 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; !eos_received && 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); /* Check for errors */ if (context.status != MMAL_SUCCESS) break; /* Send data to decode to the input port of the video decoder */ if (!eos_sent && (buffer = mmal_queue_get(pool_in->queue)) != NULL) { SOURCE_READ_DATA_INTO_BUFFER(buffer); if(!buffer->length) eos_sent = MMAL_TRUE; buffer->flags = buffer->length ? 0 : MMAL_BUFFER_HEADER_FLAG_EOS; buffer->pts = buffer->dts = MMAL_TIME_UNKNOWN; 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. */ eos_received = buffer->flags & MMAL_BUFFER_HEADER_FLAG_EOS; if (buffer->cmd) fprintf(stderr, "received event %4.4s", (char *)&buffer->cmd); else fprintf(stderr, "decoded frame (flags %x)\n", buffer->flags); 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; }
/* Registers a callback on the camera preview port to receive * notifications of new frames. * This must be called before rapitex_start and may not be called again * without calling raspitex_destroy first. * * @param state Pointer to the GL preview state. * @param port Pointer to the camera preview port * @return Zero if successful. */ int raspitex_configure_preview_port(RASPITEX_STATE *state, MMAL_PORT_T *preview_port) { MMAL_STATUS_T status; vcos_log_trace("%s port %p", VCOS_FUNCTION, preview_port); /* Enable ZERO_COPY mode on the preview port which instructs MMAL to only * pass the 4-byte opaque buffer handle instead of the contents of the opaque * buffer. * The opaque handle is resolved on VideoCore by the GL driver when the EGL * image is created. */ status = mmal_port_parameter_set_boolean(preview_port, MMAL_PARAMETER_ZERO_COPY, MMAL_TRUE); if (status != MMAL_SUCCESS) { vcos_log_error("Failed to enable zero copy on camera preview port"); goto end; } status = mmal_port_format_commit(preview_port); if (status != MMAL_SUCCESS) { vcos_log_error("camera viewfinder format couldn't be set"); goto end; } /* For GL a pool of opaque buffer handles must be allocated in the client. * These buffers are used to create the EGL images. */ state->preview_port = preview_port; preview_port->buffer_num = preview_port->buffer_num_recommended; preview_port->buffer_size = preview_port->buffer_size_recommended; vcos_log_trace("Creating buffer pool for GL renderer num %d size %d", preview_port->buffer_num, preview_port->buffer_size); /* Pool + queue to hold preview frames */ state->preview_pool = mmal_port_pool_create(preview_port, preview_port->buffer_num, preview_port->buffer_size); if (! state->preview_pool) { vcos_log_error("Error allocating pool"); status = MMAL_ENOMEM; goto end; } /* Place filled buffers from the preview port in a queue to render */ state->preview_queue = mmal_queue_create(); if (! state->preview_queue) { vcos_log_error("Error allocating queue"); status = MMAL_ENOMEM; goto end; } /* Enable preview port callback */ preview_port->userdata = (struct MMAL_PORT_USERDATA_T*) state; status = mmal_port_enable(preview_port, preview_output_cb); if (status != MMAL_SUCCESS) { vcos_log_error("Failed to camera preview port"); goto end; } end: return (status == MMAL_SUCCESS ? 0 : -1); }
int main (int argc, char* argv[]) { MMAL_STATUS_T status; int i, max, fd, length, cam_setting; unsigned long int cam_setting_long; char readbuf[20]; char *filename_temp, *filename_temp2, *cmd_temp; bcm_host_init(); // // read arguments // unsigned char of_set = 0; for(i=1; i<argc; i++) { if(strcmp(argv[i], "--version") == 0) { printf("RaspiMJPEG Version "); printf(VERSION); printf("\n"); exit(0); } else if(strcmp(argv[i], "-w") == 0) { i++; width = atoi(argv[i]); } else if(strcmp(argv[i], "-h") == 0) { i++; height = atoi(argv[i]); } else if(strcmp(argv[i], "-wp") == 0) { i++; width_pic = atoi(argv[i]); } else if(strcmp(argv[i], "-hp") == 0) { i++; height_pic = atoi(argv[i]); } else if(strcmp(argv[i], "-q") == 0) { i++; quality = atoi(argv[i]); } else if(strcmp(argv[i], "-d") == 0) { i++; divider = atoi(argv[i]); } else if(strcmp(argv[i], "-p") == 0) { mp4box = 1; } else if(strcmp(argv[i], "-ic") == 0) { i++; image2_cnt = atoi(argv[i]); } else if(strcmp(argv[i], "-vc") == 0) { i++; video_cnt = atoi(argv[i]); } else if(strcmp(argv[i], "-of") == 0) { i++; jpeg_filename = argv[i]; of_set = 1; } else if(strcmp(argv[i], "-if") == 0) { i++; jpeg2_filename = argv[i]; of_set = 1; } else if(strcmp(argv[i], "-cf") == 0) { i++; pipe_filename = argv[i]; } else if(strcmp(argv[i], "-vf") == 0) { i++; h264_filename = argv[i]; } else if(strcmp(argv[i], "-sf") == 0) { i++; status_filename = argv[i]; } else if(strcmp(argv[i], "-pa") == 0) { autostart = 0; idle = 1; } else if(strcmp(argv[i], "-md") == 0) { motion_detection = 1; } else if(strcmp(argv[i], "-fp") == 0) { preview_mode = RES_4_3; } else if(strcmp(argv[i], "-audio") == 0) { audio_mode = 1; } else error("Invalid arguments"); } if(!of_set) error("Output file not specified"); // // init // if(autostart) start_all(); if(motion_detection) { if(system("motion") == -1) error("Could not start Motion"); } // // run // if(autostart) { if(pipe_filename != 0) printf("MJPEG streaming, ready to receive commands\n"); else printf("MJPEG streaming\n"); } else { if(pipe_filename != 0) printf("MJPEG idle, ready to receive commands\n"); else printf("MJPEG idle\n"); } struct sigaction action; memset(&action, 0, sizeof(struct sigaction)); action.sa_handler = term; sigaction(SIGTERM, &action, NULL); sigaction(SIGINT, &action, NULL); if(status_filename != 0) { status_file = fopen(status_filename, "w"); if(!status_file) error("Could not open/create status-file"); if(autostart) { if(!motion_detection) { fprintf(status_file, "ready"); } else fprintf(status_file, "md_ready"); } else fprintf(status_file, "halted"); fclose(status_file); } while(running) { if(pipe_filename != 0) { fd = open(pipe_filename, O_RDONLY | O_NONBLOCK); if(fd < 0) error("Could not open PIPE"); fcntl(fd, F_SETFL, 0); length = read(fd, readbuf, 20); close(fd); if(length) { if((readbuf[0]=='p') && (readbuf[1]=='m')) { stop_all(); readbuf[0] = ' '; readbuf[1] = ' '; readbuf[length] = 0; if(strcmp(readbuf, " 4_3") == 0) preview_mode = RES_4_3; else if(strcmp(readbuf, " 16_9_STD") == 0) preview_mode = RES_16_9_STD; else if(strcmp(readbuf, " 16_9_WIDE") == 0) preview_mode = RES_16_9_WIDE; start_all(); printf("Changed preview mode\n"); if(status_filename != 0) { status_file = fopen(status_filename, "w"); fprintf(status_file, "ready"); fclose(status_file); } } else if((readbuf[0]=='c') && (readbuf[1]=='a')) { if(readbuf[3]=='1') { if(!capturing) { status = mmal_component_enable(h264encoder); if(status != MMAL_SUCCESS) error("Could not enable h264encoder"); pool_h264encoder = mmal_port_pool_create(h264encoder->output[0], h264encoder->output[0]->buffer_num, h264encoder->output[0]->buffer_size); if(!pool_h264encoder) error("Could not create pool"); status = mmal_connection_create(&con_cam_h264, camera->output[1], h264encoder->input[0], MMAL_CONNECTION_FLAG_TUNNELLING | MMAL_CONNECTION_FLAG_ALLOCATION_ON_INPUT); if(status != MMAL_SUCCESS) error("Could not create connecton camera -> video converter"); status = mmal_connection_enable(con_cam_h264); if(status != MMAL_SUCCESS) error("Could not enable connection camera -> video converter"); currTime = time(NULL); localTime = localtime (&currTime); if(mp4box) { asprintf(&filename_temp, h264_filename, video_cnt, localTime->tm_year+1900, localTime->tm_mon+1, localTime->tm_mday, localTime->tm_hour, localTime->tm_min, localTime->tm_sec); asprintf(&filename_temp2, "%s.h264", filename_temp); } else { asprintf(&filename_temp2, h264_filename, video_cnt, localTime->tm_year+1900, localTime->tm_mon+1, localTime->tm_mday, localTime->tm_hour, localTime->tm_min, localTime->tm_sec); } h264output_file = fopen(filename_temp2, "wb"); free(filename_temp2); if(mp4box) { if(audio_mode) { asprintf(&cmd_temp, "/usr/bin/arecord -q -D hw:1,0 -f S16_LE -t wav | /usr/bin/lame - %s.mp3 -S &", filename_temp); printf("Audio recording with \"%s\\n", cmd_temp); if(system(cmd_temp) == -1) error("Could not start audio recording"); } free(filename_temp); } if(!h264output_file) error("Could not open/create video-file"); status = mmal_port_enable(h264encoder->output[0], h264encoder_buffer_callback); if(status != MMAL_SUCCESS) error("Could not enable video port"); max = mmal_queue_length(pool_h264encoder->queue); for(i=0;i<max;i++) { MMAL_BUFFER_HEADER_T *h264buffer = mmal_queue_get(pool_h264encoder->queue); if(!h264buffer) error("Could not create video pool header"); status = mmal_port_send_buffer(h264encoder->output[0], h264buffer); if(status != MMAL_SUCCESS) error("Could not send buffers to video port"); } mmal_port_parameter_set_boolean(camera->output[1], MMAL_PARAMETER_CAPTURE, 1); if(status != MMAL_SUCCESS) error("Could not start capture"); printf("Capturing started\n"); if(status_filename != 0) { status_file = fopen(status_filename, "w"); if(!motion_detection) fprintf(status_file, "video"); else fprintf(status_file, "md_video"); fclose(status_file); } capturing = 1; } } else { if(capturing) { mmal_port_parameter_set_boolean(camera->output[1], MMAL_PARAMETER_CAPTURE, 0); if(status != MMAL_SUCCESS) error("Could not stop capture"); status = mmal_port_disable(h264encoder->output[0]); if(status != MMAL_SUCCESS) error("Could not disable video port"); status = mmal_connection_destroy(con_cam_h264); if(status != MMAL_SUCCESS) error("Could not destroy connection camera -> video encoder"); mmal_port_pool_destroy(h264encoder->output[0], pool_h264encoder); if(status != MMAL_SUCCESS) error("Could not destroy video buffer pool"); status = mmal_component_disable(h264encoder); if(status != MMAL_SUCCESS) error("Could not disable video converter"); fclose(h264output_file); h264output_file = NULL; printf("Capturing stopped\n"); if(mp4box) { printf("Boxing started\n"); status_file = fopen(status_filename, "w"); if(!motion_detection) fprintf(status_file, "boxing"); else fprintf(status_file, "md_boxing"); fclose(status_file); asprintf(&filename_temp, h264_filename, video_cnt, localTime->tm_year+1900, localTime->tm_mon+1, localTime->tm_mday, localTime->tm_hour, localTime->tm_min, localTime->tm_sec); if(audio_mode) { asprintf(&cmd_temp, "/usr/bin/killall arecord > /dev/null"); if(system(cmd_temp) == -1) error("Could not stop audio recording"); free(cmd_temp); asprintf(&cmd_temp, "MP4Box -fps 25 -add %s.h264 -add %s.mp3 %s > /dev/null", filename_temp, filename_temp, filename_temp); } else { asprintf(&cmd_temp, "MP4Box -fps 25 -add %s.h264 %s > /dev/null", filename_temp, filename_temp); } if(system(cmd_temp) == -1) error("Could not start MP4Box"); asprintf(&filename_temp2, "%s.h264", filename_temp); remove(filename_temp2); free(filename_temp2); if (audio_mode) { asprintf(&filename_temp2, "%s.mp3", filename_temp); remove(filename_temp2); free(filename_temp2); } free(filename_temp); free(cmd_temp); printf("Boxing stopped\n"); } video_cnt++; if(status_filename != 0) { status_file = fopen(status_filename, "w"); if(!motion_detection) fprintf(status_file, "ready"); else fprintf(status_file, "md_ready"); fclose(status_file); } capturing = 0; } } } else if((readbuf[0]=='i') && (readbuf[1]=='m')) { capt_img(); } else if((readbuf[0]=='t') && (readbuf[1]=='l')) { readbuf[0] = ' '; readbuf[1] = ' '; readbuf[length] = 0; time_between_pic = atoi(readbuf); if(time_between_pic) { if(status_filename != 0) { status_file = fopen(status_filename, "w"); fprintf(status_file, "timelapse"); fclose(status_file); } timelapse = 1; printf("Timelapse started\n"); } else { if(status_filename != 0) { status_file = fopen(status_filename, "w"); fprintf(status_file, "ready"); fclose(status_file); } timelapse = 0; printf("Timelapse stopped\n"); } } else if((readbuf[0]=='s') && (readbuf[1]=='h')) { readbuf[0] = ' '; readbuf[1] = ' '; readbuf[length] = 0; cam_setting = atoi(readbuf); MMAL_RATIONAL_T value = {cam_setting, 100}; status = mmal_port_parameter_set_rational(camera->control, MMAL_PARAMETER_SHARPNESS, value); if(status != MMAL_SUCCESS) error("Could not set sharpness"); printf("Sharpness: %d\n", cam_setting); } else if((readbuf[0]=='c') && (readbuf[1]=='o')) { readbuf[0] = ' '; readbuf[1] = ' '; readbuf[length] = 0; cam_setting = atoi(readbuf); MMAL_RATIONAL_T value = {cam_setting, 100}; status = mmal_port_parameter_set_rational(camera->control, MMAL_PARAMETER_CONTRAST, value); if(status != MMAL_SUCCESS) error("Could not set contrast"); printf("Contrast: %d\n", cam_setting); } else if((readbuf[0]=='b') && (readbuf[1]=='r')) { readbuf[0] = ' '; readbuf[1] = ' '; readbuf[length] = 0; cam_setting = atoi(readbuf); MMAL_RATIONAL_T value = {cam_setting, 100}; status = mmal_port_parameter_set_rational(camera->control, MMAL_PARAMETER_BRIGHTNESS, value); if(status != MMAL_SUCCESS) error("Could not set brightness"); printf("Brightness: %d\n", cam_setting); } else if((readbuf[0]=='s') && (readbuf[1]=='a')) { readbuf[0] = ' '; readbuf[1] = ' '; readbuf[length] = 0; cam_setting = atoi(readbuf); MMAL_RATIONAL_T value = {cam_setting, 100}; status = mmal_port_parameter_set_rational(camera->control, MMAL_PARAMETER_SATURATION, value); if(status != MMAL_SUCCESS) error("Could not set saturation"); printf("Saturation: %d\n", cam_setting); } else if((readbuf[0]=='i') && (readbuf[1]=='s')) { readbuf[0] = ' '; readbuf[1] = ' '; readbuf[length] = 0; cam_setting = atoi(readbuf); status = mmal_port_parameter_set_uint32(camera->control, MMAL_PARAMETER_ISO, cam_setting); if(status != MMAL_SUCCESS) error("Could not set ISO"); printf("ISO: %d\n", cam_setting); } else if((readbuf[0]=='v') && (readbuf[1]=='s')) { if(readbuf[3]=='1') { status = mmal_port_parameter_set_boolean(camera->control, MMAL_PARAMETER_VIDEO_STABILISATION, 1); printf("Video Stabilisation ON\n"); } else { status = mmal_port_parameter_set_boolean(camera->control, MMAL_PARAMETER_VIDEO_STABILISATION, 0); printf("Video Stabilisation OFF\n"); } if(status != MMAL_SUCCESS) error("Could not set video stabilisation"); } else if((readbuf[0]=='e') && (readbuf[1]=='c')) { readbuf[0] = ' '; readbuf[1] = ' '; readbuf[length] = 0; cam_setting = atoi(readbuf); status = mmal_port_parameter_set_int32(camera->control, MMAL_PARAMETER_EXPOSURE_COMP, cam_setting); if(status != MMAL_SUCCESS) error("Could not set exposure compensation"); printf("Exposure Compensation: %d\n", cam_setting); } else if((readbuf[0]=='e') && (readbuf[1]=='m')) { readbuf[0] = ' '; readbuf[1] = ' '; readbuf[length] = 0; MMAL_PARAM_EXPOSUREMODE_T mode = MMAL_PARAM_EXPOSUREMODE_OFF; if(strcmp(readbuf, " auto") == 0) mode = MMAL_PARAM_EXPOSUREMODE_AUTO; else if(strcmp(readbuf, " night") == 0) mode = MMAL_PARAM_EXPOSUREMODE_NIGHT; else if(strcmp(readbuf, " nightpreview") == 0) mode = MMAL_PARAM_EXPOSUREMODE_NIGHTPREVIEW; else if(strcmp(readbuf, " backlight") == 0) mode = MMAL_PARAM_EXPOSUREMODE_BACKLIGHT; else if(strcmp(readbuf, " spotlight") == 0) mode = MMAL_PARAM_EXPOSUREMODE_SPOTLIGHT; else if(strcmp(readbuf, " sports") == 0) mode = MMAL_PARAM_EXPOSUREMODE_SPORTS; else if(strcmp(readbuf, " snow") == 0) mode = MMAL_PARAM_EXPOSUREMODE_SNOW; else if(strcmp(readbuf, " beach") == 0) mode = MMAL_PARAM_EXPOSUREMODE_BEACH; else if(strcmp(readbuf, " verylong") == 0) mode = MMAL_PARAM_EXPOSUREMODE_VERYLONG; else if(strcmp(readbuf, " fixedfps") == 0) mode = MMAL_PARAM_EXPOSUREMODE_FIXEDFPS; else if(strcmp(readbuf, " antishake") == 0) mode = MMAL_PARAM_EXPOSUREMODE_ANTISHAKE; else if(strcmp(readbuf, " fireworks") == 0) mode = MMAL_PARAM_EXPOSUREMODE_FIREWORKS; MMAL_PARAMETER_EXPOSUREMODE_T exp_mode = {{MMAL_PARAMETER_EXPOSURE_MODE,sizeof(exp_mode)}, mode}; status = mmal_port_parameter_set(camera->control, &exp_mode.hdr); if(status != MMAL_SUCCESS) error("Could not set exposure mode"); printf("Exposure mode changed\n"); } else if((readbuf[0]=='w') && (readbuf[1]=='b')) { readbuf[0] = ' '; readbuf[1] = ' '; readbuf[length] = 0; MMAL_PARAM_AWBMODE_T awb_mode = MMAL_PARAM_AWBMODE_OFF; if(strcmp(readbuf, " auto") == 0) awb_mode = MMAL_PARAM_AWBMODE_AUTO; else if(strcmp(readbuf, " auto") == 0) awb_mode = MMAL_PARAM_AWBMODE_AUTO; else if(strcmp(readbuf, " sun") == 0) awb_mode = MMAL_PARAM_AWBMODE_SUNLIGHT; else if(strcmp(readbuf, " cloudy") == 0) awb_mode = MMAL_PARAM_AWBMODE_CLOUDY; else if(strcmp(readbuf, " shade") == 0) awb_mode = MMAL_PARAM_AWBMODE_SHADE; else if(strcmp(readbuf, " tungsten") == 0) awb_mode = MMAL_PARAM_AWBMODE_TUNGSTEN; else if(strcmp(readbuf, " fluorescent") == 0) awb_mode = MMAL_PARAM_AWBMODE_FLUORESCENT; else if(strcmp(readbuf, " incandescent") == 0) awb_mode = MMAL_PARAM_AWBMODE_INCANDESCENT; else if(strcmp(readbuf, " flash") == 0) awb_mode = MMAL_PARAM_AWBMODE_FLASH; else if(strcmp(readbuf, " horizon") == 0) awb_mode = MMAL_PARAM_AWBMODE_HORIZON; MMAL_PARAMETER_AWBMODE_T param = {{MMAL_PARAMETER_AWB_MODE,sizeof(param)}, awb_mode}; status = mmal_port_parameter_set(camera->control, ¶m.hdr); if(status != MMAL_SUCCESS) error("Could not set white balance"); printf("White balance changed\n"); } else if((readbuf[0]=='r') && (readbuf[1]=='o')) { readbuf[0] = ' '; readbuf[1] = ' '; readbuf[length] = 0; cam_setting = atoi(readbuf); status = mmal_port_parameter_set_int32(camera->output[0], MMAL_PARAMETER_ROTATION, cam_setting); if(status != MMAL_SUCCESS) error("Could not set rotation (0)"); status = mmal_port_parameter_set_int32(camera->output[1], MMAL_PARAMETER_ROTATION, cam_setting); if(status != MMAL_SUCCESS) error("Could not set rotation (1)"); status = mmal_port_parameter_set_int32(camera->output[2], MMAL_PARAMETER_ROTATION, cam_setting); if(status != MMAL_SUCCESS) error("Could not set rotation (2)"); printf("Rotation: %d\n", cam_setting); } else if((readbuf[0]=='q') && (readbuf[1]=='u')) { readbuf[0] = ' '; readbuf[1] = ' '; readbuf[length] = 0; cam_setting = atoi(readbuf); status = mmal_port_parameter_set_uint32(jpegencoder2->output[0], MMAL_PARAMETER_JPEG_Q_FACTOR, cam_setting); if(status != MMAL_SUCCESS) error("Could not set quality"); printf("Quality: %d\n", cam_setting); } else if((readbuf[0]=='b') && (readbuf[1]=='i')) { readbuf[0] = ' '; readbuf[1] = ' '; readbuf[length] = 0; cam_setting_long = strtoull(readbuf, NULL, 0); h264encoder->output[0]->format->bitrate = cam_setting_long; status = mmal_port_format_commit(h264encoder->output[0]); if(status != MMAL_SUCCESS) error("Could not set bitrate"); printf("Bitrate: %lu\n", cam_setting_long); } else if((readbuf[0]=='r') && (readbuf[1]=='u')) { if(readbuf[3]=='0') { stop_all(); idle = 1; printf("Stream halted\n"); if(status_filename != 0) { status_file = fopen(status_filename, "w"); fprintf(status_file, "halted"); fclose(status_file); } } else { start_all(); idle = 0; printf("Stream continued\n"); if(status_filename != 0) { status_file = fopen(status_filename, "w"); fprintf(status_file, "ready"); fclose(status_file); } } } else if((readbuf[0]=='m') && (readbuf[1]=='d')) { if(readbuf[3]=='0') { motion_detection = 0; if(system("killall motion") == -1) error("Could not stop Motion"); printf("Motion detection stopped\n"); if(status_filename != 0) { status_file = fopen(status_filename, "w"); fprintf(status_file, "ready"); fclose(status_file); } } else { motion_detection = 1; if(system("motion") == -1) error("Could not start Motion"); printf("Motion detection started\n"); if(status_filename != 0) { status_file = fopen(status_filename, "w"); fprintf(status_file, "md_ready"); fclose(status_file); } } } } } if(timelapse) { tl_cnt++; if(tl_cnt >= time_between_pic) { if(capturing == 0) { capt_img(); tl_cnt = 0; } } } usleep(100000); } printf("SIGINT/SIGTERM received, stopping\n"); // // tidy up // if(!idle) stop_all(); return 0; }
void start_all (void) { MMAL_STATUS_T status; MMAL_ES_FORMAT_T *format; int max, i; unsigned int video_width, video_height; // // get resolution // if(preview_mode == RES_16_9_STD) { video_width = 1920; video_height = 1080; } else if(preview_mode == RES_16_9_WIDE) { video_width = 1296; video_height = 730; } else { video_width = 1296; video_height = 976; } // // create camera // status = mmal_component_create(MMAL_COMPONENT_DEFAULT_CAMERA, &camera); if(status != MMAL_SUCCESS) error("Could not create camera"); status = mmal_port_enable(camera->control, camera_control_callback); if(status != MMAL_SUCCESS) error("Could not enable camera control port"); MMAL_PARAMETER_CAMERA_CONFIG_T cam_config = { {MMAL_PARAMETER_CAMERA_CONFIG, sizeof(cam_config)}, .max_stills_w = 2592, .max_stills_h = 1944, .stills_yuv422 = 0, .one_shot_stills = 1, .max_preview_video_w = video_width, .max_preview_video_h = video_height, .num_preview_video_frames = 3, .stills_capture_circular_buffer_height = 0, .fast_preview_resume = 0, .use_stc_timestamp = MMAL_PARAM_TIMESTAMP_MODE_RESET_STC }; mmal_port_parameter_set(camera->control, &cam_config.hdr); format = camera->output[0]->format; format->es->video.width = video_width; format->es->video.height = video_height; format->es->video.crop.x = 0; format->es->video.crop.y = 0; format->es->video.crop.width = video_width; format->es->video.crop.height = video_height; format->es->video.frame_rate.num = 0; format->es->video.frame_rate.den = 1; status = mmal_port_format_commit(camera->output[0]); if(status != MMAL_SUCCESS) error("Coult not set preview format"); format = camera->output[1]->format; format->encoding_variant = MMAL_ENCODING_I420; format->encoding = MMAL_ENCODING_OPAQUE; format->es->video.width = video_width; format->es->video.height = video_height; format->es->video.crop.x = 0; format->es->video.crop.y = 0; format->es->video.crop.width = video_width; format->es->video.crop.height = video_height; format->es->video.frame_rate.num = 25; format->es->video.frame_rate.den = 1; status = mmal_port_format_commit(camera->output[1]); if(status != MMAL_SUCCESS) error("Could not set video format"); if(camera->output[1]->buffer_num < 3) camera->output[1]->buffer_num = 3; format = camera->output[2]->format; format->encoding = MMAL_ENCODING_OPAQUE; format->es->video.width = 2592; format->es->video.height = 1944; format->es->video.crop.x = 0; format->es->video.crop.y = 0; format->es->video.crop.width = 2592; format->es->video.crop.height = 1944; format->es->video.frame_rate.num = 0; format->es->video.frame_rate.den = 1; status = mmal_port_format_commit(camera->output[2]); if(status != MMAL_SUCCESS) error("Could not set still format"); if(camera->output[2]->buffer_num < 3) camera->output[2]->buffer_num = 3; status = mmal_component_enable(camera); if(status != MMAL_SUCCESS) error("Could not enable camera"); // // create jpeg-encoder // status = mmal_component_create(MMAL_COMPONENT_DEFAULT_IMAGE_ENCODER, &jpegencoder); if(status != MMAL_SUCCESS && status != MMAL_ENOSYS) error("Could not create image encoder"); mmal_format_copy(jpegencoder->output[0]->format, jpegencoder->input[0]->format); jpegencoder->output[0]->format->encoding = MMAL_ENCODING_JPEG; jpegencoder->output[0]->buffer_size = jpegencoder->output[0]->buffer_size_recommended; if(jpegencoder->output[0]->buffer_size < jpegencoder->output[0]->buffer_size_min) jpegencoder->output[0]->buffer_size = jpegencoder->output[0]->buffer_size_min; jpegencoder->output[0]->buffer_num = jpegencoder->output[0]->buffer_num_recommended; if(jpegencoder->output[0]->buffer_num < jpegencoder->output[0]->buffer_num_min) jpegencoder->output[0]->buffer_num = jpegencoder->output[0]->buffer_num_min; status = mmal_port_format_commit(jpegencoder->output[0]); if(status != MMAL_SUCCESS) error("Could not set image format"); status = mmal_port_parameter_set_uint32(jpegencoder->output[0], MMAL_PARAMETER_JPEG_Q_FACTOR, quality); if(status != MMAL_SUCCESS) error("Could not set jpeg quality"); status = mmal_component_enable(jpegencoder); if(status != MMAL_SUCCESS) error("Could not enable image encoder"); pool_jpegencoder = mmal_port_pool_create(jpegencoder->output[0], jpegencoder->output[0]->buffer_num, jpegencoder->output[0]->buffer_size); if(!pool_jpegencoder) error("Could not create image buffer pool"); // // create second jpeg-encoder // status = mmal_component_create(MMAL_COMPONENT_DEFAULT_IMAGE_ENCODER, &jpegencoder2); if(status != MMAL_SUCCESS && status != MMAL_ENOSYS) error("Could not create image encoder 2"); mmal_format_copy(jpegencoder2->output[0]->format, jpegencoder2->input[0]->format); jpegencoder2->output[0]->format->encoding = MMAL_ENCODING_JPEG; jpegencoder2->output[0]->buffer_size = jpegencoder2->output[0]->buffer_size_recommended; if(jpegencoder2->output[0]->buffer_size < jpegencoder2->output[0]->buffer_size_min) jpegencoder2->output[0]->buffer_size = jpegencoder2->output[0]->buffer_size_min; jpegencoder2->output[0]->buffer_num = jpegencoder2->output[0]->buffer_num_recommended; if(jpegencoder2->output[0]->buffer_num < jpegencoder2->output[0]->buffer_num_min) jpegencoder2->output[0]->buffer_num = jpegencoder2->output[0]->buffer_num_min; status = mmal_port_format_commit(jpegencoder2->output[0]); if(status != MMAL_SUCCESS) error("Could not set image format 2"); status = mmal_port_parameter_set_uint32(jpegencoder2->output[0], MMAL_PARAMETER_JPEG_Q_FACTOR, 85); if(status != MMAL_SUCCESS) error("Could not set jpeg quality 2"); status = mmal_component_enable(jpegencoder2); if(status != MMAL_SUCCESS) error("Could not enable image encoder 2"); pool_jpegencoder2 = mmal_port_pool_create(jpegencoder2->output[0], jpegencoder2->output[0]->buffer_num, jpegencoder2->output[0]->buffer_size); if(!pool_jpegencoder2) error("Could not create image buffer pool 2"); // // create h264-encoder // status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_ENCODER, &h264encoder); if(status != MMAL_SUCCESS && status != MMAL_ENOSYS) error("Could not create video encoder"); mmal_format_copy(h264encoder->output[0]->format, h264encoder->input[0]->format); h264encoder->output[0]->format->encoding = MMAL_ENCODING_H264; h264encoder->output[0]->format->bitrate = 17000000; h264encoder->output[0]->buffer_size = h264encoder->output[0]->buffer_size_recommended; if(h264encoder->output[0]->buffer_size < h264encoder->output[0]->buffer_size_min) h264encoder->output[0]->buffer_size = h264encoder->output[0]->buffer_size_min; h264encoder->output[0]->buffer_num = h264encoder->output[0]->buffer_num_recommended; if(h264encoder->output[0]->buffer_num < h264encoder->output[0]->buffer_num_min) h264encoder->output[0]->buffer_num = h264encoder->output[0]->buffer_num_min; h264encoder->output[0]->format->es->video.frame_rate.num = 0; h264encoder->output[0]->format->es->video.frame_rate.den = 1; status = mmal_port_format_commit(h264encoder->output[0]); if(status != MMAL_SUCCESS) error("Could not set video format"); MMAL_PARAMETER_UINT32_T param2 = {{ MMAL_PARAMETER_VIDEO_ENCODE_INITIAL_QUANT, sizeof(param2)}, 25}; status = mmal_port_parameter_set(h264encoder->output[0], ¶m2.hdr); if(status != MMAL_SUCCESS) error("Could not set video quantisation"); MMAL_PARAMETER_UINT32_T param3 = {{ MMAL_PARAMETER_VIDEO_ENCODE_QP_P, sizeof(param3)}, 31}; status = mmal_port_parameter_set(h264encoder->output[0], ¶m3.hdr); if(status != MMAL_SUCCESS) error("Could not set video quantisation"); MMAL_PARAMETER_VIDEO_PROFILE_T param4; param4.hdr.id = MMAL_PARAMETER_PROFILE; param4.hdr.size = sizeof(param4); param4.profile[0].profile = MMAL_VIDEO_PROFILE_H264_HIGH; param4.profile[0].level = MMAL_VIDEO_LEVEL_H264_4; status = mmal_port_parameter_set(h264encoder->output[0], ¶m4.hdr); if(status != MMAL_SUCCESS) error("Could not set video port format"); status = mmal_port_parameter_set_boolean(h264encoder->input[0], MMAL_PARAMETER_VIDEO_IMMUTABLE_INPUT, 1); if(status != MMAL_SUCCESS) error("Could not set immutable flag"); status = mmal_port_parameter_set_boolean(h264encoder->output[0], MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER, 0); if(status != MMAL_SUCCESS) error("Could not set inline flag"); // // create image-resizer // status = mmal_component_create("vc.ril.resize", &resizer); if(status != MMAL_SUCCESS && status != MMAL_ENOSYS) error("Could not create image resizer"); format = resizer->output[0]->format; format->es->video.width = (preview_mode==RES_4_3) ? width_pic : width; format->es->video.height = (preview_mode==RES_4_3) ? height_pic : height; format->es->video.crop.x = 0; format->es->video.crop.y = 0; format->es->video.crop.width = (preview_mode==RES_4_3) ? width_pic : width; format->es->video.crop.height = (preview_mode==RES_4_3) ? height_pic : height; format->es->video.frame_rate.num = 30; format->es->video.frame_rate.den = 1; status = mmal_port_format_commit(resizer->output[0]); if(status != MMAL_SUCCESS) error("Could not set image resizer output"); status = mmal_component_enable(resizer); if(status != MMAL_SUCCESS) error("Could not enable image resizer"); // // connect // status = mmal_connection_create(&con_cam_res, camera->output[0], resizer->input[0], MMAL_CONNECTION_FLAG_TUNNELLING | MMAL_CONNECTION_FLAG_ALLOCATION_ON_INPUT); if(status != MMAL_SUCCESS) error("Could not create connection camera -> resizer"); status = mmal_connection_enable(con_cam_res); if(status != MMAL_SUCCESS) error("Could not enable connection camera -> resizer"); status = mmal_connection_create(&con_res_jpeg, resizer->output[0], jpegencoder->input[0], MMAL_CONNECTION_FLAG_TUNNELLING | MMAL_CONNECTION_FLAG_ALLOCATION_ON_INPUT); if(status != MMAL_SUCCESS) error("Could not create connection resizer -> encoder"); status = mmal_connection_enable(con_res_jpeg); if(status != MMAL_SUCCESS) error("Could not enable connection resizer -> encoder"); status = mmal_port_enable(jpegencoder->output[0], jpegencoder_buffer_callback); if(status != MMAL_SUCCESS) error("Could not enable jpeg port"); max = mmal_queue_length(pool_jpegencoder->queue); for(i=0;i<max;i++) { MMAL_BUFFER_HEADER_T *jpegbuffer = mmal_queue_get(pool_jpegencoder->queue); if(!jpegbuffer) error("Could not create jpeg buffer header"); status = mmal_port_send_buffer(jpegencoder->output[0], jpegbuffer); if(status != MMAL_SUCCESS) error("Could not send buffers to jpeg port"); } status = mmal_connection_create(&con_cam_jpeg, camera->output[2], jpegencoder2->input[0], MMAL_CONNECTION_FLAG_TUNNELLING | MMAL_CONNECTION_FLAG_ALLOCATION_ON_INPUT); if(status != MMAL_SUCCESS) error("Could not create connection camera -> encoder"); status = mmal_connection_enable(con_cam_jpeg); if(status != MMAL_SUCCESS) error("Could not enable connection camera -> encoder"); status = mmal_port_enable(jpegencoder2->output[0], jpegencoder2_buffer_callback); if(status != MMAL_SUCCESS) error("Could not enable jpeg port 2"); max = mmal_queue_length(pool_jpegencoder2->queue); for(i=0;i<max;i++) { MMAL_BUFFER_HEADER_T *jpegbuffer2 = mmal_queue_get(pool_jpegencoder2->queue); if(!jpegbuffer2) error("Could not create jpeg buffer header 2"); status = mmal_port_send_buffer(jpegencoder2->output[0], jpegbuffer2); if(status != MMAL_SUCCESS) error("Could not send buffers to jpeg port 2"); } }
void video_h264_encoder_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *mmalbuf) { VideoCircularBuffer *vcb = &video_circular_buffer; MotionFrame *mf = &motion_frame; KeyFrame *kf; int i, end_space, t_elapsed, event = 0; int t_usec, dt_frame; boolean force_stop; time_t t_cur = pikrellcam.t_now; static int fps_count, pause_frame_count_adjust; static time_t t_sec, t_prev; uint64_t t64_now; static int t_annotate, t_key_frame; static struct timeval tv; static uint64_t t0_stc, pts_prev; static boolean prev_pause; if (vcb->state == VCB_STATE_RESTARTING) { if (mmalbuf->flags & MMAL_BUFFER_HEADER_FLAG_CONFIG) h264_header_save(mmalbuf); fps_count = 0; return_buffer_to_port(port, mmalbuf); return; } if (mmalbuf->pts > 0) { if (pikrellcam.t_now > tv.tv_sec + 10) { /* Rarely, but time skew can change if ntp updates. */ gettimeofday(&tv, NULL); mmal_port_parameter_get_uint64(port, MMAL_PARAMETER_SYSTEM_TIME, &t0_stc); t0_stc = (uint64_t) tv.tv_sec * 1000000LL + (uint64_t) tv.tv_usec - t0_stc; } /* Skew adjust to the system clock to get second transitions. | Annotate times need to be set early to get displayed time synced | with system time. Needs >2 frames + offset to get it to work over | range of fps values. | Key frames can be delivered one frame after a request, so request | within 1 1/2 frames before second time transitions. */ t64_now = t0_stc + mmalbuf->pts; t_sec = (int) (t64_now / 1000000LL); t_usec = (int) (t64_now % 1000000LL); dt_frame = 1000000 / pikrellcam.camera_adjust.video_fps; if ( t_annotate < t_sec && t_usec > 900000 - 5 * dt_frame / 2 ) { t_annotate = t_sec; annotate_text_update(t_annotate + 1); } if ( (vcb->state == VCB_STATE_NONE || vcb->pause) && t_key_frame < t_sec && t_usec > 1000000 - 3 * dt_frame / 2 ) { t_key_frame = t_sec; mmal_port_parameter_set_boolean(port, MMAL_PARAMETER_VIDEO_REQUEST_I_FRAME, 1); } if ( (mmalbuf->flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME) && t_cur < t_sec ) t_cur = t_sec; } pthread_mutex_lock(&vcb->mutex); if (mmalbuf->flags & MMAL_BUFFER_HEADER_FLAG_CONFIG) h264_header_save(mmalbuf); else if (mmalbuf->flags & MMAL_BUFFER_HEADER_FLAG_CODECSIDEINFO) { if (++fps_count >= pikrellcam.mjpeg_divider) { motion_frame_event = TRUE; /* synchronize with i420 callback */ fps_count = 0; mmal_buffer_header_mem_lock(mmalbuf); memcpy(motion_frame.vectors, mmalbuf->data, motion_frame.vectors_size); mmal_buffer_header_mem_unlock(mmalbuf); motion_frame_process(vcb, &motion_frame); } } else { if ( (mmalbuf->flags & MMAL_BUFFER_HEADER_FLAG_KEYFRAME) && !vcb->in_keyframe ) { /* Keep key_frame[cur_frame_index] always pointing to the latest | keyframe (this one) in the video buffer. Then adjust the | key_frame[pre_frame_index] to point to a keyframe | in the video buffer that is pre_capture time behind. | If paused, always keep tail pointing to the latest keyframe. */ vcb->in_keyframe = TRUE; vcb->cur_frame_index = (vcb->cur_frame_index + 1) % KEYFRAME_SIZE; kf = &vcb->key_frame[vcb->cur_frame_index]; kf->position = vcb->head; kf->frame_count = 0; pause_frame_count_adjust = 0; if (vcb->pause && vcb->state == VCB_STATE_MANUAL_RECORD) { vcb->tail = vcb->head; pts_prev = mmalbuf->pts; pause_frame_count_adjust = 0; } kf->t_frame = t_cur; kf->frame_pts = mmalbuf->pts; while (t_cur - vcb->key_frame[vcb->pre_frame_index].t_frame > pikrellcam.motion_times.pre_capture) { vcb->pre_frame_index = (vcb->pre_frame_index + 1) % KEYFRAME_SIZE; if (vcb->pre_frame_index == vcb->cur_frame_index) break; } } if (mmalbuf->flags & MMAL_BUFFER_HEADER_FLAG_FRAME_END) { vcb->in_keyframe = FALSE; i = vcb->pre_frame_index; while (1) { vcb->key_frame[i].frame_count += 1; if (i++ == vcb->cur_frame_index) break; i %= KEYFRAME_SIZE; } if ( vcb->state == VCB_STATE_MOTION_RECORD || vcb->state == VCB_STATE_MANUAL_RECORD ) { if (!vcb->pause) vcb->frame_count += 1; else pause_frame_count_adjust += 1; } } if (t_cur > t_prev) { if (!vcb->pause) ++vcb->record_elapsed_time; t_prev = t_cur; } if (vcb->state == VCB_STATE_MOTION_RECORD_START) { /* Write mp4 header and set tail to beginning of pre_capture | video data, then write the entire pre_capture time data. | The keyframe data we collected above keeps a pointer to | video data close to the pre_capture time we want. */ fwrite(vcb->h264_header, 1, vcb->h264_header_position, vcb->file); pikrellcam.video_header_size = vcb->h264_header_position; pikrellcam.video_size = vcb->h264_header_position; vcb->tail = vcb->key_frame[vcb->record_start_frame_index].position; vcb_video_write(vcb); vcb->frame_count = vcb->key_frame[vcb->record_start_frame_index].frame_count; vcb->video_frame_count = vcb->frame_count; motion_event_write(vcb, mf); vcb->state = VCB_STATE_MOTION_RECORD; if (mf->external_trigger_time_limit > 0) { vcb->motion_sync_time = t_cur + mf->external_trigger_time_limit; vcb->max_record_time = mf->external_trigger_time_limit; } else { vcb->motion_sync_time = t_cur + pikrellcam.motion_times.post_capture; vcb->max_record_time = pikrellcam.motion_record_time_limit; } /* Schedule any motion begin command. */ event |= EVENT_MOTION_BEGIN; } if (vcb->state == VCB_STATE_MANUAL_RECORD_START) { /* Write mp4 header and set tail to most recent keyframe. | So manual records may have up to about a sec pre_capture. */ fwrite(vcb->h264_header, 1, vcb->h264_header_position, vcb->file); pikrellcam.video_header_size = vcb->h264_header_position; pikrellcam.video_size = vcb->h264_header_position; vcb->tail = vcb->key_frame[vcb->record_start_frame_index].position; vcb_video_write(vcb); vcb->frame_count = vcb->key_frame[vcb->record_start_frame_index].frame_count; pts_prev = 0; vcb->state = VCB_STATE_MANUAL_RECORD; event |= EVENT_PREVIEW_SAVE; } if (h264_conn_status == H264_TCP_SEND_HEADER) tcp_send_h264_header(vcb->h264_header, vcb->h264_header_position); /* Save video data into the circular buffer. */ mmal_buffer_header_mem_lock(mmalbuf); end_space = vcb->size - vcb->head; if (mmalbuf->length <= end_space) { memcpy(vcb->data + vcb->head, mmalbuf->data, mmalbuf->length); if(h264_conn_status == H264_TCP_SEND_DATA) tcp_send_h264_data("data 1",vcb->data + vcb->head, mmalbuf->length); } else { memcpy(vcb->data + vcb->head, mmalbuf->data, end_space); memcpy(vcb->data, mmalbuf->data + end_space, mmalbuf->length - end_space); if (h264_conn_status == H264_TCP_SEND_DATA) { tcp_send_h264_data("data 2",vcb->data + vcb->head, end_space); tcp_send_h264_data("data 3",vcb->data, mmalbuf->length - end_space); } } vcb->head = (vcb->head + mmalbuf->length) % vcb->size; mmal_buffer_header_mem_unlock(mmalbuf); /* And write video data to a video file according to record state. | Record time limit (if any) does not include pre capture times or | manual paused time which is accounted for in record_elapsed_time. */ force_stop = FALSE; if (vcb->max_record_time > 0) { t_elapsed = vcb->record_elapsed_time; if (vcb->state == VCB_STATE_MOTION_RECORD) t_elapsed -= (mf->external_trigger_pre_capture > 0) ? mf->external_trigger_pre_capture : pikrellcam.motion_times.pre_capture; else t_elapsed -= vcb->manual_pre_capture; if (t_elapsed >= vcb->max_record_time) force_stop = TRUE; } if (vcb->state == VCB_STATE_MANUAL_RECORD) { if (!vcb->pause) { if (mmalbuf->pts > 0) { if (pts_prev > 0) vcb->last_pts += mmalbuf->pts - pts_prev; else vcb->last_pts = mmalbuf->pts; pts_prev = mmalbuf->pts; } if (prev_pause) { vcb->frame_count += pause_frame_count_adjust; pause_frame_count_adjust = 0; } vcb->video_frame_count = vcb->frame_count; vcb_video_write(vcb); /* Continuously write video data */ } prev_pause = vcb->pause; if (force_stop) video_record_stop(vcb); } else if (vcb->state == VCB_STATE_MOTION_RECORD) { /* Always write until we reach motion_sync time (which is last | motion detect time + post_capture time), then hold during | event_gap time. Motion events during event_gap time will bump | motion_sync_time and event_gap expiration time higher thus | triggering more writes up to the new sync_time. | If there is not another motion event, event_gap time will be | reached and we stop recording with the post_capture time | already written. */ if (t_cur <= vcb->motion_sync_time) { if (mmalbuf->pts > 0) vcb->last_pts = mmalbuf->pts; vcb->video_frame_count = vcb->frame_count; vcb_video_write(vcb); } if ( force_stop || ( mf->external_trigger_time_limit == 0 && t_cur >= vcb->motion_last_detect_time + pikrellcam.motion_times.event_gap ) ) { /* For motion recording, preview_save_mode "first" has been | handled in motion_frame_process(). But if not "first", | there is a preview save waiting to be handled. */ video_record_stop(vcb); event |= EVENT_MOTION_END; if (strcmp(pikrellcam.motion_preview_save_mode, "first") != 0) event |= EVENT_MOTION_PREVIEW_SAVE_CMD; } } } pthread_mutex_unlock(&vcb->mutex); return_buffer_to_port(port, mmalbuf); /* This handles preview saves for manual records for possible future use. | preview_save_cmd does not apply for manual records. | All preview saves for motion records are scheduled in motion_frame_process(). | preview_save_cmd for save mode "best" is handled in video_record_stop(). */ if (event & EVENT_PREVIEW_SAVE) event_add("manual preview save", pikrellcam.t_now, 0, event_preview_save, NULL); if ( (event & EVENT_MOTION_BEGIN) && *pikrellcam.on_motion_begin_cmd != '\0' ) event_add("motion begin", pikrellcam.t_now, 0, exec_no_wait, pikrellcam.on_motion_begin_cmd); /* motion end event and preview dispose are handled in video_record_stop() */ }
/** * main */ int main(int argc, const char **argv) { // Our main data storage vessel.. RASPIVID_STATE state; MMAL_STATUS_T status = -1; MMAL_PORT_T *camera_video_port = NULL; MMAL_PORT_T *camera_still_port = NULL; MMAL_PORT_T *preview_input_port = NULL; MMAL_PORT_T *encoder_input_port = NULL; MMAL_PORT_T *encoder_output_port = NULL; time_t timer_begin,timer_end; double secondsElapsed; bcm_host_init(); signal(SIGINT, signal_handler); // read default status default_status(&state); // init windows and OpenCV Stuff cvNamedWindow("camcvWin", CV_WINDOW_AUTOSIZE); int w=state.width; int h=state.height; dstImage = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, 3); py = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, 1); // Y component of YUV I420 frame pu = cvCreateImage(cvSize(w/2,h/2), IPL_DEPTH_8U, 1); // U component of YUV I420 frame pv = cvCreateImage(cvSize(w/2,h/2), IPL_DEPTH_8U, 1); // V component of YUV I420 frame pu_big = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, 1); pv_big = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, 1); image = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, 3); // final picture to display // create camera if (!create_camera_component(&state)) { vcos_log_error("%s: Failed to create camera component", __func__); } else if ((status = raspipreview_create(&state.preview_parameters)) != MMAL_SUCCESS) { vcos_log_error("%s: Failed to create preview component", __func__); destroy_camera_component(&state); } else { PORT_USERDATA callback_data; camera_video_port = state.camera_component->output[MMAL_CAMERA_VIDEO_PORT]; camera_still_port = state.camera_component->output[MMAL_CAMERA_CAPTURE_PORT]; VCOS_STATUS_T vcos_status; callback_data.pstate = &state; vcos_status = vcos_semaphore_create(&callback_data.complete_semaphore, "RaspiStill-sem", 0); vcos_assert(vcos_status == VCOS_SUCCESS); // assign data to use for callback camera_video_port->userdata = (struct MMAL_PORT_USERDATA_T *)&callback_data; // init timer time(&timer_begin); // start capture if (mmal_port_parameter_set_boolean(camera_video_port, MMAL_PARAMETER_CAPTURE, 1) != MMAL_SUCCESS) { goto error; } // Send all the buffers to the video port int num = mmal_queue_length(state.video_pool->queue); int q; for (q=0;q<num;q++) { MMAL_BUFFER_HEADER_T *buffer = mmal_queue_get(state.video_pool->queue); if (!buffer) vcos_log_error("Unable to get a required buffer %d from pool queue", q); if (mmal_port_send_buffer(camera_video_port, buffer)!= MMAL_SUCCESS) vcos_log_error("Unable to send a buffer to encoder output port (%d)", q); } // Now wait until we need to stop vcos_sleep(state.timeout); error: mmal_status_to_int(status); // Disable all our ports that are not handled by connections check_disable_port(camera_still_port); if (state.camera_component) mmal_component_disable(state.camera_component); //destroy_encoder_component(&state); raspipreview_destroy(&state.preview_parameters); destroy_camera_component(&state); } if (status != 0) raspicamcontrol_check_configuration(128); time(&timer_end); /* get current time; same as: timer = time(NULL) */ cvReleaseImage(&dstImage); cvReleaseImage(&pu); cvReleaseImage(&pv); cvReleaseImage(&py); cvReleaseImage(&pu_big); cvReleaseImage(&pv_big); secondsElapsed = difftime(timer_end,timer_begin); printf ("%.f seconds for %d frames : FPS = %f\n", secondsElapsed,nCount,(float)((float)(nCount)/secondsElapsed)); return 0; }
void ofxRaspicam::create_camera_component() { MMAL_ES_FORMAT_T *format; MMAL_STATUS_T status; /* Create the component */ status = mmal_component_create(MMAL_COMPONENT_DEFAULT_CAMERA, &camera); if (status != MMAL_SUCCESS) { ofLogVerbose() << "Failed to create camera component"; } if (!camera->output_num) { ofLogVerbose() << "Camera doesn't have output ports"; }else { ofLogVerbose() << "camera->output_num: " << camera->output_num; } camera_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) { ofLogVerbose() << "Enable control port FAIL: error" << status; } else { ofLogVerbose() << "Enable control port : PASS " << status; } //raspicamcontrol_set_all_parameters(camera, &photo.camera_parameters); // Now set up the port formats format = camera_still_port->format; // Set our stills format on the stills (for encoder) port format->encoding = MMAL_ENCODING_OPAQUE; format->es->video.width = photo.width; format->es->video.height = photo.height; format->es->video.crop.x = 0; format->es->video.crop.y = 0; format->es->video.crop.width = photo.width; format->es->video.crop.height = photo.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(camera_still_port); if (status) { ofLogVerbose() << "camera still format couldn't be set"; } /* Ensure there are enough buffers to avoid dropping frames */ if (camera_still_port->buffer_num < OUTPUT_BUFFERS_NUM) { camera_still_port->buffer_num = OUTPUT_BUFFERS_NUM; } /* Enable component */ status = mmal_component_enable(camera); if (status) { ofLogVerbose() << "camera component enable FAIL"; }else { ofLogVerbose() << "camera component enable PASS"; } if (photo.wantRAW) { if (mmal_port_parameter_set_boolean(camera_still_port, MMAL_PARAMETER_ENABLE_RAW_CAPTURE, 1) != MMAL_SUCCESS) { ofLogVerbose() << "RAW was requested, but failed to enable"; // Continue on and take picture without. } } photo.setup(camera); ofLogVerbose() << "Camera component done"; }
/* Create Simple Video Player instance. */ SVP_T *svp_create(const char *uri, SVP_CALLBACKS_T *callbacks, const SVP_OPTS_T *opts) { SVP_T *svp; MMAL_STATUS_T st; VCOS_STATUS_T vst; MMAL_PORT_T *reader_output = NULL; MMAL_COMPONENT_T *video_decode = NULL; MMAL_PORT_T *video_output = NULL; LOG_TRACE("Creating player for %s", (uri ? uri : "camera preview")); vcos_assert(callbacks->video_frame_cb); vcos_assert(callbacks->stop_cb); svp = vcos_calloc(1, sizeof(*svp), "svp"); CHECK_STATUS((svp ? MMAL_SUCCESS : MMAL_ENOMEM), "Failed to allocate context"); svp->opts = *opts; svp->callbacks = *callbacks; /* Semaphore used for synchronising buffer handling for decoded frames */ vst = vcos_semaphore_create(&svp->sema, "svp-sem", 0); CHECK_STATUS((vst == VCOS_SUCCESS ? MMAL_SUCCESS : MMAL_ENOMEM), "Failed to create semaphore"); svp->created |= SVP_CREATED_SEM; vst = vcos_mutex_create(&svp->mutex, "svp-mutex"); CHECK_STATUS((vst == VCOS_SUCCESS ? MMAL_SUCCESS : MMAL_ENOMEM), "Failed to create mutex"); svp->created |= SVP_CREATED_MUTEX; vst = vcos_timer_create(&svp->timer, "svp-timer", svp_timer_cb, svp); CHECK_STATUS((vst == VCOS_SUCCESS ? MMAL_SUCCESS : MMAL_ENOMEM), "Failed to create timer"); svp->created |= SVP_CREATED_TIMER; vst = vcos_timer_create(&svp->wd_timer, "svp-wd-timer", svp_watchdog_cb, svp); CHECK_STATUS((vst == VCOS_SUCCESS ? MMAL_SUCCESS : MMAL_ENOMEM), "Failed to create timer"); svp->created |= SVP_CREATED_WD_TIMER; /* Create components */ svp->reader = NULL; svp->video_decode = NULL; svp->camera = NULL; svp->connection = NULL; if (uri) { /* Video from URI: setup container_reader -> video_decode */ /* Create and set up container reader */ st = mmal_component_create(MMAL_COMPONENT_DEFAULT_CONTAINER_READER, &svp->reader); CHECK_STATUS(st, "Failed to create container reader"); st = svp_setup_reader(svp->reader, uri, &reader_output); if (st != MMAL_SUCCESS) goto error; st = mmal_component_enable(svp->reader); CHECK_STATUS(st, "Failed to enable container reader"); st = svp_port_enable(svp, svp->reader->control, svp_bh_control_cb); CHECK_STATUS(st, "Failed to enable container reader control port"); /* Create and set up video decoder */ st = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_DECODER, &svp->video_decode); CHECK_STATUS(st, "Failed to create video decoder"); video_decode = svp->video_decode; video_output = video_decode->output[0]; st = mmal_component_enable(video_decode); CHECK_STATUS(st, "Failed to enable video decoder"); st = svp_port_enable(svp, video_decode->control, svp_bh_control_cb); CHECK_STATUS(st, "Failed to enable video decoder control port"); } else { /* Camera preview */ MMAL_PARAMETER_CAMERA_CONFIG_T config; st = mmal_component_create(MMAL_COMPONENT_DEFAULT_CAMERA, &svp->camera); CHECK_STATUS(st, "Failed to create camera"); st = mmal_component_enable(svp->camera); CHECK_STATUS(st, "Failed to enable camera"); st = svp_port_enable(svp, svp->camera->control, svp_bh_control_cb); CHECK_STATUS(st, "Failed to enable camera control port"); video_output = svp->camera->output[0]; /* Preview port */ } st = mmal_port_parameter_set_boolean(video_output, MMAL_PARAMETER_ZERO_COPY, MMAL_TRUE); CHECK_STATUS((st == MMAL_ENOSYS ? MMAL_SUCCESS : st), "Failed to enable zero copy"); if (uri) { /* Create connection: container_reader -> video_decoder */ st = mmal_connection_create(&svp->connection, reader_output, video_decode->input[0], MMAL_CONNECTION_FLAG_TUNNELLING); CHECK_STATUS(st, "Failed to create connection"); } /* Set video output port format. * Opaque encoding ensures we get buffer data as handles to relocatable heap. */ video_output->format->encoding = MMAL_ENCODING_OPAQUE; if (!uri) { /* Set video format for camera preview */ MMAL_VIDEO_FORMAT_T *vfmt = &video_output->format->es->video; CHECK_STATUS((video_output->format->type == MMAL_ES_TYPE_VIDEO) ? MMAL_SUCCESS : MMAL_EINVAL, "Output port isn't video format"); vfmt->width = SVP_CAMERA_WIDTH; vfmt->height = SVP_CAMERA_HEIGHT; vfmt->crop.x = 0; vfmt->crop.y = 0; vfmt->crop.width = vfmt->width; vfmt->crop.height = vfmt->height; vfmt->frame_rate.num = SVP_CAMERA_FRAMERATE; vfmt->frame_rate.den = 1; } st = mmal_port_format_commit(video_output); CHECK_STATUS(st, "Failed to set output port format"); /* Finally, set buffer num/size. N.B. For container_reader/video_decode, must be after * connection created, in order for port format to propagate. * Don't enable video output port until want to produce frames. */ video_output->buffer_num = video_output->buffer_num_recommended; video_output->buffer_size = video_output->buffer_size_recommended; /* Pool + queue to hold decoded video frames */ svp->out_pool = mmal_port_pool_create(video_output, video_output->buffer_num, video_output->buffer_size); CHECK_STATUS((svp->out_pool ? MMAL_SUCCESS : MMAL_ENOMEM), "Error allocating pool"); svp->queue = mmal_queue_create(); CHECK_STATUS((svp ? MMAL_SUCCESS : MMAL_ENOMEM), "Error allocating queue"); svp->video_output = video_output; return svp; error: svp_destroy(svp); return NULL; }
bool CMMALRenderer::init_vout(ERenderFormat format, bool opaque) { CSingleLock lock(m_sharedSection); bool formatChanged = m_format != format || m_opaque != opaque; MMAL_STATUS_T status; CLog::Log(LOGDEBUG, "%s::%s configured:%d format %d->%d opaque %d->%d", CLASSNAME, __func__, m_bConfigured, m_format, format, m_opaque, opaque); if (m_bMMALConfigured && formatChanged) UnInitMMAL(); if (m_bMMALConfigured || format != RENDER_FMT_MMAL) return true; m_format = format; m_opaque = opaque; /* Create video renderer */ status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_RENDERER, &m_vout); if(status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to create vout component (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } m_vout_input = m_vout->input[0]; m_vout_input->userdata = (struct MMAL_PORT_USERDATA_T *)this; MMAL_ES_FORMAT_T *es_format = m_vout_input->format; es_format->type = MMAL_ES_TYPE_VIDEO; if (CONF_FLAGS_YUVCOEF_MASK(m_iFlags) == CONF_FLAGS_YUVCOEF_BT709) es_format->es->video.color_space = MMAL_COLOR_SPACE_ITUR_BT709; else if (CONF_FLAGS_YUVCOEF_MASK(m_iFlags) == CONF_FLAGS_YUVCOEF_BT601) es_format->es->video.color_space = MMAL_COLOR_SPACE_ITUR_BT601; else if (CONF_FLAGS_YUVCOEF_MASK(m_iFlags) == CONF_FLAGS_YUVCOEF_240M) es_format->es->video.color_space = MMAL_COLOR_SPACE_SMPTE240M; es_format->es->video.crop.width = m_sourceWidth; es_format->es->video.crop.height = m_sourceHeight; es_format->es->video.width = m_sourceWidth; es_format->es->video.height = m_sourceHeight; es_format->encoding = m_opaque ? MMAL_ENCODING_OPAQUE : MMAL_ENCODING_I420; status = mmal_port_parameter_set_boolean(m_vout_input, MMAL_PARAMETER_ZERO_COPY, MMAL_TRUE); if (status != MMAL_SUCCESS) CLog::Log(LOGERROR, "%s::%s Failed to enable zero copy mode on %s (status=%x %s)", CLASSNAME, __func__, m_vout_input->name, status, mmal_status_to_string(status)); status = mmal_port_format_commit(m_vout_input); if (status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to commit vout input format (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } m_vout_input->buffer_num = std::max(m_vout_input->buffer_num_recommended, (uint32_t)m_NumYV12Buffers+(m_opaque?0:32)); m_vout_input->buffer_size = m_vout_input->buffer_size_recommended; status = mmal_port_enable(m_vout_input, vout_input_port_cb_static); if(status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to vout enable input port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } status = mmal_component_enable(m_vout); if(status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to enable vout component (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } CLog::Log(LOGDEBUG, "%s::%s Created pool of size %d x %d", CLASSNAME, __func__, m_vout_input->buffer_num, m_vout_input->buffer_size); m_vout_input_pool = mmal_port_pool_create(m_vout_input , m_vout_input->buffer_num, m_opaque ? m_vout_input->buffer_size:0); if (!m_vout_input_pool) { CLog::Log(LOGERROR, "%s::%s Failed to create pool for decoder input port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } if (!CSettings::GetInstance().GetBool("videoplayer.usedisplayasclock")) { m_queue = mmal_queue_create(); Create(); } return true; }
/** * main */ int main(int argc, const char **argv) { // Our main data storage vessel.. RASPISTILLYUV_STATE state; int exit_code = EX_OK; MMAL_STATUS_T status = MMAL_SUCCESS; MMAL_PORT_T *camera_preview_port = NULL; MMAL_PORT_T *camera_video_port = NULL; MMAL_PORT_T *camera_still_port = NULL; MMAL_PORT_T *preview_input_port = NULL; FILE *output_file = NULL; bcm_host_init(); // Register our application with the logging system vcos_log_register("RaspiStill", VCOS_LOG_CATEGORY); signal(SIGINT, signal_handler); // Disable USR1 for the moment - may be reenabled if go in to signal capture mode signal(SIGUSR1, SIG_IGN); default_status(&state); // Do we have any parameters if (argc == 1) { fprintf(stdout, "\n%s Camera App %s\n\n", basename(argv[0]), VERSION_STRING); display_valid_parameters(basename(argv[0])); exit(EX_USAGE); } default_status(&state); // Parse the command line and put options in to our status structure if (parse_cmdline(argc, argv, &state)) { status = -1; exit(EX_USAGE); } if (state.verbose) { fprintf(stderr, "\n%s Camera App %s\n\n", basename(argv[0]), VERSION_STRING); dump_status(&state); } // OK, we have a nice set of parameters. Now set up our components // We have two components. Camera and Preview // Camera is different in stills/video, but preview // is the same so handed off to a separate module if ((status = create_camera_component(&state)) != MMAL_SUCCESS) { vcos_log_error("%s: Failed to create camera component", __func__); exit_code = EX_SOFTWARE; } else if ((status = raspipreview_create(&state.preview_parameters)) != MMAL_SUCCESS) { vcos_log_error("%s: Failed to create preview component", __func__); destroy_camera_component(&state); exit_code = EX_SOFTWARE; } else { PORT_USERDATA callback_data; if (state.verbose) fprintf(stderr, "Starting component connection stage\n"); camera_preview_port = state.camera_component->output[MMAL_CAMERA_PREVIEW_PORT]; camera_video_port = state.camera_component->output[MMAL_CAMERA_VIDEO_PORT]; camera_still_port = state.camera_component->output[MMAL_CAMERA_CAPTURE_PORT]; // Note we are lucky that the preview and null sink components use the same input port // so we can simple do this without conditionals preview_input_port = state.preview_parameters.preview_component->input[0]; // Connect camera to preview (which might be a null_sink if no preview required) status = connect_ports(camera_preview_port, preview_input_port, &state.preview_connection); if (status == MMAL_SUCCESS) { VCOS_STATUS_T vcos_status; // Set up our userdata - this is passed though to the callback where we need the information. // Null until we open our filename callback_data.file_handle = NULL; callback_data.pstate = &state; vcos_status = vcos_semaphore_create(&callback_data.complete_semaphore, "RaspiStill-sem", 0); vcos_assert(vcos_status == VCOS_SUCCESS); camera_still_port->userdata = (struct MMAL_PORT_USERDATA_T *)&callback_data; if (state.verbose) fprintf(stderr, "Enabling camera still output port\n"); // Enable the camera still output port and tell it its callback function status = mmal_port_enable(camera_still_port, camera_buffer_callback); if (status != MMAL_SUCCESS) { vcos_log_error("Failed to setup camera output"); goto error; } if (state.verbose) fprintf(stderr, "Starting video preview\n"); int frame, keep_looping = 1; FILE *output_file = NULL; char *use_filename = NULL; // Temporary filename while image being written char *final_filename = NULL; // Name that file gets once writing complete frame = 0; while (keep_looping) { keep_looping = wait_for_next_frame(&state, &frame); // Open the file if (state.filename) { if (state.filename[0] == '-') { output_file = stdout; // Ensure we don't upset the output stream with diagnostics/info state.verbose = 0; } else { vcos_assert(use_filename == NULL && final_filename == NULL); status = create_filenames(&final_filename, &use_filename, state.filename, frame); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to create filenames"); goto error; } if (state.verbose) fprintf(stderr, "Opening output file %s\n", final_filename); // Technically it is opening the temp~ filename which will be ranamed to the final filename output_file = fopen(use_filename, "wb"); if (!output_file) { // Notify user, carry on but discarding encoded output buffers vcos_log_error("%s: Error opening output file: %s\nNo output file will be generated\n", __func__, use_filename); } } callback_data.file_handle = output_file; } if (output_file) { int num, q; // There is a possibility that shutter needs to be set each loop. if (mmal_status_to_int(mmal_port_parameter_set_uint32(state.camera_component->control, MMAL_PARAMETER_SHUTTER_SPEED, state.camera_parameters.shutter_speed) != MMAL_SUCCESS)) vcos_log_error("Unable to set shutter speed"); // Send all the buffers to the camera output port num = mmal_queue_length(state.camera_pool->queue); for (q=0;q<num;q++) { MMAL_BUFFER_HEADER_T *buffer = mmal_queue_get(state.camera_pool->queue); if (!buffer) vcos_log_error("Unable to get a required buffer %d from pool queue", q); if (mmal_port_send_buffer(camera_still_port, buffer)!= MMAL_SUCCESS) vcos_log_error("Unable to send a buffer to camera output port (%d)", q); } if (state.burstCaptureMode && frame==1) { mmal_port_parameter_set_boolean(state.camera_component->control, MMAL_PARAMETER_CAMERA_BURST_CAPTURE, 1); } if (state.verbose) fprintf(stderr, "Starting capture %d\n", frame); if (mmal_port_parameter_set_boolean(camera_still_port, MMAL_PARAMETER_CAPTURE, 1) != MMAL_SUCCESS) { vcos_log_error("%s: Failed to start capture", __func__); } else { // Wait for capture to complete // For some reason using vcos_semaphore_wait_timeout sometimes returns immediately with bad parameter error // even though it appears to be all correct, so reverting to untimed one until figure out why its erratic vcos_semaphore_wait(&callback_data.complete_semaphore); if (state.verbose) fprintf(stderr, "Finished capture %d\n", frame); } // Ensure we don't die if get callback with no open file callback_data.file_handle = NULL; if (output_file != stdout) { rename_file(&state, output_file, final_filename, use_filename, frame); } } if (use_filename) { free(use_filename); use_filename = NULL; } if (final_filename) { free(final_filename); final_filename = NULL; } } // end for (frame) vcos_semaphore_delete(&callback_data.complete_semaphore); } else { mmal_status_to_int(status); vcos_log_error("%s: Failed to connect camera to preview", __func__); } error: mmal_status_to_int(status); if (state.verbose) fprintf(stderr, "Closing down\n"); if (output_file) fclose(output_file); // Disable all our ports that are not handled by connections check_disable_port(camera_video_port); if (state.preview_connection) mmal_connection_destroy(state.preview_connection); /* Disable components */ if (state.preview_parameters.preview_component) mmal_component_disable(state.preview_parameters.preview_component); if (state.camera_component) mmal_component_disable(state.camera_component); raspipreview_destroy(&state.preview_parameters); destroy_camera_component(&state); if (state.verbose) fprintf(stderr, "Close down completed, all components disconnected, disabled and destroyed\n\n"); } if (status != MMAL_SUCCESS) raspicamcontrol_check_configuration(128); return exit_code; }
/** * 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(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) { 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 = 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 }; 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 (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) { 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) { vcos_log_error("camera component couldn't be enabled"); goto error; } if (state->wantRAW) { if (mmal_port_parameter_set_boolean(still_port, MMAL_PARAMETER_ENABLE_RAW_CAPTURE, 1) != MMAL_SUCCESS) { vcos_log_error("RAW was requested, but failed to enable"); // Continue on and take picture without. } } state->camera_component = camera; if (state->verbose) fprintf(stderr, "Camera component done\n"); return camera; error: if (camera) mmal_component_destroy(camera); return 0; }
bool CMMALRenderer::init_vout(ERenderFormat format) { CSingleLock lock(m_sharedSection); bool formatChanged = m_format != format; MMAL_STATUS_T status; CLog::Log(LOGDEBUG, "%s::%s configured:%d format:%d->%d", CLASSNAME, __func__, m_bConfigured, m_format, format); if (m_bMMALConfigured && formatChanged) UnInitMMAL(); if (m_bMMALConfigured) return true; m_format = format; if (m_format != RENDER_FMT_MMAL && m_format != RENDER_FMT_YUV420P) return true; /* Create video renderer */ status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_RENDERER, &m_vout); if(status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to create vout component (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } m_vout->control->userdata = (struct MMAL_PORT_USERDATA_T *)this; status = mmal_port_enable(m_vout->control, vout_control_port_cb); if(status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to enable vout control port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } m_vout_input = m_vout->input[0]; m_vout_input->userdata = (struct MMAL_PORT_USERDATA_T *)this; MMAL_ES_FORMAT_T *es_format = m_vout_input->format; es_format->type = MMAL_ES_TYPE_VIDEO; es_format->es->video.crop.width = m_sourceWidth; es_format->es->video.crop.height = m_sourceHeight; if (m_format == RENDER_FMT_MMAL) { es_format->encoding = MMAL_ENCODING_OPAQUE; es_format->es->video.width = m_sourceWidth; es_format->es->video.height = m_sourceHeight; } else if (m_format == RENDER_FMT_YUV420P) { const int pitch = ALIGN_UP(m_sourceWidth, 32); const int aligned_height = ALIGN_UP(m_sourceHeight, 16); es_format->encoding = MMAL_ENCODING_I420; es_format->es->video.width = pitch; es_format->es->video.height = aligned_height; if (CONF_FLAGS_YUVCOEF_MASK(m_iFlags) == CONF_FLAGS_YUVCOEF_BT709) es_format->es->video.color_space = MMAL_COLOR_SPACE_ITUR_BT709; else if (CONF_FLAGS_YUVCOEF_MASK(m_iFlags) == CONF_FLAGS_YUVCOEF_BT601) es_format->es->video.color_space = MMAL_COLOR_SPACE_ITUR_BT601; else if (CONF_FLAGS_YUVCOEF_MASK(m_iFlags) == CONF_FLAGS_YUVCOEF_240M) es_format->es->video.color_space = MMAL_COLOR_SPACE_SMPTE240M; } if (m_format == RENDER_FMT_MMAL) { status = mmal_port_parameter_set_boolean(m_vout_input, MMAL_PARAMETER_ZERO_COPY, MMAL_TRUE); if (status != MMAL_SUCCESS) CLog::Log(LOGERROR, "%s::%s Failed to enable zero copy mode on %s (status=%x %s)", CLASSNAME, __func__, m_vout_input->name, status, mmal_status_to_string(status)); } status = mmal_port_format_commit(m_vout_input); if (status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to commit vout input format (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } m_vout_input->buffer_num = std::max(m_vout_input->buffer_num_recommended, (uint32_t)m_NumYV12Buffers); m_vout_input->buffer_size = m_vout_input->buffer_size_recommended; status = mmal_port_enable(m_vout_input, vout_input_port_cb_static); if(status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to vout enable input port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } status = mmal_component_enable(m_vout); if(status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to enable vout component (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } m_vout_input_pool = mmal_port_pool_create(m_vout_input , m_vout_input->buffer_num, m_vout_input->buffer_size); if (!m_vout_input_pool) { CLog::Log(LOGERROR, "%s::%s Failed to create pool for decoder input port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } return true; }
/** * main */ int main(int argc, const char **argv) { // Our main data storage vessel.. RASPISTILL_STATE state; MMAL_STATUS_T status = -1; MMAL_PORT_T *camera_preview_port = NULL; MMAL_PORT_T *camera_video_port = NULL; MMAL_PORT_T *camera_still_port = NULL; MMAL_PORT_T *preview_input_port = NULL; MMAL_PORT_T *encoder_input_port = NULL; MMAL_PORT_T *encoder_output_port = NULL; bcm_host_init(); signal(SIGINT, signal_handler); default_status(&state); if (!create_camera_component(&state)) { vcos_log_error("%s: Failed to create camera component", __func__); } else if ( (status = raspipreview_create(&state.preview_parameters)) != MMAL_SUCCESS) { vcos_log_error("%s: Failed to create preview component", __func__); destroy_camera_component(&state); } else if (!create_encoder_component(&state)) { vcos_log_error("%s: Failed to create encode component", __func__); raspipreview_destroy(&state.preview_parameters); destroy_camera_component(&state); } else { PORT_USERDATA callback_data; // *** PR : we don't want preview camera_preview_port = NULL;//state.camera_component->output[MMAL_CAMERA_PREVIEW_PORT]; camera_video_port = state.camera_component->output[MMAL_CAMERA_VIDEO_PORT]; camera_still_port = state.camera_component->output[MMAL_CAMERA_CAPTURE_PORT]; preview_input_port = state.preview_parameters.preview_component->input[0]; encoder_input_port = state.encoder_component->input[0]; encoder_output_port = state.encoder_component->output[0]; if (state.preview_parameters.wantPreview ) { if (state.verbose) { fprintf(stderr, "Connecting camera preview port to preview input port\n"); fprintf(stderr, "Starting video preview\n"); } // PR : we don't want preview // Connect camera to preview // status = connect_ports(camera_preview_port, preview_input_port, &state.preview_connection); } VCOS_STATUS_T vcos_status; if (state.verbose) fprintf(stderr, "Connecting camera stills port to encoder input port\n"); // Now connect the camera to the encoder status = connect_ports(camera_still_port, encoder_input_port, &state.encoder_connection); if (status != MMAL_SUCCESS) { vcos_log_error("%s: Failed to connect camera video port to encoder input", __func__); goto error; } // Set up our userdata - this is passed though to the callback where we need the information. // Null until we open our filename callback_data.file_handle = NULL; callback_data.pstate = &state; vcos_status = vcos_semaphore_create(&callback_data.complete_semaphore, "RaspiStill-sem", 0); vcos_assert(vcos_status == VCOS_SUCCESS); encoder_output_port->userdata = (struct MMAL_PORT_USERDATA_T *)&callback_data; if (state.verbose) fprintf(stderr, "Enabling encoder output port\n"); // Enable the encoder output port and tell it its callback function status = mmal_port_enable(encoder_output_port, encoder_buffer_callback); if (status != MMAL_SUCCESS) { vcos_log_error("Failed to setup encoder output"); goto error; } { int num_iterations = state.timelapse ? state.timeout / state.timelapse : 1; int frame; for (frame = 1;frame<=num_iterations; frame++) { if (state.timelapse) vcos_sleep(state.timelapse); else vcos_sleep(state.timeout); // Send all the buffers to the encoder output port int num = mmal_queue_length(state.encoder_pool->queue); int q; for (q=0;q<num;q++) { MMAL_BUFFER_HEADER_T *buffer = mmal_queue_get(state.encoder_pool->queue); if (!buffer) vcos_log_error("Unable to get a required buffer %d from pool queue", q); if (mmal_port_send_buffer(encoder_output_port, buffer)!= MMAL_SUCCESS) vcos_log_error("Unable to send a buffer to encoder output port (%d)", q); } if (mmal_port_parameter_set_boolean(camera_still_port, MMAL_PARAMETER_CAPTURE, 1) != MMAL_SUCCESS) { vcos_log_error("%s: Failed to start capture", __func__); } else { // Wait for capture to complete // For some reason using vcos_semaphore_wait_timeout sometimes returns immediately with bad parameter error // even though it appears to be all correct, so reverting to untimed one until figure out why its erratic vcos_semaphore_wait(&callback_data.complete_semaphore); } } // end for (frame) vcos_semaphore_delete(&callback_data.complete_semaphore); } error: mmal_status_to_int(status); // Disable all our ports that are not handled by connections check_disable_port(camera_video_port); check_disable_port(encoder_output_port); // PR : we don't want preview //if (state.preview_parameters.wantPreview ) // mmal_connection_destroy(state.preview_connection); mmal_connection_destroy(state.encoder_connection); /* Disable components */ if (state.encoder_component) mmal_component_disable(state.encoder_component); if (state.preview_parameters.preview_component) mmal_component_disable(state.preview_parameters.preview_component); if (state.camera_component) mmal_component_disable(state.camera_component); destroy_encoder_component(&state); raspipreview_destroy(&state.preview_parameters); destroy_camera_component(&state); if (state.verbose) fprintf(stderr, "Close down completed, all components disconnected, disabled and destroyed\n\n"); } if (status != 0) raspicamcontrol_check_configuration(128); return 0; }
/** * main */ int main(int argc, const char **argv) { // Our main data storage vessel.. RASPISTILLYUV_STATE state; MMAL_STATUS_T status = MMAL_SUCCESS; MMAL_PORT_T *camera_preview_port = NULL; MMAL_PORT_T *camera_video_port = NULL; MMAL_PORT_T *camera_still_port = NULL; MMAL_PORT_T *preview_input_port = NULL; FILE *output_file = NULL; bcm_host_init(); // Register our application with the logging system vcos_log_register("RaspiStill", VCOS_LOG_CATEGORY); signal(SIGINT, signal_handler); // Do we have any parameters if (argc == 1) { fprintf(stderr, "\n%s Camera App %s\n\n", basename(argv[0]), VERSION_STRING); display_valid_parameters(basename(argv[0])); exit(0); } default_status(&state); // Parse the command line and put options in to our status structure if (parse_cmdline(argc, argv, &state)) { status = -1; exit(0); } if (state.verbose) { fprintf(stderr, "\n%s Camera App %s\n\n", basename(argv[0]), VERSION_STRING); dump_status(&state); } // OK, we have a nice set of parameters. Now set up our components // We have two components. Camera and Preview // Camera is different in stills/video, but preview // is the same so handed off to a separate module if ((status = create_camera_component(&state)) != MMAL_SUCCESS) { vcos_log_error("%s: Failed to create camera component", __func__); } else if ((status = raspipreview_create(&state.preview_parameters)) != MMAL_SUCCESS) { vcos_log_error("%s: Failed to create preview component", __func__); destroy_camera_component(&state); } else { PORT_USERDATA callback_data; if (state.verbose) fprintf(stderr, "Starting component connection stage\n"); camera_preview_port = state.camera_component->output[MMAL_CAMERA_PREVIEW_PORT]; camera_video_port = state.camera_component->output[MMAL_CAMERA_VIDEO_PORT]; camera_still_port = state.camera_component->output[MMAL_CAMERA_CAPTURE_PORT]; preview_input_port = state.preview_parameters.preview_component->input[0]; if (state.preview_parameters.wantPreview ) { if (state.verbose) { fprintf(stderr, "Connecting camera preview port to preview input port\n"); fprintf(stderr, "Starting video preview\n"); } // Connect camera to preview status = connect_ports(camera_preview_port, preview_input_port, &state.preview_connection); } else { status = MMAL_SUCCESS; } if (status == MMAL_SUCCESS) { VCOS_STATUS_T vcos_status; if (state.filename) { if (state.verbose) fprintf(stderr, "Opening output file %s\n", state.filename); output_file = fopen(state.filename, "wb"); if (!output_file) { // Notify user, carry on but discarding output buffers vcos_log_error("%s: Error opening output file: %s\nNo output file will be generated\n", __func__, state.filename); } } // Set up our userdata - this is passed though to the callback where we need the information. callback_data.file_handle = output_file; callback_data.pstate = &state; vcos_status = vcos_semaphore_create(&callback_data.complete_semaphore, "RaspiStill-sem", 0); vcos_assert(vcos_status == VCOS_SUCCESS); camera_still_port->userdata = (struct MMAL_PORT_USERDATA_T *)&callback_data; if (state.verbose) fprintf(stderr, "Enabling camera still output port\n"); // Enable the camera still output port and tell it its callback function status = mmal_port_enable(camera_still_port, camera_buffer_callback); if (status != MMAL_SUCCESS) { vcos_log_error("Failed to setup camera output"); goto error; } if (state.verbose) fprintf(stderr, "Starting video preview\n"); int num_iterations = state.timelapse ? state.timeout / state.timelapse : 1; int frame; FILE *output_file = NULL; for (frame = 1; frame<=num_iterations; frame++) { if (state.timelapse) vcos_sleep(state.timelapse); else vcos_sleep(state.timeout); // Open the file if (state.filename) { if (state.filename[0] == '-') { output_file = stdout; // Ensure we don't upset the output stream with diagnostics/info state.verbose = 0; } else { char *use_filename = state.filename; if (state.timelapse) asprintf(&use_filename, state.filename, frame); if (state.verbose) fprintf(stderr, "Opening output file %s\n", use_filename); output_file = fopen(use_filename, "wb"); if (!output_file) { // Notify user, carry on but discarding encoded output buffers vcos_log_error("%s: Error opening output file: %s\nNo output file will be generated\n", __func__, use_filename); } // asprintf used in timelapse mode allocates its own memory which we need to free if (state.timelapse) free(use_filename); } callback_data.file_handle = output_file; } // And only do the capture if we have specified a filename and its opened OK if (output_file) { // Send all the buffers to the camera output port { int num = mmal_queue_length(state.camera_pool->queue); int q; for (q=0; q<num; q++) { MMAL_BUFFER_HEADER_T *buffer = mmal_queue_get(state.camera_pool->queue); if (!buffer) vcos_log_error("Unable to get a required buffer %d from pool queue", q); if (mmal_port_send_buffer(camera_still_port, buffer)!= MMAL_SUCCESS) vcos_log_error("Unable to send a buffer to camera output port (%d)", q); } } if (state.verbose) fprintf(stderr, "Starting capture %d\n", frame); // Fire the capture if (mmal_port_parameter_set_boolean(camera_still_port, MMAL_PARAMETER_CAPTURE, 1) != MMAL_SUCCESS) { vcos_log_error("%s: Failed to start capture", __func__); } else { // Wait for capture to complete // For some reason using vcos_semaphore_wait_timeout sometimes returns immediately with bad parameter error // even though it appears to be all correct, so reverting to untimed one until figure out why its erratic vcos_semaphore_wait(&callback_data.complete_semaphore); if (state.verbose) fprintf(stderr, "Finished capture %d\n", frame); } // Ensure we don't die if get callback with no open file callback_data.file_handle = NULL; if (output_file != stdout) fclose(output_file); } } vcos_semaphore_delete(&callback_data.complete_semaphore); } else { mmal_status_to_int(status); vcos_log_error("%s: Failed to connect camera to preview", __func__); } error: mmal_status_to_int(status); if (state.verbose) fprintf(stderr, "Closing down\n"); if (output_file) fclose(output_file); // Disable all our ports that are not handled by connections check_disable_port(camera_video_port); if (state.preview_parameters.wantPreview ) mmal_connection_destroy(state.preview_connection); /* Disable components */ if (state.preview_parameters.preview_component) mmal_component_disable(state.preview_parameters.preview_component); if (state.camera_component) mmal_component_disable(state.camera_component); raspipreview_destroy(&state.preview_parameters); destroy_camera_component(&state); if (state.verbose) fprintf(stderr, "Close down completed, all components disconnected, disabled and destroyed\n\n"); } if (status != MMAL_SUCCESS) raspicamcontrol_check_configuration(128); return 0; }
/** * main */ int main(int argc, const char **argv) { // Our main data storage vessel.. RASPIVID_STATE state; MMAL_STATUS_T status; MMAL_PORT_T *camera_preview_port = NULL; MMAL_PORT_T *camera_video_port = NULL; MMAL_PORT_T *camera_still_port = NULL; MMAL_PORT_T *preview_input_port = NULL; MMAL_PORT_T *encoder_input_port = NULL; MMAL_PORT_T *encoder_output_port = NULL; FILE *output_file = NULL; // Register our application with the logging system vcos_log_register("RaspiVid", VCOS_LOG_CATEGORY); printf("\nRaspiVid Camera App\n"); printf("===================\n\n"); signal(SIGINT, signal_handler); default_status(&state); // Do we have any parameters if (argc == 1) { display_valid_parameters(); exit(0); } // Parse the command line and put options in to our status structure if (parse_cmdline(argc, argv, &state)) { status = -1; exit(0); } if (state.verbose) dump_status(&state); // OK, we have a nice set of parameters. Now set up our components // We have three components. Camera, Preview and encoder. if (!create_camera_component(&state)) { vcos_log_error("%s: Failed to create camera component", __func__); } else if (!raspipreview_create(&state.preview_parameters)) { vcos_log_error("%s: Failed to create preview component", __func__); destroy_camera_component(&state); } else if (!create_encoder_component(&state)) { vcos_log_error("%s: Failed to create encode component", __func__); raspipreview_destroy(&state.preview_parameters); destroy_camera_component(&state); } else { PORT_USERDATA callback_data; if (state.verbose) printf("Starting component connection stage\n"); camera_preview_port = state.camera_component->output[MMAL_CAMERA_PREVIEW_PORT]; camera_video_port = state.camera_component->output[MMAL_CAMERA_VIDEO_PORT]; camera_still_port = state.camera_component->output[MMAL_CAMERA_CAPTURE_PORT]; preview_input_port = state.preview_parameters.preview_component->input[0]; encoder_input_port = state.encoder_component->input[0]; encoder_output_port = state.encoder_component->output[0]; if (state.preview_parameters.wantPreview ) { if (state.verbose) { printf("Connecting camera preview port to preview input port\n"); printf("Starting video preview\n"); } // Connect camera to preview status = connect_ports(camera_preview_port, preview_input_port, &state.preview_connection); } if (status == MMAL_SUCCESS) { VCOS_STATUS_T vcos_status; if (state.verbose) printf("Connecting camera stills port to encoder input port\n"); // Now connect the camera to the encoder status = connect_ports(camera_video_port, encoder_input_port, &state.encoder_connection); if (status != MMAL_SUCCESS) { vcos_log_error("%s: Failed to connect camera video port to encoder input", __func__); goto error; } if (state.filename) { if (state.verbose) printf("Opening output file %s\n", state.filename); output_file = fopen(state.filename, "wb"); if (!output_file) { // Notify user, carry on but discarding encoded output buffers vcos_log_error("%s: Error opening output file: %s\nNo output file will be generated\n", __func__, state.filename); } } // Set up our userdata - this is passed though to the callback where we need the information. callback_data.file_handle = output_file; callback_data.pstate = &state; vcos_status = vcos_semaphore_create(&callback_data.complete_semaphore, "RaspiStill-sem", 0); vcos_assert(vcos_status == VCOS_SUCCESS); encoder_output_port->userdata = (struct MMAL_PORT_USERDATA_T *)&callback_data; if (state.verbose) printf("Enabling encoder output port\n"); // Enable the encoder output port and tell it its callback function status = mmal_port_enable(encoder_output_port, encoder_buffer_callback); if (status != MMAL_SUCCESS) { vcos_log_error("Failed to setup encoder output"); goto error; } if (state.demoMode) { // Run for the user specific time.. int num_iterations = state.timeout / state.demoInterval; int i; printf("Running in demo mode\n"); for (i=0;i<num_iterations;i++) { raspicamcontrol_cycle_test(state.camera_component); vcos_sleep(state.demoInterval); } } else { // Only encode stuff if we have a filename and it opened if (output_file) { if (state.verbose) printf("Starting video capture\n"); if (mmal_port_parameter_set_boolean(camera_video_port, MMAL_PARAMETER_CAPTURE, 1) != MMAL_SUCCESS) { goto error; } // Send all the buffers to the encoder output port { int num = mmal_queue_length(state.encoder_pool->queue); int q; for (q=0;q<num;q++) { MMAL_BUFFER_HEADER_T *buffer = mmal_queue_get(state.encoder_pool->queue); if (!buffer) vcos_log_error("Unable to get a required buffer %d from pool queue", q); if (mmal_port_send_buffer(encoder_output_port, buffer)!= MMAL_SUCCESS) vcos_log_error("Unable to send a buffer to encoder output port (%d)", q); } } // Now wait until we need to stop vcos_sleep(state.timeout); printf("Finished capture\n"); } else vcos_sleep(state.timeout); } } else { mmal_status_to_int(status); vcos_log_error("%s: Failed to connect camera to preview", __func__); } error: mmal_status_to_int(status); if (state.verbose) printf("Closing down\n"); // Disable all our ports that are not handled by connections check_disable_port(camera_still_port); check_disable_port(encoder_output_port); if (state.preview_parameters.wantPreview ) mmal_connection_destroy(state.preview_connection); mmal_connection_destroy(state.encoder_connection); // Can now close our file. Note disabling ports may flush buffers which causes // problems if we have already closed the file! if (output_file) fclose(output_file); /* Disable components */ if (state.encoder_component) mmal_component_disable(state.encoder_component); if (state.preview_parameters.preview_component) mmal_component_disable(state.preview_parameters.preview_component); if (state.camera_component) mmal_component_disable(state.camera_component); destroy_encoder_component(&state); raspipreview_destroy(&state.preview_parameters); destroy_camera_component(&state); if (state.verbose) printf("Close down completed, all components disconnected, disabled and destroyed\n\n"); } return 0; }
RaspiCamCvCapture * raspiCamCvCreateCameraCapture(int index) { RaspiCamCvCapture * capture = (RaspiCamCvCapture*)malloc(sizeof(RaspiCamCvCapture)); // Our main data storage vessel.. RASPIVID_STATE * state = (RASPIVID_STATE*)malloc(sizeof(RASPIVID_STATE)); capture->pState = state; MMAL_STATUS_T status = -1; MMAL_PORT_T *camera_preview_port = NULL; MMAL_PORT_T *camera_video_port = NULL; //MMAL_PORT_T *camera_still_port = NULL; MMAL_PORT_T *encoder_input_port = NULL; MMAL_PORT_T *encoder_output_port = NULL; bcm_host_init(); // read default status default_status(state); int w = state->width; int h = state->height; state->py = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, 1); // Y component of YUV I420 frame if (state->graymode==0) { state->pu = cvCreateImage(cvSize(w/2,h/2), IPL_DEPTH_8U, 1); // U component of YUV I420 frame state->pv = cvCreateImage(cvSize(w/2,h/2), IPL_DEPTH_8U, 1); // V component of YUV I420 frame } vcos_semaphore_create(&state->capture_sem, "Capture-Sem", 0); vcos_semaphore_create(&state->capture_done_sem, "Capture-Done-Sem", 0); if (state->graymode==0) { state->pu_big = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, 1); state->pv_big = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, 1); state->yuvImage = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, 3); state->dstImage = cvCreateImage(cvSize(w,h), IPL_DEPTH_8U, 3); // final picture to display } //printf("point2.0\n"); // create camera if (!create_camera_component(state)) { vcos_log_error("%s: Failed to create camera component", __func__); raspiCamCvReleaseCapture(&capture); return NULL; } else if ((status = create_encoder_component(state)) != MMAL_SUCCESS) { vcos_log_error("%s: Failed to create encode component", __func__); destroy_camera_component(state); return NULL; } //printf("point2.1\n"); //create_encoder_component(state); camera_preview_port = state->camera_component->output[MMAL_CAMERA_PREVIEW_PORT]; camera_video_port = state->camera_component->output[MMAL_CAMERA_VIDEO_PORT]; //camera_still_port = state->camera_component->output[MMAL_CAMERA_CAPTURE_PORT]; encoder_input_port = state->encoder_component->input[0]; encoder_output_port = state->encoder_component->output[0]; // assign data to use for callback camera_preview_port->userdata = (struct MMAL_PORT_USERDATA_T *)state; // assign data to use for callback camera_video_port->userdata = (struct MMAL_PORT_USERDATA_T *)state; vcos_log_error("Connecting ports now"); // Now connect the camera to the encoder status = connect_ports(camera_video_port, encoder_input_port, &state->encoder_connection); if (state->filename) { if (state->filename[0] == '-') { state->callback_data.file_handle = stdout; } else { state->callback_data.file_handle = open_filename(state); } if (!state->callback_data.file_handle) { // Notify user, carry on but discarding encoded output buffers vcos_log_error("%s: Error opening output file: %s\nNo output file will be generated\n", __func__, state->filename); } } // Set up our userdata - this is passed though to the callback where we need the information. state->callback_data.pstate = state; state->callback_data.abort = 0; encoder_output_port->userdata = (struct MMAL_PORT_USERDATA_T *)&state->callback_data; // Enable the encoder output port and tell it its callback function status = mmal_port_enable(encoder_output_port, encoder_buffer_callback); if (status != MMAL_SUCCESS) { state->encoder_connection = NULL; vcos_log_error("%s: Failed to connect camera video port to encoder input", __func__); return NULL; } if (status != MMAL_SUCCESS) { vcos_log_error("Failed to setup encoder output"); return NULL; } //mmal_port_enable(encoder_output_port, encoder_buffer_callback); // Only encode stuff if we have a filename and it opened // Note we use the copy in the callback, as the call back MIGHT change the file handle if (state->callback_data.file_handle) { int running = 1; // Send all the buffers to the encoder output port { int num = mmal_queue_length(state->encoder_pool->queue); int q; for (q=0;q<num;q++) { MMAL_BUFFER_HEADER_T *buffer2 = mmal_queue_get(state->encoder_pool->queue); if (!buffer2) vcos_log_error("Unable to get a required buffer %d from pool queue", q); if (mmal_port_send_buffer(encoder_output_port, buffer2)!= MMAL_SUCCESS) vcos_log_error("Unable to send a buffer to encoder output port (%d)", q); } } } // start capture if (mmal_port_parameter_set_boolean(camera_video_port, MMAL_PARAMETER_CAPTURE, 1) != MMAL_SUCCESS) { vcos_log_error("%s: Failed to start capture", __func__); raspiCamCvReleaseCapture(&capture); return NULL; } // Send all the buffers to the preview port int num = mmal_queue_length(state->preview_pool->queue); int q; for (q = 0; q < num; q++) { MMAL_BUFFER_HEADER_T *buffer = mmal_queue_get(state->preview_pool->queue); if (!buffer) vcos_log_error("Unable to get a required buffer %d from pool queue", q); if (mmal_port_send_buffer(camera_preview_port, buffer)!= MMAL_SUCCESS) vcos_log_error("Unable to send a buffer to encoder output port (%d)", q); } //mmal_status_to_int(status); // Disable all our ports that are not handled by connections //check_disable_port(camera_still_port); //if (status != 0) // raspicamcontrol_check_configuration(128); vcos_semaphore_wait(&state->capture_done_sem); return capture; }
void camera_thread( void ) { static MMAL_STATUS_T status; static RASPIVID_STATE state; static MMAL_PORT_T *camera_preview_port = NULL; static MMAL_PORT_T *camera_video_port = NULL; static MMAL_PORT_T *camera_still_port = NULL; static MMAL_PORT_T *preview_input_port = NULL; static MMAL_PORT_T *encoder_input_port = NULL; static MMAL_PORT_T *encoder_output_port = NULL; static FILE *output_file = NULL; f_nal_queue = sx_queue_create(); bcm_host_init(); default_status(&state); state.verbose = 1; status = create_camera_component(&state); assert(status == MMAL_SUCCESS); status = raspipreview_create(&state.preview_parameters); assert(status == MMAL_SUCCESS); status = create_encoder_component(&state); assert(status == MMAL_SUCCESS); PORT_USERDATA callback_data; camera_preview_port = state.camera_component->output[MMAL_CAMERA_PREVIEW_PORT]; camera_video_port = state.camera_component->output[MMAL_CAMERA_VIDEO_PORT]; camera_still_port = state.camera_component->output[MMAL_CAMERA_CAPTURE_PORT]; preview_input_port = state.preview_parameters.preview_component->input[0]; encoder_input_port = state.encoder_component->input[0]; encoder_output_port = state.encoder_component->output[0]; // Now connect the camera to the encoder status = connect_ports(camera_video_port, encoder_input_port, &state.encoder_connection); assert(status == MMAL_SUCCESS); char *filename = "output.h264"; state.filename = filename; output_file = fopen(state.filename, "wb"); // Set up our userdata - this is passed though to the callback where we need the information. callback_data.file_handle = output_file; callback_data.pstate = &state; callback_data.abort = 0; encoder_output_port->userdata = (struct MMAL_PORT_USERDATA_T *) &callback_data; // Enable the encoder output port and tell it its callback function status = mmal_port_enable(encoder_output_port, encoder_buffer_callback); assert(status == MMAL_SUCCESS); // Only encode stuff if we have a filename and it opened if (output_file) { int wait; if (state.verbose) fprintf(stderr, "Starting video capture\n"); status = mmal_port_parameter_set_boolean(camera_video_port, MMAL_PARAMETER_CAPTURE, 1); assert(status == MMAL_SUCCESS); // Send all the buffers to the encoder output port { int num = mmal_queue_length(state.encoder_pool->queue); int q; fprintf(stderr, "mmal_queue_len = %d\n", num); for (q=0;q<num;q++) { printf("start current time = %d\n", get_time_ns()); MMAL_BUFFER_HEADER_T *buffer = mmal_queue_get(state.encoder_pool->queue); assert(buffer != NULL); status = mmal_port_send_buffer(encoder_output_port, buffer); assert(status == MMAL_SUCCESS); } } // Now wait until we need to stop. Whilst waiting we do need to check to see if we have aborted (for example // out of storage space) // Going to check every ABORT_INTERVAL milliseconds #if 1 while(1) { // sleep forever. vcos_sleep(ABORT_INTERVAL); } #endif #if 0 for (wait = 0; state.timeout == 0 || wait < state.timeout; wait+= ABORT_INTERVAL) { vcos_sleep(ABORT_INTERVAL); if (callback_data.abort) { fprintf(stderr, "333\n"); break; } fprintf(stderr, "222\n"); } fprintf(stderr, "wait = %u\n", wait); if (state.verbose) fprintf(stderr, "Finished capture\n"); #endif } }
void Private_Impl::commitVideoStabilization() { // Set Video Stabilization if ( mmal_port_parameter_set_boolean ( State.camera_component->control, MMAL_PARAMETER_VIDEO_STABILISATION, State.videoStabilisation ) != MMAL_SUCCESS ) cout << __func__ << ": Failed to set video stabilization parameter.\n"; }
/** * Reset the encoder component, set up its ports * * @param state Pointer to state control struct * * @return MMAL_SUCCESS if all OK, something else otherwise * */ MMAL_STATUS_T reset_encoder_component(RASPIVID_STATE *state) { MMAL_COMPONENT_T *encoder = 0; MMAL_PORT_T *encoder_input = NULL, *encoder_output = NULL; MMAL_STATUS_T status; MMAL_POOL_T *pool; // Get the encoder component if( state->encoder_component == NULL ) { vcos_log_error("Unable to get video encoder component"); goto error; } else { encoder = state->encoder_component; } #ifdef __NOT_REQURED__ if (!encoder->input_num || !encoder->output_num) { status = MMAL_ENOSYS; vcos_log_error("Video encoder doesn't have input/output ports"); goto error; } encoder_input = encoder->input[0]; encoder_output = encoder->output[0]; // We want same format on input and output mmal_format_copy(encoder_output->format, encoder_input->format); // Only supporting H264 at the moment encoder_output->format->encoding = state->encoding; encoder_output->format->bitrate = state->bitrate; if (state->encoding == MMAL_ENCODING_H264) encoder_output->buffer_size = encoder_output->buffer_size_recommended; else encoder_output->buffer_size = 256<<10; if (encoder_output->buffer_size < encoder_output->buffer_size_min) encoder_output->buffer_size = encoder_output->buffer_size_min; encoder_output->buffer_num = encoder_output->buffer_num_recommended; if (encoder_output->buffer_num < encoder_output->buffer_num_min) encoder_output->buffer_num = encoder_output->buffer_num_min; // We need to set the frame rate on output to 0, to ensure it gets // updated correctly from the input framerate when port connected encoder_output->format->es->video.frame_rate.num = 0; encoder_output->format->es->video.frame_rate.den = 1; // Commit the port changes to the output port status = mmal_port_format_commit(encoder_output); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set format on video encoder output port"); goto error; } if (state->encoding == MMAL_ENCODING_H264 && state->intraperiod != -1) { MMAL_PARAMETER_UINT32_T param = {{ MMAL_PARAMETER_INTRAPERIOD, sizeof(param)}, state->intraperiod}; status = mmal_port_parameter_set(encoder_output, ¶m.hdr); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set intraperiod"); goto error; } } if (state->encoding == MMAL_ENCODING_H264 && state->quantisationParameter) { MMAL_PARAMETER_UINT32_T param = {{ MMAL_PARAMETER_VIDEO_ENCODE_INITIAL_QUANT, sizeof(param)}, state->quantisationInitialParameter}; status = mmal_port_parameter_set(encoder_output, ¶m.hdr); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set initial QP"); goto error; } MMAL_PARAMETER_UINT32_T param2 = {{ MMAL_PARAMETER_VIDEO_ENCODE_MIN_QUANT, sizeof(param)}, state->quantisationMinParameter}; status = mmal_port_parameter_set(encoder_output, ¶m2.hdr); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set min QP"); goto error; } MMAL_PARAMETER_UINT32_T param3 = {{ MMAL_PARAMETER_VIDEO_ENCODE_MAX_QUANT, sizeof(param)}, state->quantisationMaxParameter}; status = mmal_port_parameter_set(encoder_output, ¶m3.hdr); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set max QP"); goto error; } } if (state->encoding == MMAL_ENCODING_H264) { MMAL_PARAMETER_VIDEO_PROFILE_T param; param.hdr.id = MMAL_PARAMETER_PROFILE; param.hdr.size = sizeof(param); param.profile[0].profile = state->profile; param.profile[0].level = MMAL_VIDEO_LEVEL_H264_4; // This is the only value supported status = mmal_port_parameter_set(encoder_output, ¶m.hdr); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set H264 profile"); goto error; } } if (mmal_port_parameter_set_boolean(encoder_input, MMAL_PARAMETER_VIDEO_IMMUTABLE_INPUT, state->immutableInput) != MMAL_SUCCESS) { vcos_log_error("Unable to set immutable input flag"); // Continue rather than abort.. } //set INLINE HEADER flag to generate SPS and PPS for every IDR if requested if (mmal_port_parameter_set_boolean(encoder_output, MMAL_PARAMETER_VIDEO_ENCODE_INLINE_HEADER, state->bInlineHeaders) != MMAL_SUCCESS) { vcos_log_error("failed to set INLINE HEADER FLAG parameters"); // Continue rather than abort.. } //set Encode SPS Timing if (mmal_port_parameter_set_boolean(encoder_output, MMAL_PARAMETER_VIDEO_ENCODE_SPS_TIMING, MMAL_TRUE) != MMAL_SUCCESS) { vcos_log_error("failed to set SPS TIMING HEADER FLAG parameters"); // Continue rather than abort.. } // set Minimise Fragmentation if (mmal_port_parameter_set_boolean(encoder_output, MMAL_PARAMETER_MINIMISE_FRAGMENTATION, MMAL_FALSE) != MMAL_SUCCESS) { vcos_log_error("failed to set SPS TIMING HEADER FLAG parameters"); // Continue rather than abort.. } // Adaptive intra refresh settings if (state->encoding == MMAL_ENCODING_H264 && state->intra_refresh_type != -1) { MMAL_PARAMETER_VIDEO_INTRA_REFRESH_T param; param.hdr.id = MMAL_PARAMETER_VIDEO_INTRA_REFRESH; param.hdr.size = sizeof(param); // Get first so we don't overwrite anything unexpectedly status = mmal_port_parameter_get(encoder_output, ¶m.hdr); if (status != MMAL_SUCCESS) { vcos_log_warn("Unable to get existing H264 intra-refresh values. Please update your firmware"); // Set some defaults, don't just pass random stack data param.air_mbs = param.air_ref = param.cir_mbs = param.pir_mbs = 0; } param.refresh_mode = state->intra_refresh_type; //if (state->intra_refresh_type == MMAL_VIDEO_INTRA_REFRESH_CYCLIC_MROWS) // param.cir_mbs = 10; status = mmal_port_parameter_set(encoder_output, ¶m.hdr); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to set H264 intra-refresh values"); goto error; } } #endif /* NOT_REQUIRED */ // Enable component status = mmal_component_enable(encoder); if (status != MMAL_SUCCESS) { vcos_log_error("Unable to enable video encoder component"); goto error; } #ifdef __NOT_REQURED__ /* Create pool of buffer headers for the output port to consume */ pool = mmal_port_pool_create(encoder_output, encoder_output->buffer_num, encoder_output->buffer_size); if (!pool) { vcos_log_error("Failed to create buffer header pool for encoder output port %s", encoder_output->name); } state->encoder_pool = pool; state->encoder_component = encoder; #endif /* NOT_REQUIRED */ return status; error: if (encoder) mmal_component_destroy(encoder); state->encoder_component = NULL; return status; }
/** * main */ int main(int argc, const char **argv) { // Our main data storage vessel.. RASPIVID_STATE state; int exit_code = EX_OK; MMAL_STATUS_T status = MMAL_SUCCESS; MMAL_PORT_T *camera_preview_port = NULL; MMAL_PORT_T *camera_video_port = NULL; MMAL_PORT_T *camera_still_port = NULL; MMAL_PORT_T *preview_input_port = NULL; MMAL_PORT_T *encoder_input_port = NULL; MMAL_PORT_T *encoder_output_port = NULL; FILE *output_file = NULL; bcm_host_init(); // Register our application with the logging system vcos_log_register("RaspiVid", VCOS_LOG_CATEGORY); signal(SIGINT, signal_handler); default_status(&state); // Do we have any parameters if (argc == 1) { fprintf(stderr, "\n%s Camera App %s\n\n", basename(argv[0]), VERSION_STRING); display_valid_parameters(basename(argv[0])); exit(EX_USAGE); } // Parse the command line and put options in to our status structure if (parse_cmdline(argc, argv, &state)) { status = -1; exit(EX_USAGE); } if (state.verbose) { fprintf(stderr, "\n%s Camera App %s\n\n", basename(argv[0]), VERSION_STRING); dump_status(&state); } // OK, we have a nice set of parameters. Now set up our components // We have three components. Camera, Preview and encoder. if ((status = create_camera_component(&state)) != MMAL_SUCCESS) { vcos_log_error("%s: Failed to create camera component", __func__); exit_code = EX_SOFTWARE; } else if ((status = raspipreview_create(&state.preview_parameters)) != MMAL_SUCCESS) { vcos_log_error("%s: Failed to create preview component", __func__); destroy_camera_component(&state); exit_code = EX_SOFTWARE; } else if ((status = create_encoder_component(&state)) != MMAL_SUCCESS) { vcos_log_error("%s: Failed to create encode component", __func__); raspipreview_destroy(&state.preview_parameters); destroy_camera_component(&state); exit_code = EX_SOFTWARE; } else { PORT_USERDATA callback_data; if (state.verbose) fprintf(stderr, "Starting component connection stage\n"); camera_preview_port = state.camera_component->output[MMAL_CAMERA_PREVIEW_PORT]; camera_video_port = state.camera_component->output[MMAL_CAMERA_VIDEO_PORT]; camera_still_port = state.camera_component->output[MMAL_CAMERA_CAPTURE_PORT]; preview_input_port = state.preview_parameters.preview_component->input[0]; encoder_input_port = state.encoder_component->input[0]; encoder_output_port = state.encoder_component->output[0]; if (state.preview_parameters.wantPreview ) { if (state.verbose) { fprintf(stderr, "Connecting camera preview port to preview input port\n"); fprintf(stderr, "Starting video preview\n"); } // Connect camera to preview status = connect_ports(camera_preview_port, preview_input_port, &state.preview_connection); } else { status = MMAL_SUCCESS; } if (status == MMAL_SUCCESS) { if (state.verbose) fprintf(stderr, "Connecting camera stills port to encoder input port\n"); // Now connect the camera to the encoder status = connect_ports(camera_video_port, encoder_input_port, &state.encoder_connection); if (status != MMAL_SUCCESS) { vcos_log_error("%s: Failed to connect camera video port to encoder input", __func__); goto error; } if (state.filename) { if (state.filename[0] == '-') { output_file = stdout; // Ensure we don't upset the output stream with diagnostics/info state.verbose = 0; } else { if (state.verbose) fprintf(stderr, "Opening output file \"%s\"\n", state.filename); output_file = fopen(state.filename, "wb"); } if (!output_file) { // Notify user, carry on but discarding encoded output buffers vcos_log_error("%s: Error opening output file: %s\nNo output file will be generated\n", __func__, state.filename); } } // Set up our userdata - this is passed though to the callback where we need the information. callback_data.file_handle = output_file; callback_data.pstate = &state; callback_data.abort = 0; encoder_output_port->userdata = (struct MMAL_PORT_USERDATA_T *)&callback_data; if (state.verbose) fprintf(stderr, "Enabling encoder output port\n"); // Enable the encoder output port and tell it its callback function status = mmal_port_enable(encoder_output_port, encoder_buffer_callback); if (status != MMAL_SUCCESS) { vcos_log_error("Failed to setup encoder output"); goto error; } if (state.demoMode) { // Run for the user specific time.. int num_iterations = state.timeout / state.demoInterval; int i; if (state.verbose) fprintf(stderr, "Running in demo mode\n"); for (i=0;state.timeout == 0 || i<num_iterations;i++) { raspicamcontrol_cycle_test(state.camera_component); vcos_sleep(state.demoInterval); } } else { // Only encode stuff if we have a filename and it opened if (output_file) { int wait; if (state.verbose) fprintf(stderr, "Starting video capture\n"); if (mmal_port_parameter_set_boolean(camera_video_port, MMAL_PARAMETER_CAPTURE, 1) != MMAL_SUCCESS) { goto error; } // Send all the buffers to the encoder output port { int num = mmal_queue_length(state.encoder_pool->queue); int q; for (q=0;q<num;q++) { MMAL_BUFFER_HEADER_T *buffer = mmal_queue_get(state.encoder_pool->queue); if (!buffer) vcos_log_error("Unable to get a required buffer %d from pool queue", q); if (mmal_port_send_buffer(encoder_output_port, buffer)!= MMAL_SUCCESS) vcos_log_error("Unable to send a buffer to encoder output port (%d)", q); } } // Now wait until we need to stop. Whilst waiting we do need to check to see if we have aborted (for example // out of storage space) // Going to check every ABORT_INTERVAL milliseconds for (wait = 0; state.timeout == 0 || wait < state.timeout; wait+= ABORT_INTERVAL) { vcos_sleep(ABORT_INTERVAL); if (callback_data.abort) break; } if (state.verbose) fprintf(stderr, "Finished capture\n"); } else { if (state.timeout) vcos_sleep(state.timeout); else for (;;) vcos_sleep(ABORT_INTERVAL); } } } else { mmal_status_to_int(status); vcos_log_error("%s: Failed to connect camera to preview", __func__); } error: mmal_status_to_int(status); if (state.verbose) fprintf(stderr, "Closing down\n"); // Disable all our ports that are not handled by connections check_disable_port(camera_still_port); check_disable_port(encoder_output_port); if (state.preview_parameters.wantPreview ) mmal_connection_destroy(state.preview_connection); mmal_connection_destroy(state.encoder_connection); // Can now close our file. Note disabling ports may flush buffers which causes // problems if we have already closed the file! if (output_file && output_file != stdout) fclose(output_file); /* Disable components */ if (state.encoder_component) mmal_component_disable(state.encoder_component); if (state.preview_parameters.preview_component) mmal_component_disable(state.preview_parameters.preview_component); if (state.camera_component) mmal_component_disable(state.camera_component); destroy_encoder_component(&state); raspipreview_destroy(&state.preview_parameters); destroy_camera_component(&state); if (state.verbose) fprintf(stderr, "Close down completed, all components disconnected, disabled and destroyed\n\n"); } if (status != MMAL_SUCCESS) raspicamcontrol_check_configuration(128); return exit_code; }
/** * main */ int main(int argc, const char **argv) { // Our main data storage vessel.. RASPIVID_STATE state; MMAL_STATUS_T status = -1; MMAL_PORT_T *camera_video_port = NULL; MMAL_PORT_T *camera_still_port = NULL; MMAL_PORT_T *preview_input_port = NULL; MMAL_PORT_T *encoder_input_port = NULL; MMAL_PORT_T *encoder_output_port = NULL; time_t timer_begin,timer_end; double secondsElapsed; bcm_host_init(); signal(SIGINT, signal_handler); // read default status default_status(&state); // init windows and OpenCV Stuff cvNamedWindow("camcvWin", CV_WINDOW_AUTOSIZE); int w=state.width; int h=state.height; int minsz = 20; int maxsz = 80; float scalefact = 1.2; int minneigh = 3; char tracking = 1; int i; // List of long program options, to be passed as "--option=xx" char *params[] = {"minsize", "maxsize", "scalefactor", "minneighbors", "disabletracking"}; for (i = 1; i < argc; i++) { const char *s = argv[i]; int parnum; if (s[0] == '-' && s[1] == '-') { for (parnum = 0; parnum < sizeof(params) / sizeof(*params); parnum++) { int len = strlen(params[parnum]); if (strstr(s + 2, params[parnum]) == s + 2 && s[len + 2] == '=') { s += len + 3; switch (parnum) { case 0: minsz = atoi(s); break; case 1: maxsz = atoi(s); break; case 2: scalefact = atof(s); break; case 3: minneigh = atoi(s); break; case 4: if (!strcmp(s, "true")) tracking = 0; else if (!strcmp(s, "false")) tracking = 1; else fprintf(stderr, "Unknown option for --disabletracking: '%s'. Known values are 'true' and 'false'\n", s); } break; } } } } fprintf(stderr, "Minimum window search size: %dpx\n", minsz); fprintf(stderr, "Maximum window search size: %dpx\n", maxsz); fprintf(stderr, "Scale factor: %f\n", scalefact); fprintf(stderr, "Minimum required neighbors: %d\n", minneigh); fprintf(stderr, "Tracking: %s\n", tracking ? "true" : "false"); initFaceDetect(state.width, state.height, scalefact, minneigh, minsz, maxsz, tracking); // create camera if (!create_camera_component(&state)) { vcos_log_error("%s: Failed to create camera component", __func__); } else if (raspipreview_create(&state.preview_parameters) != MMAL_SUCCESS) { vcos_log_error("%s: Failed to create preview component", __func__); destroy_camera_component(&state); } else { PORT_USERDATA callback_data; camera_video_port = state.camera_component->output[MMAL_CAMERA_VIDEO_PORT]; camera_still_port = state.camera_component->output[MMAL_CAMERA_CAPTURE_PORT]; VCOS_STATUS_T vcos_status; callback_data.pstate = &state; vcos_status = vcos_semaphore_create(&callback_data.complete_semaphore, "RaspiStill-sem", 0); vcos_assert(vcos_status == VCOS_SUCCESS); // assign data to use for callback camera_video_port->userdata = (struct MMAL_PORT_USERDATA_T *)&callback_data; // init timer time(&timer_begin); // start capture if (mmal_port_parameter_set_boolean(camera_video_port, MMAL_PARAMETER_CAPTURE, 1) != MMAL_SUCCESS) { goto error; } // Send all the buffers to the video port int num = mmal_queue_length(state.video_pool->queue); int q; for (q=0;q<num;q++) { MMAL_BUFFER_HEADER_T *buffer = mmal_queue_get(state.video_pool->queue); if (!buffer) vcos_log_error("Unable to get a required buffer %d from pool queue", q); if (mmal_port_send_buffer(camera_video_port, buffer)!= MMAL_SUCCESS) vcos_log_error("Unable to send a buffer to encoder output port (%d)", q); } // Now wait until we need to stop vcos_sleep(state.timeout); error: mmal_status_to_int(status); // Disable all our ports that are not handled by connections check_disable_port(camera_still_port); if (state.camera_component) mmal_component_disable(state.camera_component); //destroy_encoder_component(&state); raspipreview_destroy(&state.preview_parameters); destroy_camera_component(&state); } if (status != 0) raspicamcontrol_check_configuration(128); time(&timer_end); /* get current time; same as: timer = time(NULL) */ secondsElapsed = difftime(timer_end,timer_begin); printf ("%.f seconds for %d frames : FPS = %f\n", secondsElapsed,nCount,(float)((float)(nCount)/secondsElapsed)); return 0; }