Implemented camera switching

This commit is contained in:
Martijn Braam 2020-09-04 17:45:57 +02:00
parent e41b090090
commit dae8aafacf
2 changed files with 75 additions and 60 deletions

131
main.c
View File

@ -55,14 +55,17 @@ static char *media_drv_name;
static int *interface_entity_id; static int *interface_entity_id;
static char *dev_name[20]; static char *dev_name[20];
static int media_fd; static int media_fd;
static int video_fd;
// State // State
static int ready = 0;
static int current_width = -1; static int current_width = -1;
static int current_height = -1; static int current_height = -1;
static int current_fmt = 0; static int current_fmt = 0;
static int current_rotate = 0; static int current_rotate = 0;
static int current_fd; static int current_fd;
static int capture = 0; static int capture = 0;
static int current_is_rear = 1;
static cairo_surface_t *surface = NULL; static cairo_surface_t *surface = NULL;
static int preview_width = -1; static int preview_width = -1;
static int preview_height = -1; static int preview_height = -1;
@ -91,49 +94,43 @@ static void
start_capturing(int fd) start_capturing(int fd)
{ {
enum v4l2_buf_type type; enum v4l2_buf_type type;
switch (io) {
case IO_METHOD_READ:
/* Nothing to do. */
break;
case IO_METHOD_MMAP:
for (int i = 0; i < n_buffers; ++i) {
struct v4l2_buffer buf = {
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
.memory = V4L2_MEMORY_MMAP,
.index = i,
};
if (xioctl(fd, VIDIOC_QBUF, &buf) == -1) { for (int i = 0; i < n_buffers; ++i) {
errno_exit("VIDIOC_QBUF"); struct v4l2_buffer buf = {
} .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
} .memory = V4L2_MEMORY_MMAP,
.index = i,
};
type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (xioctl(fd, VIDIOC_QBUF, &buf) == -1) {
if (xioctl(fd, VIDIOC_STREAMON, &type) == -1) { errno_exit("VIDIOC_QBUF");
errno_exit("VIDIOC_STREAMON"); }
}
break;
case IO_METHOD_USERPTR:
for (int i = 0; i < n_buffers; ++i) {
struct v4l2_buffer buf = {
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
.memory = V4L2_MEMORY_USERPTR,
.index = i,
};
buf.m.userptr = (unsigned long) buffers[i].start;
buf.length = buffers[i].length;
if (xioctl(fd, VIDIOC_QBUF, &buf) == -1) {
errno_exit("VIDIOC_QBUF");
}
}
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (xioctl(fd, VIDIOC_STREAMON, &type) == -1) {
errno_exit("VIDIOC_STREAMON");
}
break;
} }
type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if (xioctl(fd, VIDIOC_STREAMON, &type) == -1) {
errno_exit("VIDIOC_STREAMON");
}
ready = 1;
}
static void
stop_capturing(int fd)
{
int i;
ready = 0;
printf("Stopping capture\n");
enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
if(xioctl(fd, VIDIOC_STREAMOFF, &type) == -1) {
errno_exit("VIDIOC_STREAMOFF");
}
for(i=0;i<n_buffers;++i){
munmap(buffers[i].start, buffers[i].length);
}
} }
static void static void
@ -199,7 +196,7 @@ v4l2_ctrl_set(int fd, uint32_t id, int val)
ctrl.value = val; ctrl.value = val;
if(xioctl(fd, VIDIOC_S_CTRL, &ctrl) == -1){ if(xioctl(fd, VIDIOC_S_CTRL, &ctrl) == -1){
g_printerr("Failed to set control %d to %d", id, val); g_printerr("Failed to set control %d to %d\n", id, val);
return -1; return -1;
} }
return 0; return 0;
@ -229,7 +226,8 @@ init_sensor(char* fn, int width, int height, int mbus)
fmt.format.width, fmt.format.height, fmt.format.width, fmt.format.height,
fmt.format.code); fmt.format.code);
v4l2_ctrl_set(fd, V4L2_CID_AUTOGAIN, 0); // Placeholder, default is also 1
//v4l2_ctrl_set(fd, V4L2_CID_AUTOGAIN, 1);
close(current_fd); close(current_fd);
current_fd = fd; current_fd = fd;
} }
@ -342,19 +340,7 @@ init_device(int fd)
fmt.fmt.pix.sizeimage = min; fmt.fmt.pix.sizeimage = min;
} }
switch (io) { init_mmap(fd);
case IO_METHOD_READ:
//init_read(fmt.fmt.pix.sizeimage);
break;
case IO_METHOD_MMAP:
init_mmap(fd);
break;
case IO_METHOD_USERPTR:
//init_userp(fmt.fmt.pix.sizeimage);
break;
}
} }
static void static void
@ -412,8 +398,8 @@ process_image(const int *p, int size)
cr = cairo_create(surface); cr = cairo_create(surface);
cairo_set_source_rgb(cr, 0,0,0); cairo_set_source_rgb(cr, 0,0,0);
cairo_paint(cr); cairo_paint(cr);
gdk_cairo_set_source_pixbuf(cr, pixbufrot, 0, 0);
cairo_scale(cr, scale, scale); cairo_scale(cr, scale, scale);
gdk_cairo_set_source_pixbuf(cr, pixbufrot, 0, 0);
cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_NONE); cairo_pattern_set_extend(cairo_get_source(cr), CAIRO_EXTEND_NONE);
cairo_paint(cr); cairo_paint(cr);
gtk_widget_queue_draw_area(preview, 0, 0, preview_width, preview_height); gtk_widget_queue_draw_area(preview, 0, 0, preview_width, preview_height);
@ -538,6 +524,8 @@ read_frame(int fd)
static gboolean static gboolean
get_frame(int fd) get_frame(int fd)
{ {
if (ready == 0)
return TRUE;
while (1) { while (1) {
fd_set fds; fd_set fds;
struct timeval tv; struct timeval tv;
@ -751,7 +739,7 @@ setup_front()
link.sink.index = 0; link.sink.index = 0;
if(xioctl(media_fd, MEDIA_IOC_SETUP_LINK, &link) < 0){ if(xioctl(media_fd, MEDIA_IOC_SETUP_LINK, &link) < 0){
g_printerr("Could not disable front camera link\n"); g_printerr("Could not disable rear camera link\n");
return -1; return -1;
} }
@ -763,7 +751,7 @@ setup_front()
link.sink.index = 0; link.sink.index = 0;
if(xioctl(media_fd, MEDIA_IOC_SETUP_LINK, &link) < 0){ if(xioctl(media_fd, MEDIA_IOC_SETUP_LINK, &link) < 0){
g_printerr("Could not enable rear camera link\n"); g_printerr("Could not enable front camera link\n");
return -1; return -1;
} }
current_width = front_width; current_width = front_width;
@ -846,6 +834,29 @@ on_shutter_clicked(GtkWidget *widget, gpointer user_data)
capture = 1; capture = 1;
} }
void
on_camera_switch_clicked(GtkWidget *widget, gpointer user_data)
{
stop_capturing(video_fd);
close(current_fd);
if(current_is_rear == 1){
setup_front();
current_is_rear = 0;
}else{
setup_rear();
current_is_rear = 1;
}
printf("close() = %d\n", close(video_fd));
printf("Opening %s again\n", dev_name);
video_fd = open(dev_name, O_RDWR);
if (video_fd == -1) {
g_printerr("Error opening video device: %s\n", dev_name);
return 1;
}
init_device(video_fd);
start_capturing(video_fd);
}
int int
main(int argc, char *argv[]) main(int argc, char *argv[])
{ {
@ -871,10 +882,12 @@ main(int argc, char *argv[])
GObject *window = gtk_builder_get_object(builder, "window"); GObject *window = gtk_builder_get_object(builder, "window");
GObject *preview_box = gtk_builder_get_object(builder, "preview_box"); GObject *preview_box = gtk_builder_get_object(builder, "preview_box");
GObject *shutter = gtk_builder_get_object(builder, "shutter"); GObject *shutter = gtk_builder_get_object(builder, "shutter");
GObject *switch_btn = gtk_builder_get_object(builder, "switch_camera");
GObject *settings_btn = gtk_builder_get_object(builder, "settings"); GObject *settings_btn = gtk_builder_get_object(builder, "settings");
preview = gtk_builder_get_object(builder, "preview"); preview = gtk_builder_get_object(builder, "preview");
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL); g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(shutter, "clicked", G_CALLBACK(on_shutter_clicked), NULL); g_signal_connect(shutter, "clicked", G_CALLBACK(on_shutter_clicked), NULL);
g_signal_connect(switch_btn, "clicked", G_CALLBACK(on_camera_switch_clicked), NULL);
g_signal_connect(preview, "draw", G_CALLBACK(preview_draw), NULL); g_signal_connect(preview, "draw", G_CALLBACK(preview_draw), NULL);
g_signal_connect(preview, "configure-event", G_CALLBACK(preview_configure), NULL); g_signal_connect(preview, "configure-event", G_CALLBACK(preview_configure), NULL);
@ -917,6 +930,8 @@ main(int argc, char *argv[])
return 1; return 1;
} }
video_fd = fd;
init_device(fd); init_device(fd);
start_capturing(fd); start_capturing(fd);

View File

@ -10,7 +10,7 @@ rotate=270
[front] [front]
driver=gc2145 driver=gc2145
width=1280 width=800
height=720 height=600
fmt=BGGR8 fmt=BGGR8
rotate=90 rotate=90