/* Connect a component output[portnum] to a components input[0] using | TUNNELLING to keep processing within the GPU (no callbacks to the | ARM for these connections). */ boolean ports_tunnel_connect(CameraObject *out, int port_num, CameraObject *in) { MMAL_PORT_T *out_port, *in_port; MMAL_CONNECTION_T *connection = NULL; MMAL_STATUS_T status; char *msg = "mmal_connection_create"; boolean result = TRUE; if (!out->component || !in->component) return FALSE; out_port = out->component->output[port_num]; in_port = in->component->input[0]; if ((status = mmal_connection_create(&connection, out_port, in_port, MMAL_CONNECTION_FLAG_ALLOCATION_ON_INPUT | MMAL_CONNECTION_FLAG_TUNNELLING)) == MMAL_SUCCESS) { msg = "mmal_connection_enable"; status = mmal_connection_enable(connection); } if (status != MMAL_SUCCESS) { if (connection) mmal_connection_destroy(connection); connection = NULL; result = FALSE; log_printf("ports_tunnel_connect %s_out->%s_in: %s failed. Status %s\n", out->name, in->name, msg, mmal_status[status]); } in->input_connection = connection; return result; }
MMAL_STATUS_T Private_Impl_Still::connectPorts ( MMAL_PORT_T *output_port, MMAL_PORT_T *input_port, MMAL_CONNECTION_T **connection ) { MMAL_STATUS_T status = mmal_connection_create ( connection, output_port, input_port, MMAL_CONNECTION_FLAG_TUNNELLING | MMAL_CONNECTION_FLAG_ALLOCATION_ON_INPUT ); if ( status == MMAL_SUCCESS ) { status = mmal_connection_enable ( *connection ); if ( status != MMAL_SUCCESS ) mmal_connection_destroy ( *connection ); } return status; }
/** * Connect two specific ports together * * @param output_port Pointer the output port * @param input_port Pointer the input port * @param Pointer to a mmal connection pointer, reassigned if function successful * @return Returns a MMAL_STATUS_T giving result of operation * */ static MMAL_STATUS_T connect_ports(MMAL_PORT_T *output_port, MMAL_PORT_T *input_port, MMAL_CONNECTION_T **connection) { MMAL_STATUS_T status; status = mmal_connection_create(connection, output_port, input_port, MMAL_CONNECTION_FLAG_TUNNELLING | MMAL_CONNECTION_FLAG_ALLOCATION_ON_INPUT); if (status == MMAL_SUCCESS) { status = mmal_connection_enable(*connection); if (status != MMAL_SUCCESS) { vcos_log_error("Failed to connect ports %s and %s - status %d", output_port->name, input_port->name); mmal_connection_destroy(*connection); } } return status; }
int setup_preview(PORT_USERDATA *userdata) { MMAL_STATUS_T status; MMAL_COMPONENT_T *preview = 0; MMAL_CONNECTION_T *camera_preview_connection = 0; MMAL_PORT_T *preview_input_port; status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_RENDERER, &preview); if (status != MMAL_SUCCESS) { fprintf(stderr, "Error: unable to create preview (%u)\n", status); return -1; } userdata->preview = preview; preview_input_port = preview->input[0]; { MMAL_DISPLAYREGION_T param; param.hdr.id = MMAL_PARAMETER_DISPLAYREGION; param.hdr.size = sizeof (MMAL_DISPLAYREGION_T); param.set = MMAL_DISPLAY_SET_LAYER; param.layer = 0; param.set |= MMAL_DISPLAY_SET_FULLSCREEN; param.fullscreen = 1; status = mmal_port_parameter_set(preview_input_port, ¶m.hdr); if (status != MMAL_SUCCESS && status != MMAL_ENOSYS) { fprintf(stderr, "Error: unable to set preview port parameters (%u)\n", status); return -1; } } status = mmal_connection_create(&camera_preview_connection, userdata->camera_preview_port, preview_input_port, MMAL_CONNECTION_FLAG_TUNNELLING | MMAL_CONNECTION_FLAG_ALLOCATION_ON_INPUT); if (status != MMAL_SUCCESS) { fprintf(stderr, "Error: unable to create connection (%u)\n", status); return -1; } status = mmal_connection_enable(camera_preview_connection); if (status != MMAL_SUCCESS) { fprintf(stderr, "Error: unable to enable connection (%u)\n", status); return -1; } //fprintf(stderr, "INFO: preview created\n"); return 0; }
bool CCameraOutput::Init(int width, int height, MMAL_COMPONENT_T* input_component, int input_port_idx, bool do_argb_conversion) { printf("Init camera output with %d/%d\n",width,height); Width = width; Height = height; MMAL_COMPONENT_T *resizer = 0; MMAL_CONNECTION_T* connection = 0; MMAL_STATUS_T status; MMAL_POOL_T* video_buffer_pool = 0; MMAL_QUEUE_T* output_queue = 0; //got the port we're receiving from MMAL_PORT_T* input_port = input_component->output[input_port_idx]; //check if user wants conversion to argb or the width or height is different to the input if(do_argb_conversion || width != input_port->format->es->video.width || height != input_port->format->es->video.height) { //create the resizing component, reading from the splitter output resizer = CreateResizeComponentAndSetupPorts(input_port,do_argb_conversion); if(!resizer) goto error; //create and enable a connection between the video output and the resizer input status = mmal_connection_create(&connection, input_port, resizer->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(connection); if (status != MMAL_SUCCESS) { printf("Failed to enable connection\n"); goto error; } //set the buffer pool port to be the resizer output BufferPort = resizer->output[0]; } else { //no convert/resize needed so just set the buffer pool port to be the input port BufferPort = input_port; } //setup the video buffer callback video_buffer_pool = EnablePortCallbackAndCreateBufferPool(BufferPort,VideoBufferCallback,3); if(!video_buffer_pool) goto error; //create the output queue output_queue = mmal_queue_create(); if(!output_queue) { printf("Failed to create output queue\n"); goto error; } ResizerComponent = resizer; BufferPool = video_buffer_pool; OutputQueue = output_queue; Connection = connection; return true; error: if(output_queue) mmal_queue_destroy(output_queue); if(video_buffer_pool) mmal_port_pool_destroy(resizer->output[0],video_buffer_pool); if(connection) mmal_connection_destroy(connection); if(resizer) mmal_component_destroy(resizer); return false; }
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); // Change default parameter, i.e .rotate image int rotation = 90; int my_rotation = ((rotation % 360 ) / 90) * 90; CameraParameters.rotation = my_rotation; //ret = mmal_port_parameter_set_int32(camera->output[0], MMAL_PARAMETER_ROTATION, my_rotation); //mmal_port_parameter_set_int32(camera->output[1], MMAL_PARAMETER_ROTATION, my_rotation); //mmal_port_parameter_set_int32(camera->output[2], MMAL_PARAMETER_ROTATION, my_rotation); #ifdef WITH_ENCODER MMAL_COMPONENT_T *encoder = 0; #endif 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; //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; } } #ifdef WITH_ENCODER encoder = CreateEncoderComponentAndSetupPorts(); if (!encoder) goto error; #endif //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]; } } #ifdef WITH_ENCODER if(encoder){} #endif return false; }
int main(int argc, char **argv) { MMAL_COMPONENT_T *camera =0; MMAL_COMPONENT_T *preview=0; MMAL_COMPONENT_T *encoder=0; MMAL_CONNECTION_T *preview_conn=0; MMAL_CONNECTION_T *encoder_conn=0; USERDATA_T callback_data; // bcm should be initialized before any GPU call is made bcm_host_init(); setNonDefaultOptions(argc, argv); // Open file to save the video open_new_file_handle(&callback_data, output_file_name); fprintf(stderr, "Output Filename: %s\n", output_file_name); // Create Camera, set default values and enable it vcos_assert((mmal_component_create(MMAL_COMPONENT_DEFAULT_CAMERA, &camera) == MMAL_SUCCESS) && "Failed creating camera component"); vcos_assert((set_camera_component_defaults(camera)) == MMAL_SUCCESS && "Failed setting camera components default values"); vcos_assert((mmal_component_enable(camera) == MMAL_SUCCESS) && "Failed to enable camera component"); // Create Preview, set default values and enable it vcos_assert((mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_RENDERER, &preview) == MMAL_SUCCESS) && "Failed creating preview component"); vcos_assert((set_preview_component_defaults(preview) == MMAL_SUCCESS) && "Failed setting preview components default values"); vcos_assert((mmal_component_enable(preview) == MMAL_SUCCESS) && "Failed to enable camera component"); // Create Encoder, set defaults, enable it and create encoder pool vcos_assert((mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_ENCODER, &encoder) == MMAL_SUCCESS) && "Failed to create encoder component"); vcos_assert((encoder->input_num && encoder->output_num) && "Video encoder does not have input/output ports\n"); set_encoder_component_defaults(encoder); vcos_assert((mmal_component_enable(encoder) == MMAL_SUCCESS) && "Failed enabling encoder component"); callback_data.pool = (MMAL_POOL_T *)mmal_port_pool_create(encoder->output[0], encoder->output[0]->buffer_num, encoder->output[0]->buffer_size); vcos_assert(callback_data.pool && "Failed creating encoder pool\n"); // Setup connections vcos_assert((mmal_connection_create(&preview_conn, camera->output[0], preview->input[0], MMAL_CONNECTION_FLAG_TUNNELLING | MMAL_CONNECTION_FLAG_ALLOCATION_ON_INPUT) == MMAL_SUCCESS) && "Failed stablishing connection between camera output 0 and preview"); vcos_assert((mmal_connection_enable(preview_conn) == MMAL_SUCCESS) && "Failed enabling connection between camera output 0 and preview"); vcos_assert((mmal_connection_create(&encoder_conn, camera->output[1], encoder->input[0], // MMAL_CONNECTION_FLAG_TUNNELLING | MMAL_CONNECTION_FLAG_ALLOCATION_ON_INPUT) == MMAL_SUCCESS) MMAL_CONNECTION_FLAG_ALLOCATION_ON_INPUT) == MMAL_SUCCESS) && "Failed creating encoder connection to capture (camera output 1)"); vcos_assert((mmal_connection_enable(encoder_conn) == MMAL_SUCCESS) && "Failed enabling encoder connection to capture (campera output 1)"); encoder_conn->callback = connection_video2encoder_callback; // Set callback and enable encoder port encoder->output[0]->userdata = (struct MMAL_PORT_USERDATA_T *)&callback_data; vcos_assert(MMAL_SUCCESS == mmal_port_enable(encoder->output[0], encoder_callback)); // Send the buffer to encode output port MMAL_BUFFER_HEADER_T *buffer = mmal_queue_get(callback_data.pool->queue); vcos_assert((mmal_port_send_buffer(encoder->output[0], buffer)== MMAL_SUCCESS) && "Unable to send buffer to encoder output port"); vcos_assert((mmal_port_parameter_set_boolean(camera->output[1], MMAL_PARAMETER_CAPTURE, 1) == MMAL_SUCCESS) && "Unable to set camera->output[1] capture parameter"); consume_queue_on_connection(encoder_conn->out, encoder_conn->pool->queue); while(1) { vcos_sleep(1000); // wait for exit call if (exit_prog){ vcos_sleep(500); // exit called, wait for all buffers be flushed break; } } return 0; }
static MMAL_STATUS_T mmalplay_connection_create(MMALPLAY_T *ctx, MMAL_PORT_T *out, MMAL_PORT_T *in, uint32_t flags) { MMAL_CONNECTION_T **connection = &ctx->connection[ctx->connection_num]; uint32_t encoding_override = MMAL_ENCODING_UNKNOWN; MMAL_RECT_T *rect_override = NULL; MMAL_BOOL_T format_override = MMAL_FALSE; MMAL_STATUS_T status; if (ctx->connection_num >= MMAL_COUNTOF(ctx->connection)) return MMAL_ENOMEM; /* Globally enable tunnelling if requested by the user */ flags |= ctx->options.tunnelling ? MMAL_CONNECTION_FLAG_TUNNELLING : 0; /* Apply any override to the format specified by the user */ if (out == ctx->video_out_port) { encoding_override = ctx->options.output_format; rect_override = &ctx->options.output_rect; } else if (out == ctx->converter_out_port) { encoding_override = ctx->options.render_format; rect_override = &ctx->options.render_rect; } if (encoding_override != MMAL_ENCODING_UNKNOWN && encoding_override != out->format->encoding) { out->format->encoding = encoding_override; format_override = MMAL_TRUE; } if (rect_override && rect_override->width && rect_override->height) { out->format->es->video.crop = *rect_override; out->format->es->video.width = rect_override->width; out->format->es->video.height = rect_override->height; format_override = MMAL_TRUE; } if (format_override) { status = mmal_port_format_commit(out); if (status != MMAL_SUCCESS) { LOG_ERROR("cannot override format on output port %s", out->name); return status; } } /* Create the actual connection */ status = mmal_connection_create(connection, out, in, flags); if (status != MMAL_SUCCESS) { LOG_ERROR("cannot create connection"); return status; } /* Set our connection callback */ (*connection)->callback = mmalplay_connection_cb; (*connection)->user_data = (void *)ctx; log_format(out->format, out); log_format(in->format, in); ctx->connection_num++; return MMAL_SUCCESS; }
bool CMMALVideo::CreateDeinterlace(EINTERLACEMETHOD interlace_method) { MMAL_STATUS_T status; if (g_advancedSettings.CanLogComponent(LOGVIDEO)) CLog::Log(LOGDEBUG, "%s::%s method:%d", CLASSNAME, __func__, interlace_method); assert(!m_deint); assert(m_dec_output == m_dec->output[0]); status = mmal_port_disable(m_dec_output); if (status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to disable decoder output port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } /* Create deinterlace filter */ status = mmal_component_create("vc.ril.image_fx", &m_deint); if (status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to create deinterlace component (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } MMAL_PARAMETER_IMAGEFX_PARAMETERS_T imfx_param = {{MMAL_PARAMETER_IMAGE_EFFECT_PARAMETERS, sizeof(imfx_param)}, interlace_method == VS_INTERLACEMETHOD_MMAL_ADVANCED || interlace_method == VS_INTERLACEMETHOD_MMAL_ADVANCED_HALF ? MMAL_PARAM_IMAGEFX_DEINTERLACE_ADV : MMAL_PARAM_IMAGEFX_DEINTERLACE_FAST, 3, {3, 0, interlace_method == VS_INTERLACEMETHOD_MMAL_ADVANCED_HALF || interlace_method == VS_INTERLACEMETHOD_MMAL_BOB_HALF }}; status = mmal_port_parameter_set(m_deint->output[0], &imfx_param.hdr); if (status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to set deinterlace parameters (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } MMAL_PORT_T *m_deint_input = m_deint->input[0]; m_deint_input->userdata = (struct MMAL_PORT_USERDATA_T *)this; // Now connect the decoder output port to deinterlace input port status = mmal_connection_create(&m_deint_connection, m_dec->output[0], m_deint->input[0], MMAL_CONNECTION_FLAG_TUNNELLING | MMAL_CONNECTION_FLAG_ALLOCATION_ON_INPUT); if (status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to connect deinterlacer component %s (status=%x %s)", CLASSNAME, __func__, m_deint->name, status, mmal_status_to_string(status)); return false; } status = mmal_connection_enable(m_deint_connection); if (status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to enable connection %s (status=%x %s)", CLASSNAME, __func__, m_deint->name, status, mmal_status_to_string(status)); return false; } mmal_format_copy(m_deint->output[0]->format, m_es_format); status = mmal_port_format_commit(m_deint->output[0]); if (status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to commit deint output format (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } status = mmal_component_enable(m_deint); if (status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to enable deinterlacer component %s (status=%x %s)", CLASSNAME, __func__, m_deint->name, status, mmal_status_to_string(status)); return false; } m_deint->output[0]->buffer_size = m_deint->output[0]->buffer_size_min; m_deint->output[0]->buffer_num = m_deint->output[0]->buffer_num_recommended; m_deint->output[0]->userdata = (struct MMAL_PORT_USERDATA_T *)this; status = mmal_port_enable(m_deint->output[0], dec_output_port_cb_static); if (status != MMAL_SUCCESS) { CLog::Log(LOGERROR, "%s::%s Failed to enable decoder output port (status=%x %s)", CLASSNAME, __func__, status, mmal_status_to_string(status)); return false; } m_dec_output = m_deint->output[0]; m_interlace_method = interlace_method; return true; }
/* 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; }
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"); } }
/** Create an instance of a component */ static MMAL_STATUS_T mmal_component_create_aggregator_pipeline(const char *full_name, const char *component_names, MMAL_COMPONENT_T *component) { MMAL_GRAPH_T *graph = 0; MMAL_COMPONENT_T *subcomponent[2] = {0}; MMAL_STATUS_T status = MMAL_ENOMEM; unsigned int length; char *orig, *names; length = strlen(component_names); names = orig = vcos_calloc(1, length + 1, "mmal aggregator"); if (!names) goto error; memcpy(names, component_names, length); /* We'll build the aggregator using a graph */ status = mmal_graph_create(&graph, sizeof(MMAL_GRAPH_USERDATA_T)); if (status != MMAL_SUCCESS) goto error; graph->pf_parameter_get = aggregator_parameter_get; graph->pf_parameter_set = aggregator_parameter_set; /* Iterate through all the specified components */ while (*names) { MMAL_CONNECTION_T *connection; const char *name; /* Switch to a new connection */ if (subcomponent[0]) mmal_component_destroy(subcomponent[0]); subcomponent[0] = subcomponent[1]; subcomponent[1] = 0; /* Extract the name of the next component */ for (name = names; *names && *names != ':'; names++); /* Replace the separator */ if (*names) *(names++) = 0; /* Skip empty strings */ if (!*name) continue; status = mmal_component_create(name, &subcomponent[1]); if (status != MMAL_SUCCESS) goto error; status = mmal_graph_add_component(graph, subcomponent[1]); if (status != MMAL_SUCCESS) goto error; /* Special case for dealing with the first component in the chain */ if (!subcomponent[0]) { /* Add first input port if any */ if (subcomponent[1]->input_num) { status = mmal_graph_add_port(graph, subcomponent[1]->input[0]); if (status != MMAL_SUCCESS) goto error; } continue; } /* Create connection between the 2 ports */ if (subcomponent[0]->output_num < 1 || subcomponent[1]->input_num < 1) goto error; status = mmal_connection_create(&connection, subcomponent[0]->output[0], subcomponent[1]->input[0], 0); if (status != MMAL_SUCCESS) goto error; status = mmal_graph_add_connection(graph, connection); /* Now the connection is added to the graph we don't care about it anymore */ mmal_connection_destroy(connection); if (status != MMAL_SUCCESS) goto error; } /* Add last output port if any */ if (subcomponent[1] && subcomponent[1]->output_num && subcomponent[1]->output[0]) { status = mmal_graph_add_port(graph, subcomponent[1]->output[0]); if (status != MMAL_SUCCESS) goto error; } /* Build the graph */ component->priv->module = (struct MMAL_COMPONENT_MODULE_T *)graph; status = mmal_graph_component_constructor(full_name, component); if (status != MMAL_SUCCESS) goto error; end: if (subcomponent[0]) mmal_component_destroy(subcomponent[0]); if (subcomponent[1]) mmal_component_destroy(subcomponent[1]); vcos_free(orig); return status; error: if (graph) mmal_graph_destroy(graph); goto end; }
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; //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)); //custom parameters raspicamcontrol_set_saturation(camera, 0); raspicamcontrol_set_contrast(camera, 100); raspicamcontrol_set_brightness(camera, 50); //raspicamcontrol_set_exposure_mode(camera, MMAL_PARAM_EXPOSUREMODE_OFF); //raspicamcontrol_set_awb_mode(camera, MMAL_PARAM_AWBMODE_OFF); raspicamcontrol_set_shutter_speed(camera, 2400); //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; }
int main(int argc, char** argv) { MMAL_COMPONENT_T *camera = 0; MMAL_COMPONENT_T *preview = 0; MMAL_ES_FORMAT_T *format; MMAL_STATUS_T status; MMAL_PORT_T *camera_preview_port = NULL, *camera_video_port = NULL, *camera_still_port = NULL; MMAL_PORT_T *preview_input_port = NULL; MMAL_CONNECTION_T *camera_preview_connection = 0; printf("Running...\n"); bcm_host_init(); status = mmal_component_create(MMAL_COMPONENT_DEFAULT_CAMERA, &camera); if (status != MMAL_SUCCESS) { printf("Error: create camera %x\n", status); return -1; } 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 = 1280, .max_preview_video_h = 720, .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_preview_port->format; format->encoding = MMAL_ENCODING_OPAQUE; format->encoding_variant = MMAL_ENCODING_I420; format->es->video.width = 1280; format->es->video.height = 720; format->es->video.crop.x = 0; format->es->video.crop.y = 0; format->es->video.crop.width = 1280; format->es->video.crop.height = 720; status = mmal_port_format_commit(camera_preview_port); if (status != MMAL_SUCCESS) { printf("Error: camera viewfinder format couldn't be set\n"); return -1; } status = mmal_component_enable(camera); status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_RENDERER, &preview); if (status != MMAL_SUCCESS) { printf("Error: unable to create preview (%u)\n", status); return -1; } preview_input_port = preview->input[0]; { MMAL_DISPLAYREGION_T param; param.hdr.id = MMAL_PARAMETER_DISPLAYREGION; param.hdr.size = sizeof (MMAL_DISPLAYREGION_T); param.set = MMAL_DISPLAY_SET_LAYER; param.layer = 0; param.set |= MMAL_DISPLAY_SET_FULLSCREEN; param.fullscreen = 1; status = mmal_port_parameter_set(preview_input_port, ¶m.hdr); if (status != MMAL_SUCCESS && status != MMAL_ENOSYS) { printf("Error: unable to set preview port parameters (%u)\n", status); return -1; } } status = mmal_connection_create(&camera_preview_connection, camera_preview_port, preview_input_port, MMAL_CONNECTION_FLAG_TUNNELLING | MMAL_CONNECTION_FLAG_ALLOCATION_ON_INPUT); if (status != MMAL_SUCCESS) { printf("Error: unable to create connection (%u)\n", status); return -1; } status = mmal_connection_enable(camera_preview_connection); if (status != MMAL_SUCCESS) { printf("Error: unable to enable connection (%u)\n", status); return -1; } while (1); return 0; }