Revise return codes

This commit is contained in:
Mr-Dave
2022-11-13 21:32:14 -07:00
parent 27cb2e98e1
commit 1eb12610bd
10 changed files with 305 additions and 404 deletions

View File

@@ -342,7 +342,7 @@ int cls_libcam::cam_next(ctx_image_data *img_data)
int indx;
if (started_cam == false) {
return -1;
return CAPTURE_FAILURE;
}
/* Allow time for request to finish.*/
@@ -361,31 +361,15 @@ int cls_libcam::cam_next(ctx_image_data *img_data)
request->reuse(Request::ReuseBuffers);
req_add(request);
return 0;
return CAPTURE_SUCCESS;
} else {
return -1;
return CAPTURE_FAILURE;
}
}
#endif
/** initialize and start libcam */
int libcam_start(ctx_cam *cam)
{
#ifdef HAVE_LIBCAM
int retcd;
MOTION_LOG(NTC, TYPE_VIDEO, NO_ERRNO, "Starting experimental libcamera .");
MOTION_LOG(NTC, TYPE_VIDEO, NO_ERRNO, "EXPECT crashes and hung processes!!!");
cam->libcam = new cls_libcam;
retcd = cam->libcam->cam_start(cam);
return retcd;
#else
(void)cam;
return -1;
#endif
}
/** close and stop libcam */
void libcam_cleanup(ctx_cam *cam)
{
@@ -393,11 +377,33 @@ void libcam_cleanup(ctx_cam *cam)
cam->libcam->cam_stop();
delete cam->libcam;
cam->libcam = nullptr;
#else
(void)cam;
#endif
cam->camera_status = STATUS_CLOSED;
cam->running_cam = false;
}
/** initialize and start libcam */
void libcam_start(ctx_cam *cam)
{
#ifdef HAVE_LIBCAM
int retcd;
MOTION_LOG(NTC, TYPE_VIDEO, NO_ERRNO,_("Opening libcam"));
MOTION_LOG(NTC, TYPE_VIDEO, NO_ERRNO, "Starting experimental libcamera .");
MOTION_LOG(NTC, TYPE_VIDEO, NO_ERRNO, "EXPECT crashes and hung processes!!!");
cam->libcam = new cls_libcam;
retcd = cam->libcam->cam_start(cam);
if (retcd < 0) {
MOTION_LOG(ERR, TYPE_VIDEO, NO_ERRNO,_("libcam failed to open"));
libcam_cleanup(cam);
} else {
cam->camera_status = STATUS_OPENED;
}
#else
cam->camera_status = STATUS_CLOSED;
#endif
}
/** get next image from libcam */
int libcam_next(ctx_cam *cam, ctx_image_data *img_data)
{
@@ -405,17 +411,19 @@ int libcam_next(ctx_cam *cam, ctx_image_data *img_data)
int retcd;
if (cam->libcam == nullptr){
return -1;
return CAPTURE_FAILURE;
}
retcd = cam->libcam->cam_next(img_data);
if (retcd == 0) {
if (retcd == CAPTURE_SUCCESS) {
rotate_map(cam, img_data);
}
return retcd;
#else
(void)cam;
(void)img_data;
return -1;
return CAPTURE_FAILURE;
#endif
}

View File

@@ -73,7 +73,7 @@
};
#endif
int libcam_start (ctx_cam *cam);
void libcam_start (ctx_cam *cam);
int libcam_next (ctx_cam *cam, ctx_image_data *img_data);
void libcam_cleanup (ctx_cam *cam);

View File

