📄 video_freebsd.c
字号:
} */ viddev->norm=norm; if (set_geometry(viddev, width, height) == -1) return; v4l_picture_controls(cnt, viddev); viddev->input = input; viddev->width = width; viddev->height = height; viddev->freq = freq; /* skip a few frames if needed */ for (i=0; i<skip; i++) v4l_next(viddev, map, width, height); }else{ /* No round robin - we only adjust picture controls */ v4l_picture_controls(cnt, viddev); }}/***************************************************************************** Wrappers calling the current capture routines *****************************************************************************//*vid_init - Initi vid_mutex.vid_start - Setup Device parameters ( device , channel , freq , contrast , hue , saturation , brightness ) and open it.vid_next - Capture a frame and set input , contrast , hue , saturation and brightness if necessary. vid_close - close devices. vid_cleanup - Destroy vid_mutex.*//* big lock for vid_start to ensure exclusive access to viddevs while adding * devices during initialization of each thread */static pthread_mutex_t vid_mutex;/* Here we setup the viddevs structure which is used globally in the vid_* * functions. */ static struct video_dev *viddevs = NULL;/* * vid_init * * Called from motion.c at the very beginning before setting up the threads. * Function prepares the vid_mutex */void vid_init(void){ pthread_mutex_init(&vid_mutex, NULL);} /** * vid_cleanup * * vid_cleanup is called from motion.c when Motion is stopped or restarted */void vid_cleanup(void){ pthread_mutex_destroy(&vid_mutex);}#endif /*WITHOUT_V4L*//** * vid_close * * vid_close is called from motion.c when a Motion thread is stopped or restarted */void vid_close(struct context *cnt) {#ifndef WITHOUT_V4L struct video_dev *dev = viddevs; struct video_dev *prev = NULL;#endif /* Cleanup the netcam part */ if(cnt->netcam) { netcam_cleanup(cnt->netcam, 0); cnt->netcam = NULL; return; } #ifndef WITHOUT_V4L /* Cleanup the v4l part */ pthread_mutex_lock(&vid_mutex); while (dev) { if (dev->fd_bktr == cnt->video_dev) break; prev = dev; dev = dev->next; } pthread_mutex_unlock(&vid_mutex); /* Set it as closed in thread context */ cnt->video_dev = -1; if (dev == NULL) { motion_log(LOG_ERR, 0, "vid_close: Unable to find video device"); return; } if( --dev->usage_count == 0) { motion_log(LOG_INFO, 0, "Closing video device %s", dev->video_device); if (dev->fd_tuner > 0) close(dev->fd_tuner); if (dev->fd_bktr > 0){ dev->fd_tuner = METEOR_CAP_STOP_CONT; ioctl(dev->fd_bktr, METEORCAPTUR, &dev->fd_tuner); close(dev->fd_bktr); dev->fd_tuner = -1; } munmap(viddevs->v4l_buffers[0],viddevs->v4l_bufsize); viddevs->v4l_buffers[0] = MAP_FAILED; dev->fd_bktr = -1; pthread_mutex_lock(&vid_mutex); /* Remove from list */ if (prev == NULL) viddevs = dev->next; else prev->next = dev->next; pthread_mutex_unlock(&vid_mutex); pthread_mutexattr_destroy(&dev->attr); pthread_mutex_destroy(&dev->mutex); free(dev); } else { motion_log(LOG_INFO, 0, "Still %d users of video device %s, so we don't close it now", dev->usage_count, dev->video_device); /* There is still at least one thread using this device * If we own it, release it */ if (dev->owner == cnt->threadnr) { dev->frames = 0; dev->owner = -1; pthread_mutex_unlock(&dev->mutex); } }#endif /* WITHOUT_V4L */}int vid_start(struct context *cnt){ struct config *conf = &cnt->conf; int fd_bktr = -1; if (conf->netcam_url) { fd_bktr = netcam_start(cnt); if (fd_bktr < 0) { netcam_cleanup(cnt->netcam, 1); cnt->netcam = NULL; } } #ifdef WITHOUT_V4L else motion_log(LOG_ERR, 0,"You must setup netcam_url"); #else else{ struct video_dev *dev; int fd_tuner =-1; int width, height; unsigned short input, norm; unsigned long frequency; motion_log(-1, 0, "vid_start [%s]", conf->video_device); /* We use width and height from conf in this function. They will be assigned * to width and height in imgs here, and cap_width and cap_height in * rotate_data won't be set until in rotate_init. * Motion requires that width and height are multiples of 16 so we check for this */ if (conf->width % 16) { motion_log(LOG_ERR, 0, "config image width (%d) is not modulo 16", conf->width); return -1; } if (conf->height % 16) { motion_log(LOG_ERR, 0, "config image height (%d) is not modulo 16", conf->height); return -1; } width = conf->width; height = conf->height; input = conf->input; norm = conf->norm; frequency = conf->frequency; pthread_mutex_lock(&vid_mutex); /* Transfer width and height from conf to imgs. The imgs values are the ones * that is used internally in Motion. That way, setting width and height via * http remote control won't screw things up. */ cnt->imgs.width = width; cnt->imgs.height = height; /* First we walk through the already discovered video devices to see * if we have already setup the same device before. If this is the case * the device is a Round Robin device and we set the basic settings * and return the file descriptor */ dev = viddevs; while (dev) { if (!strcmp(conf->video_device, dev->video_device)) { dev->usage_count++; cnt->imgs.type = dev->v4l_fmt; motion_log(-1, 0, "vid_start cnt->imgs.type [%i]", cnt->imgs.type); switch (cnt->imgs.type) { case VIDEO_PALETTE_GREY: cnt->imgs.motionsize = width * height; cnt->imgs.size = width * height; break; case VIDEO_PALETTE_RGB24: case VIDEO_PALETTE_YUV422: cnt->imgs.type = VIDEO_PALETTE_YUV420P; case VIDEO_PALETTE_YUV420P: motion_log(-1, 0, " VIDEO_PALETTE_YUV420P setting imgs.size and imgs.motionsize"); cnt->imgs.motionsize = width * height; cnt->imgs.size = (width * height * 3) / 2; break; } pthread_mutex_unlock(&vid_mutex); return dev->fd_bktr; // FIXME return fd_tuner ?! } dev = dev->next; } dev = mymalloc(sizeof(struct video_dev)); memset(dev, 0, sizeof(struct video_dev)); fd_bktr=open(conf->video_device, O_RDWR); if (fd_bktr < 0) { motion_log(LOG_ERR, 1, "open video device %s",conf->video_device); free(dev); pthread_mutex_unlock(&vid_mutex); return -1; } /* Only open tuner if conf->tuner_device has set , freq and input is 1 */ if ( (conf->tuner_device != NULL) && (frequency > 0) && ( input == IN_TV )) { fd_tuner=open(conf->tuner_device, O_RDWR); if (fd_tuner < 0) { motion_log(LOG_ERR, 1, "open tuner device %s",conf->tuner_device); free(dev); pthread_mutex_unlock(&vid_mutex); return -1; } } pthread_mutexattr_init(&dev->attr); pthread_mutex_init(&dev->mutex, &dev->attr); dev->usage_count = 1; dev->video_device = conf->video_device; dev->tuner_device = conf->tuner_device; dev->fd_bktr = fd_bktr; dev->fd_tuner = fd_tuner; dev->input = input; dev->height = height; dev->width = width; dev->freq = frequency; dev->owner = -1; /* We set brightness, contrast, saturation and hue = 0 so that they only get * set if the config is not zero. */ dev->brightness = 0; dev->contrast = 0; dev->saturation = 0; dev->hue = 0; dev->owner = -1; /* default palette */ dev->v4l_fmt = VIDEO_PALETTE_YUV420P; dev->v4l_curbuffer = 0; dev->v4l_maxbuffer = 1; if (!v4l_start (cnt, dev, width, height, input, norm, frequency)){ close(dev->fd_bktr); pthread_mutexattr_destroy(&dev->attr); pthread_mutex_destroy(&dev->mutex); free(dev); pthread_mutex_unlock(&vid_mutex); return -1; } cnt->imgs.type=dev->v4l_fmt; switch (cnt->imgs.type) { case VIDEO_PALETTE_GREY: cnt->imgs.size = width * height; cnt->imgs.motionsize = width * height; break; case VIDEO_PALETTE_RGB24: case VIDEO_PALETTE_YUV422: cnt->imgs.type = VIDEO_PALETTE_YUV420P; case VIDEO_PALETTE_YUV420P: motion_log(-1, 0, "VIDEO_PALETTE_YUV420P imgs.type"); cnt->imgs.size = (width * height * 3) / 2; cnt->imgs.motionsize = width * height; break; } /* Insert into linked list */ dev->next = viddevs; viddevs = dev; pthread_mutex_unlock(&vid_mutex); }#endif /* WITHOUT_V4L */ /* FIXME needed tuner device ?! */ return fd_bktr;}/** * vid_next fetches a video frame from a either v4l device or netcam * Parameters: * cnt Pointer to the context for this thread * map Pointer to the buffer in which the function puts the new image * * Returns * 0 Success * -1 Fatal V4L error * -2 Fatal Netcam error * 1 Non fatal V4L error (not implemented) * 2 Non fatal Netcam error */int vid_next(struct context *cnt, unsigned char *map){ struct config *conf=&cnt->conf; int ret = -1; if (conf->netcam_url) { if (cnt->video_dev == -1) return NETCAM_GENERAL_ERROR; ret = netcam_next(cnt, map); return ret; }#ifndef WITHOUT_V4L struct video_dev *dev; int width, height; int dev_bktr = cnt->video_dev; /* NOTE: Since this is a capture, we need to use capture dimensions. */ width = cnt->rotate_data.cap_width; height = cnt->rotate_data.cap_height; pthread_mutex_lock(&vid_mutex); dev = viddevs; while (dev){ if (dev->fd_bktr==dev_bktr) break; dev = dev->next; } pthread_mutex_unlock(&vid_mutex); if (dev == NULL) return V4L_FATAL_ERROR; //return -1; if (dev->owner!=cnt->threadnr) { pthread_mutex_lock(&dev->mutex); dev->owner = cnt->threadnr; dev->frames = conf->roundrobin_frames; } v4l_set_input(cnt, dev, map, width, height, conf->input, conf->norm, conf->roundrobin_skip, conf->frequency); ret = v4l_next(dev, map, width, height); if (--dev->frames <= 0) { dev->owner = -1; dev->frames = 0; pthread_mutex_unlock(&dev->mutex); } if(cnt->rotate_data.degrees > 0){ /* rotate the image as specified */ rotate_map(cnt, map); } #endif /*WITHOUT_V4L*/ return ret;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -