/* * Copyright (C) 2011 Texas Instruments * Author: Rob Clark * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 as published by * the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for * more details. * * You should have received a copy of the GNU General Public License along with * this program. If not, see . */ #include #include "util.h" #define NBUF 6 #define CNT 500000 enum display_area { FULL, OVERLAY }; struct thr_data { struct display *disp; struct v4l2 *v4l2; uint32_t fourcc, width, height; enum display_area area; }; static void usage(char *name) { MSG("Usage: %s [OPTION]...", name); MSG("Test of buffer passing between v4l2 camera and display."); MSG(""); disp_usage(); v4l2_usage(); } void * capture_loop(void *arg) { struct thr_data *data = (struct thr_data *)arg; struct display *disp = data->disp; struct v4l2 *v4l2 = data->v4l2; uint32_t fourcc = data->fourcc; uint32_t width = data->width, height = data->height; struct buffer **buffers, *capt; int ret, i; buffers = disp_get_vid_buffers(disp, NBUF, fourcc, width, height); if (!buffers) { return NULL; } ret = v4l2_reqbufs(v4l2, buffers, NBUF); if (ret) { return NULL; } if(data->area == OVERLAY) { for (i = 0; i < NBUF; i++) { buffers[i]->noScale = true; get_overlay_plane(disp, buffers[i]); } } for (i = 0; i < NBUF; i++) { v4l2_qbuf(v4l2, buffers[i]); } v4l2_streamon(v4l2); for (i = 1; i < CNT; i++) { capt = v4l2_dqbuf(v4l2); switch(data->area) { case FULL: ret = disp_post_vid_buffer(disp, capt, 0, 0, width, height); break; case OVERLAY: ret = disp_post_vid_buffer(disp, capt, 0, 0, width, height); break; } if (ret) { return NULL; } v4l2_qbuf(v4l2, capt); } v4l2_streamoff(v4l2); MSG("Ok!"); return disp; } int main(int argc, char **argv) { struct display *disp; struct v4l2 *v4l2; pthread_t threads[2]; struct thr_data tdata[2]; void *result = NULL; int ret = 0, i, dual = 0; MSG("Opening Display.."); disp = disp_open(argc, argv); if (!disp) { usage(argv[0]); return 1; } for (i = 1; i < argc; i++) { if (!argv[i]) continue; if (!strcmp("--dual", argv[i])) { dual = 1; argv[i] = NULL; } } MSG("Opening V4L2.."); v4l2 = v4l2_open(argc, argv, &tdata[0].fourcc, &tdata[0].width, &tdata[0].height); if (!v4l2) { usage(argv[0]); return 1; } tdata[0].disp = disp; tdata[0].v4l2 = v4l2; tdata[0].area = FULL; if(dual) { MSG("Opening second V4L2.."); v4l2 = v4l2_open(argc, argv, &tdata[1].fourcc, &tdata[1].width, &tdata[1].height); if (!v4l2) { usage(argv[0]); return 1; } tdata[1].disp = disp; tdata[1].v4l2 = v4l2; tdata[1].area = OVERLAY; } if (check_args(argc, argv)) { /* remaining args.. print usage msg */ usage(argv[0]); return 0; } if(dual) { ret = pthread_create(&threads[0], NULL, capture_loop, &tdata[0]); if(ret) { MSG("Failed creating thread"); } ret = pthread_create(&threads[1], NULL, capture_loop, &tdata[1]); if(ret) { MSG("Failed creating thread"); } } else { capture_loop(&tdata[0]); } pthread_join(threads[0], &result); pthread_join(threads[1], &result); disp_close(disp); return ret; }