@@ -271,26 +271,36 @@ static void destroy_camera_buffer_structures(ctx_mmalcam_ptr mmalcam)
#endif
/**
* mmalcam_start
*
* This routine is called from the main motion thread. It's job is
* to open up the requested camera device via MMAL and do any required
* initialization.
*
* Parameters:
*
* cam Pointer to the motion context structure for this device.
*
* Returns: 0 on success
* -1 on any failure
*/
int mmalcam_start(ctx_cam *cam)
void mmalcam_cleanup(ctx_cam *cam)
{
#ifdef HAVE_MMAL
MOTION_LOG(NTC, TYPE_VIDEO, NO_ERRNO, _("MMAL Camera cleanup"));
if (cam->mmalcam != NULL ) {
if (cam->mmalcam->camera_component) {
check_disable_port(cam->mmalcam->camera_capture_port);
mmal_component_disable(cam->mmalcam->camera_component);
destroy_camera_buffer_structures(cam->mmalcam);
destroy_camera_component(cam->mmalcam);
}
myfree(&cam->mmalcam->camera_parameters);
myfree(&cam->mmalcam);
}
#endif
cam->camera_status = STATUS_CLOSED;
cam->running_cam = false;
}
void mmalcam_start(ctx_cam *cam)
{
#ifdef HAVE_MMAL
ctx_mmalcam_ptr mmalcam;
MOTION_LOG(NTC, TYPE_VIDEO, NO_ERRNO,_("Opening MMAL cam"));
cam->mmalcam = (ctx_mmalcam*) mymalloc(sizeof(ctx_mmalcam));
memset(cam->mmalcam, 0, sizeof(ctx_mmalcam));
mmalcam = cam->mmalcam;
@@ -303,7 +313,9 @@ int mmalcam_start(ctx_cam *cam)
mmalcam->camera_parameters = (RASPICAM_CAMERA_PARAMETERS*)malloc(sizeof(RASPICAM_CAMERA_PARAMETERS));
if (mmalcam->camera_parameters == NULL) {
MOTION_LOG(ERR, TYPE_VIDEO, NO_ERRNO, _("camera params couldn't be allocated"));
return MMALCAM_ERROR;
MOTION_LOG(ERR, TYPE_VIDEO, NO_ERRNO,_("MMAL cam failed to open"));
mmalcam_cleanup(cam);
return;
}
raspicamcontrol_set_defaults(mmalcam->camera_parameters);
@@ -345,62 +357,21 @@ int mmalcam_start(ctx_cam *cam)
retval = send_pooled_buffers_to_port(mmalcam->camera_buffer_pool, mmalcam->camera_capture_port);
}
return retval;
#else
(void)cam;
MOTION_LOG(NTC, TYPE_VIDEO, NO_ERRNO,_("MMAL Camera not available"));
return -1;
#endif
}
/**
* mmalcam_cleanup
*
* This routine shuts down any MMAL resources, then releases any allocated data
* within the mmalcam context and frees the context itself.
* This function is also called from motion_init if first time connection
* fails and we start retrying until we get a valid first frame from the
* camera.
*
* Parameters:
*
* mmalcam Pointer to a mmalcam context
*
* Returns: Nothing.
*
*/
void mmalcam_cleanup(ctx_mmalcam *mmalcam)
{
#ifdef HAVE_MMAL
MOTION_LOG(NTC, TYPE_VIDEO, NO_ERRNO, _("MMAL Camera cleanup"));
if (mmalcam != NULL ) {
if (mmalcam->camera_component) {
check_disable_port(mmalcam->camera_capture_port);
mmal_component_disable(mmalcam->camera_component);
destroy_camera_buffer_structures(mmalcam);
destroy_camera_component(mmalcam);
}
myfree(&mmalcam->camera_parameters);
myfree(&mmalcam);
if (retval == 0) {
cam->camera_status = STATUS_OPENED;
} else {
MOTION_LOG(ERR, TYPE_VIDEO, NO_ERRNO,_("MMAL cam failed to open"));
mmalcam_cleanup(cam);
}
#else
(void)mmalcam;
cam->camera_status = STATUS_CLOSED;
MOTION_LOG(NTC, TYPE_VIDEO, NO_ERRNO,_("MMAL Camera not available"));
#endif
}
/**
* mmalcam_next
*
* This routine is called when the main 'motion' thread wants a new
* frame of video. It fetches the most recent frame available from
* the Pi camera already in YUV420P, and returns it to motion.
*
* Parameters:
* cam Pointer to the context for this thread
* image Pointer to a buffer for the returned image
*
* Returns: Error code
* Return image from mmalcam. Runs on motion_loop thread.
*/
int mmalcam_next(ctx_cam *cam, ctx_image_data *img_data)
{
@@ -408,7 +379,7 @@ int mmalcam_next(ctx_cam *cam, ctx_image_data *img_data)
ctx_mmalcam_ptr mmalcam;
if ((!cam) || (!cam->mmalcam)) {
return -1;
return CAPTURE_FAILURE;
}
mmalcam = cam->mmalcam;
@@ -445,11 +416,11 @@ int mmalcam_next(ctx_cam *cam, ctx_image_data *img_data)
rotate_map(cam,img_data);
return 0;
return CAPTURE_SUCCESS;
#else
(void)cam;
(void)img_data;
return -1;
return CAPTURE_FAILURE;
#endif
}

View File

@@ -38,8 +38,8 @@
#endif
} ctx_mmalcam;
int mmalcam_start (ctx_cam *cam);
void mmalcam_start (ctx_cam *cam);
int mmalcam_next (ctx_cam *cam, ctx_image_data *img_data);
void mmalcam_cleanup (ctx_mmalcam *mmalcam);
void mmalcam_cleanup (ctx_cam *cam);
#endif /* _INCLUDE_MMALCAM_HPP_ */

View File

