📄 netcam.c
字号:
* Note that the average frame time is held in microseconds. */ if (netcam->last_image.tv_sec) { netcam->av_frame_time = (9.0 * netcam->av_frame_time + 1000000.0 * (curtime.tv_sec - netcam->last_image.tv_sec) + (curtime.tv_usec- netcam->last_image.tv_usec)) / 10.0; if (debug_level > CAMERA_INFO) motion_log(-1, 0, "Calculated frame time %f", netcam->av_frame_time); } netcam->last_image = curtime; pthread_mutex_lock(&netcam->mutex); xchg = netcam->latest; netcam->latest = netcam->receiving; netcam->receiving = xchg; netcam->imgcnt++; /* * We have a new frame ready. We send a signal so that * any thread (e.g. the motion main loop) waiting for the * next frame to become available may proceed. */ pthread_cond_signal(&netcam->pic_ready); pthread_mutex_unlock(&netcam->mutex); if (!netcam->caps.streaming) { if (!netcam->connect_keepalive) { if (debug_level > CAMERA_INFO ) motion_log(LOG_DEBUG, 0, "netcam_read_html_jpeg disconnecting netcam since keep-alive not set." ); netcam_disconnect(netcam); } else if (debug_level > CAMERA_INFO ) { motion_log(LOG_DEBUG, 0, "netcam_read_html_jpeg leaving netcam connected." ); } } return 0;}/** * netcam_read_ftp_jpeg * * This routine reads from a netcam using the FTP protocol. * The current implementation is still a little experimental, * and needs some additional code for error detection and * recovery. */static int netcam_read_ftp_jpeg(netcam_context_ptr netcam){ netcam_buff_ptr buffer; int len; netcam_buff *xchg; struct timeval curtime; /* Point to our working buffer */ buffer = netcam->receiving; buffer->used = 0; /* Request the image from the remote server */ if (ftp_get_socket(netcam->ftp) <= 0) { motion_log(LOG_ERR, 0, "ftp_get_socket failed in netcam_read_jpeg"); return -1; } /* Now fetch the image using ftp_read. Note this is a blocking call */ do { /* Assure there's enough room in the buffer */ netcam_check_buffsize(buffer, FTP_BUF_SIZE); /* Do the read */ if ((len = ftp_read(netcam->ftp, buffer->ptr + buffer->used, FTP_BUF_SIZE)) < 0) return -1; buffer->used += len; } while (len > 0); if (gettimeofday(&curtime, NULL) < 0) { motion_log(LOG_ERR, 1, "gettimeofday in netcam_read_jpeg"); } netcam->receiving->image_time = curtime; /* * Calculate our "running average" time for this netcam's * frame transmissions (except for the first time). * Note that the average frame time is held in microseconds. */ if (netcam->last_image.tv_sec) { netcam->av_frame_time = ((9.0 * netcam->av_frame_time) + 1000000.0 * (curtime.tv_sec - netcam->last_image.tv_sec) + (curtime.tv_usec- netcam->last_image.tv_usec)) / 10.0; if (debug_level > CAMERA_INFO) motion_log(-1, 0, "Calculated frame time %f", netcam->av_frame_time); } netcam->last_image = curtime; /* * read is complete - set the current 'receiving' buffer atomically * as 'latest', and make the buffer previously in 'latest' become * the new 'receiving' */ pthread_mutex_lock(&netcam->mutex); xchg = netcam->latest; netcam->latest = netcam->receiving; netcam->receiving = xchg; netcam->imgcnt++; /* * We have a new frame ready. We send a signal so that * any thread (e.g. the motion main loop) waiting for the * next frame to become available may proceed. */ pthread_cond_signal(&netcam->pic_ready); pthread_mutex_unlock(&netcam->mutex); return 0;}/** * netcam_read_file_jpeg * * This routine reads local image file. ( netcam_url file:///path/image.jpg ) * The current implementation is still a little experimental, * and needs some additional code for error detection and * recovery. */static int netcam_read_file_jpeg(netcam_context_ptr netcam){ int loop_counter=0; if (debug_level > CAMERA_VERBOSE) { motion_log(-1,0,"Begin %s", __FUNCTION__); } netcam_buff_ptr buffer; int len; netcam_buff *xchg; struct timeval curtime; struct stat statbuf; /* Point to our working buffer */ buffer = netcam->receiving; buffer->used = 0; /*int fstat(int filedes, struct stat *buf);*/ do { if( stat( netcam->file->path, &statbuf) ) { motion_log(-1, 0, "stat(%s) error", netcam->file->path ); return -1; } if (debug_level > CAMERA_VERBOSE) { motion_log(-1, 0, "statbuf.st_mtime[%d] != last_st_mtime[%d]", statbuf.st_mtime, netcam->file->last_st_mtime); } if( loop_counter>((POLLING_TIMEOUT*1000*1000)/(POLLING_TIME/1000)) ) { //its waits POLLING_TIMEOUT motion_log(-1, 0, "waiting new file image timeout" ); return -1; } if (debug_level > CAMERA_VERBOSE) { motion_log(-1, 0, "delay waiting new file image "); } //SLEEP(netcam->timeout.tv_sec, netcam->timeout.tv_usec*1000 ); //its waits 5seconds - READ_TIMEOUT SLEEP( 0, POLLING_TIME ); // its waits 500ms /*return -1;*/ loop_counter++; } while(statbuf.st_mtime==netcam->file->last_st_mtime); netcam->file->last_st_mtime = statbuf.st_mtime; if (debug_level > CAMERA_INFO) { motion_log(LOG_INFO, 0, "processing new file image - st_mtime " "%d", netcam->file->last_st_mtime ); } /* Assure there's enough room in the buffer */ while( buffer->size < (size_t)statbuf.st_size ) { netcam_check_buffsize(buffer, statbuf.st_size ); } /* Do the read */ netcam->file->control_file_desc = open( netcam->file->path, O_RDONLY ); if( netcam->file->control_file_desc < 0 ) { motion_log(-1, 0, "open(%s) error:%d", netcam->file->path, netcam->file->control_file_desc ); return -1; } if ((len = read(netcam->file->control_file_desc, buffer->ptr + buffer->used, statbuf.st_size)) < 0) { motion_log(-1, 0, "read(%s) error:%d", netcam->file->control_file_desc, len ); return -1; } buffer->used += len; close( netcam->file->control_file_desc ); if (gettimeofday(&curtime, NULL) < 0) { motion_log(LOG_ERR, 1, "gettimeofday in netcam_read_jpeg"); } netcam->receiving->image_time = curtime; /* * Calculate our "running average" time for this netcam's * frame transmissions (except for the first time). * Note that the average frame time is held in microseconds. */ if (netcam->last_image.tv_sec) { netcam->av_frame_time = ((9.0 * netcam->av_frame_time) + 1000000.0 * (curtime.tv_sec - netcam->last_image.tv_sec) + (curtime.tv_usec- netcam->last_image.tv_usec)) / 10.0; if (debug_level > CAMERA_INFO) motion_log(-1, 0, "Calculated frame time %f", netcam->av_frame_time); } netcam->last_image = curtime; /* * read is complete - set the current 'receiving' buffer atomically * as 'latest', and make the buffer previously in 'latest' become * the new 'receiving' */ pthread_mutex_lock(&netcam->mutex); xchg = netcam->latest; netcam->latest = netcam->receiving; netcam->receiving = xchg; netcam->imgcnt++; /* * We have a new frame ready. We send a signal so that * any thread (e.g. the motion main loop) waiting for the * next frame to become available may proceed. */ pthread_cond_signal(&netcam->pic_ready); pthread_mutex_unlock(&netcam->mutex); if (debug_level > CAMERA_VERBOSE) { motion_log(-1,0,"End %s", __FUNCTION__); } return 0;}tfile_context *file_new_context(void) { tfile_context *ret; /* note that mymalloc will exit on any problem */ ret = mymalloc(sizeof(tfile_context)); if (!ret) return ret; memset(ret, 0, sizeof(tfile_context)); return ret;}void file_free_context(tfile_context* ctxt) { if (ctxt == NULL) return; if (ctxt->path != NULL) free(ctxt->path); free(ctxt);}static int netcam_setup_file(netcam_context_ptr netcam, struct url_t *url) { if ((netcam->file = file_new_context()) == NULL) return -1; /* * We copy the strings out of the url structure into the ftp_context * structure. By setting url->{string} to NULL we effectively "take * ownership" of the string away from the URL (i.e. it won't be freed * when we cleanup the url structure later). */ netcam->file->path = url->path; url->path = NULL; if (debug_level > CAMERA_INFO) motion_log(LOG_INFO, 0, "netcam_setup_file: netcam->file->path %s",netcam->file->path); netcam_url_free(url); netcam->get_image = netcam_read_file_jpeg; return 0;}/** * netcam_handler_loop * This is the "main loop" for the handler thread. It is created * in netcam_start when a streaming camera is detected. * * Parameters * * arg Pointer to the motion context for this camera * * Returns: NULL pointer * */static void *netcam_handler_loop(void *arg){ int retval; int open_error = 0; netcam_context_ptr netcam = arg; struct context *cnt = netcam->cnt; /* needed for the SETUP macro :-( */ /* Store the corresponding motion thread number in TLS also for this * thread (necessary for 'motion_log' to function properly). */ pthread_setspecific(tls_key_threadnr, (void *)((unsigned long)cnt->threadnr)); if (SETUP) motion_log(LOG_INFO, 0, "Camera handler thread [%d] started", netcam->threadnr); /* * The logic of our loop is very simple. If this is a non- * streaming camera, we re-establish connection with the camera * and read the header record. If it's a streaming camera, we * position to the next "boundary string" in the input stream. * In either case, we then read the following JPEG image into the * next available buffer, updating the "next" and "latest" indices * in our netcam * structure. The loop continues until netcam->finish * or cnt->finish is set. */ while (!netcam->finish) { if (netcam->response) { /* if html input */ if (!netcam->caps.streaming) { /* Non-streaming ie. jpeg */ if (!netcam->connect_keepalive || (netcam->connect_keepalive && netcam->keepalive_timeup)) { /* If keepalive flag set but time up, time to close this socket */ if (netcam->connect_keepalive && netcam->keepalive_timeup) { motion_log(LOG_INFO, 0, "Closing netcam socket as Keep-Alive time is up " "(camera sent Close field). A reconnect should happen."); netcam_disconnect(netcam); netcam->keepalive_timeup = FALSE; } /* And the netcam_connect call below will open a new one */ if (netcam_connect(netcam, open_error) < 0) { if (!open_error) { /* log first error */ motion_log(LOG_ERR, 0, "re-opening camera (non-streaming)"); open_error = 1; } /* need to have a dynamic delay here */ SLEEP(5,0); continue; } if (open_error) { /* log re-connection */ motion_log(LOG_ERR, 0, "camera re-connected"); open_error = 0; } } /* Send our request and look at the response */ if ((retval = netcam_read_first_header(netcam)) != 1) { if (retval > 0) { motion_log(LOG_ERR, 0, "Unrecognized image header (%d)", retval); } else if (retval != -1) { motion_log(LOG_ERR, 0, "Error in header (%d)", retval); } /* need to have a dynamic delay here */ continue; } } else { /* Streaming */ if (netcam_read_next_header(netcam) < 0) { if (netcam_connect(netcam, open_error) < 0) { if (!open_error) { /* log first error */ motion_log(LOG_ERR, 0, "re-opening camera (streaming)"); open_error = 1; } SLEEP(5,0); continue; } if ((retval = netcam_read_first_header(netcam) != 2)) { if (retval > 0) { motion_log(LOG_ERR, 0, "Unrecognized image header (%d)", retval); } else if (retval != -1) { motion_log(LOG_ERR, 0, "Error in header (%d)", retval); } /* FIXME need some limit */ continue; } } if (open_error) { /* log re-connection */ motion_log(LOG_ERR, 0, "camera re-connected"); open_error = 0; } } } if (netcam->get_image(netcam) < 0) { motion_log(LOG_ERR, 0, "Error getting jpeg image"); /* if FTP connection, attempt to re-connect to server */ if (netcam->ftp) { close(netcam->ftp->control_file_desc); if (ftp_connect(netcam) < 0) { motion_log(LOG_ERR, 0, "Trying to re-connect"); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -