代码拉取完成,页面将自动刷新
/*
Copyright (c) 2013, Broadcom Europe Ltd
Copyright (c) 2013, James Hughes
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* \file RaspiVid.c
* Command line program to capture a camera video stream and encode it to file.
* Also optionally display a preview/viewfinder of current camera input.
*
* \date 28th Feb 2013
* \Author: James Hughes
*
* Description
*
* 3 components are created; camera, preview and video encoder.
* Camera component has three ports, preview, video and stills.
* This program connects preview and stills to the preview and video
* encoder. Using mmal we don't need to worry about buffers between these
* components, but we do need to handle buffers from the encoder, which
* are simply written straight to the file in the requisite buffer callback.
*
* We use the RaspiCamControl code to handle the specific camera settings.
* We use the RaspiPreview code to handle the (generic) preview window
*/
// We use some GNU extensions (basename)
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
#define VERSION_STRING "v1.2"
#include "bcm_host.h"
#include "interface/vcos/vcos.h"
#include "interface/mmal/mmal.h"
#include "interface/mmal/mmal_logging.h"
#include "interface/mmal/mmal_buffer.h"
#include "interface/mmal/util/mmal_util.h"
#include "interface/mmal/util/mmal_util_params.h"
#include "interface/mmal/util/mmal_default_components.h"
#include "interface/mmal/util/mmal_connection.h"
#include "RaspiCamControl.h"
#include "RaspiPreview.h"
#include "RaspiCLI.h"
#include <semaphore.h>
/// Camera number to use - we only have one camera, indexed from 0.
#define CAMERA_NUMBER 0
// Standard port setting for the camera component
#define MMAL_CAMERA_PREVIEW_PORT 0
#define MMAL_CAMERA_VIDEO_PORT 1
#define MMAL_CAMERA_CAPTURE_PORT 2
// Video format information
#define VIDEO_FRAME_RATE_NUM 30
#define VIDEO_FRAME_RATE_DEN 1
/// Video render needs at least 2 buffers.
#define VIDEO_OUTPUT_BUFFERS_NUM 3
// Max bitrate we allow for recording
const int MAX_BITRATE = 30000000; // 30Mbits/s
/// Interval at which we check for an failure abort during capture
const int ABORT_INTERVAL = 100; // ms
int mmal_status_to_int(MMAL_STATUS_T status);
/** Structure containing all state information for the current run
*/
typedef struct
{
int timeout; /// Time taken before frame is grabbed and app then shuts down. Units are milliseconds
int width; /// Requested width of image
int height; /// requested height of image
int bitrate; /// Requested bitrate
int framerate; /// Requested frame rate (fps)
int intraperiod; /// Intra-refresh period (key frame rate)
char *filename; /// filename of output file
int verbose; /// !0 if want detailed run information
//Me int demoMode; /// Run app in demo mode
//Me int demoInterval; /// Interval between camera settings changes
int immutableInput; /// Flag to specify whether encoder works in place or creates a new buffer. Result is preview can display either
/// the camera output or the encoder output (with compression artifacts)
int useRGB; /// Flag to specify RGB output rather than YUV
RASPIPREVIEW_PARAMETERS preview_parameters; /// Preview setup parameters
RASPICAM_CAMERA_PARAMETERS camera_parameters; /// Camera setup parameters
MMAL_COMPONENT_T *camera_component; /// Pointer to the camera component
MMAL_COMPONENT_T *encoder_component; /// Pointer to the encoder component
MMAL_CONNECTION_T *preview_connection; /// Pointer to the connection from camera to preview
MMAL_CONNECTION_T *encoder_connection; /// Pointer to the connection from camera to encoder
MMAL_POOL_T *video_pool; /// Pointer to the pool of buffers used by encoder output port
} RASPIVID_STATE;
/** Struct used to pass information in encoder port userdata to callback
*/
typedef struct
{
FILE *file_handle; /// File handle to write buffer data to.
VCOS_SEMAPHORE_T complete_semaphore; /// semaphore which is posted when we reach end of frame (indicates end of capture or fault)
RASPIVID_STATE *pstate; /// pointer to our state in case required in callback
int abort; /// Set to 1 in callback if an error occurs to attempt to abort the capture
} PORT_USERDATA;
static void display_valid_parameters(char *app_name);
/// Command ID's and Structure defining our command line options
#define CommandHelp 0
#define CommandWidth 1
#define CommandHeight 2
#define CommandBitrate 3
#define CommandOutput 4
#define CommandVerbose 5
#define CommandTimeout 6
//Me #define CommandDemoMode 7
#define CommandFramerate 7
//Me #define CommandPreviewEnc 9
#define CommandIntraPeriod 8
#define CommandUseRGB 9
static COMMAND_LIST cmdline_commands[] =
{
{ CommandHelp, "-help", "?", "This help information", 0 },
{ CommandWidth, "-width", "w", "Set image width <size>. Default 1920", 1 },
{ CommandHeight, "-height", "h", "Set image height <size>. Default 1080", 1 },
{ CommandBitrate, "-bitrate", "b", "Set bitrate. Use bits per second (e.g. 10MBits/s would be -b 10000000)", 1 },
{ CommandOutput, "-output", "o", "Output filename <filename> (to write to stdout, use '-o -')", 1 },
{ CommandVerbose, "-verbose", "v", "Output verbose information during run", 0 },
{ CommandTimeout, "-timeout", "t", "Time (in ms) to capture for. If not specified, set to 5s. Zero to disable", 1 },
//Me { CommandDemoMode,"-demo", "d", "Run a demo mode (cycle through range of camera options, no capture)", 1},
{ CommandFramerate,"-framerate", "fps","Specify the frames per second to record", 1},
//Me { CommandPreviewEnc,"-penc", "e", "Display preview image *after* encoding (shows compression artifacts)", 0},
{ CommandIntraPeriod,"-intra", "g", "Specify the intra refresh period (key frame rate/GoP size)", 1},
{ CommandUseRGB, "-rgb", "rgb","Save as RGB data rather than YUV", 0},
};
static int cmdline_commands_size = sizeof(cmdline_commands) / sizeof(cmdline_commands[0]);
/**
* Assign a default set of parameters to the state passed in
*
* @param state Pointer to state structure to assign defaults to
*/
static void default_status(RASPIVID_STATE *state)
{
if (!state)
{
vcos_assert(0);
return;
}
// Default everything to zero
memset(state, 0, sizeof(RASPIVID_STATE));
// Now set anything non-zero
state->timeout = 5000; // 5s delay before take image
state->width = 1280; // Must be a multiple of 320
state->height = 960; // Must be a multiple of 240
state->bitrate = 17000000; // This is a decent default bitrate for 1080p
state->framerate = VIDEO_FRAME_RATE_NUM;
state->intraperiod = 0; // Not set
//Me state->demoMode = 0;
//Me state->demoInterval = 250; // ms
state->immutableInput = 1;
// Setup preview window defaults
raspipreview_set_defaults(&state->preview_parameters);
// Set up the camera_parameters to default
raspicamcontrol_set_defaults(&state->camera_parameters);
}
/**
* Dump image state parameters to printf. Used for debugging
*
* @param state Pointer to state structure to assign defaults to
*/
static void dump_status(RASPIVID_STATE *state)
{
if (!state)
{
vcos_assert(0);
return;
}
fprintf(stderr, "Width %d, Height %d, filename %s\n", state->width, state->height, state->filename);
fprintf(stderr, "bitrate %d, framerate %d, time delay %d\n", state->bitrate, state->framerate, state->timeout);
raspipreview_dump_parameters(&state->preview_parameters);
raspicamcontrol_dump_parameters(&state->camera_parameters);
}
/**
* Parse the incoming command line and put resulting parameters in to the state
*
* @param argc Number of arguments in command line
* @param argv Array of pointers to strings from command line
* @param state Pointer to state structure to assign any discovered parameters to
* @return Non-0 if failed for some reason, 0 otherwise
*/
static int parse_cmdline(int argc, const char **argv, RASPIVID_STATE *state)
{
// Parse the command line arguments.
// We are looking for --<something> or -<abreviation of something>
int valid = 1;
int i;
for (i = 1; i < argc && valid; i++)
{
int command_id, num_parameters;
if (!argv[i])
continue;
if (argv[i][0] != '-')
{
valid = 0;
continue;
}
// Assume parameter is valid until proven otherwise
valid = 1;
command_id = raspicli_get_command_id(cmdline_commands, cmdline_commands_size, &argv[i][1], &num_parameters);
// If we found a command but are missing a parameter, continue (and we will drop out of the loop)
if (command_id != -1 && num_parameters > 0 && (i + 1 >= argc) )
continue;
// We are now dealing with a command line option
switch (command_id)
{
case CommandHelp:
display_valid_parameters(basename(argv[0]));
return -1;
case CommandWidth: // Width > 0
if (sscanf(argv[i + 1], "%u", &state->width) != 1)
valid = 0;
else
i++;
break;
case CommandHeight: // Height > 0
if (sscanf(argv[i + 1], "%u", &state->height) != 1)
valid = 0;
else
i++;
break;
case CommandBitrate: // 1-100
if (sscanf(argv[i + 1], "%u", &state->bitrate) == 1)
{
if (state->bitrate > MAX_BITRATE)
{
state->bitrate = MAX_BITRATE;
}
i++;
}
else
valid = 0;
break;
case CommandOutput: // output filename
{
int len = strlen(argv[i + 1]);
if (len)
{
state->filename = malloc(len + 1);
vcos_assert(state->filename);
if (state->filename)
strncpy(state->filename, argv[i + 1], len);
i++;
}
else
valid = 0;
break;
}
case CommandVerbose: // display lots of data during run
state->verbose = 1;
break;
case CommandUseRGB:
state->useRGB = 1;
break;
case CommandTimeout: // Time to run viewfinder/capture
{
if (sscanf(argv[i + 1], "%u", &state->timeout) == 1)
{
// TODO : What limits do we need for timeout?
i++;
}
else
valid = 0;
break;
}
//Me case CommandDemoMode: // Run in demo mode - no capture
//Me {
//Me // Demo mode might have a timing parameter
//Me // so check if a) we have another parameter, b) its not the start of the next option
//Me if (i + 1 < argc && argv[i+1][0] != '-')
//Me {
//Me if (sscanf(argv[i + 1], "%u", &state->demoInterval) == 1)
//Me {
//Me // TODO : What limits do we need for timeout?
//Me if (state->demoInterval == 0)
//Me state->demoInterval = 250; // ms
//Me
//Me state->demoMode = 1;
//Me i++;
//Me }
//Me else
//Me valid = 0;
//Me }
//Me else
//Me {
//Me state->demoMode = 1;
//Me }
//Me
//Me break;
//Me }
case CommandFramerate: // fps to record
{
if (sscanf(argv[i + 1], "%u", &state->framerate) == 1)
{
// TODO : What limits do we need for fps 1 - 30 - 120??
i++;
}
else
valid = 0;
break;
}
//Me case CommandPreviewEnc:
//Me state->immutableInput = 0;
//Me break;
case CommandIntraPeriod: // key frame rate
{
if (sscanf(argv[i + 1], "%u", &state->intraperiod) == 1)
i++;
else
valid = 0;
break;
}
default:
{
// Try parsing for any image specific parameters
// result indicates how many parameters were used up, 0,1,2
// but we adjust by -1 as we have used one already
const char *second_arg = (i + 1 < argc) ? argv[i + 1] : NULL;
int parms_used = (raspicamcontrol_parse_cmdline(&state->camera_parameters, &argv[i][1], second_arg));
// Still unused, try preview options
if (!parms_used)
parms_used = raspipreview_parse_cmdline(&state->preview_parameters, &argv[i][1], second_arg);
// If no parms were used, this must be a bad parameters
if (!parms_used)
valid = 0;
else
i += parms_used - 1;
break;
}
}
}
if (!valid)
{
fprintf(stderr, "Invalid command line option (%s)\n", argv[i]);
return 1;
}
// Always disable verbose if output going to stdout
if (state->filename && state->filename[0] == '-')
{
state->verbose = 0;
}
return 0;
}
/**
* Display usage information for the application to stdout
*
* @param app_name String to display as the application name
*/
static void display_valid_parameters(char *app_name)
{
fprintf(stderr, "Display camera output to display, and optionally saves an H264 capture at requested bitrate\n\n");
fprintf(stderr, "\nusage: %s [options]\n\n", app_name);
fprintf(stderr, "Image parameter commands\n\n");
raspicli_display_help(cmdline_commands, cmdline_commands_size);
// Help for preview options
raspipreview_display_help();
// Now display any help information from the camcontrol code
raspicamcontrol_display_help();
fprintf(stderr, "\n");
return;
}
/**
* buffer header callback function for camera control
*
* Callback will dump buffer data to the specific file
*
* @param port Pointer to port from which callback originated
* @param buffer mmal buffer header pointer
*/
static void camera_control_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
{
if (buffer->cmd == MMAL_EVENT_PARAMETER_CHANGED)
{
}
else
{
vcos_log_error("Received unexpected camera control callback event, 0x%08x", buffer->cmd);
}
mmal_buffer_header_release(buffer);
}
/**
* buffer header callback function for encoder
*
* Callback will dump buffer data to the specific file
*
* @param port Pointer to port from which callback originated
* @param buffer mmal buffer header pointer
*/
static void video_buffer_callback(MMAL_PORT_T *port, MMAL_BUFFER_HEADER_T *buffer)
{
MMAL_BUFFER_HEADER_T *new_buffer;
// We pass our file handle and other stuff in via the userdata field.
PORT_USERDATA *pData = (PORT_USERDATA *)port->userdata;
if (pData)
{
int bytes_written = buffer->length;
vcos_assert(pData->file_handle);
if (buffer->length)
{
mmal_buffer_header_mem_lock(buffer);
bytes_written = fwrite(buffer->data, 1, buffer->length, pData->file_handle);
mmal_buffer_header_mem_unlock(buffer);
}
if (bytes_written != buffer->length)
{
vcos_log_error("Failed to write buffer data (%d from %d)- aborting", bytes_written, buffer->length);
pData->abort = 1;
}
}
else
{
vcos_log_error("Received a encoder buffer callback with no state");
}
// release buffer back to the pool
mmal_buffer_header_release(buffer);
// and send one back to the port (if still open)
if (port->is_enabled)
{
MMAL_STATUS_T status;
new_buffer = mmal_queue_get(pData->pstate->video_pool->queue);
if (new_buffer)
status = mmal_port_send_buffer(port, new_buffer);
if (!new_buffer || status != MMAL_SUCCESS)
vcos_log_error("Unable to return a buffer to the encoder port");
}
}
/**
* Create the camera component, set up its ports
*
* @param state Pointer to state control struct
*
* @return 0 if failed, pointer to component if successful
*
*/
static MMAL_COMPONENT_T *create_camera_component(RASPIVID_STATE *state)
{
MMAL_COMPONENT_T *camera = 0;
MMAL_ES_FORMAT_T *format;
MMAL_PORT_T *preview_port = NULL, *video_port = NULL, *still_port = NULL;
MMAL_STATUS_T status;
/* Create the component */
status = mmal_component_create(MMAL_COMPONENT_DEFAULT_CAMERA, &camera);
if (status != MMAL_SUCCESS)
{
vcos_log_error("Failed to create camera component");
goto error;
}
if (!camera->output_num)
{
//Me status = MMAL_ENOSYS;
vcos_log_error("Camera doesn't have output ports");
goto error;
}
preview_port = camera->output[MMAL_CAMERA_PREVIEW_PORT];
video_port = camera->output[MMAL_CAMERA_VIDEO_PORT];
still_port = camera->output[MMAL_CAMERA_CAPTURE_PORT];
// Enable the camera, and tell it its control callback function
status = mmal_port_enable(camera->control, camera_control_callback);
if (status != MMAL_SUCCESS)
{
vcos_log_error("Unable to enable control port : error %d", status);
goto error;
}
// set up the camera configuration
{
MMAL_PARAMETER_CAMERA_CONFIG_T cam_config =
{
{ MMAL_PARAMETER_CAMERA_CONFIG, sizeof(cam_config) },
.max_stills_w = state->width,
.max_stills_h = state->height,
.stills_yuv422 = 0,
.one_shot_stills = 0,
.max_preview_video_w = state->width,
.max_preview_video_h = state->height,
.num_preview_video_frames = 3,
.stills_capture_circular_buffer_height = 0,
.fast_preview_resume = 0,
.use_stc_timestamp = MMAL_PARAM_TIMESTAMP_MODE_RESET_STC
};
mmal_port_parameter_set(camera->control, &cam_config.hdr);
}
// Now set up the port formats
// Set the encode format on the Preview port
// HW limitations mean we need the preview to be the same size as the required recorded output
format = preview_port->format;
format->encoding = MMAL_ENCODING_OPAQUE;
format->encoding_variant = MMAL_ENCODING_I420;
format->encoding = MMAL_ENCODING_OPAQUE;
format->es->video.width = state->width;
format->es->video.height = state->height;
format->es->video.crop.x = 0;
format->es->video.crop.y = 0;
format->es->video.crop.width = state->width;
format->es->video.crop.height = state->height;
format->es->video.frame_rate.num = state->framerate;
format->es->video.frame_rate.den = VIDEO_FRAME_RATE_DEN;
status = mmal_port_format_commit(preview_port);
if (status != MMAL_SUCCESS)
{
vcos_log_error("camera viewfinder format couldn't be set");
goto error;
}
// Set the encode format on the video port
format = video_port->format;
if (state->useRGB)
{
format->encoding = MMAL_ENCODING_BGR24;
format->encoding_variant = MMAL_ENCODING_BGR24;
}
else
{
format->encoding = MMAL_ENCODING_I420;
format->encoding_variant = MMAL_ENCODING_I420;
}
format->es->video.width = state->width;
format->es->video.height = state->height;
format->es->video.crop.x = 0;
format->es->video.crop.y = 0;
format->es->video.crop.width = state->width;
format->es->video.crop.height = state->height;
format->es->video.frame_rate.num = state->framerate;
format->es->video.frame_rate.den = VIDEO_FRAME_RATE_DEN;
status = mmal_port_format_commit(video_port);
if (status)
{
vcos_log_error("camera video format couldn't be set");
goto error;
}
//Me
// PR : plug the callback to the video port
status = mmal_port_enable(video_port, video_buffer_callback);
if (status)
{
vcos_log_error("camera video callback2 error");
goto error;
}
// Ensure there are enough buffers to avoid dropping frames
if (video_port->buffer_num < VIDEO_OUTPUT_BUFFERS_NUM)
video_port->buffer_num = VIDEO_OUTPUT_BUFFERS_NUM;
// Set the encode format on the still port
format = still_port->format;
format->encoding = MMAL_ENCODING_OPAQUE;
format->encoding_variant = MMAL_ENCODING_I420;
format->es->video.width = state->width;
format->es->video.height = state->height;
format->es->video.crop.x = 0;
format->es->video.crop.y = 0;
format->es->video.crop.width = state->width;
format->es->video.crop.height = state->height;
format->es->video.frame_rate.num = 1;
format->es->video.frame_rate.den = 1;
status = mmal_port_format_commit(still_port);
if (status)
{
vcos_log_error("camera still format couldn't be set");
goto error;
}
//Me
//PR : create pool of message on video port
MMAL_POOL_T *pool;
video_port->buffer_size = video_port->buffer_size_recommended;
video_port->buffer_num = video_port->buffer_num_recommended;
pool = mmal_port_pool_create(video_port, video_port->buffer_num, video_port->buffer_size);
if (!pool)
{
vcos_log_error("Failed to create buffer header pool for video output port");
}
state->video_pool = pool;
/* Ensure there are enough buffers to avoid dropping frames */
if (still_port->buffer_num < VIDEO_OUTPUT_BUFFERS_NUM)
still_port->buffer_num = VIDEO_OUTPUT_BUFFERS_NUM;
/* Enable component */
status = mmal_component_enable(camera);
if (status)
{
vcos_log_error("camera component couldn't be enabled");
goto error;
}
raspicamcontrol_set_all_parameters(camera, &state->camera_parameters);
state->camera_component = camera;
if (state->verbose)
fprintf(stderr, "Camera component done\n");
return camera;
error:
if (camera)
mmal_component_destroy(camera);
return 0;
}
/**
* Destroy the camera component
*
* @param state Pointer to state control struct
*
*/
static void destroy_camera_component(RASPIVID_STATE *state)
{
if (state->camera_component)
{
mmal_component_destroy(state->camera_component);
state->camera_component = NULL;
}
}
//Me /**
//Me * Create the encoder component, set up its ports
//Me *
//Me * @param state Pointer to state control struct
//Me *
//Me * @return MMAL_SUCCESS if all OK, something else otherwise
//Me *
//Me */
//Me static MMAL_STATUS_T create_encoder_component(RASPIVID_STATE *state)
//Me {
//Me MMAL_COMPONENT_T *encoder = 0;
//Me MMAL_PORT_T *encoder_input = NULL, *encoder_output = NULL;
//Me MMAL_STATUS_T status;
//Me MMAL_POOL_T *pool;
//Me
//Me status = mmal_component_create(MMAL_COMPONENT_DEFAULT_VIDEO_ENCODER, &encoder);
//Me if (status != MMAL_SUCCESS)
//Me {
//Me vcos_log_error("Unable to create video encoder component");
//Me goto error;
//Me }
//Me
//Me if (!encoder->input_num || !encoder->output_num)
//Me {
//Me status = MMAL_ENOSYS;
//Me vcos_log_error("Video encoder doesn't have input/output ports");
//Me goto error;
//Me }
//Me
//Me encoder_input = encoder->input[0];
//Me encoder_output = encoder->output[0];
//Me
//Me // We want same format on input and output
//Me mmal_format_copy(encoder_output->format, encoder_input->format);
//Me
//Me // Only supporting H264 at the moment
//Me encoder_output->format->encoding = MMAL_ENCODING_H264;
//Me
//Me encoder_output->format->bitrate = state->bitrate;
//Me
//Me encoder_output->buffer_size = encoder_output->buffer_size_recommended;
//Me
//Me if (encoder_output->buffer_size < encoder_output->buffer_size_min)
//Me encoder_output->buffer_size = encoder_output->buffer_size_min;
//Me
//Me encoder_output->buffer_num = encoder_output->buffer_num_recommended;
//Me
//Me if (encoder_output->buffer_num < encoder_output->buffer_num_min)
//Me encoder_output->buffer_num = encoder_output->buffer_num_min;
//Me
//Me // Commit the port changes to the output port
//Me status = mmal_port_format_commit(encoder_output);
//Me
//Me if (status != MMAL_SUCCESS)
//Me {
//Me vcos_log_error("Unable to set format on video encoder output port");
//Me goto error;
//Me }
//Me
//Me
//Me // Set the rate control parameter
//Me if (0)
//Me {
//Me MMAL_PARAMETER_VIDEO_RATECONTROL_T param = {{ MMAL_PARAMETER_RATECONTROL, sizeof(param)}, MMAL_VIDEO_RATECONTROL_DEFAULT};
//Me status = mmal_port_parameter_set(encoder_output, ¶m.hdr);
//Me if (status != MMAL_SUCCESS)
//Me {
//Me vcos_log_error("Unable to set ratecontrol");
//Me goto error;
//Me }
//Me
//Me }
//Me
//Me if (state->intraperiod)
//Me {
//Me MMAL_PARAMETER_UINT32_T param = {{ MMAL_PARAMETER_INTRAPERIOD, sizeof(param)}, state->intraperiod};
//Me status = mmal_port_parameter_set(encoder_output, ¶m.hdr);
//Me if (status != MMAL_SUCCESS)
//Me {
//Me vcos_log_error("Unable to set intraperiod");
//Me goto error;
//Me }
//Me
//Me }
//Me
//Me if (mmal_port_parameter_set_boolean(encoder_input, MMAL_PARAMETER_VIDEO_IMMUTABLE_INPUT, state->immutableInput) != MMAL_SUCCESS)
//Me {
//Me vcos_log_error("Unable to set immutable input flag");
//Me // Continue rather than abort..
//Me }
//Me
//Me // Enable component
//Me status = mmal_component_enable(encoder);
//Me
//Me if (status != MMAL_SUCCESS)
//Me {
//Me vcos_log_error("Unable to enable video encoder component");
//Me goto error;
//Me }
//Me
//Me /* Create pool of buffer headers for the output port to consume */
//Me pool = mmal_port_pool_create(encoder_output, encoder_output->buffer_num, encoder_output->buffer_size);
//Me
//Me if (!pool)
//Me {
//Me vcos_log_error("Failed to create buffer header pool for encoder output port %s", encoder_output->name);
//Me }
//Me
//Me state->encoder_pool = pool;
//Me state->encoder_component = encoder;
//Me
//Me if (state->verbose)
//Me fprintf(stderr, "Encoder component done\n");
//Me
//Me return status;
//Me
//Me error:
//Me if (encoder)
//Me mmal_component_destroy(encoder);
//Me
//Me return status;
//Me }
/**
* Destroy the encoder component
*
* @param state Pointer to state control struct
*
*/
static void destroy_encoder_component(RASPIVID_STATE *state)
{
// Get rid of any port buffers first
if (state->video_pool)
{
mmal_port_pool_destroy(state->encoder_component->output[0], state->video_pool);
}
if (state->encoder_component)
{
mmal_component_destroy(state->encoder_component);
state->encoder_component = NULL;
}
}
/**
* 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)
mmal_connection_destroy(*connection);
}
return status;
}
/**
* Checks if specified port is valid and enabled, then disables it
*
* @param port Pointer the port
*
*/
static void check_disable_port(MMAL_PORT_T *port)
{
if (port && port->is_enabled)
mmal_port_disable(port);
}
/**
* Handler for sigint signals
*
* @param signal_number ID of incoming signal.
*
*/
static void signal_handler(int signal_number)
{
// Going to abort on all signals
vcos_log_error("Aborting program\n");
// TODO : Need to close any open stuff...how?
exit(255);
}
/**
* 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_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(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)
{
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 (!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);
}
//Me else if ((status = create_encoder_component(&state)) != MMAL_SUCCESS)
//Me {
//Me vcos_log_error("%s: Failed to create encode component", __func__);
//Me raspipreview_destroy(&state.preview_parameters);
//Me destroy_camera_component(&state);
//Me }
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];
//Me encoder_input_port = state.encoder_component->input[0];
//Me 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");
//Me // Now connect the camera to the encoder
//Me status = connect_ports(camera_video_port, encoder_input_port, &state.encoder_connection);
//Me
//Me if (status != MMAL_SUCCESS)
//Me {
//Me vcos_log_error("%s: Failed to connect camera video port to encoder input", __func__);
//Me goto error;
//Me }
//Me
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);
}
}
VCOS_STATUS_T vcos_status;
// 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;
vcos_status = vcos_semaphore_create(&callback_data.complete_semaphore, "RaspiStill-sem", 0);
vcos_assert(vcos_status == VCOS_SUCCESS);
camera_video_port->userdata = (struct MMAL_PORT_USERDATA_T *)&callback_data;
if (state.verbose)
fprintf(stderr, "Enabling encoder output port\n");
//Me // Enable the encoder output port and tell it its callback function
//Me status = mmal_port_enable(encoder_output_port, encoder_buffer_callback);
//Me
//Me if (status != MMAL_SUCCESS)
//Me {
//Me vcos_log_error("Failed to setup encoder output");
//Me goto error;
//Me }
//Me
//Me if (state.demoMode)
//Me {
//Me // Run for the user specific time..
//Me int num_iterations = state.timeout / state.demoInterval;
//Me int i;
//Me
//Me if (state.verbose)
//Me fprintf(stderr, "Running in demo mode\n");
//Me
//Me for (i=0;state.timeout == 0 || i<num_iterations;i++)
//Me {
//Me raspicamcontrol_cycle_test(state.camera_component);
//Me vcos_sleep(state.demoInterval);
//Me }
//Me }
//Me else
//Me {
// 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 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. 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);
}
//Me }
}
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);
//Me check_disable_port(encoder_output_port);
//Me
if (state.preview_parameters.wantPreview )
mmal_connection_destroy(state.preview_connection);
//Me 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 */
//Me if (state.encoder_component)
//Me mmal_component_disable(state.encoder_component);
//Me
if (state.preview_parameters.preview_component)
mmal_component_disable(state.preview_parameters.preview_component);
if (state.camera_component)
mmal_component_disable(state.camera_component);
//Me 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;
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。