@@ -365,25 +365,22 @@ static void mlp_mask_privacy(ctx_cam *cam)
/* Close and clean up camera*/
void mlp_cam_close(ctx_cam *cam)
{
if (cam->mmalcam) {
mmalcam_cleanup(cam->mmalcam);
cam->mmalcam = NULL;
cam->running_cam = false;
if (cam->mmalcam != NULL) {
mmalcam_cleanup(cam);
return;
}
if (cam->libcam) {
if (cam->libcam != NULL) {
libcam_cleanup(cam);
cam->running_cam = false;
return;
}
if (cam->netcam) {
netcam_cleanup(cam, false);
if (cam->netcam != NULL) {
netcam_cleanup(cam);
return;
}
if (cam->camera_type == CAMERA_TYPE_V4L2) {
if (cam->v4l2cam != NULL) {
v4l2_cleanup(cam);
return;
}
@@ -394,85 +391,37 @@ void mlp_cam_close(ctx_cam *cam)
}
/* Start camera */
int mlp_cam_start(ctx_cam *cam)
void mlp_cam_start(ctx_cam *cam)
{
int retcd;
if (cam->camera_type == CAMERA_TYPE_MMAL) {
MOTION_LOG(NTC, TYPE_VIDEO, NO_ERRNO,_("Opening MMAL cam"));
retcd = mmalcam_start(cam);
if (retcd < 0) {
mmalcam_cleanup(cam->mmalcam);
cam->mmalcam = NULL;
MOTION_LOG(ERR, TYPE_VIDEO, NO_ERRNO,_("MMAL cam failed to open"));
}
return retcd;
mmalcam_start(cam);
} else if (cam->camera_type == CAMERA_TYPE_LIBCAM) {
libcam_start(cam);
} else if (cam->camera_type == CAMERA_TYPE_NETCAM) {
netcam_start(cam);
} else if (cam->camera_type == CAMERA_TYPE_V4L2) {
v4l2_start(cam);
} else {
MOTION_LOG(ERR, TYPE_VIDEO, NO_ERRNO
,_("No Camera device specified"));
cam->camera_status = STATUS_CLOSED;
}
if (cam->camera_type == CAMERA_TYPE_LIBCAM) {
MOTION_LOG(NTC, TYPE_VIDEO, NO_ERRNO,_("Opening libcam"));
retcd = libcam_start(cam);
if (retcd < 0) {
libcam_cleanup(cam);
MOTION_LOG(ERR, TYPE_VIDEO, NO_ERRNO,_("libcam failed to open"));
}
return retcd;
}
if (cam->camera_type == CAMERA_TYPE_NETCAM) {
MOTION_LOG(NTC, TYPE_VIDEO, NO_ERRNO,_("Opening Netcam"));
retcd = netcam_setup(cam);
if (retcd < 0) {
netcam_cleanup(cam, true);
MOTION_LOG(ERR, TYPE_VIDEO, NO_ERRNO,_("Netcam failed to open"));
}
return retcd;
}
if (cam->camera_type == CAMERA_TYPE_V4L2) {
MOTION_LOG(NTC, TYPE_VIDEO, NO_ERRNO,_("Opening V4L2 device"));
retcd = v4l2_start(cam);
if (retcd < 0) {
MOTION_LOG(ERR, TYPE_VIDEO, NO_ERRNO,_("V4L2 device failed to open"));
}
return retcd;
}
MOTION_LOG(ERR, TYPE_VIDEO, NO_ERRNO
,_("No Camera device specified"));
return -1;
}
/* Get next image from camera */
int mlp_cam_next(ctx_cam *cam, ctx_image_data *img_data)
{
if (cam->camera_type == CAMERA_TYPE_MMAL) {
if (cam->mmalcam == NULL) {
return NETCAM_GENERAL_ERROR;
}
return mmalcam_next(cam, img_data);
}
if (cam->camera_type == CAMERA_TYPE_LIBCAM) {
if (cam->libcam == NULL) {
return NETCAM_GENERAL_ERROR;
}
} else if (cam->camera_type == CAMERA_TYPE_LIBCAM) {
return libcam_next(cam, img_data);
}
if (cam->camera_type == CAMERA_TYPE_NETCAM) {
if (cam->video_dev == -1) {
return NETCAM_GENERAL_ERROR;
}
} else if (cam->camera_type == CAMERA_TYPE_NETCAM) {
return netcam_next(cam, img_data);
} else if (cam->camera_type == CAMERA_TYPE_V4L2) {
return v4l2_next(cam, img_data);
}
if (cam->camera_type == CAMERA_TYPE_V4L2) {
return v4l2_next(cam, img_data);
}
return -2;
return CAPTURE_FAILURE;
}
/* Assign the camera type */
@@ -511,9 +460,9 @@ static void mlp_init_firstimage(ctx_cam *cam)
int indx;
cam->current_image = &cam->imgs.image_ring[cam->imgs.ring_in];
if (cam->video_dev >= 0) {
if (cam->camera_status == STATUS_OPENED) {
for (indx = 0; indx < 5; indx++) {
if (mlp_cam_next(cam, cam->current_image) == 0) {
if (mlp_cam_next(cam, cam->current_image) == CAPTURE_SUCCESS) {
break;
}
SLEEP(2, 0);
@@ -621,7 +570,7 @@ static void mlp_init_values(ctx_cam *cam)
} else {
cam->threshold_maximum = (cam->imgs.height * cam->imgs.width * 3) / 2;
}
cam->camera_status = STATUS_CLOSED;
cam->startup_frames = (cam->conf->framerate * 2) + cam->conf->pre_capture + cam->conf->minimum_motion_frames;
cam->minimum_frame_time_downcounter = cam->conf->minimum_frame_time;
@@ -638,25 +587,22 @@ static void mlp_init_values(ctx_cam *cam)
/* start the camera */
static int mlp_init_cam_start(ctx_cam *cam)
{
cam->video_dev = mlp_cam_start(cam);
mlp_cam_start(cam);
if (cam->video_dev == -1) {
MOTION_LOG(WRN, TYPE_ALL, NO_ERRNO
,_("Could not fetch initial image from camera "));
return -1;
} else if (cam->video_dev == -2) {
if (cam->camera_status == STATUS_CLOSED) {
MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO
,_("Could not fetch initial image from camera "));
,_("Failed to start camera."));
MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO
,_("Motion only supports width and height modulo 8"));
,_("Use webcontrol to start camera when it is ready."));
cam->restart_cam = false;
return -1;
} else {
cam->imgs.motionsize = (cam->imgs.width * cam->imgs.height);
cam->imgs.size_norm = (cam->imgs.width * cam->imgs.height * 3) / 2;
cam->imgs.size_high = (cam->imgs.width_high * cam->imgs.height_high * 3) / 2;
}
cam->imgs.motionsize = (cam->imgs.width * cam->imgs.height);
cam->imgs.size_norm = (cam->imgs.width * cam->imgs.height * 3) / 2;
cam->imgs.size_high = (cam->imgs.width_high * cam->imgs.height_high * 3) / 2;
return 0;
}
/* initialize reference images*/
@@ -747,7 +693,7 @@ void mlp_cleanup(ctx_cam *cam)
algsec_deinit(cam);
if (cam->video_dev >= 0) {
if (cam->camera_status == STATUS_OPENED) {
mlp_cam_close(cam);
}
@@ -895,13 +841,14 @@ static int mlp_retry(ctx_cam *cam)
{
int size_high;
if (cam->video_dev < 0 &&
cam->frame_curr_ts.tv_sec % 10 == 0 && cam->shots == 0) {
if ((cam->camera_status == STATUS_CLOSED) &&
(cam->frame_curr_ts.tv_sec % 10 == 0) &&
(cam->shots == 0)) {
MOTION_LOG(WRN, TYPE_ALL, NO_ERRNO
,_("Retrying until successful connection with camera"));
cam->video_dev = mlp_cam_start(cam);
if (cam->video_dev < 0) {
mlp_cam_start(cam);
if (cam->camera_status != STATUS_OPENED) {
return 1;
}
@@ -945,15 +892,11 @@ static int mlp_capture(ctx_cam *cam)
{
const char *tmpin;
char tmpout[80];
int vid_return_code = 0; /* Return code used when calling mlp_cam_next */
int retcd;
if (cam->video_dev >= 0) {
vid_return_code = mlp_cam_next(cam, cam->current_image);
} else {
vid_return_code = 1; /* Non fatal error */
}
retcd = mlp_cam_next(cam, cam->current_image);
if (vid_return_code == 0) {
if (retcd == CAPTURE_SUCCESS) {
cam->lost_connection = 0;
cam->connectionlosttime.tv_sec = 0;
@@ -966,34 +909,26 @@ static int mlp_capture(ctx_cam *cam)
mlp_mask_privacy(cam);
memcpy(cam->imgs.image_vprvcy, cam->current_image->image_norm, cam->imgs.size_norm);
} else if (vid_return_code < 0) {
} else if (retcd == CAPTURE_FAILURE) {
MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO
,_("Video device fatal error - Closing video device"));
mlp_cam_close(cam);
memcpy(cam->current_image->image_norm, cam->imgs.image_virgin, cam->imgs.size_norm);
cam->lost_connection = 1;
} else {
if (vid_return_code == NETCAM_RESTART_ERROR) {
MOTION_LOG(NTC, TYPE_ALL, NO_ERRNO
,_("Restarting Motion thread to reinitialize all "
"image buffers"));
cam->lost_connection = 1;
return 1;
}
if (cam->connectionlosttime.tv_sec == 0) {
clock_gettime(CLOCK_REALTIME, &cam->connectionlosttime);
}
++cam->missing_frame_counter;
cam->missing_frame_counter++;
if (cam->video_dev >= 0 &&
cam->missing_frame_counter < (cam->conf->camera_tmo * cam->conf->framerate)) {
if ((cam->camera_status == STATUS_OPENED) &&
(cam->missing_frame_counter <
(cam->conf->camera_tmo * cam->conf->framerate))) {
memcpy(cam->current_image->image_norm, cam->imgs.image_vprvcy, cam->imgs.size_norm);
} else {
cam->lost_connection = 1;
if (cam->video_dev >= 0) {
if (cam->camera_status == STATUS_OPENED) {
tmpin = "CONNECTION TO CAMERA LOST\\nSINCE %Y-%m-%d %T";
} else {
tmpin = "UNABLE TO OPEN VIDEO DEVICE\\nSINCE %Y-%m-%d %T";
@@ -1012,7 +947,7 @@ static int mlp_capture(ctx_cam *cam)
event(cam, EVENT_CAMERA_LOST, NULL, NULL, NULL, &cam->connectionlosttime);
}
if ((cam->video_dev > 0) &&
if ((cam->camera_status == STATUS_OPENED) &&
(cam->missing_frame_counter == ((cam->conf->camera_tmo * 4) * cam->conf->framerate))) {
MOTION_LOG(ERR, TYPE_ALL, NO_ERRNO
,_("Video signal still lost - Trying to close video device"));

View File

@@ -174,6 +174,17 @@ enum MOTION_SIGNAL {
MOTION_SIGNAL_SIGTERM
};
enum CAPTURE_RESULT {
CAPTURE_SUCCESS,
CAPTURE_FAILURE,
CAPTURE_ATTEMPTED
};
enum CAM_STATUS {
STATUS_CLOSED, /* Camera is closed and not Initialized */
STATUS_OPENED /* Successfully started the camera */
};
struct ctx_webu_clients {
std::string clientip;
bool authenticated;
@@ -285,10 +296,6 @@ struct ctx_stream {
ctx_stream_data secondary; /* Copy of the image to use for web stream*/
};
/*
* These used to be global variables but now each thread will have its
* own context
*/
struct ctx_cam {
ctx_motapp *motapp;
@@ -320,6 +327,7 @@ struct ctx_cam {
int track_posy;
int camera_id;
enum CAMERA_TYPE camera_type;
enum CAM_STATUS camera_status;
unsigned int new_img;
int locate_motion_mode;
int locate_motion_style;
@@ -362,7 +370,6 @@ struct ctx_cam {
int missing_frame_counter; /* counts failed attempts to fetch picture frame from camera */
unsigned int lost_connection;
int video_dev;
int pipe;
int mpipe;
@@ -395,7 +402,7 @@ struct ctx_cam {
};
/* ctx_cam for whole motion application including all the cameras */
/* ctx_motapp for whole motion application including all the cameras */
struct ctx_motapp {
ctx_cam **cam_list;

View File

@@ -1502,6 +1502,10 @@ static void netcam_set_parms (ctx_cam *cam, ctx_netcam *netcam )
netcam->motapp = cam->motapp;
netcam->conf = cam->conf;
pthread_mutex_lock(&netcam->motapp->global_lock);
netcam->threadnbr = ++netcam->motapp->threads_running;
pthread_mutex_unlock(&netcam->motapp->global_lock);
if (netcam->high_resolution) {
netcam->imgsize.width = 0;
netcam->imgsize.height = 0;
@@ -1582,7 +1586,7 @@ static void netcam_set_parms (ctx_cam *cam, ctx_netcam *netcam )
}
static int netcam_set_dimensions (ctx_cam *cam)
static void netcam_set_dimensions (ctx_cam *cam)
{
cam->imgs.width = 0;
@@ -1617,7 +1621,6 @@ static int netcam_set_dimensions (ctx_cam *cam)
cam->imgs.size_norm = (cam->conf->width * cam->conf->height * 3) / 2;
cam->imgs.motionsize = cam->conf->width * cam->conf->height;
return 0;
}
static int netcam_copy_stream(ctx_netcam *netcam)
@@ -2064,10 +2067,6 @@ static int netcam_start_handler(ctx_netcam *netcam)
pthread_attr_init(&handler_attribute);
pthread_attr_setdetachstate(&handler_attribute, PTHREAD_CREATE_DETACHED);
pthread_mutex_lock(&netcam->motapp->global_lock);
netcam->threadnbr = ++netcam->motapp->threads_running;
pthread_mutex_unlock(&netcam->motapp->global_lock);
retcd = pthread_create(&netcam->thread_id, &handler_attribute, &netcam_handler, netcam);
if (retcd < 0) {
MOTION_LOG(ALR, TYPE_NETCAM, SHOW_ERRNO
@@ -2102,141 +2101,8 @@ static int netcam_start_handler(ctx_netcam *netcam)
}
int netcam_setup(ctx_cam *cam)
void netcam_cleanup(ctx_cam *cam)
{
int retcd;
int indx_cam, indx_max;
ctx_netcam *netcam;
cam->netcam = NULL;
cam->netcam_high = NULL;
if (netcam_set_dimensions(cam) < 0 ) {
return -1;
}
indx_cam = 1;
if (cam->conf->netcam_high_url != "") {
indx_max = 2;
} else {
indx_max = 1;
}
while (indx_cam <= indx_max){
if (indx_cam == 1) {
cam->netcam = netcam_new_context();
if (cam->netcam == NULL) {
MOTION_LOG(ERR, TYPE_NETCAM, NO_ERRNO
,_("unable to create rtsp context"));
return -1;
}
netcam = cam->netcam;
netcam->high_resolution = false; /* Set flag for this being the normal resolution camera */
} else {
cam->netcam_high = netcam_new_context();
if (cam->netcam_high == NULL) {
MOTION_LOG(ERR, TYPE_NETCAM, NO_ERRNO
,_("unable to create rtsp high context"));
return -1;
}
netcam = cam->netcam_high;
netcam->high_resolution = true; /* Set flag for this being the high resolution camera */
}
netcam_null_context(netcam);
netcam_set_parms(cam, netcam);
if (netcam_connect(netcam) < 0) {
return -1;
}
retcd = netcam_read_image(netcam);
if (retcd < 0) {
MOTION_LOG(CRT, TYPE_NETCAM, NO_ERRNO
,_("Failed trying to read first image - retval:%d"), retcd);
netcam->status = NETCAM_NOTCONNECTED;
return -1;
}
/* When running dual, there seems to be contamination across norm/high with codec functions. */
netcam_close_context(netcam); /* Close in this thread to open it again within handler thread */
netcam->status = NETCAM_RECONNECTING; /* Set as reconnecting to avoid excess messages when starting */
netcam->first_image = false; /* Set flag that we are not processing our first image */
/* For normal resolution, we resize the image to the config parms so we do not need
* to set the dimension parameters here (it is done in the set_parms). For high res
* we must get the dimensions from the first image captured
*/
if (netcam->high_resolution) {
cam->imgs.width_high = netcam->imgsize.width;
cam->imgs.height_high = netcam->imgsize.height;
}
if (netcam_start_handler(netcam) < 0 ) {
return -1;
}
indx_cam++;
}
return 0;
}
/* netcam_next (Called from the motion loop thread) */
int netcam_next(ctx_cam *cam, ctx_image_data *img_data)
{
if (cam == NULL) {
return 1;
}
if (cam->netcam != NULL) {
if ((cam->netcam->status == NETCAM_RECONNECTING) ||
(cam->netcam->status == NETCAM_NOTCONNECTED)) {
return 1;
}
pthread_mutex_lock(&cam->netcam->mutex);
netcam_pktarray_resize(cam, false);
memcpy(img_data->image_norm
, cam->netcam->img_latest->ptr
, cam->netcam->img_latest->used);
img_data->idnbr_norm = cam->netcam->idnbr;
pthread_mutex_unlock(&cam->netcam->mutex);
}
if (cam->netcam_high != NULL) {
if ((cam->netcam_high->status == NETCAM_RECONNECTING) ||
(cam->netcam_high->status == NETCAM_NOTCONNECTED)) {
return 1;
}
pthread_mutex_lock(&cam->netcam_high->mutex);
netcam_pktarray_resize(cam, true);
if (!cam->netcam_high->passthrough) {
memcpy(img_data->image_high
,cam->netcam_high->img_latest->ptr
,cam->netcam_high->img_latest->used);
}
img_data->idnbr_high = cam->netcam_high->idnbr;
pthread_mutex_unlock(&cam->netcam_high->mutex);
}
/* Rotate images if requested */
rotate_map(cam, img_data);
return 0;
}
void netcam_cleanup(ctx_cam *cam, bool init_retry_flag)
{
/*
* If the init_retry_flag is not set this function was
* called while retrying the initial connection and there is
* no camera-handler started yet and thread_running must
* not be decremented. This is called from motion_loop thread
*/
int wait_counter;
int indx_cam, indx_max;
ctx_netcam *netcam;
@@ -2258,11 +2124,6 @@ void netcam_cleanup(ctx_cam *cam, bool init_retry_flag)
if (netcam) {
MOTION_LOG(INF, TYPE_NETCAM, NO_ERRNO
,_("%s: Shutting down network camera."),netcam->cameratype);
/* Throw the finish flag in context and wait a bit for it to finish its work and close everything
* This is shutting down the thread so for the moment, we are not worrying about the
* cross threading and protecting these variables with mutex's
*/
netcam->finish = true;
netcam->interruptduration = 0;
wait_counter = 0;
@@ -2273,17 +2134,13 @@ void netcam_cleanup(ctx_cam *cam, bool init_retry_flag)
if (!netcam->handler_finished) {
MOTION_LOG(ERR, TYPE_NETCAM, NO_ERRNO
,_("%s: No response from handler thread."),netcam->cameratype);
/* Last resort. Kill the thread. Not safe for posix but if no response, what to do...*/
/* pthread_kill(netcam->thread_id); */
/* Last resort. Kill the thread.*/
pthread_cancel(netcam->thread_id);
pthread_kill(netcam->thread_id, SIGVTALRM); /* This allows the cancel to be processed */
if (!init_retry_flag) {
pthread_mutex_lock(&netcam->motapp->global_lock);
netcam->motapp->threads_running--;
pthread_mutex_unlock(&netcam->motapp->global_lock);
}
pthread_kill(netcam->thread_id, SIGVTALRM);
pthread_mutex_lock(&netcam->motapp->global_lock);
netcam->motapp->threads_running--;
pthread_mutex_unlock(&netcam->motapp->global_lock);
}
/* If we never connect we don't have a handler but we still need to clean up some */
netcam_shutdown(netcam);
pthread_mutex_destroy(&netcam->mutex);
@@ -2304,8 +2161,133 @@ void netcam_cleanup(ctx_cam *cam, bool init_retry_flag)
}
cam->netcam = NULL;
cam->netcam_high = NULL;
if (init_retry_flag == false) {
cam->running_cam = false;
}
cam->running_cam = false;
cam->camera_status = STATUS_CLOSED;
}
void netcam_start(ctx_cam *cam)
{
int indx_cam, indx_max;
ctx_netcam *netcam;
MOTION_LOG(NTC, TYPE_VIDEO, NO_ERRNO,_("Opening Netcam"));
cam->netcam = NULL;
cam->netcam_high = NULL;
netcam_set_dimensions(cam);
indx_cam = 1;
if (cam->conf->netcam_high_url != "") {
indx_max = 2;
} else {
indx_max = 1;
}
while (indx_cam <= indx_max) {
if (indx_cam == 1) {
cam->netcam = netcam_new_context();
if (cam->netcam == NULL) {
MOTION_LOG(ERR, TYPE_NETCAM, NO_ERRNO
,_("unable to create rtsp context"));
netcam_cleanup(cam);
return;
}
netcam = cam->netcam;
netcam->high_resolution = false; /* Set flag for this being the normal resolution camera */
} else {
cam->netcam_high = netcam_new_context();
if (cam->netcam_high == NULL) {
MOTION_LOG(ERR, TYPE_NETCAM, NO_ERRNO
,_("unable to create rtsp high context"));
netcam_cleanup(cam);
return;
}
netcam = cam->netcam_high;
netcam->high_resolution = true; /* Set flag for this being the high resolution camera */
}
netcam_null_context(netcam);
netcam_set_parms(cam, netcam);
if (netcam_connect(netcam) != 0) {
netcam_cleanup(cam);
return;
}
if (netcam_read_image(netcam) != 0) {
MOTION_LOG(CRT, TYPE_NETCAM, NO_ERRNO
,_("Failed trying to read first image"));
netcam->status = NETCAM_NOTCONNECTED;
netcam_cleanup(cam);
return;
}
/* When running dual, there seems to be contamination across norm/high with codec functions. */
netcam_close_context(netcam); /* Close in this thread to open it again within handler thread */
netcam->status = NETCAM_RECONNECTING; /* Set as reconnecting to avoid excess messages when starting */
netcam->first_image = false; /* Set flag that we are not processing our first image */
/* For normal resolution, we resize the image to the config parms so we do not need
* to set the dimension parameters here (it is done in the set_parms). For high res
* we must get the dimensions from the first image captured
*/
if (netcam->high_resolution) {
cam->imgs.width_high = netcam->imgsize.width;
cam->imgs.height_high = netcam->imgsize.height;
}
if (netcam_start_handler(netcam) != 0 ) {
netcam_cleanup(cam);
return;
}
indx_cam++;
}
cam->camera_status = STATUS_OPENED;
return;
}
/* netcam_next (Called from the motion loop thread) */
int netcam_next(ctx_cam *cam, ctx_image_data *img_data)
{
if ((cam == NULL) || (cam->netcam == NULL)) {
return CAPTURE_FAILURE;
}
if ((cam->netcam->status == NETCAM_RECONNECTING) ||
(cam->netcam->status == NETCAM_NOTCONNECTED)) {
return CAPTURE_ATTEMPTED;
}
pthread_mutex_lock(&cam->netcam->mutex);
netcam_pktarray_resize(cam, false);
memcpy(img_data->image_norm
, cam->netcam->img_latest->ptr
, cam->netcam->img_latest->used);
img_data->idnbr_norm = cam->netcam->idnbr;
pthread_mutex_unlock(&cam->netcam->mutex);
if (cam->netcam_high != NULL) {
if ((cam->netcam_high->status == NETCAM_RECONNECTING) ||
(cam->netcam_high->status == NETCAM_NOTCONNECTED)) {
return CAPTURE_ATTEMPTED;
}
pthread_mutex_lock(&cam->netcam_high->mutex);
netcam_pktarray_resize(cam, true);
if (!cam->netcam_high->passthrough) {
memcpy(img_data->image_high
,cam->netcam_high->img_latest->ptr
,cam->netcam_high->img_latest->used);
}
img_data->idnbr_high = cam->netcam_high->idnbr;
pthread_mutex_unlock(&cam->netcam_high->mutex);
}
rotate_map(cam, img_data);
return CAPTURE_SUCCESS;
}

View File

@@ -22,8 +22,6 @@
#ifndef _INCLUDE_NETCAM_HPP_
#define _INCLUDE_NETCAM_HPP_
#define NETCAM_GENERAL_ERROR 0x02 /* binary 000010 */
#define NETCAM_RESTART_ERROR 0x12 /* binary 010010 */
#define NETCAM_BUFFSIZE 4096
enum NETCAM_STATUS {
@@ -151,8 +149,8 @@ struct ctx_netcam {
};
int netcam_setup(ctx_cam *cam);
void netcam_start(ctx_cam *cam);
int netcam_next(ctx_cam *cam, ctx_image_data *img_data);
void netcam_cleanup(ctx_cam *cam, bool init_retry_flag);
void netcam_cleanup(ctx_cam *cam);
#endif /* _INCLUDE_NETCAM_HPP_ */

View File

@@ -836,7 +836,7 @@ static int v4l2_capture(ctx_v4l2cam *v4l2cam)
if (retcd == -1) {
MOTION_LOG(ERR, TYPE_VIDEO, SHOW_ERRNO, "VIDIOC_QBUF");
pthread_sigmask(SIG_UNBLOCK, &old, NULL);
return retcd;
return -1;
}
}
@@ -850,7 +850,7 @@ static int v4l2_capture(ctx_v4l2cam *v4l2cam)
if (retcd == -1) {
MOTION_LOG(ERR, TYPE_VIDEO, SHOW_ERRNO, "VIDIOC_DQBUF");
pthread_sigmask(SIG_UNBLOCK, &old, NULL);
return retcd;
return -1;
}
v4l2cam->pframe = v4l2cam->buf.index;
@@ -935,7 +935,7 @@ static int v4l2_convert(ctx_cam *cam, ctx_v4l2cam *v4l2cam, unsigned char *img_n
return 0;
}
return 1;
return -1;
}
@@ -1199,10 +1199,6 @@ void v4l2_cleanup(ctx_cam *cam)
MOTION_LOG(NTC, TYPE_VIDEO, NO_ERRNO
,_("Closing video device %s"), cam->conf->v4l2_device.c_str());
if (cam->v4l2cam == NULL) {
return;
}
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (cam->v4l2cam->fd_device != -1) {
@@ -1232,19 +1228,20 @@ void v4l2_cleanup(ctx_cam *cam)
myfree(&cam->v4l2cam->params);
myfree(&cam->v4l2cam);
cam->running_cam = false;
#else
(void)cam;
#endif // HAVE_V4L2
cam->running_cam = false;
cam->camera_status = STATUS_CLOSED;
}
int v4l2_start(ctx_cam *cam)
void v4l2_start(ctx_cam *cam)
{
#ifdef HAVE_V4L2
int retcd;
MOTION_LOG(NTC, TYPE_VIDEO, NO_ERRNO,_("Opening V4L2 device"));
retcd = v4l2_device_init(cam);
if (retcd == 0) retcd = v4l2_device_open(cam);
if (retcd == 0) v4l2_log_types(cam->v4l2cam);
@@ -1259,15 +1256,14 @@ int v4l2_start(ctx_cam *cam)
if (retcd == 0) v4l2_ctrls_set(cam->v4l2cam);
if (retcd == 0) retcd = v4l2_set_mmap(cam->v4l2cam);
if (retcd == 0) v4l2_set_imgs(cam);
if (retcd < 0) {
if (retcd == 0) {
cam->camera_status = STATUS_OPENED;
} else {
MOTION_LOG(ERR, TYPE_VIDEO, NO_ERRNO,_("V4L2 device failed to open"));
v4l2_cleanup(cam);
return retcd;
}
return cam->v4l2cam->fd_device;
#else
(void)cam;
return -1;
cam->camera_status = STATUS_CLOSED;
#endif // HAVE_V4l2
}
@@ -1276,25 +1272,29 @@ int v4l2_next(ctx_cam *cam, ctx_image_data *img_data)
#ifdef HAVE_V4L2
int retcd;
if (cam->v4l2cam == NULL) {
return CAPTURE_FAILURE;
}
v4l2_device_select(cam);
retcd = v4l2_capture(cam->v4l2cam);
if (retcd != 0) {
return retcd;
return CAPTURE_FAILURE;
}
retcd = v4l2_convert(cam, cam->v4l2cam, img_data->image_norm);
if (retcd != 0) {
return retcd;
return CAPTURE_FAILURE;
}
rotate_map(cam, img_data);
return retcd;
return CAPTURE_SUCCESS;
#else
(void)cam;
(void)img_data;
return -1;
return CAPTURE_FAILURE;
#endif // HAVE_V4L2
}

View File

@@ -73,7 +73,7 @@ struct ctx_v4l2cam {
#endif
};
int v4l2_start(ctx_cam *cam);
void v4l2_start(ctx_cam *cam);
int v4l2_next(ctx_cam *cam, ctx_image_data *img_data);
void v4l2_cleanup(ctx_cam *cam);