static int v4l2_check_buffer_change_ok(int index) { v4l2_unmap_buffers(index); /* Check if the app itself still is using the stream */ if (v4l2_buffers_mapped(index) || (!(devices[index].flags & V4L2_STREAM_CONTROLLED_BY_READ) && ((devices[index].flags & V4L2_STREAMON) || devices[index].frame_queued))) { V4L2_LOG("v4l2_check_buffer_change_ok(): stream busy\n"); errno = EBUSY; return -1; } /* We may change from convert to non conversion mode and v4l2_unrequest_read_buffers may change the no_frames, so free the convert mmap buffer */ SYS_MUNMAP(devices[index].convert_mmap_buf, devices[index].no_frames * V4L2_FRAME_BUF_SIZE); devices[index].convert_mmap_buf = MAP_FAILED; if (devices[index].flags & V4L2_STREAM_CONTROLLED_BY_READ) { V4L2_LOG("deactivating read-stream for settings change\n"); return v4l2_deactivate_read_stream(index); } return 0; }
static void v4l2_unmap_buffers(int index) { unsigned int i; /* unmap the buffers */ for (i = 0; i < devices[index].no_frames; i++) { if (devices[index].frame_pointers[i] != MAP_FAILED) { SYS_MUNMAP(devices[index].frame_pointers[i], devices[index].frame_sizes[i]); devices[index].frame_pointers[i] = MAP_FAILED; V4L2_LOG("unmapped buffer %u\n", i); } } }
int v4l2_close(int fd) { int index, result; index = v4l2_get_index(fd); if (index == -1) return SYS_CLOSE(fd); /* Abuse stream_lock to stop 2 closes from racing and trying to free the resources twice */ pthread_mutex_lock(&devices[index].stream_lock); devices[index].open_count--; result = devices[index].open_count != 0; pthread_mutex_unlock(&devices[index].stream_lock); if (result) return 0; /* Free resources */ v4l2_unmap_buffers(index); if (devices[index].convert_mmap_buf != MAP_FAILED) { if (v4l2_buffers_mapped(index)) V4L2_LOG_WARN("v4l2 mmap buffers still mapped on close()\n"); else SYS_MUNMAP(devices[index].convert_mmap_buf, devices[index].no_frames * V4L2_FRAME_BUF_SIZE); devices[index].convert_mmap_buf = MAP_FAILED; } v4lconvert_destroy(devices[index].convert); free(devices[index].readbuf); devices[index].readbuf = NULL; devices[index].readbuf_size = 0; /* Remove the fd from our list of managed fds before closing it, because as soon as we've done the actual close the fd maybe returned by an open in another thread and we don't want to intercept calls to this new fd. */ devices[index].fd = -1; /* Since we've marked the fd as no longer used, and freed the resources, redo the close in case it was interrupted */ do { result = SYS_CLOSE(fd); } while (result == -1 && errno == EINTR); V4L2_LOG("close: %d\n", fd); return result; }
int v4l1_close(int fd) { int index, result; index = v4l1_get_index(fd); if (index == -1) return SYS_CLOSE(fd); /* Abuse stream_lock to stop 2 closes from racing and trying to free the resources twice */ pthread_mutex_lock(&devices[index].stream_lock); devices[index].open_count--; result = devices[index].open_count != 0; pthread_mutex_unlock(&devices[index].stream_lock); if (result) return v4l2_close(fd); /* Free resources */ if (devices[index].v4l1_frame_pointer != MAP_FAILED) { if (devices[index].v4l1_frame_buf_map_count) V4L1_LOG("v4l1 capture buffer still mapped: %d times on close()\n", devices[index].v4l1_frame_buf_map_count); else SYS_MUNMAP(devices[index].v4l1_frame_pointer, V4L1_NO_FRAMES * V4L1_FRAME_BUF_SIZE); devices[index].v4l1_frame_pointer = MAP_FAILED; } /* Remove the fd from our list of managed fds before closing it, because as soon as we've done the actual close the fd maybe returned by an open in another thread and we don't want to intercept calls to this new fd. */ devices[index].fd = -1; result = v4l2_close(fd); V4L1_LOG("close: %d\n", fd); return result; }