mirror of
				https://github.com/hyperion-project/hyperion.ng.git
				synced 2025-03-01 10:33:28 +00:00 
			
		
		
		
	Replaced exit statements for exceptions
Former-commit-id: 1eb180620fb59613eaa02da84026ffdcb28803a4
This commit is contained in:
		| @@ -1,4 +1,6 @@ | ||||
| #include <iostream> | ||||
| #include <sstream> | ||||
| #include <stdexcept> | ||||
| #include <cstdio> | ||||
| #include <cassert> | ||||
| #include <cstdlib> | ||||
| @@ -92,14 +94,13 @@ void V4L2Grabber::capture(int frameCount) | ||||
| 			if (-1 == r) | ||||
| 			{ | ||||
| 				if (EINTR == errno) | ||||
| 						continue; | ||||
| 				errno_exit("select"); | ||||
| 					continue; | ||||
| 				throw_errno_exception("select"); | ||||
| 			} | ||||
|  | ||||
| 			if (0 == r) | ||||
| 			{ | ||||
| 				fprintf(stderr, "select timeout\n"); | ||||
| 				exit(EXIT_FAILURE); | ||||
| 				throw_exception("select timeout"); | ||||
| 			} | ||||
|  | ||||
| 			if (read_frame()) | ||||
| @@ -119,317 +120,327 @@ void V4L2Grabber::stop() | ||||
|  | ||||
| void V4L2Grabber::open_device() | ||||
| { | ||||
| 		struct stat st; | ||||
| 	struct stat st; | ||||
|  | ||||
| 		if (-1 == stat(_deviceName.c_str(), &st)) | ||||
| 		{ | ||||
| 				fprintf(stderr, "Cannot identify '%s': %d, %s\n", _deviceName.c_str(), errno, strerror(errno)); | ||||
| 				exit(EXIT_FAILURE); | ||||
| 		} | ||||
| 	if (-1 == stat(_deviceName.c_str(), &st)) | ||||
| 	{ | ||||
| 		std::ostringstream oss; | ||||
| 		oss << "Cannot identify '" << _deviceName << "'"; | ||||
| 		throw_errno_exception(oss.str()); | ||||
| 	} | ||||
|  | ||||
| 		if (!S_ISCHR(st.st_mode)) | ||||
| 		{ | ||||
| 				fprintf(stderr, "%s is no device\n", _deviceName.c_str()); | ||||
| 				exit(EXIT_FAILURE); | ||||
| 		} | ||||
| 	if (!S_ISCHR(st.st_mode)) | ||||
| 	{ | ||||
| 		std::ostringstream oss; | ||||
| 		oss << "'" << _deviceName << "' is no device"; | ||||
| 		throw_exception(oss.str()); | ||||
| 	} | ||||
|  | ||||
| 		_fileDescriptor = open(_deviceName.c_str(), O_RDWR /* required */ | O_NONBLOCK, 0); | ||||
| 	_fileDescriptor = open(_deviceName.c_str(), O_RDWR /* required */ | O_NONBLOCK, 0); | ||||
|  | ||||
| 		if (-1 == _fileDescriptor) | ||||
| 		{ | ||||
| 				fprintf(stderr, "Cannot open '%s': %d, %s\n", _deviceName.c_str(), errno, strerror(errno)); | ||||
| 				exit(EXIT_FAILURE); | ||||
| 		} | ||||
| 	if (-1 == _fileDescriptor) | ||||
| 	{ | ||||
| 		std::ostringstream oss; | ||||
| 		oss << "Cannot open '" << _deviceName << "'"; | ||||
| 		throw_errno_exception(oss.str()); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void V4L2Grabber::close_device() | ||||
| { | ||||
| 		if (-1 == close(_fileDescriptor)) | ||||
| 				errno_exit("close"); | ||||
| 	if (-1 == close(_fileDescriptor)) | ||||
| 		throw_errno_exception("close"); | ||||
|  | ||||
| 		_fileDescriptor = -1; | ||||
| 	_fileDescriptor = -1; | ||||
| } | ||||
|  | ||||
| void V4L2Grabber::init_read(unsigned int buffer_size) | ||||
| { | ||||
| 		_buffers.resize(1); | ||||
| 	_buffers.resize(1); | ||||
|  | ||||
| 		_buffers[0].length = buffer_size; | ||||
| 		_buffers[0].start = malloc(buffer_size); | ||||
| 	_buffers[0].length = buffer_size; | ||||
| 	_buffers[0].start = malloc(buffer_size); | ||||
|  | ||||
| 		if (!_buffers[0].start) { | ||||
| 				fprintf(stderr, "Out of memory\n"); | ||||
| 				exit(EXIT_FAILURE); | ||||
| 		} | ||||
| 	if (!_buffers[0].start) { | ||||
| 		throw_exception("Out of memory"); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void V4L2Grabber::init_mmap() | ||||
| { | ||||
| 		struct v4l2_requestbuffers req; | ||||
| 	struct v4l2_requestbuffers req; | ||||
|  | ||||
| 		CLEAR(req); | ||||
| 	CLEAR(req); | ||||
|  | ||||
| 		req.count = 4; | ||||
| 		req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||||
| 		req.memory = V4L2_MEMORY_MMAP; | ||||
| 	req.count = 4; | ||||
| 	req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||||
| 	req.memory = V4L2_MEMORY_MMAP; | ||||
|  | ||||
| 		if (-1 == xioctl(VIDIOC_REQBUFS, &req)) { | ||||
| 				if (EINVAL == errno) { | ||||
| 						fprintf(stderr, "%s does not support memory mapping\n", _deviceName.c_str()); | ||||
| 						exit(EXIT_FAILURE); | ||||
| 				} else { | ||||
| 						errno_exit("VIDIOC_REQBUFS"); | ||||
| 				} | ||||
| 	if (-1 == xioctl(VIDIOC_REQBUFS, &req)) { | ||||
| 		if (EINVAL == errno) { | ||||
| 			std::ostringstream oss; | ||||
| 			oss << "'" << _deviceName << "' does not support memory mapping"; | ||||
| 			throw_exception(oss.str()); | ||||
| 		} else { | ||||
| 			throw_errno_exception("VIDIOC_REQBUFS"); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 		if (req.count < 2) { | ||||
| 				fprintf(stderr, "Insufficient buffer memory on %s\n", _deviceName.c_str()); | ||||
| 				exit(EXIT_FAILURE); | ||||
| 		} | ||||
| 	if (req.count < 2) { | ||||
| 		std::ostringstream oss; | ||||
| 		oss << "Insufficient buffer memory on " << _deviceName; | ||||
| 		throw_exception(oss.str()); | ||||
| 	} | ||||
|  | ||||
| 		_buffers.resize(req.count); | ||||
| 	_buffers.resize(req.count); | ||||
|  | ||||
| 		for (size_t n_buffers = 0; n_buffers < req.count; ++n_buffers) { | ||||
| 				struct v4l2_buffer buf; | ||||
| 	for (size_t n_buffers = 0; n_buffers < req.count; ++n_buffers) { | ||||
| 		struct v4l2_buffer buf; | ||||
|  | ||||
| 				CLEAR(buf); | ||||
| 		CLEAR(buf); | ||||
|  | ||||
| 				buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||||
| 				buf.memory      = V4L2_MEMORY_MMAP; | ||||
| 				buf.index       = n_buffers; | ||||
| 		buf.type        = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||||
| 		buf.memory      = V4L2_MEMORY_MMAP; | ||||
| 		buf.index       = n_buffers; | ||||
|  | ||||
| 				if (-1 == xioctl(VIDIOC_QUERYBUF, &buf)) | ||||
| 						errno_exit("VIDIOC_QUERYBUF"); | ||||
| 		if (-1 == xioctl(VIDIOC_QUERYBUF, &buf)) | ||||
| 			throw_errno_exception("VIDIOC_QUERYBUF"); | ||||
|  | ||||
| 				_buffers[n_buffers].length = buf.length; | ||||
| 				_buffers[n_buffers].start = | ||||
| 						mmap(NULL /* start anywhere */, | ||||
| 							  buf.length, | ||||
| 							  PROT_READ | PROT_WRITE /* required */, | ||||
| 							  MAP_SHARED /* recommended */, | ||||
| 							  _fileDescriptor, buf.m.offset); | ||||
| 		_buffers[n_buffers].length = buf.length; | ||||
| 		_buffers[n_buffers].start = | ||||
| 				mmap(NULL /* start anywhere */, | ||||
| 					 buf.length, | ||||
| 					 PROT_READ | PROT_WRITE /* required */, | ||||
| 					 MAP_SHARED /* recommended */, | ||||
| 					 _fileDescriptor, buf.m.offset); | ||||
|  | ||||
| 				if (MAP_FAILED == _buffers[n_buffers].start) | ||||
| 						errno_exit("mmap"); | ||||
| 		} | ||||
| 		if (MAP_FAILED == _buffers[n_buffers].start) | ||||
| 			throw_errno_exception("mmap"); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void V4L2Grabber::init_userp(unsigned int buffer_size) | ||||
| { | ||||
| 		struct v4l2_requestbuffers req; | ||||
| 	struct v4l2_requestbuffers req; | ||||
|  | ||||
| 		CLEAR(req); | ||||
| 	CLEAR(req); | ||||
|  | ||||
| 		req.count  = 4; | ||||
| 		req.type   = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||||
| 		req.memory = V4L2_MEMORY_USERPTR; | ||||
| 	req.count  = 4; | ||||
| 	req.type   = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||||
| 	req.memory = V4L2_MEMORY_USERPTR; | ||||
|  | ||||
| 		if (-1 == xioctl(VIDIOC_REQBUFS, &req)) { | ||||
| 				if (EINVAL == errno) | ||||
| 				{ | ||||
| 						fprintf(stderr, "%s does not support user pointer i/o\n", _deviceName.c_str()); | ||||
| 						exit(EXIT_FAILURE); | ||||
| 				} else { | ||||
| 						errno_exit("VIDIOC_REQBUFS"); | ||||
| 				} | ||||
| 	if (-1 == xioctl(VIDIOC_REQBUFS, &req)) { | ||||
| 		if (EINVAL == errno) | ||||
| 		{ | ||||
| 			std::ostringstream oss; | ||||
| 			oss << "'" << _deviceName << "' does not support user pointer"; | ||||
| 			throw_exception(oss.str()); | ||||
| 		} else { | ||||
| 			throw_errno_exception("VIDIOC_REQBUFS"); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 		_buffers.resize(4); | ||||
| 	_buffers.resize(4); | ||||
|  | ||||
| 		for (size_t n_buffers = 0; n_buffers < 4; ++n_buffers) { | ||||
| 				_buffers[n_buffers].length = buffer_size; | ||||
| 				_buffers[n_buffers].start = malloc(buffer_size); | ||||
| 	for (size_t n_buffers = 0; n_buffers < 4; ++n_buffers) { | ||||
| 		_buffers[n_buffers].length = buffer_size; | ||||
| 		_buffers[n_buffers].start = malloc(buffer_size); | ||||
|  | ||||
| 				if (!_buffers[n_buffers].start) { | ||||
| 						fprintf(stderr, "Out of memory\n"); | ||||
| 						exit(EXIT_FAILURE); | ||||
| 				} | ||||
| 		if (!_buffers[n_buffers].start) { | ||||
| 			throw_exception("Out of memory"); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void V4L2Grabber::init_device(VideoStandard videoStandard, int input) | ||||
| { | ||||
| 		struct v4l2_capability cap; | ||||
| 		if (-1 == xioctl(VIDIOC_QUERYCAP, &cap)) | ||||
| 		{ | ||||
| 				if (EINVAL == errno) { | ||||
| 						fprintf(stderr, "%s is no V4L2 device\n", _deviceName.c_str()); | ||||
| 						exit(EXIT_FAILURE); | ||||
| 				} else { | ||||
| 						errno_exit("VIDIOC_QUERYCAP"); | ||||
| 				} | ||||
| 		} | ||||
|  | ||||
| 		if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) | ||||
| 		{ | ||||
| 				fprintf(stderr, "%s is no video capture device\n", _deviceName.c_str()); | ||||
| 				exit(EXIT_FAILURE); | ||||
| 		} | ||||
|  | ||||
| 		switch (_ioMethod) { | ||||
| 		case IO_METHOD_READ: | ||||
| 				if (!(cap.capabilities & V4L2_CAP_READWRITE)) | ||||
| 				{ | ||||
| 						fprintf(stderr, "%s does not support read i/o\n", _deviceName.c_str()); | ||||
| 						exit(EXIT_FAILURE); | ||||
| 				} | ||||
| 				break; | ||||
|  | ||||
| 		case IO_METHOD_MMAP: | ||||
| 		case IO_METHOD_USERPTR: | ||||
| 				if (!(cap.capabilities & V4L2_CAP_STREAMING)) | ||||
| 				{ | ||||
| 						fprintf(stderr, "%s does not support streaming i/o\n", _deviceName.c_str()); | ||||
| 						exit(EXIT_FAILURE); | ||||
| 				} | ||||
| 				break; | ||||
| 		} | ||||
|  | ||||
|  | ||||
| 		/* Select video input, video standard and tune here. */ | ||||
|  | ||||
| 		struct v4l2_cropcap cropcap; | ||||
| 		CLEAR(cropcap); | ||||
|  | ||||
| 		cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||||
|  | ||||
| 		if (0 == xioctl(VIDIOC_CROPCAP, &cropcap)) { | ||||
| 				struct v4l2_crop crop; | ||||
| 				crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||||
| 				crop.c = cropcap.defrect; /* reset to default */ | ||||
|  | ||||
| 				if (-1 == xioctl(VIDIOC_S_CROP, &crop)) { | ||||
| 						switch (errno) { | ||||
| 						case EINVAL: | ||||
| 								/* Cropping not supported. */ | ||||
| 								break; | ||||
| 						default: | ||||
| 								/* Errors ignored. */ | ||||
| 								break; | ||||
| 						} | ||||
| 				} | ||||
| 	struct v4l2_capability cap; | ||||
| 	if (-1 == xioctl(VIDIOC_QUERYCAP, &cap)) | ||||
| 	{ | ||||
| 		if (EINVAL == errno) { | ||||
| 			std::ostringstream oss; | ||||
| 			oss << "'" << _deviceName << "' is no V4L2 device"; | ||||
| 			throw_exception(oss.str()); | ||||
| 		} else { | ||||
| 			throw_errno_exception("VIDIOC_QUERYCAP"); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) | ||||
| 	{ | ||||
| 		std::ostringstream oss; | ||||
| 		oss << "'" << _deviceName << "' is no video capture device"; | ||||
| 		throw_exception(oss.str()); | ||||
| 	} | ||||
|  | ||||
| 	switch (_ioMethod) { | ||||
| 	case IO_METHOD_READ: | ||||
| 		if (!(cap.capabilities & V4L2_CAP_READWRITE)) | ||||
| 		{ | ||||
| 			std::ostringstream oss; | ||||
| 			oss << "'" << _deviceName << "' does not support read i/o"; | ||||
| 			throw_exception(oss.str()); | ||||
| 		} | ||||
| 		break; | ||||
|  | ||||
| 	case IO_METHOD_MMAP: | ||||
| 	case IO_METHOD_USERPTR: | ||||
| 		if (!(cap.capabilities & V4L2_CAP_STREAMING)) | ||||
| 		{ | ||||
| 			std::ostringstream oss; | ||||
| 			oss << "'" << _deviceName << "' does not support streaming i/o"; | ||||
| 			throw_exception(oss.str()); | ||||
| 		} | ||||
| 		break; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	/* Select video input, video standard and tune here. */ | ||||
|  | ||||
| 	struct v4l2_cropcap cropcap; | ||||
| 	CLEAR(cropcap); | ||||
|  | ||||
| 	cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||||
|  | ||||
| 	if (0 == xioctl(VIDIOC_CROPCAP, &cropcap)) { | ||||
| 		struct v4l2_crop crop; | ||||
| 		crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||||
| 		crop.c = cropcap.defrect; /* reset to default */ | ||||
|  | ||||
| 		if (-1 == xioctl(VIDIOC_S_CROP, &crop)) { | ||||
| 			switch (errno) { | ||||
| 			case EINVAL: | ||||
| 				/* Cropping not supported. */ | ||||
| 				break; | ||||
| 			default: | ||||
| 				/* Errors ignored. */ | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
| 	} else { | ||||
| 		/* Errors ignored. */ | ||||
| 	} | ||||
|  | ||||
| 		// set input if needed | ||||
| 		if (input >= 0) | ||||
| 	// set input if needed | ||||
| 	if (input >= 0) | ||||
| 	{ | ||||
| 		if (-1 == xioctl(VIDIOC_S_INPUT, &input)) | ||||
| 		{ | ||||
| 			if (-1 == xioctl(VIDIOC_S_INPUT, &input)) | ||||
| 			{ | ||||
| 				errno_exit("VIDIOC_S_INPUT"); | ||||
| 			} | ||||
| 			throw_errno_exception("VIDIOC_S_INPUT"); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 		// set the video standard if needed | ||||
| 		switch (videoStandard) | ||||
| 	// set the video standard if needed | ||||
| 	switch (videoStandard) | ||||
| 	{ | ||||
| 	case PAL: | ||||
| 	{ | ||||
| 		v4l2_std_id std_id = V4L2_STD_PAL; | ||||
| 		if (-1 == xioctl(VIDIOC_S_STD, &std_id)) | ||||
| 		{ | ||||
| 		case PAL: | ||||
| 			{ | ||||
| 				v4l2_std_id std_id = V4L2_STD_PAL; | ||||
| 				if (-1 == xioctl(VIDIOC_S_STD, &std_id)) | ||||
| 				{ | ||||
| 						errno_exit("VIDIOC_S_STD"); | ||||
| 				} | ||||
| 			} | ||||
| 			break; | ||||
| 		case NTSC: | ||||
| 			{ | ||||
| 				v4l2_std_id std_id = V4L2_STD_NTSC; | ||||
| 				if (-1 == xioctl(VIDIOC_S_STD, &std_id)) | ||||
| 				{ | ||||
| 						errno_exit("VIDIOC_S_STD"); | ||||
| 				} | ||||
| 			} | ||||
| 			break; | ||||
| 		case NO_CHANGE: | ||||
| 		default: | ||||
| 			// No change to device settings | ||||
| 			break; | ||||
| 			throw_errno_exception("VIDIOC_S_STD"); | ||||
| 		} | ||||
| 	} | ||||
| 		break; | ||||
| 	case NTSC: | ||||
| 	{ | ||||
| 		v4l2_std_id std_id = V4L2_STD_NTSC; | ||||
| 		if (-1 == xioctl(VIDIOC_S_STD, &std_id)) | ||||
| 		{ | ||||
| 			throw_errno_exception("VIDIOC_S_STD"); | ||||
| 		} | ||||
| 	} | ||||
| 		break; | ||||
| 	case NO_CHANGE: | ||||
| 	default: | ||||
| 		// No change to device settings | ||||
| 		break; | ||||
| 	} | ||||
|  | ||||
|  | ||||
| 	// get the current settings | ||||
| 	struct v4l2_format fmt; | ||||
| 	CLEAR(fmt); | ||||
| 	fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||||
| 	if (-1 == xioctl(VIDIOC_G_FMT, &fmt)) | ||||
| 	{ | ||||
| 		throw_errno_exception("VIDIOC_G_FMT"); | ||||
| 	} | ||||
|  | ||||
| 	// check pixel format | ||||
| 	if (fmt.fmt.pix.pixelformat != V4L2_PIX_FMT_UYVY) | ||||
| 	{ | ||||
| 		throw_exception("Only pixel format UYVY is supported"); | ||||
| 	} | ||||
|  | ||||
| 	if (_width > 0 || _height > 0) | ||||
| 	{ | ||||
| 		if (_width > 0) | ||||
| 		{ | ||||
| 			fmt.fmt.pix.width = _width; | ||||
| 		} | ||||
|  | ||||
| 		if (fmt.fmt.pix.height > 0) | ||||
| 		{ | ||||
| 			fmt.fmt.pix.height = _height; | ||||
| 		} | ||||
|  | ||||
| 		// get the current settings | ||||
| 		struct v4l2_format fmt; | ||||
| 		CLEAR(fmt); | ||||
| 		fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||||
| 		// set the settings | ||||
| 		if (-1 == xioctl(VIDIOC_S_FMT, &fmt)) | ||||
| 		{ | ||||
| 			throw_errno_exception("VIDIOC_S_FMT"); | ||||
| 		} | ||||
|  | ||||
| 		// get the format settings again | ||||
| 		// (the size may not have been accepted without an error) | ||||
| 		if (-1 == xioctl(VIDIOC_G_FMT, &fmt)) | ||||
| 		{ | ||||
| 			errno_exit("VIDIOC_G_FMT"); | ||||
| 			throw_errno_exception("VIDIOC_G_FMT"); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 		// check pixel format | ||||
| 		if (fmt.fmt.pix.pixelformat != V4L2_PIX_FMT_UYVY) | ||||
| 		{ | ||||
| 			exit(EXIT_FAILURE); | ||||
| 		} | ||||
| 	// store width & height | ||||
| 	_width = fmt.fmt.pix.width; | ||||
| 	_height = fmt.fmt.pix.height; | ||||
|  | ||||
| 		if (_width > 0 || _height > 0) | ||||
| 		{ | ||||
| 			if (_width > 0) | ||||
| 			{ | ||||
| 				fmt.fmt.pix.width = _width; | ||||
| 			} | ||||
| 	// print the eventually used width and height | ||||
| 	std::cout << "V4L2 width=" << _width << " height=" << _height << std::endl; | ||||
|  | ||||
| 			if (fmt.fmt.pix.height > 0) | ||||
| 			{ | ||||
| 				fmt.fmt.pix.height = _height; | ||||
| 			} | ||||
| 	switch (_ioMethod) { | ||||
| 	case IO_METHOD_READ: | ||||
| 		init_read(fmt.fmt.pix.sizeimage); | ||||
| 		break; | ||||
|  | ||||
| 			// set the settings | ||||
| 			if (-1 == xioctl(VIDIOC_S_FMT, &fmt)) | ||||
| 			{ | ||||
| 				errno_exit("VIDIOC_S_FMT"); | ||||
| 			} | ||||
| 	case IO_METHOD_MMAP: | ||||
| 		init_mmap(); | ||||
| 		break; | ||||
|  | ||||
| 			// get the format settings again | ||||
| 			// (the size may not have been accepted without an error) | ||||
| 			if (-1 == xioctl(VIDIOC_G_FMT, &fmt)) | ||||
| 			{ | ||||
| 				errno_exit("VIDIOC_G_FMT"); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		// store width & height | ||||
| 		_width = fmt.fmt.pix.width; | ||||
| 		_height = fmt.fmt.pix.height; | ||||
| 		std::cout << "V4L2 width=" << _width << " height=" << _height << std::endl; | ||||
|  | ||||
| 		switch (_ioMethod) { | ||||
| 		case IO_METHOD_READ: | ||||
| 				init_read(fmt.fmt.pix.sizeimage); | ||||
| 				break; | ||||
|  | ||||
| 		case IO_METHOD_MMAP: | ||||
| 				init_mmap(); | ||||
| 				break; | ||||
|  | ||||
| 		case IO_METHOD_USERPTR: | ||||
| 				init_userp(fmt.fmt.pix.sizeimage); | ||||
| 				break; | ||||
| 		} | ||||
| 	case IO_METHOD_USERPTR: | ||||
| 		init_userp(fmt.fmt.pix.sizeimage); | ||||
| 		break; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void V4L2Grabber::uninit_device() | ||||
| { | ||||
| 		switch (_ioMethod) { | ||||
| 		case IO_METHOD_READ: | ||||
| 				free(_buffers[0].start); | ||||
| 				break; | ||||
| 	switch (_ioMethod) { | ||||
| 	case IO_METHOD_READ: | ||||
| 		free(_buffers[0].start); | ||||
| 		break; | ||||
|  | ||||
| 		case IO_METHOD_MMAP: | ||||
| 				for (size_t i = 0; i < _buffers.size(); ++i) | ||||
| 						if (-1 == munmap(_buffers[i].start, _buffers[i].length)) | ||||
| 								errno_exit("munmap"); | ||||
| 				break; | ||||
| 	case IO_METHOD_MMAP: | ||||
| 		for (size_t i = 0; i < _buffers.size(); ++i) | ||||
| 			if (-1 == munmap(_buffers[i].start, _buffers[i].length)) | ||||
| 				throw_errno_exception("munmap"); | ||||
| 		break; | ||||
|  | ||||
| 		case IO_METHOD_USERPTR: | ||||
| 				for (size_t i = 0; i < _buffers.size(); ++i) | ||||
| 						free(_buffers[i].start); | ||||
| 				break; | ||||
| 		} | ||||
| 	case IO_METHOD_USERPTR: | ||||
| 		for (size_t i = 0; i < _buffers.size(); ++i) | ||||
| 			free(_buffers[i].start); | ||||
| 		break; | ||||
| 	} | ||||
|  | ||||
| 		_buffers.resize(0); | ||||
| 	_buffers.resize(0); | ||||
| } | ||||
|  | ||||
| void V4L2Grabber::start_capturing() | ||||
| @@ -442,39 +453,39 @@ void V4L2Grabber::start_capturing() | ||||
| 	case IO_METHOD_MMAP: | ||||
| 	{ | ||||
| 		for (size_t i = 0; i < _buffers.size(); ++i) { | ||||
| 				struct v4l2_buffer buf; | ||||
| 			struct v4l2_buffer buf; | ||||
|  | ||||
| 				CLEAR(buf); | ||||
| 				buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||||
| 				buf.memory = V4L2_MEMORY_MMAP; | ||||
| 				buf.index = i; | ||||
| 			CLEAR(buf); | ||||
| 			buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||||
| 			buf.memory = V4L2_MEMORY_MMAP; | ||||
| 			buf.index = i; | ||||
|  | ||||
| 				if (-1 == xioctl(VIDIOC_QBUF, &buf)) | ||||
| 						errno_exit("VIDIOC_QBUF"); | ||||
| 			if (-1 == xioctl(VIDIOC_QBUF, &buf)) | ||||
| 				throw_errno_exception("VIDIOC_QBUF"); | ||||
| 		} | ||||
| 		v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||||
| 		if (-1 == xioctl(VIDIOC_STREAMON, &type)) | ||||
| 				errno_exit("VIDIOC_STREAMON"); | ||||
| 			throw_errno_exception("VIDIOC_STREAMON"); | ||||
| 		break; | ||||
| 	} | ||||
| 	case IO_METHOD_USERPTR: | ||||
| 	{ | ||||
| 		for (size_t i = 0; i < _buffers.size(); ++i) { | ||||
| 				struct v4l2_buffer buf; | ||||
| 			struct v4l2_buffer buf; | ||||
|  | ||||
| 				CLEAR(buf); | ||||
| 				buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||||
| 				buf.memory = V4L2_MEMORY_USERPTR; | ||||
| 				buf.index = i; | ||||
| 				buf.m.userptr = (unsigned long)_buffers[i].start; | ||||
| 				buf.length = _buffers[i].length; | ||||
| 			CLEAR(buf); | ||||
| 			buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||||
| 			buf.memory = V4L2_MEMORY_USERPTR; | ||||
| 			buf.index = i; | ||||
| 			buf.m.userptr = (unsigned long)_buffers[i].start; | ||||
| 			buf.length = _buffers[i].length; | ||||
|  | ||||
| 				if (-1 == xioctl(VIDIOC_QBUF, &buf)) | ||||
| 						errno_exit("VIDIOC_QBUF"); | ||||
| 			if (-1 == xioctl(VIDIOC_QBUF, &buf)) | ||||
| 				throw_errno_exception("VIDIOC_QBUF"); | ||||
| 		} | ||||
| 		v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||||
| 		if (-1 == xioctl(VIDIOC_STREAMON, &type)) | ||||
| 				errno_exit("VIDIOC_STREAMON"); | ||||
| 			throw_errno_exception("VIDIOC_STREAMON"); | ||||
| 		break; | ||||
| 	} | ||||
| 	} | ||||
| @@ -486,15 +497,15 @@ void V4L2Grabber::stop_capturing() | ||||
|  | ||||
| 	switch (_ioMethod) { | ||||
| 	case IO_METHOD_READ: | ||||
| 			/* Nothing to do. */ | ||||
| 			break; | ||||
| 		/* Nothing to do. */ | ||||
| 		break; | ||||
|  | ||||
| 	case IO_METHOD_MMAP: | ||||
| 	case IO_METHOD_USERPTR: | ||||
| 			type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||||
| 			if (-1 == xioctl(VIDIOC_STREAMOFF, &type)) | ||||
| 					errno_exit("VIDIOC_STREAMOFF"); | ||||
| 			break; | ||||
| 		type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||||
| 		if (-1 == xioctl(VIDIOC_STREAMOFF, &type)) | ||||
| 			throw_errno_exception("VIDIOC_STREAMOFF"); | ||||
| 		break; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -506,99 +517,99 @@ int V4L2Grabber::read_frame() | ||||
|  | ||||
| 	switch (_ioMethod) { | ||||
| 	case IO_METHOD_READ: | ||||
| 			int size; | ||||
| 			if ((size = read(_fileDescriptor, _buffers[0].start, _buffers[0].length)) == -1) | ||||
| 		int size; | ||||
| 		if ((size = read(_fileDescriptor, _buffers[0].start, _buffers[0].length)) == -1) | ||||
| 		{ | ||||
| 			switch (errno) | ||||
| 			{ | ||||
| 					switch (errno) | ||||
| 					{ | ||||
| 					case EAGAIN: | ||||
| 							return 0; | ||||
| 			case EAGAIN: | ||||
| 				return 0; | ||||
|  | ||||
| 					case EIO: | ||||
| 							/* Could ignore EIO, see spec. */ | ||||
| 			case EIO: | ||||
| 				/* Could ignore EIO, see spec. */ | ||||
|  | ||||
| 							/* fall through */ | ||||
| 				/* fall through */ | ||||
|  | ||||
| 					default: | ||||
| 							errno_exit("read"); | ||||
| 					} | ||||
| 			default: | ||||
| 				throw_errno_exception("read"); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 			rc = process_image(_buffers[0].start, size); | ||||
| 			break; | ||||
| 		rc = process_image(_buffers[0].start, size); | ||||
| 		break; | ||||
|  | ||||
| 	case IO_METHOD_MMAP: | ||||
| 			CLEAR(buf); | ||||
| 		CLEAR(buf); | ||||
|  | ||||
| 			buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||||
| 			buf.memory = V4L2_MEMORY_MMAP; | ||||
| 		buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||||
| 		buf.memory = V4L2_MEMORY_MMAP; | ||||
|  | ||||
| 			if (-1 == xioctl(VIDIOC_DQBUF, &buf)) | ||||
| 		if (-1 == xioctl(VIDIOC_DQBUF, &buf)) | ||||
| 		{ | ||||
| 			switch (errno) | ||||
| 			{ | ||||
| 					switch (errno) | ||||
| 					{ | ||||
| 					case EAGAIN: | ||||
| 							return 0; | ||||
| 			case EAGAIN: | ||||
| 				return 0; | ||||
|  | ||||
| 					case EIO: | ||||
| 							/* Could ignore EIO, see spec. */ | ||||
| 			case EIO: | ||||
| 				/* Could ignore EIO, see spec. */ | ||||
|  | ||||
| 							/* fall through */ | ||||
| 				/* fall through */ | ||||
|  | ||||
| 					default: | ||||
| 							errno_exit("VIDIOC_DQBUF"); | ||||
| 					} | ||||
| 			default: | ||||
| 				throw_errno_exception("VIDIOC_DQBUF"); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 			assert(buf.index < _buffers.size()); | ||||
| 		assert(buf.index < _buffers.size()); | ||||
|  | ||||
| 			rc = process_image(_buffers[buf.index].start, buf.bytesused); | ||||
| 		rc = process_image(_buffers[buf.index].start, buf.bytesused); | ||||
|  | ||||
| 			if (-1 == xioctl(VIDIOC_QBUF, &buf)) | ||||
| 			{ | ||||
| 					errno_exit("VIDIOC_QBUF"); | ||||
| 			} | ||||
| 		if (-1 == xioctl(VIDIOC_QBUF, &buf)) | ||||
| 		{ | ||||
| 			throw_errno_exception("VIDIOC_QBUF"); | ||||
| 		} | ||||
|  | ||||
| 			break; | ||||
| 		break; | ||||
|  | ||||
| 	case IO_METHOD_USERPTR: | ||||
| 			CLEAR(buf); | ||||
| 		CLEAR(buf); | ||||
|  | ||||
| 			buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||||
| 			buf.memory = V4L2_MEMORY_USERPTR; | ||||
| 		buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; | ||||
| 		buf.memory = V4L2_MEMORY_USERPTR; | ||||
|  | ||||
| 			if (-1 == xioctl(VIDIOC_DQBUF, &buf)) | ||||
| 		if (-1 == xioctl(VIDIOC_DQBUF, &buf)) | ||||
| 		{ | ||||
| 			switch (errno) | ||||
| 			{ | ||||
| 					switch (errno) | ||||
| 					{ | ||||
| 					case EAGAIN: | ||||
| 							return 0; | ||||
| 			case EAGAIN: | ||||
| 				return 0; | ||||
|  | ||||
| 					case EIO: | ||||
| 							/* Could ignore EIO, see spec. */ | ||||
| 			case EIO: | ||||
| 				/* Could ignore EIO, see spec. */ | ||||
|  | ||||
| 							/* fall through */ | ||||
| 				/* fall through */ | ||||
|  | ||||
| 					default: | ||||
| 							errno_exit("VIDIOC_DQBUF"); | ||||
| 					} | ||||
| 			default: | ||||
| 				throw_errno_exception("VIDIOC_DQBUF"); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 			for (size_t i = 0; i < _buffers.size(); ++i) | ||||
| 		for (size_t i = 0; i < _buffers.size(); ++i) | ||||
| 		{ | ||||
| 			if (buf.m.userptr == (unsigned long)_buffers[i].start && buf.length == _buffers[i].length) | ||||
| 			{ | ||||
| 					if (buf.m.userptr == (unsigned long)_buffers[i].start && buf.length == _buffers[i].length) | ||||
| 					{ | ||||
| 							break; | ||||
| 					} | ||||
| 				break; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 			rc = process_image((void *)buf.m.userptr, buf.bytesused); | ||||
| 		rc = process_image((void *)buf.m.userptr, buf.bytesused); | ||||
|  | ||||
| 			if (-1 == xioctl(VIDIOC_QBUF, &buf)) | ||||
| 			{ | ||||
| 					errno_exit("VIDIOC_QBUF"); | ||||
| 			} | ||||
| 			break; | ||||
| 		if (-1 == xioctl(VIDIOC_QBUF, &buf)) | ||||
| 		{ | ||||
| 			throw_errno_exception("VIDIOC_QBUF"); | ||||
| 		} | ||||
| 		break; | ||||
| 	} | ||||
|  | ||||
| 	return rc ? 1 : 0; | ||||
| @@ -665,8 +676,16 @@ int V4L2Grabber::xioctl(int request, void *arg) | ||||
| 	return r; | ||||
| } | ||||
|  | ||||
| void V4L2Grabber::errno_exit(const char *s) | ||||
| void V4L2Grabber::throw_exception(const std::string & error) | ||||
| { | ||||
| 	fprintf(stderr, "%s error %d, %s\n", s, errno, strerror(errno)); | ||||
| 	exit(EXIT_FAILURE); | ||||
| 	std::ostringstream oss; | ||||
| 	oss << error << " error"; | ||||
| 	throw std::runtime_error(oss.str()); | ||||
| } | ||||
|  | ||||
| void V4L2Grabber::throw_errno_exception(const std::string & error) | ||||
| { | ||||
| 	std::ostringstream oss; | ||||
| 	oss << error << " error " << errno << ", " << strerror(errno); | ||||
| 	throw std::runtime_error(oss.str()); | ||||
| } | ||||
|   | ||||
| @@ -59,7 +59,9 @@ private: | ||||
|  | ||||
| 	int xioctl(int request, void *arg); | ||||
|  | ||||
| 	void errno_exit(const char *s); | ||||
| 	void throw_exception(const std::string &error); | ||||
|  | ||||
| 	void throw_errno_exception(const std::string &error); | ||||
|  | ||||
| private: | ||||
| 	enum io_method { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user