From d9fcd7e5495fbd0fe020223823338d21ce31dcaf Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 13 Feb 2009 12:56:07 +0100 Subject: libv4l2util: rename from libv4l2 to prevent clash with the libv4l2 conversion library From: Hans Verkuil libv4l2 was introduced to fix conversion problems. But this clashed with the already existing libv4l2 utility library. Renamed that libv4l2 library and header to libv4l2util. Priority: normal Signed-off-by: Hans Verkuil --- v4l2-apps/lib/Makefile | 6 ++--- v4l2-apps/lib/frequencies.c | 2 +- v4l2-apps/lib/libv4l2util.h | 45 ++++++++++++++++++++++++++++++++++++ v4l2-apps/lib/v4l2.h | 45 ------------------------------------ v4l2-apps/test/Makefile | 6 ++--- v4l2-apps/util/Makefile | 6 ++--- v4l2-apps/util/qv4l2/ctrl-tab.cpp | 2 +- v4l2-apps/util/qv4l2/general-tab.cpp | 2 +- v4l2-apps/util/qv4l2/qv4l2.cpp | 2 +- v4l2-apps/util/qv4l2/qv4l2.pro | 2 +- 10 files changed, 59 insertions(+), 59 deletions(-) create mode 100644 v4l2-apps/lib/libv4l2util.h delete mode 100644 v4l2-apps/lib/v4l2.h (limited to 'v4l2-apps') diff --git a/v4l2-apps/lib/Makefile b/v4l2-apps/lib/Makefile index 8443039b4..f3f413071 100644 --- a/v4l2-apps/lib/Makefile +++ b/v4l2-apps/lib/Makefile @@ -2,12 +2,12 @@ CPPFLAGS += -I../include -I.. -includes = v4l2.h +includes = libv4l2util.h objects = frequencies.o v4l2_driver.o -sharedlib = libv4l2.so -staticlib = libv4l2.a +sharedlib = libv4l2util.so +staticlib = libv4l2util.a ifeq ($(prefix),) prefix = /usr diff --git a/v4l2-apps/lib/frequencies.c b/v4l2-apps/lib/frequencies.c index 64379d2b0..df8d47dba 100644 --- a/v4l2-apps/lib/frequencies.c +++ b/v4l2-apps/lib/frequencies.c @@ -22,7 +22,7 @@ #include #include -#include "v4l2.h" +#include "libv4l2util.h" /* This source was originally written by Nathan Laredo . He kindly gave permission to release this source under the LGPL diff --git a/v4l2-apps/lib/libv4l2util.h b/v4l2-apps/lib/libv4l2util.h new file mode 100644 index 000000000..fde7cdc75 --- /dev/null +++ b/v4l2-apps/lib/libv4l2util.h @@ -0,0 +1,45 @@ +/* Copyright (C) 2006 Hans Verkuil + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _V4L2UTIL_H_ +#define _V4L2UTIL_H_ + +/* --------------------------------------------------------------------- */ + +struct v4l2_channel_list { + const char * const name; /* channel name */ + unsigned freq; /* channel frequency in kHz */ +}; + +struct v4l2_channel_lists { + const char * const name; /* channel list name */ + const struct v4l2_channel_list * const list; + unsigned count; /* number of channels in channel list */ +}; + +extern const struct v4l2_channel_lists v4l2_channel_lists[]; + +/* This list is sorted alphabetically on ISO code. The last item is + denoted by a NULL pointer for the iso_code. */ +struct v4l2_country_std_map { + const char * const iso_code; /* The 2-character upper case ISO-3166 country code */ + v4l2_std_id std; /* The TV standard(s) in use */ +}; + +extern const struct v4l2_country_std_map v4l2_country_std_map[]; + +#endif diff --git a/v4l2-apps/lib/v4l2.h b/v4l2-apps/lib/v4l2.h deleted file mode 100644 index 172688853..000000000 --- a/v4l2-apps/lib/v4l2.h +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright (C) 2006 Hans Verkuil - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#ifndef _V4L2_H_ -#define _V4L2_H_ - -/* --------------------------------------------------------------------- */ - -struct v4l2_channel_list { - const char * const name; /* channel name */ - unsigned freq; /* channel frequency in kHz */ -}; - -struct v4l2_channel_lists { - const char * const name; /* channel list name */ - const struct v4l2_channel_list * const list; - unsigned count; /* number of channels in channel list */ -}; - -extern const struct v4l2_channel_lists v4l2_channel_lists[]; - -/* This list is sorted alphabetically on ISO code. The last item is - denoted by a NULL pointer for the iso_code. */ -struct v4l2_country_std_map { - const char * const iso_code; /* The 2-character upper case ISO-3166 country code */ - v4l2_std_id std; /* The TV standard(s) in use */ -}; - -extern const struct v4l2_country_std_map v4l2_country_std_map[]; - -#endif diff --git a/v4l2-apps/test/Makefile b/v4l2-apps/test/Makefile index a996c0baf..e3879bc5e 100644 --- a/v4l2-apps/test/Makefile +++ b/v4l2-apps/test/Makefile @@ -21,10 +21,10 @@ clean:: install: -../lib/libv4l2.a: ../lib/v4l2_driver.c ../lib/frequencies.c - make -C ../lib libv4l2.a +../lib/libv4l2util.a: ../lib/v4l2_driver.c ../lib/frequencies.c + make -C ../lib libv4l2util.a -driver-test: driver-test.o ../lib/libv4l2.a +driver-test: driver-test.o ../lib/libv4l2util.a pixfmt-test: pixfmt-test.o $(CC) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@ -lX11 diff --git a/v4l2-apps/util/Makefile b/v4l2-apps/util/Makefile index f2c4c0a38..80bffc50d 100644 --- a/v4l2-apps/util/Makefile +++ b/v4l2-apps/util/Makefile @@ -36,11 +36,11 @@ v4l2-dbg.o: v4l2-dbg.h v4l2-dbg-bttv.h v4l2-dbg-em28xx.h v4l2-dbg-saa7134.h v4l2_sysfs_path.o: v4l2_sysfs_path.c ../lib/v4l2_driver.h -v4l2_sysfs_path: v4l2_sysfs_path.o ../lib/libv4l2.a +v4l2_sysfs_path: v4l2_sysfs_path.o ../lib/libv4l2util.a $(CC) $^ -o $@ -lsysfs -../lib/libv4l2.a: - $(MAKE) -C ../lib libv4l2.a +../lib/libv4l2util.a: + $(MAKE) -C ../lib libv4l2util.a install: mkdir -p $(prefix)/bin diff --git a/v4l2-apps/util/qv4l2/ctrl-tab.cpp b/v4l2-apps/util/qv4l2/ctrl-tab.cpp index c7d1a275c..6f436b494 100644 --- a/v4l2-apps/util/qv4l2/ctrl-tab.cpp +++ b/v4l2-apps/util/qv4l2/ctrl-tab.cpp @@ -1,6 +1,6 @@ #include "qv4l2.h" -#include "v4l2.h" +#include "libv4l2util.h" #include #include diff --git a/v4l2-apps/util/qv4l2/general-tab.cpp b/v4l2-apps/util/qv4l2/general-tab.cpp index 3b9ad2e5b..78656cf10 100644 --- a/v4l2-apps/util/qv4l2/general-tab.cpp +++ b/v4l2-apps/util/qv4l2/general-tab.cpp @@ -20,7 +20,7 @@ #include "qv4l2.h" #include "general-tab.h" -#include "v4l2.h" +#include "libv4l2util.h" #include #include diff --git a/v4l2-apps/util/qv4l2/qv4l2.cpp b/v4l2-apps/util/qv4l2/qv4l2.cpp index d144723d9..764fbd172 100644 --- a/v4l2-apps/util/qv4l2/qv4l2.cpp +++ b/v4l2-apps/util/qv4l2/qv4l2.cpp @@ -1,7 +1,7 @@ #include "qv4l2.h" #include "general-tab.h" -#include "v4l2.h" +#include "libv4l2util.h" #include #include diff --git a/v4l2-apps/util/qv4l2/qv4l2.pro b/v4l2-apps/util/qv4l2/qv4l2.pro index 5e0b7555d..770c2d702 100644 --- a/v4l2-apps/util/qv4l2/qv4l2.pro +++ b/v4l2-apps/util/qv4l2/qv4l2.pro @@ -9,4 +9,4 @@ CONFIG += debug # Input HEADERS += qv4l2.h general-tab.h SOURCES += qv4l2.cpp general-tab.cpp ctrl-tab.cpp -LIBS += -lv4l2 -L../../lib +LIBS += -lv4l2util -L../../lib -- cgit v1.2.3 From 4e061e403e8a5ab5f041a54a6852c69e6b00b368 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 13 Feb 2009 13:06:29 +0100 Subject: v4l2-apps: move libraries around to make the directory tree flatter From: Hans Verkuil Instead of having libv4l2util in v4l2-apps/lib and libv4l in v4l2-apps/lib/libv4l, both are now moved to v4l2-apps/libv4l2util and v4l2-apps/libv4l. This is much cleaner and less confusing. Priority: normal Signed-off-by: Hans Verkuil --- v4l2-apps/Makefile | 3 +- v4l2-apps/lib/COPYING.LIB | 510 ---- v4l2-apps/lib/Makefile | 33 - v4l2-apps/lib/TODO | 81 - v4l2-apps/lib/frequencies.c | 1502 ------------ v4l2-apps/lib/libv4l/COPYING.LIB | 510 ---- v4l2-apps/lib/libv4l/ChangeLog | 247 -- v4l2-apps/lib/libv4l/Makefile | 16 - v4l2-apps/lib/libv4l/README | 141 -- v4l2-apps/lib/libv4l/README.multi-threading | 12 - v4l2-apps/lib/libv4l/TODO | 12 - v4l2-apps/lib/libv4l/include/libv4l1.h | 73 - v4l2-apps/lib/libv4l/include/libv4l2.h | 110 - v4l2-apps/lib/libv4l/include/libv4lconvert.h | 88 - v4l2-apps/lib/libv4l/libv4l1/Makefile | 83 - v4l2-apps/lib/libv4l/libv4l1/libv4l1-priv.h | 83 - v4l2-apps/lib/libv4l/libv4l1/libv4l1.c | 837 ------- v4l2-apps/lib/libv4l/libv4l1/log.c | 145 -- v4l2-apps/lib/libv4l/libv4l1/v4l1compat.c | 127 - v4l2-apps/lib/libv4l/libv4l2/Makefile | 82 - v4l2-apps/lib/libv4l/libv4l2/libv4l2-priv.h | 95 - v4l2-apps/lib/libv4l/libv4l2/libv4l2.c | 1145 --------- v4l2-apps/lib/libv4l/libv4l2/log.c | 148 -- v4l2-apps/lib/libv4l/libv4l2/v4l2convert.c | 166 -- v4l2-apps/lib/libv4l/libv4lconvert/Makefile | 70 - v4l2-apps/lib/libv4l/libv4lconvert/bayer.c | 613 ----- v4l2-apps/lib/libv4l/libv4lconvert/flip.c | 107 - v4l2-apps/lib/libv4l/libv4lconvert/jidctflt.c | 286 --- .../lib/libv4l/libv4lconvert/libv4lconvert-priv.h | 166 -- v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c | 737 ------ v4l2-apps/lib/libv4l/libv4lconvert/pac207.c | 418 ---- v4l2-apps/lib/libv4l/libv4lconvert/rgbyuv.c | 316 --- v4l2-apps/lib/libv4l/libv4lconvert/sn9c10x.c | 287 --- v4l2-apps/lib/libv4l/libv4lconvert/spca501.c | 126 - .../lib/libv4l/libv4lconvert/spca561-decompress.c | 1003 -------- .../lib/libv4l/libv4lconvert/tinyjpeg-internal.h | 121 - v4l2-apps/lib/libv4l/libv4lconvert/tinyjpeg.c | 2463 -------------------- v4l2-apps/lib/libv4l/libv4lconvert/tinyjpeg.h | 74 - v4l2-apps/lib/libv4l2util.h | 45 - v4l2-apps/lib/v4l2_driver.c | 804 ------- v4l2-apps/lib/v4l2_driver.h | 81 - v4l2-apps/libv4l/COPYING.LIB | 510 ++++ v4l2-apps/libv4l/ChangeLog | 247 ++ v4l2-apps/libv4l/Makefile | 16 + v4l2-apps/libv4l/README | 141 ++ v4l2-apps/libv4l/README.multi-threading | 12 + v4l2-apps/libv4l/TODO | 12 + v4l2-apps/libv4l/include/libv4l1.h | 73 + v4l2-apps/libv4l/include/libv4l2.h | 110 + v4l2-apps/libv4l/include/libv4lconvert.h | 88 + v4l2-apps/libv4l/libv4l1/Makefile | 83 + v4l2-apps/libv4l/libv4l1/libv4l1-priv.h | 83 + v4l2-apps/libv4l/libv4l1/libv4l1.c | 837 +++++++ v4l2-apps/libv4l/libv4l1/log.c | 145 ++ v4l2-apps/libv4l/libv4l1/v4l1compat.c | 127 + v4l2-apps/libv4l/libv4l2/Makefile | 82 + v4l2-apps/libv4l/libv4l2/libv4l2-priv.h | 95 + v4l2-apps/libv4l/libv4l2/libv4l2.c | 1145 +++++++++ v4l2-apps/libv4l/libv4l2/log.c | 148 ++ v4l2-apps/libv4l/libv4l2/v4l2convert.c | 166 ++ v4l2-apps/libv4l/libv4lconvert/Makefile | 70 + v4l2-apps/libv4l/libv4lconvert/bayer.c | 613 +++++ v4l2-apps/libv4l/libv4lconvert/flip.c | 107 + v4l2-apps/libv4l/libv4lconvert/jidctflt.c | 286 +++ .../libv4l/libv4lconvert/libv4lconvert-priv.h | 166 ++ v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c | 737 ++++++ v4l2-apps/libv4l/libv4lconvert/pac207.c | 418 ++++ v4l2-apps/libv4l/libv4lconvert/rgbyuv.c | 316 +++ v4l2-apps/libv4l/libv4lconvert/sn9c10x.c | 287 +++ v4l2-apps/libv4l/libv4lconvert/spca501.c | 126 + .../libv4l/libv4lconvert/spca561-decompress.c | 1003 ++++++++ v4l2-apps/libv4l/libv4lconvert/tinyjpeg-internal.h | 121 + v4l2-apps/libv4l/libv4lconvert/tinyjpeg.c | 2463 ++++++++++++++++++++ v4l2-apps/libv4l/libv4lconvert/tinyjpeg.h | 74 + v4l2-apps/libv4l2util/COPYING.LIB | 510 ++++ v4l2-apps/libv4l2util/Makefile | 33 + v4l2-apps/libv4l2util/TODO | 81 + v4l2-apps/libv4l2util/frequencies.c | 1502 ++++++++++++ v4l2-apps/libv4l2util/libv4l2util.h | 45 + v4l2-apps/libv4l2util/v4l2_driver.c | 804 +++++++ v4l2-apps/libv4l2util/v4l2_driver.h | 81 + v4l2-apps/test/Makefile | 6 +- v4l2-apps/test/driver-test.c | 2 +- v4l2-apps/util/Makefile | 8 +- v4l2-apps/util/qv4l2/qv4l2.pro | 4 +- v4l2-apps/util/v4l2_sysfs_path.c | 2 +- 86 files changed, 13976 insertions(+), 13975 deletions(-) delete mode 100644 v4l2-apps/lib/COPYING.LIB delete mode 100644 v4l2-apps/lib/Makefile delete mode 100644 v4l2-apps/lib/TODO delete mode 100644 v4l2-apps/lib/frequencies.c delete mode 100644 v4l2-apps/lib/libv4l/COPYING.LIB delete mode 100644 v4l2-apps/lib/libv4l/ChangeLog delete mode 100644 v4l2-apps/lib/libv4l/Makefile delete mode 100644 v4l2-apps/lib/libv4l/README delete mode 100644 v4l2-apps/lib/libv4l/README.multi-threading delete mode 100644 v4l2-apps/lib/libv4l/TODO delete mode 100644 v4l2-apps/lib/libv4l/include/libv4l1.h delete mode 100644 v4l2-apps/lib/libv4l/include/libv4l2.h delete mode 100644 v4l2-apps/lib/libv4l/include/libv4lconvert.h delete mode 100644 v4l2-apps/lib/libv4l/libv4l1/Makefile delete mode 100644 v4l2-apps/lib/libv4l/libv4l1/libv4l1-priv.h delete mode 100644 v4l2-apps/lib/libv4l/libv4l1/libv4l1.c delete mode 100644 v4l2-apps/lib/libv4l/libv4l1/log.c delete mode 100644 v4l2-apps/lib/libv4l/libv4l1/v4l1compat.c delete mode 100644 v4l2-apps/lib/libv4l/libv4l2/Makefile delete mode 100644 v4l2-apps/lib/libv4l/libv4l2/libv4l2-priv.h delete mode 100644 v4l2-apps/lib/libv4l/libv4l2/libv4l2.c delete mode 100644 v4l2-apps/lib/libv4l/libv4l2/log.c delete mode 100644 v4l2-apps/lib/libv4l/libv4l2/v4l2convert.c delete mode 100644 v4l2-apps/lib/libv4l/libv4lconvert/Makefile delete mode 100644 v4l2-apps/lib/libv4l/libv4lconvert/bayer.c delete mode 100644 v4l2-apps/lib/libv4l/libv4lconvert/flip.c delete mode 100644 v4l2-apps/lib/libv4l/libv4lconvert/jidctflt.c delete mode 100644 v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h delete mode 100644 v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c delete mode 100644 v4l2-apps/lib/libv4l/libv4lconvert/pac207.c delete mode 100644 v4l2-apps/lib/libv4l/libv4lconvert/rgbyuv.c delete mode 100644 v4l2-apps/lib/libv4l/libv4lconvert/sn9c10x.c delete mode 100644 v4l2-apps/lib/libv4l/libv4lconvert/spca501.c delete mode 100644 v4l2-apps/lib/libv4l/libv4lconvert/spca561-decompress.c delete mode 100644 v4l2-apps/lib/libv4l/libv4lconvert/tinyjpeg-internal.h delete mode 100644 v4l2-apps/lib/libv4l/libv4lconvert/tinyjpeg.c delete mode 100644 v4l2-apps/lib/libv4l/libv4lconvert/tinyjpeg.h delete mode 100644 v4l2-apps/lib/libv4l2util.h delete mode 100644 v4l2-apps/lib/v4l2_driver.c delete mode 100644 v4l2-apps/lib/v4l2_driver.h create mode 100644 v4l2-apps/libv4l/COPYING.LIB create mode 100644 v4l2-apps/libv4l/ChangeLog create mode 100644 v4l2-apps/libv4l/Makefile create mode 100644 v4l2-apps/libv4l/README create mode 100644 v4l2-apps/libv4l/README.multi-threading create mode 100644 v4l2-apps/libv4l/TODO create mode 100644 v4l2-apps/libv4l/include/libv4l1.h create mode 100644 v4l2-apps/libv4l/include/libv4l2.h create mode 100644 v4l2-apps/libv4l/include/libv4lconvert.h create mode 100644 v4l2-apps/libv4l/libv4l1/Makefile create mode 100644 v4l2-apps/libv4l/libv4l1/libv4l1-priv.h create mode 100644 v4l2-apps/libv4l/libv4l1/libv4l1.c create mode 100644 v4l2-apps/libv4l/libv4l1/log.c create mode 100644 v4l2-apps/libv4l/libv4l1/v4l1compat.c create mode 100644 v4l2-apps/libv4l/libv4l2/Makefile create mode 100644 v4l2-apps/libv4l/libv4l2/libv4l2-priv.h create mode 100644 v4l2-apps/libv4l/libv4l2/libv4l2.c create mode 100644 v4l2-apps/libv4l/libv4l2/log.c create mode 100644 v4l2-apps/libv4l/libv4l2/v4l2convert.c create mode 100644 v4l2-apps/libv4l/libv4lconvert/Makefile create mode 100644 v4l2-apps/libv4l/libv4lconvert/bayer.c create mode 100644 v4l2-apps/libv4l/libv4lconvert/flip.c create mode 100644 v4l2-apps/libv4l/libv4lconvert/jidctflt.c create mode 100644 v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h create mode 100644 v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c create mode 100644 v4l2-apps/libv4l/libv4lconvert/pac207.c create mode 100644 v4l2-apps/libv4l/libv4lconvert/rgbyuv.c create mode 100644 v4l2-apps/libv4l/libv4lconvert/sn9c10x.c create mode 100644 v4l2-apps/libv4l/libv4lconvert/spca501.c create mode 100644 v4l2-apps/libv4l/libv4lconvert/spca561-decompress.c create mode 100644 v4l2-apps/libv4l/libv4lconvert/tinyjpeg-internal.h create mode 100644 v4l2-apps/libv4l/libv4lconvert/tinyjpeg.c create mode 100644 v4l2-apps/libv4l/libv4lconvert/tinyjpeg.h create mode 100644 v4l2-apps/libv4l2util/COPYING.LIB create mode 100644 v4l2-apps/libv4l2util/Makefile create mode 100644 v4l2-apps/libv4l2util/TODO create mode 100644 v4l2-apps/libv4l2util/frequencies.c create mode 100644 v4l2-apps/libv4l2util/libv4l2util.h create mode 100644 v4l2-apps/libv4l2util/v4l2_driver.c create mode 100644 v4l2-apps/libv4l2util/v4l2_driver.h (limited to 'v4l2-apps') diff --git a/v4l2-apps/Makefile b/v4l2-apps/Makefile index 2bba8fcd4..86b5bc267 100644 --- a/v4l2-apps/Makefile +++ b/v4l2-apps/Makefile @@ -5,7 +5,8 @@ all:: prepare-includes all clean install:: - $(MAKE) -C lib $@ + $(MAKE) -C libv4l $@ + $(MAKE) -C libv4l2util $@ $(MAKE) -C util $@ $(MAKE) -C test $@ diff --git a/v4l2-apps/lib/COPYING.LIB b/v4l2-apps/lib/COPYING.LIB deleted file mode 100644 index 1dd325d2b..000000000 --- a/v4l2-apps/lib/COPYING.LIB +++ /dev/null @@ -1,510 +0,0 @@ - - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations -below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. -^L - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it -becomes a de-facto standard. To achieve this, non-free programs must -be allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. -^L - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control -compilation and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. -^L - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. -^L - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at least - three years, to give the same user the materials specified in - Subsection 6a, above, for a charge no more than the cost of - performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. -^L - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. -^L - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply, and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License -may add an explicit geographical distribution limitation excluding those -countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. -^L - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS -^L - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms -of the ordinary General Public License). - - To apply these terms, attach the following notices to the library. -It is safest to attach them to the start of each source file to most -effectively convey the exclusion of warranty; and each file should -have at least the "copyright" line and a pointer to where the full -notice is found. - - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or -your school, if any, to sign a "copyright disclaimer" for the library, -if necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James - Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - diff --git a/v4l2-apps/lib/Makefile b/v4l2-apps/lib/Makefile deleted file mode 100644 index f3f413071..000000000 --- a/v4l2-apps/lib/Makefile +++ /dev/null @@ -1,33 +0,0 @@ -# Makefile for linuxtv.org v4l2-apps/lib - -CPPFLAGS += -I../include -I.. - -includes = libv4l2util.h - -objects = frequencies.o v4l2_driver.o - -sharedlib = libv4l2util.so -staticlib = libv4l2util.a - -ifeq ($(prefix),) -prefix = /usr -endif - -.PHONY: all clean install - -all: $(sharedlib) $(staticlib) - -$(sharedlib): $(objects) - -$(staticlib): $(objects) - -clean:: - rm -f $(objects) $(sharedlib) $(staticlib) - -install: - mkdir -p $(prefix)/include - cp $(includes) $(prefix)/include - mkdir -p $(prefix)/lib - cp $(sharedlib) $(staticlib) $(prefix)/lib - -include ../Make.rules diff --git a/v4l2-apps/lib/TODO b/v4l2-apps/lib/TODO deleted file mode 100644 index 456a916ce..000000000 --- a/v4l2-apps/lib/TODO +++ /dev/null @@ -1,81 +0,0 @@ -The only capture method implemented currently is mmap. - -Missing V4L2 ioctls to be implemented at library: - Methods to change controls at V4L devices: - VIDIOC_QUERYCTRL - VIDIOC_QUERYMENU - VIDIOC_G_CTRL - VIDIOC_S_CTRL - VIDIOC_TRY_EXT_CTRLS - VIDIOC_G_EXT_CTRLS - VIDIOC_S_EXT_CTRLS - - Tuner control methods: - VIDIOC_G_TUNER - VIDIOC_S_TUNER - VIDIOC_S_FREQUENCY - VIDIOC_G_FREQUENCY - - Crop methods: - VIDIOC_CROPCAP - VIDIOC_S_CROP - VIDIOC_G_CROP - - Audio input/output: - VIDIOC_ENUMAUDIO - VIDIOC_ENUMAUDOUT - VIDIOC_G_AUDIO - VIDIOC_S_AUDIO - VIDIOC_G_AUDOUT - VIDIOC_S_AUDOUT - - Video output: - VIDIOC_ENUMOUTPUT - VIDIOC_G_OUTPUT - VIDIOC_S_OUTPUT - - Priority control: - VIDIOC_G_PRIORITY - VIDIOC_S_PRIORITY - - Sliced VBI control: - VIDIOC_G_SLICED_VBI_CAP - - The received video STD: - VIDIOC_QUERYSTD - - Streaming parameters: - VIDIOC_G_PARM - VIDIOC_S_PARM - - Output modulator (generally for TV): - VIDIOC_G_MODULATOR - VIDIOC_S_MODULATOR - - Those methods are brand new. Not yet used on drivers: - VIDIOC_ENUM_FRAMEINTERVALS - VIDIOC_ENUM_FRAMESIZES - - Overlay is somewhat legacy stuff those days: - VIDIOC_OVERLAY - VIDIOC_G_FBUF - VIDIOC_S_FBUF - - Those are unlikely to be implemented at API (legacy stuff, debug stuff or private): - VIDIOC_G_JPEGCOMP - VIDIOC_S_JPEGCOMP - VIDIOC_LOG_STATUS - VIDIOC_PRIVATE - VIDIOC_RESERVED - VIDIOC_OVERLAY_OLD - VIDIOC_S_PARM_OLD - VIDIOC_S_CTRL_OLD - VIDIOC_G_AUDIO_OLD - VIDIOC_G_AUDOUT_OLD - VIDIOC_CROPCAP_OLD - -Also missing V4L1 mmap method: - VIDIOCGMBUF - - This method is interesting only to be used by driver-test to check -API compliance to the legacy method. diff --git a/v4l2-apps/lib/frequencies.c b/v4l2-apps/lib/frequencies.c deleted file mode 100644 index df8d47dba..000000000 --- a/v4l2-apps/lib/frequencies.c +++ /dev/null @@ -1,1502 +0,0 @@ -/* Copyright (C) 2006 Nathan Laredo - Nathan contributed the frequency tables. - - Copyright (C) 2006 Hans Verkuil - Added the iso-std table. - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#include - -#include -#include "libv4l2util.h" - -/* This source was originally written by Nathan Laredo . - He kindly gave permission to release this source under the LGPL - license. */ - -/* --------------------------------------------------------------------- */ - -/* US broadcast */ -static const struct v4l2_channel_list ntsc_bcast[] = { - { "2", 55250 }, - { "3", 61250 }, - { "4", 67250 }, - { "5", 77250 }, - { "6", 83250 }, - { "7", 175250 }, - { "8", 181250 }, - { "9", 187250 }, - { "10", 193250 }, - { "11", 199250 }, - { "12", 205250 }, - { "13", 211250 }, - { "14", 471250 }, - { "15", 477250 }, - { "16", 483250 }, - { "17", 489250 }, - { "18", 495250 }, - { "19", 501250 }, - { "20", 507250 }, - { "21", 513250 }, - { "22", 519250 }, - { "23", 525250 }, - { "24", 531250 }, - { "25", 537250 }, - { "26", 543250 }, - { "27", 549250 }, - { "28", 555250 }, - { "29", 561250 }, - { "30", 567250 }, - { "31", 573250 }, - { "32", 579250 }, - { "33", 585250 }, - { "34", 591250 }, - { "35", 597250 }, - { "36", 603250 }, - { "37", 609250 }, - { "38", 615250 }, - { "39", 621250 }, - { "40", 627250 }, - { "41", 633250 }, - { "42", 639250 }, - { "43", 645250 }, - { "44", 651250 }, - { "45", 657250 }, - { "46", 663250 }, - { "47", 669250 }, - { "48", 675250 }, - { "49", 681250 }, - { "50", 687250 }, - { "51", 693250 }, - { "52", 699250 }, - { "53", 705250 }, - { "54", 711250 }, - { "55", 717250 }, - { "56", 723250 }, - { "57", 729250 }, - { "58", 735250 }, - { "59", 741250 }, - { "60", 747250 }, - { "61", 753250 }, - { "62", 759250 }, - { "63", 765250 }, - { "64", 771250 }, - { "65", 777250 }, - { "66", 783250 }, - { "67", 789250 }, - { "68", 795250 }, - { "69", 801250 }, - - { "70", 807250 }, - { "71", 813250 }, - { "72", 819250 }, - { "73", 825250 }, - { "74", 831250 }, - { "75", 837250 }, - { "76", 843250 }, - { "77", 849250 }, - { "78", 855250 }, - { "79", 861250 }, - { "80", 867250 }, - { "81", 873250 }, - { "82", 879250 }, - { "83", 885250 }, -}; - -/* US cable */ -static const struct v4l2_channel_list ntsc_cable[] = { - { "1", 73250 }, - { "2", 55250 }, - { "3", 61250 }, - { "4", 67250 }, - { "5", 77250 }, - { "6", 83250 }, - { "7", 175250 }, - { "8", 181250 }, - { "9", 187250 }, - { "10", 193250 }, - { "11", 199250 }, - { "12", 205250 }, - - { "13", 211250 }, - { "14", 121250 }, - { "15", 127250 }, - { "16", 133250 }, - { "17", 139250 }, - { "18", 145250 }, - { "19", 151250 }, - { "20", 157250 }, - - { "21", 163250 }, - { "22", 169250 }, - { "23", 217250 }, - { "24", 223250 }, - { "25", 229250 }, - { "26", 235250 }, - { "27", 241250 }, - { "28", 247250 }, - { "29", 253250 }, - { "30", 259250 }, - { "31", 265250 }, - { "32", 271250 }, - { "33", 277250 }, - { "34", 283250 }, - { "35", 289250 }, - { "36", 295250 }, - { "37", 301250 }, - { "38", 307250 }, - { "39", 313250 }, - { "40", 319250 }, - { "41", 325250 }, - { "42", 331250 }, - { "43", 337250 }, - { "44", 343250 }, - { "45", 349250 }, - { "46", 355250 }, - { "47", 361250 }, - { "48", 367250 }, - { "49", 373250 }, - { "50", 379250 }, - { "51", 385250 }, - { "52", 391250 }, - { "53", 397250 }, - { "54", 403250 }, - { "55", 409250 }, - { "56", 415250 }, - { "57", 421250 }, - { "58", 427250 }, - { "59", 433250 }, - { "60", 439250 }, - { "61", 445250 }, - { "62", 451250 }, - { "63", 457250 }, - { "64", 463250 }, - { "65", 469250 }, - { "66", 475250 }, - { "67", 481250 }, - { "68", 487250 }, - { "69", 493250 }, - - { "70", 499250 }, - { "71", 505250 }, - { "72", 511250 }, - { "73", 517250 }, - { "74", 523250 }, - { "75", 529250 }, - { "76", 535250 }, - { "77", 541250 }, - { "78", 547250 }, - { "79", 553250 }, - { "80", 559250 }, - { "81", 565250 }, - { "82", 571250 }, - { "83", 577250 }, - { "84", 583250 }, - { "85", 589250 }, - { "86", 595250 }, - { "87", 601250 }, - { "88", 607250 }, - { "89", 613250 }, - { "90", 619250 }, - { "91", 625250 }, - { "92", 631250 }, - { "93", 637250 }, - { "94", 643250 }, - { "95", 91250 }, - { "96", 97250 }, - { "97", 103250 }, - { "98", 109250 }, - { "99", 115250 }, - { "100", 649250 }, - { "101", 655250 }, - { "102", 661250 }, - { "103", 667250 }, - { "104", 673250 }, - { "105", 679250 }, - { "106", 685250 }, - { "107", 691250 }, - { "108", 697250 }, - { "109", 703250 }, - { "110", 709250 }, - { "111", 715250 }, - { "112", 721250 }, - { "113", 727250 }, - { "114", 733250 }, - { "115", 739250 }, - { "116", 745250 }, - { "117", 751250 }, - { "118", 757250 }, - { "119", 763250 }, - { "120", 769250 }, - { "121", 775250 }, - { "122", 781250 }, - { "123", 787250 }, - { "124", 793250 }, - { "125", 799250 }, - - { "T7", 8250 }, - { "T8", 14250 }, - { "T9", 20250 }, - { "T10", 26250 }, - { "T11", 32250 }, - { "T12", 38250 }, - { "T13", 44250 }, - { "T14", 50250 } -}; - -/* US HRC */ -static const struct v4l2_channel_list ntsc_hrc[] = { - { "1", 72000 }, - - { "2", 54000 }, - { "3", 60000 }, - { "4", 66000 }, - - { "5", 78000 }, - { "6", 84000 }, - - { "7", 174000 }, - { "8", 180000 }, - { "9", 186000 }, - { "10", 192000 }, - { "11", 198000 }, - { "12", 204000 }, - { "13", 210000 }, - { "14", 120000 }, - { "15", 126000 }, - { "16", 132000 }, - { "17", 138000 }, - { "18", 144000 }, - { "19", 150000 }, - { "20", 156000 }, - { "21", 162000 }, - { "22", 168000 }, - { "23", 216000 }, - { "24", 222000 }, - { "25", 228000 }, - { "26", 234000 }, - { "27", 240000 }, - { "28", 246000 }, - { "29", 252000 }, - { "30", 258000 }, - { "31", 264000 }, - { "32", 270000 }, - { "33", 276000 }, - { "34", 282000 }, - { "35", 288000 }, - { "36", 294000 }, - { "37", 300000 }, - { "38", 306000 }, - { "39", 312000 }, - { "40", 318000 }, - { "41", 324000 }, - { "42", 330000 }, - { "43", 336000 }, - { "44", 342000 }, - { "45", 348000 }, - { "46", 354000 }, - { "47", 360000 }, - { "48", 366000 }, - { "49", 372000 }, - { "50", 378000 }, - { "51", 384000 }, - { "52", 390000 }, - { "53", 396000 }, - { "54", 402000 }, - { "55", 408000 }, - { "56", 414000 }, - { "57", 420000 }, - { "58", 426000 }, - { "59", 432000 }, - { "60", 438000 }, - { "61", 444000 }, - { "62", 450000 }, - { "63", 456000 }, - { "64", 462000 }, - { "65", 468000 }, - { "66", 474000 }, - { "67", 480000 }, - { "68", 486000 }, - { "69", 492000 }, - { "70", 498000 }, - { "71", 504000 }, - { "72", 510000 }, - { "73", 516000 }, - { "74", 522000 }, - { "75", 528000 }, - { "76", 534000 }, - { "77", 540000 }, - { "78", 546000 }, - { "79", 552000 }, - { "80", 558000 }, - { "81", 564000 }, - { "82", 570000 }, - { "83", 576000 }, - { "84", 582000 }, - { "85", 588000 }, - { "86", 594000 }, - { "87", 600000 }, - { "88", 606000 }, - { "89", 612000 }, - { "90", 618000 }, - { "91", 624000 }, - { "92", 630000 }, - { "93", 636000 }, - { "94", 642000 }, - - { "95", 90000 }, - { "96", 96000 }, - { "97", 102000 }, - { "98", 108000 }, - { "99", 114000 }, - - { "100", 648000 }, - { "101", 654000 }, - { "102", 660000 }, - { "103", 666000 }, - { "104", 672000 }, - { "105", 678000 }, - { "106", 684000 }, - { "107", 690000 }, - { "108", 696000 }, - { "109", 702000 }, - { "110", 708000 }, - { "111", 714000 }, - { "112", 720000 }, - { "113", 726000 }, - { "114", 732000 }, - { "115", 738000 }, - { "116", 744000 }, - { "117", 750000 }, - { "118", 756000 }, - { "119", 762000 }, - { "120", 768000 }, - { "121", 774000 }, - { "122", 780000 }, - { "123", 786000 }, - { "124", 792000 }, - { "125", 798000 }, - - { "T7", 7000 }, - { "T8", 13000 }, - { "T9", 19000 }, - { "T10", 25000 }, - { "T11", 31000 }, - { "T12", 37000 }, - { "T13", 43000 }, - { "T14", 49000 }, -}; - -/* US IRC */ -static const struct v4l2_channel_list ntsc_irc[] = { - { "1", 73250 }, - { "2", 55250 }, - { "3", 61250 }, - { "4", 67250 }, - { "5", 79250 }, - { "6", 85250 }, - { "7", 175250 }, - { "8", 181250 }, - { "9", 187250 }, - { "10", 193250 }, - { "11", 199250 }, - { "12", 205250 }, - { "13", 211250 }, - - { "14", 121150 }, - { "15", 127150 }, - { "16", 133150 }, - { "17", 139150 }, - { "18", 145150 }, - { "19", 151150 }, - { "20", 157150 }, - { "21", 163150 }, - { "22", 169150 }, - - { "23", 217250 }, - { "24", 223250 }, - { "25", 229250 }, - { "26", 235250 }, - { "27", 241250 }, - { "28", 247250 }, - { "29", 253250 }, - { "30", 259250 }, - { "31", 265250 }, - { "32", 271250 }, - { "33", 277250 }, - { "34", 283250 }, - { "35", 289250 }, - { "36", 295250 }, - { "37", 301250 }, - { "38", 307250 }, - { "39", 313250 }, - { "40", 319250 }, - { "41", 325250 }, - { "42", 331250 }, - { "43", 337250 }, - { "44", 343250 }, - { "45", 349250 }, - { "46", 355250 }, - { "47", 361250 }, - { "48", 367250 }, - { "49", 373250 }, - { "50", 379250 }, - { "51", 385250 }, - { "52", 391250 }, - { "53", 397250 }, - { "54", 403250 }, - { "55", 409250 }, - { "56", 415250 }, - { "57", 421250 }, - { "58", 427250 }, - { "59", 433250 }, - { "60", 439250 }, - { "61", 445250 }, - { "62", 451250 }, - { "63", 457250 }, - { "64", 463250 }, - { "65", 469250 }, - { "66", 475250 }, - { "67", 481250 }, - { "68", 487250 }, - { "69", 493250 }, - { "70", 499250 }, - { "71", 505250 }, - { "72", 511250 }, - { "73", 517250 }, - { "74", 523250 }, - { "75", 529250 }, - { "76", 535250 }, - { "77", 541250 }, - { "78", 547250 }, - { "79", 553250 }, - { "80", 559250 }, - { "81", 565250 }, - { "82", 571250 }, - { "83", 577250 }, - { "84", 583250 }, - { "85", 589250 }, - { "86", 595250 }, - { "87", 601250 }, - { "88", 607250 }, - { "89", 613250 }, - { "90", 619250 }, - { "91", 625250 }, - { "92", 631250 }, - { "93", 637250 }, - { "94", 643250 }, - - { "95", 91250 }, - { "96", 97250 }, - { "97", 103250 }, - { "98", 109250 }, - { "99", 115250 }, - { "100", 649250 }, - { "101", 655250 }, - { "102", 661250 }, - { "103", 667250 }, - { "104", 673250 }, - { "105", 679250 }, - { "106", 685250 }, - { "107", 691250 }, - { "108", 697250 }, - { "109", 703250 }, - { "110", 709250 }, - { "111", 715250 }, - { "112", 721250 }, - { "113", 727250 }, - { "114", 733250 }, - { "115", 739250 }, - { "116", 745250 }, - { "117", 751250 }, - { "118", 757250 }, - { "119", 763250 }, - { "120", 769250 }, - { "121", 775250 }, - { "122", 781250 }, - { "123", 787250 }, - { "124", 793250 }, - { "125", 799250 }, - - { "T7", 8250 }, - { "T8", 14250 }, - { "T9", 20250 }, - { "T10", 26250 }, - { "T11", 32250 }, - { "T12", 38250 }, - { "T13", 44250 }, - { "T14", 50250 } -}; - - -/* --------------------------------------------------------------------- */ - -/* JP broadcast */ -static const struct v4l2_channel_list ntsc_bcast_jp[] = { - { "1", 91250 }, - { "2", 97250 }, - { "3", 103250 }, - { "4", 171250 }, - { "5", 177250 }, - { "6", 183250 }, - { "7", 189250 }, - { "8", 193250 }, - { "9", 199250 }, - { "10", 205250 }, - { "11", 211250 }, - { "12", 217250 }, - - { "13", 471250 }, - { "14", 477250 }, - { "15", 483250 }, - { "16", 489250 }, - { "17", 495250 }, - { "18", 501250 }, - { "19", 507250 }, - { "20", 513250 }, - { "21", 519250 }, - { "22", 525250 }, - { "23", 531250 }, - { "24", 537250 }, - { "25", 543250 }, - { "26", 549250 }, - { "27", 555250 }, - { "28", 561250 }, - { "29", 567250 }, - { "30", 573250 }, - { "31", 579250 }, - { "32", 585250 }, - { "33", 591250 }, - { "34", 597250 }, - { "35", 603250 }, - { "36", 609250 }, - { "37", 615250 }, - { "38", 621250 }, - { "39", 627250 }, - { "40", 633250 }, - { "41", 639250 }, - { "42", 645250 }, - { "43", 651250 }, - { "44", 657250 }, - - { "45", 663250 }, - { "46", 669250 }, - { "47", 675250 }, - { "48", 681250 }, - { "49", 687250 }, - { "50", 693250 }, - { "51", 699250 }, - { "52", 705250 }, - { "53", 711250 }, - { "54", 717250 }, - { "55", 723250 }, - { "56", 729250 }, - { "57", 735250 }, - { "58", 741250 }, - { "59", 747250 }, - { "60", 753250 }, - { "61", 759250 }, - { "62", 765250 }, -}; - -/* JP cable */ -static const struct v4l2_channel_list ntsc_cable_jp[] = { - { "13", 109250 }, - { "14", 115250 }, - { "15", 121250 }, - { "16", 127250 }, - { "17", 133250 }, - { "18", 139250 }, - { "19", 145250 }, - { "20", 151250 }, - - { "21", 157250 }, - { "22", 165250 }, - { "23", 223250 }, - { "24", 231250 }, - { "25", 237250 }, - { "26", 243250 }, - { "27", 249250 }, - { "28", 253250 }, - { "29", 259250 }, - { "30", 265250 }, - { "31", 271250 }, - { "32", 277250 }, - { "33", 283250 }, - { "34", 289250 }, - { "35", 295250 }, - { "36", 301250 }, - { "37", 307250 }, - { "38", 313250 }, - { "39", 319250 }, - { "40", 325250 }, - { "41", 331250 }, - { "42", 337250 }, - { "43", 343250 }, - { "44", 349250 }, - { "45", 355250 }, - { "46", 361250 }, - { "47", 367250 }, - { "48", 373250 }, - { "49", 379250 }, - { "50", 385250 }, - { "51", 391250 }, - { "52", 397250 }, - { "53", 403250 }, - { "54", 409250 }, - { "55", 415250 }, - { "56", 421250 }, - { "57", 427250 }, - { "58", 433250 }, - { "59", 439250 }, - { "60", 445250 }, - { "61", 451250 }, - { "62", 457250 }, - { "63", 463250 }, -}; - -/* --------------------------------------------------------------------- */ - -/* australia */ -static const struct v4l2_channel_list pal_australia[] = { - { "0", 46250 }, - { "1", 57250 }, - { "2", 64250 }, - { "3", 86250 }, - { "4", 95250 }, - { "5", 102250 }, - { "5A", 138250 }, - { "6", 175250 }, - { "7", 182250 }, - { "8", 189250 }, - { "9", 196250 }, - { "10", 209250 }, - { "11", 216250 }, - { "28", 527250 }, - { "29", 534250 }, - { "30", 541250 }, - { "31", 548250 }, - { "32", 555250 }, - { "33", 562250 }, - { "34", 569250 }, - { "35", 576250 }, - { "36", 591250 }, - { "39", 604250 }, - { "40", 611250 }, - { "41", 618250 }, - { "42", 625250 }, - { "43", 632250 }, - { "44", 639250 }, - { "45", 646250 }, - { "46", 653250 }, - { "47", 660250 }, - { "48", 667250 }, - { "49", 674250 }, - { "50", 681250 }, - { "51", 688250 }, - { "52", 695250 }, - { "53", 702250 }, - { "54", 709250 }, - { "55", 716250 }, - { "56", 723250 }, - { "57", 730250 }, - { "58", 737250 }, - { "59", 744250 }, - { "60", 751250 }, - { "61", 758250 }, - { "62", 765250 }, - { "63", 772250 }, - { "64", 779250 }, - { "65", 786250 }, - { "66", 793250 }, - { "67", 800250 }, - { "68", 807250 }, - { "69", 814250 }, -}; - -static const struct v4l2_channel_list pal_australia_optus[] = { - { "1", 138250 }, - { "2", 147250 }, - { "3", 154250 }, - { "4", 161250 }, - { "5", 168250 }, - { "6", 175250 }, - { "7", 182250 }, - { "8", 189250 }, - { "9", 196250 }, - { "10", 209250 }, - { "11", 216250 }, - { "12", 224250 }, - { "13", 231250 }, - { "14", 238250 }, - { "15", 245250 }, - { "16", 252250 }, - { "17", 259250 }, - { "18", 266250 }, - { "19", 273250 }, - { "20", 280250 }, - { "21", 287250 }, - { "22", 294250 }, - { "23", 303250 }, - { "24", 310250 }, - { "25", 317250 }, - { "26", 324250 }, - { "27", 338250 }, - { "28", 345250 }, - { "29", 352250 }, - { "30", 359250 }, - { "31", 366250 }, - { "32", 373250 }, - { "33", 380250 }, - { "34", 387250 }, - { "35", 394250 }, - { "36", 401250 }, - { "37", 408250 }, - { "38", 415250 }, - { "39", 422250 }, - { "40", 429250 }, - { "41", 436250 }, - { "42", 443250 }, - { "43", 450250 }, - { "44", 457250 }, - { "45", 464250 }, - { "46", 471250 }, - { "47", 478250 }, - { "48", 485250 }, - { "49", 492250 }, - { "50", 499250 }, - { "51", 506250 }, - { "52", 513250 }, - { "53", 520250 }, - { "54", 527250 }, - { "55", 534250 }, -}; - - -/* --------------------------------------------------------------------- */ -/* europe */ - -/* CCIR frequencies */ - -#define FREQ_CCIR_I_III \ - { "E2", 48250 }, \ - { "E3", 55250 }, \ - { "E4", 62250 }, \ - \ - { "S01", 69250 }, \ - { "S02", 76250 }, \ - { "S03", 83250 }, \ - \ - { "E5", 175250 }, \ - { "E6", 182250 }, \ - { "E7", 189250 }, \ - { "E8", 196250 }, \ - { "E9", 203250 }, \ - { "E10", 210250 }, \ - { "E11", 217250 }, \ - { "E12", 224250 } - -#define FREQ_CCIR_SL_SH \ - { "SE1", 105250 }, \ - { "SE2", 112250 }, \ - { "SE3", 119250 }, \ - { "SE4", 126250 }, \ - { "SE5", 133250 }, \ - { "SE6", 140250 }, \ - { "SE7", 147250 }, \ - { "SE8", 154250 }, \ - { "SE9", 161250 }, \ - { "SE10", 168250 }, \ - \ - { "SE11", 231250 }, \ - { "SE12", 238250 }, \ - { "SE13", 245250 }, \ - { "SE14", 252250 }, \ - { "SE15", 259250 }, \ - { "SE16", 266250 }, \ - { "SE17", 273250 }, \ - { "SE18", 280250 }, \ - { "SE19", 287250 }, \ - { "SE20", 294250 } - -#define FREQ_CCIR_H \ - { "S21", 303250 }, \ - { "S22", 311250 }, \ - { "S23", 319250 }, \ - { "S24", 327250 }, \ - { "S25", 335250 }, \ - { "S26", 343250 }, \ - { "S27", 351250 }, \ - { "S28", 359250 }, \ - { "S29", 367250 }, \ - { "S30", 375250 }, \ - { "S31", 383250 }, \ - { "S32", 391250 }, \ - { "S33", 399250 }, \ - { "S34", 407250 }, \ - { "S35", 415250 }, \ - { "S36", 423250 }, \ - { "S37", 431250 }, \ - { "S38", 439250 }, \ - { "S39", 447250 }, \ - { "S40", 455250 }, \ - { "S41", 463250 } - -/* OIRT frequencies */ - -#define FREQ_OIRT_I_III \ - { "R1", 49750 }, \ - { "R2", 59250 }, \ - \ - { "R3", 77250 }, \ - { "R4", 85250 }, \ - { "R5", 93250 }, \ - \ - { "R6", 175250 }, \ - { "R7", 183250 }, \ - { "R8", 191250 }, \ - { "R9", 199250 }, \ - { "R10", 207250 }, \ - { "R11", 215250 }, \ - { "R12", 223250 } - -#define FREQ_OIRT_SL_SH \ - { "SR1", 111250 }, \ - { "SR2", 119250 }, \ - { "SR3", 127250 }, \ - { "SR4", 135250 }, \ - { "SR5", 143250 }, \ - { "SR6", 151250 }, \ - { "SR7", 159250 }, \ - { "SR8", 167250 }, \ - \ - { "SR11", 231250 }, \ - { "SR12", 239250 }, \ - { "SR13", 247250 }, \ - { "SR14", 255250 }, \ - { "SR15", 263250 }, \ - { "SR16", 271250 }, \ - { "SR17", 279250 }, \ - { "SR18", 287250 }, \ - { "SR19", 295250 } - -#define FREQ_UHF \ - { "21", 471250 }, \ - { "22", 479250 }, \ - { "23", 487250 }, \ - { "24", 495250 }, \ - { "25", 503250 }, \ - { "26", 511250 }, \ - { "27", 519250 }, \ - { "28", 527250 }, \ - { "29", 535250 }, \ - { "30", 543250 }, \ - { "31", 551250 }, \ - { "32", 559250 }, \ - { "33", 567250 }, \ - { "34", 575250 }, \ - { "35", 583250 }, \ - { "36", 591250 }, \ - { "37", 599250 }, \ - { "38", 607250 }, \ - { "39", 615250 }, \ - { "40", 623250 }, \ - { "41", 631250 }, \ - { "42", 639250 }, \ - { "43", 647250 }, \ - { "44", 655250 }, \ - { "45", 663250 }, \ - { "46", 671250 }, \ - { "47", 679250 }, \ - { "48", 687250 }, \ - { "49", 695250 }, \ - { "50", 703250 }, \ - { "51", 711250 }, \ - { "52", 719250 }, \ - { "53", 727250 }, \ - { "54", 735250 }, \ - { "55", 743250 }, \ - { "56", 751250 }, \ - { "57", 759250 }, \ - { "58", 767250 }, \ - { "59", 775250 }, \ - { "60", 783250 }, \ - { "61", 791250 }, \ - { "62", 799250 }, \ - { "63", 807250 }, \ - { "64", 815250 }, \ - { "65", 823250 }, \ - { "66", 831250 }, \ - { "67", 839250 }, \ - { "68", 847250 }, \ - { "69", 855250 } - -static const struct v4l2_channel_list europe_west[] = { - FREQ_CCIR_I_III, - FREQ_CCIR_SL_SH, - FREQ_CCIR_H, - FREQ_UHF -}; - -static const struct v4l2_channel_list europe_east[] = { - FREQ_OIRT_I_III, - FREQ_OIRT_SL_SH, - FREQ_CCIR_I_III, - FREQ_CCIR_SL_SH, - FREQ_CCIR_H, - FREQ_UHF -}; - -static const struct v4l2_channel_list pal_italy[] = { - { "A", 53750 }, - { "B", 62250 }, - { "C", 82250 }, - { "D", 175250 }, - { "E", 183750 }, - { "F", 192250 }, - { "G", 201250 }, - { "H", 210250 }, - { "H1", 217250 }, - { "H2", 224250 }, - FREQ_UHF -}; - -static const struct v4l2_channel_list pal_ireland[] = { - { "A0", 45750 }, - { "A1", 48000 }, - { "A2", 53750 }, - { "A3", 56000 }, - { "A4", 61750 }, - { "A5", 64000 }, - { "A6", 175250 }, - { "A7", 176000 }, - { "A8", 183250 }, - { "A9", 184000 }, - { "A10", 191250 }, - { "A11", 192000 }, - { "A12", 199250 }, - { "A13", 200000 }, - { "A14", 207250 }, - { "A15", 208000 }, - { "A16", 215250 }, - { "A17", 216000 }, - { "A18", 224000 }, - { "A19", 232000 }, - { "A20", 248000 }, - { "A21", 256000 }, - { "A22", 264000 }, - { "A23", 272000 }, - { "A24", 280000 }, - { "A25", 288000 }, - { "A26", 296000 }, - { "A27", 304000 }, - { "A28", 312000 }, - { "A29", 320000 }, - { "A30", 344000 }, - { "A31", 352000 }, - { "A32", 408000 }, - { "A33", 416000 }, - { "A34", 448000 }, - { "A35", 480000 }, - { "A36", 520000 }, - FREQ_UHF, -}; - -static const struct v4l2_channel_list secam_france[] = { - { "K01", 47750 }, - { "K02", 55750 }, - { "K03", 60500 }, - { "K04", 63750 }, - { "K05", 176000 }, - { "K06", 184000 }, - { "K07", 192000 }, - { "K08", 200000 }, - { "K09", 208000 }, - { "K10", 216000 }, - { "KB", 116750 }, - { "KC", 128750 }, - { "KD", 140750 }, - { "KE", 159750 }, - { "KF", 164750 }, - { "KG", 176750 }, - { "KH", 188750 }, - { "KI", 200750 }, - { "KJ", 212750 }, - { "KK", 224750 }, - { "KL", 236750 }, - { "KM", 248750 }, - { "KN", 260750 }, - { "KO", 272750 }, - { "KP", 284750 }, - { "KQ", 296750 }, - { "H01", 303250 }, - { "H02", 311250 }, - { "H03", 319250 }, - { "H04", 327250 }, - { "H05", 335250 }, - { "H06", 343250 }, - { "H07", 351250 }, - { "H08", 359250 }, - { "H09", 367250 }, - { "H10", 375250 }, - { "H11", 383250 }, - { "H12", 391250 }, - { "H13", 399250 }, - { "H14", 407250 }, - { "H15", 415250 }, - { "H16", 423250 }, - { "H17", 431250 }, - { "H18", 439250 }, - { "H19", 447250 }, - FREQ_UHF, -}; - -/* --------------------------------------------------------------------- */ - -static const struct v4l2_channel_list pal_newzealand[] = { - { "1", 45250 }, - { "2", 55250 }, - { "3", 62250 }, - { "4", 175250 }, - { "5", 182250 }, - { "6", 189250 }, - { "7", 196250 }, - { "8", 203250 }, - { "9", 210250 }, - { "10", 217250 }, - { "11", 224250 }, - FREQ_UHF, -}; - -/* --------------------------------------------------------------------- */ - -/* China broadcast */ -static const struct v4l2_channel_list pal_bcast_cn[] = { - { "1", 49750 }, - { "2", 57750 }, - { "3", 65750 }, - { "4", 77250 }, - { "5", 85250 }, - { "6", 112250 }, - { "7", 120250 }, - { "8", 128250 }, - { "9", 136250 }, - { "10", 144250 }, - { "11", 152250 }, - { "12", 160250 }, - { "13", 168250 }, - { "14", 176250 }, - { "15", 184250 }, - { "16", 192250 }, - { "17", 200250 }, - { "18", 208250 }, - { "19", 216250 }, - { "20", 224250 }, - { "21", 232250 }, - { "22", 240250 }, - { "23", 248250 }, - { "24", 256250 }, - { "25", 264250 }, - { "26", 272250 }, - { "27", 280250 }, - { "28", 288250 }, - { "29", 296250 }, - { "30", 304250 }, - { "31", 312250 }, - { "32", 320250 }, - { "33", 328250 }, - { "34", 336250 }, - { "35", 344250 }, - { "36", 352250 }, - { "37", 360250 }, - { "38", 368250 }, - { "39", 376250 }, - { "40", 384250 }, - { "41", 392250 }, - { "42", 400250 }, - { "43", 408250 }, - { "44", 416250 }, - { "45", 424250 }, - { "46", 432250 }, - { "47", 440250 }, - { "48", 448250 }, - { "49", 456250 }, - { "50", 463250 }, - { "51", 471250 }, - { "52", 479250 }, - { "53", 487250 }, - { "54", 495250 }, - { "55", 503250 }, - { "56", 511250 }, - { "57", 519250 }, - { "58", 527250 }, - { "59", 535250 }, - { "60", 543250 }, - { "61", 551250 }, - { "62", 559250 }, - { "63", 607250 }, - { "64", 615250 }, - { "65", 623250 }, - { "66", 631250 }, - { "67", 639250 }, - { "68", 647250 }, - { "69", 655250 }, - { "70", 663250 }, - { "71", 671250 }, - { "72", 679250 }, - { "73", 687250 }, - { "74", 695250 }, - { "75", 703250 }, - { "76", 711250 }, - { "77", 719250 }, - { "78", 727250 }, - { "79", 735250 }, - { "80", 743250 }, - { "81", 751250 }, - { "82", 759250 }, - { "83", 767250 }, - { "84", 775250 }, - { "85", 783250 }, - { "86", 791250 }, - { "87", 799250 }, - { "88", 807250 }, - { "89", 815250 }, - { "90", 823250 }, - { "91", 831250 }, - { "92", 839250 }, - { "93", 847250 }, - { "94", 855250 }, -}; - -/* --------------------------------------------------------------------- */ -/* South Africa Broadcast */ - -static const struct v4l2_channel_list pal_bcast_za[] ={ - { "4", 175250 }, - { "5", 183250 }, - { "6", 191250 }, - { "7", 199250 }, - { "8", 207250 }, - { "9", 215250 }, - { "10", 223250 }, - { "11", 231250 }, - { "12", 239250 }, - { "13", 247250 }, - FREQ_UHF -}; - -/* --------------------------------------------------------------------- */ - -static const struct v4l2_channel_list argentina[] = { - { "001", 56250 }, - { "002", 62250 }, - { "003", 68250 }, - { "004", 78250 }, - { "005", 84250 }, - { "006", 176250 }, - { "007", 182250 }, - { "008", 188250 }, - { "009", 194250 }, - { "010", 200250 }, - { "011", 206250 }, - { "012", 212250 }, - { "013", 122250 }, - { "014", 128250 }, - { "015", 134250 }, - { "016", 140250 }, - { "017", 146250 }, - { "018", 152250 }, - { "019", 158250 }, - { "020", 164250 }, - { "021", 170250 }, - { "022", 218250 }, - { "023", 224250 }, - { "024", 230250 }, - { "025", 236250 }, - { "026", 242250 }, - { "027", 248250 }, - { "028", 254250 }, - { "029", 260250 }, - { "030", 266250 }, - { "031", 272250 }, - { "032", 278250 }, - { "033", 284250 }, - { "034", 290250 }, - { "035", 296250 }, - { "036", 302250 }, - { "037", 308250 }, - { "038", 314250 }, - { "039", 320250 }, - { "040", 326250 }, - { "041", 332250 }, - { "042", 338250 }, - { "043", 344250 }, - { "044", 350250 }, - { "045", 356250 }, - { "046", 362250 }, - { "047", 368250 }, - { "048", 374250 }, - { "049", 380250 }, - { "050", 386250 }, - { "051", 392250 }, - { "052", 398250 }, - { "053", 404250 }, - { "054", 410250 }, - { "055", 416250 }, - { "056", 422250 }, - { "057", 428250 }, - { "058", 434250 }, - { "059", 440250 }, - { "060", 446250 }, - { "061", 452250 }, - { "062", 458250 }, - { "063", 464250 }, - { "064", 470250 }, - { "065", 476250 }, - { "066", 482250 }, - { "067", 488250 }, - { "068", 494250 }, - { "069", 500250 }, - { "070", 506250 }, - { "071", 512250 }, - { "072", 518250 }, - { "073", 524250 }, - { "074", 530250 }, - { "075", 536250 }, - { "076", 542250 }, - { "077", 548250 }, - { "078", 554250 }, - { "079", 560250 }, - { "080", 566250 }, - { "081", 572250 }, - { "082", 578250 }, - { "083", 584250 }, - { "084", 590250 }, - { "085", 596250 }, - { "086", 602250 }, - { "087", 608250 }, - { "088", 614250 }, - { "089", 620250 }, - { "090", 626250 }, - { "091", 632250 }, - { "092", 638250 }, - { "093", 644250 }, -}; - -/* --------------------------------------------------------------------- */ - -#define CHAN_COUNT(x) (sizeof(x)/sizeof(struct v4l2_channel_list)) - -const struct v4l2_channel_lists v4l2_channel_lists[] = { - { "us-bcast", ntsc_bcast, CHAN_COUNT(ntsc_bcast) }, - { "us-cable", ntsc_cable, CHAN_COUNT(ntsc_cable) }, - { "us-cable-hrc", ntsc_hrc, CHAN_COUNT(ntsc_hrc) }, - { "us-cable-irc", ntsc_irc, CHAN_COUNT(ntsc_irc) }, - { "japan-bcast", ntsc_bcast_jp, CHAN_COUNT(ntsc_bcast_jp) }, - { "japan-cable", ntsc_cable_jp, CHAN_COUNT(ntsc_cable_jp) }, - { "europe-west", europe_west, CHAN_COUNT(europe_west) }, - { "europe-east", europe_east, CHAN_COUNT(europe_east) }, - { "italy", pal_italy, CHAN_COUNT(pal_italy) }, - { "newzealand", pal_newzealand, CHAN_COUNT(pal_newzealand) }, - { "australia", pal_australia, CHAN_COUNT(pal_australia) }, - { "ireland", pal_ireland, CHAN_COUNT(pal_ireland) }, - { "france", secam_france, CHAN_COUNT(secam_france) }, - { "china-bcast", pal_bcast_cn, CHAN_COUNT(pal_bcast_cn) }, - { "southafrica", pal_bcast_za, CHAN_COUNT(pal_bcast_za) }, - { "argentina", argentina, CHAN_COUNT(argentina) }, - { "australia-optus", pal_australia_optus, CHAN_COUNT(pal_australia_optus) }, - { NULL, NULL, 0 } /* EOF */ -}; - -/* This list contains omissions and almost certainly incorrect information. - Please provide me (Hans Verkuil, ) with corrections. */ -const struct v4l2_country_std_map v4l2_country_std_map[] = { - { "AE", V4L2_STD_PAL_BG }, /* United Arab Emirates */ - { "AF", V4L2_STD_SECAM_D }, /* Afghanistan */ - { "AG", V4L2_STD_NTSC_M }, /* Antigua */ - { "AL", V4L2_STD_PAL_BG }, /* Albania */ - { "AM", V4L2_STD_SECAM_DK }, /* Armenia */ - { "AN", V4L2_STD_NTSC_M }, /* Netherlands Antilles */ - { "AO", V4L2_STD_PAL_I }, /* Angola */ - { "AR", V4L2_STD_PAL_Nc }, /* Argentina */ - { "AT", V4L2_STD_PAL_BG }, /* Austria */ - { "AU", V4L2_STD_PAL_B }, /* Australia */ - { "AW", V4L2_STD_NTSC_M }, /* Aruba */ - { "AZ", V4L2_STD_SECAM_DK }, /* Azerbaijan */ - { "BA", V4L2_STD_PAL_BG }, /* Bosnia and Herzegovina */ - { "BB", V4L2_STD_NTSC_M }, /* Barbados */ - { "BD", V4L2_STD_PAL_B }, /* Bangladesh */ - { "BE", V4L2_STD_PAL_B | V4L2_STD_PAL_H }, /* Belgium */ - { "BF", V4L2_STD_SECAM_K1 }, /* Burkina Faso */ - { "BG", V4L2_STD_SECAM_DK }, /* Bulgaria */ - { "BH", V4L2_STD_PAL_BG }, /* Bahrain */ - { "BI", V4L2_STD_SECAM_K1 }, /* Burundi */ - { "BJ", V4L2_STD_SECAM_K1 }, /* Benin */ - { "BM", V4L2_STD_NTSC_M }, /* Bermuda */ - { "BN", V4L2_STD_PAL_B }, /* Brunei Darussalam */ - { "BO", V4L2_STD_NTSC_M }, /* Bolivia */ - { "BR", V4L2_STD_PAL_M }, /* Brazil */ - { "BS", V4L2_STD_NTSC_M }, /* Bahamas */ - { "BW", V4L2_STD_PAL_I }, /* Botswana */ - { "BY", V4L2_STD_SECAM_D }, /* Belarus */ - { "BZ", V4L2_STD_NTSC_M }, /* Belize */ - { "CA", V4L2_STD_NTSC_M }, /* Canada */ - { "CD", V4L2_STD_SECAM_K1 }, /* The Democratic Republic of the Congo */ - { "CF", V4L2_STD_SECAM_K1 }, /* Central African Republic */ - { "CG", V4L2_STD_SECAM_K1 }, /* Republic of the Congo */ - { "CH", V4L2_STD_PAL_BG }, /* Switzerland */ - { "CL", V4L2_STD_NTSC_M }, /* Chile */ - { "CM", V4L2_STD_PAL_BG }, /* Cameroon */ - { "CN", V4L2_STD_PAL_D }, /* China */ - { "CO", V4L2_STD_NTSC_M }, /* Colombia */ - { "CR", V4L2_STD_NTSC_M }, /* Costa Rica */ - { "CU", V4L2_STD_NTSC_M }, /* Cuba */ - { "CY", V4L2_STD_PAL_BG }, /* Cyprus */ - { "CZ", V4L2_STD_PAL_D }, /* Czech Republic */ - { "DE", V4L2_STD_PAL_BG }, /* Germany */ - { "DJ", V4L2_STD_SECAM_B }, /* Djibouti */ - { "DK", V4L2_STD_PAL_BG }, /* Denmark */ - { "DO", V4L2_STD_NTSC_M }, /* Dominican Republic */ - { "DZ", V4L2_STD_PAL_BG }, /* Algeria */ - { "EC", V4L2_STD_NTSC_M }, /* Ecuador */ - { "EE", V4L2_STD_SECAM_DK }, /* Estonia */ - { "EG", V4L2_STD_PAL_BG }, /* Egypt */ - { "ES", V4L2_STD_PAL_BG }, /* Spain */ - { "ET", V4L2_STD_PAL_BG }, /* Ethiopia */ - { "FI", V4L2_STD_PAL_BG }, /* Finland */ - { "FR", V4L2_STD_SECAM_L }, /* France */ - { "GA", V4L2_STD_SECAM_K1 }, /* Gabon */ - { "GB", V4L2_STD_PAL_I }, /* United Kingdom */ - { "GE", V4L2_STD_SECAM_DK }, /* Georgia */ - { "GH", V4L2_STD_PAL_B }, /* Ghana */ - { "GI", V4L2_STD_PAL_BG }, /* Gibraltar */ - { "GL", V4L2_STD_PAL_BG }, /* Greenland */ - { "GM", V4L2_STD_PAL_I }, /* Gambia */ - { "GQ", V4L2_STD_PAL_BG }, /* Equatorial Guinea */ - { "GR", V4L2_STD_SECAM_B }, /* Greece */ - { "GR", V4L2_STD_SECAM_G }, /* Greece */ - { "GT", V4L2_STD_NTSC_M }, /* Guatemala */ - { "GU", V4L2_STD_NTSC_M }, /* Guam */ - { "GW", V4L2_STD_PAL_I }, /* Guinea-Bissau */ - { "HK", V4L2_STD_PAL_I }, /* Hong Kong */ - { "HN", V4L2_STD_NTSC_M }, /* Honduras */ - { "HR", V4L2_STD_PAL_BG }, /* Croatia */ - { "HU", V4L2_STD_SECAM_DK }, /* Hungary */ - { "ID", V4L2_STD_PAL_B }, /* Indonesia */ - { "IE", V4L2_STD_PAL_I }, /* Ireland */ - { "IL", V4L2_STD_PAL_BG }, /* Israel */ - { "IN", V4L2_STD_PAL_B }, /* India */ - { "IQ", V4L2_STD_SECAM_B | V4L2_STD_SECAM_G }, /* Iraq */ - { "IR", V4L2_STD_SECAM_B | V4L2_STD_SECAM_G }, /* Iran */ - { "IS", V4L2_STD_PAL_BG }, /* Iceland */ - { "IT", V4L2_STD_PAL_BG }, /* Italy */ - { "JM", V4L2_STD_NTSC_M }, /* Jamaica */ - { "JO", V4L2_STD_PAL_BG }, /* Jordan */ - { "JP", V4L2_STD_NTSC_M_JP }, /* Japan */ - { "KE", V4L2_STD_PAL_BG }, /* Kenya */ - { "KH", V4L2_STD_PAL_BG }, /* Cambodia */ - { "KM", V4L2_STD_SECAM_K1 }, /* Comoros */ - { "KN", V4L2_STD_NTSC_M }, /* Saint Kitts and Nevis */ - { "KP", V4L2_STD_PAL_D }, /* North Korea */ - { "KR", V4L2_STD_NTSC_M_KR }, /* South Korea */ - { "KW", V4L2_STD_PAL_BG }, /* Kuwait */ - { "KZ", V4L2_STD_SECAM_D }, /* Kazakhstan */ - { "KZ", V4L2_STD_SECAM_K }, /* Kazakhstan */ - { "LB", V4L2_STD_SECAM_B }, /* Lebanon */ - { "LK", V4L2_STD_PAL_BG }, /* Sri Lanka */ - { "LR", V4L2_STD_PAL_BG }, /* Liberia */ - { "LS", V4L2_STD_PAL_I }, /* Lesotho */ - { "LT", V4L2_STD_SECAM_DK }, /* Lithuania */ - { "LU", V4L2_STD_PAL_BG }, /* Luxembourg */ - { "LY", V4L2_STD_PAL_BG }, /* Libya */ - { "MA", V4L2_STD_SECAM_B | V4L2_STD_SECAM_G }, /* Morocco */ - { "MC", V4L2_STD_PAL_G }, /* Monaco */ - { "MD", V4L2_STD_SECAM_DK }, /* Moldova */ - { "MG", V4L2_STD_SECAM_K | V4L2_STD_SECAM_K1 }, /* Madagascar */ - { "ML", V4L2_STD_SECAM_B | V4L2_STD_SECAM_G }, /* Mali */ - { "MM", V4L2_STD_NTSC_M }, /* Myanmar */ - { "MN", V4L2_STD_SECAM_D }, /* Mongolia */ - { "MR", V4L2_STD_SECAM_B }, /* Mauritania */ - { "MS", V4L2_STD_NTSC_M }, /* Montserrat */ - { "MT", V4L2_STD_PAL_B }, /* Malta */ - { "MU", V4L2_STD_SECAM_B | V4L2_STD_SECAM_G }, /* Mauritius */ - { "MV", V4L2_STD_PAL_B }, /* Maldives */ - { "MW", V4L2_STD_PAL_I }, /* Malawi */ - { "MX", V4L2_STD_NTSC_M }, /* Mexico */ - { "MY", V4L2_STD_PAL_BG }, /* Malaysia */ - { "MZ", V4L2_STD_PAL_G }, /* Mozambique */ - { "NA", V4L2_STD_PAL_I }, /* Namibia */ - { "NE", V4L2_STD_SECAM_K1 }, /* Niger */ - { "NG", V4L2_STD_PAL_BG }, /* Nigeria */ - { "NI", V4L2_STD_NTSC_M }, /* Nicaragua */ - { "NL", V4L2_STD_PAL_BG }, /* Netherlands */ - { "NO", V4L2_STD_PAL_BG }, /* Norway */ - { "NP", V4L2_STD_PAL_B }, /* Nepal */ - { "NZ", V4L2_STD_PAL_BG }, /* New Zealand */ - { "OM", V4L2_STD_PAL_BG }, /* Oman */ - { "PA", V4L2_STD_NTSC_M }, /* Panama */ - { "PE", V4L2_STD_NTSC_M }, /* Peru */ - { "PG", V4L2_STD_PAL_BG }, /* Papua New Guinea */ - { "PH", V4L2_STD_NTSC_M }, /* Philippines */ - { "PK", V4L2_STD_PAL_BG }, /* Pakistan */ - { "PL", V4L2_STD_SECAM_K }, /* Poland */ - { "PR", V4L2_STD_NTSC_M }, /* Puerto Rico */ - { "PT", V4L2_STD_PAL_BG }, /* Portugal */ - { "PY", V4L2_STD_PAL_N }, /* Paraguay */ - { "QA", V4L2_STD_PAL_BG }, /* Qatar */ - { "RO", V4L2_STD_PAL_DK }, /* Romania */ - { "RU", V4L2_STD_SECAM_DK }, /* Russia */ - { "RW", V4L2_STD_SECAM_K1 }, /* Rwanda */ - { "SA", V4L2_STD_PAL_BG | V4L2_STD_SECAM_B | V4L2_STD_SECAM_G }, /* Saudi Arabia */ - { "SC", V4L2_STD_PAL_B }, /* Seychelles */ - { "SD", V4L2_STD_PAL_BG }, /* Sudan */ - { "SE", V4L2_STD_PAL_BG }, /* Sweden */ - { "SG", V4L2_STD_PAL_BG }, /* Singapore */ - { "SI", V4L2_STD_PAL_BG }, /* Slovenia */ - { "SK", V4L2_STD_SECAM_DK }, /* Slovak Republic */ - { "SL", V4L2_STD_PAL_BG }, /* Sierra Leone */ - { "SN", V4L2_STD_SECAM_K1 }, /* Senegal */ - { "SO", V4L2_STD_PAL_BG }, /* Somalia */ - { "SR", V4L2_STD_NTSC_M }, /* Suriname */ - { "ST", V4L2_STD_PAL_B }, /* Sao Tome and Principe */ - { "SV", V4L2_STD_NTSC_M }, /* El Salvador */ - { "SY", V4L2_STD_PAL_BG }, /* Syria */ - { "SZ", V4L2_STD_PAL_BG }, /* Swaziland */ - { "TD", V4L2_STD_SECAM_K1 }, /* Chad */ - { "TG", V4L2_STD_SECAM_K1 }, /* Togo */ - { "TH", V4L2_STD_PAL_BG }, /* Thailand */ - { "TN", V4L2_STD_PAL_BG }, /* Tunisia */ - { "TR", V4L2_STD_PAL_BG }, /* Turkey */ - { "TT", V4L2_STD_NTSC_M }, /* Trinidad and Tobago */ - { "TW", V4L2_STD_NTSC_M }, /* Taiwan */ - { "TZ", V4L2_STD_PAL_I }, /* Tanzania */ - { "UA", V4L2_STD_SECAM_DK }, /* Ukraine */ - { "UG", V4L2_STD_PAL_B }, /* Uganda */ - { "US", V4L2_STD_NTSC_M }, /* United States */ - { "UY", V4L2_STD_PAL_N }, /* Uruguay */ - { "VC", V4L2_STD_SECAM_K1 }, /* Cape Verde */ - { "VE", V4L2_STD_NTSC_M }, /* Venezuela */ - { "VG", V4L2_STD_NTSC_M }, /* Virgin Islands, British */ - { "VI", V4L2_STD_NTSC_M }, /* Virgin Islands, U.S. */ - { "VN", V4L2_STD_SECAM_DK }, /* Vietnam */ - { "WS", V4L2_STD_NTSC_M }, /* Samoa */ - { "YE", V4L2_STD_PAL_BG }, /* Yemen */ - { "ZA", V4L2_STD_PAL_I }, /* South Africa */ - { "ZM", V4L2_STD_PAL_G }, /* Zambia */ - { "ZW", V4L2_STD_PAL_G }, /* Zimbabwe */ - { NULL, 0 } -}; diff --git a/v4l2-apps/lib/libv4l/COPYING.LIB b/v4l2-apps/lib/libv4l/COPYING.LIB deleted file mode 100644 index 1dd325d2b..000000000 --- a/v4l2-apps/lib/libv4l/COPYING.LIB +++ /dev/null @@ -1,510 +0,0 @@ - - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations -below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. -^L - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it -becomes a de-facto standard. To achieve this, non-free programs must -be allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. -^L - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control -compilation and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. -^L - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. -^L - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at least - three years, to give the same user the materials specified in - Subsection 6a, above, for a charge no more than the cost of - performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. -^L - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. -^L - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply, and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License -may add an explicit geographical distribution limitation excluding those -countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. -^L - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS -^L - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms -of the ordinary General Public License). - - To apply these terms, attach the following notices to the library. -It is safest to attach them to the start of each source file to most -effectively convey the exclusion of warranty; and each file should -have at least the "copyright" line and a pointer to where the full -notice is found. - - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -Also add information on how to contact you by electronic and paper mail. - -You should also get your employer (if you work as a programmer) or -your school, if any, to sign a "copyright disclaimer" for the library, -if necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James - Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! - - diff --git a/v4l2-apps/lib/libv4l/ChangeLog b/v4l2-apps/lib/libv4l/ChangeLog deleted file mode 100644 index dd53eced9..000000000 --- a/v4l2-apps/lib/libv4l/ChangeLog +++ /dev/null @@ -1,247 +0,0 @@ -libv4l-0.5.0 ------------- -* Add support for enumerating framesizes and frameintervals of emulated - formats when the driver supports it for the real format -* Make sure the video device always gets opened RW even if the application - asks for RO -* Add Genius E-Messenger 112 (093a:2476) to list of cams which have their - sensor upside down - -libv4l-0.4.3 ------------- -* Add suport for YUYV and YVYU packed pixel formats (Jean-Francois Moine) -* Prefer compressed pixformats for resolutions > 176x144 - -libv4l-0.4.2 ------------- -* The bayer pixel order in gspca's sonixb driver was different from that in - the sn9c102 driver from the mainline kernel, a recent gspca patch fixes - this, adjust libv4l to match (and make it work properly with the sn9c102 - driver). - -libv4l-0.4.1 ------------- -* When the driver supports read() and we are not converting let the driver - handle read() instead of emulating it with mmap mode -* Fix errors and warnings when compiling with ICC (Gregor Jasny) -* Add support to libv4lconvert for rotating images 90 (for Pixart 7302 cams) - or 180 (Philips SPC200NC / Philips SPC300NC) degrees -* Add support for Pixart custom JPEG format -* Hide non public symbols (Gregor Jasny) -* Fix and enable x86_64 asm jpeg decompress helper functions (Gregor Jasny) - -libv4l-0.4.0 ------------- -* Be more relaxed in our checks for mixing read and mmap access, we were - being more strict in this then certain kernel drivers (bttv) making xawtv - unhappy -* With some drivers the buffers must be mapped before queuing, so when - converting map the (real) buffers before calling the qbuf ioctl -* Add support for conversion to RGB24 (before we only supported BGR24) based - on a patch by Jean-Francois Moine -* When the hardware supports a format natively prefer using the native - version over converting from another supported format -* Various Makefile and pkgconfig file improvements by Gregor Jasny (Debian) -* Drop the appl-patches dir, all application patches are now available and - tracked here: http://linuxtv.org/v4lwiki/index.php/Libv4l_Progress - - -libv4l-0.3.9 ------------- -* Not only see /dev/video* but also /dev/v4l/* as video devices - (only affects libv4l1 and the wrappers) patch from Brandon Philips -* Silence the creation of the .pc files in the Makefiles (Brandon Philips) -* Part of the copyright headers refered GPL instead of LGPL due to a copy - and paste error (Brandon Philips) - - -libv4l-0.3.8 ------------- -* work around wrong REQUEST_BUFFERS ioctl return code from certain drivers -* add pkg-config (.pc) files for easier detection if libv4l is available -* check capabilities for streaming, if the driver cannot do streaming don't - insert ourselves between the application and the driver -* intercept get capabilites and report read capability (which we always offer) -* query buffer: indicate the mapping state of our (fake) buffer in the flags - - -libv4l-0.3.7 ------------- -* Add spca505/6 and spca508 cam specific formats (YUYV per line variations) - - -libv4l-0.3.6 ------------- -* Add missing COPYING.LIB file - - -libv4l-0.3.5 ------------- -* Make JPEG decoding more robust - - -libv4l-0.3.4 (the brownpaperbag release) ----------------------------------------- -* The mmap64 support in 0.3.3, has caused a bug in libv4l1 when running on - 32 bit systems (who uses those now a days?), this bug caused v4l1 - compatibility to not work at all, this release fixes this -* Some apps (xawtv, kopete) use an ioctl wrapper internally for various - reasons. This wrappers request argument is an int, but the real ioctl's - request argument is an unsigned long. Passing the VIDIOC_xxx defines through - to the wrapper, and then to the real ioctl, causes the request to get sign - extended on 64 bit args. The kernel seems to ignore the upper 32 bits, - causing the sign extension to not make a difference. libv4l now also - ignores the upper 32 bits of the libv4lx_ioctl request argument on 64 bit - archs -* Add a bugfix patch for kopete in the appl-patches dir, currently it assumes - that it got the width and height it asked for when doing a S_FMT, which is a - wrong assumption - - -libv4l-0.3.3 ------------- -* Add open64 and mmap64 wrappers to the LD_PRELOAD wrapper libs, so that - they also work for applications compiled with FILE_OFFSET_BITS=64, this - fixes using them with v4l-info -* While looking at xawtv in general, found a few bugs in xawtv itself, added - a patch to fix those to the appl-patches dir -* Talking about the appl-patches dir, restore that as it accidentally got - dropped from 0.3.2 -* Be more verbose in various places when it comes to logging (esp errors) -* Change v4lconvert_enum_fmt code a bit, so that it is easier to add more - supported destination formats to libv4lconvert -* Don't return -EINVAL from try_fmt when we cannot convert because the cam - doesn't have any formats we know. Instead just return as format whatever the - cam returns from try_fmt, this new behavior is compliant with the v4l2 - api as documented - -libv4l-0.3.2 ------------- -* Add support for converting from sn9c10x compressed data -* Add support for converting from pac207 compressed data -* Add "make install" Makefile target - -libv4l-0.3.1 ------------- -* Only serialize V4L2_BUF_TYPE_VIDEO_CAPTURE type ioctls -* Do not return an uninitialized variable as result code for GPICT - (fixes vlc, but see below) -* Add an apps-patches directory which includes: - * vlc-0.8.6-libv4l1.patch, modify vlc's v4l1 plugin to directly call into - libv4l1, in the end we want all apps todo this as its better then - LD_PRELOAD tricks, but for vlc this is needed as vlc's plugin system - causes LD_PRELOAD to not work on symbols in the plugins - * camorama-0.19-fixes.patch, small bugfixes to camorama's v4l1 support, - this patch only fixes _real_ bugs in camorama and does not change it to - work with v4l1compat. Although it does work better with these bugs fixed - :) With this patch and LD_PRELOAD=/v4l1compat.so it works - flawless. - - -libv4l-0.3 ----------- -* add extern "C" magic to public header files for c++ usage (Gregor Jasny) -* Make libv4l1 and libv4l2 multithread use safe, see README.multi-threading -* Add v4lx_dup() calls (and intercept dup() from the wrappers) this fixes - use with gstreamer's v4l2 plugin (tested with cheese) -* Hopefully definitely fix compile errors on systems with a broken videodev2.h - -libv4l-0.2 ----------- -*** API change *** -* Change v4lconvert api so that the v4lconvert struct always gets allocated - by the library, this to make it opaque, so that we can avoid future API - and ABI changes -* Add support for yuv420 -> bgr24 conversion -* When converting from v4l2 pixelformat to v4l12 palette return - VIDEO_PALETTE_YUV420P instead of VIDEO_PALETTE_YUV420 for - V4L2_PIX_FMT_YUV420 as that is what most apps seem to expect -* override kernel v4l1 compat min / max size with our own more accurate values -* fix v4l1 munmap bug where it didn't recognise the buffer being unmapped was - our fake buffer (fixes gstreamer v4l1 support, checked with cheese) -* add support for reporting the emulated pixelformats with ENUM_FMT, this - defaults to off, and can be activated by passing a flag to enable it to - v4l2_fd_open. This gets enabled by default the wrappers. -* v4l2: mmap the real device buffers before doing conversion when DQBUF gets - called before the application has called mmap (avoid crash). - - -libv4l-0.1 ----------- -* major shuffle / rewrite now split into libv4l1, libv4l2, libv4lconvert - and 2 wrappers for binary compatibility -* rewritten LGPL bayer decoding -* many many other changes and fixes - - -v4l1-compat-0.6 (V4L2 apps stay working) ----------------------------------------- -* Do not go into emulation mode of rgb24 immediately, but only after a - GPICT ioctl which has not been preceded by a SPICT ioctl, AKA do not get - in the way of V4L2 read calls by doing conversion on them -* Do not get in the way of mmap calls made by V4L2 applications -* Fix swapping of red and blue in bayer -> bgr24 decode routine -* Remember the v4l1 palette asked for with SPICT and return that, as - otherwise we loose information when going v4l1 -> v4l2 -> v4l1, for example - YUV420P becomes YUV420, which are separate in v4l1. - - -v4l1-compat-0.5 (perfect camorama) ----------------------------------- -* Allow changing of format after the buffers have been mapped, by tearing - down the entire house, changing the fundament and then rebuilding it. - Now changing the capture resolution in camorama works! -* Fix jpeg decoding error reporting -* Allow jpeg's with a height which is a multiple of 8 (was 16) -* Remove a number of pretty new VIDIOCXXX -> string mappings from log.c, - fixing compiling with somewhat older kernels - - -v4l1-compat 0.4 ---------------- -* Do not even try to change the format in v4l1_compat_set_format(), unless - _really_ necessary. -* Cleanup ambigious use of src_format (no functional changes) -* Drop the mmap hack for zerocopy access under certain conditions, one of them - that the cam can deliver the requested format. Although avoiding the - memcpy in this scenarios is a good thing todo, there were several issues - with the 0.3 implementation of this, fixing all these means adding lots of - special cases all over the code. So instead we just drop support and - always do atleast a memcpy (or a conversion). If an application cannot - live with the speed penalty this imposes it should be ported to v4l2. -* Now that we've gotten rid of the zerocopy mmap hack, we can safely allow - mixing read and mmap based IO. -* Explictly include linux/ioctl.h, to fix compile with kernel headers where - linux/videodev.h doesn't. - - -v4l1-compat 0.3 ---------------- -* Don't allow multiple opens, in theory our code can handle it, but not all - v4l2 devices like it (ekiga does it and uvc doesn't like it). - - -v4l1-compat 0.2 ---------------- -* When mmap gets passed an fd of -1 (anonymous map) don't look for it in our - list of managed fds, as we use -1 to mark unused entries (fixes ekiga - crashing). Also check for an fd of -1 in the other calls we intercept. -* In close() start with removing the fd from our list of managed fds, this must - be done first, because as soon as we've done the actual close syscall, the - fd maybe returned by an open in another thread and we don't want to intercept - calls to this new fd. -* Make unknown v4l1 palette types a normal level log messages instead of an - error. -* When an applicaiton changes the width / height through the CMCAPTURE ioctl - remember the new width and height. -* If the devices initial v4l2 pixformat has no corresponding v4l1 palette, try - setting a format which does (and which we emulate when necessary) so that - applicactions which just query the current format (GPICT) and then take - whatever they get will work (partially fixes camorama) -* Implement our own SWIN instead of using kernel compat layer, for more - flexibility and better error checking - - -v4l1-compat 0.1 ---------------- -* Initial public release. diff --git a/v4l2-apps/lib/libv4l/Makefile b/v4l2-apps/lib/libv4l/Makefile deleted file mode 100644 index 4c99c3167..000000000 --- a/v4l2-apps/lib/libv4l/Makefile +++ /dev/null @@ -1,16 +0,0 @@ -LIB_RELEASE=0 -V4L2_LIB_VERSION=$(LIB_RELEASE).5.0 - -all clean install: - $(MAKE) -C libv4lconvert V4L2_LIB_VERSION=$(V4L2_LIB_VERSION) $@ - $(MAKE) -C libv4l2 V4L2_LIB_VERSION=$(V4L2_LIB_VERSION) $@ - $(MAKE) -C libv4l1 V4L2_LIB_VERSION=$(V4L2_LIB_VERSION) $@ - -export: clean - mkdir /tmp/libv4l-$(V4L2_LIB_VERSION) - cp -a . /tmp/libv4l-$(V4L2_LIB_VERSION)/ - cd /tmp/ && \ - tar cvf /tmp/libv4l-$(V4L2_LIB_VERSION).tar\ - libv4l-$(V4L2_LIB_VERSION) - gzip /tmp/libv4l-$(V4L2_LIB_VERSION).tar - rm -rf /tmp/libv4l-$(V4L2_LIB_VERSION) diff --git a/v4l2-apps/lib/libv4l/README b/v4l2-apps/lib/libv4l/README deleted file mode 100644 index 3a2059224..000000000 --- a/v4l2-apps/lib/libv4l/README +++ /dev/null @@ -1,141 +0,0 @@ -Introduction ------------- - -libv4l is a collection of libraries which adds a thin abstraction layer on -top of video4linux2 devices. The purpose of this (thin) layer is to make it -easy for application writers to support a wide variety of devices without -having to write seperate code for different devices in the same class. - -All libv4l components are licensed under the GNU Lesser General Public -License version 2 or (at your option) any later version. - -libv4l consists of 3 different libraries: - - -libv4lconvert -------------- - -libv4lconvert offers functions to convert from any (known) pixelformat -to V4l2_PIX_FMT_BGR24 or V4l2_PIX_FMT_YUV420. - -Currently the following source formats are supported: -jpeg, mjpeg, bayer (all 4 variants: bggr, rggb, gbrg, grbg), -spca501 (chip specific yuv 420 with interlaced components), -spca561 (chip specific compressed gbrg bayer) -For more details on the v4lconvert_ functions see libv4lconvert.h . - - -libv4l1 -------- - -This offers functions like v4l1_open, v4l1_ioctl, etc. which can by used to -quickly make v4l1 applications work with v4l2 devices. These functions work -exactly like the normal open/close/etc, except that libv4l1 does full emulation -of the v4l1 api on top of v4l2 drivers, in case of v4l1 drivers it will just -pass calls through. For more details on the v4l1_ functions see libv4l1.h . - - -libv4l2 -------- - -This offers functions like v4l2_open, v4l2_ioctl, etc. which can by used to -quickly make v4l2 applications work with v4l2 devices with weird formats. -libv4l2 mostly passes calls directly through to the v4l2 driver. When the -app does a TRY_FMT / S_FMT with a not supported format libv4l2 will get in -the middle and emulate the format (if an app wants to know which formats the -hardware can _really_ do it should use ENUM_FMT, not randomly try a bunch of -S_FMT's). For more details on the v4l2_ functions see libv4l2.h . - - -wrappers --------- - -The functionality provided by libv4l1 for v4l1 apps and libv4l2 for v4l2 apps -can also be used by existing apps without modifying them. For this purpose -2 wrapper libraries are provided which can be preloaded before starting the -application using the LD_PRELOAD environment variable. These wrappers will -then intercept calls to open/close/ioctl/etc. and if these calls directed -towards a video device the wrapper will redirect the call to the libv4lX -counterparts. - -The preloadable libv4l1 wrapper which adds v4l2 device compatibility to v4l1 -applications is called v4l1compat.so. The preloadable libv4l2 wrapper which -adds support for various pixelformats to v4l2 applications is called -v4l2convert.so. - -Example usage (after install in default location): -$ export LD_PRELOAD=/usr/local/lib/libv4l/v4l1compat.so -$ camorama - - -Installation Instructions -------------------------- - -Simple type the following commands from the libv4l-x.y.z directory -(adjusting PREFIX as desired): -make -make install PREFIX=/usr/local - -Note: make install also supports the DESTDIR=... paramter for installation -into chroots. - - -FAQ ---- - -Q: Why libv4l, whats wrong with directly accessing v4l2 devices ? -Q: Do we really need yet another library ? -A: Current webcam using applications like ekiga contain code to handle many -different specific pixelformats webcam's use, but that code only supports a -small subset of all native webcam (compressed) pixelformats. Other current -v4l2 applications do not support anything but rgb pixelformats (xawtv for -example) and this will not work with most webcams at all. - -With gspca being ported to v4l2 and thus decoding to normal formats being -removed from the device driver as this really belongs in userspace, ekiga -would need to be extended with many more often chip dependent formats, like -the bayer compression used by the spca561 and the (different) compression used -by the pac207 and the (again different) compression used by the sn9c102. Adding -support for all these formats should not be done at the application level, as -then it needs to be written for each application seperately. Licensing issues -with the decompressors will then also become a problem as just cut and pasting -from one application to another is bound to hit license incompatibilities. - -So clearly this belongs in a library, and in a library with a license which -allows this code to be used from as many different applications as possible. -Hence libv4l was born. - -Q: Under which license may I use and distribute libv4l? -A: All libv4l components are licensed under the GNU Library General Publishing -License version 2 or (at your option) any later version. See the included -COPYING.LIB file. - -Q: Okay so I get the use of having a libv4lconvert, but why libv4l1 ? -A: Many v4l2 drivers do not offer full v4l1 compatibility. They often do not -implemented the CGMBUF ioctl and v4l1 style mmap call. Adding support to all -these drivers for this is a lot of work and more importantly unnecessary -adds code to kernel space. - -Also even if the CGMBUF ioctl and v4l1 style mmap are supported, then most -cams still deliver pixelformats which v4l1 applications do not understand. - -This libv4l1 was born as an easy way to get v4l1 applications to work with -v4l2 devices without requiring full v4l1 emulation (including format -conversion) in the kernel, and without requiring major changes to the -applications. - - -Q: Why should I use libv4l2 in my app instead of direct device access -combined with libv4lconvert? - -libv4l2 is mainly meant for quickly and easily adding support for more -pixelformats to existing v4l2 applications. So if you feel better directly -accessing the device in combination with libv4lconvert thats fine too. - -Notice that libv4l2 also does emulation of the read() call on devices which -do not support it in the driver. In the background this uses mmap buffers -(even on devices which do support the read call). This mmap gives libv4lconvert -zero-copy access to the captured frame, and then it can write the converted -data directly to the buffer the application provided to v4l2_read(). Thus -another reason to use liv4l2 is to get the no memcpy advantage of the mmap -capture method combined with the simplicity of making a simple read() call. diff --git a/v4l2-apps/lib/libv4l/README.multi-threading b/v4l2-apps/lib/libv4l/README.multi-threading deleted file mode 100644 index 93b393c8c..000000000 --- a/v4l2-apps/lib/libv4l/README.multi-threading +++ /dev/null @@ -1,12 +0,0 @@ -libv4lconvert is not safe for using one convert instance as returned by -v4lconvert_create from multiple threads, if you want to use one v4lconvert -instance from multiple threads you must provide your own locking and make -sure no simultanious calls are made. - -libv4l1 and libv4l2 are safe for multithread use *under* *the* *following* -*conditions* : - -* when using v4lx_fd_open, do not make any v4lx_ calls to the passed fd until - v4lx_fd_open has completed - -* all v4lx_ calls must be completed before calling v4lx_close diff --git a/v4l2-apps/lib/libv4l/TODO b/v4l2-apps/lib/libv4l/TODO deleted file mode 100644 index f3f9ff527..000000000 --- a/v4l2-apps/lib/libv4l/TODO +++ /dev/null @@ -1,12 +0,0 @@ --add support for setting / getting the number of read buffers - --add code to v4l2_read to not return frames more then say 5 seconds old - --add support for libv4l1 for non pure capture (combined capture and overlay) - devices so that atleast CGMBUF emulation (but no conversion, as thats - impossible for overlays) can be done, so that it will no longer be - necessary to implement CGMBUF in the kernel for each driver. - --check v4l2_field during conversion - --add conversion from bgr24 to yuv420 diff --git a/v4l2-apps/lib/libv4l/include/libv4l1.h b/v4l2-apps/lib/libv4l/include/libv4l1.h deleted file mode 100644 index c878cc198..000000000 --- a/v4l2-apps/lib/libv4l/include/libv4l1.h +++ /dev/null @@ -1,73 +0,0 @@ -/* -# (C) 2008 Hans de Goede - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 2.1 of the License, or -# (at your option) any later version. -# -# 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 Lesser General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef __LIBV4L1_H -#define __LIBV4L1_H - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#include -#include - -#if __GNUC__ >= 4 -#define LIBV4L_PUBLIC __attribute__ ((visibility("default"))) -#else -#define LIBV4L_PUBLIC -#endif - -/* Point this to a FILE opened for writing when you want to log error and - status messages to a file, when NULL errors will get send to stderr */ -LIBV4L_PUBLIC extern FILE *v4l1_log_file; - -/* Just like your regular open/close/etc, except that when opening a v4l2 - capture only device, full v4l1 emulation is done including emulating the - often not implemented in v4l2 drivers CGMBUF ioctl and v4l1 style mmap call - in userspace. - - Format conversion is done if necessary when capturing. That is if you - (try to) set a capture format which is not supported by the cam, but is - supported by libv4lconvert then SPICT will succeed and on SYNC / read the - data will be converted for you and returned in the request format. - - Note that currently libv4l1 depends on the kernel v4l1 compatibility layer - for: 1) Devices which are not capture only, 2) Emulation of many basic - v4l1 ioctl's which require no driver specific handling. - - Note that no functionality is added to v4l1 devices, so if for example an - obscure v4l1 device is opened which only supports some weird capture format - then libv4l1 will not be of any help (in this case it would be best to get - the driver converted to v4l2, as v4l2 has been designed to include weird - capture formats, like hw specific bayer compression methods). -*/ - -LIBV4L_PUBLIC int v4l1_open (const char *file, int oflag, ...); -LIBV4L_PUBLIC int v4l1_close(int fd); -LIBV4L_PUBLIC int v4l1_dup(int fd); -LIBV4L_PUBLIC int v4l1_ioctl (int fd, unsigned long int request, ...); -LIBV4L_PUBLIC ssize_t v4l1_read (int fd, void* buffer, size_t n); -LIBV4L_PUBLIC void *v4l1_mmap(void *start, size_t length, int prot, int flags, int fd, - __off64_t offset); -LIBV4L_PUBLIC int v4l1_munmap(void *_start, size_t length); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif diff --git a/v4l2-apps/lib/libv4l/include/libv4l2.h b/v4l2-apps/lib/libv4l/include/libv4l2.h deleted file mode 100644 index b05b57cb6..000000000 --- a/v4l2-apps/lib/libv4l/include/libv4l2.h +++ /dev/null @@ -1,110 +0,0 @@ -/* -# (C) 2008 Hans de Goede - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 2.1 of the License, or -# (at your option) any later version. -# -# 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 Lesser General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef __LIBV4L2_H -#define __LIBV4L2_H - -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#if __GNUC__ >= 4 -#define LIBV4L_PUBLIC __attribute__ ((visibility("default"))) -#else -#define LIBV4L_PUBLIC -#endif - -/* Point this to a FILE opened for writing when you want to log error and - status messages to a file, when NULL errors will get send to stderr */ -LIBV4L_PUBLIC extern FILE *v4l2_log_file; - -/* Just like your regular open/close/etc, except that format conversion is - done if necessary when capturing. That is if you (try to) set a capture - format which is not supported by the cam, but is supported by libv4lconvert, - then the try_fmt / set_fmt will succeed as if the cam supports the format - and on dqbuf / read the data will be converted for you and returned in - the request format. - - Another difference is that you can make v4l2_read() calls even on devices - which do not support the regular read() method. - - Note that libv4l2 normally does not interfere with enum_fmt, so enum_fmt - will still return the actual formats the hardware supports, and not any - formats which may be emulated on top of that. If you pass the - V4L2_ENABLE_ENUM_FMT_EMULATION flag to v4l2_fd_open (as the v4l2convert.so - wrapper does) then enum_fmt will also report support for the formats to - which conversion is possible. - - Note the device name passed to v4l2_open must be of a video4linux2 device, - if it is anything else (including a video4linux1 device), v4l2_open will - fail. -*/ - -LIBV4L_PUBLIC int v4l2_open (const char *file, int oflag, ...); -LIBV4L_PUBLIC int v4l2_close(int fd); -LIBV4L_PUBLIC int v4l2_dup(int fd); -LIBV4L_PUBLIC int v4l2_ioctl (int fd, unsigned long int request, ...); -LIBV4L_PUBLIC ssize_t v4l2_read (int fd, void* buffer, size_t n); -LIBV4L_PUBLIC void *v4l2_mmap(void *start, size_t length, int prot, int flags, int fd, - __off64_t offset); -LIBV4L_PUBLIC int v4l2_munmap(void *_start, size_t length); - - -/* Misc utility functions */ - -/* This function takes a value of 0 - 65535, and then scales that range to - the actual range of the given v4l control id, and then if the cid exists - and is not locked sets the cid to the scaled value. - - Normally returns 0, even if the cid did not exist or was locked, returns - non 0 when an other error occured. */ -LIBV4L_PUBLIC int v4l2_set_control(int fd, int cid, int value); - -/* This function returns a value of 0 - 65535, scaled to from the actual range - of the given v4l control id. when the cid does not exist, could not be - accessed for some reason, or some error occured 0 is returned. */ -LIBV4L_PUBLIC int v4l2_get_control(int fd, int cid); - - -/* "low level" access functions, these functions allow somewhat lower level - access to libv4l2 (currently there only is v4l2_fd_open here) */ - -/* Flags for v4l2_fd_open's v4l2_flags argument */ - -/* Disable all format conversion done by libv4l2 (reduces libv4l2 functionality - to offering v4l2_read() even on devices which don't implement read()) */ -#define V4L2_DISABLE_CONVERSION 0x01 -/* Report not only real but also emulated formats with the ENUM_FMT ioctl */ -#define V4L2_ENABLE_ENUM_FMT_EMULATION 02 - -/* v4l2_fd_open: open an already opened fd for further use through - v4l2lib and possibly modify libv4l2's default behavior through the - v4l2_flags argument. - - Returns fd on success, -1 if the fd is not suitable for use through libv4l2 - (note the fd is left open in this case). */ -LIBV4L_PUBLIC int v4l2_fd_open(int fd, int v4l2_flags); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif diff --git a/v4l2-apps/lib/libv4l/include/libv4lconvert.h b/v4l2-apps/lib/libv4l/include/libv4lconvert.h deleted file mode 100644 index 626c43473..000000000 --- a/v4l2-apps/lib/libv4l/include/libv4lconvert.h +++ /dev/null @@ -1,88 +0,0 @@ -/* -# (C) 2008 Hans de Goede - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 2.1 of the License, or -# (at your option) any later version. -# -# 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 Lesser General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef __LIBV4LCONVERT_H -#define __LIBV4LCONVERT_H - -/* These headers are not needed by us, but by linux/videodev2.h, - which is broken on some systems and doesn't include them itself :( */ -#include -#include -#include -/* end broken header workaround includes */ -#include - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -#if __GNUC__ >= 4 -#define LIBV4L_PUBLIC __attribute__ ((visibility("default"))) -#else -#define LIBV4L_PUBLIC -#endif - -struct v4lconvert_data; - -LIBV4L_PUBLIC struct v4lconvert_data *v4lconvert_create(int fd); -LIBV4L_PUBLIC void v4lconvert_destroy(struct v4lconvert_data *data); - -/* With regards to dest_fmt just like VIDIOC_TRY_FMT, except that the try - format will succeed and return the requested V4L2_PIX_FMT_foo in dest_fmt if - the cam has a format from which v4lconvert can convert to dest_fmt. - The real format to which the cam should be set is returned through src_fmt - when not NULL. */ -LIBV4L_PUBLIC int v4lconvert_try_format(struct v4lconvert_data *data, - struct v4l2_format *dest_fmt, /* in / out */ - struct v4l2_format *src_fmt /* out */ -); - -/* Just like VIDIOC_ENUM_FMT, except that the emulated formats are added at - the end of the list */ -LIBV4L_PUBLIC int v4lconvert_enum_fmt(struct v4lconvert_data *data, struct v4l2_fmtdesc *fmt); - -/* Is conversion necessary or can the app use the data directly? */ -LIBV4L_PUBLIC int v4lconvert_needs_conversion(struct v4lconvert_data *data, - const struct v4l2_format *src_fmt, /* in */ - const struct v4l2_format *dest_fmt); /* in */ - -/* return value of -1 on error, otherwise the amount of bytes written to - dest */ -LIBV4L_PUBLIC int v4lconvert_convert(struct v4lconvert_data *data, - const struct v4l2_format *src_fmt, /* in */ - const struct v4l2_format *dest_fmt, /* in */ - unsigned char *src, int src_size, unsigned char *dest, int dest_size); - -/* get a string describing the last error*/ -LIBV4L_PUBLIC const char *v4lconvert_get_error_message(struct v4lconvert_data *data); - -/* Just like VIDIOC_ENUM_FRAMESIZE, except that the framesizes of emulated - formats can be enumerated as well. */ -LIBV4L_PUBLIC int v4lconvert_enum_framesizes(struct v4lconvert_data *data, - struct v4l2_frmsizeenum *frmsize); - -/* Just like VIDIOC_ENUM_FRAMEINTERVALS, except that the intervals of emulated - formats can be enumerated as well. */ -LIBV4L_PUBLIC int v4lconvert_enum_frameintervals(struct v4lconvert_data *data, - struct v4l2_frmivalenum *frmival); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif diff --git a/v4l2-apps/lib/libv4l/libv4l1/Makefile b/v4l2-apps/lib/libv4l/libv4l1/Makefile deleted file mode 100644 index 27848477e..000000000 --- a/v4l2-apps/lib/libv4l/libv4l1/Makefile +++ /dev/null @@ -1,83 +0,0 @@ -override CPPFLAGS += -I../include -I../../../include -fvisibility=hidden - -CFLAGS := -g -O1 -CFLAGS += -Wall -Wno-unused -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes - -LIBS = -lpthread - -V4L1_OBJS = libv4l1.o log.o -V4L1COMPAT = v4l1compat.so -V4L1COMPAT_O = v4l1compat.o libv4l1.so -TARGETS = $(V4L1_LIB) libv4l1.pc -INCLUDES = ../include/libv4l1.h - -ifeq ($(LINKTYPE),static) -V4L1_LIB = libv4l1.a -else -V4L1_LIB = libv4l1.so -V4L1_OBJS += ../libv4l2/libv4l2.so -TARGETS += $(V4L1COMPAT) -override CPPFLAGS += -fPIC -endif - -ifeq ($(LIB_RELEASE),) -LIB_RELEASE = 0 -endif - -ifeq ($(PREFIX),) -PREFIX = /usr/local -endif - -ifeq ($(LIBDIR),) -LIBDIR = $(PREFIX)/lib -endif - -all: $(TARGETS) - - -$(V4L1_LIB): $(V4L1_OBJS) - -$(V4L1COMPAT): $(V4L1COMPAT_O) $(V4L1_LIB) - -libv4l1.pc: - @echo prefix=$(PREFIX) > libv4l1.pc - @echo libdir=$(LIBDIR) >> libv4l1.pc - @echo >> libv4l1.pc - @echo 'Name: libv4l1' >> libv4l1.pc - @echo 'Description: v4l1 compatibility library' >> libv4l1.pc - @echo 'Version: '$(V4L2_LIB_VERSION) >> libv4l1.pc - @echo 'Requires: libv4l2' >> libv4l1.pc - @echo 'Libs: -L$${libdir} -lv4l1' >> libv4l1.pc - @echo 'Libs.private: -lpthread' >> libv4l1.pc - @echo 'Cflags: -I$${prefix}/include' >> libv4l1.pc - -install: all - mkdir -p $(DESTDIR)$(PREFIX)/include - install -p -m 644 $(INCLUDES) $(DESTDIR)$(PREFIX)/include -ifeq ($(LINKTYPE),static) - mkdir -p $(DESTDIR)$(LIBDIR) - install -m 644 $(V4L1_LIB) $(DESTDIR)$(LIBDIR) -else - mkdir -p $(DESTDIR)$(LIBDIR)/libv4l - install -m 755 $(V4L1_LIB).$(LIB_RELEASE) $(DESTDIR)$(LIBDIR) - cd $(DESTDIR)$(LIBDIR) && \ - ln -f -s $(V4L1_LIB).$(LIB_RELEASE) $(V4L1_LIB) - install -m 755 $(V4L1COMPAT).$(LIB_RELEASE) \ - $(DESTDIR)$(LIBDIR)/libv4l/$(V4L1COMPAT) -endif - mkdir -p $(DESTDIR)$(LIBDIR)/pkgconfig - install -m 644 libv4l1.pc $(DESTDIR)$(LIBDIR)/pkgconfig - -clean:: - rm -f *.a *.so* *.o *.d libv4l1.pc log *~ - -%.o: %.c - $(CC) -c -MMD $(CPPFLAGS) $(CFLAGS) -o $@ $< - -%.so: - $(CC) -shared $(LDFLAGS) -Wl,-soname,$@.$(LIB_RELEASE) -o $@.$(LIB_RELEASE) $^ $(LIBS) - ln -f -s $@.$(LIB_RELEASE) $@ - -%.a: - $(AR) cqs $@ $^ - diff --git a/v4l2-apps/lib/libv4l/libv4l1/libv4l1-priv.h b/v4l2-apps/lib/libv4l/libv4l1/libv4l1-priv.h deleted file mode 100644 index 651599255..000000000 --- a/v4l2-apps/lib/libv4l/libv4l1/libv4l1-priv.h +++ /dev/null @@ -1,83 +0,0 @@ -/* -# (C) 2008 Hans de Goede - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 2.1 of the License, or -# (at your option) any later version. -# -# 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 Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef __LIBV4L1_PRIV_H -#define __LIBV4L1_PRIV_H - -#include -#include - -/* On 32 bits archs we always use mmap2, on 64 bits archs there is no mmap2 */ -#ifdef __NR_mmap2 -#define SYS_mmap2 __NR_mmap2 -#define MMAP2_PAGE_SHIFT 12 -#else -#define SYS_mmap2 SYS_mmap -#define MMAP2_PAGE_SHIFT 0 -#endif - -#define V4L1_MAX_DEVICES 16 -#define V4L1_NO_FRAMES 4 -#define V4L1_FRAME_BUF_SIZE (4096 * 4096) - -extern FILE *v4l1_log_file; - -#define V4L1_LOG_ERR(...) \ - do { \ - if (v4l1_log_file) { \ - fprintf(v4l1_log_file, "libv4l1: error " __VA_ARGS__); \ - fflush(v4l1_log_file); \ - } else \ - fprintf(stderr, "libv4l1: error " __VA_ARGS__); \ - } while(0) - -#define V4L1_LOG_WARN(...) \ - do { \ - if (v4l1_log_file) { \ - fprintf(v4l1_log_file, "libv4l1: warning " __VA_ARGS__); \ - fflush(v4l1_log_file); \ - } else \ - fprintf(stderr, "libv4l1: warning " __VA_ARGS__); \ - } while(0) - -#define V4L1_LOG(...) \ - do { \ - if (v4l1_log_file) { \ - fprintf(v4l1_log_file, "libv4l1: " __VA_ARGS__); \ - fflush(v4l1_log_file); \ - } \ - } while(0) - -struct v4l1_dev_info { - int fd; - int flags; - int open_count; - int v4l1_frame_buf_map_count; - pthread_mutex_t stream_lock; - unsigned int depth; - unsigned int v4l1_pal; /* VIDEO_PALETTE */ - unsigned int v4l2_pixfmt; /* V4L2_PIX_FMT */ - unsigned int min_width, min_height, max_width, max_height; - unsigned int width, height; - unsigned char *v4l1_frame_pointer; -}; - -/* From log.c */ -void v4l1_log_ioctl(unsigned long int request, void *arg, int result); - -#endif diff --git a/v4l2-apps/lib/libv4l/libv4l1/libv4l1.c b/v4l2-apps/lib/libv4l/libv4l1/libv4l1.c deleted file mode 100644 index 797c8768a..000000000 --- a/v4l2-apps/lib/libv4l/libv4l1/libv4l1.c +++ /dev/null @@ -1,837 +0,0 @@ -/* -# libv4l1 userspace v4l1 api emulation for v4l2 devices - -# (C) 2008 Hans de Goede - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 2.1 of the License, or -# (at your option) any later version. -# -# 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 Lesser General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* MAKING CHANGES TO THIS FILE?? READ THIS FIRST!!! - - Important note to people making changes to this file: All functions - (v4l1_close, v4l1_ioctl, etc.) are designed to function as their regular - counterpart when they get passed a fd that is not "registered" by libv4l1, - there are 2 reasons for this: - 1) This allows us to get completely out of the way when dealing with non - capture only devices, or non v4l2 devices. - 2) libv4l1 is the base of the v4l1compat.so wrapper lib, which is a .so - which can be LD_PRELOAD-ed and the overrules the libc's open/close/etc, - and when opening /dev/videoX or /dev/v4l/ calls v4l1_open. Because we - behave as the regular counterpart when the fd is not known (instead of - say throwing an error), v4l1compat.so can simply call the v4l1_ prefixed - function for all wrapped functions. This way the wrapper does not have - to keep track of which fd's are being handled by libv4l1, as libv4l1 - already keeps track of this itself. - - This also means that libv4l1 may not use any of the regular functions - it mimics, as for example open could be a symbol in v4l1compat.so, which - in turn will call v4l1_open, so therefor v4l1_open (for example) may not - use the regular open()! -*/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -/* These headers are not needed by us, but by linux/videodev2.h, - which is broken on some systems and doesn't include them itself :( */ -#include -#include -#include -/* end broken header workaround includes */ -#include -#include -#include -#include "libv4l1.h" -#include "libv4l1-priv.h" - -#define V4L1_SUPPORTS_ENUMINPUT 0x01 -#define V4L1_SUPPORTS_ENUMSTD 0x02 -#define V4L1_PIX_FMT_TOUCHED 0x04 -#define V4L1_PIX_SIZE_TOUCHED 0x08 - -static pthread_mutex_t v4l1_open_mutex = PTHREAD_MUTEX_INITIALIZER; -static struct v4l1_dev_info devices[V4L1_MAX_DEVICES] = { { .fd = -1 }, - { .fd = -1 }, { .fd = -1 }, { .fd = -1 }, { .fd = -1 }, { .fd = -1 }, - { .fd = -1 }, { .fd = -1 }, { .fd = -1 }, { .fd = -1 }, { .fd = -1 }, - { .fd = -1 }, { .fd = -1 }, { .fd = -1 }, { .fd = -1 }, { .fd = -1 }}; -static int devices_used = 0; - -static unsigned int palette_to_pixelformat(unsigned int palette) -{ - switch (palette) { - case VIDEO_PALETTE_GREY: - return V4L2_PIX_FMT_GREY; - case VIDEO_PALETTE_RGB555: - return V4L2_PIX_FMT_RGB555; - case VIDEO_PALETTE_RGB565: - return V4L2_PIX_FMT_RGB565; - case VIDEO_PALETTE_RGB24: - return V4L2_PIX_FMT_BGR24; - case VIDEO_PALETTE_RGB32: - return V4L2_PIX_FMT_BGR32; - case VIDEO_PALETTE_YUYV: - return V4L2_PIX_FMT_YUYV; - case VIDEO_PALETTE_YUV422: - return V4L2_PIX_FMT_YUYV; - case VIDEO_PALETTE_UYVY: - return V4L2_PIX_FMT_UYVY; - case VIDEO_PALETTE_YUV410P: - return V4L2_PIX_FMT_YUV410; - case VIDEO_PALETTE_YUV420: - case VIDEO_PALETTE_YUV420P: - return V4L2_PIX_FMT_YUV420; - case VIDEO_PALETTE_YUV411P: - return V4L2_PIX_FMT_YUV411P; - case VIDEO_PALETTE_YUV422P: - return V4L2_PIX_FMT_YUV422P; - } - return 0; -} - -static unsigned int pixelformat_to_palette(unsigned int pixelformat) -{ - switch (pixelformat) { - case V4L2_PIX_FMT_GREY: - return VIDEO_PALETTE_GREY; - case V4L2_PIX_FMT_RGB555: - return VIDEO_PALETTE_RGB555; - case V4L2_PIX_FMT_RGB565: - return VIDEO_PALETTE_RGB565; - case V4L2_PIX_FMT_BGR24: - return VIDEO_PALETTE_RGB24; - case V4L2_PIX_FMT_BGR32: - return VIDEO_PALETTE_RGB32; - case V4L2_PIX_FMT_YUYV: - return VIDEO_PALETTE_YUYV; - case V4L2_PIX_FMT_UYVY: - return VIDEO_PALETTE_UYVY; - case V4L2_PIX_FMT_YUV410: - case V4L2_PIX_FMT_YUV420: - return VIDEO_PALETTE_YUV420P; - case V4L2_PIX_FMT_YUV411P: - return VIDEO_PALETTE_YUV411P; - case V4L2_PIX_FMT_YUV422P: - return VIDEO_PALETTE_YUV422P; - } - return 0; -} - -static int v4l1_set_format(int index, unsigned int width, - unsigned int height, int v4l1_pal, int width_height_may_differ) -{ - int result; - unsigned int v4l2_pixfmt; - struct v4l2_format fmt2 = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE }; - - if (v4l1_pal != -1) { - v4l2_pixfmt = palette_to_pixelformat(v4l1_pal); - if (!v4l2_pixfmt) { - V4L1_LOG("Unknown v4l1 palette number: %d\n", v4l1_pal); - errno = EINVAL; - return -1; - } - } else { - v4l2_pixfmt = devices[index].v4l2_pixfmt; - v4l1_pal = devices[index].v4l1_pal; - } - - /* Do we need to change the resolution / format ? */ - if (width == devices[index].width && height == devices[index].height && - v4l2_pixfmt == devices[index].v4l2_pixfmt) - return 0; - - /* Get current settings, apply our changes and try the new setting */ - if ((result = v4l2_ioctl(devices[index].fd, VIDIOC_G_FMT, &fmt2))) { - int saved_err = errno; - V4L1_LOG_ERR("getting pixformat: %s\n", strerror(errno)); - errno = saved_err; - return result; - } - - fmt2.fmt.pix.pixelformat = v4l2_pixfmt; - fmt2.fmt.pix.width = width; - fmt2.fmt.pix.height = height; - if ((result = v4l2_ioctl(devices[index].fd, VIDIOC_TRY_FMT, &fmt2))) - { - int saved_err = errno; - V4L1_LOG("error trying pixformat: %s\n", strerror(errno)); - errno = saved_err; - return result; - } - - /* Check if we get what we asked for */ - if (fmt2.fmt.pix.pixelformat != v4l2_pixfmt || (!width_height_may_differ && - (fmt2.fmt.pix.width != width || fmt2.fmt.pix.height != height))) { - V4L1_LOG("requested fmt, width, height combo not available\n"); - errno = EINVAL; - return -1; - } - - /* Maybe after the TRY_FMT things haven't changed after all ? */ - if (fmt2.fmt.pix.width == devices[index].width && - fmt2.fmt.pix.height == devices[index].height && - fmt2.fmt.pix.pixelformat == devices[index].v4l2_pixfmt) { - devices[index].v4l1_pal = v4l1_pal; - return 0; - } - - if ((result = v4l2_ioctl(devices[index].fd, VIDIOC_S_FMT, &fmt2))) { - int saved_err = errno; - V4L1_LOG_ERR("setting pixformat: %s\n", strerror(errno)); - errno = saved_err; - return result; - } - - devices[index].width = fmt2.fmt.pix.width; - devices[index].height = fmt2.fmt.pix.height; - devices[index].v4l2_pixfmt = v4l2_pixfmt; - devices[index].v4l1_pal = v4l1_pal; - devices[index].depth = ((fmt2.fmt.pix.bytesperline << 3) + - (fmt2.fmt.pix.width - 1)) / fmt2.fmt.pix.width; - - return result; -} - -static void v4l1_find_min_and_max_size(int index, struct v4l2_format *fmt2) -{ - int i; - struct v4l2_fmtdesc fmtdesc2 = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE }; - - devices[index].min_width = -1; - devices[index].min_height = -1; - devices[index].max_width = 0; - devices[index].max_height = 0; - - for (i = 0; ; i++) { - fmtdesc2.index = i; - - if (syscall(SYS_ioctl, devices[index].fd, VIDIOC_ENUM_FMT, &fmtdesc2)) - break; - - fmt2->fmt.pix.pixelformat = fmtdesc2.pixelformat; - fmt2->fmt.pix.width = 48; - fmt2->fmt.pix.height = 32; - - if (syscall(SYS_ioctl, devices[index].fd, VIDIOC_TRY_FMT, fmt2) == 0) { - if (fmt2->fmt.pix.width < devices[index].min_width) - devices[index].min_width = fmt2->fmt.pix.width; - if (fmt2->fmt.pix.height < devices[index].min_height) - devices[index].min_height = fmt2->fmt.pix.height; - } - - fmt2->fmt.pix.pixelformat = fmtdesc2.pixelformat; - fmt2->fmt.pix.width = 100000; - fmt2->fmt.pix.height = 100000; - - if (syscall(SYS_ioctl, devices[index].fd, VIDIOC_TRY_FMT, fmt2) == 0) { - if (fmt2->fmt.pix.width > devices[index].max_width) - devices[index].max_width = fmt2->fmt.pix.width; - if (fmt2->fmt.pix.height > devices[index].max_height) - devices[index].max_height = fmt2->fmt.pix.height; - } - } -} - - -int v4l1_open (const char *file, int oflag, ...) -{ - int index, fd; - char *lfname; - struct v4l2_capability cap2; - struct v4l2_format fmt2; - struct v4l2_input input2; - struct v4l2_standard standard2; - int v4l_device = 0; - - /* check if we're opening a video4linux2 device */ - if (!strncmp(file, "/dev/video", 10) || !strncmp(file, "/dev/v4l/", 9)) { - /* Some apps open the device read only, but we need rw rights as the - buffers *MUST* be mapped rw */ - oflag = (oflag & ~O_ACCMODE) | O_RDWR; - v4l_device = 1; - } - - /* original open code */ - if (oflag & O_CREAT) - { - va_list ap; - mode_t mode; - - va_start (ap, oflag); - mode = va_arg (ap, mode_t); - - fd = syscall(SYS_open, file, oflag, mode); - - va_end(ap); - } else - fd = syscall(SYS_open, file, oflag); - /* end of original open code */ - - if (fd == -1 || !v4l_device) - return fd; - - /* check that this is an v4l2 device, no need to emulate v4l1 on - a v4l1 device */ - if (syscall(SYS_ioctl, fd, VIDIOC_QUERYCAP, &cap2)) - return fd; - - /* IMPROVEME */ - /* we only support simple video capture devices which do not do overlay */ - if ((cap2.capabilities & 0x0F) != V4L2_CAP_VIDEO_CAPTURE) - return fd; - - /* If no log file was set by the app, see if one was specified through the - environment */ - if (!v4l1_log_file && (lfname = getenv("LIBV4L1_LOG_FILENAME"))) - v4l1_log_file = fopen(lfname, "w"); - - /* redirect libv4l2 log messages to our logfile if no libv4l2 logfile is - specified */ - if (!v4l2_log_file) - v4l2_log_file = v4l1_log_file; - - /* Get initial width, height and pixelformat */ - fmt2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (syscall(SYS_ioctl, fd, VIDIOC_G_FMT, &fmt2)) { - int saved_err = errno; - V4L1_LOG_ERR("getting pixformat: %s\n", strerror(errno)); - syscall(SYS_close, fd); - errno = saved_err; - return -1; - } - - /* Register with libv4l2, as we use that todo format conversion and read() - emulation for us */ - if (v4l2_fd_open(fd, V4L2_ENABLE_ENUM_FMT_EMULATION) == -1) { - int saved_err = errno; - syscall(SYS_close, fd); - errno = saved_err; - return -1; - } - - /* So we have a device on which we can (and want to) emulate v4l1, register - it in our devices array */ - pthread_mutex_lock(&v4l1_open_mutex); - for (index = 0; index < V4L1_MAX_DEVICES; index++) - if(devices[index].fd == -1) { - devices[index].fd = fd; - break; - } - pthread_mutex_unlock(&v4l1_open_mutex); - - if (index == V4L1_MAX_DEVICES) { - V4L1_LOG_ERR("attempting to open more then %d video devices\n", - V4L1_MAX_DEVICES); - v4l2_close(fd); - errno = EBUSY; - return -1; - } - - if (index >= devices_used) - devices_used = index + 1; - - devices[index].flags = 0; - devices[index].open_count = 1; - devices[index].v4l1_frame_buf_map_count = 0; - devices[index].v4l1_frame_pointer = MAP_FAILED; - devices[index].width = fmt2.fmt.pix.width; - devices[index].height = fmt2.fmt.pix.height; - devices[index].v4l2_pixfmt = fmt2.fmt.pix.pixelformat; - devices[index].v4l1_pal = pixelformat_to_palette(fmt2.fmt.pix.pixelformat); - devices[index].depth = ((fmt2.fmt.pix.bytesperline << 3) + - (fmt2.fmt.pix.width - 1)) / fmt2.fmt.pix.width; - - v4l1_find_min_and_max_size(index, &fmt2); - - /* Check ENUM_INPUT and ENUM_STD support */ - input2.index = 0; - if (v4l2_ioctl(fd, VIDIOC_ENUMINPUT, &input2) == 0) - devices[index].flags |= V4L1_SUPPORTS_ENUMINPUT; - - standard2.index = 0; - if (v4l2_ioctl(fd, VIDIOC_ENUMSTD, &input2) == 0) - devices[index].flags |= V4L1_SUPPORTS_ENUMSTD; - - V4L1_LOG("open: %d\n", fd); - - return fd; -} - -/* Is this an fd for which we are emulating v4l1 ? */ -static int v4l1_get_index(int fd) -{ - int index; - - /* We never handle fd -1 */ - if (fd == -1) - return -1; - - for (index = 0; index < devices_used; index++) - if (devices[index].fd == fd) - break; - - if (index == devices_used) - return -1; - - return index; -} - - -int v4l1_close(int fd) { - int index, result; - - if ((index = v4l1_get_index(fd)) == -1) - return syscall(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 - syscall(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; -} - -int v4l1_dup(int fd) -{ - int index; - - if ((index = v4l1_get_index(fd)) == -1) - return syscall(SYS_dup, fd); - - devices[index].open_count++; - - return v4l2_dup(fd); -} - - -int v4l1_ioctl (int fd, unsigned long int request, ...) -{ - void *arg; - va_list ap; - int result, index, saved_err, stream_locked = 0; - - va_start (ap, request); - arg = va_arg (ap, void *); - va_end (ap); - - if ((index = v4l1_get_index(fd)) == -1) - return syscall(SYS_ioctl, fd, request, arg); - - /* Appearantly the kernel and / or glibc ignore the 32 most significant bits - when long = 64 bits, and some applications pass an int holding the req to - ioctl, causing it to get sign extended, depending upon this behavior */ - request = (unsigned int)request; - - /* do we need to take the stream lock for this ioctl? */ - switch (request) { - case VIDIOCSPICT: - case VIDIOCGPICT: - case VIDIOCSWIN: - case VIDIOCGWIN: - case VIDIOCGMBUF: - case VIDIOCMCAPTURE: - case VIDIOCSYNC: - case VIDIOC_S_FMT: - pthread_mutex_lock(&devices[index].stream_lock); - stream_locked = 1; - } - - switch (request) { - - case VIDIOCGCAP: - { - struct video_capability *cap = arg; - - result = syscall(SYS_ioctl, fd, request, arg); - - /* override kernel v4l1 compat min / max size with our own more - accurate values */ - cap->minwidth = devices[index].min_width; - cap->minheight = devices[index].min_height; - cap->maxwidth = devices[index].max_width; - cap->maxheight = devices[index].max_height; - } - break; - - case VIDIOCSPICT: - { - struct video_picture *pic = arg; - - devices[index].flags |= V4L1_PIX_FMT_TOUCHED; - - v4l2_set_control(fd, V4L2_CID_BRIGHTNESS, pic->brightness); - v4l2_set_control(fd, V4L2_CID_HUE, pic->hue); - v4l2_set_control(fd, V4L2_CID_CONTRAST, pic->contrast); - v4l2_set_control(fd, V4L2_CID_SATURATION, pic->colour); - v4l2_set_control(fd, V4L2_CID_WHITENESS, pic->whiteness); - - result = v4l1_set_format(index, devices[index].width, - devices[index].height, pic->palette, 0); - } - break; - - case VIDIOCGPICT: - { - struct video_picture *pic = arg; - - /* If our v4l2 pixformat has no corresponding v4l1 palette, and the - app has not touched the pixformat sofar, try setting a palette which - does (and which we emulate when necessary) so that applications - which just query the current format and then take whatever they get - will work */ - if (!(devices[index].flags & V4L1_PIX_FMT_TOUCHED) && - !pixelformat_to_palette(devices[index].v4l2_pixfmt)) - v4l1_set_format(index, devices[index].width, - devices[index].height, - VIDEO_PALETTE_RGB24, - (devices[index].flags & - V4L1_PIX_SIZE_TOUCHED) ? 0 : 1); - - devices[index].flags |= V4L1_PIX_FMT_TOUCHED; - - pic->depth = devices[index].depth; - pic->palette = devices[index].v4l1_pal; - pic->hue = v4l2_get_control(devices[index].fd, V4L2_CID_HUE); - pic->colour = v4l2_get_control(devices[index].fd, V4L2_CID_SATURATION); - pic->contrast = v4l2_get_control(devices[index].fd, V4L2_CID_CONTRAST); - pic->whiteness = v4l2_get_control(devices[index].fd, - V4L2_CID_WHITENESS); - pic->brightness = v4l2_get_control(devices[index].fd, - V4L2_CID_BRIGHTNESS); - - result = 0; - } - break; - - case VIDIOCSWIN: - { - struct video_window *win = arg; - - devices[index].flags |= V4L1_PIX_SIZE_TOUCHED; - - result = v4l1_set_format(index, win->width, win->height, -1, 1); - if (result == 0) { - win->width = devices[index].width; - win->height = devices[index].height; - } - } - break; - - case VIDIOCGWIN: - devices[index].flags |= V4L1_PIX_SIZE_TOUCHED; - result = syscall(SYS_ioctl, fd, request, arg); - break; - - case VIDIOCGCHAN: - { - struct v4l2_input input2; - struct video_channel *chan = arg; - - if ((devices[index].flags & V4L1_SUPPORTS_ENUMINPUT) && - (devices[index].flags & V4L1_SUPPORTS_ENUMSTD)) { - result = syscall(SYS_ioctl, fd, request, arg); - break; - } - - /* Set some defaults */ - chan->tuners = 0; - chan->flags = 0; - chan->type = VIDEO_TYPE_CAMERA; - chan->norm = 0; - - /* In case of no ENUMSTD support, ignore the norm member of the - channel struct */ - if (devices[index].flags & V4L1_SUPPORTS_ENUMINPUT) { - input2.index = chan->channel; - result = v4l2_ioctl(fd, VIDIOC_ENUMINPUT, &input2); - if (result == 0) { - snprintf(chan->name, sizeof(chan->name), "%s", (char*)input2.name); - if (input2.type == V4L2_INPUT_TYPE_TUNER) { - chan->tuners = 1; - chan->type = VIDEO_TYPE_TV; - chan->flags = VIDEO_VC_TUNER; - } - } - break; - } - - /* No ENUMINPUT support, fake it (assume its a Camera in this case) */ - if (chan->channel == 0) { - snprintf(chan->name, sizeof(chan->name), "Camera"); - result = 0; - } else { - errno = EINVAL; - result = -1; - } - } - break; - - case VIDIOCSCHAN: - { - struct video_channel *chan = arg; - if ((devices[index].flags & V4L1_SUPPORTS_ENUMINPUT) && - (devices[index].flags & V4L1_SUPPORTS_ENUMSTD)) { - result = syscall(SYS_ioctl, fd, request, arg); - break; - } - /* In case of no ENUMSTD support, ignore the norm member of the - channel struct */ - if (devices[index].flags & V4L1_SUPPORTS_ENUMINPUT) { - result = v4l2_ioctl(fd, VIDIOC_S_INPUT, &chan->channel); - break; - } - /* No ENUMINPUT support, fake it (assume its a Camera in this case) */ - if (chan->channel == 0) { - result = 0; - } else { - errno = EINVAL; - result = -1; - } - } - break; - - case VIDIOCGMBUF: - /* When VIDIOCGMBUF is done, we don't necessarrily know the format the - application wants yet (with some apps this is passed for the first - time through VIDIOCMCAPTURE), so we just create an anonymous mapping - that should be large enough to hold any sort of frame. Note this only - takes virtual memory, and does not use memory until actually used. */ - { - int i; - struct video_mbuf *mbuf = arg; - - mbuf->size = V4L1_NO_FRAMES * V4L1_FRAME_BUF_SIZE; - mbuf->frames = V4L1_NO_FRAMES; - for (i = 0; i < mbuf->frames; i++) { - mbuf->offsets[i] = i * V4L1_FRAME_BUF_SIZE; - } - - if (devices[index].v4l1_frame_pointer == MAP_FAILED) { - devices[index].v4l1_frame_pointer = (void *)syscall(SYS_mmap2, NULL, - (size_t)mbuf->size, - PROT_READ|PROT_WRITE, - MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); - if (devices[index].v4l1_frame_pointer == MAP_FAILED) { - saved_err = errno; - V4L1_LOG_ERR("allocating v4l1 buffer: %s\n", strerror(errno)); - errno = saved_err; - result = -1; - break; - } - V4L1_LOG("allocated v4l1 buffer @ %p\n", - devices[index].v4l1_frame_pointer); - } - result = 0; - } - break; - - case VIDIOCMCAPTURE: - { - struct video_mmap *map = arg; - - devices[index].flags |= V4L1_PIX_FMT_TOUCHED | - V4L1_PIX_SIZE_TOUCHED; - - result = v4l1_set_format(index, map->width, map->height, - map->format, 0); - } - break; - - case VIDIOCSYNC: - { - int *frame_index = arg; - - if (devices[index].v4l1_frame_pointer == MAP_FAILED || - *frame_index < 0 || *frame_index >= V4L1_NO_FRAMES) { - errno = EINVAL; - result = -1; - break; - } - - result = v4l2_read(devices[index].fd, - devices[index].v4l1_frame_pointer + - *frame_index * V4L1_FRAME_BUF_SIZE, - V4L1_FRAME_BUF_SIZE); - result = (result > 0) ? 0:result; - } - break; - - /* We are passing through v4l2 calls to libv4l2 for applications which are - using v4l2 through libv4l1 (possible with the v4l1compat.so wrapper). - - So the application could be calling VIDIOC_S_FMT, in this case update - our own bookkeeping of the cam's format. Note that this really only is - relevant if an application is mixing and matching v4l1 and v4l2 calls, - which is crazy, but better safe then sorry. */ - case VIDIOC_S_FMT: - { - struct v4l2_format *fmt2 = arg; - - result = v4l2_ioctl(fd, request, arg); - - if (result == 0 && fmt2->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - if (devices[index].v4l2_pixfmt != fmt2->fmt.pix.pixelformat) { - devices[index].v4l2_pixfmt = fmt2->fmt.pix.pixelformat; - devices[index].v4l1_pal = - pixelformat_to_palette(fmt2->fmt.pix.pixelformat); - } - devices[index].width = fmt2->fmt.pix.width; - devices[index].height = fmt2->fmt.pix.height; - } - } - break; - - default: - /* Pass through libv4l2 for applications which are using v4l2 through - libv4l1 (this can happen with the v4l1compat.so wrapper preloaded */ - result = v4l2_ioctl(fd, request, arg); - } - - if (stream_locked) - pthread_mutex_unlock(&devices[index].stream_lock); - - saved_err = errno; - v4l1_log_ioctl(request, arg, result); - errno = saved_err; - - return result; -} - - -ssize_t v4l1_read(int fd, void* buffer, size_t n) -{ - int index; - ssize_t result; - - if ((index = v4l1_get_index(fd)) == -1) - return syscall(SYS_read, fd, buffer, n); - - pthread_mutex_lock(&devices[index].stream_lock); - result = v4l2_read(fd, buffer, n); - pthread_mutex_unlock(&devices[index].stream_lock); - - return result; -} - - -void *v4l1_mmap(void *start, size_t length, int prot, int flags, int fd, - __off64_t offset) -{ - int index; - void *result; - - /* Check if the mmap data matches our answer to VIDIOCGMBUF, if not - pass through libv4l2 for applications which are using v4l2 through - libv4l1 (this can happen with the v4l1compat.so wrapper preloaded */ - if ((index = v4l1_get_index(fd)) == -1 || start || offset || - length != (V4L1_NO_FRAMES * V4L1_FRAME_BUF_SIZE)) - return v4l2_mmap(start, length, prot, flags, fd, offset); - - - pthread_mutex_lock(&devices[index].stream_lock); - - /* It could be that we get called with an mmap which seems to match what - we expect, but no VIDIOCGMBUF has been done yet, then it is certainly not - for us so pass it through */ - if (devices[index].v4l1_frame_pointer == MAP_FAILED) { - result = v4l2_mmap(start, length, prot, flags, fd, offset); - goto leave; - } - - devices[index].v4l1_frame_buf_map_count++; - - V4L1_LOG("v4l1 buffer @ %p mapped by application\n", - devices[index].v4l1_frame_pointer); - - result = devices[index].v4l1_frame_pointer; - -leave: - pthread_mutex_unlock(&devices[index].stream_lock); - - return result; -} - -int v4l1_munmap(void *_start, size_t length) -{ - int index; - unsigned char *start = _start; - - /* Is this memory ours? */ - if (start != MAP_FAILED && - length == (V4L1_FRAME_BUF_SIZE * V4L1_NO_FRAMES)) { - for (index = 0; index < devices_used; index++) - if (devices[index].fd != -1 && - start == devices[index].v4l1_frame_pointer) - break; - - if (index != devices_used) { - int unmapped = 0; - - pthread_mutex_lock(&devices[index].stream_lock); - - /* Redo our checks now that we have the lock, things may have changed */ - if (start == devices[index].v4l1_frame_pointer) { - if (devices[index].v4l1_frame_buf_map_count > 0) - devices[index].v4l1_frame_buf_map_count--; - - unmapped = 1; - } - - pthread_mutex_unlock(&devices[index].stream_lock); - - if (unmapped) { - V4L1_LOG("v4l1 buffer munmap %p, %d\n", start, (int)length); - return 0; - } - } - } - - V4L1_LOG("v4l1 unknown munmap %p, %d\n", start, (int)length); - - /* If not pass through libv4l2 for applications which are using v4l2 through - libv4l1 (this can happen with the v4l1compat.so wrapper preloaded */ - return v4l2_munmap(start, length); -} diff --git a/v4l2-apps/lib/libv4l/libv4l1/log.c b/v4l2-apps/lib/libv4l/libv4l1/log.c deleted file mode 100644 index 9ff0cea46..000000000 --- a/v4l2-apps/lib/libv4l/libv4l1/log.c +++ /dev/null @@ -1,145 +0,0 @@ -/* -# (C) 2008 Hans de Goede - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 2.1 of the License, or -# (at your option) any later version. -# -# 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 Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include -#include -#include -/* These headers are not needed by us, but by linux/videodev2.h, - which is broken on some systems and doesn't include them itself :( */ -#include -#include -/* end broken header workaround includes */ -#include -#include "libv4l1-priv.h" - -#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0])) - -FILE *v4l1_log_file = NULL; - -static const char *v4l1_ioctls[] = { - [_IOC_NR(VIDIOCGCAP)] = "VIDIOCGCAP", - [_IOC_NR(VIDIOCGCHAN)] = "VIDIOCGCHAN", - [_IOC_NR(VIDIOCSCHAN)] = "VIDIOCSCHAN", - [_IOC_NR(VIDIOCGTUNER)] = "VIDIOCGTUNER", - [_IOC_NR(VIDIOCSTUNER)] = "VIDIOCSTUNER", - [_IOC_NR(VIDIOCGPICT)] = "VIDIOCGPICT", - [_IOC_NR(VIDIOCSPICT)] = "VIDIOCSPICT", - [_IOC_NR(VIDIOCCAPTURE)] = "VIDIOCCAPTURE", - [_IOC_NR(VIDIOCGWIN)] = "VIDIOCGWIN", - [_IOC_NR(VIDIOCSWIN)] = "VIDIOCSWIN", - [_IOC_NR(VIDIOCGFBUF)] = "VIDIOCGFBUF", - [_IOC_NR(VIDIOCSFBUF)] = "VIDIOCSFBUF", - [_IOC_NR(VIDIOCKEY)] = "VIDIOCKEY", - [_IOC_NR(VIDIOCGFREQ)] = "VIDIOCGFREQ", - [_IOC_NR(VIDIOCSFREQ)] = "VIDIOCSFREQ", - [_IOC_NR(VIDIOCGAUDIO)] = "VIDIOCGAUDIO", - [_IOC_NR(VIDIOCSAUDIO)] = "VIDIOCSAUDIO", - [_IOC_NR(VIDIOCSYNC)] = "VIDIOCSYNC", - [_IOC_NR(VIDIOCMCAPTURE)] = "VIDIOCMCAPTURE", - [_IOC_NR(VIDIOCGMBUF)] = "VIDIOCGMBUF", - [_IOC_NR(VIDIOCGUNIT)] = "VIDIOCGUNIT", - [_IOC_NR(VIDIOCGCAPTURE)] = "VIDIOCGCAPTURE", - [_IOC_NR(VIDIOCSCAPTURE)] = "VIDIOCSCAPTURE", - [_IOC_NR(VIDIOCSPLAYMODE)] = "VIDIOCSPLAYMODE", - [_IOC_NR(VIDIOCSWRITEMODE)] = "VIDIOCSWRITEMODE", - [_IOC_NR(VIDIOCGPLAYINFO)] = "VIDIOCGPLAYINFO", - [_IOC_NR(VIDIOCSMICROCODE)] = "VIDIOCSMICROCODE", - [_IOC_NR(VIDIOCGVBIFMT)] = "VIDIOCGVBIFMT", - [_IOC_NR(VIDIOCSVBIFMT)] = "VIDIOCSVBIFMT", -}; - -void v4l1_log_ioctl(unsigned long int request, void *arg, int result) -{ - const char *ioctl_str = "unknown"; - char buf[40]; - - if (!v4l1_log_file) - return; - - /* Don't log v4l2 ioctl's as unknown we pass them to libv4l2 which will - log them for us */ - if (_IOC_TYPE(request) == 'V') - return; - - if (_IOC_TYPE(request) == 'v' && _IOC_NR(request) < ARRAY_SIZE(v4l1_ioctls)) - ioctl_str = v4l1_ioctls[_IOC_NR(request)]; - else { - snprintf(buf, sizeof(buf), "unknown request: %c %d\n", - (int)_IOC_TYPE(request), (int)_IOC_NR(request)); - ioctl_str = buf; - } - - fprintf(v4l1_log_file, "request == %s\n", ioctl_str); - - switch(request) - { - case VIDIOCGCAP:fprintf(v4l1_log_file,"name %s\n",( (struct video_capability*)arg)->name ); - fprintf(v4l1_log_file,"type %d\n",( (struct video_capability*)arg)->type ); - fprintf(v4l1_log_file,"channels %d\n",( (struct video_capability*)arg)->channels ); - fprintf(v4l1_log_file,"audios %d\n",( (struct video_capability*)arg)->audios ); - fprintf(v4l1_log_file,"maxwidth %d\n",( (struct video_capability*)arg)->maxwidth ); - fprintf(v4l1_log_file,"maxheight %d\n",( (struct video_capability*)arg)->maxheight ); - fprintf(v4l1_log_file,"minwidth %d\n",( (struct video_capability*)arg)->minwidth ); - fprintf(v4l1_log_file,"minheight %d\n",( (struct video_capability*)arg)->minheight ); - break; - case VIDIOCGWIN: - case VIDIOCSWIN: - fprintf(v4l1_log_file,"width\t%u\n", - ((struct video_window *)arg)->width); - fprintf(v4l1_log_file,"height\t%u\n", - ((struct video_window *)arg)->height); - break; - - case VIDIOCGCHAN: - case VIDIOCSCHAN: - fprintf(v4l1_log_file,"channel %d\n",( (struct video_channel*)arg)->channel ); - fprintf(v4l1_log_file,"name %s\n",( (struct video_channel*)arg)->name ); - break; - - case VIDIOCGPICT: - case VIDIOCSPICT: - fprintf(v4l1_log_file,"brightness %d\n",( (int)((struct video_picture*)arg)->brightness) ); - fprintf(v4l1_log_file,"hue %d\n",( (int)((struct video_picture*)arg)->hue) ); - fprintf(v4l1_log_file,"colour %d\n",( (int)((struct video_picture*)arg)->colour) ); - fprintf(v4l1_log_file,"contrast %d\n",( (int)((struct video_picture*)arg)->contrast) ); - fprintf(v4l1_log_file,"whiteness %d\n",( (int)((struct video_picture*)arg)->whiteness) ); - fprintf(v4l1_log_file,"depth %d\n",( (int)((struct video_picture*)arg)->depth) ); - fprintf(v4l1_log_file,"palette %d\n",( (int)((struct video_picture*)arg)->palette) ); - break; - - case VIDIOCCAPTURE: fprintf(v4l1_log_file,"on/off? %d\n", *((int *)arg) ); - break; - - case VIDIOCSYNC: fprintf(v4l1_log_file,"sync %d\n", *((int *)arg) ); - break; - - case VIDIOCMCAPTURE: - fprintf(v4l1_log_file,"frame %u\n",( (struct video_mmap*)arg)->frame ); - fprintf(v4l1_log_file,"width %d\n",( (struct video_mmap*)arg)->width ); - fprintf(v4l1_log_file,"height %d\n",( (struct video_mmap*)arg)->height ); - fprintf(v4l1_log_file,"format %u\n",( (struct video_mmap*)arg)->format ); - break; - - case VIDIOCGMBUF: - fprintf(v4l1_log_file,"size %d\n",( (struct video_mbuf*)arg)->size ); - fprintf(v4l1_log_file,"frames %d\n",( (struct video_mbuf*)arg)->frames ); - break; - } - fprintf(v4l1_log_file, "result == %d\n", result); - fflush(v4l1_log_file); -} diff --git a/v4l2-apps/lib/libv4l/libv4l1/v4l1compat.c b/v4l2-apps/lib/libv4l/libv4l1/v4l1compat.c deleted file mode 100644 index e4293d2f9..000000000 --- a/v4l2-apps/lib/libv4l/libv4l1/v4l1compat.c +++ /dev/null @@ -1,127 +0,0 @@ -/* -# open/close/ioctl/mmap/munmap library call wrapper doing v4l1 api emulation -# for v4l2 devices - -# (C) 2008 Hans de Goede - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 2.1 of the License, or -# (at your option) any later version. -# -# 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 Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#define _LARGEFILE64_SOURCE 1 - -#include -#include -#include -#include - -#include -#include - -/* Check that open/read/mmap is not a define */ -#if defined open || defined read || defined mmap -#error open/read/mmap is a prepocessor macro !! -#endif - -#if __GNUC__ >= 4 -#define LIBV4L_PUBLIC __attribute__ ((visibility("default"))) -#else -#define LIBV4L_PUBLIC -#endif - -LIBV4L_PUBLIC int open (const char *file, int oflag, ...) -{ - int fd; - - if (oflag & O_CREAT) - { - va_list ap; - mode_t mode; - - va_start (ap, oflag); - mode = va_arg (ap, mode_t); - - fd = v4l1_open(file, oflag, mode); - - va_end(ap); - } else - fd = v4l1_open(file, oflag); - - return fd; -} - -LIBV4L_PUBLIC int open64 (const char *file, int oflag, ...) -{ - int fd; - - if (oflag & O_CREAT) - { - va_list ap; - mode_t mode; - - va_start (ap, oflag); - mode = va_arg (ap, mode_t); - - fd = v4l1_open(file, oflag | O_LARGEFILE, mode); - - va_end(ap); - } else - fd = v4l1_open(file, oflag | O_LARGEFILE); - - return fd; -} - -LIBV4L_PUBLIC int close(int fd) { - return v4l1_close(fd); -} - -LIBV4L_PUBLIC int dup(int fd) -{ - return v4l1_dup(fd); -} - -LIBV4L_PUBLIC int ioctl (int fd, unsigned long int request, ...) -{ - void *arg; - va_list ap; - - va_start (ap, request); - arg = va_arg (ap, void *); - va_end (ap); - - return v4l1_ioctl (fd, request, arg); -} - -LIBV4L_PUBLIC ssize_t read(int fd, void* buffer, size_t n) -{ - return v4l1_read (fd, buffer, n); -} - -LIBV4L_PUBLIC void *mmap(void *start, size_t length, int prot, int flags, int fd, - __off_t offset) -{ - return v4l1_mmap(start, length, prot, flags, fd, offset); -} - -LIBV4L_PUBLIC void *mmap64(void *start, size_t length, int prot, int flags, int fd, - __off64_t offset) -{ - return v4l1_mmap(start, length, prot, flags, fd, offset); -} - -LIBV4L_PUBLIC int munmap(void *start, size_t length) -{ - return v4l1_munmap(start, length); -} - diff --git a/v4l2-apps/lib/libv4l/libv4l2/Makefile b/v4l2-apps/lib/libv4l/libv4l2/Makefile deleted file mode 100644 index 648d27c0c..000000000 --- a/v4l2-apps/lib/libv4l/libv4l2/Makefile +++ /dev/null @@ -1,82 +0,0 @@ -override CPPFLAGS += -I../include -I../../../include -fvisibility=hidden - -CFLAGS := -g -O1 -CFLAGS += -Wall -Wno-unused -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes - -LIBS = -lpthread - -V4L2_OBJS = libv4l2.o log.o -V4L2CONVERT = v4l2convert.so -V4L2CONVERT_O = v4l2convert.o libv4l2.so -TARGETS = $(V4L2_LIB) libv4l2.pc -INCLUDES = ../include/libv4l2.h - -ifeq ($(LINKTYPE),static) -V4L2_LIB = libv4l2.a -else -V4L2_LIB = libv4l2.so -V4L2_OBJS += ../libv4lconvert/libv4lconvert.so -TARGETS += $(V4L2CONVERT) -override CPPFLAGS += -fPIC -endif - -ifeq ($(LIB_RELEASE),) -LIB_RELEASE = 0 -endif - -ifeq ($(PREFIX),) -PREFIX = /usr/local -endif - -ifeq ($(LIBDIR),) -LIBDIR = $(PREFIX)/lib -endif - -all: $(TARGETS) - -$(V4L2_LIB): $(V4L2_OBJS) - -$(V4L2CONVERT): $(V4L2CONVERT_O) $(V4L2_LIB) - -libv4l2.pc: - @echo prefix=$(PREFIX) > libv4l2.pc - @echo libdir=$(LIBDIR) >> libv4l2.pc - @echo >> libv4l2.pc - @echo 'Name: libv4l2' >> libv4l2.pc - @echo 'Description: v4l2 device access library' >> libv4l2.pc - @echo 'Version: '$(V4L2_LIB_VERSION) >> libv4l2.pc - @echo 'Requires: libv4lconvert' >> libv4l2.pc - @echo 'Libs: -L$${libdir} -lv4l2' >> libv4l2.pc - @echo 'Libs.private: -lpthread' >> libv4l2.pc - @echo 'Cflags: -I$${prefix}/include' >> libv4l2.pc - -install: all - mkdir -p $(DESTDIR)$(PREFIX)/include - install -p -m 644 $(INCLUDES) $(DESTDIR)$(PREFIX)/include -ifeq ($(LINKTYPE),static) - mkdir -p $(DESTDIR)$(LIBDIR) - install -m 644 $(V4L2_LIB) $(DESTDIR)$(LIBDIR) -else - mkdir -p $(DESTDIR)$(LIBDIR)/libv4l - install -m 755 $(V4L2_LIB).$(LIB_RELEASE) $(DESTDIR)$(LIBDIR) - cd $(DESTDIR)$(LIBDIR) && \ - ln -f -s $(V4L2_LIB).$(LIB_RELEASE) $(V4L2_LIB) - install -m 755 $(V4L2CONVERT).$(LIB_RELEASE) \ - $(DESTDIR)$(LIBDIR)/libv4l/$(V4L2CONVERT) -endif - mkdir -p $(DESTDIR)$(LIBDIR)/pkgconfig - install -m 644 libv4l2.pc $(DESTDIR)$(LIBDIR)/pkgconfig - -clean:: - rm -f *.a *.so* *.o *.d libv4l2.pc log *~ - -%.o: %.c - $(CC) -c -MMD $(CPPFLAGS) $(CFLAGS) -o $@ $< - -%.so: - $(CC) -shared $(LDFLAGS) -Wl,-soname,$@.$(LIB_RELEASE) -o $@.$(LIB_RELEASE) $^ $(LIBS) - ln -f -s $@.$(LIB_RELEASE) $@ - -%.a: - $(AR) cqs $@ $^ - diff --git a/v4l2-apps/lib/libv4l/libv4l2/libv4l2-priv.h b/v4l2-apps/lib/libv4l/libv4l2/libv4l2-priv.h deleted file mode 100644 index 8724832e1..000000000 --- a/v4l2-apps/lib/libv4l/libv4l2/libv4l2-priv.h +++ /dev/null @@ -1,95 +0,0 @@ -/* -# (C) 2008 Hans de Goede - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 2.1 of the License, or -# (at your option) any later version. -# -# 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef __LIBV4L2_PRIV_H -#define __LIBV4L2_PRIV_H - -#include -#include -#include /* includes videodev2.h for us */ - -/* On 32 bits archs we always use mmap2, on 64 bits archs there is no mmap2 */ -#ifdef __NR_mmap2 -#define SYS_mmap2 __NR_mmap2 -#define MMAP2_PAGE_SHIFT 12 -#else -#define SYS_mmap2 SYS_mmap -#define MMAP2_PAGE_SHIFT 0 -#endif - -#define V4L2_MAX_DEVICES 16 -/* Warning when making this larger the frame_queued and frame_mapped members of - the v4l2_dev_info struct can no longer be a bitfield, so the code needs to - be adjusted! */ -#define V4L2_MAX_NO_FRAMES 32 -#define V4L2_DEFAULT_NREADBUFFERS 4 -#define V4L2_FRAME_BUF_SIZE (4096 * 4096) - -#define V4L2_LOG_ERR(...) \ - do { \ - if (v4l2_log_file) { \ - fprintf(v4l2_log_file, "libv4l2: error " __VA_ARGS__); \ - fflush(v4l2_log_file); \ - } else \ - fprintf(stderr, "libv4l2: error " __VA_ARGS__); \ - } while(0) - -#define V4L2_LOG_WARN(...) \ - do { \ - if (v4l2_log_file) { \ - fprintf(v4l2_log_file, "libv4l2: warning " __VA_ARGS__); \ - fflush(v4l2_log_file); \ - } else \ - fprintf(stderr, "libv4l2: warning " __VA_ARGS__); \ - } while(0) - -#define V4L2_LOG(...) \ - do { \ - if (v4l2_log_file) { \ - fprintf(v4l2_log_file, "libv4l2: " __VA_ARGS__); \ - fflush(v4l2_log_file); \ - } \ - } while(0) - -#define MIN(a,b) (((a)<(b))?(a):(b)) - -struct v4l2_dev_info { - int fd; - int flags; - int open_count; - /* actually format of the cam */ - struct v4l2_format src_fmt; - /* fmt as seen by the application (iow after conversion) */ - struct v4l2_format dest_fmt; - pthread_mutex_t stream_lock; - unsigned int no_frames; - unsigned int nreadbuffers; - struct v4lconvert_data *convert; - unsigned char *convert_mmap_buf; - /* Frame bookkeeping is only done when in read or mmap-conversion mode */ - unsigned char *frame_pointers[V4L2_MAX_NO_FRAMES]; - int frame_sizes[V4L2_MAX_NO_FRAMES]; - int frame_queued; /* 1 status bit per frame */ - /* mapping tracking of our fake (converting mmap) frame buffers */ - unsigned char frame_map_count[V4L2_MAX_NO_FRAMES]; -}; - -/* From log.c */ -void v4l2_log_ioctl(unsigned long int request, void *arg, int result); - -#endif diff --git a/v4l2-apps/lib/libv4l/libv4l2/libv4l2.c b/v4l2-apps/lib/libv4l/libv4l2/libv4l2.c deleted file mode 100644 index b4a10afac..000000000 --- a/v4l2-apps/lib/libv4l/libv4l2/libv4l2.c +++ /dev/null @@ -1,1145 +0,0 @@ -/* -# (C) 2008 Hans de Goede - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 2.1 of the License, or -# (at your option) any later version. -# -# 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -/* MAKING CHANGES TO THIS FILE?? READ THIS FIRST!!! - - This file implements libv4l2, which offers v4l2_ prefixed versions of - open/close/etc. The API is 100% the same as directly opening /dev/videoX - using regular open/close/etc, the big difference is that format conversion - is done if necessary when capturing. That is if you (try to) set a capture - format which is not supported by the cam, but is supported by libv4lconvert, - then the try_fmt / set_fmt will succeed as if the cam supports the format - and on dqbuf / read the data will be converted for you and returned in - the request format. - - Important note to people making changes to this file: All functions - (v4l2_close, v4l2_ioctl, etc.) are designed to function as their regular - counterpart when they get passed a fd that is not "registered" by libv4l2, - there are 2 reasons for this: - 1) This allows us to get completely out of the way when dealing with non - capture devices. - 2) libv4l2 is the base of the v4l2convert.so wrapper lib, which is a .so - which can be LD_PRELOAD-ed and the overrules the libc's open/close/etc, - and when opening /dev/videoX or /dev/v4l/ calls v4l2_open. Because we - behave as the regular counterpart when the fd is not known (instead of say - throwing an error), v4l2convert.so can simply call the v4l2_ prefixed - function for all wrapped functions (except for v4l2_open which will fail - when not called on a v4l2 device). This way the wrapper does not have to - keep track of which fd's are being handled by libv4l2, as libv4l2 already - keeps track of this itself. - - This also means that libv4l2 may not use any of the regular functions - it mimics, as for example open could be a symbol in v4l2convert.so, which - in turn will call v4l2_open, so therefor v4l2_open (for example) may not - use the regular open()! - - Another important note: libv4l2 does conversion for capture usage only, if - any calls are made which are passed a v4l2_buffer or v4l2_format with a - v4l2_buf_type which is different from V4L2_BUF_TYPE_VIDEO_CAPTURE, then - the v4l2_ methods behave exactly the same as their regular counterparts. - When modifications are made, one should be carefull that this behavior is - preserved. -*/ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "libv4l2.h" -#include "libv4l2-priv.h" - -/* Note these flags are stored together with the flags passed to v4l2_fd_open() - in v4l2_dev_info's flags member, so care should be taken that the do not - use the same bits! */ -#define V4L2_STREAMON 0x0100 -#define V4L2_BUFFERS_REQUESTED_BY_READ 0x0200 -#define V4L2_STREAM_CONTROLLED_BY_READ 0x0400 -#define V4L2_SUPPORTS_READ 0x0800 - -#define V4L2_MMAP_OFFSET_MAGIC 0xABCDEF00u - -static pthread_mutex_t v4l2_open_mutex = PTHREAD_MUTEX_INITIALIZER; -static struct v4l2_dev_info devices[V4L2_MAX_DEVICES] = { { .fd = -1 }, - { .fd = -1 }, { .fd = -1 }, { .fd = -1 }, { .fd = -1 }, { .fd = -1 }, - { .fd = -1 }, { .fd = -1 }, { .fd = -1 }, { .fd = -1 }, { .fd = -1 }, - { .fd = -1 }, { .fd = -1 }, { .fd = -1 }, { .fd = -1 }, { .fd = -1 }}; -static int devices_used = 0; - - -static int v4l2_request_read_buffers(int index) -{ - int result; - struct v4l2_requestbuffers req; - - /* Note we re-request the buffers if they are already requested as the format - and thus the needed buffersize may have changed. */ - req.count = (devices[index].no_frames)? devices[index].no_frames: - devices[index].nreadbuffers; - req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - req.memory = V4L2_MEMORY_MMAP; - if ((result = syscall(SYS_ioctl, devices[index].fd, VIDIOC_REQBUFS, &req)) < 0){ - int saved_err = errno; - V4L2_LOG_ERR("requesting %u buffers: %s\n", req.count, strerror(errno)); - errno = saved_err; - return result; - } - - if (!devices[index].no_frames && req.count) - devices[index].flags |= V4L2_BUFFERS_REQUESTED_BY_READ; - - devices[index].no_frames = MIN(req.count, V4L2_MAX_NO_FRAMES); - return 0; -} - -static void v4l2_unrequest_read_buffers(int index) -{ - struct v4l2_requestbuffers req; - - if (!(devices[index].flags & V4L2_BUFFERS_REQUESTED_BY_READ) || - devices[index].no_frames == 0) - return; - - /* (Un)Request buffers, note not all driver support this, and those - who do not support it don't need it. */ - req.count = 0; - req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - req.memory = V4L2_MEMORY_MMAP; - if(syscall(SYS_ioctl, devices[index].fd, VIDIOC_REQBUFS, &req) < 0) - return; - - devices[index].no_frames = MIN(req.count, V4L2_MAX_NO_FRAMES); - if (devices[index].no_frames == 0) - devices[index].flags &= ~V4L2_BUFFERS_REQUESTED_BY_READ; -} - -static int v4l2_map_buffers(int index) -{ - int result = 0; - unsigned int i; - struct v4l2_buffer buf; - - for (i = 0; i < devices[index].no_frames; i++) { - if (devices[index].frame_pointers[i] != MAP_FAILED) - continue; - - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; - buf.index = i; - result = syscall(SYS_ioctl, devices[index].fd, VIDIOC_QUERYBUF, &buf); - if (result) { - int saved_err = errno; - V4L2_LOG_ERR("querying buffer %u: %s\n", i, strerror(errno)); - errno = saved_err; - break; - } - - devices[index].frame_pointers[i] = (void *)syscall(SYS_mmap2, NULL, - (size_t)buf.length, PROT_READ|PROT_WRITE, MAP_SHARED, devices[index].fd, - (__off_t)(buf.m.offset >> MMAP2_PAGE_SHIFT)); - if (devices[index].frame_pointers[i] == MAP_FAILED) { - int saved_err = errno; - V4L2_LOG_ERR("mmapping buffer %u: %s\n", i, strerror(errno)); - errno = saved_err; - result = -1; - break; - } - V4L2_LOG("mapped buffer %u at %p\n", i, - devices[index].frame_pointers[i]); - - devices[index].frame_sizes[i] = buf.length; - } - - return result; -} - -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) { - syscall(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); - } - } -} - -static int v4l2_streamon(int index) -{ - int result; - enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - if (!(devices[index].flags & V4L2_STREAMON)) { - if ((result = syscall(SYS_ioctl, devices[index].fd, VIDIOC_STREAMON, - &type))) { - int saved_err = errno; - V4L2_LOG_ERR("turning on stream: %s\n", strerror(errno)); - errno = saved_err; - return result; - } - devices[index].flags |= V4L2_STREAMON; - } - - return 0; -} - -static int v4l2_streamoff(int index) -{ - int result; - enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - if (devices[index].flags & V4L2_STREAMON) { - if ((result = syscall(SYS_ioctl, devices[index].fd, VIDIOC_STREAMOFF, - &type))) { - int saved_err = errno; - V4L2_LOG_ERR("turning off stream: %s\n", strerror(errno)); - errno = saved_err; - return result; - } - devices[index].flags &= ~V4L2_STREAMON; - - /* Stream off also unqueues all our buffers! */ - devices[index].frame_queued = 0; - } - - return 0; -} - -static int v4l2_queue_read_buffer(int index, int buffer_index) -{ - int result; - struct v4l2_buffer buf; - - if (devices[index].frame_queued & (1 << buffer_index)) - return 0; - - memset(&buf, 0, sizeof(buf)); - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; - buf.index = buffer_index; - if ((result = syscall(SYS_ioctl, devices[index].fd, VIDIOC_QBUF, &buf))) { - int saved_err = errno; - V4L2_LOG_ERR("queuing buf %d: %s\n", buffer_index, strerror(errno)); - errno = saved_err; - return result; - } - - devices[index].frame_queued |= 1 << buffer_index; - return 0; -} - -static int v4l2_dequeue_and_convert(int index, struct v4l2_buffer *buf, - unsigned char *dest, int dest_size) -{ - const int max_tries = 10; - int result, tries = max_tries; - - /* Make sure we have the real v4l2 buffers mapped */ - if ((result = v4l2_map_buffers(index))) - return result; - - do { - if ((result = syscall(SYS_ioctl, devices[index].fd, VIDIOC_DQBUF, buf))) { - int saved_err = errno; - V4L2_LOG_ERR("dequeuing buf: %s\n", strerror(errno)); - errno = saved_err; - return result; - } - - devices[index].frame_queued &= ~(1 << buf->index); - - result = v4lconvert_convert(devices[index].convert, - &devices[index].src_fmt, &devices[index].dest_fmt, - devices[index].frame_pointers[buf->index], - buf->bytesused, dest ? dest : (devices[index].convert_mmap_buf + - buf->index * V4L2_FRAME_BUF_SIZE), dest_size); - - if (result < 0) { - int saved_err = errno; - - if(errno == EAGAIN) - V4L2_LOG("warning error while converting frame data: %s\n", - v4lconvert_get_error_message(devices[index].convert)); - else - V4L2_LOG_ERR("converting / decoding frame data: %s\n", - v4lconvert_get_error_message(devices[index].convert)); - - v4l2_queue_read_buffer(index, buf->index); - errno = saved_err; - } - tries--; - } while (result < 0 && errno == EAGAIN && tries); - - if (result < 0 && errno == EAGAIN) { - V4L2_LOG_ERR("got %d consecutive frame decode errors, last error: %s\n", - max_tries, v4lconvert_get_error_message(devices[index].convert)); - } - - return result; -} - -static int v4l2_queue_read_buffers(int index) -{ - unsigned int i; - int last_error = EIO, queued = 0; - - for (i = 0; i < devices[index].no_frames; i++) { - /* Don't queue unmapped buffers (should never happen) */ - if (devices[index].frame_pointers[i] != MAP_FAILED) { - if (v4l2_queue_read_buffer(index, i)) { - last_error = errno; - continue; - } - queued++; - } - } - - if (!queued) { - errno = last_error; - return -1; - } - return 0; -} - -static int v4l2_activate_read_stream(int index) -{ - int result; - - if ((result = v4l2_request_read_buffers(index))) - return result; - - if ((result = v4l2_map_buffers(index))) - return result; - - if ((result = v4l2_queue_read_buffers(index))) - return result; - - devices[index].flags |= V4L2_STREAM_CONTROLLED_BY_READ; - - return result = v4l2_streamon(index); -} - -static int v4l2_deactivate_read_stream(int index) -{ - int result; - - if ((result = v4l2_streamoff(index))) - return result; - - /* No need to unqueue our buffers, streamoff does that for us */ - - v4l2_unmap_buffers(index); - - v4l2_unrequest_read_buffers(index); - - devices[index].flags &= ~V4L2_STREAM_CONTROLLED_BY_READ; - - return 0; -} - -static int v4l2_buffers_mapped(int index) -{ - unsigned int i; - - if (devices[index].src_fmt.fmt.pix.pixelformat == - devices[index].dest_fmt.fmt.pix.pixelformat) { - /* Normal (no conversion) mode */ - struct v4l2_buffer buf; - - for (i = 0; i < devices[index].no_frames; i++) { - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; - buf.index = i; - if (syscall(SYS_ioctl, devices[index].fd, VIDIOC_QUERYBUF, &buf)) { - int saved_err = errno; - V4L2_LOG_ERR("querying buffer %u: %s\n", i, strerror(errno)); - errno = saved_err; - break; - } - if (buf.flags & V4L2_BUF_FLAG_MAPPED) - break; - } - } else { - /* Conversion mode */ - for (i = 0; i < devices[index].no_frames; i++) - if (devices[index].frame_map_count[i]) - break; - } - - if (i != devices[index].no_frames) - V4L2_LOG("v4l2_buffers_mapped(): buffers still mapped\n"); - - return i != devices[index].no_frames; -} - - -int v4l2_open (const char *file, int oflag, ...) -{ - int fd; - - /* original open code */ - if (oflag & O_CREAT) - { - va_list ap; - mode_t mode; - - va_start (ap, oflag); - mode = va_arg (ap, mode_t); - - fd = syscall(SYS_open, file, oflag, mode); - - va_end(ap); - } - else - fd = syscall(SYS_open, file, oflag); - /* end of original open code */ - - if (fd == -1) - return fd; - - if (v4l2_fd_open(fd, 0) == -1) { - int saved_err = errno; - syscall(SYS_close, fd); - errno = saved_err; - return -1; - } - - return fd; -} - -int v4l2_fd_open(int fd, int v4l2_flags) -{ - int i, index; - char *lfname; - struct v4l2_capability cap; - struct v4l2_format fmt; - struct v4lconvert_data *convert; - - /* If no log file was set by the app, see if one was specified through the - environment */ - if (!v4l2_log_file && (lfname = getenv("LIBV4L2_LOG_FILENAME"))) - v4l2_log_file = fopen(lfname, "w"); - - /* check that this is an v4l2 device */ - if (syscall(SYS_ioctl, fd, VIDIOC_QUERYCAP, &cap)) { - int saved_err = errno; - V4L2_LOG_ERR("getting capabilities: %s\n", strerror(errno)); - errno = saved_err; - return -1; - } - - /* we only add functionality for video capture devices, and we do not - handle devices which don't do mmap */ - if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) || - !(cap.capabilities & V4L2_CAP_STREAMING)) - return fd; - - /* Get current cam format */ - fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (syscall(SYS_ioctl, fd, VIDIOC_G_FMT, &fmt)) { - int saved_err = errno; - V4L2_LOG_ERR("getting pixformat: %s\n", strerror(errno)); - errno = saved_err; - return -1; - } - - /* init libv4lconvert */ - if (!(convert = v4lconvert_create(fd))) - return -1; - - /* So we have a v4l2 capture device, register it in our devices array */ - pthread_mutex_lock(&v4l2_open_mutex); - for (index = 0; index < V4L2_MAX_DEVICES; index++) - if(devices[index].fd == -1) { - devices[index].fd = fd; - break; - } - pthread_mutex_unlock(&v4l2_open_mutex); - - if (index == V4L2_MAX_DEVICES) { - V4L2_LOG_ERR("attempting to open more then %d video devices\n", - V4L2_MAX_DEVICES); - errno = EBUSY; - return -1; - } - - devices[index].flags = v4l2_flags; - if (cap.capabilities & V4L2_CAP_READWRITE) - devices[index].flags |= V4L2_SUPPORTS_READ; - devices[index].open_count = 1; - devices[index].src_fmt = fmt; - devices[index].dest_fmt = fmt; - - pthread_mutex_init(&devices[index].stream_lock, NULL); - - devices[index].no_frames = 0; - devices[index].nreadbuffers = V4L2_DEFAULT_NREADBUFFERS; - devices[index].convert = convert; - devices[index].convert_mmap_buf = MAP_FAILED; - for (i = 0; i < V4L2_MAX_NO_FRAMES; i++) { - devices[index].frame_pointers[i] = MAP_FAILED; - devices[index].frame_map_count[i] = 0; - } - devices[index].frame_queued = 0; - - if (index >= devices_used) - devices_used = index + 1; - - V4L2_LOG("open: %d\n", fd); - - return fd; -} - -/* Is this an fd for which we are emulating v4l1 ? */ -static int v4l2_get_index(int fd) -{ - int index; - - /* We never handle fd -1 */ - if (fd == -1) - return -1; - - for (index = 0; index < devices_used; index++) - if (devices[index].fd == fd) - break; - - if (index == devices_used) - return -1; - - return index; -} - - -int v4l2_close(int fd) -{ - int index, result; - - if ((index = v4l2_get_index(fd)) == -1) - return syscall(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); - v4lconvert_destroy(devices[index].convert); - 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 - syscall(SYS_munmap, devices[index].convert_mmap_buf, - devices[index].no_frames * V4L2_FRAME_BUF_SIZE); - devices[index].convert_mmap_buf = 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; - - /* Since we've marked the fd as no longer used, and freed the resources, - redo the close in case it was interrupted */ - do { - result = syscall(SYS_close, fd); - } while (result == -1 && errno == EINTR); - - V4L2_LOG("close: %d\n", fd); - - return result; -} - -int v4l2_dup(int fd) -{ - int index; - - if ((index = v4l2_get_index(fd)) == -1) - return syscall(SYS_dup, fd); - - devices[index].open_count++; - - return fd; -} - -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 */ - syscall(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; -} - -int v4l2_ioctl (int fd, unsigned long int request, ...) -{ - void *arg; - va_list ap; - int result, converting, index, saved_err; - int is_capture_request = 0, stream_needs_locking = 0; - - va_start (ap, request); - arg = va_arg (ap, void *); - va_end (ap); - - if ((index = v4l2_get_index(fd)) == -1) - return syscall(SYS_ioctl, fd, request, arg); - - /* Appearantly the kernel and / or glibc ignore the 32 most significant bits - when long = 64 bits, and some applications pass an int holding the req to - ioctl, causing it to get sign extended, depending upon this behavior */ - request = (unsigned int)request; - - /* Is this a capture request and do we need to take the stream lock? */ - switch (request) { - case VIDIOC_QUERYCAP: - is_capture_request = 1; - break; - case VIDIOC_ENUM_FMT: - if (((struct v4l2_fmtdesc *)arg)->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && - (devices[index].flags & V4L2_ENABLE_ENUM_FMT_EMULATION)) - is_capture_request = 1; - break; - case VIDIOC_ENUM_FRAMESIZES: - case VIDIOC_ENUM_FRAMEINTERVALS: - if (devices[index].flags & V4L2_ENABLE_ENUM_FMT_EMULATION) - is_capture_request = 1; - break; - case VIDIOC_TRY_FMT: - if (((struct v4l2_format *)arg)->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) - is_capture_request = 1; - break; - case VIDIOC_S_FMT: - case VIDIOC_G_FMT: - if (((struct v4l2_format *)arg)->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - is_capture_request = 1; - stream_needs_locking = 1; - } - break; - case VIDIOC_REQBUFS: - if (((struct v4l2_requestbuffers *)arg)->type == - V4L2_BUF_TYPE_VIDEO_CAPTURE) { - is_capture_request = 1; - stream_needs_locking = 1; - } - break; - case VIDIOC_QUERYBUF: - case VIDIOC_QBUF: - case VIDIOC_DQBUF: - if (((struct v4l2_buffer *)arg)->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - is_capture_request = 1; - stream_needs_locking = 1; - } - break; - case VIDIOC_STREAMON: - case VIDIOC_STREAMOFF: - if (*((enum v4l2_buf_type *)arg) == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - is_capture_request = 1; - stream_needs_locking = 1; - } - } - - if (!is_capture_request) { - result = syscall(SYS_ioctl, fd, request, arg); - saved_err = errno; - v4l2_log_ioctl(request, arg, result); - errno = saved_err; - return result; - } - - - if (stream_needs_locking) - pthread_mutex_lock(&devices[index].stream_lock); - - converting = v4lconvert_needs_conversion(devices[index].convert, - &devices[index].src_fmt, &devices[index].dest_fmt); - - switch (request) { - case VIDIOC_QUERYCAP: - { - struct v4l2_capability *cap = arg; - - result = syscall(SYS_ioctl, devices[index].fd, VIDIOC_QUERYCAP, cap); - if (result == 0) - /* We always support read() as we fake it using mmap mode */ - cap->capabilities |= V4L2_CAP_READWRITE; - } - break; - - case VIDIOC_ENUM_FMT: - result = v4lconvert_enum_fmt(devices[index].convert, arg); - break; - - case VIDIOC_ENUM_FRAMESIZES: - result = v4lconvert_enum_framesizes(devices[index].convert, arg); - break; - - case VIDIOC_ENUM_FRAMEINTERVALS: - result = v4lconvert_enum_frameintervals(devices[index].convert, arg); - break; - - case VIDIOC_TRY_FMT: - result = v4lconvert_try_format(devices[index].convert, arg, NULL); - break; - - case VIDIOC_S_FMT: - { - struct v4l2_format src_fmt, *dest_fmt = arg; - - if (!memcmp(&devices[index].dest_fmt, dest_fmt, sizeof(*dest_fmt))) { - result = 0; - break; - } - - if (devices[index].flags & V4L2_DISABLE_CONVERSION) { - result = syscall(SYS_ioctl, devices[index].fd, VIDIOC_TRY_FMT, - dest_fmt); - src_fmt = *dest_fmt; - } else { - result = v4lconvert_try_format(devices[index].convert, dest_fmt, - &src_fmt); - } - - if (result) - break; - - if (src_fmt.fmt.pix.pixelformat != dest_fmt->fmt.pix.pixelformat && - v4l2_log_file) { - int pixfmt = src_fmt.fmt.pix.pixelformat; - - fprintf(v4l2_log_file, "VIDIOC_S_FMT converting from: %c%c%c%c\n", - pixfmt & 0xff, - (pixfmt >> 8) & 0xff, - (pixfmt >> 16) & 0xff, - pixfmt >> 24); - } - - /* Maybe after try format has adjusted width/height etc, to whats - available nothing has changed (on the cam side) ? */ - if (!memcmp(&devices[index].src_fmt, &src_fmt, sizeof(src_fmt))) { - devices[index].dest_fmt = *dest_fmt; - result = 0; - break; - } - - if ((result = v4l2_check_buffer_change_ok(index))) - break; - - result = syscall(SYS_ioctl, devices[index].fd, VIDIOC_S_FMT, &src_fmt); - if (result) { - saved_err = errno; - V4L2_LOG_ERR("setting pixformat: %s\n", strerror(errno)); - /* Report to the app dest_fmt has not changed */ - *dest_fmt = devices[index].dest_fmt; - errno = saved_err; - break; - } - - devices[index].src_fmt = src_fmt; - devices[index].dest_fmt = *dest_fmt; - } - break; - - case VIDIOC_G_FMT: - { - struct v4l2_format* fmt = arg; - - *fmt = devices[index].dest_fmt; - result = 0; - } - break; - - case VIDIOC_REQBUFS: - { - struct v4l2_requestbuffers *req = arg; - - /* IMPROVEME (maybe?) add support for userptr's? */ - if (req->memory != V4L2_MEMORY_MMAP) { - errno = EINVAL; - result = -1; - break; - } - - if ((result = v4l2_check_buffer_change_ok(index))) - break; - - /* No more buffers then we can manage please */ - if (req->count > V4L2_MAX_NO_FRAMES) - req->count = V4L2_MAX_NO_FRAMES; - - result = syscall(SYS_ioctl, devices[index].fd, VIDIOC_REQBUFS, req); - if (result < 0) - break; - result = 0; /* some drivers return the number of buffers on success */ - - devices[index].no_frames = MIN(req->count, V4L2_MAX_NO_FRAMES); - devices[index].flags &= ~V4L2_BUFFERS_REQUESTED_BY_READ; - } - break; - - case VIDIOC_QUERYBUF: - { - struct v4l2_buffer *buf = arg; - - if (devices[index].flags & V4L2_STREAM_CONTROLLED_BY_READ) - if ((result = v4l2_deactivate_read_stream(index))) - break; - - /* Do a real query even when converting to let the driver fill in - things like buf->field */ - result = syscall(SYS_ioctl, devices[index].fd, VIDIOC_QUERYBUF, buf); - if (result || !converting) - break; - - buf->m.offset = V4L2_MMAP_OFFSET_MAGIC | buf->index; - buf->length = V4L2_FRAME_BUF_SIZE; - if (devices[index].frame_map_count[buf->index]) - buf->flags |= V4L2_BUF_FLAG_MAPPED; - else - buf->flags &= ~V4L2_BUF_FLAG_MAPPED; - } - break; - - case VIDIOC_QBUF: - if (devices[index].flags & V4L2_STREAM_CONTROLLED_BY_READ) - if ((result = v4l2_deactivate_read_stream(index))) - break; - - /* With some drivers the buffers must be mapped before queuing */ - if (converting) - if ((result = v4l2_map_buffers(index))) - break; - - result = syscall(SYS_ioctl, devices[index].fd, VIDIOC_QBUF, arg); - break; - - case VIDIOC_DQBUF: - { - struct v4l2_buffer *buf = arg; - - if (devices[index].flags & V4L2_STREAM_CONTROLLED_BY_READ) - if ((result = v4l2_deactivate_read_stream(index))) - break; - - if (!converting) { - result = syscall(SYS_ioctl, devices[index].fd, VIDIOC_DQBUF, buf); - if (result) { - int saved_err = errno; - V4L2_LOG_ERR("dequeuing buf: %s\n", strerror(errno)); - errno = saved_err; - } - break; - } - - /* An application can do a DQBUF before mmap-ing in the buffer, - but we need the buffer _now_ to write our converted data - to it! */ - if (devices[index].convert_mmap_buf == MAP_FAILED) { - devices[index].convert_mmap_buf = (void *)syscall(SYS_mmap2, - (size_t)( - devices[index].no_frames * - V4L2_FRAME_BUF_SIZE), - PROT_READ|PROT_WRITE, - MAP_ANONYMOUS|MAP_PRIVATE, - -1, 0); - if (devices[index].convert_mmap_buf == MAP_FAILED) { - saved_err = errno; - V4L2_LOG_ERR("allocating conversion buffer\n"); - errno = saved_err; - result = -1; - break; - } - } - - result = v4l2_dequeue_and_convert(index, buf, 0, V4L2_FRAME_BUF_SIZE); - if (result < 0) - break; - - buf->bytesused = result; - buf->m.offset = V4L2_MMAP_OFFSET_MAGIC | buf->index; - buf->length = V4L2_FRAME_BUF_SIZE; - if (devices[index].frame_map_count[buf->index]) - buf->flags |= V4L2_BUF_FLAG_MAPPED; - else - buf->flags &= ~V4L2_BUF_FLAG_MAPPED; - - result = 0; - } - break; - - case VIDIOC_STREAMON: - case VIDIOC_STREAMOFF: - if (devices[index].flags & V4L2_STREAM_CONTROLLED_BY_READ) - if ((result = v4l2_deactivate_read_stream(index))) - break; - - if (request == VIDIOC_STREAMON) - result = v4l2_streamon(index); - else - result = v4l2_streamoff(index); - break; - - default: - result = syscall(SYS_ioctl, fd, request, arg); - } - - if (stream_needs_locking) - pthread_mutex_unlock(&devices[index].stream_lock); - - saved_err = errno; - v4l2_log_ioctl(request, arg, result); - errno = saved_err; - - return result; -} - - -ssize_t v4l2_read (int fd, void* dest, size_t n) -{ - ssize_t result; - int index; - struct v4l2_buffer buf; - - if ((index = v4l2_get_index(fd)) == -1) - return syscall(SYS_read, fd, dest, n); - - pthread_mutex_lock(&devices[index].stream_lock); - - /* When not converting and the device supports read let the kernel handle - it */ - if ((devices[index].flags & V4L2_SUPPORTS_READ) && - !v4lconvert_needs_conversion(devices[index].convert, - &devices[index].src_fmt, &devices[index].dest_fmt)) { - result = syscall(SYS_read, fd, dest, n); - goto leave; - } - - if (!(devices[index].flags & V4L2_STREAM_CONTROLLED_BY_READ)) { - if ((devices[index].flags & V4L2_STREAMON) || - devices[index].frame_queued) { - errno = EBUSY; - result = -1; - goto leave; - } - if ((result = v4l2_activate_read_stream(index))) - goto leave; - } - - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; - result = v4l2_dequeue_and_convert(index, &buf, dest, n); - - if (result >= 0) - v4l2_queue_read_buffer(index, buf.index); - -leave: - pthread_mutex_unlock(&devices[index].stream_lock); - - return result; -} - -void *v4l2_mmap(void *start, size_t length, int prot, int flags, int fd, - __off64_t offset) -{ - int index; - unsigned int buffer_index; - void *result; - - if ((index = v4l2_get_index(fd)) == -1 || - /* Check if the mmap data matches our answer to QUERY_BUF, if it doesn't - let the kernel handle it (to allow for mmap based non capture use) */ - start || length != V4L2_FRAME_BUF_SIZE || - ((unsigned int)offset & ~0xFFu) != V4L2_MMAP_OFFSET_MAGIC) { - if (index != -1) - V4L2_LOG("Passing mmap(%p, %d, ..., %x, through to the driver\n", - start, (int)length, (int)offset); - - if (offset & ((1 << MMAP2_PAGE_SHIFT) - 1)) { - errno = EINVAL; - return MAP_FAILED; - } - - return (void *)syscall(SYS_mmap2, start, length, prot, flags, fd, - (__off_t)(offset >> MMAP2_PAGE_SHIFT)); - } - - pthread_mutex_lock(&devices[index].stream_lock); - - buffer_index = offset & 0xff; - if (buffer_index >= devices[index].no_frames || - /* Got magic offset and not converting ?? */ - !v4lconvert_needs_conversion(devices[index].convert, - &devices[index].src_fmt, &devices[index].dest_fmt)) { - errno = EINVAL; - result = MAP_FAILED; - goto leave; - } - - if (devices[index].convert_mmap_buf == MAP_FAILED) { - devices[index].convert_mmap_buf = (void *)syscall(SYS_mmap2, NULL, - (size_t)( - devices[index].no_frames * - V4L2_FRAME_BUF_SIZE), - PROT_READ|PROT_WRITE, - MAP_ANONYMOUS|MAP_PRIVATE, - -1, 0); - if (devices[index].convert_mmap_buf == MAP_FAILED) { - int saved_err = errno; - V4L2_LOG_ERR("allocating conversion buffer\n"); - errno = saved_err; - result = MAP_FAILED; - goto leave; - } - } - - devices[index].frame_map_count[buffer_index]++; - - result = devices[index].convert_mmap_buf + - buffer_index * V4L2_FRAME_BUF_SIZE; - - V4L2_LOG("Fake (conversion) mmap buf %u, seen by app at: %p\n", - buffer_index, result); - -leave: - pthread_mutex_unlock(&devices[index].stream_lock); - - return result; -} - -int v4l2_munmap(void *_start, size_t length) -{ - int index; - unsigned int buffer_index; - unsigned char *start = _start; - - /* Is this memory ours? */ - if (start != MAP_FAILED && length == V4L2_FRAME_BUF_SIZE) { - for (index = 0; index < devices_used; index++) - if (devices[index].fd != -1 && - devices[index].convert_mmap_buf != MAP_FAILED && - start >= devices[index].convert_mmap_buf && - (start - devices[index].convert_mmap_buf) % length == 0) - break; - - if (index != devices_used) { - int unmapped = 0; - - pthread_mutex_lock(&devices[index].stream_lock); - - buffer_index = (start - devices[index].convert_mmap_buf) / length; - - /* Redo our checks now that we have the lock, things may have changed */ - if (devices[index].convert_mmap_buf != MAP_FAILED && - start >= devices[index].convert_mmap_buf && - (start - devices[index].convert_mmap_buf) % length == 0 && - buffer_index < devices[index].no_frames) { - if (devices[index].frame_map_count[buffer_index] > 0) - devices[index].frame_map_count[buffer_index]--; - unmapped = 1; - } - - pthread_mutex_unlock(&devices[index].stream_lock); - - if (unmapped) { - V4L2_LOG("v4l2 fake buffer munmap %p, %d\n", start, (int)length); - return 0; - } - } - } - - V4L2_LOG("v4l2 unknown munmap %p, %d\n", start, (int)length); - - return syscall(SYS_munmap, _start, length); -} - -/* Misc utility functions */ -int v4l2_set_control(int fd, int cid, int value) -{ - struct v4l2_queryctrl qctrl = { .id = cid }; - struct v4l2_control ctrl = { .id = cid }; - int result; - - if ((result = syscall(SYS_ioctl, fd, VIDIOC_QUERYCTRL, &qctrl))) - return result; - - if (!(qctrl.flags & V4L2_CTRL_FLAG_DISABLED) && - !(qctrl.flags & V4L2_CTRL_FLAG_GRABBED)) { - if (qctrl.type == V4L2_CTRL_TYPE_BOOLEAN) - ctrl.value = value? 1:0; - else - ctrl.value = (value * (qctrl.maximum - qctrl.minimum) + 32767) / 65535 + - qctrl.minimum; - - result = syscall(SYS_ioctl, fd, VIDIOC_S_CTRL, &ctrl); - } - - return result; -} - -int v4l2_get_control(int fd, int cid) -{ - struct v4l2_queryctrl qctrl = { .id = cid }; - struct v4l2_control ctrl = { .id = cid }; - - if (syscall(SYS_ioctl, fd, VIDIOC_QUERYCTRL, &qctrl)) - return 0; - - if (qctrl.flags & V4L2_CTRL_FLAG_DISABLED) - return 0; - - if (syscall(SYS_ioctl, fd, VIDIOC_G_CTRL, &ctrl)) - return 0; - - return ((ctrl.value - qctrl.minimum) * 65535 + - (qctrl.maximum - qctrl.minimum) / 2) / - (qctrl.maximum - qctrl.minimum); -} diff --git a/v4l2-apps/lib/libv4l/libv4l2/log.c b/v4l2-apps/lib/libv4l/libv4l2/log.c deleted file mode 100644 index 6237d55ec..000000000 --- a/v4l2-apps/lib/libv4l/libv4l2/log.c +++ /dev/null @@ -1,148 +0,0 @@ -/* -# (C) 2008 Hans de Goede - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 2.1 of the License, or -# (at your option) any later version. -# -# 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include -#include -#include -/* These headers are not needed by us, but by linux/videodev2.h, - which is broken on some systems and doesn't include them itself :( */ -#include -#include -/* end broken header workaround includes */ -#include -#include "libv4l2.h" -#include "libv4l2-priv.h" - -#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0])) - -FILE *v4l2_log_file = NULL; - -static const char *v4l2_ioctls[] = { - /* start v4l2 ioctls */ - [_IOC_NR(VIDIOC_QUERYCAP)] = "VIDIOC_QUERYCAP", - [_IOC_NR(VIDIOC_RESERVED)] = "VIDIOC_RESERVED", - [_IOC_NR(VIDIOC_ENUM_FMT)] = "VIDIOC_ENUM_FMT", - [_IOC_NR(VIDIOC_G_FMT)] = "VIDIOC_G_FMT", - [_IOC_NR(VIDIOC_S_FMT)] = "VIDIOC_S_FMT", - [_IOC_NR(VIDIOC_REQBUFS)] = "VIDIOC_REQBUFS", - [_IOC_NR(VIDIOC_QUERYBUF)] = "VIDIOC_QUERYBUF", - [_IOC_NR(VIDIOC_G_FBUF)] = "VIDIOC_G_FBUF", - [_IOC_NR(VIDIOC_S_FBUF)] = "VIDIOC_S_FBUF", - [_IOC_NR(VIDIOC_OVERLAY)] = "VIDIOC_OVERLAY", - [_IOC_NR(VIDIOC_QBUF)] = "VIDIOC_QBUF", - [_IOC_NR(VIDIOC_DQBUF)] = "VIDIOC_DQBUF", - [_IOC_NR(VIDIOC_STREAMON)] = "VIDIOC_STREAMON", - [_IOC_NR(VIDIOC_STREAMOFF)] = "VIDIOC_STREAMOFF", - [_IOC_NR(VIDIOC_G_PARM)] = "VIDIOC_G_PARM", - [_IOC_NR(VIDIOC_S_PARM)] = "VIDIOC_S_PARM", - [_IOC_NR(VIDIOC_G_STD)] = "VIDIOC_G_STD", - [_IOC_NR(VIDIOC_S_STD)] = "VIDIOC_S_STD", - [_IOC_NR(VIDIOC_ENUMSTD)] = "VIDIOC_ENUMSTD", - [_IOC_NR(VIDIOC_ENUMINPUT)] = "VIDIOC_ENUMINPUT", - [_IOC_NR(VIDIOC_G_CTRL)] = "VIDIOC_G_CTRL", - [_IOC_NR(VIDIOC_S_CTRL)] = "VIDIOC_S_CTRL", - [_IOC_NR(VIDIOC_G_TUNER)] = "VIDIOC_G_TUNER", - [_IOC_NR(VIDIOC_S_TUNER)] = "VIDIOC_S_TUNER", - [_IOC_NR(VIDIOC_G_AUDIO)] = "VIDIOC_G_AUDIO", - [_IOC_NR(VIDIOC_S_AUDIO)] = "VIDIOC_S_AUDIO", - [_IOC_NR(VIDIOC_QUERYCTRL)] = "VIDIOC_QUERYCTRL", - [_IOC_NR(VIDIOC_QUERYMENU)] = "VIDIOC_QUERYMENU", - [_IOC_NR(VIDIOC_G_INPUT)] = "VIDIOC_G_INPUT", - [_IOC_NR(VIDIOC_S_INPUT)] = "VIDIOC_S_INPUT", - [_IOC_NR(VIDIOC_G_OUTPUT)] = "VIDIOC_G_OUTPUT", - [_IOC_NR(VIDIOC_S_OUTPUT)] = "VIDIOC_S_OUTPUT", - [_IOC_NR(VIDIOC_ENUMOUTPUT)] = "VIDIOC_ENUMOUTPUT", - [_IOC_NR(VIDIOC_G_AUDOUT)] = "VIDIOC_G_AUDOUT", - [_IOC_NR(VIDIOC_S_AUDOUT)] = "VIDIOC_S_AUDOUT", - [_IOC_NR(VIDIOC_G_MODULATOR)] = "VIDIOC_G_MODULATOR", - [_IOC_NR(VIDIOC_S_MODULATOR)] = "VIDIOC_S_MODULATOR", - [_IOC_NR(VIDIOC_G_FREQUENCY)] = "VIDIOC_G_FREQUENCY", - [_IOC_NR(VIDIOC_S_FREQUENCY)] = "VIDIOC_S_FREQUENCY", - [_IOC_NR(VIDIOC_CROPCAP)] = "VIDIOC_CROPCAP", - [_IOC_NR(VIDIOC_G_CROP)] = "VIDIOC_G_CROP", - [_IOC_NR(VIDIOC_S_CROP)] = "VIDIOC_S_CROP", - [_IOC_NR(VIDIOC_G_JPEGCOMP)] = "VIDIOC_G_JPEGCOMP", - [_IOC_NR(VIDIOC_S_JPEGCOMP)] = "VIDIOC_S_JPEGCOMP", - [_IOC_NR(VIDIOC_QUERYSTD)] = "VIDIOC_QUERYSTD", - [_IOC_NR(VIDIOC_TRY_FMT)] = "VIDIOC_TRY_FMT", - [_IOC_NR(VIDIOC_ENUMAUDIO)] = "VIDIOC_ENUMAUDIO", - [_IOC_NR(VIDIOC_ENUMAUDOUT)] = "VIDIOC_ENUMAUDOUT", - [_IOC_NR(VIDIOC_G_PRIORITY)] = "VIDIOC_G_PRIORITY", - [_IOC_NR(VIDIOC_S_PRIORITY)] = "VIDIOC_S_PRIORITY", - [_IOC_NR(VIDIOC_G_SLICED_VBI_CAP)] = "VIDIOC_G_SLICED_VBI_CAP", - [_IOC_NR(VIDIOC_LOG_STATUS)] = "VIDIOC_LOG_STATUS", - [_IOC_NR(VIDIOC_G_EXT_CTRLS)] = "VIDIOC_G_EXT_CTRLS", - [_IOC_NR(VIDIOC_S_EXT_CTRLS)] = "VIDIOC_S_EXT_CTRLS", - [_IOC_NR(VIDIOC_TRY_EXT_CTRLS)] = "VIDIOC_TRY_EXT_CTRLS", -}; - -void v4l2_log_ioctl(unsigned long int request, void *arg, int result) -{ - const char *ioctl_str; - char buf[40]; - - if (!v4l2_log_file) - return; - - if (_IOC_TYPE(request) == 'V' && _IOC_NR(request) < ARRAY_SIZE(v4l2_ioctls)) - ioctl_str = v4l2_ioctls[_IOC_NR(request)]; - else { - snprintf(buf, sizeof(buf), "unknown request: %c %d\n", - (int)_IOC_TYPE(request), (int)_IOC_NR(request)); - ioctl_str = buf; - } - - fprintf(v4l2_log_file, "request == %s\n", ioctl_str); - - switch (request) { - case VIDIOC_G_FMT: - case VIDIOC_S_FMT: - case VIDIOC_TRY_FMT: - { - struct v4l2_format* fmt = arg; - int pixfmt = fmt->fmt.pix.pixelformat; - - if (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { - fprintf(v4l2_log_file, " pixelformat: %c%c%c%c %ux%u\n", - pixfmt & 0xff, - (pixfmt >> 8) & 0xff, - (pixfmt >> 16) & 0xff, - pixfmt >> 24, - fmt->fmt.pix.width, - fmt->fmt.pix.height); - fprintf(v4l2_log_file, " field: %d bytesperline: %d imagesize%d\n", - (int)fmt->fmt.pix.field, (int)fmt->fmt.pix.bytesperline, - (int)fmt->fmt.pix.sizeimage); - fprintf(v4l2_log_file, " colorspace: %d, priv: %x\n", - (int)fmt->fmt.pix.colorspace, (int)fmt->fmt.pix.priv); - } - } - break; - case VIDIOC_REQBUFS: - { - struct v4l2_requestbuffers *req = arg; - - fprintf(v4l2_log_file, " count: %u type: %d memory: %d\n", - req->count, (int)req->type, (int)req->memory); - } - break; - } - - fprintf(v4l2_log_file, "result == %d\n", result); - fflush(v4l2_log_file); -} diff --git a/v4l2-apps/lib/libv4l/libv4l2/v4l2convert.c b/v4l2-apps/lib/libv4l/libv4l2/v4l2convert.c deleted file mode 100644 index 307a03ce5..000000000 --- a/v4l2-apps/lib/libv4l/libv4l2/v4l2convert.c +++ /dev/null @@ -1,166 +0,0 @@ -/* -# open/close/ioctl/mmap/munmap library call wrapper doing format conversion -# for v4l2 applications which want to be able to simply capture bgr24 / yuv420 -# from v4l2 devices with more exotic frame formats. - -# (C) 2008 Hans de Goede - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 2.1 of the License, or -# (at your option) any later version. -# -# 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 -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#define _LARGEFILE64_SOURCE 1 - -#include -#include -#include -#include -#include -#include -#include -/* These headers are not needed by us, but by linux/videodev2.h, - which is broken on some systems and doesn't include them itself :( */ -#include -#include -#include -/* end broken header workaround includes */ -#include -#include - -/* Check that open/read/mmap is not a define */ -#if defined open || defined read || defined mmap -#error open/read/mmap is a prepocessor macro !! -#endif - -#if __GNUC__ >= 4 -#define LIBV4L_PUBLIC __attribute__ ((visibility("default"))) -#else -#define LIBV4L_PUBLIC -#endif - -LIBV4L_PUBLIC int open (const char *file, int oflag, ...) -{ - int fd; - struct v4l2_capability cap; - int v4l_device = 0; - - /* check if we're opening a video4linux2 device */ - if (!strncmp(file, "/dev/video", 10) || !strncmp(file, "/dev/v4l/", 9)) { - /* Some apps open the device read only, but we need rw rights as the - buffers *MUST* be mapped rw */ - oflag = (oflag & ~O_ACCMODE) | O_RDWR; - v4l_device = 1; - } - - /* original open code */ - if (oflag & O_CREAT) - { - va_list ap; - mode_t mode; - - va_start (ap, oflag); - mode = va_arg (ap, mode_t); - - fd = syscall(SYS_open, file, oflag, mode); - - va_end(ap); - } else - fd = syscall(SYS_open, file, oflag); - /* end of original open code */ - - if (fd == -1 || !v4l_device) - return fd; - - /* check that this is an v4l2 device, libv4l2 only supports v4l2 devices */ - if (syscall(SYS_ioctl, fd, VIDIOC_QUERYCAP, &cap)) - return fd; - - /* libv4l2 only adds functionality to capture capable devices */ - if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) - return fd; - - /* Try to Register with libv4l2 (in case of failure pass the fd to the - application as is) */ - v4l2_fd_open(fd, V4L2_ENABLE_ENUM_FMT_EMULATION); - - return fd; -} - -LIBV4L_PUBLIC int open64(const char *file, int oflag, ...) -{ - int fd; - - /* original open code */ - if (oflag & O_CREAT) - { - va_list ap; - mode_t mode; - - va_start (ap, oflag); - mode = va_arg (ap, mode_t); - - fd = open(file, oflag | O_LARGEFILE, mode); - - va_end(ap); - } else - fd = open(file, oflag | O_LARGEFILE); - /* end of original open code */ - - return fd; -} - -LIBV4L_PUBLIC int close(int fd) -{ - return v4l2_close(fd); -} - -LIBV4L_PUBLIC int dup(int fd) -{ - return v4l2_dup(fd); -} - -LIBV4L_PUBLIC int ioctl (int fd, unsigned long int request, ...) -{ - void *arg; - va_list ap; - - va_start (ap, request); - arg = va_arg (ap, void *); - va_end (ap); - - return v4l2_ioctl (fd, request, arg); -} - -LIBV4L_PUBLIC ssize_t read (int fd, void* buffer, size_t n) -{ - return v4l2_read (fd, buffer, n); -} - -LIBV4L_PUBLIC void *mmap(void *start, size_t length, int prot, int flags, int fd, - __off_t offset) -{ - return v4l2_mmap(start, length, prot, flags, fd, offset); -} - -LIBV4L_PUBLIC void *mmap64(void *start, size_t length, int prot, int flags, int fd, - __off64_t offset) -{ - return v4l2_mmap(start, length, prot, flags, fd, offset); -} - -LIBV4L_PUBLIC int munmap(void *start, size_t length) -{ - return v4l2_munmap(start, length); -} - diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/Makefile b/v4l2-apps/lib/libv4l/libv4lconvert/Makefile deleted file mode 100644 index 641d19d6e..000000000 --- a/v4l2-apps/lib/libv4l/libv4lconvert/Makefile +++ /dev/null @@ -1,70 +0,0 @@ -override CPPFLAGS += -I../include -I../../../include -fvisibility=hidden - -CFLAGS := -g -O1 -CFLAGS += -Wall -Wno-unused -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes - -ifeq ($(LINKTYPE),static) -CONVERT_LIB = libv4lconvert.a -else -CONVERT_LIB = libv4lconvert.so -override CPPFLAGS += -fPIC -endif - -CONVERT_OBJS = libv4lconvert.o tinyjpeg.o sn9c10x.o pac207.o flip.o \ - jidctflt.o spca561-decompress.o rgbyuv.o spca501.o bayer.o -TARGETS = $(CONVERT_LIB) libv4lconvert.pc -INCLUDES = ../include/libv4lconvert.h - -ifeq ($(LIB_RELEASE),) -LIB_RELEASE = 0 -endif - -ifeq ($(PREFIX),) -PREFIX = /usr/local -endif - -ifeq ($(LIBDIR),) -LIBDIR = $(PREFIX)/lib -endif - -all: $(TARGETS) - -$(CONVERT_LIB): $(CONVERT_OBJS) - -libv4lconvert.pc: - @echo prefix=$(PREFIX) > libv4lconvert.pc - @echo libdir=$(LIBDIR) >> libv4lconvert.pc - @echo >> libv4lconvert.pc - @echo 'Name: libv4lconvert' >> libv4lconvert.pc - @echo 'Description: v4l format conversion library' >> libv4lconvert.pc - @echo 'Version: '$(V4L2_LIB_VERSION) >> libv4lconvert.pc - @echo 'Libs: -L$${libdir} -lv4lconvert' >> libv4lconvert.pc - @echo 'Cflags: -I$${prefix}/include' >> libv4lconvert.pc - -install: all - mkdir -p $(DESTDIR)$(PREFIX)/include - install -p -m 644 $(INCLUDES) $(DESTDIR)$(PREFIX)/include - mkdir -p $(DESTDIR)$(LIBDIR) -ifeq ($(LINKTYPE),static) - mkdir -p $(DESTDIR)$(LIBDIR) - install -m 644 $(CONVERT_LIB) $(DESTDIR)$(LIBDIR) -else - install -m 755 $(CONVERT_LIB).$(LIB_RELEASE) $(DESTDIR)$(LIBDIR) - cd $(DESTDIR)$(LIBDIR) && \ - ln -f -s $(CONVERT_LIB).$(LIB_RELEASE) $(CONVERT_LIB) -endif - mkdir -p $(DESTDIR)$(LIBDIR)/pkgconfig - install -m 644 libv4lconvert.pc $(DESTDIR)$(LIBDIR)/pkgconfig - -clean:: - rm -f *.a *.so* *.o *.d libv4lconvert.pc log *~ - -%.o: %.c - $(CC) -c -MMD $(CPPFLAGS) $(CFLAGS) -o $@ $< - -%.so: - $(CC) -shared $(LDFLAGS) -Wl,-soname,$@.$(LIB_RELEASE) -o $@.$(LIB_RELEASE) $^ - ln -f -s $@.$(LIB_RELEASE) $@ - -%.a: - $(AR) cqs $@ $^ diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/bayer.c b/v4l2-apps/lib/libv4l/libv4lconvert/bayer.c deleted file mode 100644 index ca7bb486f..000000000 --- a/v4l2-apps/lib/libv4l/libv4lconvert/bayer.c +++ /dev/null @@ -1,613 +0,0 @@ -/* - * lib4lconvert, video4linux2 format conversion lib - * (C) 2008 Hans de Goede - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - * Note: original bayer_to_bgr24 code from : - * 1394-Based Digital Camera Control Library - * - * Bayer pattern decoding functions - * - * Written by Damien Douxchamps and Frederic Devernay - * - * Note that the original bayer.c in libdc1394 supports many different - * bayer decode algorithms, for lib4lconvert the one in this file has been - * chosen (and optimized a bit) and the other algorithm's have been removed, - * see bayer.c from libdc1394 for all supported algorithms - */ - -#include -#include "libv4lconvert-priv.h" - -/************************************************************** - * Color conversion functions for cameras that can * - * output raw-Bayer pattern images, such as some Basler and * - * Point Grey camera. Most of the algos presented here come * - * from http://www-ise.stanford.edu/~tingchen/ and have been * - * converted from Matlab to C and extended to all elementary * - * patterns. * - **************************************************************/ - -/* insprired by OpenCV's Bayer decoding */ -static void v4lconvert_border_bayer_line_to_bgr24( - const unsigned char* bayer, const unsigned char* adjacent_bayer, - unsigned char *bgr, int width, int start_with_green, int blue_line) -{ - int t0, t1; - - if (start_with_green) { - /* First pixel */ - if (blue_line) { - *bgr++ = bayer[1]; - *bgr++ = bayer[0]; - *bgr++ = adjacent_bayer[0]; - } else { - *bgr++ = adjacent_bayer[0]; - *bgr++ = bayer[0]; - *bgr++ = bayer[1]; - } - /* Second pixel */ - t0 = (bayer[0] + bayer[2] + adjacent_bayer[1] + 1) / 3; - t1 = (adjacent_bayer[0] + adjacent_bayer[2] + 1) >> 1; - if (blue_line) { - *bgr++ = bayer[1]; - *bgr++ = t0; - *bgr++ = t1; - } else { - *bgr++ = t1; - *bgr++ = t0; - *bgr++ = bayer[1]; - } - bayer++; - adjacent_bayer++; - width -= 2; - } else { - /* First pixel */ - t0 = (bayer[1] + adjacent_bayer[0] + 1) >> 1; - if (blue_line) { - *bgr++ = bayer[0]; - *bgr++ = t0; - *bgr++ = adjacent_bayer[1]; - } else { - *bgr++ = adjacent_bayer[1]; - *bgr++ = t0; - *bgr++ = bayer[0]; - } - width--; - } - - if (blue_line) { - for ( ; width > 2; width -= 2) { - t0 = (bayer[0] + bayer[2] + 1) >> 1; - *bgr++ = t0; - *bgr++ = bayer[1]; - *bgr++ = adjacent_bayer[1]; - bayer++; - adjacent_bayer++; - - t0 = (bayer[0] + bayer[2] + adjacent_bayer[1] + 1) / 3; - t1 = (adjacent_bayer[0] + adjacent_bayer[2] + 1) >> 1; - *bgr++ = bayer[1]; - *bgr++ = t0; - *bgr++ = t1; - bayer++; - adjacent_bayer++; - } - } else { - for ( ; width > 2; width -= 2) { - t0 = (bayer[0] + bayer[2] + 1) >> 1; - *bgr++ = adjacent_bayer[1]; - *bgr++ = bayer[1]; - *bgr++ = t0; - bayer++; - adjacent_bayer++; - - t0 = (bayer[0] + bayer[2] + adjacent_bayer[1] + 1) / 3; - t1 = (adjacent_bayer[0] + adjacent_bayer[2] + 1) >> 1; - *bgr++ = t1; - *bgr++ = t0; - *bgr++ = bayer[1]; - bayer++; - adjacent_bayer++; - } - } - - if (width == 2) { - /* Second to last pixel */ - t0 = (bayer[0] + bayer[2] + 1) >> 1; - if (blue_line) { - *bgr++ = t0; - *bgr++ = bayer[1]; - *bgr++ = adjacent_bayer[1]; - } else { - *bgr++ = adjacent_bayer[1]; - *bgr++ = bayer[1]; - *bgr++ = t0; - } - /* Last pixel */ - t0 = (bayer[1] + adjacent_bayer[2] + 1) >> 1; - if (blue_line) { - *bgr++ = bayer[2]; - *bgr++ = t0; - *bgr++ = adjacent_bayer[1]; - } else { - *bgr++ = adjacent_bayer[1]; - *bgr++ = t0; - *bgr++ = bayer[2]; - } - } else { - /* Last pixel */ - if (blue_line) { - *bgr++ = bayer[0]; - *bgr++ = bayer[1]; - *bgr++ = adjacent_bayer[1]; - } else { - *bgr++ = adjacent_bayer[1]; - *bgr++ = bayer[1]; - *bgr++ = bayer[0]; - } - } -} - -/* From libdc1394, which on turn was based on OpenCV's Bayer decoding */ -static void bayer_to_rgbbgr24(const unsigned char *bayer, - unsigned char *bgr, int width, int height, unsigned int pixfmt, - int start_with_green, int blue_line) -{ - /* render the first line */ - v4lconvert_border_bayer_line_to_bgr24(bayer, bayer + width, bgr, width, - start_with_green, blue_line); - bgr += width * 3; - - /* reduce height by 2 because of the special case top/bottom line */ - for (height -= 2; height; height--) { - int t0, t1; - /* (width - 2) because of the border */ - const unsigned char *bayerEnd = bayer + (width - 2); - - if (start_with_green) { - /* OpenCV has a bug in the next line, which was - t0 = (bayer[0] + bayer[width * 2] + 1) >> 1; */ - t0 = (bayer[1] + bayer[width * 2 + 1] + 1) >> 1; - /* Write first pixel */ - t1 = (bayer[0] + bayer[width * 2] + bayer[width + 1] + 1) / 3; - if (blue_line) { - *bgr++ = t0; - *bgr++ = t1; - *bgr++ = bayer[width]; - } else { - *bgr++ = bayer[width]; - *bgr++ = t1; - *bgr++ = t0; - } - - /* Write second pixel */ - t1 = (bayer[width] + bayer[width + 2] + 1) >> 1; - if (blue_line) { - *bgr++ = t0; - *bgr++ = bayer[width + 1]; - *bgr++ = t1; - } else { - *bgr++ = t1; - *bgr++ = bayer[width + 1]; - *bgr++ = t0; - } - bayer++; - } else { - /* Write first pixel */ - t0 = (bayer[0] + bayer[width * 2] + 1) >> 1; - if (blue_line) { - *bgr++ = t0; - *bgr++ = bayer[width]; - *bgr++ = bayer[width + 1]; - } else { - *bgr++ = bayer[width + 1]; - *bgr++ = bayer[width]; - *bgr++ = t0; - } - } - - if (blue_line) { - for (; bayer <= bayerEnd - 2; bayer += 2) { - t0 = (bayer[0] + bayer[2] + bayer[width * 2] + - bayer[width * 2 + 2] + 2) >> 2; - t1 = (bayer[1] + bayer[width] + - bayer[width + 2] + bayer[width * 2 + 1] + - 2) >> 2; - *bgr++ = t0; - *bgr++ = t1; - *bgr++ = bayer[width + 1]; - - t0 = (bayer[2] + bayer[width * 2 + 2] + 1) >> 1; - t1 = (bayer[width + 1] + bayer[width + 3] + - 1) >> 1; - *bgr++ = t0; - *bgr++ = bayer[width + 2]; - *bgr++ = t1; - } - } else { - for (; bayer <= bayerEnd - 2; bayer += 2) { - t0 = (bayer[0] + bayer[2] + bayer[width * 2] + - bayer[width * 2 + 2] + 2) >> 2; - t1 = (bayer[1] + bayer[width] + - bayer[width + 2] + bayer[width * 2 + 1] + - 2) >> 2; - *bgr++ = bayer[width + 1]; - *bgr++ = t1; - *bgr++ = t0; - - t0 = (bayer[2] + bayer[width * 2 + 2] + 1) >> 1; - t1 = (bayer[width + 1] + bayer[width + 3] + - 1) >> 1; - *bgr++ = t1; - *bgr++ = bayer[width + 2]; - *bgr++ = t0; - } - } - - if (bayer < bayerEnd) { - /* write second to last pixel */ - t0 = (bayer[0] + bayer[2] + bayer[width * 2] + - bayer[width * 2 + 2] + 2) >> 2; - t1 = (bayer[1] + bayer[width] + - bayer[width + 2] + bayer[width * 2 + 1] + - 2) >> 2; - if (blue_line) { - *bgr++ = t0; - *bgr++ = t1; - *bgr++ = bayer[width + 1]; - } else { - *bgr++ = bayer[width + 1]; - *bgr++ = t1; - *bgr++ = t0; - } - /* write last pixel */ - t0 = (bayer[2] + bayer[width * 2 + 2] + 1) >> 1; - if (blue_line) { - *bgr++ = t0; - *bgr++ = bayer[width + 2]; - *bgr++ = bayer[width + 1]; - } else { - *bgr++ = bayer[width + 1]; - *bgr++ = bayer[width + 2]; - *bgr++ = t0; - } - bayer++; - } else { - /* write last pixel */ - t0 = (bayer[0] + bayer[width * 2] + 1) >> 1; - t1 = (bayer[1] + bayer[width * 2 + 1] + bayer[width] + 1) / 3; - if (blue_line) { - *bgr++ = t0; - *bgr++ = t1; - *bgr++ = bayer[width + 1]; - } else { - *bgr++ = bayer[width + 1]; - *bgr++ = t1; - *bgr++ = t0; - } - } - - /* skip 2 border pixels */ - bayer += 2; - - blue_line = !blue_line; - start_with_green = !start_with_green; - } - - /* render the last line */ - v4lconvert_border_bayer_line_to_bgr24(bayer + width, bayer, bgr, width, - !start_with_green, !blue_line); -} - -void v4lconvert_bayer_to_rgb24(const unsigned char *bayer, - unsigned char *bgr, int width, int height, unsigned int pixfmt) -{ - bayer_to_rgbbgr24(bayer, bgr, width, height, pixfmt, - pixfmt == V4L2_PIX_FMT_SGBRG8 /* start with green */ - || pixfmt == V4L2_PIX_FMT_SGRBG8, - pixfmt != V4L2_PIX_FMT_SBGGR8 /* blue line */ - && pixfmt != V4L2_PIX_FMT_SGBRG8); -} - -void v4lconvert_bayer_to_bgr24(const unsigned char *bayer, - unsigned char *bgr, int width, int height, unsigned int pixfmt) -{ - bayer_to_rgbbgr24(bayer, bgr, width, height, pixfmt, - pixfmt == V4L2_PIX_FMT_SGBRG8 /* start with green */ - || pixfmt == V4L2_PIX_FMT_SGRBG8, - pixfmt == V4L2_PIX_FMT_SBGGR8 /* blue line */ - || pixfmt == V4L2_PIX_FMT_SGBRG8); -} - -static void v4lconvert_border_bayer_line_to_y( - const unsigned char* bayer, const unsigned char* adjacent_bayer, - unsigned char *y, int width, int start_with_green, int blue_line) -{ - int t0, t1; - - if (start_with_green) { - /* First pixel */ - if (blue_line) { - *y++ = (8453*adjacent_bayer[0] + 16594*bayer[0] + 3223*bayer[1] + 524288) - >> 15; - } else { - *y++ = (8453*bayer[1] + 16594*bayer[0] + 3223*adjacent_bayer[0] + 524288) - >> 15; - } - /* Second pixel */ - t0 = bayer[0] + bayer[2] + adjacent_bayer[1]; - t1 = adjacent_bayer[0] + adjacent_bayer[2]; - if (blue_line) { - *y++ = (4226*t1 + 5531*t0 + 3223*bayer[1] + 524288) >> 15; - } else { - *y++ = (8453*bayer[1] + 5531*t0 + 1611*t1 + 524288) >> 15; - } - bayer++; - adjacent_bayer++; - width -= 2; - } else { - /* First pixel */ - t0 = bayer[1] + adjacent_bayer[0]; - if (blue_line) { - *y++ = (8453*adjacent_bayer[1] + 8297*t0 + 3223*bayer[0] + 524288) - >> 15; - } else { - *y++ = (8453*bayer[0] + 8297*t0 + 3223*adjacent_bayer[1] + 524288) - >> 15; - } - width--; - } - - if (blue_line) { - for ( ; width > 2; width -= 2) { - t0 = bayer[0] + bayer[2]; - *y++ = (8453*adjacent_bayer[1] + 16594*bayer[1] + 1611*t0 + 524288) - >> 15; - bayer++; - adjacent_bayer++; - - t0 = bayer[0] + bayer[2] + adjacent_bayer[1]; - t1 = adjacent_bayer[0] + adjacent_bayer[2]; - *y++ = (4226*t1 + 5531*t0 + 3223*bayer[1] + 524288) >> 15; - bayer++; - adjacent_bayer++; - } - } else { - for ( ; width > 2; width -= 2) { - t0 = bayer[0] + bayer[2]; - *y++ = (4226*t0 + 16594*bayer[1] + 3223*adjacent_bayer[1] + 524288) - >> 15; - bayer++; - adjacent_bayer++; - - t0 = bayer[0] + bayer[2] + adjacent_bayer[1]; - t1 = adjacent_bayer[0] + adjacent_bayer[2]; - *y++ = (8453*bayer[1] + 5531*t0 + 1611*t1 + 524288) >> 15; - bayer++; - adjacent_bayer++; - } - } - - if (width == 2) { - /* Second to last pixel */ - t0 = bayer[0] + bayer[2]; - if (blue_line) { - *y++ = (8453*adjacent_bayer[1] + 16594*bayer[1] + 1611*t0 + 524288) - >> 15; - } else { - *y++ = (4226*t0 + 16594*bayer[1] + 3223*adjacent_bayer[1] + 524288) - >> 15; - } - /* Last pixel */ - t0 = bayer[1] + adjacent_bayer[2]; - if (blue_line) { - *y++ = (8453*adjacent_bayer[1] + 8297*t0 + 3223*bayer[2] + 524288) - >> 15; - } else { - *y++ = (8453*bayer[2] + 8297*t0 + 3223*adjacent_bayer[1] + 524288) - >> 15; - } - } else { - /* Last pixel */ - if (blue_line) { - *y++ = (8453*adjacent_bayer[1] + 16594*bayer[1] + 3223*bayer[0] + 524288) - >> 15; - } else { - *y++ = (8453*bayer[0] + 16594*bayer[1] + 3223*adjacent_bayer[1] + 524288) - >> 15; - } - } -} - -void v4lconvert_bayer_to_yuv420(const unsigned char *bayer, - unsigned char *yuv, int width, int height, unsigned int pixfmt) -{ - int blue_line = 0, start_with_green = 0, x, y; - unsigned char *ydst = yuv; - unsigned char *udst = yuv + width * height; - unsigned char *vdst = udst + width * height / 4; - - /* First calculate the u and v planes 2x2 pixels at a time */ - switch (pixfmt) { - case V4L2_PIX_FMT_SBGGR8: - for (y = 0; y < height; y += 2) { - for (x = 0; x < width; x += 2) { - int b, g, r; - b = bayer[x]; - g = bayer[x+1]; - g += bayer[x+width]; - r = bayer[x+width+1]; - *udst++ = (-4878 * r - 4789 * g + 14456 * b + 4210688) >> 15; - *vdst++ = (14456 * r - 6052 * g - 2351 * b + 4210688) >> 15; - } - bayer += 2 * width; - } - blue_line = 1; - break; - - case V4L2_PIX_FMT_SRGGB8: - for (y = 0; y < height; y += 2) { - for (x = 0; x < width; x += 2) { - int b, g, r; - r = bayer[x]; - g = bayer[x+1]; - g += bayer[x+width]; - b = bayer[x+width+1]; - *udst++ = (-4878 * r - 4789 * g + 14456 * b + 4210688) >> 15; - *vdst++ = (14456 * r - 6052 * g - 2351 * b + 4210688) >> 15; - } - bayer += 2 * width; - } - break; - - case V4L2_PIX_FMT_SGBRG8: - for (y = 0; y < height; y += 2) { - for (x = 0; x < width; x += 2) { - int b, g, r; - g = bayer[x]; - b = bayer[x+1]; - r = bayer[x+width]; - g += bayer[x+width+1]; - *udst++ = (-4878 * r - 4789 * g + 14456 * b + 4210688) >> 15; - *vdst++ = (14456 * r - 6052 * g - 2351 * b + 4210688) >> 15; - } - bayer += 2 * width; - } - blue_line = 1; - start_with_green = 1; - break; - - case V4L2_PIX_FMT_SGRBG8: - for (y = 0; y < height; y += 2) { - for (x = 0; x < width; x += 2) { - int b, g, r; - g = bayer[x]; - r = bayer[x+1]; - b = bayer[x+width]; - g += bayer[x+width+1]; - *udst++ = (-4878 * r - 4789 * g + 14456 * b + 4210688) >> 15; - *vdst++ = (14456 * r - 6052 * g - 2351 * b + 4210688) >> 15; - } - bayer += 2 * width; - } - start_with_green = 1; - break; - } - - bayer -= width * height; - - /* render the first line */ - v4lconvert_border_bayer_line_to_y(bayer, bayer + width, ydst, width, - start_with_green, blue_line); - ydst += width; - - /* reduce height by 2 because of the border */ - for (height -= 2; height; height--) { - int t0, t1; - /* (width - 2) because of the border */ - const unsigned char *bayerEnd = bayer + (width - 2); - - if (start_with_green) { - t0 = bayer[1] + bayer[width * 2 + 1]; - /* Write first pixel */ - t1 = bayer[0] + bayer[width * 2] + bayer[width + 1]; - if (blue_line) - *ydst++ = (8453*bayer[width] + 5516*t1 + 1661*t0 + 524288) >> 15; - else - *ydst++ = (4226*t0 + 5516*t1 + 3223*bayer[width] + 524288) >> 15; - - /* Write second pixel */ - t1 = bayer[width] + bayer[width + 2]; - if (blue_line) - *ydst++ = (4226*t1 + 16594*bayer[width+1] + 1611*t0 + 524288) >> 15; - else - *ydst++ = (4226*t0 + 16594*bayer[width+1] + 1611*t1 + 524288) >> 15; - bayer++; - } else { - /* Write first pixel */ - t0 = bayer[0] + bayer[width * 2]; - if (blue_line) { - *ydst++ = (8453*bayer[width+1] + 16594*bayer[width] + 1661*t0 + - 524288) >> 15; - } else { - *ydst++ = (4226*t0 + 16594*bayer[width] + 3223*bayer[width+1] + - 524288) >> 15; - } - } - - if (blue_line) { - for (; bayer <= bayerEnd - 2; bayer += 2) { - t0 = bayer[0] + bayer[2] + bayer[width * 2] + bayer[width * 2 + 2]; - t1 = bayer[1] + bayer[width] + bayer[width + 2] + bayer[width * 2 + 1]; - *ydst++ = (8453*bayer[width+1] + 4148*t1 + 806*t0 + 524288) >> 15; - - t0 = bayer[2] + bayer[width * 2 + 2]; - t1 = bayer[width + 1] + bayer[width + 3]; - *ydst++ = (4226*t1 + 16594*bayer[width+2] + 1611*t0 + 524288) >> 15; - } - } else { - for (; bayer <= bayerEnd - 2; bayer += 2) { - t0 = bayer[0] + bayer[2] + bayer[width * 2] + bayer[width * 2 + 2]; - t1 = bayer[1] + bayer[width] + bayer[width + 2] + bayer[width * 2 + 1]; - *ydst++ = (2113*t0 + 4148*t1 + 3223*bayer[width+1] + 524288) >> 15; - - t0 = bayer[2] + bayer[width * 2 + 2]; - t1 = bayer[width + 1] + bayer[width + 3]; - *ydst++ = (4226*t0 + 16594*bayer[width+2] + 1611*t1 + 524288) >> 15; - } - } - - if (bayer < bayerEnd) { - /* Write second to last pixel */ - t0 = bayer[0] + bayer[2] + bayer[width * 2] + bayer[width * 2 + 2]; - t1 = bayer[1] + bayer[width] + bayer[width + 2] + bayer[width * 2 + 1]; - if (blue_line) - *ydst++ = (8453*bayer[width+1] + 4148*t1 + 806*t0 + 524288) >> 15; - else - *ydst++ = (2113*t0 + 4148*t1 + 3223*bayer[width+1] + 524288) >> 15; - - /* write last pixel */ - t0 = bayer[2] + bayer[width * 2 + 2]; - if (blue_line) { - *ydst++ = (8453*bayer[width+1] + 16594*bayer[width+2] + 1661*t0 + - 524288) >> 15; - } else { - *ydst++ = (4226*t0 + 16594*bayer[width+2] + 3223*bayer[width+1] + - 524288) >> 15; - } - bayer++; - } else { - /* write last pixel */ - t0 = bayer[0] + bayer[width * 2]; - t1 = bayer[1] + bayer[width * 2 + 1] + bayer[width]; - if (blue_line) - *ydst++ = (8453*bayer[width+1] + 5516*t1 + 1661*t0 + 524288) >> 15; - else - *ydst++ = (4226*t0 + 5516*t1 + 3223*bayer[width+1] + 524288) >> 15; - } - - /* skip 2 border pixels */ - bayer += 2; - - blue_line = !blue_line; - start_with_green = !start_with_green; - } - - /* render the last line */ - v4lconvert_border_bayer_line_to_y(bayer + width, bayer, ydst, width, - !start_with_green, !blue_line); -} diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/flip.c b/v4l2-apps/lib/libv4l/libv4lconvert/flip.c deleted file mode 100644 index cd3468a89..000000000 --- a/v4l2-apps/lib/libv4l/libv4lconvert/flip.c +++ /dev/null @@ -1,107 +0,0 @@ -/* - -# RGB / YUV flip/rotate routines - -# (C) 2008 Hans de Goede - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 2.1 of the License, or -# (at your option) any later version. -# -# 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 Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include "libv4lconvert-priv.h" - -void v4lconvert_rotate180_rgbbgr24(const unsigned char *src, unsigned char *dst, - int width, int height) -{ - int i; - - src += 3 * width * height - 3; - - for (i = 0; i < width * height; i++) { - dst[0] = src[0]; - dst[1] = src[1]; - dst[2] = src[2]; - dst += 3; - src -= 3; - } -} - -void v4lconvert_rotate180_yuv420(const unsigned char *src, unsigned char *dst, - int width, int height) -{ - int i; - - /* First flip x and y of the Y plane */ - src += width * height - 1; - for (i = 0; i < width * height; i++) - *dst++ = *src--; - - /* Now flip the U plane */ - src += width * height * 5 / 4; - for (i = 0; i < width * height / 4; i++) - *dst++ = *src--; - - /* Last flip the V plane */ - src += width * height / 2; - for (i = 0; i < width * height / 4; i++) - *dst++ = *src--; -} - -void v4lconvert_rotate90_rgbbgr24(const unsigned char *src, unsigned char *dst, - int destwidth, int destheight) -{ - int x, y; -#define srcwidth destheight -#define srcheight destwidth - - for (y = 0; y < destheight; y++) - for (x = 0; x < destwidth; x++) { - int offset = ((srcheight - x - 1) * srcwidth + y) * 3; - *dst++ = src[offset++]; - *dst++ = src[offset++]; - *dst++ = src[offset]; - } -} - -void v4lconvert_rotate90_yuv420(const unsigned char *src, unsigned char *dst, - int destwidth, int destheight) -{ - int x, y; - - /* Y-plane */ - for (y = 0; y < destheight; y++) - for (x = 0; x < destwidth; x++) { - int offset = (srcheight - x - 1) * srcwidth + y; - *dst++ = src[offset]; - } - - /* U-plane */ - src += srcwidth * srcheight; - destwidth /= 2; - destheight /= 2; - for (y = 0; y < destheight; y++) - for (x = 0; x < destwidth; x++) { - int offset = (srcheight - x - 1) * srcwidth + y; - *dst++ = src[offset]; - } - - /* V-plane */ - src += srcwidth * srcheight; - for (y = 0; y < destheight; y++) - for (x = 0; x < destwidth; x++) { - int offset = (srcheight - x - 1) * srcwidth + y; - *dst++ = src[offset]; - } -} diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/jidctflt.c b/v4l2-apps/lib/libv4l/libv4lconvert/jidctflt.c deleted file mode 100644 index 532abc7ea..000000000 --- a/v4l2-apps/lib/libv4l/libv4lconvert/jidctflt.c +++ /dev/null @@ -1,286 +0,0 @@ -/* - * jidctflt.c - * - * Copyright (C) 1994-1998, Thomas G. Lane. - * This file is part of the Independent JPEG Group's software. - * - * The authors make NO WARRANTY or representation, either express or implied, - * with respect to this software, its quality, accuracy, merchantability, or - * fitness for a particular purpose. This software is provided "AS IS", and you, - * its user, assume the entire risk as to its quality and accuracy. - * - * This software is copyright (C) 1991-1998, Thomas G. Lane. - * All Rights Reserved except as specified below. - * - * Permission is hereby granted to use, copy, modify, and distribute this - * software (or portions thereof) for any purpose, without fee, subject to these - * conditions: - * (1) If any part of the source code for this software is distributed, then this - * README file must be included, with this copyright and no-warranty notice - * unaltered; and any additions, deletions, or changes to the original files - * must be clearly indicated in accompanying documentation. - * (2) If only executable code is distributed, then the accompanying - * documentation must state that "this software is based in part on the work of - * the Independent JPEG Group". - * (3) Permission for use of this software is granted only if the user accepts - * full responsibility for any undesirable consequences; the authors accept - * NO LIABILITY for damages of any kind. - * - * These conditions apply to any software derived from or based on the IJG code, - * not just to the unmodified library. If you use our work, you ought to - * acknowledge us. - * - * Permission is NOT granted for the use of any IJG author's name or company name - * in advertising or publicity relating to this software or products derived from - * it. This software may be referred to only as "the Independent JPEG Group's - * software". - * - * We specifically permit and encourage the use of this software as the basis of - * commercial products, provided that all warranty or liability claims are - * assumed by the product vendor. - * - * - * This file contains a floating-point implementation of the - * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine - * must also perform dequantization of the input coefficients. - * - * This implementation should be more accurate than either of the integer - * IDCT implementations. However, it may not give the same results on all - * machines because of differences in roundoff behavior. Speed will depend - * on the hardware's floating point capacity. - * - * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT - * on each row (or vice versa, but it's more convenient to emit a row at - * a time). Direct algorithms are also available, but they are much more - * complex and seem not to be any faster when reduced to code. - * - * This implementation is based on Arai, Agui, and Nakajima's algorithm for - * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in - * Japanese, but the algorithm is described in the Pennebaker & Mitchell - * JPEG textbook (see REFERENCES section in file README). The following code - * is based directly on figure 4-8 in P&M. - * While an 8-point DCT cannot be done in less than 11 multiplies, it is - * possible to arrange the computation so that many of the multiplies are - * simple scalings of the final outputs. These multiplies can then be - * folded into the multiplications or divisions by the JPEG quantization - * table entries. The AA&N method leaves only 5 multiplies and 29 adds - * to be done in the DCT itself. - * The primary disadvantage of this method is that with a fixed-point - * implementation, accuracy is lost due to imprecise representation of the - * scaled quantization values. However, that problem does not arise if - * we use floating point arithmetic. - */ - -#include -#include "tinyjpeg-internal.h" - -#define FAST_FLOAT float -#define DCTSIZE 8 -#define DCTSIZE2 (DCTSIZE*DCTSIZE) - -#define DEQUANTIZE(coef,quantval) (((FAST_FLOAT) (coef)) * (quantval)) - -#if defined(__GNUC__) && (defined(__i686__) || defined(__x86_64__)) - -static inline unsigned char descale_and_clamp(int x, int shift) -{ - __asm__ ( - "add %3,%1\n" - "\tsar %2,%1\n" - "\tsub $-128,%1\n" - "\tcmovl %5,%1\n" /* Use the sub to compare to 0 */ - "\tcmpl %4,%1\n" - "\tcmovg %4,%1\n" - : "=r"(x) - : "0"(x), "Ic"((unsigned char)shift), "ir"(1U<<(shift-1)), "r" (0xff), "r" (0) - ); - return x; -} - -#else -static inline unsigned char descale_and_clamp(int x, int shift) -{ - x += (1UL<<(shift-1)); - if (x<0) - x = (x >> shift) | ((~(0UL)) << (32-(shift))); - else - x >>= shift; - x += 128; - if (x>255) - return 255; - else if (x<0) - return 0; - else - return x; -} -#endif - -/* - * Perform dequantization and inverse DCT on one block of coefficients. - */ - -void -tinyjpeg_idct_float (struct component *compptr, uint8_t *output_buf, int stride) -{ - FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; - FAST_FLOAT tmp10, tmp11, tmp12, tmp13; - FAST_FLOAT z5, z10, z11, z12, z13; - int16_t *inptr; - FAST_FLOAT *quantptr; - FAST_FLOAT *wsptr; - uint8_t *outptr; - int ctr; - FAST_FLOAT workspace[DCTSIZE2]; /* buffers data between passes */ - - /* Pass 1: process columns from input, store into work array. */ - - inptr = compptr->DCT; - quantptr = compptr->Q_table; - wsptr = workspace; - for (ctr = DCTSIZE; ctr > 0; ctr--) { - /* Due to quantization, we will usually find that many of the input - * coefficients are zero, especially the AC terms. We can exploit this - * by short-circuiting the IDCT calculation for any column in which all - * the AC terms are zero. In that case each output is equal to the - * DC coefficient (with scale factor as needed). - * With typical images and quantization tables, half or more of the - * column DCT calculations can be simplified this way. - */ - - if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && - inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && - inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && - inptr[DCTSIZE*7] == 0) { - /* AC terms all zero */ - FAST_FLOAT dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - - wsptr[DCTSIZE*0] = dcval; - wsptr[DCTSIZE*1] = dcval; - wsptr[DCTSIZE*2] = dcval; - wsptr[DCTSIZE*3] = dcval; - wsptr[DCTSIZE*4] = dcval; - wsptr[DCTSIZE*5] = dcval; - wsptr[DCTSIZE*6] = dcval; - wsptr[DCTSIZE*7] = dcval; - - inptr++; /* advance pointers to next column */ - quantptr++; - wsptr++; - continue; - } - - /* Even part */ - - tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); - tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); - tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); - tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); - - tmp10 = tmp0 + tmp2; /* phase 3 */ - tmp11 = tmp0 - tmp2; - - tmp13 = tmp1 + tmp3; /* phases 5-3 */ - tmp12 = (tmp1 - tmp3) * ((FAST_FLOAT) 1.414213562) - tmp13; /* 2*c4 */ - - tmp0 = tmp10 + tmp13; /* phase 2 */ - tmp3 = tmp10 - tmp13; - tmp1 = tmp11 + tmp12; - tmp2 = tmp11 - tmp12; - - /* Odd part */ - - tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); - tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); - tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); - tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); - - z13 = tmp6 + tmp5; /* phase 6 */ - z10 = tmp6 - tmp5; - z11 = tmp4 + tmp7; - z12 = tmp4 - tmp7; - - tmp7 = z11 + z13; /* phase 5 */ - tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); /* 2*c4 */ - - z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ - tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */ - tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */ - - tmp6 = tmp12 - tmp7; /* phase 2 */ - tmp5 = tmp11 - tmp6; - tmp4 = tmp10 + tmp5; - - wsptr[DCTSIZE*0] = tmp0 + tmp7; - wsptr[DCTSIZE*7] = tmp0 - tmp7; - wsptr[DCTSIZE*1] = tmp1 + tmp6; - wsptr[DCTSIZE*6] = tmp1 - tmp6; - wsptr[DCTSIZE*2] = tmp2 + tmp5; - wsptr[DCTSIZE*5] = tmp2 - tmp5; - wsptr[DCTSIZE*4] = tmp3 + tmp4; - wsptr[DCTSIZE*3] = tmp3 - tmp4; - - inptr++; /* advance pointers to next column */ - quantptr++; - wsptr++; - } - - /* Pass 2: process rows from work array, store into output array. */ - /* Note that we must descale the results by a factor of 8 == 2**3. */ - - wsptr = workspace; - outptr = output_buf; - for (ctr = 0; ctr < DCTSIZE; ctr++) { - /* Rows of zeroes can be exploited in the same way as we did with columns. - * However, the column calculation has created many nonzero AC terms, so - * the simplification applies less often (typically 5% to 10% of the time). - * And testing floats for zero is relatively expensive, so we don't bother. - */ - - /* Even part */ - - tmp10 = wsptr[0] + wsptr[4]; - tmp11 = wsptr[0] - wsptr[4]; - - tmp13 = wsptr[2] + wsptr[6]; - tmp12 = (wsptr[2] - wsptr[6]) * ((FAST_FLOAT) 1.414213562) - tmp13; - - tmp0 = tmp10 + tmp13; - tmp3 = tmp10 - tmp13; - tmp1 = tmp11 + tmp12; - tmp2 = tmp11 - tmp12; - - /* Odd part */ - - z13 = wsptr[5] + wsptr[3]; - z10 = wsptr[5] - wsptr[3]; - z11 = wsptr[1] + wsptr[7]; - z12 = wsptr[1] - wsptr[7]; - - tmp7 = z11 + z13; - tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); - - z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ - tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */ - tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */ - - tmp6 = tmp12 - tmp7; - tmp5 = tmp11 - tmp6; - tmp4 = tmp10 + tmp5; - - /* Final output stage: scale down by a factor of 8 and range-limit */ - - outptr[0] = descale_and_clamp((int)(tmp0 + tmp7), 3); - outptr[7] = descale_and_clamp((int)(tmp0 - tmp7), 3); - outptr[1] = descale_and_clamp((int)(tmp1 + tmp6), 3); - outptr[6] = descale_and_clamp((int)(tmp1 - tmp6), 3); - outptr[2] = descale_and_clamp((int)(tmp2 + tmp5), 3); - outptr[5] = descale_and_clamp((int)(tmp2 - tmp5), 3); - outptr[4] = descale_and_clamp((int)(tmp3 + tmp4), 3); - outptr[3] = descale_and_clamp((int)(tmp3 - tmp4), 3); - - - wsptr += DCTSIZE; /* advance pointer to next row */ - outptr += stride; - } -} - diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h b/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h deleted file mode 100644 index 0c4eff6ce..000000000 --- a/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert-priv.h +++ /dev/null @@ -1,166 +0,0 @@ -/* -# (C) 2008 Hans de Goede - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 2.1 of the License, or -# (at your option) any later version. -# -# 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 Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef __LIBV4LCONVERT_PRIV_H -#define __LIBV4LCONVERT_PRIV_H - -#include -#include "libv4lconvert.h" -#include "tinyjpeg.h" - -#ifndef V4L2_PIX_FMT_SPCA501 -#define V4L2_PIX_FMT_SPCA501 v4l2_fourcc('S','5','0','1') /* YUYV per line */ -#endif - -#ifndef V4L2_PIX_FMT_SPCA505 -#define V4L2_PIX_FMT_SPCA505 v4l2_fourcc('S','5','0','5') /* YYUV per line */ -#endif - -#ifndef V4L2_PIX_FMT_SPCA508 -#define V4L2_PIX_FMT_SPCA508 v4l2_fourcc('S','5','0','8') /* YUVY per line */ -#endif - -#ifndef V4L2_PIX_FMT_SPCA561 -#define V4L2_PIX_FMT_SPCA561 v4l2_fourcc('S','5','6','1') -#endif - -#ifndef V4L2_PIX_FMT_PAC207 -#define V4L2_PIX_FMT_PAC207 v4l2_fourcc('P','2','0','7') -#endif - -#ifndef V4L2_PIX_FMT_PJPG -#define V4L2_PIX_FMT_PJPG v4l2_fourcc('P', 'J', 'P', 'G') -#endif - -#ifndef V4L2_PIX_FMT_SGBRG8 -#define V4L2_PIX_FMT_SGBRG8 v4l2_fourcc('G','B','R','G') -#endif - -#ifndef V4L2_PIX_FMT_SGRBG8 -#define V4L2_PIX_FMT_SGRBG8 v4l2_fourcc('G','R','B','G') -#endif - -#ifndef V4L2_PIX_FMT_SRGGB8 -#define V4L2_PIX_FMT_SRGGB8 v4l2_fourcc('R','G','G','B') -#endif - -#ifndef V4L2_PIX_FMT_YVYU -#define V4L2_PIX_FMT_YVYU v4l2_fourcc('Y', 'V', 'Y', 'U') -#endif - -#define V4LCONVERT_ERROR_MSG_SIZE 256 -#define V4LCONVERT_MAX_FRAMESIZES 16 - -#define V4LCONVERT_ERR(...) \ - snprintf(data->error_msg, V4LCONVERT_ERROR_MSG_SIZE, \ - "v4l-convert: error " __VA_ARGS__) - -/* Card flags */ -#define V4LCONVERT_UPSIDE_DOWN 0x01 - -/* Pixformat flags */ -#define V4LCONVERT_COMPRESSED 0x01 - -struct v4lconvert_data { - int fd; - int flags; /* bitfield */ - int supported_src_formats; /* bitfield */ - unsigned int no_formats; - char error_msg[V4LCONVERT_ERROR_MSG_SIZE]; - struct jdec_private *jdec; - struct v4l2_frmsizeenum framesizes[V4LCONVERT_MAX_FRAMESIZES]; - unsigned int no_framesizes; -}; - -struct v4lconvert_flags_info { - const char *card; - int flags; -}; - -struct v4lconvert_pixfmt { - unsigned int fmt; - int flags; -}; - -void v4lconvert_yuv420_to_rgb24(const unsigned char *src, unsigned char *dst, - int width, int height); - -void v4lconvert_yuv420_to_bgr24(const unsigned char *src, unsigned char *dst, - int width, int height); - -void v4lconvert_yuyv_to_rgb24(const unsigned char *src, unsigned char *dst, - int width, int height); - -void v4lconvert_yuyv_to_bgr24(const unsigned char *src, unsigned char *dst, - int width, int height); - -void v4lconvert_yuyv_to_yuv420(const unsigned char *src, unsigned char *dst, - int width, int height); - -void v4lconvert_yvyu_to_rgb24(const unsigned char *src, unsigned char *dst, - int width, int height); - -void v4lconvert_yvyu_to_bgr24(const unsigned char *src, unsigned char *dst, - int width, int height); - -void v4lconvert_yvyu_to_yuv420(const unsigned char *src, unsigned char *dst, - int width, int height); - -void v4lconvert_swap_rgb(const unsigned char *src, unsigned char *dst, - int width, int height); - -void v4lconvert_spca501_to_yuv420(const unsigned char *src, unsigned char *dst, - int width, int height); - -void v4lconvert_spca505_to_yuv420(const unsigned char *src, unsigned char *dst, - int width, int height); - -void v4lconvert_spca508_to_yuv420(const unsigned char *src, unsigned char *dst, - int width, int height); - -void v4lconvert_decode_spca561(const unsigned char *src, unsigned char *dst, - int width, int height); - -void v4lconvert_decode_sn9c10x(const unsigned char *src, unsigned char *dst, - int width, int height); - -void v4lconvert_decode_pac207(const unsigned char *src, unsigned char *dst, - int width, int height); - -void v4lconvert_bayer_to_rgb24(const unsigned char *bayer, - unsigned char *rgb, int width, int height, unsigned int pixfmt); - -void v4lconvert_bayer_to_bgr24(const unsigned char *bayer, - unsigned char *rgb, int width, int height, unsigned int pixfmt); - -void v4lconvert_bayer_to_yuv420(const unsigned char *bayer, - unsigned char *yuv, int width, int height, unsigned int pixfmt); - -void v4lconvert_rotate90_rgbbgr24(const unsigned char *src, unsigned char *dst, - int destwidth, int destheight); - -void v4lconvert_rotate90_yuv420(const unsigned char *src, unsigned char *dst, - int destwidth, int destheight); - -void v4lconvert_rotate180_rgbbgr24(const unsigned char *src, unsigned char *dst, - int width, int height); - -void v4lconvert_rotate180_yuv420(const unsigned char *src, unsigned char *dst, - int width, int height); - -#endif diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c b/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c deleted file mode 100644 index 93bc67c7e..000000000 --- a/v4l2-apps/lib/libv4l/libv4lconvert/libv4lconvert.c +++ /dev/null @@ -1,737 +0,0 @@ -/* -# (C) 2008 Hans de Goede - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 2.1 of the License, or -# (at your option) any later version. -# -# 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 Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include -#include -#include -#include -#include -#include "libv4lconvert.h" -#include "libv4lconvert-priv.h" - -#define MIN(a,b) (((a)<(b))?(a):(b)) -#define ARRAY_SIZE(x) ((int)sizeof(x)/(int)sizeof((x)[0])) - -/* Note for proper functioning of v4lconvert_enum_fmt the first entries in - supported_src_pixfmts must match with the entries in supported_dst_pixfmts */ -#define SUPPORTED_DST_PIXFMTS \ - { V4L2_PIX_FMT_RGB24, 0 }, \ - { V4L2_PIX_FMT_BGR24, 0 }, \ - { V4L2_PIX_FMT_YUV420, 0 } - -static void v4lconvert_get_framesizes(struct v4lconvert_data *data, - unsigned int pixelformat); - -/* Note uncompressed formats must go first so that they are prefered by - v4lconvert_try_format for low resolutions */ -static const struct v4lconvert_pixfmt supported_src_pixfmts[] = { - SUPPORTED_DST_PIXFMTS, - { V4L2_PIX_FMT_YUYV, 0 }, - { V4L2_PIX_FMT_YVYU, 0 }, - { V4L2_PIX_FMT_SBGGR8, 0 }, - { V4L2_PIX_FMT_SGBRG8, 0 }, - { V4L2_PIX_FMT_SGRBG8, 0 }, - { V4L2_PIX_FMT_SRGGB8, 0 }, - { V4L2_PIX_FMT_SPCA501, 0 }, - { V4L2_PIX_FMT_SPCA505, 0 }, - { V4L2_PIX_FMT_SPCA508, 0 }, - { V4L2_PIX_FMT_MJPEG, V4LCONVERT_COMPRESSED }, - { V4L2_PIX_FMT_JPEG, V4LCONVERT_COMPRESSED }, - { V4L2_PIX_FMT_SPCA561, V4LCONVERT_COMPRESSED }, - { V4L2_PIX_FMT_SN9C10X, V4LCONVERT_COMPRESSED }, - { V4L2_PIX_FMT_PAC207, V4LCONVERT_COMPRESSED }, - { V4L2_PIX_FMT_PJPG, V4LCONVERT_COMPRESSED }, -}; - -static const struct v4lconvert_pixfmt supported_dst_pixfmts[] = { - SUPPORTED_DST_PIXFMTS -}; - -/* List of cams which need special flags */ -static const struct v4lconvert_flags_info v4lconvert_flags[] = { - { "SPC 200NC ", V4LCONVERT_UPSIDE_DOWN }, - { "SPC 300NC ", V4LCONVERT_UPSIDE_DOWN }, - { "USB Camera (0471:0325)", V4LCONVERT_UPSIDE_DOWN }, /* SPC200NC */ - { "USB Camera (0471:0326)", V4LCONVERT_UPSIDE_DOWN }, /* SPC300NC */ - { "USB Camera (093a:2476)", V4LCONVERT_UPSIDE_DOWN }, /* Genius E-M 112 */ -}; - -struct v4lconvert_data *v4lconvert_create(int fd) -{ - int i, j; - struct v4lconvert_data *data = calloc(1, sizeof(struct v4lconvert_data)); - struct v4l2_capability cap; - - if (!data) - return NULL; - - data->fd = fd; - data->jdec = NULL; - - /* Check supported formats */ - for (i = 0; ; i++) { - struct v4l2_fmtdesc fmt = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE }; - - fmt.index = i; - - if (syscall(SYS_ioctl, fd, VIDIOC_ENUM_FMT, &fmt)) - break; - - for (j = 0; j < ARRAY_SIZE(supported_src_pixfmts); j++) - if (fmt.pixelformat == supported_src_pixfmts[j].fmt) { - data->supported_src_formats |= 1 << j; - break; - } - - v4lconvert_get_framesizes(data, fmt.pixelformat); - } - - data->no_formats = i; - - /* Check if this cam has any special flags */ - if (syscall(SYS_ioctl, fd, VIDIOC_QUERYCAP, &cap) == 0) { - for (i = 0; i < ARRAY_SIZE(v4lconvert_flags); i++) - if (!strcmp((const char *)v4lconvert_flags[i].card, (char *)cap.card)) { - data->flags = v4lconvert_flags[i].flags; - break; - } - } - - return data; -} - -void v4lconvert_destroy(struct v4lconvert_data *data) -{ - if (data->jdec) { - unsigned char *comps[3] = { NULL, NULL, NULL }; - tinyjpeg_set_components(data->jdec, comps, 3); - tinyjpeg_free(data->jdec); - } - free(data); -} - -static int v4lconvert_supported_dst_format(unsigned int pixelformat) -{ - int i; - - for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) - if (supported_dst_pixfmts[i].fmt == pixelformat) - break; - - return i != ARRAY_SIZE(supported_dst_pixfmts); -} - -/* See libv4lconvert.h for description of in / out parameters */ -int v4lconvert_enum_fmt(struct v4lconvert_data *data, struct v4l2_fmtdesc *fmt) -{ - int i, no_faked_fmts = 0; - unsigned int faked_fmts[ARRAY_SIZE(supported_dst_pixfmts)]; - - if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || - fmt->index < data->no_formats || - !data->supported_src_formats) - return syscall(SYS_ioctl, data->fd, VIDIOC_ENUM_FMT, fmt); - - for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) - if (!(data->supported_src_formats & (1 << i))) { - faked_fmts[no_faked_fmts] = supported_dst_pixfmts[i].fmt; - no_faked_fmts++; - } - - i = fmt->index - data->no_formats; - if (i >= no_faked_fmts) { - errno = EINVAL; - return -1; - } - - fmt->flags = 0; - fmt->pixelformat = faked_fmts[i]; - fmt->description[0] = faked_fmts[i] & 0xff; - fmt->description[1] = (faked_fmts[i] >> 8) & 0xff; - fmt->description[2] = (faked_fmts[i] >> 16) & 0xff; - fmt->description[3] = faked_fmts[i] >> 24; - fmt->description[4] = '\0'; - memset(fmt->reserved, 0, 4); - - return 0; -} - -/* See libv4lconvert.h for description of in / out parameters */ -int v4lconvert_try_format(struct v4lconvert_data *data, - struct v4l2_format *dest_fmt, struct v4l2_format *src_fmt) -{ - int i; - unsigned int closest_fmt_size_diff = -1; - unsigned int desired_pixfmt = dest_fmt->fmt.pix.pixelformat; - struct v4l2_format try_fmt, closest_fmt = { .type = 0 }; - - /* Can we do conversion to the requested format & type? */ - if (!v4lconvert_supported_dst_format(desired_pixfmt) || - dest_fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { - int ret = syscall(SYS_ioctl, data->fd, VIDIOC_TRY_FMT, dest_fmt); - if (src_fmt) - *src_fmt = *dest_fmt; - return ret; - } - - for (i = 0; i < ARRAY_SIZE(supported_src_pixfmts); i++) { - /* is this format supported? */ - if (!(data->supported_src_formats & (1 << i))) - continue; - - try_fmt = *dest_fmt; - try_fmt.fmt.pix.pixelformat = supported_src_pixfmts[i].fmt; - - if (!syscall(SYS_ioctl, data->fd, VIDIOC_TRY_FMT, &try_fmt)) - { - if (try_fmt.fmt.pix.pixelformat == supported_src_pixfmts[i].fmt) { - int size_x_diff = abs((int)try_fmt.fmt.pix.width - - (int)dest_fmt->fmt.pix.width); - int size_y_diff = abs((int)try_fmt.fmt.pix.height - - (int)dest_fmt->fmt.pix.height); - unsigned int size_diff = size_x_diff * size_x_diff + - size_y_diff * size_y_diff; - if (size_diff < closest_fmt_size_diff || - (size_diff == closest_fmt_size_diff && - (supported_src_pixfmts[i].fmt == desired_pixfmt || - ((try_fmt.fmt.pix.width > 176 || try_fmt.fmt.pix.height > 144) && - (supported_src_pixfmts[i].flags & V4LCONVERT_COMPRESSED))))) { - closest_fmt_size_diff = size_diff; - closest_fmt = try_fmt; - } - } - } - } - - if (closest_fmt.type == 0) { - int ret = syscall(SYS_ioctl, data->fd, VIDIOC_TRY_FMT, dest_fmt); - if (src_fmt) - *src_fmt = *dest_fmt; - return ret; - } - - *dest_fmt = closest_fmt; - - /* Are we converting? */ - if (closest_fmt.fmt.pix.pixelformat != desired_pixfmt) { - dest_fmt->fmt.pix.pixelformat = desired_pixfmt; - switch (dest_fmt->fmt.pix.pixelformat) { - case V4L2_PIX_FMT_RGB24: - case V4L2_PIX_FMT_BGR24: - dest_fmt->fmt.pix.bytesperline = dest_fmt->fmt.pix.width * 3; - dest_fmt->fmt.pix.sizeimage = dest_fmt->fmt.pix.width * - dest_fmt->fmt.pix.height * 3; - break; - case V4L2_PIX_FMT_YUV420: - dest_fmt->fmt.pix.bytesperline = dest_fmt->fmt.pix.width; - dest_fmt->fmt.pix.sizeimage = (dest_fmt->fmt.pix.width * - dest_fmt->fmt.pix.height * 3) / 2; - break; - } - } - - if (src_fmt) - *src_fmt = closest_fmt; - - return 0; -} - -/* Is conversion necessary ? */ -int v4lconvert_needs_conversion(struct v4lconvert_data *data, - const struct v4l2_format *src_fmt, /* in */ - const struct v4l2_format *dest_fmt) /* in */ -{ - if(memcmp(src_fmt, dest_fmt, sizeof(*src_fmt))) - return 1; /* Formats differ */ - - if (!(data->flags & V4LCONVERT_UPSIDE_DOWN)) - return 0; /* Formats identical and we don't need flip */ - - /* Formats are identical, but we need flip, do we support the dest_fmt? */ - if (!v4lconvert_supported_dst_format(dest_fmt->fmt.pix.pixelformat)) - return 0; /* Needs flip but we cannot do it :( */ - else - return 1; /* Needs flip and thus conversion */ -} - -int v4lconvert_convert(struct v4lconvert_data *data, - const struct v4l2_format *src_fmt, /* in */ - const struct v4l2_format *dest_fmt, /* in */ - unsigned char *src, int src_size, unsigned char *_dest, int dest_size) -{ - unsigned int header_width, header_height; - int result, needed, rotate = 0, jpeg_flags = TINYJPEG_FLAGS_MJPEG_TABLE; - unsigned char *components[3]; - unsigned char *dest = _dest; - - /* Special case when no conversion is needed */ - if (!v4lconvert_needs_conversion(data, src_fmt, dest_fmt)) { - int to_copy = MIN(dest_size, src_size); - memcpy(dest, src, to_copy); - return to_copy; - } - - /* sanity check, is the dest buffer large enough? */ - switch (dest_fmt->fmt.pix.pixelformat) { - case V4L2_PIX_FMT_RGB24: - case V4L2_PIX_FMT_BGR24: - needed = dest_fmt->fmt.pix.width * dest_fmt->fmt.pix.height * 3; - break; - case V4L2_PIX_FMT_YUV420: - needed = (dest_fmt->fmt.pix.width * dest_fmt->fmt.pix.height * 3) / 2; - break; - default: - V4LCONVERT_ERR("Unknown dest format in conversion\n"); - errno = EINVAL; - return -1; - } - - if (dest_size < needed) { - V4LCONVERT_ERR("destination buffer too small\n"); - errno = EFAULT; - return -1; - } - - if (data->flags & V4LCONVERT_UPSIDE_DOWN) { - rotate = 180; - dest = alloca(needed); - } - - switch (src_fmt->fmt.pix.pixelformat) { - case V4L2_PIX_FMT_PJPG: - jpeg_flags |= TINYJPEG_FLAGS_PIXART_JPEG; - /* Fall through */ - case V4L2_PIX_FMT_MJPEG: - case V4L2_PIX_FMT_JPEG: - if (!data->jdec) { - data->jdec = tinyjpeg_init(); - if (!data->jdec) { - V4LCONVERT_ERR("out of memory!\n"); - errno = ENOMEM; - return -1; - } - } - tinyjpeg_set_flags(data->jdec, jpeg_flags); - if (tinyjpeg_parse_header(data->jdec, src, src_size)) { - V4LCONVERT_ERR("parsing JPEG header: %s\n", - tinyjpeg_get_errorstring(data->jdec)); - errno = EIO; - return -1; - } - tinyjpeg_get_size(data->jdec, &header_width, &header_height); - - if (header_width != dest_fmt->fmt.pix.width || - header_height != dest_fmt->fmt.pix.height) { - /* Check for (pixart) rotated JPEG */ - if (header_width == dest_fmt->fmt.pix.height || - header_height == dest_fmt->fmt.pix.width) { - if (!rotate) - dest = alloca(needed); - rotate += 90; - } else { - V4LCONVERT_ERR("unexpected width / height in JPEG header" - "expected: %ux%u, header: %ux%u\n", - dest_fmt->fmt.pix.width, dest_fmt->fmt.pix.height, - header_width, header_height); - errno = EIO; - return -1; - } - } - - components[0] = dest; - components[1] = components[0] + dest_fmt->fmt.pix.width * - dest_fmt->fmt.pix.height; - components[2] = components[1] + (dest_fmt->fmt.pix.width * - dest_fmt->fmt.pix.height) / 4; - - switch (dest_fmt->fmt.pix.pixelformat) { - case V4L2_PIX_FMT_RGB24: - tinyjpeg_set_components(data->jdec, components, 1); - result = tinyjpeg_decode(data->jdec, TINYJPEG_FMT_RGB24); - break; - case V4L2_PIX_FMT_BGR24: - tinyjpeg_set_components(data->jdec, components, 1); - result = tinyjpeg_decode(data->jdec, TINYJPEG_FMT_BGR24); - break; - default: - tinyjpeg_set_components(data->jdec, components, 3); - result = tinyjpeg_decode(data->jdec, TINYJPEG_FMT_YUV420P); - break; - } - - if (result) { - /* Pixart webcam's seem to regulary generate corrupt frames, which - are best thrown away to avoid flashes in the video stream. Tell - the upper layer this is an intermediate fault and it should try - again with a new buffer by setting errno to EAGAIN */ - if (src_fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_PJPG) { - V4LCONVERT_ERR("Error decompressing JPEG: %s", - tinyjpeg_get_errorstring(data->jdec)); - errno = EAGAIN; - return -1; - } else { - /* If the JPEG header checked out ok and we get an error during actual - decompression, log the error, but don't return an errorcode to the - application, so that the user gets what we managed to decompress */ - fprintf(stderr, "libv4lconvert: Error decompressing JPEG: %s", - tinyjpeg_get_errorstring(data->jdec)); - } - } - break; - - case V4L2_PIX_FMT_SBGGR8: - case V4L2_PIX_FMT_SGBRG8: - case V4L2_PIX_FMT_SGRBG8: - case V4L2_PIX_FMT_SRGGB8: - switch (dest_fmt->fmt.pix.pixelformat) { - case V4L2_PIX_FMT_RGB24: - v4lconvert_bayer_to_rgb24(src, dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height, src_fmt->fmt.pix.pixelformat); - break; - case V4L2_PIX_FMT_BGR24: - v4lconvert_bayer_to_bgr24(src, dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height, src_fmt->fmt.pix.pixelformat); - break; - default: - v4lconvert_bayer_to_yuv420(src, dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height, src_fmt->fmt.pix.pixelformat); - break; - } - break; - - /* YUYV line by line formats */ - case V4L2_PIX_FMT_SPCA501: - case V4L2_PIX_FMT_SPCA505: - case V4L2_PIX_FMT_SPCA508: - { - unsigned char tmpbuf[dest_fmt->fmt.pix.width * dest_fmt->fmt.pix.height * - 3 / 2]; - unsigned char *my_dst = (dest_fmt->fmt.pix.pixelformat != - V4L2_PIX_FMT_YUV420) ? tmpbuf : dest; - - switch (src_fmt->fmt.pix.pixelformat) { - case V4L2_PIX_FMT_SPCA501: - v4lconvert_spca501_to_yuv420(src, my_dst, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - break; - case V4L2_PIX_FMT_SPCA505: - v4lconvert_spca505_to_yuv420(src, my_dst, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - break; - case V4L2_PIX_FMT_SPCA508: - v4lconvert_spca508_to_yuv420(src, my_dst, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - break; - } - - switch (dest_fmt->fmt.pix.pixelformat) { - case V4L2_PIX_FMT_RGB24: - v4lconvert_yuv420_to_rgb24(tmpbuf, dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - break; - case V4L2_PIX_FMT_BGR24: - v4lconvert_yuv420_to_bgr24(tmpbuf, dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - break; - } - break; - } - - /* compressed bayer formats */ - case V4L2_PIX_FMT_SPCA561: - case V4L2_PIX_FMT_SN9C10X: - case V4L2_PIX_FMT_PAC207: - { - unsigned char tmpbuf[dest_fmt->fmt.pix.width*dest_fmt->fmt.pix.height]; - unsigned int bayer_fmt = 0; - - switch (src_fmt->fmt.pix.pixelformat) { - case V4L2_PIX_FMT_SPCA561: - v4lconvert_decode_spca561(src, tmpbuf, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - bayer_fmt = V4L2_PIX_FMT_SGBRG8; - break; - case V4L2_PIX_FMT_SN9C10X: - v4lconvert_decode_sn9c10x(src, tmpbuf, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - bayer_fmt = V4L2_PIX_FMT_SBGGR8; - break; - case V4L2_PIX_FMT_PAC207: - v4lconvert_decode_pac207(src, tmpbuf, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - bayer_fmt = V4L2_PIX_FMT_SBGGR8; - break; - } - - switch (dest_fmt->fmt.pix.pixelformat) { - case V4L2_PIX_FMT_RGB24: - v4lconvert_bayer_to_rgb24(tmpbuf, dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height, bayer_fmt); - break; - case V4L2_PIX_FMT_BGR24: - v4lconvert_bayer_to_bgr24(tmpbuf, dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height, bayer_fmt); - break; - default: - v4lconvert_bayer_to_yuv420(tmpbuf, dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height, bayer_fmt); - break; - } - break; - } - - case V4L2_PIX_FMT_RGB24: - switch (dest_fmt->fmt.pix.pixelformat) { - case V4L2_PIX_FMT_BGR24: - v4lconvert_swap_rgb(src, dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - break; - case V4L2_PIX_FMT_YUV420: - printf("FIXME add rgb24 -> yuv420 conversion\n"); - break; - } - break; - case V4L2_PIX_FMT_BGR24: - switch (dest_fmt->fmt.pix.pixelformat) { - case V4L2_PIX_FMT_RGB24: - v4lconvert_swap_rgb(src, dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - break; - case V4L2_PIX_FMT_YUV420: - printf("FIXME add bgr24 -> yuv420 conversion\n"); - break; - } - break; - - case V4L2_PIX_FMT_YUV420: - switch (dest_fmt->fmt.pix.pixelformat) { - case V4L2_PIX_FMT_RGB24: - v4lconvert_yuv420_to_rgb24(src, dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - break; - case V4L2_PIX_FMT_BGR24: - v4lconvert_yuv420_to_bgr24(src, dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - break; - } - break; - - case V4L2_PIX_FMT_YUYV: - switch (dest_fmt->fmt.pix.pixelformat) { - case V4L2_PIX_FMT_RGB24: - v4lconvert_yuyv_to_rgb24(src, dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - break; - case V4L2_PIX_FMT_BGR24: - v4lconvert_yuyv_to_bgr24(src, dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - break; - default: - v4lconvert_yuyv_to_yuv420(src, dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - break; - } - break; - - case V4L2_PIX_FMT_YVYU: - switch (dest_fmt->fmt.pix.pixelformat) { - case V4L2_PIX_FMT_RGB24: - v4lconvert_yvyu_to_rgb24(src, dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - break; - case V4L2_PIX_FMT_BGR24: - v4lconvert_yvyu_to_bgr24(src, dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - break; - default: - v4lconvert_yvyu_to_yuv420(src, dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - break; - } - break; - - default: - V4LCONVERT_ERR("Unknown src format in conversion\n"); - errno = EINVAL; - return -1; - } - - /* Note when rotating dest is our temporary buffer to which our conversion - was done and _dest is the real dest! If the formats are identical no - conversion has been done! */ - if (rotate && dest_fmt->fmt.pix.pixelformat == src_fmt->fmt.pix.pixelformat) - dest = src; - - switch (rotate) { - case 0: - break; - case 90: - switch (dest_fmt->fmt.pix.pixelformat) { - case V4L2_PIX_FMT_RGB24: - case V4L2_PIX_FMT_BGR24: - v4lconvert_rotate90_rgbbgr24(dest, _dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - break; - case V4L2_PIX_FMT_YUV420: - v4lconvert_rotate90_yuv420(dest, _dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - break; - } - break; - case 180: - switch (dest_fmt->fmt.pix.pixelformat) { - case V4L2_PIX_FMT_RGB24: - case V4L2_PIX_FMT_BGR24: - v4lconvert_rotate180_rgbbgr24(dest, _dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - break; - case V4L2_PIX_FMT_YUV420: - v4lconvert_rotate180_yuv420(dest, _dest, dest_fmt->fmt.pix.width, - dest_fmt->fmt.pix.height); - break; - } - break; - default: - printf("FIXME add %d degrees rotation\n", rotate); - } - - return needed; -} - -const char *v4lconvert_get_error_message(struct v4lconvert_data *data) -{ - return data->error_msg; -} - -static void v4lconvert_get_framesizes(struct v4lconvert_data *data, - unsigned int pixelformat) -{ - int i, j, match; - struct v4l2_frmsizeenum frmsize = { .pixel_format = pixelformat }; - - for (i = 0; ; i++) { - frmsize.index = i; - if (syscall(SYS_ioctl, data->fd, VIDIOC_ENUM_FRAMESIZES, &frmsize)) - break; - - /* We got a framesize, check we don't have the same one already */ - match = 0; - for (j = 0; j < data->no_framesizes && !match; j++) { - if (frmsize.type != data->framesizes[j].type) - continue; - - switch(frmsize.type) { - case V4L2_FRMSIZE_TYPE_DISCRETE: - if(!memcmp(&frmsize.discrete, &data->framesizes[j].discrete, - sizeof(frmsize.discrete))) - match = 1; - break; - case V4L2_FRMSIZE_TYPE_CONTINUOUS: - case V4L2_FRMSIZE_TYPE_STEPWISE: - if(!memcmp(&frmsize.stepwise, &data->framesizes[j].stepwise, - sizeof(frmsize.stepwise))) - match = 1; - break; - } - } - /* Add this framesize if it is not already in our list */ - if (!match) { - if (data->no_framesizes == V4LCONVERT_MAX_FRAMESIZES) { - fprintf(stderr, - "libv4lconvert: warning more framesizes then I can handle!\n"); - return; - } - data->framesizes[data->no_framesizes].type = frmsize.type; - switch(frmsize.type) { - case V4L2_FRMSIZE_TYPE_DISCRETE: - data->framesizes[data->no_framesizes].discrete = frmsize.discrete; - break; - case V4L2_FRMSIZE_TYPE_CONTINUOUS: - case V4L2_FRMSIZE_TYPE_STEPWISE: - data->framesizes[data->no_framesizes].stepwise = frmsize.stepwise; - break; - } - data->no_framesizes++; - } - } -} - -int v4lconvert_enum_framesizes(struct v4lconvert_data *data, - struct v4l2_frmsizeenum *frmsize) -{ - if (!v4lconvert_supported_dst_format(frmsize->pixel_format)) - return syscall(SYS_ioctl, data->fd, VIDIOC_ENUM_FRAMESIZES, frmsize); - - if (frmsize->index >= data->no_framesizes) { - errno = EINVAL; - return -1; - } - - frmsize->type = data->framesizes[frmsize->index].type; - switch(frmsize->type) { - case V4L2_FRMSIZE_TYPE_DISCRETE: - frmsize->discrete = data->framesizes[frmsize->index].discrete; - break; - case V4L2_FRMSIZE_TYPE_CONTINUOUS: - case V4L2_FRMSIZE_TYPE_STEPWISE: - frmsize->stepwise = data->framesizes[frmsize->index].stepwise; - break; - } - - return 0; -} - -int v4lconvert_enum_frameintervals(struct v4lconvert_data *data, - struct v4l2_frmivalenum *frmival) -{ - int res; - struct v4l2_format src_fmt, dest_fmt; - - if (!v4lconvert_supported_dst_format(frmival->pixel_format)) - return syscall(SYS_ioctl, data->fd, VIDIOC_ENUM_FRAMEINTERVALS, frmival); - - /* Check which format we will be using to convert to frmival->pixel_format */ - memset(&dest_fmt, 0, sizeof(dest_fmt)); - dest_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - dest_fmt.fmt.pix.pixelformat = frmival->pixel_format; - dest_fmt.fmt.pix.width = frmival->width; - dest_fmt.fmt.pix.height = frmival->height; - if ((res = v4lconvert_try_format(data, &dest_fmt, &src_fmt))) - return res; - - /* Check the requested format is supported exactly as requested */ - if (dest_fmt.fmt.pix.pixelformat != frmival->pixel_format || - dest_fmt.fmt.pix.width != frmival->width || - dest_fmt.fmt.pix.height != frmival->height) { - errno = EINVAL; - return -1; - } - - /* Enumerate the frameintervals of the source format we will be using */ - frmival->pixel_format = src_fmt.fmt.pix.pixelformat; - frmival->width = src_fmt.fmt.pix.width; - frmival->height = src_fmt.fmt.pix.height; - res = syscall(SYS_ioctl, data->fd, VIDIOC_ENUM_FRAMEINTERVALS, frmival); - - /* Restore the requested format in the frmival struct */ - frmival->pixel_format = dest_fmt.fmt.pix.pixelformat; - frmival->width = dest_fmt.fmt.pix.width; - frmival->height = dest_fmt.fmt.pix.height; - - return res; -} diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/pac207.c b/v4l2-apps/lib/libv4l/libv4lconvert/pac207.c deleted file mode 100644 index 97ef4ebc0..000000000 --- a/v4l2-apps/lib/libv4l/libv4lconvert/pac207.c +++ /dev/null @@ -1,418 +0,0 @@ -/* - -# PAC207 decoder -# Bertrik.Sikken. Thomas Kaiser (C) 2005 -# Copyright (C) 2003 2004 2005 Michel Xhaard - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 2.1 of the License, or -# (at your option) any later version. -# -# 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 Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -# Note this code was originally licensed under the GNU GPL instead of the -# GNU LGPL, its license has been changed with permission, see the permission -# mails at the end of this file. - -*/ - -#include -#include "libv4lconvert-priv.h" - -#define CLIP(color) (unsigned char)(((color)>0xFF)?0xff:(((color)<0)?0:(color))) - -/* FIXME not threadsafe */ -static int decoder_initialized = 0; - -static struct { - unsigned char is_abs; - unsigned char len; - signed char val; -} table[256]; - -static void init_pixart_decoder(void) -{ - int i; - int is_abs, val, len; - for (i = 0; i < 256; i++) { - is_abs = 0; - val = 0; - len = 0; - if ((i & 0xC0) == 0) { - /* code 00 */ - val = 0; - len = 2; - } else if ((i & 0xC0) == 0x40) { - /* code 01 */ - val = -5; - len = 2; - } else if ((i & 0xC0) == 0x80) { - /* code 10 */ - val = +5; - len = 2; - } else if ((i & 0xF0) == 0xC0) { - /* code 1100 */ - val = -10; - len = 4; - } else if ((i & 0xF0) == 0xD0) { - /* code 1101 */ - val = +10; - len = 4; - } else if ((i & 0xF8) == 0xE0) { - /* code 11100 */ - val = -15; - len = 5; - } else if ((i & 0xF8) == 0xE8) { - /* code 11101 */ - val = +15; - len = 5; - } else if ((i & 0xFC) == 0xF0) { - /* code 111100 */ - val = -20; - len = 6; - } else if ((i & 0xFC) == 0xF4) { - /* code 111101 */ - val = +20; - len = 6; - } else if ((i & 0xF8) == 0xF8) { - /* code 11111xxxxxx */ - is_abs = 1; - val = 0; - len = 5; - } - table[i].is_abs = is_abs; - table[i].val = val; - table[i].len = len; - } - decoder_initialized = 1; -} - -static inline unsigned char getByte(const unsigned char *inp, - unsigned int bitpos) -{ - const unsigned char *addr; - addr = inp + (bitpos >> 3); - return (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7))); -} - -static inline unsigned short getShort(const unsigned char *pt) -{ - return ((pt[0] << 8) | pt[1]); -} - -static int -pac_decompress_row(const unsigned char *inp, unsigned char *outp, int width) -{ - int col; - int val; - int bitpos; - unsigned char code; - - if (!decoder_initialized) - init_pixart_decoder(); - - /* first two pixels are stored as raw 8-bit */ - *outp++ = inp[2]; - *outp++ = inp[3]; - bitpos = 32; - - /* main decoding loop */ - for (col = 2; col < width; col++) { - /* get bitcode */ - - code = getByte(inp, bitpos); - bitpos += table[code].len; - - /* calculate pixel value */ - if (table[code].is_abs) { - /* absolute value: get 6 more bits */ - code = getByte(inp, bitpos); - bitpos += 6; - *outp++ = code & 0xFC; - } else { - /* relative to left pixel */ - val = outp[-2] + table[code].val; - *outp++ = CLIP(val); - } - } - - /* return line length, rounded up to next 16-bit word */ - return 2 * ((bitpos + 15) / 16); -} - -void v4lconvert_decode_pac207(const unsigned char *inp, unsigned char *outp, - int width, int height) -{ -/* we should received a whole frame with header and EOL marker -in myframe->data and return a GBRG pattern in frame->tmpbuffer -remove the header then copy line by line EOL is set with 0x0f 0xf0 marker -or 0x1e 0xe1 for compressed line*/ - unsigned short word; - int row; - - /* iterate over all rows */ - for (row = 0; row < height; row++) { - word = getShort(inp); - switch (word) { - case 0x0FF0: - memcpy(outp, inp + 2, width); - inp += (2 + width); - break; - case 0x1EE1: - inp += pac_decompress_row(inp, outp, width); - break; - - case 0x2DD2: /* prefix for "stronger" compressed lines, currently the - kernel driver programs the cam so that we should not - get any of these */ - - default: /* corrupt frame */ - /* FIXME add error reporting */ - return; - } - outp += width; - } - - return; -} - - - - -/* -Return-Path: -Received: from koko.hhs.nl ([145.52.2.16] verified) - by hhs.nl (CommuniGate Pro SMTP 4.3.6) - with ESMTP id 88906346 for j.w.r.degoede@hhs.nl; Thu, 26 Jun 2008 01:17:00 +0200 -Received: from exim (helo=koko) - by koko.hhs.nl with local-smtp (Exim 4.62) - (envelope-from ) - id 1KBeEW-0001qu-H6 - for j.w.r.degoede@hhs.nl; Thu, 26 Jun 2008 01:17:00 +0200 -Received: from [192.87.102.74] (port=41049 helo=filter6-ams.mf.surf.net) - by koko.hhs.nl with esmtp (Exim 4.62) - (envelope-from ) - id 1KBeEV-0001qn-2T - for j.w.r.degoede@hhs.nl; Thu, 26 Jun 2008 01:17:00 +0200 -Received: from smtp0.lie-comtel.li (smtp0.lie-comtel.li [217.173.238.80]) - by filter6-ams.mf.surf.net (8.13.8/8.13.8/Debian-3) with ESMTP id m5PNGwSF007539 - for ; Thu, 26 Jun 2008 01:16:58 +0200 -Received: from localhost (localhost.lie-comtel.li [127.0.0.1]) - by smtp0.lie-comtel.li (Postfix) with ESMTP id DDB609FEC1D; - Thu, 26 Jun 2008 00:16:56 +0100 (GMT-1) -X-Virus-Scanned: Virus scanned by amavis at smtp.lie-comtel.li -Received: from [192.168.0.16] (217-173-228-198.cmts.powersurf.li [217.173.228.198]) - by smtp0.lie-comtel.li (Postfix) with ESMTP id 80B589FEC19; - Thu, 26 Jun 2008 00:16:56 +0100 (GMT-1) -Message-ID: <4862D211.3000802@kaiser-linux.li> -Date: Thu, 26 Jun 2008 01:17:37 +0200 -From: Thomas Kaiser -User-Agent: Thunderbird 2.0.0.14 (X11/20080505) -MIME-Version: 1.0 -To: Hans de Goede -CC: Thomas Kaiser , bertrik@zonnet.nl, - mxhaard@magic.fr -Subject: Re: pac207 bayer decompression algorithm license question -References: <4862C0A4.3060003@hhs.nl> -In-Reply-To: <4862C0A4.3060003@hhs.nl> -Content-Type: text/plain; charset=ISO-8859-1; format=flowed -Content-Transfer-Encoding: 7bit -X-Canit-CHI2: 0.00 -X-Bayes-Prob: 0.0001 (Score 0, tokens from: @@RPTN) -X-Spam-Score: 0.00 () [Tag at 8.00] -X-CanItPRO-Stream: hhs:j.w.r.degoede@hhs.nl (inherits from hhs:default,base:default) -X-Canit-Stats-ID: 88604132 - 38b3b44cd798 -X-Scanned-By: CanIt (www . roaringpenguin . com) on 192.87.102.74 -X-Anti-Virus: Kaspersky Anti-Virus for MailServers 5.5.2/RELEASE, bases: 25062008 #787666, status: clean - -Hello Hans - -Hans de Goede wrote: -> Hi, -> -> As you may have seen on the mailinglist, I've created a userspace -> library to handle cam specific format handling in userspace where it -> belongs, see: -> http://hansdegoede.livejournal.com/ -Yes, I saw it on the mail list and I think it is a good idea :-) -> -> I would like to also add support for decompressing the pac207's -> compressed bayer to this lib (and remove it from the kernel driver) -> for this I need permission to relicense the decompress code under the -> LGPL (version 2 or later). -Actually, this was done by Bertrik Sikken (bertrik@zonnet.nl), Michel -Xhaard (mxhaard@magic.fr) and me. But Bertrik was the one who found out -how to decode the lines :-) -> -> Can you give me permission for this, or if the code is not yours put -> me in contact with someone who can? -For me it's no problem to release it with LGPL. Maybe you have to ask -the other one's also. -> -> Thanks & Regards, -> -> Hans - -Rgeards, Thomas -*/ - -/* -Return-Path: -Received: from koko.hhs.nl ([145.52.2.16] verified) - by hhs.nl (CommuniGate Pro SMTP 4.3.6) - with ESMTP id 88910192 for j.w.r.degoede@hhs.nl; Thu, 26 Jun 2008 09:15:37 +0200 -Received: from exim (helo=koko) - by koko.hhs.nl with local-smtp (Exim 4.62) - (envelope-from ) - id 1KBlhh-0006Fi-Oe - for j.w.r.degoede@hhs.nl; Thu, 26 Jun 2008 09:15:37 +0200 -Received: from [194.171.167.220] (port=54180 helo=filter4-til.mf.surf.net) - by koko.hhs.nl with esmtp (Exim 4.62) - (envelope-from ) - id 1KBlhh-0006Fd-FY - for j.w.r.degoede@hhs.nl; Thu, 26 Jun 2008 09:15:37 +0200 -Received: from smtp4-g19.free.fr (smtp4-g19.free.fr [212.27.42.30]) - by filter4-til.mf.surf.net (8.13.8/8.13.8/Debian-3) with ESMTP id m5Q7FY1I006360 - for ; Thu, 26 Jun 2008 09:15:34 +0200 -Received: from smtp4-g19.free.fr (localhost.localdomain [127.0.0.1]) - by smtp4-g19.free.fr (Postfix) with ESMTP id 51C683EA0E7; - Thu, 26 Jun 2008 09:15:34 +0200 (CEST) -Received: from [192.168.1.11] (lns-bzn-54-82-251-105-53.adsl.proxad.net [82.251.105.53]) - by smtp4-g19.free.fr (Postfix) with ESMTP id 1149E3EA0C7; - Thu, 26 Jun 2008 09:15:34 +0200 (CEST) -From: Michel Xhaard -To: Hans de Goede -Subject: Re: pac207 bayer decompression algorithm license question -Date: Thu, 26 Jun 2008 11:15:32 +0200 -User-Agent: KMail/1.9.5 -Cc: bertrik@zonnet.nl, spca5xx@kaiser-linux.li, - "Jean-Francois Moine" -References: <48633F02.3040108@hhs.nl> -In-Reply-To: <48633F02.3040108@hhs.nl> -MIME-Version: 1.0 -Content-Type: text/plain; - charset="iso-8859-1" -Content-Transfer-Encoding: quoted-printable -Content-Disposition: inline -Message-Id: <200806261115.32909.mxhaard@magic.fr> -X-Canit-CHI2: 0.00 -X-Bayes-Prob: 0.0001 (Score 0, tokens from: @@RPTN) -X-Spam-Score: 0.00 () [Tag at 8.00] -X-CanItPRO-Stream: hhs:j.w.r.degoede@hhs.nl (inherits from hhs:default,base:default) -X-Canit-Stats-ID: 88656338 - 0dde233cb8b5 -X-Scanned-By: CanIt (www . roaringpenguin . com) on 194.171.167.220 -X-Anti-Virus: Kaspersky Anti-Virus for MailServers 5.5.2/RELEASE, bases: 26062008 #787720, status: clean - -Le jeudi 26 juin 2008 09:02, Hans de Goede a =E9crit=A0: -> Hi, -> -> As you may have seen on the mailinglist, I've created a userspace library -> to handle cam specific format handling in userspace, see: -> http://hansdegoede.livejournal.com/ -> -> I would like to also add support for decompressing the pac207's compressed -> bayer to this lib (and remove it from the kernel driver) and I've heard -> from Thomas Kaiser that you are a co-author of the decompression code. In -> order to add support for decompressing pac207 compressed bayer to libv4l I -> need permission to relicense the decompression code under the LGPL (versi= -on -> 2 or later). -> -> Can you give me permission for this? -> -> Thanks & Regards, -> -> Hans -> -> -> -> p.s. -> -> Thomas has already given permission. - -=46or me it is ok and a good idea for all free world familly ;-). -Bests regards -=2D-=20 -Michel Xhaard -http://mxhaard.free.fr -*/ - -/* -Return-Path: -Received: from koko.hhs.nl ([145.52.2.16] verified) - by hhs.nl (CommuniGate Pro SMTP 4.3.6) - with ESMTP id 88940205 for j.w.r.degoede@hhs.nl; Thu, 26 Jun 2008 22:03:30 +0200 -Received: from exim (helo=koko) - by koko.hhs.nl with local-smtp (Exim 4.62) - (envelope-from ) - id 1KBxgo-0003Dj-ET - for j.w.r.degoede@hhs.nl; Thu, 26 Jun 2008 22:03:30 +0200 -Received: from [192.87.102.69] (port=51992 helo=filter1-ams.mf.surf.net) - by koko.hhs.nl with esmtp (Exim 4.62) - (envelope-from ) - id 1KBxgo-0003Dd-5i - for j.w.r.degoede@hhs.nl; Thu, 26 Jun 2008 22:03:30 +0200 -Received: from pelian.kabelfoon.nl (pelian3.kabelfoon.nl [62.45.45.106]) - by filter1-ams.mf.surf.net (8.13.8/8.13.8/Debian-3) with ESMTP id m5QK3ThE007720 - for ; Thu, 26 Jun 2008 22:03:29 +0200 -Received: from [192.168.1.1] (062-015-045-062.dynamic.caiway.nl [62.45.15.62]) - by pelian.kabelfoon.nl (Postfix) with ESMTP id 9239B428100 - for ; Thu, 26 Jun 2008 22:03:29 +0200 (CEST) -Message-ID: <4863F611.80104@sikken.nl> -Date: Thu, 26 Jun 2008 22:03:29 +0200 -From: Bertrik Sikken -User-Agent: Thunderbird 2.0.0.14 (Windows/20080421) -MIME-Version: 1.0 -To: Hans de Goede -Subject: Re: pac207 bayer decompression algorithm license question -References: <48633F02.3040108@hhs.nl> -In-Reply-To: <48633F02.3040108@hhs.nl> -X-Enigmail-Version: 0.95.6 -Content-Type: text/plain; charset=ISO-8859-1; format=flowed -Content-Transfer-Encoding: 7bit -X-Canit-CHI2: 0.00 -X-Bayes-Prob: 0.0001 (Score 0, tokens from: @@RPTN) -X-Spam-Score: 0.00 () [Tag at 8.00] -X-CanItPRO-Stream: hhs:j.w.r.degoede@hhs.nl (inherits from hhs:default,base:default) -X-Canit-Stats-ID: 88938005 - ef1f0836ffc7 -X-Scanned-By: CanIt (www . roaringpenguin . com) on 192.87.102.69 -X-Anti-Virus: Kaspersky Anti-Virus for MailServers 5.5.2/RELEASE, bases: 26062008 #787877, status: clean - -Hallo Hans, - -Hans de Goede wrote: -> Hi, -> -> As you may have seen on the mailinglist, I've created a userspace -> library to -> handle cam specific format handling in userspace, see: -> http://hansdegoede.livejournal.com/ - -O leuk, zoiets is naar mijn idee precies wat er nodig is voor webcam -support onder linux. Ik ben een jaar of 3 geleden heel actief geweest -met een aantal webcams, maar doe er tegenwoordig helemaal niets meer -aan. - -> I would like to also add support for decompressing the pac207's compressed -> bayer to this lib (and remove it from the kernel driver) and I've heard -> from Thomas Kaiser that you are a co-author of the decompression code. -> In order to add support for decompressing pac207 compressed bayer to -> libv4l I need -> permission to relicense the decompression code under the LGPL (version 2 -> or later). -> -> Can you give me permission for this? - -Ja, vind ik goed. - -Vriendelijke groet, -Bertrik -*/ diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/rgbyuv.c b/v4l2-apps/lib/libv4l/libv4lconvert/rgbyuv.c deleted file mode 100644 index 0f26b227a..000000000 --- a/v4l2-apps/lib/libv4l/libv4lconvert/rgbyuv.c +++ /dev/null @@ -1,316 +0,0 @@ -/* - -# RGB <-> YUV conversion routines - -# (C) 2008 Hans de Goede - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 2.1 of the License, or -# (at your option) any later version. -# -# 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 Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -*/ - -#include "libv4lconvert-priv.h" - -#define RGB2YUV(r,g,b,y,u,v) \ - (y) = (( 8453*(r) + 16594*(g) + 3223*(b) + 524288) >> 15); \ - (u) = (( -4878*(r) - 9578*(g) + 14456*(b) + 4210688) >> 15); \ - (v) = (( 14456*(r) - 12105*(g) - 2351*(b) + 4210688) >> 15) - -#define YUV2R(y, u, v) ({ \ - int r = (y) + ((((v)-128)*1436) >> 10); r > 255 ? 255 : r < 0 ? 0 : r; }) -#define YUV2G(y, u, v) ({ \ - int g = (y) - ((((u)-128)*352 + ((v)-128)*731) >> 10); g > 255 ? 255 : g < 0 ? 0 : g; }) -#define YUV2B(y, u, v) ({ \ - int b = (y) + ((((u)-128)*1814) >> 10); b > 255 ? 255 : b < 0 ? 0 : b; }) - -#define CLIP(color) (unsigned char)(((color)>0xFF)?0xff:(((color)<0)?0:(color))) - -void v4lconvert_yuv420_to_bgr24(const unsigned char *src, unsigned char *dest, - int width, int height) -{ - int i,j; - - const unsigned char *ysrc = src; - const unsigned char *usrc = src + width * height; - const unsigned char *vsrc = usrc + (width * height) / 4; - - for (i = 0; i < height; i++) { - for (j = 0; j < width; j += 2) { -#if 1 /* fast slightly less accurate multiplication free code */ - int u1 = (((*usrc - 128) << 7) + (*usrc - 128)) >> 6; - int rg = (((*usrc - 128) << 1) + (*usrc - 128) + - ((*vsrc - 128) << 2) + ((*vsrc - 128) << 1)) >> 3; - int v1 = (((*vsrc - 128) << 1) + (*vsrc - 128)) >> 1; - - *dest++ = CLIP(*ysrc + u1); - *dest++ = CLIP(*ysrc - rg); - *dest++ = CLIP(*ysrc + v1); - ysrc++; - - *dest++ = CLIP(*ysrc + u1); - *dest++ = CLIP(*ysrc - rg); - *dest++ = CLIP(*ysrc + v1); -#else - *dest++ = YUV2B(*ysrc, *usrc, *vsrc); - *dest++ = YUV2G(*ysrc, *usrc, *vsrc); - *dest++ = YUV2R(*ysrc, *usrc, *vsrc); - ysrc++; - - *dest++ = YUV2B(*ysrc, *usrc, *vsrc); - *dest++ = YUV2G(*ysrc, *usrc, *vsrc); - *dest++ = YUV2R(*ysrc, *usrc, *vsrc); -#endif - ysrc++; - usrc++; - vsrc++; - } - /* Rewind u and v for next line */ - if (i&1) { - usrc -= width / 2; - vsrc -= width / 2; - } - } -} - -void v4lconvert_yuv420_to_rgb24(const unsigned char *src, unsigned char *dest, - int width, int height) -{ - int i,j; - - const unsigned char *ysrc = src; - const unsigned char *usrc = src + width * height; - const unsigned char *vsrc = usrc + (width * height) / 4; - - for (i = 0; i < height; i++) { - for (j = 0; j < width; j += 2) { -#if 1 /* fast slightly less accurate multiplication free code */ - int u1 = (((*usrc - 128) << 7) + (*usrc - 128)) >> 6; - int rg = (((*usrc - 128) << 1) + (*usrc - 128) + - ((*vsrc - 128) << 2) + ((*vsrc - 128) << 1)) >> 3; - int v1 = (((*vsrc - 128) << 1) + (*vsrc - 128)) >> 1; - - *dest++ = CLIP(*ysrc + v1); - *dest++ = CLIP(*ysrc - rg); - *dest++ = CLIP(*ysrc + u1); - ysrc++; - - *dest++ = CLIP(*ysrc + v1); - *dest++ = CLIP(*ysrc - rg); - *dest++ = CLIP(*ysrc + u1); -#else - *dest++ = YUV2R(*ysrc, *usrc, *vsrc); - *dest++ = YUV2G(*ysrc, *usrc, *vsrc); - *dest++ = YUV2B(*ysrc, *usrc, *vsrc); - ysrc++; - - *dest++ = YUV2R(*ysrc, *usrc, *vsrc); - *dest++ = YUV2G(*ysrc, *usrc, *vsrc); - *dest++ = YUV2B(*ysrc, *usrc, *vsrc); -#endif - ysrc++; - usrc++; - vsrc++; - } - /* Rewind u and v for next line */ - if (i&1) { - usrc -= width / 2; - vsrc -= width / 2; - } - } -} - -void v4lconvert_yuyv_to_bgr24(const unsigned char *src, unsigned char *dest, - int width, int height) -{ - int j; - - while (--height >= 0) { - for (j = 0; j < width; j += 2) { - int u = src[1]; - int v = src[3]; - int u1 = (((u - 128) << 7) + (u - 128)) >> 6; - int rg = (((u - 128) << 1) + (u - 128) + - ((v - 128) << 2) + ((v - 128) << 1)) >> 3; - int v1 = (((v - 128) << 1) + (v - 128)) >> 1; - - *dest++ = CLIP(src[0] + u1); - *dest++ = CLIP(src[0] - rg); - *dest++ = CLIP(src[0] + v1); - - *dest++ = CLIP(src[2] + u1); - *dest++ = CLIP(src[2] - rg); - *dest++ = CLIP(src[2] + v1); - src += 4; - } - } -} - -void v4lconvert_yuyv_to_rgb24(const unsigned char *src, unsigned char *dest, - int width, int height) -{ - int j; - - while (--height >= 0) { - for (j = 0; j < width; j += 2) { - int u = src[1]; - int v = src[3]; - int u1 = (((u - 128) << 7) + (u - 128)) >> 6; - int rg = (((u - 128) << 1) + (u - 128) + - ((v - 128) << 2) + ((v - 128) << 1)) >> 3; - int v1 = (((v - 128) << 1) + (v - 128)) >> 1; - - *dest++ = CLIP(src[0] + v1); - *dest++ = CLIP(src[0] - rg); - *dest++ = CLIP(src[0] + u1); - - *dest++ = CLIP(src[2] + v1); - *dest++ = CLIP(src[2] - rg); - *dest++ = CLIP(src[2] + u1); - src += 4; - } - } -} - -void v4lconvert_yuyv_to_yuv420(const unsigned char *src, unsigned char *dest, - int width, int height) -{ - int i, j; - const unsigned char *src1; - unsigned char *vdest; - - /* copy the Y values */ - src1 = src; - for (i = 0; i < height; i++) { - for (j = 0; j < width; j += 2) { - *dest++ = src1[0]; - *dest++ = src1[2]; - src1 += 4; - } - } - - /* copy the U and V values */ - src++; /* point to V */ - src1 = src + width * 2; /* next line */ - vdest = dest + width * height / 4; - for (i = 0; i < height; i += 2) { - for (j = 0; j < width; j += 2) { - *dest++ = ((int) src[0] + src1[0]) / 2; /* U */ - *vdest++ = ((int) src[2] + src1[2]) / 2; /* V */ - src += 4; - src1 += 4; - } - src = src1; - src1 += width * 2; - } -} - -void v4lconvert_yvyu_to_bgr24(const unsigned char *src, unsigned char *dest, - int width, int height) -{ - int j; - - while (--height >= 0) { - for (j = 0; j < width; j += 2) { - int u = src[3]; - int v = src[1]; - int u1 = (((u - 128) << 7) + (u - 128)) >> 6; - int rg = (((u - 128) << 1) + (u - 128) + - ((v - 128) << 2) + ((v - 128) << 1)) >> 3; - int v1 = (((v - 128) << 1) + (v - 128)) >> 1; - - *dest++ = CLIP(src[0] + u1); - *dest++ = CLIP(src[0] - rg); - *dest++ = CLIP(src[0] + v1); - - *dest++ = CLIP(src[2] + u1); - *dest++ = CLIP(src[2] - rg); - *dest++ = CLIP(src[2] + v1); - src += 4; - } - } -} - -void v4lconvert_yvyu_to_rgb24(const unsigned char *src, unsigned char *dest, - int width, int height) -{ - int j; - - while (--height >= 0) { - for (j = 0; j < width; j += 2) { - int u = src[3]; - int v = src[1]; - int u1 = (((u - 128) << 7) + (u - 128)) >> 6; - int rg = (((u - 128) << 1) + (u - 128) + - ((v - 128) << 2) + ((v - 128) << 1)) >> 3; - int v1 = (((v - 128) << 1) + (v - 128)) >> 1; - - *dest++ = CLIP(src[0] + v1); - *dest++ = CLIP(src[0] - rg); - *dest++ = CLIP(src[0] + u1); - - *dest++ = CLIP(src[2] + v1); - *dest++ = CLIP(src[2] - rg); - *dest++ = CLIP(src[2] + u1); - src += 4; - } - } -} - -void v4lconvert_yvyu_to_yuv420(const unsigned char *src, unsigned char *dest, - int width, int height) -{ - int i, j; - const unsigned char *src1; - unsigned char *vdest; - - /* copy the Y values */ - src1 = src; - for (i = 0; i < height; i++) { - for (j = 0; j < width; j += 2) { - *dest++ = src1[0]; - *dest++ = src1[2]; - src1 += 4; - } - } - - /* copy the U and V values */ - src++; /* point to V */ - src1 = src + width * 2; /* next line */ - vdest = dest + width * height / 4; - for (i = 0; i < height; i += 2) { - for (j = 0; j < width; j += 2) { - *dest++ = ((int) src[2] + src1[2]) / 2; /* U */ - *vdest++ = ((int) src[0] + src1[0]) / 2; /* V */ - src += 4; - src1 += 4; - } - src = src1; - src1 += width * 2; - } -} - -void v4lconvert_swap_rgb(const unsigned char *src, unsigned char *dst, - int width, int height) -{ - int i; - - for (i = 0; i < (width * height); i++) { - unsigned char tmp0, tmp1; - tmp0 = *src++; - tmp1 = *src++; - *dst++ = *src++; - *dst++ = tmp1; - *dst++ = tmp0; - } -} diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/sn9c10x.c b/v4l2-apps/lib/libv4l/libv4lconvert/sn9c10x.c deleted file mode 100644 index 4ea526d49..000000000 --- a/v4l2-apps/lib/libv4l/libv4lconvert/sn9c10x.c +++ /dev/null @@ -1,287 +0,0 @@ -/* -# sonix decoder -# Bertrik.Sikken. (C) 2005 - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 2.1 of the License, or -# (at your option) any later version. -# -# 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 Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -# Note this code was originally licensed under the GNU GPL instead of the -# GNU LGPL, its license has been changed with permission, see the permission -# mail at the end of this file. -*/ - -#include "libv4lconvert-priv.h" - -#define CLAMP(x) ((x)<0?0:((x)>255)?255:(x)) - -typedef struct { - int is_abs; - int len; - int val; - int unk; -} code_table_t; - - -/* local storage */ -/* FIXME not thread safe !! */ -static code_table_t table[256]; -static int init_done = 0; - -/* global variable */ -static int sonix_unknown = 0; - -/* - sonix_decompress_init - ===================== - pre-calculates a locally stored table for efficient huffman-decoding. - - Each entry at index x in the table represents the codeword - present at the MSB of byte x. - -*/ -static void sonix_decompress_init(void) -{ - int i; - int is_abs, val, len, unk; - - for (i = 0; i < 256; i++) { - is_abs = 0; - val = 0; - len = 0; - unk = 0; - if ((i & 0x80) == 0) { - /* code 0 */ - val = 0; - len = 1; - } - else if ((i & 0xE0) == 0x80) { - /* code 100 */ - val = +4; - len = 3; - } - else if ((i & 0xE0) == 0xA0) { - /* code 101 */ - val = -4; - len = 3; - } - else if ((i & 0xF0) == 0xD0) { - /* code 1101 */ - val = +11; - len = 4; - } - else if ((i & 0xF0) == 0xF0) { - /* code 1111 */ - val = -11; - len = 4; - } - else if ((i & 0xF8) == 0xC8) { - /* code 11001 */ - val = +20; - len = 5; - } - else if ((i & 0xFC) == 0xC0) { - /* code 110000 */ - val = -20; - len = 6; - } - else if ((i & 0xFC) == 0xC4) { - /* code 110001xx: unknown */ - val = 0; - len = 8; - unk = 1; - } - else if ((i & 0xF0) == 0xE0) { - /* code 1110xxxx */ - is_abs = 1; - val = (i & 0x0F) << 4; - len = 8; - } - table[i].is_abs = is_abs; - table[i].val = val; - table[i].len = len; - table[i].unk = unk; - } - - sonix_unknown = 0; - init_done = 1; -} - - -/* - sonix_decompress - ================ - decompresses an image encoded by a SN9C101 camera controller chip. - - IN width - height - inp pointer to compressed frame (with header already stripped) - OUT outp pointer to decompressed frame - - Returns 0 if the operation was successful. - Returns <0 if operation failed. - -*/ -void v4lconvert_decode_sn9c10x(const unsigned char *inp, unsigned char *outp, - int width, int height) -{ - int row, col; - int val; - int bitpos; - unsigned char code; - const unsigned char *addr; - - if (!init_done) - sonix_decompress_init(); - - bitpos = 0; - for (row = 0; row < height; row++) { - - col = 0; - - /* first two pixels in first two rows are stored as raw 8-bit */ - if (row < 2) { - addr = inp + (bitpos >> 3); - code = (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7))); - bitpos += 8; - *outp++ = code; - - addr = inp + (bitpos >> 3); - code = (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7))); - bitpos += 8; - *outp++ = code; - - col += 2; - } - - while (col < width) { - /* get bitcode from bitstream */ - addr = inp + (bitpos >> 3); - code = (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7))); - - /* update bit position */ - bitpos += table[code].len; - - /* update code statistics */ - sonix_unknown += table[code].unk; - - /* calculate pixel value */ - val = table[code].val; - if (!table[code].is_abs) { - /* value is relative to top and left pixel */ - if (col < 2) { - /* left column: relative to top pixel */ - val += outp[-2*width]; - } - else if (row < 2) { - /* top row: relative to left pixel */ - val += outp[-2]; - } - else { - /* main area: average of left pixel and top pixel */ - val += (outp[-2] + outp[-2*width]) / 2; - } - } - - /* store pixel */ - *outp++ = CLAMP(val); - col++; - } - } -} - -/* -Return-Path: -Received: from koko.hhs.nl ([145.52.2.16] verified) - by hhs.nl (CommuniGate Pro SMTP 4.3.6) - with ESMTP id 89132066 for j.w.r.degoede@hhs.nl; Thu, 03 Jul 2008 15:19:55 +0200 -Received: from exim (helo=koko) - by koko.hhs.nl with local-smtp (Exim 4.62) - (envelope-from ) - id 1KEOj5-0000nq-KR - for j.w.r.degoede@hhs.nl; Thu, 03 Jul 2008 15:19:55 +0200 -Received: from [192.87.102.69] (port=33783 helo=filter1-ams.mf.surf.net) - by koko.hhs.nl with esmtp (Exim 4.62) - (envelope-from ) - id 1KEOj5-0000nj-7r - for j.w.r.degoede@hhs.nl; Thu, 03 Jul 2008 15:19:55 +0200 -Received: from cardassian.kabelfoon.nl (cardassian3.kabelfoon.nl [62.45.45.105]) - by filter1-ams.mf.surf.net (8.13.8/8.13.8/Debian-3) with ESMTP id m63DJsKW032598 - for ; Thu, 3 Jul 2008 15:19:54 +0200 -Received: from [192.168.1.1] (044-013-045-062.dynamic.caiway.nl [62.45.13.44]) - by cardassian.kabelfoon.nl (Postfix) with ESMTP id 77761341D9A - for ; Thu, 3 Jul 2008 15:19:54 +0200 (CEST) -Message-ID: <486CD1F9.8000307@sikken.nl> -Date: Thu, 03 Jul 2008 15:19:53 +0200 -From: Bertrik Sikken -User-Agent: Thunderbird 2.0.0.14 (Windows/20080421) -MIME-Version: 1.0 -To: Hans de Goede -Subject: Re: pac207 bayer decompression algorithm license question -References: <48633F02.3040108@hhs.nl> <4863F611.80104@sikken.nl> <486CC6AF.7050509@hhs.nl> -In-Reply-To: <486CC6AF.7050509@hhs.nl> -X-Enigmail-Version: 0.95.6 -Content-Type: text/plain; charset=ISO-8859-1; format=flowed -Content-Transfer-Encoding: 7bit -X-Canit-CHI2: 0.00 -X-Bayes-Prob: 0.0001 (Score 0, tokens from: @@RPTN) -X-Spam-Score: 0.00 () [Tag at 8.00] -X-CanItPRO-Stream: hhs:j.w.r.degoede@hhs.nl (inherits from hhs:default,base:default) -X-Canit-Stats-ID: 90943081 - 6a9ff19e8165 -X-Scanned-By: CanIt (www . roaringpenguin . com) on 192.87.102.69 -X-Anti-Virus: Kaspersky Anti-Virus for MailServers 5.5.2/RELEASE, bases: 03072008 #811719, status: clean - ------BEGIN PGP SIGNED MESSAGE----- -Hash: SHA1 - -Hans de Goede wrote: -| Bertrik Sikken wrote: -|> Hallo Hans, -|> -|> Hans de Goede wrote: -|>> I would like to also add support for decompressing the pac207's -|>> compressed -|>> bayer to this lib (and remove it from the kernel driver) and I've -|>> heard from Thomas Kaiser that you are a co-author of the -|>> decompression code. In order to add support for decompressing pac207 -|>> compressed bayer to libv4l I need -|>> permission to relicense the decompression code under the LGPL -|>> (version 2 or later). -|>> -|>> Can you give me permission for this? -|> -|> Ja, vind ik goed. -|> -| -| Thanks! -| -| I'm currently working on adding support for the sn9c10x bayer -| compression to libv4l too, and I noticed this was written by you too. -| -| May I have your permission to relicense the sn9c10x bayer decompression -| code under the LGPL (version 2 or later)? - -I hereby grant you permission to relicense the sn9c10x bayer -decompression code under the LGPL (version 2 or later). - -Kind regards, -Bertrik ------BEGIN PGP SIGNATURE----- -Version: GnuPG v1.4.7 (MingW32) -Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org - -iD8DBQFIbNH5ETD6mlrWxPURAipvAJ9sv1ZpHyb81NMFejr6x0wqHX3i7QCfRDoB -jZi2e5lUjEh5KvS0dqXbi9I= -=KQfR ------END PGP SIGNATURE----- -*/ diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/spca501.c b/v4l2-apps/lib/libv4l/libv4lconvert/spca501.c deleted file mode 100644 index 9157629e3..000000000 --- a/v4l2-apps/lib/libv4l/libv4lconvert/spca501.c +++ /dev/null @@ -1,126 +0,0 @@ -/* -# (C) 2008 Hans de Goede - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 2.1 of the License, or -# (at your option) any later version. -# -# 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 Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "libv4lconvert-priv.h" - -/* YUYV per line */ -void v4lconvert_spca501_to_yuv420(const unsigned char *src, unsigned char *dst, - int width, int height) -{ - int i,j; - unsigned long *lsrc = (unsigned long *)src; - - for (i = 0; i < height; i += 2) { - /* -128 - 127 --> 0 - 255 and copy first line Y */ - unsigned long *ldst = (unsigned long *)(dst + i * width); - for (j = 0; j < width; j += sizeof(long)) { - *ldst = *lsrc++; - *ldst++ ^= 0x8080808080808080ULL; - } - - /* -128 - 127 --> 0 - 255 and copy 1 line U */ - ldst = (unsigned long *)(dst + width * height + i * width / 4); - for (j = 0; j < width/2; j += sizeof(long)) { - *ldst = *lsrc++; - *ldst++ ^= 0x8080808080808080ULL; - } - - /* -128 - 127 --> 0 - 255 and copy second line Y */ - ldst = (unsigned long *)(dst + i * width + width); - for (j = 0; j < width; j += sizeof(long)) { - *ldst = *lsrc++; - *ldst++ ^= 0x8080808080808080ULL; - } - - /* -128 - 127 --> 0 - 255 and copy 1 line V */ - ldst = (unsigned long *)(dst + (width * height * 5) / 4 + i * width / 4); - for (j = 0; j < width/2; j += sizeof(long)) { - *ldst = *lsrc++; - *ldst++ ^= 0x8080808080808080ULL; - } - } -} - -/* YYUV per line */ -void v4lconvert_spca505_to_yuv420(const unsigned char *src, unsigned char *dst, - int width, int height) -{ - int i,j; - unsigned long *lsrc = (unsigned long *)src; - - for (i = 0; i < height; i += 2) { - /* -128 - 127 --> 0 - 255 and copy 2 lines of Y */ - unsigned long *ldst = (unsigned long *)(dst + i * width); - for (j = 0; j < width*2; j += sizeof(long)) { - *ldst = *lsrc++; - *ldst++ ^= 0x8080808080808080ULL; - } - - /* -128 - 127 --> 0 - 255 and copy 1 line U */ - ldst = (unsigned long *)(dst + width * height + i * width / 4); - for (j = 0; j < width/2; j += sizeof(long)) { - *ldst = *lsrc++; - *ldst++ ^= 0x8080808080808080ULL; - } - - /* -128 - 127 --> 0 - 255 and copy 1 line V */ - ldst = (unsigned long *)(dst + (width * height * 5) / 4 + i * width / 4); - for (j = 0; j < width/2; j += sizeof(long)) { - *ldst = *lsrc++; - *ldst++ ^= 0x8080808080808080ULL; - } - } -} - -/* YUVY per line */ -void v4lconvert_spca508_to_yuv420(const unsigned char *src, unsigned char *dst, - int width, int height) -{ - int i,j; - unsigned long *lsrc = (unsigned long *)src; - - for (i = 0; i < height; i += 2) { - /* -128 - 127 --> 0 - 255 and copy first line Y */ - unsigned long *ldst = (unsigned long *)(dst + i * width); - for (j = 0; j < width; j += sizeof(long)) { - *ldst = *lsrc++; - *ldst++ ^= 0x8080808080808080ULL; - } - - /* -128 - 127 --> 0 - 255 and copy 1 line U */ - ldst = (unsigned long *)(dst + width * height + i * width / 4); - for (j = 0; j < width/2; j += sizeof(long)) { - *ldst = *lsrc++; - *ldst++ ^= 0x8080808080808080ULL; - } - - /* -128 - 127 --> 0 - 255 and copy 1 line V */ - ldst = (unsigned long *)(dst + (width * height * 5) / 4 + i * width / 4); - for (j = 0; j < width/2; j += sizeof(long)) { - *ldst = *lsrc++; - *ldst++ ^= 0x8080808080808080ULL; - } - - /* -128 - 127 --> 0 - 255 and copy second line Y */ - ldst = (unsigned long *)(dst + i * width + width); - for (j = 0; j < width; j += sizeof(long)) { - *ldst = *lsrc++; - *ldst++ ^= 0x8080808080808080ULL; - } - } -} diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/spca561-decompress.c b/v4l2-apps/lib/libv4l/libv4lconvert/spca561-decompress.c deleted file mode 100644 index 01eed4ec5..000000000 --- a/v4l2-apps/lib/libv4l/libv4lconvert/spca561-decompress.c +++ /dev/null @@ -1,1003 +0,0 @@ -/* - -# Spca561decoder (C) 2005 Andrzej Szombierski [qq@kuku.eu.org] - -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 2.1 of the License, or -# (at your option) any later version. -# -# 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 Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -# Note this code was originally licensed under the GNU GPL instead of the -# GNU LGPL, its license has been changed with permission, see the permission -# mail at the end of this file. - -*/ - -/* - * Decoder for compressed spca561 images - * It was developed for "Labtec WebCam Elch 2(SPCA561A)" (046d:0929) - * but it might work with other spca561 cameras - */ -#include -#include "libv4lconvert-priv.h" - -/*fixme: not reentrant */ -static unsigned int bit_bucket; -static const unsigned char *input_ptr; - -static inline void refill(int *bitfill) -{ - if (*bitfill < 8) { - bit_bucket = (bit_bucket << 8) | *(input_ptr++); - *bitfill += 8; - } -} - -static inline int nbits(int *bitfill, int n) -{ - bit_bucket = (bit_bucket << 8) | *(input_ptr++); - *bitfill -= n; - return (bit_bucket >> (*bitfill & 0xff)) & ((1 << n) - 1); -} - -static inline int _nbits(int *bitfill, int n) -{ - *bitfill -= n; - return (bit_bucket >> (*bitfill & 0xff)) & ((1 << n) - 1); -} - -static int fun_A(int *bitfill) -{ - int ret; - static int tab[] = { - 12, 13, 14, 15, 16, 17, 18, 19, -12, -13, -14, -15, - -16, -17, -18, -19, -19 - }; - - ret = tab[nbits(bitfill, 4)]; - - refill(bitfill); - return ret; -} -static int fun_B(int *bitfill) -{ - static int tab1[] = - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31, 31, - 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, - 16, 17, - 18, - 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 - }; - static int tab[] = - { 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -5, - -6, -7, -8, -9, -10, -11, -12, -13, -14, -15, -16, -17, - -18, -19 - }; - unsigned int tmp; - - tmp = nbits(bitfill, 7) - 68; - refill(bitfill); - if (tmp > 47) - return 0xff; - return tab[tab1[tmp]]; -} -static int fun_C(int *bitfill, int gkw) -{ - static int tab1[] = - { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 23, 23, 23, 23, 23, 23, - 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, - 12, 13, - 14, - 15, 16, 17, 18, 19, 20, 21, 22 - }; - static int tab[] = - { 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -9, -10, -11, - -12, -13, -14, -15, -16, -17, -18, -19 - }; - unsigned int tmp; - - if (gkw == 0xfe) { - if (nbits(bitfill, 1) == 0) - return 7; - else - return -8; - } - - if (gkw != 0xff) - return 0xff; - - tmp = nbits(bitfill, 7) - 72; - if (tmp > 43) - return 0xff; - - refill(bitfill); - return tab[tab1[tmp]]; -} -static int fun_D(int *bitfill, int gkw) -{ - if (gkw == 0xfd) { - if (nbits(bitfill, 1) == 0) - return 12; - return -13; - } - - if (gkw == 0xfc) { - if (nbits(bitfill, 1) == 0) - return 13; - return -14; - } - - if (gkw == 0xfe) { - switch (nbits(bitfill, 2)) { - case 0: - return 14; - case 1: - return -15; - case 2: - return 15; - case 3: - return -16; - } - } - - if (gkw == 0xff) { - switch (nbits(bitfill, 3)) { - case 4: - return 16; - case 5: - return -17; - case 6: - return 17; - case 7: - return -18; - case 2: - return _nbits(bitfill, 1) ? 0xed : 0x12; - case 3: - (*bitfill)--; - return 18; - } - return 0xff; - } - return gkw; -} - -static int fun_E(int cur_byte, int *bitfill) -{ - static int tab0[] = { 0, -1, 1, -2, 2, -3, 3, -4 }; - static int tab1[] = { 4, -5, 5, -6, 6, -7, 7, -8 }; - static int tab2[] = { 8, -9, 9, -10, 10, -11, 11, -12 }; - static int tab3[] = { 12, -13, 13, -14, 14, -15, 15, -16 }; - static int tab4[] = { 16, -17, 17, -18, 18, -19, 19, -19 }; - - if ((cur_byte & 0xf0) >= 0x80) { - *bitfill -= 4; - return tab0[(cur_byte >> 4) & 7]; - } - if ((cur_byte & 0xc0) == 0x40) { - *bitfill -= 5; - return tab1[(cur_byte >> 3) & 7]; - - } - if ((cur_byte & 0xe0) == 0x20) { - *bitfill -= 6; - return tab2[(cur_byte >> 2) & 7]; - - } - if ((cur_byte & 0xf0) == 0x10) { - *bitfill -= 7; - return tab3[(cur_byte >> 1) & 7]; - - } - if ((cur_byte & 0xf8) == 8) { - *bitfill -= 8; - return tab4[cur_byte & 7]; - } - return 0xff; -} - -static int fun_F(int cur_byte, int *bitfill) -{ - *bitfill -= 5; - switch (cur_byte & 0xf8) { - case 0x80: - return 0; - case 0x88: - return -1; - case 0x90: - return 1; - case 0x98: - return -2; - case 0xa0: - return 2; - case 0xa8: - return -3; - case 0xb0: - return 3; - case 0xb8: - return -4; - case 0xc0: - return 4; - case 0xc8: - return -5; - case 0xd0: - return 5; - case 0xd8: - return -6; - case 0xe0: - return 6; - case 0xe8: - return -7; - case 0xf0: - return 7; - case 0xf8: - return -8; - } - - *bitfill -= 1; - switch (cur_byte & 0xfc) { - case 0x40: - return 8; - case 0x44: - return -9; - case 0x48: - return 9; - case 0x4c: - return -10; - case 0x50: - return 10; - case 0x54: - return -11; - case 0x58: - return 11; - case 0x5c: - return -12; - case 0x60: - return 12; - case 0x64: - return -13; - case 0x68: - return 13; - case 0x6c: - return -14; - case 0x70: - return 14; - case 0x74: - return -15; - case 0x78: - return 15; - case 0x7c: - return -16; - } - - *bitfill -= 1; - switch (cur_byte & 0xfe) { - case 0x20: - return 16; - case 0x22: - return -17; - case 0x24: - return 17; - case 0x26: - return -18; - case 0x28: - return 18; - case 0x2a: - return -19; - case 0x2c: - return 19; - } - - *bitfill += 7; - return 0xff; -} - -static int internal_spca561_decode(int width, int height, - const unsigned char *inbuf, - unsigned char *outbuf) -{ - /* buffers */ - static int accum[8 * 8 * 8]; - static int i_hits[8 * 8 * 8]; - - const int nbits_A[] = - { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, - 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, - 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, - 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, - 1, 1, 1, 1, 1, - 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 7, 7, - 7, 7, - 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, - 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, - 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 3, 3, 3, 3, 3, - 3, 3, - 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - }; - const int tab_A[] = - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, 11, -11, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, - 10, 10, - 255, 254, -4, - -4, -5, -5, -6, -6, -7, -7, -8, -8, -9, -9, -10, -10, -1, - -1, -1, - -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, - -1, -1, - -1, -1, -1, -1, -1, -1, -1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, - 3, 3, 3, - 3, 3, 3, - -2, -2, -2, -2, -2, -2, -2, -2, -3, -3, -3, -3, -3, -3, -3, - -3, 1, - 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, - 1, 1, 1, 1, - 1 - }; - - const int nbits_B[] = - { 0, 8, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, - 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, - 2, 2, - 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, - 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, - 2, 2, 2, 2, 2, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, - 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, - 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, - 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, - 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - }; - const int tab_B[] = - { 0xff, -4, 3, 3, -3, -3, -3, -3, 2, 2, 2, 2, 2, 2, 2, 2, -2, - -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, - 1, 1, - 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, - 1, 1, 1, 1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, - -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, - -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, - -1, -1, - -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, - }; - - const int nbits_C[] = - { 0, 0, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, - 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, - 3, 3, - 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, - 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, - 3, 3, 3, 3, 3, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, - 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, - 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, - 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, - 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - }; - const int tab_C[] = - { 0xff, 0xfe, 6, -7, 5, 5, -6, -6, 4, 4, 4, 4, -5, -5, -5, -5, - 3, 3, 3, 3, 3, 3, 3, 3, -4, -4, -4, -4, -4, -4, -4, -4, 2, - 2, 2, 2, - 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, -3, -3, -3, -3, -3, -3, -3, -3, - -3, -3, - -3, -3, -3, - -3, -3, -3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, - 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -2, -2, -2, -2, -2, -2, -2, - -2, -2, - -2, -2, -2, - -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, - -2, -2, - -2, -2, - -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, - -1, -1, - -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, - -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, - -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, - }; - - const int nbits_D[] = - { 0, 0, 0, 0, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, - 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, - 4, 4, - 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, - 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, - 4, 4, - 4, 4, 4, 4, 4, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, - 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, - 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, - 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 3, 3, - 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 - }; - const int tab_D[] = - { 0xff, 0xfe, 0xfd, 0xfc, 10, -11, 11, -12, 8, 8, -9, -9, 9, 9, - -10, -10, 6, 6, 6, 6, -7, -7, -7, -7, 7, 7, 7, 7, -8, -8, - -8, -8, - 4, 4, 4, 4, - 4, 4, 4, 4, -5, -5, -5, -5, -5, -5, -5, -5, 5, 5, 5, 5, 5, - 5, 5, 5, - -6, -6, - -6, -6, -6, -6, -6, -6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, - 2, 2, -3, - -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, - 3, 3, - 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -4, -4, -4, -4, -4, -4, -4, - -4, -4, - -4, -4, -4, - -4, -4, -4, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, - -1, -1, - -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, - -1, -1, - -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, - 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, -2, -2, -2, -2, -2, -2, -2, -2, - -2, -2, - -2, -2, -2, - -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, - -2, -2, - -2, -2 - }; - - /* a_curve[19 + i] = ... [-19..19] => [-160..160] */ - const int a_curve[] = - { -160, -144, -128, -112, -98, -88, -80, -72, -64, -56, -48, - -40, -32, -24, -18, -12, -8, -5, -2, 0, 2, 5, 8, 12, 18, - 24, 32, - 40, 48, 56, 64, - 72, 80, 88, 98, 112, 128, 144, 160 - }; - /* clamp0_255[256 + i] = min(max(i,255),0) */ - const unsigned char clamp0_255[] = - { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 1, 2, - 3, 4, 5, 6, 7, 8, 9, 10, - 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, - 28, 29, 30, 31, 32, 33, - 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, - 49, 50, - 51, 52, 53, 54, 55, 56, - 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, - 72, 73, - 74, 75, 76, 77, 78, 79, - 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, - 95, 96, - 97, 98, 99, 100, 101, - 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, - 114, - 115, 116, 117, 118, 119, - 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, - 132, - 133, 134, 135, 136, 137, - 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, - 150, - 151, 152, 153, 154, 155, - 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, - 168, - 169, 170, 171, 172, 173, - 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, - 186, - 187, 188, 189, 190, 191, - 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, - 204, - 205, 206, 207, 208, 209, - 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, - 222, - 223, 224, 225, 226, 227, - 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, - 240, - 241, 242, 243, 244, 245, - 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 255, 255, - 255, - 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, - 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, - 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, - 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, - 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, - 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, - 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, - 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, - 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, - 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, - 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, - 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, - 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, - 255, 255, 255, 255, 255, - 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, - 255, - 255 - }; - /* abs_clamp15[19 + i] = min(abs(i), 15) */ - const int abs_clamp15[] = - { 15, 15, 15, 15, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, - 2, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 15, 15, - 15 - }; - /* diff_encoding[256 + i] = ... */ - const int diff_encoding[] = - { 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, - 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, - 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, - 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, - 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, - 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, - 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, - 7, 7, 7, 7, 7, 7, 7, - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5, 5, 5, 5, 5, 5, 5, - 5, 5, - 5, 5, 5, 5, 5, 3, 3, - 3, 3, 1, 1, 0, 2, 2, 4, 4, 4, 4, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, - 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, - 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, - 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, - 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, - 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, - 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, - 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, - 6, 6, 6, 6, 6, 6, 6, - 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, - 6, 6, - 6, 6, 6, 6, 6, 6 - }; - - int block; - int bitfill = 0; - int xwidth = width + 6; - int off_up_right = 2 - 2 * xwidth; - int off_up_left = -2 - 2 * xwidth; - int pixel_U = 0, saved_pixel_UR = 0; - int pixel_x = 0, pixel_y = 2; - unsigned char *output_ptr = outbuf; - - memset(i_hits, 0, sizeof(i_hits)); - memset(accum, 0, sizeof(accum)); - - memcpy(outbuf + xwidth * 2 + 3, inbuf + 0x14, width); - memcpy(outbuf + xwidth * 3 + 3, inbuf + 0x14 + width, width); - - input_ptr = inbuf + 0x14 + width * 2; - output_ptr = outbuf + (xwidth) * 4 + 3; - - bit_bucket = 0; - - for (block = 0; block < ((height - 2) * width) / 32; ++block) { - int b_it, var_7 = 0; - int cur_byte; - - refill(&bitfill); - - cur_byte = (bit_bucket >> (bitfill & 7)) & 0xff; - - if ((cur_byte & 0x80) == 0) { - var_7 = 0; - bitfill--; - } else if ((cur_byte & 0xC0) == 0x80) { - var_7 = 1; - bitfill -= 2; - } else if ((cur_byte & 0xc0) == 0xc0) { - var_7 = 2; - bitfill -= 2; - } - - for (b_it = 0; b_it < 32; b_it++) { - int index; - int pixel_L, pixel_UR, pixel_UL; - int multiplier; - int dL, dC, dR; - int gkw; /* God knows what */ - - refill(&bitfill); - cur_byte = bit_bucket >> (bitfill & 7) & 0xff; - - pixel_L = output_ptr[-2]; - pixel_UR = output_ptr[off_up_right]; - pixel_UL = output_ptr[off_up_left]; - - dL = diff_encoding[0x100 + pixel_UL - pixel_L]; - dC = diff_encoding[0x100 + pixel_U - pixel_UL]; - dR = diff_encoding[0x100 + pixel_UR - pixel_U]; - - if (pixel_x < 2) { - pixel_L = pixel_UL = pixel_U = - output_ptr[-xwidth * 2]; - pixel_UR = output_ptr[off_up_right]; - dL = dC = 0; - dR = diff_encoding[0x100 + pixel_UR - - pixel_U]; - } else if (pixel_x > width - 3) - dR = 0; - - multiplier = 4; - index = dR + dC * 8 + dL * 64; - - if (pixel_L + pixel_U * 2 <= 144 - && (pixel_y & 1) == 0 - && (b_it & 3) == 0 && (dR < 5) && (dC < 5) - && (dL < 5)) { - multiplier = 1; - } else if (pixel_L <= 48 - && dL <= 4 && dC <= 4 && dL >= 1 - && dC >= 1) { - multiplier = 2; - } else if (var_7 == 1) { - multiplier = 2; - } else if (dC + dL >= 11 || var_7 == 2) { - multiplier = 8; - } - - if (i_hits[index] < 7) { - bitfill -= nbits_A[cur_byte]; - gkw = tab_A[cur_byte]; - if (gkw == 0xfe) - gkw = fun_A(&bitfill); - } else if (i_hits[index] >= accum[index]) { - bitfill -= nbits_B[cur_byte]; - gkw = tab_B[cur_byte]; - if (cur_byte == 0) - gkw = fun_B(&bitfill); - } else if (i_hits[index] * 2 >= accum[index]) { - bitfill -= nbits_C[cur_byte]; - gkw = tab_C[cur_byte]; - if (cur_byte < 2) - gkw = fun_C(&bitfill, gkw); - } else if (i_hits[index] * 4 >= accum[index]) { - bitfill -= nbits_D[cur_byte]; - gkw = tab_D[cur_byte]; - if (cur_byte < 4) - gkw = fun_D(&bitfill, gkw); - } else if (i_hits[index] * 8 >= accum[index]) { - gkw = fun_E(cur_byte, &bitfill); - } else { - gkw = fun_F(cur_byte, &bitfill); - } - - if (gkw == 0xff) - return -3; - - { - int tmp1, tmp2; - - tmp1 = - (pixel_U + pixel_L) * 3 - pixel_UL * 2; - tmp1 += (tmp1 < 0) ? 3 : 0; - tmp2 = a_curve[19 + gkw] * multiplier; - tmp2 += (tmp2 < 0) ? 1 : 0; - - *(output_ptr++) = - clamp0_255[0x100 + (tmp1 >> 2) - - (tmp2 >> 1)]; - } - pixel_U = saved_pixel_UR; - saved_pixel_UR = pixel_UR; - - if (++pixel_x == width) { - output_ptr += 6; - pixel_x = 0; - pixel_y++; - } - - accum[index] += abs_clamp15[19 + gkw]; - - if (i_hits[index]++ == 15) { - i_hits[index] = 8; - accum[index] /= 2; - } - } - } - return 0; -} - -/* FIXME, change internal_spca561_decode not to need the extra border - around its dest buffer */ -void v4lconvert_decode_spca561(const unsigned char *inbuf, - unsigned char *outbuf, int width, int height) -{ - int i; - static unsigned char tmpbuf[650 * 490]; - if (internal_spca561_decode(width, height, inbuf, tmpbuf) != 0) - return; - for (i = 0; i < height; i++) - memcpy(outbuf + i * width, - tmpbuf + (i + 2) * (width + 6) + 3, width); -} - -/*************** License Change Permission Notice *************** - -Return-Path: -Received: from koko.hhs.nl ([145.52.2.16] verified) - by hhs.nl (CommuniGate Pro SMTP 4.3.6) - with ESMTP id 88574071 for j.w.r.degoede@hhs.nl; Mon, 16 Jun 2008 16:36:24 +0200 -Received: from exim (helo=koko) - by koko.hhs.nl with local-smtp (Exim 4.62) - (envelope-from ) - id 1K8Fom-0002iJ-3K - for j.w.r.degoede@hhs.nl; Mon, 16 Jun 2008 16:36:24 +0200 -Received: from [192.87.102.74] (port=41377 helo=filter6-ams.mf.surf.net) - by koko.hhs.nl with esmtp (Exim 4.62) - (envelope-from ) - id 1K8Fol-0002iC-Qo - for j.w.r.degoede@hhs.nl; Mon, 16 Jun 2008 16:36:23 +0200 -Received: from kuku.eu.org (pa90.wielkopole.sdi.tpnet.pl [217.99.123.90]) - by filter6-ams.mf.surf.net (8.13.8/8.13.8/Debian-3) with ESMTP id m5GEa55r001787 - for ; Mon, 16 Jun 2008 16:36:06 +0200 -Received: (qmail 2243 invoked by uid 500); 16 Jun 2008 14:29:37 -0000 -Date: Mon, 16 Jun 2008 16:29:37 +0200 (CEST) -From: Andrzej Szombierski -To: Hans de Goede -Subject: Re: spca561 decoder license question -In-Reply-To: <485673B6.4050003@hhs.nl> -Message-ID: -References: <485673B6.4050003@hhs.nl> -MIME-Version: 1.0 -Content-Type: TEXT/PLAIN; charset=iso-8859-2 -Content-Transfer-Encoding: QUOTED-PRINTABLE -X-Canit-CHI2: 0.00 -X-Bayes-Prob: 0.0001 (Score 0, tokens from: @@RPTN) -X-Spam-Score: 2.00 (**) [Tag at 6.00] RBL(uceprotect-blacklist.surfnet.nl,2.0) -X-CanItPRO-Stream: hhs:j.w.r.degoede@hhs.nl (inherits from hhs:default,base:default) -X-Canit-Stats-ID: 85673281 - 37e52c8b07bc -X-Scanned-By: CanIt (www . roaringpenguin . com) on 192.87.102.74 -X-Anti-Virus: Kaspersky Anti-Virus for MailServers 5.5.2/RELEASE, bases: 16062008 #776409, status: clean - -On Mon, 16 Jun 2008, Hans de Goede wrote: - -> Hi, ->=20 -> I don't know if you're still subscribed to the spca devel mailing list, s= -o let=20 -> me start with a short intro. -> -> I'm a Linux enthusiast / developer currently helping Jean-Fran=E7ois Moin= -e with=20 -> porting gspca to video4linux2 and cleaning up the code to get it ready fo= -r=20 -> mainline kernel inclusion. ->=20 -> As part of this process the decompression code for all supported cams mus= -t be=20 -> moved to userspace, as doing in kernel decompression is considered unwant= -ed by=20 -> the mainline people (I agree) as it should be done in userspace. -> - -Sounds reasonable. -=20 -> As such I'm working on a library which does decompression of custom cam f= -ormats=20 -> in userspace. -> - -Nice. I hope that the library won't be limited to spca-supported webcams,= -=20 -and as an application developer I would be able to just request RGB data=20 -from any /dev/video*, right? - -> I do not want to license this library as GPL (as the current spca code is= -), as=20 -> it should be usable by as much software as possible. Instead I want to li= -cense=20 -> it under the LGPL version 2.1 or later. - -Also sounds reasonable. - ->=20 -> So my question us my I have your permission to relicense your spca561=20 -> decompression code under the LGPL? ->=20 - -Yes, of course.=20 - -> Thanks & Regards, ->=20 -> Hans ->=20 -> - ---=20 -:: Andrzej Szombierski :: qq@kuku.eu.org :: http://kuku.eu.org :: -:: anszom@bezkitu.com :: radio bez kitu :: http://bezkitu.com :: - -*/ diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/tinyjpeg-internal.h b/v4l2-apps/lib/libv4l/libv4lconvert/tinyjpeg-internal.h deleted file mode 100644 index 26844c28a..000000000 --- a/v4l2-apps/lib/libv4l/libv4lconvert/tinyjpeg-internal.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Small jpeg decoder library (Internal header) - * - * Copyright (c) 2006, Luc Saillard - * All rights reserved. - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * - Neither the name of the author nor the names of its contributors may be - * used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - - -#ifndef __TINYJPEG_INTERNAL_H_ -#define __TINYJPEG_INTERNAL_H_ - -#include - -#define SANITY_CHECK 1 - -struct jdec_private; - -#define HUFFMAN_HASH_NBITS 9 -#define HUFFMAN_HASH_SIZE (1UL< - * All rights reserved. - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * - Neither the name of the author nor the names of its contributors may be - * used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - -#include -#include -#include -#include -#include - -#include "tinyjpeg.h" -#include "tinyjpeg-internal.h" - -enum std_markers { - DQT = 0xDB, /* Define Quantization Table */ - SOF = 0xC0, /* Start of Frame (size information) */ - DHT = 0xC4, /* Huffman Table */ - SOI = 0xD8, /* Start of Image */ - SOS = 0xDA, /* Start of Scan */ - RST = 0xD0, /* Reset Marker d0 -> .. */ - RST7 = 0xD7, /* Reset Marker .. -> d7 */ - EOI = 0xD9, /* End of Image */ - DRI = 0xDD, /* Define Restart Interval */ - APP0 = 0xE0, -}; - -#define cY 0 -#define cCb 1 -#define cCr 2 - -#define BLACK_Y 0 -#define BLACK_U 127 -#define BLACK_V 127 - -#if DEBUG -#if LOG2FILE - -#define trace(fmt, args...) do { \ - FILE *f = fopen("/tmp/jpeg.log", "a"); \ - fprintf(f, fmt, ## args); \ - fflush(f); \ - fclose(f); \ -} while(0) - -#else - -#define trace(fmt, args...) do { \ - fprintf(stderr, fmt, ## args); \ - fflush(stderr); \ -} while(0) -#endif - -#else -#define trace(fmt, args...) do { } while (0) -#endif - -#define error(fmt, args...) do { \ - snprintf(priv->error_string, sizeof(priv->error_string), fmt, ## args); \ - return -1; \ -} while(0) - - -#if 0 -static char *print_bits(unsigned int value, char *bitstr) -{ - int i, j; - i=31; - while (i>0) - { - if (value & (1UL<=0) - { - bitstr[j++] = (value & (1UL< - * Ex: 0000 0000 1010 0000 1111 0000 <== reservoir - * ^ - * bit 1 - * To get two bits from this example - * result = (reservoir >> 15) & 3 - * - */ -#define fill_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted) do { \ - while (nbits_in_reservoir= priv->stream_end) { \ - snprintf(priv->error_string, sizeof(priv->error_string), \ - "fill_nbits error: need %u more bits\n", \ - nbits_wanted - nbits_in_reservoir); \ - longjmp(priv->jump_state, -EIO); \ - } \ - c = *stream++; \ - reservoir <<= 8; \ - if (c == 0xff && *stream == 0x00) \ - stream++; \ - reservoir |= c; \ - nbits_in_reservoir+=8; \ - } \ -} while(0); - -/* Signed version !!!! */ -#define get_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted,result) do { \ - fill_nbits(reservoir,nbits_in_reservoir,stream,(nbits_wanted)); \ - result = ((reservoir)>>(nbits_in_reservoir-(nbits_wanted))); \ - nbits_in_reservoir -= (nbits_wanted); \ - reservoir &= ((1U<>(nbits_in_reservoir-(nbits_wanted))); \ -} while(0); - -/* To speed up the decoding, we assume that the reservoir have enough bit - * slow version: - * #define skip_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted) do { \ - * fill_nbits(reservoir,nbits_in_reservoir,stream,(nbits_wanted)); \ - * nbits_in_reservoir -= (nbits_wanted); \ - * reservoir &= ((1U<= priv->stream_end) { \ - snprintf(priv->error_string, sizeof(priv->error_string), \ - "fill_nbits error: need %u more bits\n", \ - nbits_wanted - nbits_in_reservoir); \ - longjmp(priv->jump_state, -EIO); \ - } \ - c = *stream++; \ - reservoir <<= 8; \ - if (c == 0xff) { \ - switch (stream[0]) { \ - case 0x00: \ - stream++; \ - break; \ - case 0xd9: /* EOF marker */ \ - stream++; \ - if (stream != priv->stream_end) { \ - snprintf(priv->error_string, sizeof(priv->error_string), \ - "Pixart JPEG error: premature EOF\n"); \ - longjmp(priv->jump_state, -EIO); \ - } \ - break; \ - case 0xff: \ - if (stream[1] == 0xff && (stream[2] < 7 || stream[2] == 0xff)) { \ - stream += 3; \ - c = *stream++; \ - break; \ - } \ - /* Error fall through */ \ - default: \ - snprintf(priv->error_string, sizeof(priv->error_string), \ - "Pixart JPEG error: invalid JPEG marker: 0xff 0x%02x 0x%02x 0x%02x\n", \ - (unsigned int)stream[0], (unsigned int)stream[1], \ - (unsigned int)stream[2]); \ - longjmp(priv->jump_state, -EIO); \ - } \ - } \ - reservoir |= c; \ - nbits_in_reservoir+=8; \ - } \ -} while(0); - -/* Signed version !!!! */ -#define pixart_get_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted,result) \ -do { \ - pixart_fill_nbits(reservoir,nbits_in_reservoir,stream,(nbits_wanted)); \ - result = ((reservoir)>>(nbits_in_reservoir-(nbits_wanted))); \ - nbits_in_reservoir -= (nbits_wanted); \ - reservoir &= ((1U<>(nbits_in_reservoir-(nbits_wanted))); \ -} while(0); - -/* Note skip_nbits is identical for both */ - - -#define be16_to_cpu(x) (((x)[0]<<8)|(x)[1]) - -static void resync(struct jdec_private *priv); - -/** - * Get the next (valid) huffman code in the stream. - * - * To speedup the procedure, we look HUFFMAN_HASH_NBITS bits and the code is - * lower than HUFFMAN_HASH_NBITS we have automaticaly the length of the code - * and the value by using two lookup table. - * Else if the value is not found, just search (linear) into an array for each - * bits is the code is present. - * - * If the code is not present for any reason, -1 is return. - */ -static int get_next_huffman_code(struct jdec_private *priv, struct huffman_table *huffman_table) -{ - int value, hcode; - unsigned int extra_nbits, nbits; - uint16_t *slowtable; - - look_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, HUFFMAN_HASH_NBITS, hcode); - value = huffman_table->lookup[hcode]; - if (value >= 0) - { - unsigned int code_size = huffman_table->code_size[value]; - skip_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, code_size); - return value; - } - - /* Decode more bits each time ... */ - for (extra_nbits=0; extra_nbits<16-HUFFMAN_HASH_NBITS; extra_nbits++) - { - nbits = HUFFMAN_HASH_NBITS + 1 + extra_nbits; - - look_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, nbits, hcode); - slowtable = huffman_table->slowtable[extra_nbits]; - /* Search if the code is in this array */ - while (slowtable[0]) { - if (slowtable[0] == hcode) { - skip_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, nbits); - return slowtable[1]; - } - slowtable+=2; - } - } - snprintf(priv->error_string, sizeof(priv->error_string), - "unknown huffman code: %08x\n", (unsigned int)hcode); - longjmp(priv->jump_state, -EIO); - return 0; -} - -/* identical as above but with *_nbits replaced with pixart_*_nbits */ -static int pixart_get_next_huffman_code(struct jdec_private *priv, - struct huffman_table *huffman_table) -{ - int value, hcode; - unsigned int extra_nbits, nbits; - uint16_t *slowtable; - - pixart_look_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, HUFFMAN_HASH_NBITS, hcode); - value = huffman_table->lookup[hcode]; - if (value >= 0) - { - unsigned int code_size = huffman_table->code_size[value]; - skip_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, code_size); - return value; - } - - /* Decode more bits each time ... */ - for (extra_nbits=0; extra_nbits<16-HUFFMAN_HASH_NBITS; extra_nbits++) - { - nbits = HUFFMAN_HASH_NBITS + 1 + extra_nbits; - - pixart_look_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, nbits, hcode); - slowtable = huffman_table->slowtable[extra_nbits]; - /* Search if the code is in this array */ - while (slowtable[0]) { - if (slowtable[0] == hcode) { - skip_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, nbits); - return slowtable[1]; - } - slowtable+=2; - } - } - snprintf(priv->error_string, sizeof(priv->error_string), - "unknown huffman code: %08x\n", (unsigned int)hcode); - longjmp(priv->jump_state, -EIO); - return 0; -} - - - -/** - * - * Decode a single block that contains the DCT coefficients. - * The table coefficients is already dezigzaged at the end of the operation. - * - */ -static void process_Huffman_data_unit(struct jdec_private *priv, int component) -{ - unsigned char j; - unsigned int huff_code; - unsigned char size_val, count_0; - - struct component *c = &priv->component_infos[component]; - short int DCT[64]; - - /* Initialize the DCT coef table */ - memset(DCT, 0, sizeof(DCT)); - - /* DC coefficient decoding */ - huff_code = get_next_huffman_code(priv, c->DC_table); - if (huff_code) { - get_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, huff_code, DCT[0]); - DCT[0] += c->previous_DC; - c->previous_DC = DCT[0]; - } else { - DCT[0] = c->previous_DC; - } - - - /* AC coefficient decoding */ - j = 1; - while (j<64) - { - huff_code = get_next_huffman_code(priv, c->AC_table); - - size_val = huff_code & 0xF; - count_0 = huff_code >> 4; - - if (size_val == 0) - { /* RLE */ - if (count_0 == 0) - break; /* EOB found, go out */ - else if (count_0 == 0xF) - j += 16; /* skip 16 zeros */ - } - else - { - j += count_0; /* skip count_0 zeroes */ - if (j < 64) { - get_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, size_val, DCT[j]); - j++; - } - } - } - - if (j > 64) { - snprintf(priv->error_string, sizeof(priv->error_string), - "error: more then 63 AC components (%d) in huffman unit\n", (int)j); - longjmp(priv->jump_state, -EIO); - } - - for (j = 0; j < 64; j++) - c->DCT[j] = DCT[zigzag[j]]; -} - -/* identical as above both with *_nbits replaced with pixart_*_nbits */ -static void pixart_process_Huffman_data_unit(struct jdec_private *priv, int component) -{ - unsigned char j; - unsigned int huff_code; - unsigned char size_val, count_0; - - struct component *c = &priv->component_infos[component]; - short int DCT[64]; - - /* Initialize the DCT coef table */ - memset(DCT, 0, sizeof(DCT)); - - /* DC coefficient decoding */ - huff_code = pixart_get_next_huffman_code(priv, c->DC_table); - if (huff_code) { - pixart_get_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, huff_code, DCT[0]); - DCT[0] += c->previous_DC; - c->previous_DC = DCT[0]; - } else { - DCT[0] = c->previous_DC; - } - - - /* AC coefficient decoding */ - j = 1; - while (j<64) - { - huff_code = pixart_get_next_huffman_code(priv, c->AC_table); - - size_val = huff_code & 0xF; - count_0 = huff_code >> 4; - - if (size_val == 0) - { /* RLE */ - if (count_0 == 0) - break; /* EOB found, go out */ - else if (count_0 == 0xF) - j += 16; /* skip 16 zeros */ - } - else - { - j += count_0; /* skip count_0 zeroes */ - if (j < 64 ) { - pixart_get_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, size_val, DCT[j]); - j++; - } - } - } - - if (j > 64) { - snprintf(priv->error_string, sizeof(priv->error_string), - "error: more then 63 AC components (%d) in huffman unit\n", (int)j); - longjmp(priv->jump_state, -EIO); - } - - for (j = 0; j < 64; j++) - c->DCT[j] = DCT[zigzag[j]]; -} - - -/* - * Takes two array of bits, and build the huffman table for size, and code - * - * lookup will return the symbol if the code is less or equal than HUFFMAN_HASH_NBITS. - * code_size will be used to known how many bits this symbol is encoded. - * slowtable will be used when the first lookup didn't give the result. - */ -static int build_huffman_table(struct jdec_private *priv, const unsigned char *bits, const unsigned char *vals, struct huffman_table *table) -{ - unsigned int i, j, code, code_size, val, nbits; - unsigned char huffsize[257], *hz; - unsigned int huffcode[257], *hc; - int next_free_entry; - int slowtable_used[16-HUFFMAN_HASH_NBITS]; - - /* - * Build a temp array - * huffsize[X] => numbers of bits to write vals[X] - */ - hz = huffsize; - for (i=1; i<=16; i++) - { - for (j=1; j<=bits[i]; j++) - *hz++ = i; - } - *hz = 0; - - memset(table->lookup, 0xff, sizeof(table->lookup)); - for (i=0; i<(16-HUFFMAN_HASH_NBITS); i++) - slowtable_used[i] = 0; - - /* Build a temp array - * huffcode[X] => code used to write vals[X] - */ - code = 0; - hc = huffcode; - hz = huffsize; - nbits = *hz; - while (*hz) - { - while (*hz == nbits) { - *hc++ = code++; - hz++; - } - code <<= 1; - nbits++; - } - - /* - * Build the lookup table, and the slowtable if needed. - */ - next_free_entry = -1; - for (i=0; huffsize[i]; i++) - { - val = vals[i]; - code = huffcode[i]; - code_size = huffsize[i]; - - trace("val=%2.2x code=%8.8x codesize=%2.2d\n", i, code, code_size); - - table->code_size[val] = code_size; - if (code_size <= HUFFMAN_HASH_NBITS) - { - /* - * Good: val can be put in the lookup table, so fill all value of this - * column with value val - */ - int repeat = 1UL<<(HUFFMAN_HASH_NBITS - code_size); - code <<= HUFFMAN_HASH_NBITS - code_size; - while ( repeat-- ) - table->lookup[code++] = val; - - } - else - { - /* Perhaps sorting the array will be an optimization */ - int slowtable_index = code_size-HUFFMAN_HASH_NBITS-1; - - if (slowtable_used[slowtable_index] == 254) - error("slow Huffman table overflow\n"); - - table->slowtable[slowtable_index][slowtable_used[slowtable_index]] - = code; - table->slowtable[slowtable_index][slowtable_used[slowtable_index] + 1] - = val; - slowtable_used[slowtable_index] += 2; - } - } - - for (i=0; i<(16-HUFFMAN_HASH_NBITS); i++) - table->slowtable[i][slowtable_used[i]] = 0; - - return 0; -} - -static int build_default_huffman_tables(struct jdec_private *priv) -{ - if ( (priv->flags & TINYJPEG_FLAGS_MJPEG_TABLE) - && priv->default_huffman_table_initialized) - return 0; - - if (build_huffman_table(priv, bits_dc_luminance, val_dc_luminance, &priv->HTDC[0])) - return -1; - if (build_huffman_table(priv, bits_ac_luminance, val_ac_luminance, &priv->HTAC[0])) - return -1; - - if (build_huffman_table(priv, bits_dc_chrominance, val_dc_chrominance, &priv->HTDC[1])) - return -1; - if (build_huffman_table(priv, bits_ac_chrominance, val_ac_chrominance, &priv->HTAC[1])) - return -1; - - priv->default_huffman_table_initialized = 1; - return 0; -} - - - -/******************************************************************************* - * - * Colorspace conversion routine - * - * - * Note: - * YCbCr is defined per CCIR 601-1, except that Cb and Cr are - * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. - * The conversion equations to be implemented are therefore - * R = Y + 1.40200 * Cr - * G = Y - 0.34414 * Cb - 0.71414 * Cr - * B = Y + 1.77200 * Cb - * - ******************************************************************************/ - -static unsigned char clamp(int i) -{ - if (i<0) - return 0; - else if (i>255) - return 255; - else - return i; -} - - -/** - * YCrCb -> YUV420P (1x1) - * .---. - * | 1 | - * `---' - */ -static void YCrCB_to_YUV420P_1x1(struct jdec_private *priv) -{ - const unsigned char *s, *y; - unsigned char *p; - int i,j; - - p = priv->plane[0]; - y = priv->Y; - for (i=0; i<8; i++) - { - memcpy(p, y, 8); - p+=priv->width; - y+=8; - } - - p = priv->plane[1]; - s = priv->Cb; - for (i=0; i<8; i+=2) - { - for (j=0; j<8; j+=2, s+=2) - *p++ = *s; - s += 8; /* Skip one line */ - p += priv->width/2 - 4; - } - - p = priv->plane[2]; - s = priv->Cr; - for (i=0; i<8; i+=2) - { - for (j=0; j<8; j+=2, s+=2) - *p++ = *s; - s += 8; /* Skip one line */ - p += priv->width/2 - 4; - } -} - -/** - * YCrCb -> YUV420P (2x1) - * .-------. - * | 1 | 2 | - * `-------' - */ -static void YCrCB_to_YUV420P_2x1(struct jdec_private *priv) -{ - unsigned char *p; - const unsigned char *s, *y1; - unsigned int i; - - p = priv->plane[0]; - y1 = priv->Y; - for (i=0; i<8; i++) - { - memcpy(p, y1, 16); - p += priv->width; - y1 += 16; - } - - p = priv->plane[1]; - s = priv->Cb; - for (i=0; i<8; i+=2) - { - memcpy(p, s, 8); - s += 16; /* Skip one line */ - p += priv->width/2; - } - - p = priv->plane[2]; - s = priv->Cr; - for (i=0; i<8; i+=2) - { - memcpy(p, s, 8); - s += 16; /* Skip one line */ - p += priv->width/2; - } -} - - -/** - * YCrCb -> YUV420P (1x2) - * .---. - * | 1 | - * |---| - * | 2 | - * `---' - */ -static void YCrCB_to_YUV420P_1x2(struct jdec_private *priv) -{ - const unsigned char *s, *y; - unsigned char *p; - int i,j; - - p = priv->plane[0]; - y = priv->Y; - for (i=0; i<16; i++) - { - memcpy(p, y, 8); - p+=priv->width; - y+=8; - } - - p = priv->plane[1]; - s = priv->Cb; - for (i=0; i<8; i++) - { - for (j=0; j<8; j+=2, s+=2) - *p++ = *s; - p += priv->width/2 - 4; - } - - p = priv->plane[2]; - s = priv->Cr; - for (i=0; i<8; i++) - { - for (j=0; j<8; j+=2, s+=2) - *p++ = *s; - p += priv->width/2 - 4; - } -} - -/** - * YCrCb -> YUV420P (2x2) - * .-------. - * | 1 | 2 | - * |---+---| - * | 3 | 4 | - * `-------' - */ -static void YCrCB_to_YUV420P_2x2(struct jdec_private *priv) -{ - unsigned char *p; - const unsigned char *s, *y1; - unsigned int i; - - p = priv->plane[0]; - y1 = priv->Y; - for (i=0; i<16; i++) - { - memcpy(p, y1, 16); - p += priv->width; - y1 += 16; - } - - p = priv->plane[1]; - s = priv->Cb; - for (i=0; i<8; i++) - { - memcpy(p, s, 8); - s += 8; - p += priv->width/2; - } - - p = priv->plane[2]; - s = priv->Cr; - for (i=0; i<8; i++) - { - memcpy(p, s, 8); - s += 8; - p += priv->width/2; - } -} - -/** - * YCrCb -> RGB24 (1x1) - * .---. - * | 1 | - * `---' - */ -static void YCrCB_to_RGB24_1x1(struct jdec_private *priv) -{ - const unsigned char *Y, *Cb, *Cr; - unsigned char *p; - int i,j; - int offset_to_next_row; - -#define SCALEBITS 10 -#define ONE_HALF (1UL << (SCALEBITS-1)) -#define FIX(x) ((int)((x) * (1UL<plane[0]; - Y = priv->Y; - Cb = priv->Cb; - Cr = priv->Cr; - offset_to_next_row = priv->width*3 - 8*3; - for (i=0; i<8; i++) { - - for (j=0; j<8; j++) { - - int y, cb, cr; - int add_r, add_g, add_b; - int r, g , b; - - y = (*Y++) << SCALEBITS; - cb = *Cb++ - 128; - cr = *Cr++ - 128; - add_r = FIX(1.40200) * cr + ONE_HALF; - add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; - add_b = FIX(1.77200) * cb + ONE_HALF; - - r = (y + add_r) >> SCALEBITS; - *p++ = clamp(r); - g = (y + add_g) >> SCALEBITS; - *p++ = clamp(g); - b = (y + add_b) >> SCALEBITS; - *p++ = clamp(b); - - } - - p += offset_to_next_row; - } - -#undef SCALEBITS -#undef ONE_HALF -#undef FIX - -} - -/** - * YCrCb -> BGR24 (1x1) - * .---. - * | 1 | - * `---' - */ -static void YCrCB_to_BGR24_1x1(struct jdec_private *priv) -{ - const unsigned char *Y, *Cb, *Cr; - unsigned char *p; - int i,j; - int offset_to_next_row; - -#define SCALEBITS 10 -#define ONE_HALF (1UL << (SCALEBITS-1)) -#define FIX(x) ((int)((x) * (1UL<plane[0]; - Y = priv->Y; - Cb = priv->Cb; - Cr = priv->Cr; - offset_to_next_row = priv->width*3 - 8*3; - for (i=0; i<8; i++) { - - for (j=0; j<8; j++) { - - int y, cb, cr; - int add_r, add_g, add_b; - int r, g , b; - - y = (*Y++) << SCALEBITS; - cb = *Cb++ - 128; - cr = *Cr++ - 128; - add_r = FIX(1.40200) * cr + ONE_HALF; - add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; - add_b = FIX(1.77200) * cb + ONE_HALF; - - b = (y + add_b) >> SCALEBITS; - *p++ = clamp(b); - g = (y + add_g) >> SCALEBITS; - *p++ = clamp(g); - r = (y + add_r) >> SCALEBITS; - *p++ = clamp(r); - - } - - p += offset_to_next_row; - } - -#undef SCALEBITS -#undef ONE_HALF -#undef FIX - -} - - -/** - * YCrCb -> RGB24 (2x1) - * .-------. - * | 1 | 2 | - * `-------' - */ -static void YCrCB_to_RGB24_2x1(struct jdec_private *priv) -{ - const unsigned char *Y, *Cb, *Cr; - unsigned char *p; - int i,j; - int offset_to_next_row; - -#define SCALEBITS 10 -#define ONE_HALF (1UL << (SCALEBITS-1)) -#define FIX(x) ((int)((x) * (1UL<plane[0]; - Y = priv->Y; - Cb = priv->Cb; - Cr = priv->Cr; - offset_to_next_row = priv->width*3 - 16*3; - for (i=0; i<8; i++) { - - for (j=0; j<8; j++) { - - int y, cb, cr; - int add_r, add_g, add_b; - int r, g , b; - - y = (*Y++) << SCALEBITS; - cb = *Cb++ - 128; - cr = *Cr++ - 128; - add_r = FIX(1.40200) * cr + ONE_HALF; - add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; - add_b = FIX(1.77200) * cb + ONE_HALF; - - r = (y + add_r) >> SCALEBITS; - *p++ = clamp(r); - g = (y + add_g) >> SCALEBITS; - *p++ = clamp(g); - b = (y + add_b) >> SCALEBITS; - *p++ = clamp(b); - - y = (*Y++) << SCALEBITS; - r = (y + add_r) >> SCALEBITS; - *p++ = clamp(r); - g = (y + add_g) >> SCALEBITS; - *p++ = clamp(g); - b = (y + add_b) >> SCALEBITS; - *p++ = clamp(b); - - } - - p += offset_to_next_row; - } - -#undef SCALEBITS -#undef ONE_HALF -#undef FIX - -} - -/* - * YCrCb -> BGR24 (2x1) - * .-------. - * | 1 | 2 | - * `-------' - */ -static void YCrCB_to_BGR24_2x1(struct jdec_private *priv) -{ - const unsigned char *Y, *Cb, *Cr; - unsigned char *p; - int i,j; - int offset_to_next_row; - -#define SCALEBITS 10 -#define ONE_HALF (1UL << (SCALEBITS-1)) -#define FIX(x) ((int)((x) * (1UL<plane[0]; - Y = priv->Y; - Cb = priv->Cb; - Cr = priv->Cr; - offset_to_next_row = priv->width*3 - 16*3; - for (i=0; i<8; i++) { - - for (j=0; j<8; j++) { - - int y, cb, cr; - int add_r, add_g, add_b; - int r, g , b; - - cb = *Cb++ - 128; - cr = *Cr++ - 128; - add_r = FIX(1.40200) * cr + ONE_HALF; - add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; - add_b = FIX(1.77200) * cb + ONE_HALF; - - y = (*Y++) << SCALEBITS; - b = (y + add_b) >> SCALEBITS; - *p++ = clamp(b); - g = (y + add_g) >> SCALEBITS; - *p++ = clamp(g); - r = (y + add_r) >> SCALEBITS; - *p++ = clamp(r); - - y = (*Y++) << SCALEBITS; - b = (y + add_b) >> SCALEBITS; - *p++ = clamp(b); - g = (y + add_g) >> SCALEBITS; - *p++ = clamp(g); - r = (y + add_r) >> SCALEBITS; - *p++ = clamp(r); - - } - - p += offset_to_next_row; - } - -#undef SCALEBITS -#undef ONE_HALF -#undef FIX - -} - -/** - * YCrCb -> RGB24 (1x2) - * .---. - * | 1 | - * |---| - * | 2 | - * `---' - */ -static void YCrCB_to_RGB24_1x2(struct jdec_private *priv) -{ - const unsigned char *Y, *Cb, *Cr; - unsigned char *p, *p2; - int i,j; - int offset_to_next_row; - -#define SCALEBITS 10 -#define ONE_HALF (1UL << (SCALEBITS-1)) -#define FIX(x) ((int)((x) * (1UL<plane[0]; - p2 = priv->plane[0] + priv->width*3; - Y = priv->Y; - Cb = priv->Cb; - Cr = priv->Cr; - offset_to_next_row = 2*priv->width*3 - 8*3; - for (i=0; i<8; i++) { - - for (j=0; j<8; j++) { - - int y, cb, cr; - int add_r, add_g, add_b; - int r, g , b; - - cb = *Cb++ - 128; - cr = *Cr++ - 128; - add_r = FIX(1.40200) * cr + ONE_HALF; - add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; - add_b = FIX(1.77200) * cb + ONE_HALF; - - y = (*Y++) << SCALEBITS; - r = (y + add_r) >> SCALEBITS; - *p++ = clamp(r); - g = (y + add_g) >> SCALEBITS; - *p++ = clamp(g); - b = (y + add_b) >> SCALEBITS; - *p++ = clamp(b); - - y = (Y[8-1]) << SCALEBITS; - r = (y + add_r) >> SCALEBITS; - *p2++ = clamp(r); - g = (y + add_g) >> SCALEBITS; - *p2++ = clamp(g); - b = (y + add_b) >> SCALEBITS; - *p2++ = clamp(b); - - } - Y += 8; - p += offset_to_next_row; - p2 += offset_to_next_row; - } - -#undef SCALEBITS -#undef ONE_HALF -#undef FIX - -} - -/* - * YCrCb -> BGR24 (1x2) - * .---. - * | 1 | - * |---| - * | 2 | - * `---' - */ -static void YCrCB_to_BGR24_1x2(struct jdec_private *priv) -{ - const unsigned char *Y, *Cb, *Cr; - unsigned char *p, *p2; - int i,j; - int offset_to_next_row; - -#define SCALEBITS 10 -#define ONE_HALF (1UL << (SCALEBITS-1)) -#define FIX(x) ((int)((x) * (1UL<plane[0]; - p2 = priv->plane[0] + priv->width*3; - Y = priv->Y; - Cb = priv->Cb; - Cr = priv->Cr; - offset_to_next_row = 2*priv->width*3 - 8*3; - for (i=0; i<8; i++) { - - for (j=0; j<8; j++) { - - int y, cb, cr; - int add_r, add_g, add_b; - int r, g , b; - - cb = *Cb++ - 128; - cr = *Cr++ - 128; - add_r = FIX(1.40200) * cr + ONE_HALF; - add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; - add_b = FIX(1.77200) * cb + ONE_HALF; - - y = (*Y++) << SCALEBITS; - b = (y + add_b) >> SCALEBITS; - *p++ = clamp(b); - g = (y + add_g) >> SCALEBITS; - *p++ = clamp(g); - r = (y + add_r) >> SCALEBITS; - *p++ = clamp(r); - - y = (Y[8-1]) << SCALEBITS; - b = (y + add_b) >> SCALEBITS; - *p2++ = clamp(b); - g = (y + add_g) >> SCALEBITS; - *p2++ = clamp(g); - r = (y + add_r) >> SCALEBITS; - *p2++ = clamp(r); - - } - Y += 8; - p += offset_to_next_row; - p2 += offset_to_next_row; - } - -#undef SCALEBITS -#undef ONE_HALF -#undef FIX - -} - - -/** - * YCrCb -> RGB24 (2x2) - * .-------. - * | 1 | 2 | - * |---+---| - * | 3 | 4 | - * `-------' - */ -static void YCrCB_to_RGB24_2x2(struct jdec_private *priv) -{ - const unsigned char *Y, *Cb, *Cr; - unsigned char *p, *p2; - int i,j; - int offset_to_next_row; - -#define SCALEBITS 10 -#define ONE_HALF (1UL << (SCALEBITS-1)) -#define FIX(x) ((int)((x) * (1UL<plane[0]; - p2 = priv->plane[0] + priv->width*3; - Y = priv->Y; - Cb = priv->Cb; - Cr = priv->Cr; - offset_to_next_row = (priv->width*3*2) - 16*3; - for (i=0; i<8; i++) { - - for (j=0; j<8; j++) { - - int y, cb, cr; - int add_r, add_g, add_b; - int r, g , b; - - cb = *Cb++ - 128; - cr = *Cr++ - 128; - add_r = FIX(1.40200) * cr + ONE_HALF; - add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; - add_b = FIX(1.77200) * cb + ONE_HALF; - - y = (*Y++) << SCALEBITS; - r = (y + add_r) >> SCALEBITS; - *p++ = clamp(r); - g = (y + add_g) >> SCALEBITS; - *p++ = clamp(g); - b = (y + add_b) >> SCALEBITS; - *p++ = clamp(b); - - y = (*Y++) << SCALEBITS; - r = (y + add_r) >> SCALEBITS; - *p++ = clamp(r); - g = (y + add_g) >> SCALEBITS; - *p++ = clamp(g); - b = (y + add_b) >> SCALEBITS; - *p++ = clamp(b); - - y = (Y[16-2]) << SCALEBITS; - r = (y + add_r) >> SCALEBITS; - *p2++ = clamp(r); - g = (y + add_g) >> SCALEBITS; - *p2++ = clamp(g); - b = (y + add_b) >> SCALEBITS; - *p2++ = clamp(b); - - y = (Y[16-1]) << SCALEBITS; - r = (y + add_r) >> SCALEBITS; - *p2++ = clamp(r); - g = (y + add_g) >> SCALEBITS; - *p2++ = clamp(g); - b = (y + add_b) >> SCALEBITS; - *p2++ = clamp(b); - } - Y += 16; - p += offset_to_next_row; - p2 += offset_to_next_row; - } - -#undef SCALEBITS -#undef ONE_HALF -#undef FIX - -} - - -/* - * YCrCb -> BGR24 (2x2) - * .-------. - * | 1 | 2 | - * |---+---| - * | 3 | 4 | - * `-------' - */ -static void YCrCB_to_BGR24_2x2(struct jdec_private *priv) -{ - const unsigned char *Y, *Cb, *Cr; - unsigned char *p, *p2; - int i,j; - int offset_to_next_row; - -#define SCALEBITS 10 -#define ONE_HALF (1UL << (SCALEBITS-1)) -#define FIX(x) ((int)((x) * (1UL<plane[0]; - p2 = priv->plane[0] + priv->width*3; - Y = priv->Y; - Cb = priv->Cb; - Cr = priv->Cr; - offset_to_next_row = (priv->width*3*2) - 16*3; - for (i=0; i<8; i++) { - - for (j=0; j<8; j++) { - - int y, cb, cr; - int add_r, add_g, add_b; - int r, g , b; - - cb = *Cb++ - 128; - cr = *Cr++ - 128; - add_r = FIX(1.40200) * cr + ONE_HALF; - add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; - add_b = FIX(1.77200) * cb + ONE_HALF; - - y = (*Y++) << SCALEBITS; - b = (y + add_b) >> SCALEBITS; - *p++ = clamp(b); - g = (y + add_g) >> SCALEBITS; - *p++ = clamp(g); - r = (y + add_r) >> SCALEBITS; - *p++ = clamp(r); - - y = (*Y++) << SCALEBITS; - b = (y + add_b) >> SCALEBITS; - *p++ = clamp(b); - g = (y + add_g) >> SCALEBITS; - *p++ = clamp(g); - r = (y + add_r) >> SCALEBITS; - *p++ = clamp(r); - - y = (Y[16-2]) << SCALEBITS; - b = (y + add_b) >> SCALEBITS; - *p2++ = clamp(b); - g = (y + add_g) >> SCALEBITS; - *p2++ = clamp(g); - r = (y + add_r) >> SCALEBITS; - *p2++ = clamp(r); - - y = (Y[16-1]) << SCALEBITS; - b = (y + add_b) >> SCALEBITS; - *p2++ = clamp(b); - g = (y + add_g) >> SCALEBITS; - *p2++ = clamp(g); - r = (y + add_r) >> SCALEBITS; - *p2++ = clamp(r); - } - Y += 16; - p += offset_to_next_row; - p2 += offset_to_next_row; - } - -#undef SCALEBITS -#undef ONE_HALF -#undef FIX - -} - - - -/** - * YCrCb -> Grey (1x1) - * .---. - * | 1 | - * `---' - */ -static void YCrCB_to_Grey_1x1(struct jdec_private *priv) -{ - const unsigned char *y; - unsigned char *p; - unsigned int i; - int offset_to_next_row; - - p = priv->plane[0]; - y = priv->Y; - offset_to_next_row = priv->width; - - for (i=0; i<8; i++) { - memcpy(p, y, 8); - y+=8; - p += offset_to_next_row; - } -} - -/** - * YCrCb -> Grey (2x1) - * .-------. - * | 1 | 2 | - * `-------' - */ -static void YCrCB_to_Grey_2x1(struct jdec_private *priv) -{ - const unsigned char *y; - unsigned char *p; - unsigned int i; - - p = priv->plane[0]; - y = priv->Y; - - for (i=0; i<8; i++) { - memcpy(p, y, 16); - y += 16; - p += priv->width; - } -} - - -/** - * YCrCb -> Grey (1x2) - * .---. - * | 1 | - * |---| - * | 2 | - * `---' - */ -static void YCrCB_to_Grey_1x2(struct jdec_private *priv) -{ - const unsigned char *y; - unsigned char *p; - unsigned int i; - - p = priv->plane[0]; - y = priv->Y; - - for (i=0; i<16; i++) { - memcpy(p, y, 8); - y += 8; - p += priv->width; - } -} - -/** - * YCrCb -> Grey (2x2) - * .-------. - * | 1 | 2 | - * |---+---| - * | 3 | 4 | - * `-------' - */ -static void YCrCB_to_Grey_2x2(struct jdec_private *priv) -{ - const unsigned char *y; - unsigned char *p; - unsigned int i; - - p = priv->plane[0]; - y = priv->Y; - - for (i=0; i<16; i++) { - memcpy(p, y, 16); - y += 16; - p += priv->width; - } -} - - -/* - * Decode all the 3 components for 1x1 - */ -static void decode_MCU_1x1_3planes(struct jdec_private *priv) -{ - // Y - process_Huffman_data_unit(priv, cY); - IDCT(&priv->component_infos[cY], priv->Y, 8); - - // Cb - process_Huffman_data_unit(priv, cCb); - IDCT(&priv->component_infos[cCb], priv->Cb, 8); - - // Cr - process_Huffman_data_unit(priv, cCr); - IDCT(&priv->component_infos[cCr], priv->Cr, 8); -} - -/* - * Decode a 1x1 directly in 1 color - */ -static void decode_MCU_1x1_1plane(struct jdec_private *priv) -{ - // Y - process_Huffman_data_unit(priv, cY); - IDCT(&priv->component_infos[cY], priv->Y, 8); - - // Cb - process_Huffman_data_unit(priv, cCb); - IDCT(&priv->component_infos[cCb], priv->Cb, 8); - - // Cr - process_Huffman_data_unit(priv, cCr); - IDCT(&priv->component_infos[cCr], priv->Cr, 8); -} - - -/* - * Decode a 2x1 - * .-------. - * | 1 | 2 | - * `-------' - */ -static void decode_MCU_2x1_3planes(struct jdec_private *priv) -{ - // Y - process_Huffman_data_unit(priv, cY); - IDCT(&priv->component_infos[cY], priv->Y, 16); - process_Huffman_data_unit(priv, cY); - IDCT(&priv->component_infos[cY], priv->Y+8, 16); - - // Cb - process_Huffman_data_unit(priv, cCb); - IDCT(&priv->component_infos[cCb], priv->Cb, 8); - - // Cr - process_Huffman_data_unit(priv, cCr); - IDCT(&priv->component_infos[cCr], priv->Cr, 8); -} - -static void pixart_decode_MCU_2x1_3planes(struct jdec_private *priv) -{ - unsigned char marker; - - pixart_look_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, - 8, marker); - /* I think the marker indicates which quantization table to use, iow - a Pixart JPEG may have a different quantization table per MCU, most - MCU's have 0x44 as marker for which our special Pixart quantization - tables are correct. Unfortunately with a 7302 some blocks also have 0x48, - and sometimes even other values. As 0x48 is quite common too, we really - need to find out the correct table for that, as currently the blocks - with a 0x48 marker look wrong. During normal operation the marker stays - within the range below, if it gets out of this range we're most likely - decoding garbage */ - if (marker < 0x20 || marker > 0x7f) { - snprintf(priv->error_string, sizeof(priv->error_string), - "Pixart JPEG error: invalid MCU marker: 0x%02x\n", - (unsigned int)marker); - longjmp(priv->jump_state, -EIO); - } - skip_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, 8); - - // Y - pixart_process_Huffman_data_unit(priv, cY); - IDCT(&priv->component_infos[cY], priv->Y, 16); - pixart_process_Huffman_data_unit(priv, cY); - IDCT(&priv->component_infos[cY], priv->Y+8, 16); - - // Cb - pixart_process_Huffman_data_unit(priv, cCb); - IDCT(&priv->component_infos[cCb], priv->Cb, 8); - - // Cr - pixart_process_Huffman_data_unit(priv, cCr); - IDCT(&priv->component_infos[cCr], priv->Cr, 8); -} - -/* - * Decode a 2x1 - * .-------. - * | 1 | 2 | - * `-------' - */ -static void decode_MCU_2x1_1plane(struct jdec_private *priv) -{ - // Y - process_Huffman_data_unit(priv, cY); - IDCT(&priv->component_infos[cY], priv->Y, 16); - process_Huffman_data_unit(priv, cY); - IDCT(&priv->component_infos[cY], priv->Y+8, 16); - - // Cb - process_Huffman_data_unit(priv, cCb); - - // Cr - process_Huffman_data_unit(priv, cCr); -} - - -/* - * Decode a 2x2 - * .-------. - * | 1 | 2 | - * |---+---| - * | 3 | 4 | - * `-------' - */ -static void decode_MCU_2x2_3planes(struct jdec_private *priv) -{ - // Y - process_Huffman_data_unit(priv, cY); - IDCT(&priv->component_infos[cY], priv->Y, 16); - process_Huffman_data_unit(priv, cY); - IDCT(&priv->component_infos[cY], priv->Y+8, 16); - process_Huffman_data_unit(priv, cY); - IDCT(&priv->component_infos[cY], priv->Y+64*2, 16); - process_Huffman_data_unit(priv, cY); - IDCT(&priv->component_infos[cY], priv->Y+64*2+8, 16); - - // Cb - process_Huffman_data_unit(priv, cCb); - IDCT(&priv->component_infos[cCb], priv->Cb, 8); - - // Cr - process_Huffman_data_unit(priv, cCr); - IDCT(&priv->component_infos[cCr], priv->Cr, 8); -} - -/* - * Decode a 2x2 directly in GREY format (8bits) - * .-------. - * | 1 | 2 | - * |---+---| - * | 3 | 4 | - * `-------' - */ -static void decode_MCU_2x2_1plane(struct jdec_private *priv) -{ - // Y - process_Huffman_data_unit(priv, cY); - IDCT(&priv->component_infos[cY], priv->Y, 16); - process_Huffman_data_unit(priv, cY); - IDCT(&priv->component_infos[cY], priv->Y+8, 16); - process_Huffman_data_unit(priv, cY); - IDCT(&priv->component_infos[cY], priv->Y+64*2, 16); - process_Huffman_data_unit(priv, cY); - IDCT(&priv->component_infos[cY], priv->Y+64*2+8, 16); - - // Cb - process_Huffman_data_unit(priv, cCb); - - // Cr - process_Huffman_data_unit(priv, cCr); -} - -/* - * Decode a 1x2 mcu - * .---. - * | 1 | - * |---| - * | 2 | - * `---' - */ -static void decode_MCU_1x2_3planes(struct jdec_private *priv) -{ - // Y - process_Huffman_data_unit(priv, cY); - IDCT(&priv->component_infos[cY], priv->Y, 8); - process_Huffman_data_unit(priv, cY); - IDCT(&priv->component_infos[cY], priv->Y+64, 8); - - // Cb - process_Huffman_data_unit(priv, cCb); - IDCT(&priv->component_infos[cCb], priv->Cb, 8); - - // Cr - process_Huffman_data_unit(priv, cCr); - IDCT(&priv->component_infos[cCr], priv->Cr, 8); -} - -/* - * Decode a 1x2 mcu - * .---. - * | 1 | - * |---| - * | 2 | - * `---' - */ -static void decode_MCU_1x2_1plane(struct jdec_private *priv) -{ - // Y - process_Huffman_data_unit(priv, cY); - IDCT(&priv->component_infos[cY], priv->Y, 8); - process_Huffman_data_unit(priv, cY); - IDCT(&priv->component_infos[cY], priv->Y+64, 8); - - // Cb - process_Huffman_data_unit(priv, cCb); - - // Cr - process_Huffman_data_unit(priv, cCr); -} - -static void print_SOF(const unsigned char *stream) -{ - int width, height, nr_components, precision; -#if DEBUG - const char *nr_components_to_string[] = { - "????", - "Grayscale", - "????", - "YCbCr", - "CYMK" - }; -#endif - - precision = stream[2]; - height = be16_to_cpu(stream+3); - width = be16_to_cpu(stream+5); - nr_components = stream[7]; - - trace("> SOF marker\n"); - trace("Size:%dx%d nr_components:%d (%s) precision:%d\n", - width, height, - nr_components, nr_components_to_string[nr_components], - precision); -} - -/******************************************************************************* - * - * JPEG/JFIF Parsing functions - * - * Note: only a small subset of the jpeg file format is supported. No markers, - * nor progressive stream is supported. - * - ******************************************************************************/ - -static void build_quantization_table(float *qtable, const unsigned char *ref_table) -{ - /* Taken from libjpeg. Copyright Independent JPEG Group's LLM idct. - * For float AA&N IDCT method, divisors are equal to quantization - * coefficients scaled by scalefactor[row]*scalefactor[col], where - * scalefactor[0] = 1 - * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 - * We apply a further scale factor of 8. - * What's actually stored is 1/divisor so that the inner loop can - * use a multiplication rather than a division. - */ - int i, j; - static const double aanscalefactor[8] = { - 1.0, 1.387039845, 1.306562965, 1.175875602, - 1.0, 0.785694958, 0.541196100, 0.275899379 - }; - const unsigned char *zz = zigzag; - - for (i=0; i<8; i++) { - for (j=0; j<8; j++) { - *qtable++ = ref_table[*zz++] * aanscalefactor[i] * aanscalefactor[j]; - } - } - -} - -static int parse_DQT(struct jdec_private *priv, const unsigned char *stream) -{ - int qi; - float *table; - const unsigned char *dqt_block_end; - - trace("> DQT marker\n"); - dqt_block_end = stream + be16_to_cpu(stream); - stream += 2; /* Skip length */ - - while (stream < dqt_block_end) - { - qi = *stream++; -#if SANITY_CHECK - if (qi>>4) - error("16 bits quantization table is not supported\n"); - if (qi >= COMPONENTS) - error("No more than %d quantization tables supported (got %d)\n", - COMPONENTS, qi + 1); -#endif - table = priv->Q_tables[qi]; - build_quantization_table(table, stream); - stream += 64; - } - trace("< DQT marker\n"); - return 0; -} - -static int parse_SOF(struct jdec_private *priv, const unsigned char *stream) -{ - int i, width, height, nr_components, cid, sampling_factor; - int Q_table; - struct component *c; - - trace("> SOF marker\n"); - print_SOF(stream); - - height = be16_to_cpu(stream+3); - width = be16_to_cpu(stream+5); - nr_components = stream[7]; -#if SANITY_CHECK - if (stream[2] != 8) - error("Precision other than 8 is not supported\n"); - if (width>JPEG_MAX_WIDTH || height>JPEG_MAX_HEIGHT) - error("Width and Height (%dx%d) seems suspicious\n", width, height); - if (nr_components != 3) - error("We only support YUV images\n"); - if (height%8) - error("Height need to be a multiple of 8 (current height is %d)\n", height); - if (width%16) - error("Width need to be a multiple of 16 (current Width is %d)\n", width); -#endif - stream += 8; - for (i=0; icomponent_infos[i]; -#if SANITY_CHECK - c->cid = cid; -#endif - c->Vfactor = sampling_factor&0xf; - c->Hfactor = sampling_factor>>4; - c->Q_table = priv->Q_tables[Q_table]; - trace("Component:%d factor:%dx%d Quantization table:%d\n", - cid, c->Hfactor, c->Hfactor, Q_table ); - - } - priv->width = width; - priv->height = height; - - trace("< SOF marker\n"); - - return 0; -} - -static int parse_SOS(struct jdec_private *priv, const unsigned char *stream) -{ - unsigned int i, cid, table; - unsigned int nr_components = stream[2]; - - trace("> SOS marker\n"); - -#if SANITY_CHECK - if (nr_components != 3) - error("We only support YCbCr image\n"); -#endif - - stream += 3; - for (i=0;i= HUFFMAN_TABLES) - error("We do not support more than %d AC Huffman table\n", - HUFFMAN_TABLES); - if ((table>>4) >= HUFFMAN_TABLES) - error("We do not support more than %d DC Huffman table\n", - HUFFMAN_TABLES); - if (cid != priv->component_infos[i].cid) - error("SOS cid order (%u:%u) isn't compatible with the SOF marker (%u:%u)\n", - i, cid, i, priv->component_infos[i].cid); - trace("ComponentId:%u tableAC:%d tableDC:%d\n", cid, table&0xf, table>>4); -#endif - priv->component_infos[i].AC_table = &priv->HTAC[table&0xf]; - priv->component_infos[i].DC_table = &priv->HTDC[table>>4]; - } - priv->stream = stream+3; - - /* ITU-T T.81 (9/92) chapter E.1.3 clearly states that RSTm is to be set to 0 at the beginning of each scan */ - priv->last_rst_marker_seen = 0; - - trace("< SOS marker\n"); - - return 0; -} - -static int parse_DHT(struct jdec_private *priv, const unsigned char *stream) -{ - unsigned int count, i; - unsigned char huff_bits[17]; - int length, index; - - length = be16_to_cpu(stream) - 2; - stream += 2; /* Skip length */ - - trace("> DHT marker (length=%d)\n", length); - - while (length>0) { - index = *stream++; - - /* We need to calculate the number of bytes 'vals' will takes */ - huff_bits[0] = 0; - count = 0; - for (i=1; i<17; i++) { - huff_bits[i] = *stream++; - count += huff_bits[i]; - } -#if SANITY_CHECK - if (count > 1024) - error("No more than 1024 bytes is allowed to describe a huffman table\n"); - if ( (index &0xf) >= HUFFMAN_TABLES) - error("No mode than %d Huffman tables is supported\n", HUFFMAN_TABLES); - trace("Huffman table %s n%d\n", (index&0xf0)?"AC":"DC", index&0xf); - trace("Length of the table: %d\n", count); -#endif - - if (index & 0xf0 ) { - if (build_huffman_table(priv, huff_bits, stream, &priv->HTAC[index&0xf])) - return -1; - } else { - if (build_huffman_table(priv, huff_bits, stream, &priv->HTDC[index&0xf])) - return -1; - } - - length -= 1; - length -= 16; - length -= count; - stream += count; - } - trace("< DHT marker\n"); - return 0; -} - -static int parse_DRI(struct jdec_private *priv, const unsigned char *stream) -{ - unsigned int length; - - trace("> DRI marker\n"); - - length = be16_to_cpu(stream); - -#if SANITY_CHECK - if (length != 4) - error("Length of DRI marker need to be 4\n"); -#endif - - priv->restart_interval = be16_to_cpu(stream+2); - -#if DEBUG - trace("Restart interval = %d\n", priv->restart_interval); -#endif - - trace("< DRI marker\n"); - - return 0; -} - - - -static void resync(struct jdec_private *priv) -{ - int i; - - /* Init DC coefficients */ - for (i=0; icomponent_infos[i].previous_DC = 0; - - priv->reservoir = 0; - priv->nbits_in_reservoir = 0; - if (priv->restart_interval > 0) - priv->restarts_to_go = priv->restart_interval; - else - priv->restarts_to_go = -1; -} - -static int find_next_rst_marker(struct jdec_private *priv) -{ - int rst_marker_found = 0; - int marker; - const unsigned char *stream = priv->stream; - - /* Parse marker */ - while (!rst_marker_found) - { - while (*stream++ != 0xff) - { - if (stream >= priv->stream_end) - error("EOF while search for a RST marker.\n"); - } - /* Skip any padding ff byte (this is normal) */ - while (*stream == 0xff) - stream++; - - marker = *stream++; - if ((RST+priv->last_rst_marker_seen) == marker) - rst_marker_found = 1; - else if (marker >= RST && marker <= RST7) - error("Wrong Reset marker found, abording\n"); - else if (marker == EOI) - return 0; - } - - priv->stream = stream; - priv->last_rst_marker_seen++; - priv->last_rst_marker_seen &= 7; - - return 0; -} - -static int parse_JFIF(struct jdec_private *priv, const unsigned char *stream) -{ - int chuck_len; - int marker; - int sof_marker_found = 0; - int dqt_marker_found = 0; - int sos_marker_found = 0; - int dht_marker_found = 0; - const unsigned char *next_chunck; - - /* Parse marker */ - while (!sos_marker_found) - { - if (*stream++ != 0xff) - goto bogus_jpeg_format; - /* Skip any padding ff byte (this is normal) */ - while (*stream == 0xff) - stream++; - - marker = *stream++; - chuck_len = be16_to_cpu(stream); - next_chunck = stream + chuck_len; - switch (marker) - { - case SOF: - if (parse_SOF(priv, stream) < 0) - return -1; - sof_marker_found = 1; - break; - case DQT: - if (parse_DQT(priv, stream) < 0) - return -1; - dqt_marker_found = 1; - break; - case SOS: - if (parse_SOS(priv, stream) < 0) - return -1; - sos_marker_found = 1; - break; - case DHT: - if (parse_DHT(priv, stream) < 0) - return -1; - dht_marker_found = 1; - break; - case DRI: - if (parse_DRI(priv, stream) < 0) - return -1; - break; - default: - trace("> Unknown marker %2.2x\n", marker); - break; - } - - stream = next_chunck; - } - - if ( !sof_marker_found || - (!dqt_marker_found && !(priv->flags & TINYJPEG_FLAGS_PIXART_JPEG))) - goto bogus_jpeg_format; - - if (priv->flags & TINYJPEG_FLAGS_PIXART_JPEG) { - if (!priv->default_huffman_table_initialized) { - build_quantization_table(priv->Q_tables[0], pixart_quantization[0]); - build_quantization_table(priv->Q_tables[1], pixart_quantization[1]); - } - - /* Pixart JPEG data starts with one unknown / unused byte */ - priv->stream++; - } - - if (!dht_marker_found) { - trace("No Huffman table loaded, using the default one\n"); - if (build_default_huffman_tables(priv)) - return -1; - } - -#ifdef SANITY_CHECK - if ( (priv->component_infos[cY].Hfactor < priv->component_infos[cCb].Hfactor) - || (priv->component_infos[cY].Hfactor < priv->component_infos[cCr].Hfactor)) - error("Horizontal sampling factor for Y should be greater than horitontal sampling factor for Cb or Cr\n"); - if ( (priv->component_infos[cY].Vfactor < priv->component_infos[cCb].Vfactor) - || (priv->component_infos[cY].Vfactor < priv->component_infos[cCr].Vfactor)) - error("Vertical sampling factor for Y should be greater than vertical sampling factor for Cb or Cr\n"); - if ( (priv->component_infos[cCb].Hfactor!=1) - || (priv->component_infos[cCr].Hfactor!=1) - || (priv->component_infos[cCb].Vfactor!=1) - || (priv->component_infos[cCr].Vfactor!=1)) - error("Sampling other than 1x1 for Cr and Cb is not supported\n"); -#endif - - return 0; -bogus_jpeg_format: - error("Bogus jpeg format\n"); - return -1; -} - -/******************************************************************************* - * - * Functions exported of the library. - * - * Note: Some applications can access directly to internal pointer of the - * structure. It's is not recommended, but if you have many images to - * uncompress with the same parameters, some functions can be called to speedup - * the decoding. - * - ******************************************************************************/ - -/** - * Allocate a new tinyjpeg decoder object. - * - * Before calling any other functions, an object need to be called. - */ -struct jdec_private *tinyjpeg_init(void) -{ - struct jdec_private *priv; - - priv = (struct jdec_private *)calloc(1, sizeof(struct jdec_private)); - if (priv == NULL) - return NULL; - return priv; -} - -/** - * Free a tinyjpeg object. - * - * No others function can be called after this one. - */ -void tinyjpeg_free(struct jdec_private *priv) -{ - int i; - for (i=0; icomponents[i]) - free(priv->components[i]); - priv->components[i] = NULL; - } - free(priv); -} - -/** - * Initialize the tinyjpeg object and prepare the decoding of the stream. - * - * Check if the jpeg can be decoded with this jpeg decoder. - * Fill some table used for preprocessing. - */ -int tinyjpeg_parse_header(struct jdec_private *priv, const unsigned char *buf, unsigned int size) -{ - int ret; - - /* Identify the file */ - if ((buf[0] != 0xFF) || (buf[1] != SOI)) - error("Not a JPG file ?\n"); - - priv->stream_begin = buf+2; - priv->stream_length = size-2; - priv->stream_end = priv->stream_begin + priv->stream_length; - - ret = parse_JFIF(priv, priv->stream_begin); - - return ret; -} - -static const decode_MCU_fct decode_mcu_3comp_table[4] = { - decode_MCU_1x1_3planes, - decode_MCU_1x2_3planes, - decode_MCU_2x1_3planes, - decode_MCU_2x2_3planes, -}; - -static const decode_MCU_fct pixart_decode_mcu_3comp_table[4] = { - NULL, - NULL, - pixart_decode_MCU_2x1_3planes, - NULL, -}; - -static const decode_MCU_fct decode_mcu_1comp_table[4] = { - decode_MCU_1x1_1plane, - decode_MCU_1x2_1plane, - decode_MCU_2x1_1plane, - decode_MCU_2x2_1plane, -}; - -static const convert_colorspace_fct convert_colorspace_yuv420p[4] = { - YCrCB_to_YUV420P_1x1, - YCrCB_to_YUV420P_1x2, - YCrCB_to_YUV420P_2x1, - YCrCB_to_YUV420P_2x2, -}; - -static const convert_colorspace_fct convert_colorspace_rgb24[4] = { - YCrCB_to_RGB24_1x1, - YCrCB_to_RGB24_1x2, - YCrCB_to_RGB24_2x1, - YCrCB_to_RGB24_2x2, -}; - -static const convert_colorspace_fct convert_colorspace_bgr24[4] = { - YCrCB_to_BGR24_1x1, - YCrCB_to_BGR24_1x2, - YCrCB_to_BGR24_2x1, - YCrCB_to_BGR24_2x2, -}; - -static const convert_colorspace_fct convert_colorspace_grey[4] = { - YCrCB_to_Grey_1x1, - YCrCB_to_Grey_1x2, - YCrCB_to_Grey_2x1, - YCrCB_to_Grey_2x2, -}; - -/** - * Decode and convert the jpeg image into @pixfmt@ image - * - * Note: components will be automaticaly allocated if no memory is attached. - */ -int tinyjpeg_decode(struct jdec_private *priv, int pixfmt) -{ - unsigned int x, y, xstride_by_mcu, ystride_by_mcu; - unsigned int bytes_per_blocklines[3], bytes_per_mcu[3]; - decode_MCU_fct decode_MCU; - const decode_MCU_fct *decode_mcu_table; - const convert_colorspace_fct *colorspace_array_conv; - convert_colorspace_fct convert_to_pixfmt; - - if (setjmp(priv->jump_state)) - return -1; - - /* To keep gcc happy initialize some array */ - bytes_per_mcu[1] = 0; - bytes_per_mcu[2] = 0; - bytes_per_blocklines[1] = 0; - bytes_per_blocklines[2] = 0; - - decode_mcu_table = decode_mcu_3comp_table; - if (priv->flags & TINYJPEG_FLAGS_PIXART_JPEG) - decode_mcu_table = pixart_decode_mcu_3comp_table; - - switch (pixfmt) { - case TINYJPEG_FMT_YUV420P: - colorspace_array_conv = convert_colorspace_yuv420p; - if (priv->components[0] == NULL) - priv->components[0] = (uint8_t *)malloc(priv->width * priv->height); - if (priv->components[1] == NULL) - priv->components[1] = (uint8_t *)malloc(priv->width * priv->height/4); - if (priv->components[2] == NULL) - priv->components[2] = (uint8_t *)malloc(priv->width * priv->height/4); - bytes_per_blocklines[0] = priv->width; - bytes_per_blocklines[1] = priv->width/4; - bytes_per_blocklines[2] = priv->width/4; - bytes_per_mcu[0] = 8; - bytes_per_mcu[1] = 4; - bytes_per_mcu[2] = 4; - break; - - case TINYJPEG_FMT_RGB24: - colorspace_array_conv = convert_colorspace_rgb24; - if (priv->components[0] == NULL) - priv->components[0] = (uint8_t *)malloc(priv->width * priv->height * 3); - bytes_per_blocklines[0] = priv->width * 3; - bytes_per_mcu[0] = 3*8; - break; - - case TINYJPEG_FMT_BGR24: - colorspace_array_conv = convert_colorspace_bgr24; - if (priv->components[0] == NULL) - priv->components[0] = (uint8_t *)malloc(priv->width * priv->height * 3); - bytes_per_blocklines[0] = priv->width * 3; - bytes_per_mcu[0] = 3*8; - break; - - case TINYJPEG_FMT_GREY: - decode_mcu_table = decode_mcu_1comp_table; - if (priv->flags & TINYJPEG_FLAGS_PIXART_JPEG) - error("Greyscale output not support for PIXART JPEG's\n"); - colorspace_array_conv = convert_colorspace_grey; - if (priv->components[0] == NULL) - priv->components[0] = (uint8_t *)malloc(priv->width * priv->height); - bytes_per_blocklines[0] = priv->width; - bytes_per_mcu[0] = 8; - break; - - default: - error("Bad pixel format\n"); - } - - xstride_by_mcu = ystride_by_mcu = 8; - if ((priv->component_infos[cY].Hfactor | priv->component_infos[cY].Vfactor) == 1) { - decode_MCU = decode_mcu_table[0]; - convert_to_pixfmt = colorspace_array_conv[0]; - trace("Use decode 1x1 sampling\n"); - } else if (priv->component_infos[cY].Hfactor == 1) { - decode_MCU = decode_mcu_table[1]; - convert_to_pixfmt = colorspace_array_conv[1]; - ystride_by_mcu = 16; - trace("Use decode 1x2 sampling (not supported)\n"); - } else if (priv->component_infos[cY].Vfactor == 2) { - decode_MCU = decode_mcu_table[3]; - convert_to_pixfmt = colorspace_array_conv[3]; - xstride_by_mcu = 16; - ystride_by_mcu = 16; - trace("Use decode 2x2 sampling\n"); - } else { - decode_MCU = decode_mcu_table[2]; - convert_to_pixfmt = colorspace_array_conv[2]; - xstride_by_mcu = 16; - trace("Use decode 2x1 sampling\n"); - } - - if (decode_MCU == NULL) - error("no decode MCU function for this JPEG format (PIXART?)\n"); - - resync(priv); - - /* Don't forget to that block can be either 8 or 16 lines */ - bytes_per_blocklines[0] *= ystride_by_mcu; - bytes_per_blocklines[1] *= ystride_by_mcu; - bytes_per_blocklines[2] *= ystride_by_mcu; - - bytes_per_mcu[0] *= xstride_by_mcu/8; - bytes_per_mcu[1] *= xstride_by_mcu/8; - bytes_per_mcu[2] *= xstride_by_mcu/8; - - /* Just the decode the image by macroblock (size is 8x8, 8x16, or 16x16) */ - for (y=0; y < priv->height/ystride_by_mcu; y++) - { - //trace("Decoding row %d\n", y); - priv->plane[0] = priv->components[0] + (y * bytes_per_blocklines[0]); - priv->plane[1] = priv->components[1] + (y * bytes_per_blocklines[1]); - priv->plane[2] = priv->components[2] + (y * bytes_per_blocklines[2]); - for (x=0; x < priv->width; x+=xstride_by_mcu) - { - decode_MCU(priv); - convert_to_pixfmt(priv); - priv->plane[0] += bytes_per_mcu[0]; - priv->plane[1] += bytes_per_mcu[1]; - priv->plane[2] += bytes_per_mcu[2]; - if (priv->restarts_to_go>0) - { - priv->restarts_to_go--; - if (priv->restarts_to_go == 0) - { - priv->stream -= (priv->nbits_in_reservoir/8); - resync(priv); - if (find_next_rst_marker(priv) < 0) - return -1; - } - } - } - } - - if (priv->flags & TINYJPEG_FLAGS_PIXART_JPEG) { - /* Additional sanity check for funky Pixart format */ - if ((priv->stream_end - priv->stream) > 5) - error("Pixart JPEG error, stream does not end with EOF marker\n"); - } - - return 0; -} - -const char *tinyjpeg_get_errorstring(struct jdec_private *priv) -{ - return priv->error_string; -} - -void tinyjpeg_get_size(struct jdec_private *priv, unsigned int *width, unsigned int *height) -{ - *width = priv->width; - *height = priv->height; -} - -int tinyjpeg_get_components(struct jdec_private *priv, unsigned char **components) -{ - int i; - for (i=0; priv->components[i] && icomponents[i]; - return 0; -} - -int tinyjpeg_set_components(struct jdec_private *priv, unsigned char **components, unsigned int ncomponents) -{ - unsigned int i; - if (ncomponents > COMPONENTS) - ncomponents = COMPONENTS; - for (i=0; icomponents[i] = components[i]; - return 0; -} - -int tinyjpeg_set_flags(struct jdec_private *priv, int flags) -{ - int oldflags = priv->flags; - priv->flags = flags; - return oldflags; -} - diff --git a/v4l2-apps/lib/libv4l/libv4lconvert/tinyjpeg.h b/v4l2-apps/lib/libv4l/libv4lconvert/tinyjpeg.h deleted file mode 100644 index b0096f0de..000000000 --- a/v4l2-apps/lib/libv4l/libv4lconvert/tinyjpeg.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Small jpeg decoder library (header file) - * - * Copyright (c) 2006, Luc Saillard - * All rights reserved. - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * - Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * - Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * - Neither the name of the author nor the names of its contributors may be - * used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - * - */ - - -#ifndef __JPEGDEC_H__ -#define __JPEGDEC_H__ - -#ifdef __cplusplus -extern "C" { -#endif - -struct jdec_private; - -/* Flags that can be set by any applications */ -#define TINYJPEG_FLAGS_MJPEG_TABLE (1<<1) -#define TINYJPEG_FLAGS_PIXART_JPEG (1<<2) - -/* Format accepted in outout */ -enum tinyjpeg_fmt { - TINYJPEG_FMT_GREY = 1, - TINYJPEG_FMT_BGR24, - TINYJPEG_FMT_RGB24, - TINYJPEG_FMT_YUV420P, -}; - -struct jdec_private *tinyjpeg_init(void); -void tinyjpeg_free(struct jdec_private *priv); - -int tinyjpeg_parse_header(struct jdec_private *priv, const unsigned char *buf, unsigned int size); -int tinyjpeg_decode(struct jdec_private *priv, int pixel_format); -const char *tinyjpeg_get_errorstring(struct jdec_private *priv); -void tinyjpeg_get_size(struct jdec_private *priv, unsigned int *width, unsigned int *height); -int tinyjpeg_get_components(struct jdec_private *priv, unsigned char **components); -int tinyjpeg_set_components(struct jdec_private *priv, unsigned char **components, unsigned int ncomponents); -int tinyjpeg_set_flags(struct jdec_private *priv, int flags); - -#ifdef __cplusplus -} -#endif - -#endif - - - diff --git a/v4l2-apps/lib/libv4l2util.h b/v4l2-apps/lib/libv4l2util.h deleted file mode 100644 index fde7cdc75..000000000 --- a/v4l2-apps/lib/libv4l2util.h +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright (C) 2006 Hans Verkuil - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library 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 - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with the GNU C Library; if not, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#ifndef _V4L2UTIL_H_ -#define _V4L2UTIL_H_ - -/* --------------------------------------------------------------------- */ - -struct v4l2_channel_list { - const char * const name; /* channel name */ - unsigned freq; /* channel frequency in kHz */ -}; - -struct v4l2_channel_lists { - const char * const name; /* channel list name */ - const struct v4l2_channel_list * const list; - unsigned count; /* number of channels in channel list */ -}; - -extern const struct v4l2_channel_lists v4l2_channel_lists[]; - -/* This list is sorted alphabetically on ISO code. The last item is - denoted by a NULL pointer for the iso_code. */ -struct v4l2_country_std_map { - const char * const iso_code; /* The 2-character upper case ISO-3166 country code */ - v4l2_std_id std; /* The TV standard(s) in use */ -}; - -extern const struct v4l2_country_std_map v4l2_country_std_map[]; - -#endif diff --git a/v4l2-apps/lib/v4l2_driver.c b/v4l2-apps/lib/v4l2_driver.c deleted file mode 100644 index 94f826968..000000000 --- a/v4l2-apps/lib/v4l2_driver.c +++ /dev/null @@ -1,804 +0,0 @@ -/* - Copyright (C) 2006 Mauro Carvalho Chehab - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library 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 - Lesser General Public License for more details. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "v4l2_driver.h" - -/**************************************************************************** - Auxiliary routines - ****************************************************************************/ -static int xioctl (int fd, int request, void *arg) -{ - int r; - - do r = ioctl (fd, request, arg); - while (-1 == r && EINTR == errno); - - return r; -} - -static void free_list(struct drv_list **list_ptr) -{ - struct drv_list *prev,*cur; - - if (list_ptr==NULL) - return; - - prev=*list_ptr; - if (prev==NULL) - return; - - do { - cur=prev->next; - if (prev->curr) - free (prev->curr); // Free data - free (prev); // Free list - prev=cur; - } while (prev); - - *list_ptr=NULL; -} - -/**************************************************************************** - Auxiliary Arrays to aid debug messages - ****************************************************************************/ -char *v4l2_field_names[] = { - [V4L2_FIELD_ANY] = "any", - [V4L2_FIELD_NONE] = "none", - [V4L2_FIELD_TOP] = "top", - [V4L2_FIELD_BOTTOM] = "bottom", - [V4L2_FIELD_INTERLACED] = "interlaced", - [V4L2_FIELD_SEQ_TB] = "seq-tb", - [V4L2_FIELD_SEQ_BT] = "seq-bt", - [V4L2_FIELD_ALTERNATE] = "alternate", -}; - -char *v4l2_type_names[] = { - [V4L2_BUF_TYPE_VIDEO_CAPTURE] = "video-cap", - [V4L2_BUF_TYPE_VIDEO_OVERLAY] = "video-over", - [V4L2_BUF_TYPE_VIDEO_OUTPUT] = "video-out", - [V4L2_BUF_TYPE_VBI_CAPTURE] = "vbi-cap", - [V4L2_BUF_TYPE_VBI_OUTPUT] = "vbi-out", - [V4L2_BUF_TYPE_SLICED_VBI_CAPTURE] = "sliced-vbi-cap", - [V4L2_BUF_TYPE_SLICED_VBI_OUTPUT] = "slicec-vbi-out", -}; - -static char *v4l2_memory_names[] = { - [V4L2_MEMORY_MMAP] = "mmap", - [V4L2_MEMORY_USERPTR] = "userptr", - [V4L2_MEMORY_OVERLAY] = "overlay", -}; - -#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(*arr)) -#define prt_names(a,arr) (((a)timecode; - - printf ("%s: %02ld:%02d:%02d.%08ld index=%d, type=%s, " - "bytesused=%d, flags=0x%08x, " - "field=%s, sequence=%d, memory=%s, offset=0x%08x, length=%d\n", - name, (p->timestamp.tv_sec/3600), - (int)(p->timestamp.tv_sec/60)%60, - (int)(p->timestamp.tv_sec%60), - p->timestamp.tv_usec, - p->index, - prt_names(p->type,v4l2_type_names), - p->bytesused,p->flags, - prt_names(p->field,v4l2_field_names), - p->sequence, - prt_names(p->memory,v4l2_memory_names), - p->m.offset, - p->length); - tc=&p->timecode; - printf ("\tTIMECODE: %02d:%02d:%02d type=%d, " - "flags=0x%08x, frames=%d, userbits=0x%08x\n", - tc->hours,tc->minutes,tc->seconds, - tc->type, tc->flags, tc->frames, *(uint32_t *) tc->userbits); -} - -/**************************************************************************** - Open V4L2 devices - ****************************************************************************/ -int v4l2_open (char *device, int debug, struct v4l2_driver *drv) -{ - int ret; - - memset(drv,0,sizeof(*drv)); - - drv->debug=debug; - - if ((drv->fd = open(device, O_RDWR )) < 0) { - return(-errno); - } - - ret=xioctl(drv->fd,VIDIOC_QUERYCAP,(void *) &drv->cap); - if (!ret && drv->debug) { - printf ("driver=%s, card=%s, bus=%s, version=%d.%d.%d, " - "capabilities=%s\n", - drv->cap.driver,drv->cap.card,drv->cap.bus_info, - (drv->cap.version >> 16) & 0xff, - (drv->cap.version >> 8) & 0xff, - drv->cap.version & 0xff, - prt_caps(drv->cap.capabilities)); - - - } - return ret; -} - - -/**************************************************************************** - V4L2 Eumberations - ****************************************************************************/ -int v4l2_enum_stds (struct v4l2_driver *drv) -{ - struct v4l2_standard *p=NULL; - struct drv_list *list; - int ok=0,ret,i; - v4l2_std_id id; - - free_list(&drv->stds); - - list=drv->stds=calloc(1,sizeof(*drv->stds)); - assert (list!=NULL); - - for (i=0; ok==0; i++) { - p=calloc(1,sizeof(*p)); - assert (p); - - p->index=i; - ok=xioctl(drv->fd,VIDIOC_ENUMSTD,p); - if (ok<0) { - ok=-errno; - free(p); - break; - } - if (drv->debug) { - printf ("STANDARD: index=%d, id=0x%08x, name=%s, fps=%.3f, " - "framelines=%d\n", p->index, - (unsigned int)p->id, p->name, - 1.*p->frameperiod.denominator/p->frameperiod.numerator, - p->framelines); - } - if (list->curr) { - list->next=calloc(1,sizeof(*list->next)); - list=list->next; - assert (list!=NULL); - } - list->curr=p; - } - if (i>0 && ok==-EINVAL) - return 0; - - return ok; -} - -int v4l2_enum_input (struct v4l2_driver *drv) -{ - struct v4l2_input *p=NULL; - struct drv_list *list; - int ok=0,ret,i; - v4l2_std_id id; - - free_list(&drv->inputs); - - list=drv->inputs=calloc(1,sizeof(*drv->inputs)); - assert (list!=NULL); - - for (i=0; ok==0; i++) { - p=calloc(1,sizeof(*p)); - assert (p); - p->index=i; - ok=xioctl(drv->fd,VIDIOC_ENUMINPUT,p); - if (ok<0) { - ok=errno; - free(p); - break; - } - if (drv->debug) { - printf ("INPUT: index=%d, name=%s, type=%d, audioset=%d, " - "tuner=%d, std=%08x, status=%d\n", - p->index,p->name,p->type,p->audioset, p->tuner, - (unsigned int)p->std, p->status); - } - if (list->curr) { - list->next=calloc(1,sizeof(*list->next)); - list=list->next; - assert (list!=NULL); - } - list->curr=p; - } - if (i>0 && ok==-EINVAL) - return 0; - return ok; -} - -int v4l2_enum_fmt (struct v4l2_driver *drv, enum v4l2_buf_type type) -{ - struct v4l2_fmtdesc *p=NULL; - struct v4l2_format fmt; - struct drv_list *list; - int ok=0,ret,i; - v4l2_std_id id; - - free_list(&drv->fmt_caps); - - list=drv->fmt_caps=calloc(1,sizeof(*drv->fmt_caps)); - assert (list!=NULL); - - for (i=0; ok==0; i++) { - p=calloc(1,sizeof(*p)); - assert (p!=NULL); - - p->index=i; - p->type =type; - - ok=xioctl(drv->fd,VIDIOC_ENUM_FMT,p); - if (ok<0) { - ok=errno; - free(p); - break; - } - if (drv->debug) { - printf ("FORMAT: index=%d, type=%d, flags=%d, description='%s'\n\t" - "fourcc=%c%c%c%c\n", - p->index, p->type, p->flags,p->description, - p->pixelformat & 0xff, - (p->pixelformat >> 8) & 0xff, - (p->pixelformat >> 16) & 0xff, - (p->pixelformat >> 24) & 0xff - ); - } - if (list->curr) { - list->next=calloc(1,sizeof(*list->next)); - list=list->next; - assert (list!=NULL); - } - list->curr=p; - } - if (i>0 && ok==-EINVAL) - return 0; - return ok; -} - -/**************************************************************************** - Set routines - currently, it also checks results with Get - ****************************************************************************/ -int v4l2_setget_std (struct v4l2_driver *drv, enum v4l2_direction dir, v4l2_std_id *id) -{ - v4l2_std_id s_id=*id; - int ret=0; - char s[256]; - - if (dir & V4L2_SET) { - ret=xioctl(drv->fd,VIDIOC_S_STD,&s_id); - if (ret<0) { - ret=errno; - - sprintf (s,"while trying to set STD to %08x", - (unsigned int) *id); - perror(s); - } - } - - if (dir & V4L2_GET) { - ret=xioctl(drv->fd,VIDIOC_G_STD,&s_id); - if (ret<0) { - ret=errno; - perror ("while trying to get STD id"); - } - } - - if (dir == V4L2_SET_GET) { - if (*id & s_id) { - if (*id != s_id) { - printf ("Warning: Received a std subset (%08x" - " std) while trying to adjust to %08x\n", - (unsigned int) s_id,(unsigned int) *id); - } - } else { - fprintf (stderr,"Error: Received %08x std while trying" - " to adjust to %08x\n", - (unsigned int) s_id,(unsigned int) *id); - } - } - return ret; -} - -int v4l2_setget_input (struct v4l2_driver *drv, enum v4l2_direction dir, struct v4l2_input *input) -{ - int ok=0,ret,i; - unsigned int inp=input->index; - char s[256]; - - if (dir & V4L2_SET) { - ret=xioctl(drv->fd,VIDIOC_S_INPUT,input); - if (ret<0) { - ret=errno; - sprintf (s,"while trying to set INPUT to %d\n", inp); - perror(s); - } - } - - if (dir & V4L2_GET) { - ret=xioctl(drv->fd,VIDIOC_G_INPUT,input); - if (ret<0) { - perror ("while trying to get INPUT id\n"); - } - } - - if (dir & V4L2_SET_GET) { - if (input->index != inp) { - printf ("Input is different than expected (received %i, set %i)\n", - inp, input->index); - } - } - - return ok; -} - -int v4l2_gettryset_fmt_cap (struct v4l2_driver *drv, enum v4l2_direction dir, - struct v4l2_format *fmt,uint32_t width, uint32_t height, - uint32_t pixelformat, enum v4l2_field field) -{ - struct v4l2_pix_format *pix=&(fmt->fmt.pix); - int ret=0; - - fmt->type=V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (dir == V4L2_GET) { - ret=xioctl(drv->fd,VIDIOC_G_FMT,fmt); - if (ret < 0) { - ret=errno; - perror("VIDIOC_G_FMT failed\n"); - } - return ret; - } else if (dir & (~(V4L2_TRY|V4L2_SET)) ) { - perror ("Invalid direction\n"); - return EINVAL; - } - - if (dir & (V4L2_TRY|V4L2_SET)) { - pix->width = width; - pix->height = height; - pix->pixelformat = pixelformat; - pix->field = field; - /* - enum v4l2_colorspace colorspace; - */ - - if (dir & V4L2_TRY) { - ret=xioctl(drv->fd,VIDIOC_TRY_FMT,fmt); - if (ret < 0) { - perror("VIDIOC_TRY_FMT failed\n"); - } - } - - if (dir & V4L2_SET) { - ret=xioctl(drv->fd,VIDIOC_S_FMT,fmt); - if (ret < 0) { - perror("VIDIOC_S_FMT failed\n"); - } - drv->sizeimage=pix->sizeimage; - } - - if (pix->pixelformat != pixelformat) { - fprintf(stderr,"Error: asked for format %d, received %d",pixelformat, - pix->pixelformat); - } - - if (pix->width != width) { - fprintf(stderr,"Error: asked for format %d, received %d\n",width, - pix->width); - } - - if (pix->height != height) { - fprintf(stderr,"Error: asked for format %d, received %d\n",height, - pix->height); - } - - if (pix->bytesperline == 0 ) { - fprintf(stderr,"Error: bytesperline = 0\n"); - } - - if (pix->sizeimage == 0 ) { - fprintf(stderr,"Error: sizeimage = 0\n"); - } - } - - if (drv->debug) - printf( "FMT SET: %dx%d, fourcc=%c%c%c%c, %d bytes/line," - " %d bytes/frame, colorspace=0x%08x\n", - pix->width,pix->height, - pix->pixelformat & 0xff, - (pix->pixelformat >> 8) & 0xff, - (pix->pixelformat >> 16) & 0xff, - (pix->pixelformat >> 24) & 0xff, - pix->bytesperline, - pix->sizeimage, - pix->colorspace); - - return 0; -} - -/**************************************************************************** - Get routines - ****************************************************************************/ -int v4l2_get_parm (struct v4l2_driver *drv) -{ - int ret; - struct v4l2_captureparm *c; - - drv->parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if ((ret=xioctl(drv->fd,VIDIOC_G_PARM,&drv->parm))>=0) { - c=&drv->parm.parm.capture; - printf ("PARM: capability=%d, capturemode=%d, %.3f fps " - "ext=%x, readbuf=%d\n", - c->capability, - c->capturemode, - c->timeperframe.denominator*1./c->timeperframe.numerator, - c->extendedmode, c->readbuffers); - } else { - ret=errno; - - perror ("VIDIOC_G_PARM"); - } - - return ret; -} - -/**************************************************************************** - Queue and stream control - ****************************************************************************/ - -int v4l2_free_bufs(struct v4l2_driver *drv) -{ - unsigned int i; - - if (!drv->n_bufs) - return 0; - - /* Requests the driver to free all buffers */ - drv->reqbuf.count = 0; - drv->reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - drv->reqbuf.memory = V4L2_MEMORY_MMAP; - - /* stop capture */ - if (xioctl(drv->fd,VIDIOC_STREAMOFF,&drv->reqbuf.type)<0) - return errno; - - sleep (1); // FIXME: Should check if all buffers are stopped - -/* V4L2 API says REQBUFS with count=0 should be used to release buffer. - However, video-buf.c doesn't implement it. - */ -#if 0 - if (xioctl(drv->fd,VIDIOC_REQBUFS,&drv->reqbuf)<0) { - perror("reqbufs while freeing buffers"); - return errno; - } -#endif - - if (drv->reqbuf.count != 0) { - fprintf(stderr,"REQBUFS returned %d buffers while asking for freeing it!\n", - drv->reqbuf.count); - } - - for (i = 0; i < drv->n_bufs; i++) { - if (drv->bufs[i].length) - munmap(drv->bufs[i].start, drv->bufs[i].length); - if (drv->v4l2_bufs[i]) - free (drv->v4l2_bufs[i]); - } - - free(drv->v4l2_bufs); - free(drv->bufs); - - drv->v4l2_bufs=NULL; - drv->bufs=NULL; - drv->n_bufs=0; - - return 0; -} - -int v4l2_mmap_bufs(struct v4l2_driver *drv, unsigned int num_buffers) -{ - /* Frees previous allocations, if required */ - v4l2_free_bufs(drv); - - if (drv->sizeimage==0) { - fprintf(stderr,"Image size is zero! Can't proceed\n"); - return -1; - } - /* Requests the specified number of buffers */ - drv->reqbuf.count = num_buffers; - drv->reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - drv->reqbuf.memory = V4L2_MEMORY_MMAP; - - if (xioctl(drv->fd,VIDIOC_REQBUFS,&drv->reqbuf)<0) { - perror("reqbufs"); - return errno; - } - - if (drv->debug) - printf ("REQBUFS: count=%d, type=%s, memory=%s\n", - drv->reqbuf.count, - prt_names(drv->reqbuf.type,v4l2_type_names), - prt_names(drv->reqbuf.memory,v4l2_memory_names)); - - /* Allocates the required number of buffers */ - drv->v4l2_bufs=calloc(drv->reqbuf.count, sizeof(*drv->v4l2_bufs)); - assert(drv->v4l2_bufs!=NULL); - drv->bufs=calloc(drv->reqbuf.count, sizeof(*drv->bufs)); - assert(drv->bufs!=NULL); - - for (drv->n_bufs = 0; drv->n_bufs < drv->reqbuf.count; drv->n_bufs++) { - struct v4l2_buffer *p; - struct v4l2_timecode *tc; - - /* Requests kernel buffers to be mmapped */ - p=drv->v4l2_bufs[drv->n_bufs]=calloc(1,sizeof(*p)); - assert (p!=NULL); - p->index = drv->n_bufs; - p->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - p->memory = V4L2_MEMORY_MMAP; - if (xioctl(drv->fd,VIDIOC_QUERYBUF,p)<0) { - int ret=errno; - perror("querybuf"); - - free (drv->v4l2_bufs[drv->n_bufs]); - - v4l2_free_bufs(drv); - return ret; - } - - if (drv->debug) - prt_buf_info("QUERYBUF",p); - - if (drv->sizeimage != p->length) { - if (drv->sizeimage < p->length) { - fprintf (stderr, "QUERYBUF: ERROR: VIDIOC_S_FMT said buffer should have %d size, but received %d from QUERYBUF!\n", - drv->sizeimage, p->length); - } else { - fprintf (stderr, "QUERYBUF: Expecting %d size, received %d buff length\n", - drv->sizeimage, p->length); - } - } - - drv->bufs[drv->n_bufs].length = p->length; - drv->bufs[drv->n_bufs].start = mmap (NULL, /* start anywhere */ - p->length, - PROT_READ | PROT_WRITE, /* required */ - MAP_SHARED, /* recommended */ - drv->fd, p->m.offset); - - - if (MAP_FAILED == drv->bufs[drv->n_bufs].start) { - perror("mmap"); - - free (drv->v4l2_bufs[drv->n_bufs]); - v4l2_free_bufs(drv); - return errno; - } - } - - return 0; -} - -int v4l2_rcvbuf(struct v4l2_driver *drv, v4l2_recebe_buffer *rec_buf) -{ - int ret; - - struct v4l2_buffer buf; - memset (&buf, 0, sizeof(buf)); - - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; - - if (-1 == xioctl (drv->fd, VIDIOC_DQBUF, &buf)) { - switch (errno) { - case EAGAIN: - return 0; - - case EIO: - /* Could ignore EIO, see spec. */ - - /* fall through */ - - default: - perror ("dqbuf"); - return errno; - } - } - prt_buf_info("DQBUF",&buf); - - assert (buf.index < drv->n_bufs); - - ret = rec_buf (&buf,&drv->bufs[buf.index]); - - if (ret) { - v4l2_free_bufs(drv); - return ret; - } - - if (-1 == xioctl (drv->fd, VIDIOC_QBUF, &buf)) { - perror ("qbuf"); - return errno; - } - return 0; -} - - -int v4l2_start_streaming(struct v4l2_driver *drv) -{ - uint32_t i; - struct v4l2_buffer buf; - - if (drv->debug) - printf("Activating %d queues\n", drv->n_bufs); - for (i = 0; i < drv->n_bufs; i++) { - int res; - - memset(&buf, 0, sizeof(buf)); - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; - buf.index = i; - - res = xioctl (drv->fd, VIDIOC_QBUF, &buf); - - if (!res) - prt_buf_info("QBUF",&buf); - else { - perror("qbuf"); - return errno; - } - } - - /* Activates stream */ - if (drv->debug) - printf("Enabling streaming\n"); - - if (xioctl(drv->fd,VIDIOC_STREAMON,&drv->reqbuf.type)<0) - return errno; - - return 0; -} - -int v4l2_stop_streaming(struct v4l2_driver *drv) -{ - v4l2_free_bufs(drv); - - return 0; -} - -/**************************************************************************** - Close V4L2, disallocating all structs - ****************************************************************************/ -int v4l2_close (struct v4l2_driver *drv) -{ - v4l2_free_bufs(drv); - - free_list(&drv->stds); - free_list(&drv->inputs); - free_list(&drv->fmt_caps); - - return (close(drv->fd)); -} - -/**************************************************************************** - Get/Set frequency - ****************************************************************************/ - -int v4l2_getset_freq (struct v4l2_driver *drv, enum v4l2_direction dir, - double *freq) -{ - struct v4l2_tuner tun; - struct v4l2_frequency frq; - double d = 62500; - unsigned int counter; - - memset(&tun, 0, sizeof(tun)); - - if (-1 == xioctl (drv->fd, VIDIOC_G_TUNER, &tun)) { - perror ("g_tuner"); - printf("Assuming 62.5 kHz step\n"); - } else { - if (tun.capability & V4L2_TUNER_CAP_LOW) - d=62.5; - } - - if (drv->debug) { - if (tun.capability & V4L2_TUNER_CAP_LOW) - printf("62.5 Hz step\n"); - else - printf("62.5 kHz step\n"); - } - - memset(&frq, 0, sizeof(frq)); - - frq.type = V4L2_TUNER_ANALOG_TV; - - if (dir & V4L2_GET) { - if (-1 == xioctl (drv->fd, VIDIOC_G_FREQUENCY, &frq)) { - perror ("s_frequency"); - return errno; - } - *freq = frq.frequency * d; - if (drv->debug) - printf("board is at freq %4.3f MHz (%d)\n", - *freq/1000000, frq.frequency); - } else { - frq.frequency = (uint32_t)(((*freq)+d/2) / d); - - if (-1 == xioctl (drv->fd, VIDIOC_S_FREQUENCY, &frq)) { - perror ("s_frequency"); - return errno; - } - if (drv->debug) - printf("board set to freq %4.3f MHz (%d)\n", - *freq/1000000, frq.frequency); - - } - return 0; -} diff --git a/v4l2-apps/lib/v4l2_driver.h b/v4l2-apps/lib/v4l2_driver.h deleted file mode 100644 index b5d5dd22d..000000000 --- a/v4l2-apps/lib/v4l2_driver.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - Copyright (C) 2006 Mauro Carvalho Chehab - - The GNU C Library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - The GNU C Library 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 - Lesser General Public License for more details. - */ - -#include -#include -#include -#include - -struct drv_list { - void *curr; - struct drv_list *next; -}; - -struct v4l2_t_buf { - void *start; - size_t length; -}; - -typedef int v4l2_recebe_buffer (struct v4l2_buffer *v4l2_buf, struct v4l2_t_buf *buf); - -struct v4l2_driver { - int fd; /* Driver descriptor */ - - int debug; - - /* V4L2 structs */ - struct v4l2_capability cap; - struct v4l2_streamparm parm; - - /* Several lists to be used to store enumbered values */ - struct drv_list *stds,*inputs,*fmt_caps; - - /* Stream control */ - struct v4l2_requestbuffers reqbuf; - struct v4l2_buffer **v4l2_bufs; - struct v4l2_t_buf *bufs; - uint32_t sizeimage,n_bufs; - - /* Queue control */ - uint32_t waitq, currq; -}; - -enum v4l2_direction { - V4L2_GET = 1, // Bit 1 - V4L2_SET = 2, // Bit 2 - V4L2_SET_GET = 3, // Bits 1 and 2 - sets then gets and compare - V4L2_TRY = 4, // Bit 3 - V4L2_TRY_SET = 6, // Bits 3 and 2 - try then sets - V4L2_TRY_SET_GET = 7, // Bits 3, 2 and 1- try, sets and gets -}; - -int v4l2_open (char *device, int debug, struct v4l2_driver *drv); -int v4l2_close (struct v4l2_driver *drv); -int v4l2_enum_stds (struct v4l2_driver *drv); -int v4l2_enum_input (struct v4l2_driver *drv); -int v4l2_enum_fmt (struct v4l2_driver *drv,enum v4l2_buf_type type); -int v4l2_get_parm (struct v4l2_driver *drv); -int v4l2_setget_std (struct v4l2_driver *drv, enum v4l2_direction dir, v4l2_std_id *id); -int v4l2_setget_input (struct v4l2_driver *drv, enum v4l2_direction dir, struct v4l2_input *input); -int v4l2_gettryset_fmt_cap (struct v4l2_driver *drv, enum v4l2_direction dir, - struct v4l2_format *fmt,uint32_t width, uint32_t height, - uint32_t pixelformat, enum v4l2_field field); -int v4l2_mmap_bufs(struct v4l2_driver *drv, unsigned int num_buffers); -int v4l2_free_bufs(struct v4l2_driver *drv); -int v4l2_start_streaming(struct v4l2_driver *drv); -int v4l2_stop_streaming(struct v4l2_driver *drv); -int v4l2_rcvbuf(struct v4l2_driver *drv, v4l2_recebe_buffer *v4l2_rec_buf); -int v4l2_getset_freq (struct v4l2_driver *drv, enum v4l2_direction dir, - double *freq); - diff --git a/v4l2-apps/libv4l/COPYING.LIB b/v4l2-apps/libv4l/COPYING.LIB new file mode 100644 index 000000000..1dd325d2b --- /dev/null +++ b/v4l2-apps/libv4l/COPYING.LIB @@ -0,0 +1,510 @@ + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations +below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. +^L + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it +becomes a de-facto standard. To achieve this, non-free programs must +be allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. +^L + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control +compilation and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. +^L + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. +^L + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at least + three years, to give the same user the materials specified in + Subsection 6a, above, for a charge no more than the cost of + performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. +^L + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. +^L + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply, and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License +may add an explicit geographical distribution limitation excluding those +countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. +^L + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS +^L + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms +of the ordinary General Public License). + + To apply these terms, attach the following notices to the library. +It is safest to attach them to the start of each source file to most +effectively convey the exclusion of warranty; and each file should +have at least the "copyright" line and a pointer to where the full +notice is found. + + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or +your school, if any, to sign a "copyright disclaimer" for the library, +if necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James + Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/v4l2-apps/libv4l/ChangeLog b/v4l2-apps/libv4l/ChangeLog new file mode 100644 index 000000000..dd53eced9 --- /dev/null +++ b/v4l2-apps/libv4l/ChangeLog @@ -0,0 +1,247 @@ +libv4l-0.5.0 +------------ +* Add support for enumerating framesizes and frameintervals of emulated + formats when the driver supports it for the real format +* Make sure the video device always gets opened RW even if the application + asks for RO +* Add Genius E-Messenger 112 (093a:2476) to list of cams which have their + sensor upside down + +libv4l-0.4.3 +------------ +* Add suport for YUYV and YVYU packed pixel formats (Jean-Francois Moine) +* Prefer compressed pixformats for resolutions > 176x144 + +libv4l-0.4.2 +------------ +* The bayer pixel order in gspca's sonixb driver was different from that in + the sn9c102 driver from the mainline kernel, a recent gspca patch fixes + this, adjust libv4l to match (and make it work properly with the sn9c102 + driver). + +libv4l-0.4.1 +------------ +* When the driver supports read() and we are not converting let the driver + handle read() instead of emulating it with mmap mode +* Fix errors and warnings when compiling with ICC (Gregor Jasny) +* Add support to libv4lconvert for rotating images 90 (for Pixart 7302 cams) + or 180 (Philips SPC200NC / Philips SPC300NC) degrees +* Add support for Pixart custom JPEG format +* Hide non public symbols (Gregor Jasny) +* Fix and enable x86_64 asm jpeg decompress helper functions (Gregor Jasny) + +libv4l-0.4.0 +------------ +* Be more relaxed in our checks for mixing read and mmap access, we were + being more strict in this then certain kernel drivers (bttv) making xawtv + unhappy +* With some drivers the buffers must be mapped before queuing, so when + converting map the (real) buffers before calling the qbuf ioctl +* Add support for conversion to RGB24 (before we only supported BGR24) based + on a patch by Jean-Francois Moine +* When the hardware supports a format natively prefer using the native + version over converting from another supported format +* Various Makefile and pkgconfig file improvements by Gregor Jasny (Debian) +* Drop the appl-patches dir, all application patches are now available and + tracked here: http://linuxtv.org/v4lwiki/index.php/Libv4l_Progress + + +libv4l-0.3.9 +------------ +* Not only see /dev/video* but also /dev/v4l/* as video devices + (only affects libv4l1 and the wrappers) patch from Brandon Philips +* Silence the creation of the .pc files in the Makefiles (Brandon Philips) +* Part of the copyright headers refered GPL instead of LGPL due to a copy + and paste error (Brandon Philips) + + +libv4l-0.3.8 +------------ +* work around wrong REQUEST_BUFFERS ioctl return code from certain drivers +* add pkg-config (.pc) files for easier detection if libv4l is available +* check capabilities for streaming, if the driver cannot do streaming don't + insert ourselves between the application and the driver +* intercept get capabilites and report read capability (which we always offer) +* query buffer: indicate the mapping state of our (fake) buffer in the flags + + +libv4l-0.3.7 +------------ +* Add spca505/6 and spca508 cam specific formats (YUYV per line variations) + + +libv4l-0.3.6 +------------ +* Add missing COPYING.LIB file + + +libv4l-0.3.5 +------------ +* Make JPEG decoding more robust + + +libv4l-0.3.4 (the brownpaperbag release) +---------------------------------------- +* The mmap64 support in 0.3.3, has caused a bug in libv4l1 when running on + 32 bit systems (who uses those now a days?), this bug caused v4l1 + compatibility to not work at all, this release fixes this +* Some apps (xawtv, kopete) use an ioctl wrapper internally for various + reasons. This wrappers request argument is an int, but the real ioctl's + request argument is an unsigned long. Passing the VIDIOC_xxx defines through + to the wrapper, and then to the real ioctl, causes the request to get sign + extended on 64 bit args. The kernel seems to ignore the upper 32 bits, + causing the sign extension to not make a difference. libv4l now also + ignores the upper 32 bits of the libv4lx_ioctl request argument on 64 bit + archs +* Add a bugfix patch for kopete in the appl-patches dir, currently it assumes + that it got the width and height it asked for when doing a S_FMT, which is a + wrong assumption + + +libv4l-0.3.3 +------------ +* Add open64 and mmap64 wrappers to the LD_PRELOAD wrapper libs, so that + they also work for applications compiled with FILE_OFFSET_BITS=64, this + fixes using them with v4l-info +* While looking at xawtv in general, found a few bugs in xawtv itself, added + a patch to fix those to the appl-patches dir +* Talking about the appl-patches dir, restore that as it accidentally got + dropped from 0.3.2 +* Be more verbose in various places when it comes to logging (esp errors) +* Change v4lconvert_enum_fmt code a bit, so that it is easier to add more + supported destination formats to libv4lconvert +* Don't return -EINVAL from try_fmt when we cannot convert because the cam + doesn't have any formats we know. Instead just return as format whatever the + cam returns from try_fmt, this new behavior is compliant with the v4l2 + api as documented + +libv4l-0.3.2 +------------ +* Add support for converting from sn9c10x compressed data +* Add support for converting from pac207 compressed data +* Add "make install" Makefile target + +libv4l-0.3.1 +------------ +* Only serialize V4L2_BUF_TYPE_VIDEO_CAPTURE type ioctls +* Do not return an uninitialized variable as result code for GPICT + (fixes vlc, but see below) +* Add an apps-patches directory which includes: + * vlc-0.8.6-libv4l1.patch, modify vlc's v4l1 plugin to directly call into + libv4l1, in the end we want all apps todo this as its better then + LD_PRELOAD tricks, but for vlc this is needed as vlc's plugin system + causes LD_PRELOAD to not work on symbols in the plugins + * camorama-0.19-fixes.patch, small bugfixes to camorama's v4l1 support, + this patch only fixes _real_ bugs in camorama and does not change it to + work with v4l1compat. Although it does work better with these bugs fixed + :) With this patch and LD_PRELOAD=/v4l1compat.so it works + flawless. + + +libv4l-0.3 +---------- +* add extern "C" magic to public header files for c++ usage (Gregor Jasny) +* Make libv4l1 and libv4l2 multithread use safe, see README.multi-threading +* Add v4lx_dup() calls (and intercept dup() from the wrappers) this fixes + use with gstreamer's v4l2 plugin (tested with cheese) +* Hopefully definitely fix compile errors on systems with a broken videodev2.h + +libv4l-0.2 +---------- +*** API change *** +* Change v4lconvert api so that the v4lconvert struct always gets allocated + by the library, this to make it opaque, so that we can avoid future API + and ABI changes +* Add support for yuv420 -> bgr24 conversion +* When converting from v4l2 pixelformat to v4l12 palette return + VIDEO_PALETTE_YUV420P instead of VIDEO_PALETTE_YUV420 for + V4L2_PIX_FMT_YUV420 as that is what most apps seem to expect +* override kernel v4l1 compat min / max size with our own more accurate values +* fix v4l1 munmap bug where it didn't recognise the buffer being unmapped was + our fake buffer (fixes gstreamer v4l1 support, checked with cheese) +* add support for reporting the emulated pixelformats with ENUM_FMT, this + defaults to off, and can be activated by passing a flag to enable it to + v4l2_fd_open. This gets enabled by default the wrappers. +* v4l2: mmap the real device buffers before doing conversion when DQBUF gets + called before the application has called mmap (avoid crash). + + +libv4l-0.1 +---------- +* major shuffle / rewrite now split into libv4l1, libv4l2, libv4lconvert + and 2 wrappers for binary compatibility +* rewritten LGPL bayer decoding +* many many other changes and fixes + + +v4l1-compat-0.6 (V4L2 apps stay working) +---------------------------------------- +* Do not go into emulation mode of rgb24 immediately, but only after a + GPICT ioctl which has not been preceded by a SPICT ioctl, AKA do not get + in the way of V4L2 read calls by doing conversion on them +* Do not get in the way of mmap calls made by V4L2 applications +* Fix swapping of red and blue in bayer -> bgr24 decode routine +* Remember the v4l1 palette asked for with SPICT and return that, as + otherwise we loose information when going v4l1 -> v4l2 -> v4l1, for example + YUV420P becomes YUV420, which are separate in v4l1. + + +v4l1-compat-0.5 (perfect camorama) +---------------------------------- +* Allow changing of format after the buffers have been mapped, by tearing + down the entire house, changing the fundament and then rebuilding it. + Now changing the capture resolution in camorama works! +* Fix jpeg decoding error reporting +* Allow jpeg's with a height which is a multiple of 8 (was 16) +* Remove a number of pretty new VIDIOCXXX -> string mappings from log.c, + fixing compiling with somewhat older kernels + + +v4l1-compat 0.4 +--------------- +* Do not even try to change the format in v4l1_compat_set_format(), unless + _really_ necessary. +* Cleanup ambigious use of src_format (no functional changes) +* Drop the mmap hack for zerocopy access under certain conditions, one of them + that the cam can deliver the requested format. Although avoiding the + memcpy in this scenarios is a good thing todo, there were several issues + with the 0.3 implementation of this, fixing all these means adding lots of + special cases all over the code. So instead we just drop support and + always do atleast a memcpy (or a conversion). If an application cannot + live with the speed penalty this imposes it should be ported to v4l2. +* Now that we've gotten rid of the zerocopy mmap hack, we can safely allow + mixing read and mmap based IO. +* Explictly include linux/ioctl.h, to fix compile with kernel headers where + linux/videodev.h doesn't. + + +v4l1-compat 0.3 +--------------- +* Don't allow multiple opens, in theory our code can handle it, but not all + v4l2 devices like it (ekiga does it and uvc doesn't like it). + + +v4l1-compat 0.2 +--------------- +* When mmap gets passed an fd of -1 (anonymous map) don't look for it in our + list of managed fds, as we use -1 to mark unused entries (fixes ekiga + crashing). Also check for an fd of -1 in the other calls we intercept. +* In close() start with removing the fd from our list of managed fds, this must + be done first, because as soon as we've done the actual close syscall, the + fd maybe returned by an open in another thread and we don't want to intercept + calls to this new fd. +* Make unknown v4l1 palette types a normal level log messages instead of an + error. +* When an applicaiton changes the width / height through the CMCAPTURE ioctl + remember the new width and height. +* If the devices initial v4l2 pixformat has no corresponding v4l1 palette, try + setting a format which does (and which we emulate when necessary) so that + applicactions which just query the current format (GPICT) and then take + whatever they get will work (partially fixes camorama) +* Implement our own SWIN instead of using kernel compat layer, for more + flexibility and better error checking + + +v4l1-compat 0.1 +--------------- +* Initial public release. diff --git a/v4l2-apps/libv4l/Makefile b/v4l2-apps/libv4l/Makefile new file mode 100644 index 000000000..4c99c3167 --- /dev/null +++ b/v4l2-apps/libv4l/Makefile @@ -0,0 +1,16 @@ +LIB_RELEASE=0 +V4L2_LIB_VERSION=$(LIB_RELEASE).5.0 + +all clean install: + $(MAKE) -C libv4lconvert V4L2_LIB_VERSION=$(V4L2_LIB_VERSION) $@ + $(MAKE) -C libv4l2 V4L2_LIB_VERSION=$(V4L2_LIB_VERSION) $@ + $(MAKE) -C libv4l1 V4L2_LIB_VERSION=$(V4L2_LIB_VERSION) $@ + +export: clean + mkdir /tmp/libv4l-$(V4L2_LIB_VERSION) + cp -a . /tmp/libv4l-$(V4L2_LIB_VERSION)/ + cd /tmp/ && \ + tar cvf /tmp/libv4l-$(V4L2_LIB_VERSION).tar\ + libv4l-$(V4L2_LIB_VERSION) + gzip /tmp/libv4l-$(V4L2_LIB_VERSION).tar + rm -rf /tmp/libv4l-$(V4L2_LIB_VERSION) diff --git a/v4l2-apps/libv4l/README b/v4l2-apps/libv4l/README new file mode 100644 index 000000000..3a2059224 --- /dev/null +++ b/v4l2-apps/libv4l/README @@ -0,0 +1,141 @@ +Introduction +------------ + +libv4l is a collection of libraries which adds a thin abstraction layer on +top of video4linux2 devices. The purpose of this (thin) layer is to make it +easy for application writers to support a wide variety of devices without +having to write seperate code for different devices in the same class. + +All libv4l components are licensed under the GNU Lesser General Public +License version 2 or (at your option) any later version. + +libv4l consists of 3 different libraries: + + +libv4lconvert +------------- + +libv4lconvert offers functions to convert from any (known) pixelformat +to V4l2_PIX_FMT_BGR24 or V4l2_PIX_FMT_YUV420. + +Currently the following source formats are supported: +jpeg, mjpeg, bayer (all 4 variants: bggr, rggb, gbrg, grbg), +spca501 (chip specific yuv 420 with interlaced components), +spca561 (chip specific compressed gbrg bayer) +For more details on the v4lconvert_ functions see libv4lconvert.h . + + +libv4l1 +------- + +This offers functions like v4l1_open, v4l1_ioctl, etc. which can by used to +quickly make v4l1 applications work with v4l2 devices. These functions work +exactly like the normal open/close/etc, except that libv4l1 does full emulation +of the v4l1 api on top of v4l2 drivers, in case of v4l1 drivers it will just +pass calls through. For more details on the v4l1_ functions see libv4l1.h . + + +libv4l2 +------- + +This offers functions like v4l2_open, v4l2_ioctl, etc. which can by used to +quickly make v4l2 applications work with v4l2 devices with weird formats. +libv4l2 mostly passes calls directly through to the v4l2 driver. When the +app does a TRY_FMT / S_FMT with a not supported format libv4l2 will get in +the middle and emulate the format (if an app wants to know which formats the +hardware can _really_ do it should use ENUM_FMT, not randomly try a bunch of +S_FMT's). For more details on the v4l2_ functions see libv4l2.h . + + +wrappers +-------- + +The functionality provided by libv4l1 for v4l1 apps and libv4l2 for v4l2 apps +can also be used by existing apps without modifying them. For this purpose +2 wrapper libraries are provided which can be preloaded before starting the +application using the LD_PRELOAD environment variable. These wrappers will +then intercept calls to open/close/ioctl/etc. and if these calls directed +towards a video device the wrapper will redirect the call to the libv4lX +counterparts. + +The preloadable libv4l1 wrapper which adds v4l2 device compatibility to v4l1 +applications is called v4l1compat.so. The preloadable libv4l2 wrapper which +adds support for various pixelformats to v4l2 applications is called +v4l2convert.so. + +Example usage (after install in default location): +$ export LD_PRELOAD=/usr/local/lib/libv4l/v4l1compat.so +$ camorama + + +Installation Instructions +------------------------- + +Simple type the following commands from the libv4l-x.y.z directory +(adjusting PREFIX as desired): +make +make install PREFIX=/usr/local + +Note: make install also supports the DESTDIR=... paramter for installation +into chroots. + + +FAQ +--- + +Q: Why libv4l, whats wrong with directly accessing v4l2 devices ? +Q: Do we really need yet another library ? +A: Current webcam using applications like ekiga contain code to handle many +different specific pixelformats webcam's use, but that code only supports a +small subset of all native webcam (compressed) pixelformats. Other current +v4l2 applications do not support anything but rgb pixelformats (xawtv for +example) and this will not work with most webcams at all. + +With gspca being ported to v4l2 and thus decoding to normal formats being +removed from the device driver as this really belongs in userspace, ekiga +would need to be extended with many more often chip dependent formats, like +the bayer compression used by the spca561 and the (different) compression used +by the pac207 and the (again different) compression used by the sn9c102. Adding +support for all these formats should not be done at the application level, as +then it needs to be written for each application seperately. Licensing issues +with the decompressors will then also become a problem as just cut and pasting +from one application to another is bound to hit license incompatibilities. + +So clearly this belongs in a library, and in a library with a license which +allows this code to be used from as many different applications as possible. +Hence libv4l was born. + +Q: Under which license may I use and distribute libv4l? +A: All libv4l components are licensed under the GNU Library General Publishing +License version 2 or (at your option) any later version. See the included +COPYING.LIB file. + +Q: Okay so I get the use of having a libv4lconvert, but why libv4l1 ? +A: Many v4l2 drivers do not offer full v4l1 compatibility. They often do not +implemented the CGMBUF ioctl and v4l1 style mmap call. Adding support to all +these drivers for this is a lot of work and more importantly unnecessary +adds code to kernel space. + +Also even if the CGMBUF ioctl and v4l1 style mmap are supported, then most +cams still deliver pixelformats which v4l1 applications do not understand. + +This libv4l1 was born as an easy way to get v4l1 applications to work with +v4l2 devices without requiring full v4l1 emulation (including format +conversion) in the kernel, and without requiring major changes to the +applications. + + +Q: Why should I use libv4l2 in my app instead of direct device access +combined with libv4lconvert? + +libv4l2 is mainly meant for quickly and easily adding support for more +pixelformats to existing v4l2 applications. So if you feel better directly +accessing the device in combination with libv4lconvert thats fine too. + +Notice that libv4l2 also does emulation of the read() call on devices which +do not support it in the driver. In the background this uses mmap buffers +(even on devices which do support the read call). This mmap gives libv4lconvert +zero-copy access to the captured frame, and then it can write the converted +data directly to the buffer the application provided to v4l2_read(). Thus +another reason to use liv4l2 is to get the no memcpy advantage of the mmap +capture method combined with the simplicity of making a simple read() call. diff --git a/v4l2-apps/libv4l/README.multi-threading b/v4l2-apps/libv4l/README.multi-threading new file mode 100644 index 000000000..93b393c8c --- /dev/null +++ b/v4l2-apps/libv4l/README.multi-threading @@ -0,0 +1,12 @@ +libv4lconvert is not safe for using one convert instance as returned by +v4lconvert_create from multiple threads, if you want to use one v4lconvert +instance from multiple threads you must provide your own locking and make +sure no simultanious calls are made. + +libv4l1 and libv4l2 are safe for multithread use *under* *the* *following* +*conditions* : + +* when using v4lx_fd_open, do not make any v4lx_ calls to the passed fd until + v4lx_fd_open has completed + +* all v4lx_ calls must be completed before calling v4lx_close diff --git a/v4l2-apps/libv4l/TODO b/v4l2-apps/libv4l/TODO new file mode 100644 index 000000000..f3f9ff527 --- /dev/null +++ b/v4l2-apps/libv4l/TODO @@ -0,0 +1,12 @@ +-add support for setting / getting the number of read buffers + +-add code to v4l2_read to not return frames more then say 5 seconds old + +-add support for libv4l1 for non pure capture (combined capture and overlay) + devices so that atleast CGMBUF emulation (but no conversion, as thats + impossible for overlays) can be done, so that it will no longer be + necessary to implement CGMBUF in the kernel for each driver. + +-check v4l2_field during conversion + +-add conversion from bgr24 to yuv420 diff --git a/v4l2-apps/libv4l/include/libv4l1.h b/v4l2-apps/libv4l/include/libv4l1.h new file mode 100644 index 000000000..c878cc198 --- /dev/null +++ b/v4l2-apps/libv4l/include/libv4l1.h @@ -0,0 +1,73 @@ +/* +# (C) 2008 Hans de Goede + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# 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 Lesser General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __LIBV4L1_H +#define __LIBV4L1_H + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include +#include + +#if __GNUC__ >= 4 +#define LIBV4L_PUBLIC __attribute__ ((visibility("default"))) +#else +#define LIBV4L_PUBLIC +#endif + +/* Point this to a FILE opened for writing when you want to log error and + status messages to a file, when NULL errors will get send to stderr */ +LIBV4L_PUBLIC extern FILE *v4l1_log_file; + +/* Just like your regular open/close/etc, except that when opening a v4l2 + capture only device, full v4l1 emulation is done including emulating the + often not implemented in v4l2 drivers CGMBUF ioctl and v4l1 style mmap call + in userspace. + + Format conversion is done if necessary when capturing. That is if you + (try to) set a capture format which is not supported by the cam, but is + supported by libv4lconvert then SPICT will succeed and on SYNC / read the + data will be converted for you and returned in the request format. + + Note that currently libv4l1 depends on the kernel v4l1 compatibility layer + for: 1) Devices which are not capture only, 2) Emulation of many basic + v4l1 ioctl's which require no driver specific handling. + + Note that no functionality is added to v4l1 devices, so if for example an + obscure v4l1 device is opened which only supports some weird capture format + then libv4l1 will not be of any help (in this case it would be best to get + the driver converted to v4l2, as v4l2 has been designed to include weird + capture formats, like hw specific bayer compression methods). +*/ + +LIBV4L_PUBLIC int v4l1_open (const char *file, int oflag, ...); +LIBV4L_PUBLIC int v4l1_close(int fd); +LIBV4L_PUBLIC int v4l1_dup(int fd); +LIBV4L_PUBLIC int v4l1_ioctl (int fd, unsigned long int request, ...); +LIBV4L_PUBLIC ssize_t v4l1_read (int fd, void* buffer, size_t n); +LIBV4L_PUBLIC void *v4l1_mmap(void *start, size_t length, int prot, int flags, int fd, + __off64_t offset); +LIBV4L_PUBLIC int v4l1_munmap(void *_start, size_t length); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/v4l2-apps/libv4l/include/libv4l2.h b/v4l2-apps/libv4l/include/libv4l2.h new file mode 100644 index 000000000..b05b57cb6 --- /dev/null +++ b/v4l2-apps/libv4l/include/libv4l2.h @@ -0,0 +1,110 @@ +/* +# (C) 2008 Hans de Goede + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# 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 Lesser General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __LIBV4L2_H +#define __LIBV4L2_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#if __GNUC__ >= 4 +#define LIBV4L_PUBLIC __attribute__ ((visibility("default"))) +#else +#define LIBV4L_PUBLIC +#endif + +/* Point this to a FILE opened for writing when you want to log error and + status messages to a file, when NULL errors will get send to stderr */ +LIBV4L_PUBLIC extern FILE *v4l2_log_file; + +/* Just like your regular open/close/etc, except that format conversion is + done if necessary when capturing. That is if you (try to) set a capture + format which is not supported by the cam, but is supported by libv4lconvert, + then the try_fmt / set_fmt will succeed as if the cam supports the format + and on dqbuf / read the data will be converted for you and returned in + the request format. + + Another difference is that you can make v4l2_read() calls even on devices + which do not support the regular read() method. + + Note that libv4l2 normally does not interfere with enum_fmt, so enum_fmt + will still return the actual formats the hardware supports, and not any + formats which may be emulated on top of that. If you pass the + V4L2_ENABLE_ENUM_FMT_EMULATION flag to v4l2_fd_open (as the v4l2convert.so + wrapper does) then enum_fmt will also report support for the formats to + which conversion is possible. + + Note the device name passed to v4l2_open must be of a video4linux2 device, + if it is anything else (including a video4linux1 device), v4l2_open will + fail. +*/ + +LIBV4L_PUBLIC int v4l2_open (const char *file, int oflag, ...); +LIBV4L_PUBLIC int v4l2_close(int fd); +LIBV4L_PUBLIC int v4l2_dup(int fd); +LIBV4L_PUBLIC int v4l2_ioctl (int fd, unsigned long int request, ...); +LIBV4L_PUBLIC ssize_t v4l2_read (int fd, void* buffer, size_t n); +LIBV4L_PUBLIC void *v4l2_mmap(void *start, size_t length, int prot, int flags, int fd, + __off64_t offset); +LIBV4L_PUBLIC int v4l2_munmap(void *_start, size_t length); + + +/* Misc utility functions */ + +/* This function takes a value of 0 - 65535, and then scales that range to + the actual range of the given v4l control id, and then if the cid exists + and is not locked sets the cid to the scaled value. + + Normally returns 0, even if the cid did not exist or was locked, returns + non 0 when an other error occured. */ +LIBV4L_PUBLIC int v4l2_set_control(int fd, int cid, int value); + +/* This function returns a value of 0 - 65535, scaled to from the actual range + of the given v4l control id. when the cid does not exist, could not be + accessed for some reason, or some error occured 0 is returned. */ +LIBV4L_PUBLIC int v4l2_get_control(int fd, int cid); + + +/* "low level" access functions, these functions allow somewhat lower level + access to libv4l2 (currently there only is v4l2_fd_open here) */ + +/* Flags for v4l2_fd_open's v4l2_flags argument */ + +/* Disable all format conversion done by libv4l2 (reduces libv4l2 functionality + to offering v4l2_read() even on devices which don't implement read()) */ +#define V4L2_DISABLE_CONVERSION 0x01 +/* Report not only real but also emulated formats with the ENUM_FMT ioctl */ +#define V4L2_ENABLE_ENUM_FMT_EMULATION 02 + +/* v4l2_fd_open: open an already opened fd for further use through + v4l2lib and possibly modify libv4l2's default behavior through the + v4l2_flags argument. + + Returns fd on success, -1 if the fd is not suitable for use through libv4l2 + (note the fd is left open in this case). */ +LIBV4L_PUBLIC int v4l2_fd_open(int fd, int v4l2_flags); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/v4l2-apps/libv4l/include/libv4lconvert.h b/v4l2-apps/libv4l/include/libv4lconvert.h new file mode 100644 index 000000000..626c43473 --- /dev/null +++ b/v4l2-apps/libv4l/include/libv4lconvert.h @@ -0,0 +1,88 @@ +/* +# (C) 2008 Hans de Goede + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# 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 Lesser General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __LIBV4LCONVERT_H +#define __LIBV4LCONVERT_H + +/* These headers are not needed by us, but by linux/videodev2.h, + which is broken on some systems and doesn't include them itself :( */ +#include +#include +#include +/* end broken header workaround includes */ +#include + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#if __GNUC__ >= 4 +#define LIBV4L_PUBLIC __attribute__ ((visibility("default"))) +#else +#define LIBV4L_PUBLIC +#endif + +struct v4lconvert_data; + +LIBV4L_PUBLIC struct v4lconvert_data *v4lconvert_create(int fd); +LIBV4L_PUBLIC void v4lconvert_destroy(struct v4lconvert_data *data); + +/* With regards to dest_fmt just like VIDIOC_TRY_FMT, except that the try + format will succeed and return the requested V4L2_PIX_FMT_foo in dest_fmt if + the cam has a format from which v4lconvert can convert to dest_fmt. + The real format to which the cam should be set is returned through src_fmt + when not NULL. */ +LIBV4L_PUBLIC int v4lconvert_try_format(struct v4lconvert_data *data, + struct v4l2_format *dest_fmt, /* in / out */ + struct v4l2_format *src_fmt /* out */ +); + +/* Just like VIDIOC_ENUM_FMT, except that the emulated formats are added at + the end of the list */ +LIBV4L_PUBLIC int v4lconvert_enum_fmt(struct v4lconvert_data *data, struct v4l2_fmtdesc *fmt); + +/* Is conversion necessary or can the app use the data directly? */ +LIBV4L_PUBLIC int v4lconvert_needs_conversion(struct v4lconvert_data *data, + const struct v4l2_format *src_fmt, /* in */ + const struct v4l2_format *dest_fmt); /* in */ + +/* return value of -1 on error, otherwise the amount of bytes written to + dest */ +LIBV4L_PUBLIC int v4lconvert_convert(struct v4lconvert_data *data, + const struct v4l2_format *src_fmt, /* in */ + const struct v4l2_format *dest_fmt, /* in */ + unsigned char *src, int src_size, unsigned char *dest, int dest_size); + +/* get a string describing the last error*/ +LIBV4L_PUBLIC const char *v4lconvert_get_error_message(struct v4lconvert_data *data); + +/* Just like VIDIOC_ENUM_FRAMESIZE, except that the framesizes of emulated + formats can be enumerated as well. */ +LIBV4L_PUBLIC int v4lconvert_enum_framesizes(struct v4lconvert_data *data, + struct v4l2_frmsizeenum *frmsize); + +/* Just like VIDIOC_ENUM_FRAMEINTERVALS, except that the intervals of emulated + formats can be enumerated as well. */ +LIBV4L_PUBLIC int v4lconvert_enum_frameintervals(struct v4lconvert_data *data, + struct v4l2_frmivalenum *frmival); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif diff --git a/v4l2-apps/libv4l/libv4l1/Makefile b/v4l2-apps/libv4l/libv4l1/Makefile new file mode 100644 index 000000000..27848477e --- /dev/null +++ b/v4l2-apps/libv4l/libv4l1/Makefile @@ -0,0 +1,83 @@ +override CPPFLAGS += -I../include -I../../../include -fvisibility=hidden + +CFLAGS := -g -O1 +CFLAGS += -Wall -Wno-unused -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes + +LIBS = -lpthread + +V4L1_OBJS = libv4l1.o log.o +V4L1COMPAT = v4l1compat.so +V4L1COMPAT_O = v4l1compat.o libv4l1.so +TARGETS = $(V4L1_LIB) libv4l1.pc +INCLUDES = ../include/libv4l1.h + +ifeq ($(LINKTYPE),static) +V4L1_LIB = libv4l1.a +else +V4L1_LIB = libv4l1.so +V4L1_OBJS += ../libv4l2/libv4l2.so +TARGETS += $(V4L1COMPAT) +override CPPFLAGS += -fPIC +endif + +ifeq ($(LIB_RELEASE),) +LIB_RELEASE = 0 +endif + +ifeq ($(PREFIX),) +PREFIX = /usr/local +endif + +ifeq ($(LIBDIR),) +LIBDIR = $(PREFIX)/lib +endif + +all: $(TARGETS) + + +$(V4L1_LIB): $(V4L1_OBJS) + +$(V4L1COMPAT): $(V4L1COMPAT_O) $(V4L1_LIB) + +libv4l1.pc: + @echo prefix=$(PREFIX) > libv4l1.pc + @echo libdir=$(LIBDIR) >> libv4l1.pc + @echo >> libv4l1.pc + @echo 'Name: libv4l1' >> libv4l1.pc + @echo 'Description: v4l1 compatibility library' >> libv4l1.pc + @echo 'Version: '$(V4L2_LIB_VERSION) >> libv4l1.pc + @echo 'Requires: libv4l2' >> libv4l1.pc + @echo 'Libs: -L$${libdir} -lv4l1' >> libv4l1.pc + @echo 'Libs.private: -lpthread' >> libv4l1.pc + @echo 'Cflags: -I$${prefix}/include' >> libv4l1.pc + +install: all + mkdir -p $(DESTDIR)$(PREFIX)/include + install -p -m 644 $(INCLUDES) $(DESTDIR)$(PREFIX)/include +ifeq ($(LINKTYPE),static) + mkdir -p $(DESTDIR)$(LIBDIR) + install -m 644 $(V4L1_LIB) $(DESTDIR)$(LIBDIR) +else + mkdir -p $(DESTDIR)$(LIBDIR)/libv4l + install -m 755 $(V4L1_LIB).$(LIB_RELEASE) $(DESTDIR)$(LIBDIR) + cd $(DESTDIR)$(LIBDIR) && \ + ln -f -s $(V4L1_LIB).$(LIB_RELEASE) $(V4L1_LIB) + install -m 755 $(V4L1COMPAT).$(LIB_RELEASE) \ + $(DESTDIR)$(LIBDIR)/libv4l/$(V4L1COMPAT) +endif + mkdir -p $(DESTDIR)$(LIBDIR)/pkgconfig + install -m 644 libv4l1.pc $(DESTDIR)$(LIBDIR)/pkgconfig + +clean:: + rm -f *.a *.so* *.o *.d libv4l1.pc log *~ + +%.o: %.c + $(CC) -c -MMD $(CPPFLAGS) $(CFLAGS) -o $@ $< + +%.so: + $(CC) -shared $(LDFLAGS) -Wl,-soname,$@.$(LIB_RELEASE) -o $@.$(LIB_RELEASE) $^ $(LIBS) + ln -f -s $@.$(LIB_RELEASE) $@ + +%.a: + $(AR) cqs $@ $^ + diff --git a/v4l2-apps/libv4l/libv4l1/libv4l1-priv.h b/v4l2-apps/libv4l/libv4l1/libv4l1-priv.h new file mode 100644 index 000000000..651599255 --- /dev/null +++ b/v4l2-apps/libv4l/libv4l1/libv4l1-priv.h @@ -0,0 +1,83 @@ +/* +# (C) 2008 Hans de Goede + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __LIBV4L1_PRIV_H +#define __LIBV4L1_PRIV_H + +#include +#include + +/* On 32 bits archs we always use mmap2, on 64 bits archs there is no mmap2 */ +#ifdef __NR_mmap2 +#define SYS_mmap2 __NR_mmap2 +#define MMAP2_PAGE_SHIFT 12 +#else +#define SYS_mmap2 SYS_mmap +#define MMAP2_PAGE_SHIFT 0 +#endif + +#define V4L1_MAX_DEVICES 16 +#define V4L1_NO_FRAMES 4 +#define V4L1_FRAME_BUF_SIZE (4096 * 4096) + +extern FILE *v4l1_log_file; + +#define V4L1_LOG_ERR(...) \ + do { \ + if (v4l1_log_file) { \ + fprintf(v4l1_log_file, "libv4l1: error " __VA_ARGS__); \ + fflush(v4l1_log_file); \ + } else \ + fprintf(stderr, "libv4l1: error " __VA_ARGS__); \ + } while(0) + +#define V4L1_LOG_WARN(...) \ + do { \ + if (v4l1_log_file) { \ + fprintf(v4l1_log_file, "libv4l1: warning " __VA_ARGS__); \ + fflush(v4l1_log_file); \ + } else \ + fprintf(stderr, "libv4l1: warning " __VA_ARGS__); \ + } while(0) + +#define V4L1_LOG(...) \ + do { \ + if (v4l1_log_file) { \ + fprintf(v4l1_log_file, "libv4l1: " __VA_ARGS__); \ + fflush(v4l1_log_file); \ + } \ + } while(0) + +struct v4l1_dev_info { + int fd; + int flags; + int open_count; + int v4l1_frame_buf_map_count; + pthread_mutex_t stream_lock; + unsigned int depth; + unsigned int v4l1_pal; /* VIDEO_PALETTE */ + unsigned int v4l2_pixfmt; /* V4L2_PIX_FMT */ + unsigned int min_width, min_height, max_width, max_height; + unsigned int width, height; + unsigned char *v4l1_frame_pointer; +}; + +/* From log.c */ +void v4l1_log_ioctl(unsigned long int request, void *arg, int result); + +#endif diff --git a/v4l2-apps/libv4l/libv4l1/libv4l1.c b/v4l2-apps/libv4l/libv4l1/libv4l1.c new file mode 100644 index 000000000..797c8768a --- /dev/null +++ b/v4l2-apps/libv4l/libv4l1/libv4l1.c @@ -0,0 +1,837 @@ +/* +# libv4l1 userspace v4l1 api emulation for v4l2 devices + +# (C) 2008 Hans de Goede + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# 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 Lesser General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* MAKING CHANGES TO THIS FILE?? READ THIS FIRST!!! + + Important note to people making changes to this file: All functions + (v4l1_close, v4l1_ioctl, etc.) are designed to function as their regular + counterpart when they get passed a fd that is not "registered" by libv4l1, + there are 2 reasons for this: + 1) This allows us to get completely out of the way when dealing with non + capture only devices, or non v4l2 devices. + 2) libv4l1 is the base of the v4l1compat.so wrapper lib, which is a .so + which can be LD_PRELOAD-ed and the overrules the libc's open/close/etc, + and when opening /dev/videoX or /dev/v4l/ calls v4l1_open. Because we + behave as the regular counterpart when the fd is not known (instead of + say throwing an error), v4l1compat.so can simply call the v4l1_ prefixed + function for all wrapped functions. This way the wrapper does not have + to keep track of which fd's are being handled by libv4l1, as libv4l1 + already keeps track of this itself. + + This also means that libv4l1 may not use any of the regular functions + it mimics, as for example open could be a symbol in v4l1compat.so, which + in turn will call v4l1_open, so therefor v4l1_open (for example) may not + use the regular open()! +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* These headers are not needed by us, but by linux/videodev2.h, + which is broken on some systems and doesn't include them itself :( */ +#include +#include +#include +/* end broken header workaround includes */ +#include +#include +#include +#include "libv4l1.h" +#include "libv4l1-priv.h" + +#define V4L1_SUPPORTS_ENUMINPUT 0x01 +#define V4L1_SUPPORTS_ENUMSTD 0x02 +#define V4L1_PIX_FMT_TOUCHED 0x04 +#define V4L1_PIX_SIZE_TOUCHED 0x08 + +static pthread_mutex_t v4l1_open_mutex = PTHREAD_MUTEX_INITIALIZER; +static struct v4l1_dev_info devices[V4L1_MAX_DEVICES] = { { .fd = -1 }, + { .fd = -1 }, { .fd = -1 }, { .fd = -1 }, { .fd = -1 }, { .fd = -1 }, + { .fd = -1 }, { .fd = -1 }, { .fd = -1 }, { .fd = -1 }, { .fd = -1 }, + { .fd = -1 }, { .fd = -1 }, { .fd = -1 }, { .fd = -1 }, { .fd = -1 }}; +static int devices_used = 0; + +static unsigned int palette_to_pixelformat(unsigned int palette) +{ + switch (palette) { + case VIDEO_PALETTE_GREY: + return V4L2_PIX_FMT_GREY; + case VIDEO_PALETTE_RGB555: + return V4L2_PIX_FMT_RGB555; + case VIDEO_PALETTE_RGB565: + return V4L2_PIX_FMT_RGB565; + case VIDEO_PALETTE_RGB24: + return V4L2_PIX_FMT_BGR24; + case VIDEO_PALETTE_RGB32: + return V4L2_PIX_FMT_BGR32; + case VIDEO_PALETTE_YUYV: + return V4L2_PIX_FMT_YUYV; + case VIDEO_PALETTE_YUV422: + return V4L2_PIX_FMT_YUYV; + case VIDEO_PALETTE_UYVY: + return V4L2_PIX_FMT_UYVY; + case VIDEO_PALETTE_YUV410P: + return V4L2_PIX_FMT_YUV410; + case VIDEO_PALETTE_YUV420: + case VIDEO_PALETTE_YUV420P: + return V4L2_PIX_FMT_YUV420; + case VIDEO_PALETTE_YUV411P: + return V4L2_PIX_FMT_YUV411P; + case VIDEO_PALETTE_YUV422P: + return V4L2_PIX_FMT_YUV422P; + } + return 0; +} + +static unsigned int pixelformat_to_palette(unsigned int pixelformat) +{ + switch (pixelformat) { + case V4L2_PIX_FMT_GREY: + return VIDEO_PALETTE_GREY; + case V4L2_PIX_FMT_RGB555: + return VIDEO_PALETTE_RGB555; + case V4L2_PIX_FMT_RGB565: + return VIDEO_PALETTE_RGB565; + case V4L2_PIX_FMT_BGR24: + return VIDEO_PALETTE_RGB24; + case V4L2_PIX_FMT_BGR32: + return VIDEO_PALETTE_RGB32; + case V4L2_PIX_FMT_YUYV: + return VIDEO_PALETTE_YUYV; + case V4L2_PIX_FMT_UYVY: + return VIDEO_PALETTE_UYVY; + case V4L2_PIX_FMT_YUV410: + case V4L2_PIX_FMT_YUV420: + return VIDEO_PALETTE_YUV420P; + case V4L2_PIX_FMT_YUV411P: + return VIDEO_PALETTE_YUV411P; + case V4L2_PIX_FMT_YUV422P: + return VIDEO_PALETTE_YUV422P; + } + return 0; +} + +static int v4l1_set_format(int index, unsigned int width, + unsigned int height, int v4l1_pal, int width_height_may_differ) +{ + int result; + unsigned int v4l2_pixfmt; + struct v4l2_format fmt2 = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE }; + + if (v4l1_pal != -1) { + v4l2_pixfmt = palette_to_pixelformat(v4l1_pal); + if (!v4l2_pixfmt) { + V4L1_LOG("Unknown v4l1 palette number: %d\n", v4l1_pal); + errno = EINVAL; + return -1; + } + } else { + v4l2_pixfmt = devices[index].v4l2_pixfmt; + v4l1_pal = devices[index].v4l1_pal; + } + + /* Do we need to change the resolution / format ? */ + if (width == devices[index].width && height == devices[index].height && + v4l2_pixfmt == devices[index].v4l2_pixfmt) + return 0; + + /* Get current settings, apply our changes and try the new setting */ + if ((result = v4l2_ioctl(devices[index].fd, VIDIOC_G_FMT, &fmt2))) { + int saved_err = errno; + V4L1_LOG_ERR("getting pixformat: %s\n", strerror(errno)); + errno = saved_err; + return result; + } + + fmt2.fmt.pix.pixelformat = v4l2_pixfmt; + fmt2.fmt.pix.width = width; + fmt2.fmt.pix.height = height; + if ((result = v4l2_ioctl(devices[index].fd, VIDIOC_TRY_FMT, &fmt2))) + { + int saved_err = errno; + V4L1_LOG("error trying pixformat: %s\n", strerror(errno)); + errno = saved_err; + return result; + } + + /* Check if we get what we asked for */ + if (fmt2.fmt.pix.pixelformat != v4l2_pixfmt || (!width_height_may_differ && + (fmt2.fmt.pix.width != width || fmt2.fmt.pix.height != height))) { + V4L1_LOG("requested fmt, width, height combo not available\n"); + errno = EINVAL; + return -1; + } + + /* Maybe after the TRY_FMT things haven't changed after all ? */ + if (fmt2.fmt.pix.width == devices[index].width && + fmt2.fmt.pix.height == devices[index].height && + fmt2.fmt.pix.pixelformat == devices[index].v4l2_pixfmt) { + devices[index].v4l1_pal = v4l1_pal; + return 0; + } + + if ((result = v4l2_ioctl(devices[index].fd, VIDIOC_S_FMT, &fmt2))) { + int saved_err = errno; + V4L1_LOG_ERR("setting pixformat: %s\n", strerror(errno)); + errno = saved_err; + return result; + } + + devices[index].width = fmt2.fmt.pix.width; + devices[index].height = fmt2.fmt.pix.height; + devices[index].v4l2_pixfmt = v4l2_pixfmt; + devices[index].v4l1_pal = v4l1_pal; + devices[index].depth = ((fmt2.fmt.pix.bytesperline << 3) + + (fmt2.fmt.pix.width - 1)) / fmt2.fmt.pix.width; + + return result; +} + +static void v4l1_find_min_and_max_size(int index, struct v4l2_format *fmt2) +{ + int i; + struct v4l2_fmtdesc fmtdesc2 = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE }; + + devices[index].min_width = -1; + devices[index].min_height = -1; + devices[index].max_width = 0; + devices[index].max_height = 0; + + for (i = 0; ; i++) { + fmtdesc2.index = i; + + if (syscall(SYS_ioctl, devices[index].fd, VIDIOC_ENUM_FMT, &fmtdesc2)) + break; + + fmt2->fmt.pix.pixelformat = fmtdesc2.pixelformat; + fmt2->fmt.pix.width = 48; + fmt2->fmt.pix.height = 32; + + if (syscall(SYS_ioctl, devices[index].fd, VIDIOC_TRY_FMT, fmt2) == 0) { + if (fmt2->fmt.pix.width < devices[index].min_width) + devices[index].min_width = fmt2->fmt.pix.width; + if (fmt2->fmt.pix.height < devices[index].min_height) + devices[index].min_height = fmt2->fmt.pix.height; + } + + fmt2->fmt.pix.pixelformat = fmtdesc2.pixelformat; + fmt2->fmt.pix.width = 100000; + fmt2->fmt.pix.height = 100000; + + if (syscall(SYS_ioctl, devices[index].fd, VIDIOC_TRY_FMT, fmt2) == 0) { + if (fmt2->fmt.pix.width > devices[index].max_width) + devices[index].max_width = fmt2->fmt.pix.width; + if (fmt2->fmt.pix.height > devices[index].max_height) + devices[index].max_height = fmt2->fmt.pix.height; + } + } +} + + +int v4l1_open (const char *file, int oflag, ...) +{ + int index, fd; + char *lfname; + struct v4l2_capability cap2; + struct v4l2_format fmt2; + struct v4l2_input input2; + struct v4l2_standard standard2; + int v4l_device = 0; + + /* check if we're opening a video4linux2 device */ + if (!strncmp(file, "/dev/video", 10) || !strncmp(file, "/dev/v4l/", 9)) { + /* Some apps open the device read only, but we need rw rights as the + buffers *MUST* be mapped rw */ + oflag = (oflag & ~O_ACCMODE) | O_RDWR; + v4l_device = 1; + } + + /* original open code */ + if (oflag & O_CREAT) + { + va_list ap; + mode_t mode; + + va_start (ap, oflag); + mode = va_arg (ap, mode_t); + + fd = syscall(SYS_open, file, oflag, mode); + + va_end(ap); + } else + fd = syscall(SYS_open, file, oflag); + /* end of original open code */ + + if (fd == -1 || !v4l_device) + return fd; + + /* check that this is an v4l2 device, no need to emulate v4l1 on + a v4l1 device */ + if (syscall(SYS_ioctl, fd, VIDIOC_QUERYCAP, &cap2)) + return fd; + + /* IMPROVEME */ + /* we only support simple video capture devices which do not do overlay */ + if ((cap2.capabilities & 0x0F) != V4L2_CAP_VIDEO_CAPTURE) + return fd; + + /* If no log file was set by the app, see if one was specified through the + environment */ + if (!v4l1_log_file && (lfname = getenv("LIBV4L1_LOG_FILENAME"))) + v4l1_log_file = fopen(lfname, "w"); + + /* redirect libv4l2 log messages to our logfile if no libv4l2 logfile is + specified */ + if (!v4l2_log_file) + v4l2_log_file = v4l1_log_file; + + /* Get initial width, height and pixelformat */ + fmt2.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (syscall(SYS_ioctl, fd, VIDIOC_G_FMT, &fmt2)) { + int saved_err = errno; + V4L1_LOG_ERR("getting pixformat: %s\n", strerror(errno)); + syscall(SYS_close, fd); + errno = saved_err; + return -1; + } + + /* Register with libv4l2, as we use that todo format conversion and read() + emulation for us */ + if (v4l2_fd_open(fd, V4L2_ENABLE_ENUM_FMT_EMULATION) == -1) { + int saved_err = errno; + syscall(SYS_close, fd); + errno = saved_err; + return -1; + } + + /* So we have a device on which we can (and want to) emulate v4l1, register + it in our devices array */ + pthread_mutex_lock(&v4l1_open_mutex); + for (index = 0; index < V4L1_MAX_DEVICES; index++) + if(devices[index].fd == -1) { + devices[index].fd = fd; + break; + } + pthread_mutex_unlock(&v4l1_open_mutex); + + if (index == V4L1_MAX_DEVICES) { + V4L1_LOG_ERR("attempting to open more then %d video devices\n", + V4L1_MAX_DEVICES); + v4l2_close(fd); + errno = EBUSY; + return -1; + } + + if (index >= devices_used) + devices_used = index + 1; + + devices[index].flags = 0; + devices[index].open_count = 1; + devices[index].v4l1_frame_buf_map_count = 0; + devices[index].v4l1_frame_pointer = MAP_FAILED; + devices[index].width = fmt2.fmt.pix.width; + devices[index].height = fmt2.fmt.pix.height; + devices[index].v4l2_pixfmt = fmt2.fmt.pix.pixelformat; + devices[index].v4l1_pal = pixelformat_to_palette(fmt2.fmt.pix.pixelformat); + devices[index].depth = ((fmt2.fmt.pix.bytesperline << 3) + + (fmt2.fmt.pix.width - 1)) / fmt2.fmt.pix.width; + + v4l1_find_min_and_max_size(index, &fmt2); + + /* Check ENUM_INPUT and ENUM_STD support */ + input2.index = 0; + if (v4l2_ioctl(fd, VIDIOC_ENUMINPUT, &input2) == 0) + devices[index].flags |= V4L1_SUPPORTS_ENUMINPUT; + + standard2.index = 0; + if (v4l2_ioctl(fd, VIDIOC_ENUMSTD, &input2) == 0) + devices[index].flags |= V4L1_SUPPORTS_ENUMSTD; + + V4L1_LOG("open: %d\n", fd); + + return fd; +} + +/* Is this an fd for which we are emulating v4l1 ? */ +static int v4l1_get_index(int fd) +{ + int index; + + /* We never handle fd -1 */ + if (fd == -1) + return -1; + + for (index = 0; index < devices_used; index++) + if (devices[index].fd == fd) + break; + + if (index == devices_used) + return -1; + + return index; +} + + +int v4l1_close(int fd) { + int index, result; + + if ((index = v4l1_get_index(fd)) == -1) + return syscall(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 + syscall(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; +} + +int v4l1_dup(int fd) +{ + int index; + + if ((index = v4l1_get_index(fd)) == -1) + return syscall(SYS_dup, fd); + + devices[index].open_count++; + + return v4l2_dup(fd); +} + + +int v4l1_ioctl (int fd, unsigned long int request, ...) +{ + void *arg; + va_list ap; + int result, index, saved_err, stream_locked = 0; + + va_start (ap, request); + arg = va_arg (ap, void *); + va_end (ap); + + if ((index = v4l1_get_index(fd)) == -1) + return syscall(SYS_ioctl, fd, request, arg); + + /* Appearantly the kernel and / or glibc ignore the 32 most significant bits + when long = 64 bits, and some applications pass an int holding the req to + ioctl, causing it to get sign extended, depending upon this behavior */ + request = (unsigned int)request; + + /* do we need to take the stream lock for this ioctl? */ + switch (request) { + case VIDIOCSPICT: + case VIDIOCGPICT: + case VIDIOCSWIN: + case VIDIOCGWIN: + case VIDIOCGMBUF: + case VIDIOCMCAPTURE: + case VIDIOCSYNC: + case VIDIOC_S_FMT: + pthread_mutex_lock(&devices[index].stream_lock); + stream_locked = 1; + } + + switch (request) { + + case VIDIOCGCAP: + { + struct video_capability *cap = arg; + + result = syscall(SYS_ioctl, fd, request, arg); + + /* override kernel v4l1 compat min / max size with our own more + accurate values */ + cap->minwidth = devices[index].min_width; + cap->minheight = devices[index].min_height; + cap->maxwidth = devices[index].max_width; + cap->maxheight = devices[index].max_height; + } + break; + + case VIDIOCSPICT: + { + struct video_picture *pic = arg; + + devices[index].flags |= V4L1_PIX_FMT_TOUCHED; + + v4l2_set_control(fd, V4L2_CID_BRIGHTNESS, pic->brightness); + v4l2_set_control(fd, V4L2_CID_HUE, pic->hue); + v4l2_set_control(fd, V4L2_CID_CONTRAST, pic->contrast); + v4l2_set_control(fd, V4L2_CID_SATURATION, pic->colour); + v4l2_set_control(fd, V4L2_CID_WHITENESS, pic->whiteness); + + result = v4l1_set_format(index, devices[index].width, + devices[index].height, pic->palette, 0); + } + break; + + case VIDIOCGPICT: + { + struct video_picture *pic = arg; + + /* If our v4l2 pixformat has no corresponding v4l1 palette, and the + app has not touched the pixformat sofar, try setting a palette which + does (and which we emulate when necessary) so that applications + which just query the current format and then take whatever they get + will work */ + if (!(devices[index].flags & V4L1_PIX_FMT_TOUCHED) && + !pixelformat_to_palette(devices[index].v4l2_pixfmt)) + v4l1_set_format(index, devices[index].width, + devices[index].height, + VIDEO_PALETTE_RGB24, + (devices[index].flags & + V4L1_PIX_SIZE_TOUCHED) ? 0 : 1); + + devices[index].flags |= V4L1_PIX_FMT_TOUCHED; + + pic->depth = devices[index].depth; + pic->palette = devices[index].v4l1_pal; + pic->hue = v4l2_get_control(devices[index].fd, V4L2_CID_HUE); + pic->colour = v4l2_get_control(devices[index].fd, V4L2_CID_SATURATION); + pic->contrast = v4l2_get_control(devices[index].fd, V4L2_CID_CONTRAST); + pic->whiteness = v4l2_get_control(devices[index].fd, + V4L2_CID_WHITENESS); + pic->brightness = v4l2_get_control(devices[index].fd, + V4L2_CID_BRIGHTNESS); + + result = 0; + } + break; + + case VIDIOCSWIN: + { + struct video_window *win = arg; + + devices[index].flags |= V4L1_PIX_SIZE_TOUCHED; + + result = v4l1_set_format(index, win->width, win->height, -1, 1); + if (result == 0) { + win->width = devices[index].width; + win->height = devices[index].height; + } + } + break; + + case VIDIOCGWIN: + devices[index].flags |= V4L1_PIX_SIZE_TOUCHED; + result = syscall(SYS_ioctl, fd, request, arg); + break; + + case VIDIOCGCHAN: + { + struct v4l2_input input2; + struct video_channel *chan = arg; + + if ((devices[index].flags & V4L1_SUPPORTS_ENUMINPUT) && + (devices[index].flags & V4L1_SUPPORTS_ENUMSTD)) { + result = syscall(SYS_ioctl, fd, request, arg); + break; + } + + /* Set some defaults */ + chan->tuners = 0; + chan->flags = 0; + chan->type = VIDEO_TYPE_CAMERA; + chan->norm = 0; + + /* In case of no ENUMSTD support, ignore the norm member of the + channel struct */ + if (devices[index].flags & V4L1_SUPPORTS_ENUMINPUT) { + input2.index = chan->channel; + result = v4l2_ioctl(fd, VIDIOC_ENUMINPUT, &input2); + if (result == 0) { + snprintf(chan->name, sizeof(chan->name), "%s", (char*)input2.name); + if (input2.type == V4L2_INPUT_TYPE_TUNER) { + chan->tuners = 1; + chan->type = VIDEO_TYPE_TV; + chan->flags = VIDEO_VC_TUNER; + } + } + break; + } + + /* No ENUMINPUT support, fake it (assume its a Camera in this case) */ + if (chan->channel == 0) { + snprintf(chan->name, sizeof(chan->name), "Camera"); + result = 0; + } else { + errno = EINVAL; + result = -1; + } + } + break; + + case VIDIOCSCHAN: + { + struct video_channel *chan = arg; + if ((devices[index].flags & V4L1_SUPPORTS_ENUMINPUT) && + (devices[index].flags & V4L1_SUPPORTS_ENUMSTD)) { + result = syscall(SYS_ioctl, fd, request, arg); + break; + } + /* In case of no ENUMSTD support, ignore the norm member of the + channel struct */ + if (devices[index].flags & V4L1_SUPPORTS_ENUMINPUT) { + result = v4l2_ioctl(fd, VIDIOC_S_INPUT, &chan->channel); + break; + } + /* No ENUMINPUT support, fake it (assume its a Camera in this case) */ + if (chan->channel == 0) { + result = 0; + } else { + errno = EINVAL; + result = -1; + } + } + break; + + case VIDIOCGMBUF: + /* When VIDIOCGMBUF is done, we don't necessarrily know the format the + application wants yet (with some apps this is passed for the first + time through VIDIOCMCAPTURE), so we just create an anonymous mapping + that should be large enough to hold any sort of frame. Note this only + takes virtual memory, and does not use memory until actually used. */ + { + int i; + struct video_mbuf *mbuf = arg; + + mbuf->size = V4L1_NO_FRAMES * V4L1_FRAME_BUF_SIZE; + mbuf->frames = V4L1_NO_FRAMES; + for (i = 0; i < mbuf->frames; i++) { + mbuf->offsets[i] = i * V4L1_FRAME_BUF_SIZE; + } + + if (devices[index].v4l1_frame_pointer == MAP_FAILED) { + devices[index].v4l1_frame_pointer = (void *)syscall(SYS_mmap2, NULL, + (size_t)mbuf->size, + PROT_READ|PROT_WRITE, + MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); + if (devices[index].v4l1_frame_pointer == MAP_FAILED) { + saved_err = errno; + V4L1_LOG_ERR("allocating v4l1 buffer: %s\n", strerror(errno)); + errno = saved_err; + result = -1; + break; + } + V4L1_LOG("allocated v4l1 buffer @ %p\n", + devices[index].v4l1_frame_pointer); + } + result = 0; + } + break; + + case VIDIOCMCAPTURE: + { + struct video_mmap *map = arg; + + devices[index].flags |= V4L1_PIX_FMT_TOUCHED | + V4L1_PIX_SIZE_TOUCHED; + + result = v4l1_set_format(index, map->width, map->height, + map->format, 0); + } + break; + + case VIDIOCSYNC: + { + int *frame_index = arg; + + if (devices[index].v4l1_frame_pointer == MAP_FAILED || + *frame_index < 0 || *frame_index >= V4L1_NO_FRAMES) { + errno = EINVAL; + result = -1; + break; + } + + result = v4l2_read(devices[index].fd, + devices[index].v4l1_frame_pointer + + *frame_index * V4L1_FRAME_BUF_SIZE, + V4L1_FRAME_BUF_SIZE); + result = (result > 0) ? 0:result; + } + break; + + /* We are passing through v4l2 calls to libv4l2 for applications which are + using v4l2 through libv4l1 (possible with the v4l1compat.so wrapper). + + So the application could be calling VIDIOC_S_FMT, in this case update + our own bookkeeping of the cam's format. Note that this really only is + relevant if an application is mixing and matching v4l1 and v4l2 calls, + which is crazy, but better safe then sorry. */ + case VIDIOC_S_FMT: + { + struct v4l2_format *fmt2 = arg; + + result = v4l2_ioctl(fd, request, arg); + + if (result == 0 && fmt2->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + if (devices[index].v4l2_pixfmt != fmt2->fmt.pix.pixelformat) { + devices[index].v4l2_pixfmt = fmt2->fmt.pix.pixelformat; + devices[index].v4l1_pal = + pixelformat_to_palette(fmt2->fmt.pix.pixelformat); + } + devices[index].width = fmt2->fmt.pix.width; + devices[index].height = fmt2->fmt.pix.height; + } + } + break; + + default: + /* Pass through libv4l2 for applications which are using v4l2 through + libv4l1 (this can happen with the v4l1compat.so wrapper preloaded */ + result = v4l2_ioctl(fd, request, arg); + } + + if (stream_locked) + pthread_mutex_unlock(&devices[index].stream_lock); + + saved_err = errno; + v4l1_log_ioctl(request, arg, result); + errno = saved_err; + + return result; +} + + +ssize_t v4l1_read(int fd, void* buffer, size_t n) +{ + int index; + ssize_t result; + + if ((index = v4l1_get_index(fd)) == -1) + return syscall(SYS_read, fd, buffer, n); + + pthread_mutex_lock(&devices[index].stream_lock); + result = v4l2_read(fd, buffer, n); + pthread_mutex_unlock(&devices[index].stream_lock); + + return result; +} + + +void *v4l1_mmap(void *start, size_t length, int prot, int flags, int fd, + __off64_t offset) +{ + int index; + void *result; + + /* Check if the mmap data matches our answer to VIDIOCGMBUF, if not + pass through libv4l2 for applications which are using v4l2 through + libv4l1 (this can happen with the v4l1compat.so wrapper preloaded */ + if ((index = v4l1_get_index(fd)) == -1 || start || offset || + length != (V4L1_NO_FRAMES * V4L1_FRAME_BUF_SIZE)) + return v4l2_mmap(start, length, prot, flags, fd, offset); + + + pthread_mutex_lock(&devices[index].stream_lock); + + /* It could be that we get called with an mmap which seems to match what + we expect, but no VIDIOCGMBUF has been done yet, then it is certainly not + for us so pass it through */ + if (devices[index].v4l1_frame_pointer == MAP_FAILED) { + result = v4l2_mmap(start, length, prot, flags, fd, offset); + goto leave; + } + + devices[index].v4l1_frame_buf_map_count++; + + V4L1_LOG("v4l1 buffer @ %p mapped by application\n", + devices[index].v4l1_frame_pointer); + + result = devices[index].v4l1_frame_pointer; + +leave: + pthread_mutex_unlock(&devices[index].stream_lock); + + return result; +} + +int v4l1_munmap(void *_start, size_t length) +{ + int index; + unsigned char *start = _start; + + /* Is this memory ours? */ + if (start != MAP_FAILED && + length == (V4L1_FRAME_BUF_SIZE * V4L1_NO_FRAMES)) { + for (index = 0; index < devices_used; index++) + if (devices[index].fd != -1 && + start == devices[index].v4l1_frame_pointer) + break; + + if (index != devices_used) { + int unmapped = 0; + + pthread_mutex_lock(&devices[index].stream_lock); + + /* Redo our checks now that we have the lock, things may have changed */ + if (start == devices[index].v4l1_frame_pointer) { + if (devices[index].v4l1_frame_buf_map_count > 0) + devices[index].v4l1_frame_buf_map_count--; + + unmapped = 1; + } + + pthread_mutex_unlock(&devices[index].stream_lock); + + if (unmapped) { + V4L1_LOG("v4l1 buffer munmap %p, %d\n", start, (int)length); + return 0; + } + } + } + + V4L1_LOG("v4l1 unknown munmap %p, %d\n", start, (int)length); + + /* If not pass through libv4l2 for applications which are using v4l2 through + libv4l1 (this can happen with the v4l1compat.so wrapper preloaded */ + return v4l2_munmap(start, length); +} diff --git a/v4l2-apps/libv4l/libv4l1/log.c b/v4l2-apps/libv4l/libv4l1/log.c new file mode 100644 index 000000000..9ff0cea46 --- /dev/null +++ b/v4l2-apps/libv4l/libv4l1/log.c @@ -0,0 +1,145 @@ +/* +# (C) 2008 Hans de Goede + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +/* These headers are not needed by us, but by linux/videodev2.h, + which is broken on some systems and doesn't include them itself :( */ +#include +#include +/* end broken header workaround includes */ +#include +#include "libv4l1-priv.h" + +#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0])) + +FILE *v4l1_log_file = NULL; + +static const char *v4l1_ioctls[] = { + [_IOC_NR(VIDIOCGCAP)] = "VIDIOCGCAP", + [_IOC_NR(VIDIOCGCHAN)] = "VIDIOCGCHAN", + [_IOC_NR(VIDIOCSCHAN)] = "VIDIOCSCHAN", + [_IOC_NR(VIDIOCGTUNER)] = "VIDIOCGTUNER", + [_IOC_NR(VIDIOCSTUNER)] = "VIDIOCSTUNER", + [_IOC_NR(VIDIOCGPICT)] = "VIDIOCGPICT", + [_IOC_NR(VIDIOCSPICT)] = "VIDIOCSPICT", + [_IOC_NR(VIDIOCCAPTURE)] = "VIDIOCCAPTURE", + [_IOC_NR(VIDIOCGWIN)] = "VIDIOCGWIN", + [_IOC_NR(VIDIOCSWIN)] = "VIDIOCSWIN", + [_IOC_NR(VIDIOCGFBUF)] = "VIDIOCGFBUF", + [_IOC_NR(VIDIOCSFBUF)] = "VIDIOCSFBUF", + [_IOC_NR(VIDIOCKEY)] = "VIDIOCKEY", + [_IOC_NR(VIDIOCGFREQ)] = "VIDIOCGFREQ", + [_IOC_NR(VIDIOCSFREQ)] = "VIDIOCSFREQ", + [_IOC_NR(VIDIOCGAUDIO)] = "VIDIOCGAUDIO", + [_IOC_NR(VIDIOCSAUDIO)] = "VIDIOCSAUDIO", + [_IOC_NR(VIDIOCSYNC)] = "VIDIOCSYNC", + [_IOC_NR(VIDIOCMCAPTURE)] = "VIDIOCMCAPTURE", + [_IOC_NR(VIDIOCGMBUF)] = "VIDIOCGMBUF", + [_IOC_NR(VIDIOCGUNIT)] = "VIDIOCGUNIT", + [_IOC_NR(VIDIOCGCAPTURE)] = "VIDIOCGCAPTURE", + [_IOC_NR(VIDIOCSCAPTURE)] = "VIDIOCSCAPTURE", + [_IOC_NR(VIDIOCSPLAYMODE)] = "VIDIOCSPLAYMODE", + [_IOC_NR(VIDIOCSWRITEMODE)] = "VIDIOCSWRITEMODE", + [_IOC_NR(VIDIOCGPLAYINFO)] = "VIDIOCGPLAYINFO", + [_IOC_NR(VIDIOCSMICROCODE)] = "VIDIOCSMICROCODE", + [_IOC_NR(VIDIOCGVBIFMT)] = "VIDIOCGVBIFMT", + [_IOC_NR(VIDIOCSVBIFMT)] = "VIDIOCSVBIFMT", +}; + +void v4l1_log_ioctl(unsigned long int request, void *arg, int result) +{ + const char *ioctl_str = "unknown"; + char buf[40]; + + if (!v4l1_log_file) + return; + + /* Don't log v4l2 ioctl's as unknown we pass them to libv4l2 which will + log them for us */ + if (_IOC_TYPE(request) == 'V') + return; + + if (_IOC_TYPE(request) == 'v' && _IOC_NR(request) < ARRAY_SIZE(v4l1_ioctls)) + ioctl_str = v4l1_ioctls[_IOC_NR(request)]; + else { + snprintf(buf, sizeof(buf), "unknown request: %c %d\n", + (int)_IOC_TYPE(request), (int)_IOC_NR(request)); + ioctl_str = buf; + } + + fprintf(v4l1_log_file, "request == %s\n", ioctl_str); + + switch(request) + { + case VIDIOCGCAP:fprintf(v4l1_log_file,"name %s\n",( (struct video_capability*)arg)->name ); + fprintf(v4l1_log_file,"type %d\n",( (struct video_capability*)arg)->type ); + fprintf(v4l1_log_file,"channels %d\n",( (struct video_capability*)arg)->channels ); + fprintf(v4l1_log_file,"audios %d\n",( (struct video_capability*)arg)->audios ); + fprintf(v4l1_log_file,"maxwidth %d\n",( (struct video_capability*)arg)->maxwidth ); + fprintf(v4l1_log_file,"maxheight %d\n",( (struct video_capability*)arg)->maxheight ); + fprintf(v4l1_log_file,"minwidth %d\n",( (struct video_capability*)arg)->minwidth ); + fprintf(v4l1_log_file,"minheight %d\n",( (struct video_capability*)arg)->minheight ); + break; + case VIDIOCGWIN: + case VIDIOCSWIN: + fprintf(v4l1_log_file,"width\t%u\n", + ((struct video_window *)arg)->width); + fprintf(v4l1_log_file,"height\t%u\n", + ((struct video_window *)arg)->height); + break; + + case VIDIOCGCHAN: + case VIDIOCSCHAN: + fprintf(v4l1_log_file,"channel %d\n",( (struct video_channel*)arg)->channel ); + fprintf(v4l1_log_file,"name %s\n",( (struct video_channel*)arg)->name ); + break; + + case VIDIOCGPICT: + case VIDIOCSPICT: + fprintf(v4l1_log_file,"brightness %d\n",( (int)((struct video_picture*)arg)->brightness) ); + fprintf(v4l1_log_file,"hue %d\n",( (int)((struct video_picture*)arg)->hue) ); + fprintf(v4l1_log_file,"colour %d\n",( (int)((struct video_picture*)arg)->colour) ); + fprintf(v4l1_log_file,"contrast %d\n",( (int)((struct video_picture*)arg)->contrast) ); + fprintf(v4l1_log_file,"whiteness %d\n",( (int)((struct video_picture*)arg)->whiteness) ); + fprintf(v4l1_log_file,"depth %d\n",( (int)((struct video_picture*)arg)->depth) ); + fprintf(v4l1_log_file,"palette %d\n",( (int)((struct video_picture*)arg)->palette) ); + break; + + case VIDIOCCAPTURE: fprintf(v4l1_log_file,"on/off? %d\n", *((int *)arg) ); + break; + + case VIDIOCSYNC: fprintf(v4l1_log_file,"sync %d\n", *((int *)arg) ); + break; + + case VIDIOCMCAPTURE: + fprintf(v4l1_log_file,"frame %u\n",( (struct video_mmap*)arg)->frame ); + fprintf(v4l1_log_file,"width %d\n",( (struct video_mmap*)arg)->width ); + fprintf(v4l1_log_file,"height %d\n",( (struct video_mmap*)arg)->height ); + fprintf(v4l1_log_file,"format %u\n",( (struct video_mmap*)arg)->format ); + break; + + case VIDIOCGMBUF: + fprintf(v4l1_log_file,"size %d\n",( (struct video_mbuf*)arg)->size ); + fprintf(v4l1_log_file,"frames %d\n",( (struct video_mbuf*)arg)->frames ); + break; + } + fprintf(v4l1_log_file, "result == %d\n", result); + fflush(v4l1_log_file); +} diff --git a/v4l2-apps/libv4l/libv4l1/v4l1compat.c b/v4l2-apps/libv4l/libv4l1/v4l1compat.c new file mode 100644 index 000000000..e4293d2f9 --- /dev/null +++ b/v4l2-apps/libv4l/libv4l1/v4l1compat.c @@ -0,0 +1,127 @@ +/* +# open/close/ioctl/mmap/munmap library call wrapper doing v4l1 api emulation +# for v4l2 devices + +# (C) 2008 Hans de Goede + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#define _LARGEFILE64_SOURCE 1 + +#include +#include +#include +#include + +#include +#include + +/* Check that open/read/mmap is not a define */ +#if defined open || defined read || defined mmap +#error open/read/mmap is a prepocessor macro !! +#endif + +#if __GNUC__ >= 4 +#define LIBV4L_PUBLIC __attribute__ ((visibility("default"))) +#else +#define LIBV4L_PUBLIC +#endif + +LIBV4L_PUBLIC int open (const char *file, int oflag, ...) +{ + int fd; + + if (oflag & O_CREAT) + { + va_list ap; + mode_t mode; + + va_start (ap, oflag); + mode = va_arg (ap, mode_t); + + fd = v4l1_open(file, oflag, mode); + + va_end(ap); + } else + fd = v4l1_open(file, oflag); + + return fd; +} + +LIBV4L_PUBLIC int open64 (const char *file, int oflag, ...) +{ + int fd; + + if (oflag & O_CREAT) + { + va_list ap; + mode_t mode; + + va_start (ap, oflag); + mode = va_arg (ap, mode_t); + + fd = v4l1_open(file, oflag | O_LARGEFILE, mode); + + va_end(ap); + } else + fd = v4l1_open(file, oflag | O_LARGEFILE); + + return fd; +} + +LIBV4L_PUBLIC int close(int fd) { + return v4l1_close(fd); +} + +LIBV4L_PUBLIC int dup(int fd) +{ + return v4l1_dup(fd); +} + +LIBV4L_PUBLIC int ioctl (int fd, unsigned long int request, ...) +{ + void *arg; + va_list ap; + + va_start (ap, request); + arg = va_arg (ap, void *); + va_end (ap); + + return v4l1_ioctl (fd, request, arg); +} + +LIBV4L_PUBLIC ssize_t read(int fd, void* buffer, size_t n) +{ + return v4l1_read (fd, buffer, n); +} + +LIBV4L_PUBLIC void *mmap(void *start, size_t length, int prot, int flags, int fd, + __off_t offset) +{ + return v4l1_mmap(start, length, prot, flags, fd, offset); +} + +LIBV4L_PUBLIC void *mmap64(void *start, size_t length, int prot, int flags, int fd, + __off64_t offset) +{ + return v4l1_mmap(start, length, prot, flags, fd, offset); +} + +LIBV4L_PUBLIC int munmap(void *start, size_t length) +{ + return v4l1_munmap(start, length); +} + diff --git a/v4l2-apps/libv4l/libv4l2/Makefile b/v4l2-apps/libv4l/libv4l2/Makefile new file mode 100644 index 000000000..648d27c0c --- /dev/null +++ b/v4l2-apps/libv4l/libv4l2/Makefile @@ -0,0 +1,82 @@ +override CPPFLAGS += -I../include -I../../../include -fvisibility=hidden + +CFLAGS := -g -O1 +CFLAGS += -Wall -Wno-unused -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes + +LIBS = -lpthread + +V4L2_OBJS = libv4l2.o log.o +V4L2CONVERT = v4l2convert.so +V4L2CONVERT_O = v4l2convert.o libv4l2.so +TARGETS = $(V4L2_LIB) libv4l2.pc +INCLUDES = ../include/libv4l2.h + +ifeq ($(LINKTYPE),static) +V4L2_LIB = libv4l2.a +else +V4L2_LIB = libv4l2.so +V4L2_OBJS += ../libv4lconvert/libv4lconvert.so +TARGETS += $(V4L2CONVERT) +override CPPFLAGS += -fPIC +endif + +ifeq ($(LIB_RELEASE),) +LIB_RELEASE = 0 +endif + +ifeq ($(PREFIX),) +PREFIX = /usr/local +endif + +ifeq ($(LIBDIR),) +LIBDIR = $(PREFIX)/lib +endif + +all: $(TARGETS) + +$(V4L2_LIB): $(V4L2_OBJS) + +$(V4L2CONVERT): $(V4L2CONVERT_O) $(V4L2_LIB) + +libv4l2.pc: + @echo prefix=$(PREFIX) > libv4l2.pc + @echo libdir=$(LIBDIR) >> libv4l2.pc + @echo >> libv4l2.pc + @echo 'Name: libv4l2' >> libv4l2.pc + @echo 'Description: v4l2 device access library' >> libv4l2.pc + @echo 'Version: '$(V4L2_LIB_VERSION) >> libv4l2.pc + @echo 'Requires: libv4lconvert' >> libv4l2.pc + @echo 'Libs: -L$${libdir} -lv4l2' >> libv4l2.pc + @echo 'Libs.private: -lpthread' >> libv4l2.pc + @echo 'Cflags: -I$${prefix}/include' >> libv4l2.pc + +install: all + mkdir -p $(DESTDIR)$(PREFIX)/include + install -p -m 644 $(INCLUDES) $(DESTDIR)$(PREFIX)/include +ifeq ($(LINKTYPE),static) + mkdir -p $(DESTDIR)$(LIBDIR) + install -m 644 $(V4L2_LIB) $(DESTDIR)$(LIBDIR) +else + mkdir -p $(DESTDIR)$(LIBDIR)/libv4l + install -m 755 $(V4L2_LIB).$(LIB_RELEASE) $(DESTDIR)$(LIBDIR) + cd $(DESTDIR)$(LIBDIR) && \ + ln -f -s $(V4L2_LIB).$(LIB_RELEASE) $(V4L2_LIB) + install -m 755 $(V4L2CONVERT).$(LIB_RELEASE) \ + $(DESTDIR)$(LIBDIR)/libv4l/$(V4L2CONVERT) +endif + mkdir -p $(DESTDIR)$(LIBDIR)/pkgconfig + install -m 644 libv4l2.pc $(DESTDIR)$(LIBDIR)/pkgconfig + +clean:: + rm -f *.a *.so* *.o *.d libv4l2.pc log *~ + +%.o: %.c + $(CC) -c -MMD $(CPPFLAGS) $(CFLAGS) -o $@ $< + +%.so: + $(CC) -shared $(LDFLAGS) -Wl,-soname,$@.$(LIB_RELEASE) -o $@.$(LIB_RELEASE) $^ $(LIBS) + ln -f -s $@.$(LIB_RELEASE) $@ + +%.a: + $(AR) cqs $@ $^ + diff --git a/v4l2-apps/libv4l/libv4l2/libv4l2-priv.h b/v4l2-apps/libv4l/libv4l2/libv4l2-priv.h new file mode 100644 index 000000000..8724832e1 --- /dev/null +++ b/v4l2-apps/libv4l/libv4l2/libv4l2-priv.h @@ -0,0 +1,95 @@ +/* +# (C) 2008 Hans de Goede + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __LIBV4L2_PRIV_H +#define __LIBV4L2_PRIV_H + +#include +#include +#include /* includes videodev2.h for us */ + +/* On 32 bits archs we always use mmap2, on 64 bits archs there is no mmap2 */ +#ifdef __NR_mmap2 +#define SYS_mmap2 __NR_mmap2 +#define MMAP2_PAGE_SHIFT 12 +#else +#define SYS_mmap2 SYS_mmap +#define MMAP2_PAGE_SHIFT 0 +#endif + +#define V4L2_MAX_DEVICES 16 +/* Warning when making this larger the frame_queued and frame_mapped members of + the v4l2_dev_info struct can no longer be a bitfield, so the code needs to + be adjusted! */ +#define V4L2_MAX_NO_FRAMES 32 +#define V4L2_DEFAULT_NREADBUFFERS 4 +#define V4L2_FRAME_BUF_SIZE (4096 * 4096) + +#define V4L2_LOG_ERR(...) \ + do { \ + if (v4l2_log_file) { \ + fprintf(v4l2_log_file, "libv4l2: error " __VA_ARGS__); \ + fflush(v4l2_log_file); \ + } else \ + fprintf(stderr, "libv4l2: error " __VA_ARGS__); \ + } while(0) + +#define V4L2_LOG_WARN(...) \ + do { \ + if (v4l2_log_file) { \ + fprintf(v4l2_log_file, "libv4l2: warning " __VA_ARGS__); \ + fflush(v4l2_log_file); \ + } else \ + fprintf(stderr, "libv4l2: warning " __VA_ARGS__); \ + } while(0) + +#define V4L2_LOG(...) \ + do { \ + if (v4l2_log_file) { \ + fprintf(v4l2_log_file, "libv4l2: " __VA_ARGS__); \ + fflush(v4l2_log_file); \ + } \ + } while(0) + +#define MIN(a,b) (((a)<(b))?(a):(b)) + +struct v4l2_dev_info { + int fd; + int flags; + int open_count; + /* actually format of the cam */ + struct v4l2_format src_fmt; + /* fmt as seen by the application (iow after conversion) */ + struct v4l2_format dest_fmt; + pthread_mutex_t stream_lock; + unsigned int no_frames; + unsigned int nreadbuffers; + struct v4lconvert_data *convert; + unsigned char *convert_mmap_buf; + /* Frame bookkeeping is only done when in read or mmap-conversion mode */ + unsigned char *frame_pointers[V4L2_MAX_NO_FRAMES]; + int frame_sizes[V4L2_MAX_NO_FRAMES]; + int frame_queued; /* 1 status bit per frame */ + /* mapping tracking of our fake (converting mmap) frame buffers */ + unsigned char frame_map_count[V4L2_MAX_NO_FRAMES]; +}; + +/* From log.c */ +void v4l2_log_ioctl(unsigned long int request, void *arg, int result); + +#endif diff --git a/v4l2-apps/libv4l/libv4l2/libv4l2.c b/v4l2-apps/libv4l/libv4l2/libv4l2.c new file mode 100644 index 000000000..b4a10afac --- /dev/null +++ b/v4l2-apps/libv4l/libv4l2/libv4l2.c @@ -0,0 +1,1145 @@ +/* +# (C) 2008 Hans de Goede + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +/* MAKING CHANGES TO THIS FILE?? READ THIS FIRST!!! + + This file implements libv4l2, which offers v4l2_ prefixed versions of + open/close/etc. The API is 100% the same as directly opening /dev/videoX + using regular open/close/etc, the big difference is that format conversion + is done if necessary when capturing. That is if you (try to) set a capture + format which is not supported by the cam, but is supported by libv4lconvert, + then the try_fmt / set_fmt will succeed as if the cam supports the format + and on dqbuf / read the data will be converted for you and returned in + the request format. + + Important note to people making changes to this file: All functions + (v4l2_close, v4l2_ioctl, etc.) are designed to function as their regular + counterpart when they get passed a fd that is not "registered" by libv4l2, + there are 2 reasons for this: + 1) This allows us to get completely out of the way when dealing with non + capture devices. + 2) libv4l2 is the base of the v4l2convert.so wrapper lib, which is a .so + which can be LD_PRELOAD-ed and the overrules the libc's open/close/etc, + and when opening /dev/videoX or /dev/v4l/ calls v4l2_open. Because we + behave as the regular counterpart when the fd is not known (instead of say + throwing an error), v4l2convert.so can simply call the v4l2_ prefixed + function for all wrapped functions (except for v4l2_open which will fail + when not called on a v4l2 device). This way the wrapper does not have to + keep track of which fd's are being handled by libv4l2, as libv4l2 already + keeps track of this itself. + + This also means that libv4l2 may not use any of the regular functions + it mimics, as for example open could be a symbol in v4l2convert.so, which + in turn will call v4l2_open, so therefor v4l2_open (for example) may not + use the regular open()! + + Another important note: libv4l2 does conversion for capture usage only, if + any calls are made which are passed a v4l2_buffer or v4l2_format with a + v4l2_buf_type which is different from V4L2_BUF_TYPE_VIDEO_CAPTURE, then + the v4l2_ methods behave exactly the same as their regular counterparts. + When modifications are made, one should be carefull that this behavior is + preserved. +*/ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "libv4l2.h" +#include "libv4l2-priv.h" + +/* Note these flags are stored together with the flags passed to v4l2_fd_open() + in v4l2_dev_info's flags member, so care should be taken that the do not + use the same bits! */ +#define V4L2_STREAMON 0x0100 +#define V4L2_BUFFERS_REQUESTED_BY_READ 0x0200 +#define V4L2_STREAM_CONTROLLED_BY_READ 0x0400 +#define V4L2_SUPPORTS_READ 0x0800 + +#define V4L2_MMAP_OFFSET_MAGIC 0xABCDEF00u + +static pthread_mutex_t v4l2_open_mutex = PTHREAD_MUTEX_INITIALIZER; +static struct v4l2_dev_info devices[V4L2_MAX_DEVICES] = { { .fd = -1 }, + { .fd = -1 }, { .fd = -1 }, { .fd = -1 }, { .fd = -1 }, { .fd = -1 }, + { .fd = -1 }, { .fd = -1 }, { .fd = -1 }, { .fd = -1 }, { .fd = -1 }, + { .fd = -1 }, { .fd = -1 }, { .fd = -1 }, { .fd = -1 }, { .fd = -1 }}; +static int devices_used = 0; + + +static int v4l2_request_read_buffers(int index) +{ + int result; + struct v4l2_requestbuffers req; + + /* Note we re-request the buffers if they are already requested as the format + and thus the needed buffersize may have changed. */ + req.count = (devices[index].no_frames)? devices[index].no_frames: + devices[index].nreadbuffers; + req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + req.memory = V4L2_MEMORY_MMAP; + if ((result = syscall(SYS_ioctl, devices[index].fd, VIDIOC_REQBUFS, &req)) < 0){ + int saved_err = errno; + V4L2_LOG_ERR("requesting %u buffers: %s\n", req.count, strerror(errno)); + errno = saved_err; + return result; + } + + if (!devices[index].no_frames && req.count) + devices[index].flags |= V4L2_BUFFERS_REQUESTED_BY_READ; + + devices[index].no_frames = MIN(req.count, V4L2_MAX_NO_FRAMES); + return 0; +} + +static void v4l2_unrequest_read_buffers(int index) +{ + struct v4l2_requestbuffers req; + + if (!(devices[index].flags & V4L2_BUFFERS_REQUESTED_BY_READ) || + devices[index].no_frames == 0) + return; + + /* (Un)Request buffers, note not all driver support this, and those + who do not support it don't need it. */ + req.count = 0; + req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + req.memory = V4L2_MEMORY_MMAP; + if(syscall(SYS_ioctl, devices[index].fd, VIDIOC_REQBUFS, &req) < 0) + return; + + devices[index].no_frames = MIN(req.count, V4L2_MAX_NO_FRAMES); + if (devices[index].no_frames == 0) + devices[index].flags &= ~V4L2_BUFFERS_REQUESTED_BY_READ; +} + +static int v4l2_map_buffers(int index) +{ + int result = 0; + unsigned int i; + struct v4l2_buffer buf; + + for (i = 0; i < devices[index].no_frames; i++) { + if (devices[index].frame_pointers[i] != MAP_FAILED) + continue; + + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = i; + result = syscall(SYS_ioctl, devices[index].fd, VIDIOC_QUERYBUF, &buf); + if (result) { + int saved_err = errno; + V4L2_LOG_ERR("querying buffer %u: %s\n", i, strerror(errno)); + errno = saved_err; + break; + } + + devices[index].frame_pointers[i] = (void *)syscall(SYS_mmap2, NULL, + (size_t)buf.length, PROT_READ|PROT_WRITE, MAP_SHARED, devices[index].fd, + (__off_t)(buf.m.offset >> MMAP2_PAGE_SHIFT)); + if (devices[index].frame_pointers[i] == MAP_FAILED) { + int saved_err = errno; + V4L2_LOG_ERR("mmapping buffer %u: %s\n", i, strerror(errno)); + errno = saved_err; + result = -1; + break; + } + V4L2_LOG("mapped buffer %u at %p\n", i, + devices[index].frame_pointers[i]); + + devices[index].frame_sizes[i] = buf.length; + } + + return result; +} + +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) { + syscall(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); + } + } +} + +static int v4l2_streamon(int index) +{ + int result; + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + if (!(devices[index].flags & V4L2_STREAMON)) { + if ((result = syscall(SYS_ioctl, devices[index].fd, VIDIOC_STREAMON, + &type))) { + int saved_err = errno; + V4L2_LOG_ERR("turning on stream: %s\n", strerror(errno)); + errno = saved_err; + return result; + } + devices[index].flags |= V4L2_STREAMON; + } + + return 0; +} + +static int v4l2_streamoff(int index) +{ + int result; + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + if (devices[index].flags & V4L2_STREAMON) { + if ((result = syscall(SYS_ioctl, devices[index].fd, VIDIOC_STREAMOFF, + &type))) { + int saved_err = errno; + V4L2_LOG_ERR("turning off stream: %s\n", strerror(errno)); + errno = saved_err; + return result; + } + devices[index].flags &= ~V4L2_STREAMON; + + /* Stream off also unqueues all our buffers! */ + devices[index].frame_queued = 0; + } + + return 0; +} + +static int v4l2_queue_read_buffer(int index, int buffer_index) +{ + int result; + struct v4l2_buffer buf; + + if (devices[index].frame_queued & (1 << buffer_index)) + return 0; + + memset(&buf, 0, sizeof(buf)); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = buffer_index; + if ((result = syscall(SYS_ioctl, devices[index].fd, VIDIOC_QBUF, &buf))) { + int saved_err = errno; + V4L2_LOG_ERR("queuing buf %d: %s\n", buffer_index, strerror(errno)); + errno = saved_err; + return result; + } + + devices[index].frame_queued |= 1 << buffer_index; + return 0; +} + +static int v4l2_dequeue_and_convert(int index, struct v4l2_buffer *buf, + unsigned char *dest, int dest_size) +{ + const int max_tries = 10; + int result, tries = max_tries; + + /* Make sure we have the real v4l2 buffers mapped */ + if ((result = v4l2_map_buffers(index))) + return result; + + do { + if ((result = syscall(SYS_ioctl, devices[index].fd, VIDIOC_DQBUF, buf))) { + int saved_err = errno; + V4L2_LOG_ERR("dequeuing buf: %s\n", strerror(errno)); + errno = saved_err; + return result; + } + + devices[index].frame_queued &= ~(1 << buf->index); + + result = v4lconvert_convert(devices[index].convert, + &devices[index].src_fmt, &devices[index].dest_fmt, + devices[index].frame_pointers[buf->index], + buf->bytesused, dest ? dest : (devices[index].convert_mmap_buf + + buf->index * V4L2_FRAME_BUF_SIZE), dest_size); + + if (result < 0) { + int saved_err = errno; + + if(errno == EAGAIN) + V4L2_LOG("warning error while converting frame data: %s\n", + v4lconvert_get_error_message(devices[index].convert)); + else + V4L2_LOG_ERR("converting / decoding frame data: %s\n", + v4lconvert_get_error_message(devices[index].convert)); + + v4l2_queue_read_buffer(index, buf->index); + errno = saved_err; + } + tries--; + } while (result < 0 && errno == EAGAIN && tries); + + if (result < 0 && errno == EAGAIN) { + V4L2_LOG_ERR("got %d consecutive frame decode errors, last error: %s\n", + max_tries, v4lconvert_get_error_message(devices[index].convert)); + } + + return result; +} + +static int v4l2_queue_read_buffers(int index) +{ + unsigned int i; + int last_error = EIO, queued = 0; + + for (i = 0; i < devices[index].no_frames; i++) { + /* Don't queue unmapped buffers (should never happen) */ + if (devices[index].frame_pointers[i] != MAP_FAILED) { + if (v4l2_queue_read_buffer(index, i)) { + last_error = errno; + continue; + } + queued++; + } + } + + if (!queued) { + errno = last_error; + return -1; + } + return 0; +} + +static int v4l2_activate_read_stream(int index) +{ + int result; + + if ((result = v4l2_request_read_buffers(index))) + return result; + + if ((result = v4l2_map_buffers(index))) + return result; + + if ((result = v4l2_queue_read_buffers(index))) + return result; + + devices[index].flags |= V4L2_STREAM_CONTROLLED_BY_READ; + + return result = v4l2_streamon(index); +} + +static int v4l2_deactivate_read_stream(int index) +{ + int result; + + if ((result = v4l2_streamoff(index))) + return result; + + /* No need to unqueue our buffers, streamoff does that for us */ + + v4l2_unmap_buffers(index); + + v4l2_unrequest_read_buffers(index); + + devices[index].flags &= ~V4L2_STREAM_CONTROLLED_BY_READ; + + return 0; +} + +static int v4l2_buffers_mapped(int index) +{ + unsigned int i; + + if (devices[index].src_fmt.fmt.pix.pixelformat == + devices[index].dest_fmt.fmt.pix.pixelformat) { + /* Normal (no conversion) mode */ + struct v4l2_buffer buf; + + for (i = 0; i < devices[index].no_frames; i++) { + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = i; + if (syscall(SYS_ioctl, devices[index].fd, VIDIOC_QUERYBUF, &buf)) { + int saved_err = errno; + V4L2_LOG_ERR("querying buffer %u: %s\n", i, strerror(errno)); + errno = saved_err; + break; + } + if (buf.flags & V4L2_BUF_FLAG_MAPPED) + break; + } + } else { + /* Conversion mode */ + for (i = 0; i < devices[index].no_frames; i++) + if (devices[index].frame_map_count[i]) + break; + } + + if (i != devices[index].no_frames) + V4L2_LOG("v4l2_buffers_mapped(): buffers still mapped\n"); + + return i != devices[index].no_frames; +} + + +int v4l2_open (const char *file, int oflag, ...) +{ + int fd; + + /* original open code */ + if (oflag & O_CREAT) + { + va_list ap; + mode_t mode; + + va_start (ap, oflag); + mode = va_arg (ap, mode_t); + + fd = syscall(SYS_open, file, oflag, mode); + + va_end(ap); + } + else + fd = syscall(SYS_open, file, oflag); + /* end of original open code */ + + if (fd == -1) + return fd; + + if (v4l2_fd_open(fd, 0) == -1) { + int saved_err = errno; + syscall(SYS_close, fd); + errno = saved_err; + return -1; + } + + return fd; +} + +int v4l2_fd_open(int fd, int v4l2_flags) +{ + int i, index; + char *lfname; + struct v4l2_capability cap; + struct v4l2_format fmt; + struct v4lconvert_data *convert; + + /* If no log file was set by the app, see if one was specified through the + environment */ + if (!v4l2_log_file && (lfname = getenv("LIBV4L2_LOG_FILENAME"))) + v4l2_log_file = fopen(lfname, "w"); + + /* check that this is an v4l2 device */ + if (syscall(SYS_ioctl, fd, VIDIOC_QUERYCAP, &cap)) { + int saved_err = errno; + V4L2_LOG_ERR("getting capabilities: %s\n", strerror(errno)); + errno = saved_err; + return -1; + } + + /* we only add functionality for video capture devices, and we do not + handle devices which don't do mmap */ + if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE) || + !(cap.capabilities & V4L2_CAP_STREAMING)) + return fd; + + /* Get current cam format */ + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (syscall(SYS_ioctl, fd, VIDIOC_G_FMT, &fmt)) { + int saved_err = errno; + V4L2_LOG_ERR("getting pixformat: %s\n", strerror(errno)); + errno = saved_err; + return -1; + } + + /* init libv4lconvert */ + if (!(convert = v4lconvert_create(fd))) + return -1; + + /* So we have a v4l2 capture device, register it in our devices array */ + pthread_mutex_lock(&v4l2_open_mutex); + for (index = 0; index < V4L2_MAX_DEVICES; index++) + if(devices[index].fd == -1) { + devices[index].fd = fd; + break; + } + pthread_mutex_unlock(&v4l2_open_mutex); + + if (index == V4L2_MAX_DEVICES) { + V4L2_LOG_ERR("attempting to open more then %d video devices\n", + V4L2_MAX_DEVICES); + errno = EBUSY; + return -1; + } + + devices[index].flags = v4l2_flags; + if (cap.capabilities & V4L2_CAP_READWRITE) + devices[index].flags |= V4L2_SUPPORTS_READ; + devices[index].open_count = 1; + devices[index].src_fmt = fmt; + devices[index].dest_fmt = fmt; + + pthread_mutex_init(&devices[index].stream_lock, NULL); + + devices[index].no_frames = 0; + devices[index].nreadbuffers = V4L2_DEFAULT_NREADBUFFERS; + devices[index].convert = convert; + devices[index].convert_mmap_buf = MAP_FAILED; + for (i = 0; i < V4L2_MAX_NO_FRAMES; i++) { + devices[index].frame_pointers[i] = MAP_FAILED; + devices[index].frame_map_count[i] = 0; + } + devices[index].frame_queued = 0; + + if (index >= devices_used) + devices_used = index + 1; + + V4L2_LOG("open: %d\n", fd); + + return fd; +} + +/* Is this an fd for which we are emulating v4l1 ? */ +static int v4l2_get_index(int fd) +{ + int index; + + /* We never handle fd -1 */ + if (fd == -1) + return -1; + + for (index = 0; index < devices_used; index++) + if (devices[index].fd == fd) + break; + + if (index == devices_used) + return -1; + + return index; +} + + +int v4l2_close(int fd) +{ + int index, result; + + if ((index = v4l2_get_index(fd)) == -1) + return syscall(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); + v4lconvert_destroy(devices[index].convert); + 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 + syscall(SYS_munmap, devices[index].convert_mmap_buf, + devices[index].no_frames * V4L2_FRAME_BUF_SIZE); + devices[index].convert_mmap_buf = 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; + + /* Since we've marked the fd as no longer used, and freed the resources, + redo the close in case it was interrupted */ + do { + result = syscall(SYS_close, fd); + } while (result == -1 && errno == EINTR); + + V4L2_LOG("close: %d\n", fd); + + return result; +} + +int v4l2_dup(int fd) +{ + int index; + + if ((index = v4l2_get_index(fd)) == -1) + return syscall(SYS_dup, fd); + + devices[index].open_count++; + + return fd; +} + +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 */ + syscall(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; +} + +int v4l2_ioctl (int fd, unsigned long int request, ...) +{ + void *arg; + va_list ap; + int result, converting, index, saved_err; + int is_capture_request = 0, stream_needs_locking = 0; + + va_start (ap, request); + arg = va_arg (ap, void *); + va_end (ap); + + if ((index = v4l2_get_index(fd)) == -1) + return syscall(SYS_ioctl, fd, request, arg); + + /* Appearantly the kernel and / or glibc ignore the 32 most significant bits + when long = 64 bits, and some applications pass an int holding the req to + ioctl, causing it to get sign extended, depending upon this behavior */ + request = (unsigned int)request; + + /* Is this a capture request and do we need to take the stream lock? */ + switch (request) { + case VIDIOC_QUERYCAP: + is_capture_request = 1; + break; + case VIDIOC_ENUM_FMT: + if (((struct v4l2_fmtdesc *)arg)->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && + (devices[index].flags & V4L2_ENABLE_ENUM_FMT_EMULATION)) + is_capture_request = 1; + break; + case VIDIOC_ENUM_FRAMESIZES: + case VIDIOC_ENUM_FRAMEINTERVALS: + if (devices[index].flags & V4L2_ENABLE_ENUM_FMT_EMULATION) + is_capture_request = 1; + break; + case VIDIOC_TRY_FMT: + if (((struct v4l2_format *)arg)->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) + is_capture_request = 1; + break; + case VIDIOC_S_FMT: + case VIDIOC_G_FMT: + if (((struct v4l2_format *)arg)->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + is_capture_request = 1; + stream_needs_locking = 1; + } + break; + case VIDIOC_REQBUFS: + if (((struct v4l2_requestbuffers *)arg)->type == + V4L2_BUF_TYPE_VIDEO_CAPTURE) { + is_capture_request = 1; + stream_needs_locking = 1; + } + break; + case VIDIOC_QUERYBUF: + case VIDIOC_QBUF: + case VIDIOC_DQBUF: + if (((struct v4l2_buffer *)arg)->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + is_capture_request = 1; + stream_needs_locking = 1; + } + break; + case VIDIOC_STREAMON: + case VIDIOC_STREAMOFF: + if (*((enum v4l2_buf_type *)arg) == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + is_capture_request = 1; + stream_needs_locking = 1; + } + } + + if (!is_capture_request) { + result = syscall(SYS_ioctl, fd, request, arg); + saved_err = errno; + v4l2_log_ioctl(request, arg, result); + errno = saved_err; + return result; + } + + + if (stream_needs_locking) + pthread_mutex_lock(&devices[index].stream_lock); + + converting = v4lconvert_needs_conversion(devices[index].convert, + &devices[index].src_fmt, &devices[index].dest_fmt); + + switch (request) { + case VIDIOC_QUERYCAP: + { + struct v4l2_capability *cap = arg; + + result = syscall(SYS_ioctl, devices[index].fd, VIDIOC_QUERYCAP, cap); + if (result == 0) + /* We always support read() as we fake it using mmap mode */ + cap->capabilities |= V4L2_CAP_READWRITE; + } + break; + + case VIDIOC_ENUM_FMT: + result = v4lconvert_enum_fmt(devices[index].convert, arg); + break; + + case VIDIOC_ENUM_FRAMESIZES: + result = v4lconvert_enum_framesizes(devices[index].convert, arg); + break; + + case VIDIOC_ENUM_FRAMEINTERVALS: + result = v4lconvert_enum_frameintervals(devices[index].convert, arg); + break; + + case VIDIOC_TRY_FMT: + result = v4lconvert_try_format(devices[index].convert, arg, NULL); + break; + + case VIDIOC_S_FMT: + { + struct v4l2_format src_fmt, *dest_fmt = arg; + + if (!memcmp(&devices[index].dest_fmt, dest_fmt, sizeof(*dest_fmt))) { + result = 0; + break; + } + + if (devices[index].flags & V4L2_DISABLE_CONVERSION) { + result = syscall(SYS_ioctl, devices[index].fd, VIDIOC_TRY_FMT, + dest_fmt); + src_fmt = *dest_fmt; + } else { + result = v4lconvert_try_format(devices[index].convert, dest_fmt, + &src_fmt); + } + + if (result) + break; + + if (src_fmt.fmt.pix.pixelformat != dest_fmt->fmt.pix.pixelformat && + v4l2_log_file) { + int pixfmt = src_fmt.fmt.pix.pixelformat; + + fprintf(v4l2_log_file, "VIDIOC_S_FMT converting from: %c%c%c%c\n", + pixfmt & 0xff, + (pixfmt >> 8) & 0xff, + (pixfmt >> 16) & 0xff, + pixfmt >> 24); + } + + /* Maybe after try format has adjusted width/height etc, to whats + available nothing has changed (on the cam side) ? */ + if (!memcmp(&devices[index].src_fmt, &src_fmt, sizeof(src_fmt))) { + devices[index].dest_fmt = *dest_fmt; + result = 0; + break; + } + + if ((result = v4l2_check_buffer_change_ok(index))) + break; + + result = syscall(SYS_ioctl, devices[index].fd, VIDIOC_S_FMT, &src_fmt); + if (result) { + saved_err = errno; + V4L2_LOG_ERR("setting pixformat: %s\n", strerror(errno)); + /* Report to the app dest_fmt has not changed */ + *dest_fmt = devices[index].dest_fmt; + errno = saved_err; + break; + } + + devices[index].src_fmt = src_fmt; + devices[index].dest_fmt = *dest_fmt; + } + break; + + case VIDIOC_G_FMT: + { + struct v4l2_format* fmt = arg; + + *fmt = devices[index].dest_fmt; + result = 0; + } + break; + + case VIDIOC_REQBUFS: + { + struct v4l2_requestbuffers *req = arg; + + /* IMPROVEME (maybe?) add support for userptr's? */ + if (req->memory != V4L2_MEMORY_MMAP) { + errno = EINVAL; + result = -1; + break; + } + + if ((result = v4l2_check_buffer_change_ok(index))) + break; + + /* No more buffers then we can manage please */ + if (req->count > V4L2_MAX_NO_FRAMES) + req->count = V4L2_MAX_NO_FRAMES; + + result = syscall(SYS_ioctl, devices[index].fd, VIDIOC_REQBUFS, req); + if (result < 0) + break; + result = 0; /* some drivers return the number of buffers on success */ + + devices[index].no_frames = MIN(req->count, V4L2_MAX_NO_FRAMES); + devices[index].flags &= ~V4L2_BUFFERS_REQUESTED_BY_READ; + } + break; + + case VIDIOC_QUERYBUF: + { + struct v4l2_buffer *buf = arg; + + if (devices[index].flags & V4L2_STREAM_CONTROLLED_BY_READ) + if ((result = v4l2_deactivate_read_stream(index))) + break; + + /* Do a real query even when converting to let the driver fill in + things like buf->field */ + result = syscall(SYS_ioctl, devices[index].fd, VIDIOC_QUERYBUF, buf); + if (result || !converting) + break; + + buf->m.offset = V4L2_MMAP_OFFSET_MAGIC | buf->index; + buf->length = V4L2_FRAME_BUF_SIZE; + if (devices[index].frame_map_count[buf->index]) + buf->flags |= V4L2_BUF_FLAG_MAPPED; + else + buf->flags &= ~V4L2_BUF_FLAG_MAPPED; + } + break; + + case VIDIOC_QBUF: + if (devices[index].flags & V4L2_STREAM_CONTROLLED_BY_READ) + if ((result = v4l2_deactivate_read_stream(index))) + break; + + /* With some drivers the buffers must be mapped before queuing */ + if (converting) + if ((result = v4l2_map_buffers(index))) + break; + + result = syscall(SYS_ioctl, devices[index].fd, VIDIOC_QBUF, arg); + break; + + case VIDIOC_DQBUF: + { + struct v4l2_buffer *buf = arg; + + if (devices[index].flags & V4L2_STREAM_CONTROLLED_BY_READ) + if ((result = v4l2_deactivate_read_stream(index))) + break; + + if (!converting) { + result = syscall(SYS_ioctl, devices[index].fd, VIDIOC_DQBUF, buf); + if (result) { + int saved_err = errno; + V4L2_LOG_ERR("dequeuing buf: %s\n", strerror(errno)); + errno = saved_err; + } + break; + } + + /* An application can do a DQBUF before mmap-ing in the buffer, + but we need the buffer _now_ to write our converted data + to it! */ + if (devices[index].convert_mmap_buf == MAP_FAILED) { + devices[index].convert_mmap_buf = (void *)syscall(SYS_mmap2, + (size_t)( + devices[index].no_frames * + V4L2_FRAME_BUF_SIZE), + PROT_READ|PROT_WRITE, + MAP_ANONYMOUS|MAP_PRIVATE, + -1, 0); + if (devices[index].convert_mmap_buf == MAP_FAILED) { + saved_err = errno; + V4L2_LOG_ERR("allocating conversion buffer\n"); + errno = saved_err; + result = -1; + break; + } + } + + result = v4l2_dequeue_and_convert(index, buf, 0, V4L2_FRAME_BUF_SIZE); + if (result < 0) + break; + + buf->bytesused = result; + buf->m.offset = V4L2_MMAP_OFFSET_MAGIC | buf->index; + buf->length = V4L2_FRAME_BUF_SIZE; + if (devices[index].frame_map_count[buf->index]) + buf->flags |= V4L2_BUF_FLAG_MAPPED; + else + buf->flags &= ~V4L2_BUF_FLAG_MAPPED; + + result = 0; + } + break; + + case VIDIOC_STREAMON: + case VIDIOC_STREAMOFF: + if (devices[index].flags & V4L2_STREAM_CONTROLLED_BY_READ) + if ((result = v4l2_deactivate_read_stream(index))) + break; + + if (request == VIDIOC_STREAMON) + result = v4l2_streamon(index); + else + result = v4l2_streamoff(index); + break; + + default: + result = syscall(SYS_ioctl, fd, request, arg); + } + + if (stream_needs_locking) + pthread_mutex_unlock(&devices[index].stream_lock); + + saved_err = errno; + v4l2_log_ioctl(request, arg, result); + errno = saved_err; + + return result; +} + + +ssize_t v4l2_read (int fd, void* dest, size_t n) +{ + ssize_t result; + int index; + struct v4l2_buffer buf; + + if ((index = v4l2_get_index(fd)) == -1) + return syscall(SYS_read, fd, dest, n); + + pthread_mutex_lock(&devices[index].stream_lock); + + /* When not converting and the device supports read let the kernel handle + it */ + if ((devices[index].flags & V4L2_SUPPORTS_READ) && + !v4lconvert_needs_conversion(devices[index].convert, + &devices[index].src_fmt, &devices[index].dest_fmt)) { + result = syscall(SYS_read, fd, dest, n); + goto leave; + } + + if (!(devices[index].flags & V4L2_STREAM_CONTROLLED_BY_READ)) { + if ((devices[index].flags & V4L2_STREAMON) || + devices[index].frame_queued) { + errno = EBUSY; + result = -1; + goto leave; + } + if ((result = v4l2_activate_read_stream(index))) + goto leave; + } + + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + result = v4l2_dequeue_and_convert(index, &buf, dest, n); + + if (result >= 0) + v4l2_queue_read_buffer(index, buf.index); + +leave: + pthread_mutex_unlock(&devices[index].stream_lock); + + return result; +} + +void *v4l2_mmap(void *start, size_t length, int prot, int flags, int fd, + __off64_t offset) +{ + int index; + unsigned int buffer_index; + void *result; + + if ((index = v4l2_get_index(fd)) == -1 || + /* Check if the mmap data matches our answer to QUERY_BUF, if it doesn't + let the kernel handle it (to allow for mmap based non capture use) */ + start || length != V4L2_FRAME_BUF_SIZE || + ((unsigned int)offset & ~0xFFu) != V4L2_MMAP_OFFSET_MAGIC) { + if (index != -1) + V4L2_LOG("Passing mmap(%p, %d, ..., %x, through to the driver\n", + start, (int)length, (int)offset); + + if (offset & ((1 << MMAP2_PAGE_SHIFT) - 1)) { + errno = EINVAL; + return MAP_FAILED; + } + + return (void *)syscall(SYS_mmap2, start, length, prot, flags, fd, + (__off_t)(offset >> MMAP2_PAGE_SHIFT)); + } + + pthread_mutex_lock(&devices[index].stream_lock); + + buffer_index = offset & 0xff; + if (buffer_index >= devices[index].no_frames || + /* Got magic offset and not converting ?? */ + !v4lconvert_needs_conversion(devices[index].convert, + &devices[index].src_fmt, &devices[index].dest_fmt)) { + errno = EINVAL; + result = MAP_FAILED; + goto leave; + } + + if (devices[index].convert_mmap_buf == MAP_FAILED) { + devices[index].convert_mmap_buf = (void *)syscall(SYS_mmap2, NULL, + (size_t)( + devices[index].no_frames * + V4L2_FRAME_BUF_SIZE), + PROT_READ|PROT_WRITE, + MAP_ANONYMOUS|MAP_PRIVATE, + -1, 0); + if (devices[index].convert_mmap_buf == MAP_FAILED) { + int saved_err = errno; + V4L2_LOG_ERR("allocating conversion buffer\n"); + errno = saved_err; + result = MAP_FAILED; + goto leave; + } + } + + devices[index].frame_map_count[buffer_index]++; + + result = devices[index].convert_mmap_buf + + buffer_index * V4L2_FRAME_BUF_SIZE; + + V4L2_LOG("Fake (conversion) mmap buf %u, seen by app at: %p\n", + buffer_index, result); + +leave: + pthread_mutex_unlock(&devices[index].stream_lock); + + return result; +} + +int v4l2_munmap(void *_start, size_t length) +{ + int index; + unsigned int buffer_index; + unsigned char *start = _start; + + /* Is this memory ours? */ + if (start != MAP_FAILED && length == V4L2_FRAME_BUF_SIZE) { + for (index = 0; index < devices_used; index++) + if (devices[index].fd != -1 && + devices[index].convert_mmap_buf != MAP_FAILED && + start >= devices[index].convert_mmap_buf && + (start - devices[index].convert_mmap_buf) % length == 0) + break; + + if (index != devices_used) { + int unmapped = 0; + + pthread_mutex_lock(&devices[index].stream_lock); + + buffer_index = (start - devices[index].convert_mmap_buf) / length; + + /* Redo our checks now that we have the lock, things may have changed */ + if (devices[index].convert_mmap_buf != MAP_FAILED && + start >= devices[index].convert_mmap_buf && + (start - devices[index].convert_mmap_buf) % length == 0 && + buffer_index < devices[index].no_frames) { + if (devices[index].frame_map_count[buffer_index] > 0) + devices[index].frame_map_count[buffer_index]--; + unmapped = 1; + } + + pthread_mutex_unlock(&devices[index].stream_lock); + + if (unmapped) { + V4L2_LOG("v4l2 fake buffer munmap %p, %d\n", start, (int)length); + return 0; + } + } + } + + V4L2_LOG("v4l2 unknown munmap %p, %d\n", start, (int)length); + + return syscall(SYS_munmap, _start, length); +} + +/* Misc utility functions */ +int v4l2_set_control(int fd, int cid, int value) +{ + struct v4l2_queryctrl qctrl = { .id = cid }; + struct v4l2_control ctrl = { .id = cid }; + int result; + + if ((result = syscall(SYS_ioctl, fd, VIDIOC_QUERYCTRL, &qctrl))) + return result; + + if (!(qctrl.flags & V4L2_CTRL_FLAG_DISABLED) && + !(qctrl.flags & V4L2_CTRL_FLAG_GRABBED)) { + if (qctrl.type == V4L2_CTRL_TYPE_BOOLEAN) + ctrl.value = value? 1:0; + else + ctrl.value = (value * (qctrl.maximum - qctrl.minimum) + 32767) / 65535 + + qctrl.minimum; + + result = syscall(SYS_ioctl, fd, VIDIOC_S_CTRL, &ctrl); + } + + return result; +} + +int v4l2_get_control(int fd, int cid) +{ + struct v4l2_queryctrl qctrl = { .id = cid }; + struct v4l2_control ctrl = { .id = cid }; + + if (syscall(SYS_ioctl, fd, VIDIOC_QUERYCTRL, &qctrl)) + return 0; + + if (qctrl.flags & V4L2_CTRL_FLAG_DISABLED) + return 0; + + if (syscall(SYS_ioctl, fd, VIDIOC_G_CTRL, &ctrl)) + return 0; + + return ((ctrl.value - qctrl.minimum) * 65535 + + (qctrl.maximum - qctrl.minimum) / 2) / + (qctrl.maximum - qctrl.minimum); +} diff --git a/v4l2-apps/libv4l/libv4l2/log.c b/v4l2-apps/libv4l/libv4l2/log.c new file mode 100644 index 000000000..6237d55ec --- /dev/null +++ b/v4l2-apps/libv4l/libv4l2/log.c @@ -0,0 +1,148 @@ +/* +# (C) 2008 Hans de Goede + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +/* These headers are not needed by us, but by linux/videodev2.h, + which is broken on some systems and doesn't include them itself :( */ +#include +#include +/* end broken header workaround includes */ +#include +#include "libv4l2.h" +#include "libv4l2-priv.h" + +#define ARRAY_SIZE(x) (sizeof(x)/sizeof((x)[0])) + +FILE *v4l2_log_file = NULL; + +static const char *v4l2_ioctls[] = { + /* start v4l2 ioctls */ + [_IOC_NR(VIDIOC_QUERYCAP)] = "VIDIOC_QUERYCAP", + [_IOC_NR(VIDIOC_RESERVED)] = "VIDIOC_RESERVED", + [_IOC_NR(VIDIOC_ENUM_FMT)] = "VIDIOC_ENUM_FMT", + [_IOC_NR(VIDIOC_G_FMT)] = "VIDIOC_G_FMT", + [_IOC_NR(VIDIOC_S_FMT)] = "VIDIOC_S_FMT", + [_IOC_NR(VIDIOC_REQBUFS)] = "VIDIOC_REQBUFS", + [_IOC_NR(VIDIOC_QUERYBUF)] = "VIDIOC_QUERYBUF", + [_IOC_NR(VIDIOC_G_FBUF)] = "VIDIOC_G_FBUF", + [_IOC_NR(VIDIOC_S_FBUF)] = "VIDIOC_S_FBUF", + [_IOC_NR(VIDIOC_OVERLAY)] = "VIDIOC_OVERLAY", + [_IOC_NR(VIDIOC_QBUF)] = "VIDIOC_QBUF", + [_IOC_NR(VIDIOC_DQBUF)] = "VIDIOC_DQBUF", + [_IOC_NR(VIDIOC_STREAMON)] = "VIDIOC_STREAMON", + [_IOC_NR(VIDIOC_STREAMOFF)] = "VIDIOC_STREAMOFF", + [_IOC_NR(VIDIOC_G_PARM)] = "VIDIOC_G_PARM", + [_IOC_NR(VIDIOC_S_PARM)] = "VIDIOC_S_PARM", + [_IOC_NR(VIDIOC_G_STD)] = "VIDIOC_G_STD", + [_IOC_NR(VIDIOC_S_STD)] = "VIDIOC_S_STD", + [_IOC_NR(VIDIOC_ENUMSTD)] = "VIDIOC_ENUMSTD", + [_IOC_NR(VIDIOC_ENUMINPUT)] = "VIDIOC_ENUMINPUT", + [_IOC_NR(VIDIOC_G_CTRL)] = "VIDIOC_G_CTRL", + [_IOC_NR(VIDIOC_S_CTRL)] = "VIDIOC_S_CTRL", + [_IOC_NR(VIDIOC_G_TUNER)] = "VIDIOC_G_TUNER", + [_IOC_NR(VIDIOC_S_TUNER)] = "VIDIOC_S_TUNER", + [_IOC_NR(VIDIOC_G_AUDIO)] = "VIDIOC_G_AUDIO", + [_IOC_NR(VIDIOC_S_AUDIO)] = "VIDIOC_S_AUDIO", + [_IOC_NR(VIDIOC_QUERYCTRL)] = "VIDIOC_QUERYCTRL", + [_IOC_NR(VIDIOC_QUERYMENU)] = "VIDIOC_QUERYMENU", + [_IOC_NR(VIDIOC_G_INPUT)] = "VIDIOC_G_INPUT", + [_IOC_NR(VIDIOC_S_INPUT)] = "VIDIOC_S_INPUT", + [_IOC_NR(VIDIOC_G_OUTPUT)] = "VIDIOC_G_OUTPUT", + [_IOC_NR(VIDIOC_S_OUTPUT)] = "VIDIOC_S_OUTPUT", + [_IOC_NR(VIDIOC_ENUMOUTPUT)] = "VIDIOC_ENUMOUTPUT", + [_IOC_NR(VIDIOC_G_AUDOUT)] = "VIDIOC_G_AUDOUT", + [_IOC_NR(VIDIOC_S_AUDOUT)] = "VIDIOC_S_AUDOUT", + [_IOC_NR(VIDIOC_G_MODULATOR)] = "VIDIOC_G_MODULATOR", + [_IOC_NR(VIDIOC_S_MODULATOR)] = "VIDIOC_S_MODULATOR", + [_IOC_NR(VIDIOC_G_FREQUENCY)] = "VIDIOC_G_FREQUENCY", + [_IOC_NR(VIDIOC_S_FREQUENCY)] = "VIDIOC_S_FREQUENCY", + [_IOC_NR(VIDIOC_CROPCAP)] = "VIDIOC_CROPCAP", + [_IOC_NR(VIDIOC_G_CROP)] = "VIDIOC_G_CROP", + [_IOC_NR(VIDIOC_S_CROP)] = "VIDIOC_S_CROP", + [_IOC_NR(VIDIOC_G_JPEGCOMP)] = "VIDIOC_G_JPEGCOMP", + [_IOC_NR(VIDIOC_S_JPEGCOMP)] = "VIDIOC_S_JPEGCOMP", + [_IOC_NR(VIDIOC_QUERYSTD)] = "VIDIOC_QUERYSTD", + [_IOC_NR(VIDIOC_TRY_FMT)] = "VIDIOC_TRY_FMT", + [_IOC_NR(VIDIOC_ENUMAUDIO)] = "VIDIOC_ENUMAUDIO", + [_IOC_NR(VIDIOC_ENUMAUDOUT)] = "VIDIOC_ENUMAUDOUT", + [_IOC_NR(VIDIOC_G_PRIORITY)] = "VIDIOC_G_PRIORITY", + [_IOC_NR(VIDIOC_S_PRIORITY)] = "VIDIOC_S_PRIORITY", + [_IOC_NR(VIDIOC_G_SLICED_VBI_CAP)] = "VIDIOC_G_SLICED_VBI_CAP", + [_IOC_NR(VIDIOC_LOG_STATUS)] = "VIDIOC_LOG_STATUS", + [_IOC_NR(VIDIOC_G_EXT_CTRLS)] = "VIDIOC_G_EXT_CTRLS", + [_IOC_NR(VIDIOC_S_EXT_CTRLS)] = "VIDIOC_S_EXT_CTRLS", + [_IOC_NR(VIDIOC_TRY_EXT_CTRLS)] = "VIDIOC_TRY_EXT_CTRLS", +}; + +void v4l2_log_ioctl(unsigned long int request, void *arg, int result) +{ + const char *ioctl_str; + char buf[40]; + + if (!v4l2_log_file) + return; + + if (_IOC_TYPE(request) == 'V' && _IOC_NR(request) < ARRAY_SIZE(v4l2_ioctls)) + ioctl_str = v4l2_ioctls[_IOC_NR(request)]; + else { + snprintf(buf, sizeof(buf), "unknown request: %c %d\n", + (int)_IOC_TYPE(request), (int)_IOC_NR(request)); + ioctl_str = buf; + } + + fprintf(v4l2_log_file, "request == %s\n", ioctl_str); + + switch (request) { + case VIDIOC_G_FMT: + case VIDIOC_S_FMT: + case VIDIOC_TRY_FMT: + { + struct v4l2_format* fmt = arg; + int pixfmt = fmt->fmt.pix.pixelformat; + + if (fmt->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) { + fprintf(v4l2_log_file, " pixelformat: %c%c%c%c %ux%u\n", + pixfmt & 0xff, + (pixfmt >> 8) & 0xff, + (pixfmt >> 16) & 0xff, + pixfmt >> 24, + fmt->fmt.pix.width, + fmt->fmt.pix.height); + fprintf(v4l2_log_file, " field: %d bytesperline: %d imagesize%d\n", + (int)fmt->fmt.pix.field, (int)fmt->fmt.pix.bytesperline, + (int)fmt->fmt.pix.sizeimage); + fprintf(v4l2_log_file, " colorspace: %d, priv: %x\n", + (int)fmt->fmt.pix.colorspace, (int)fmt->fmt.pix.priv); + } + } + break; + case VIDIOC_REQBUFS: + { + struct v4l2_requestbuffers *req = arg; + + fprintf(v4l2_log_file, " count: %u type: %d memory: %d\n", + req->count, (int)req->type, (int)req->memory); + } + break; + } + + fprintf(v4l2_log_file, "result == %d\n", result); + fflush(v4l2_log_file); +} diff --git a/v4l2-apps/libv4l/libv4l2/v4l2convert.c b/v4l2-apps/libv4l/libv4l2/v4l2convert.c new file mode 100644 index 000000000..307a03ce5 --- /dev/null +++ b/v4l2-apps/libv4l/libv4l2/v4l2convert.c @@ -0,0 +1,166 @@ +/* +# open/close/ioctl/mmap/munmap library call wrapper doing format conversion +# for v4l2 applications which want to be able to simply capture bgr24 / yuv420 +# from v4l2 devices with more exotic frame formats. + +# (C) 2008 Hans de Goede + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# 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 +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#define _LARGEFILE64_SOURCE 1 + +#include +#include +#include +#include +#include +#include +#include +/* These headers are not needed by us, but by linux/videodev2.h, + which is broken on some systems and doesn't include them itself :( */ +#include +#include +#include +/* end broken header workaround includes */ +#include +#include + +/* Check that open/read/mmap is not a define */ +#if defined open || defined read || defined mmap +#error open/read/mmap is a prepocessor macro !! +#endif + +#if __GNUC__ >= 4 +#define LIBV4L_PUBLIC __attribute__ ((visibility("default"))) +#else +#define LIBV4L_PUBLIC +#endif + +LIBV4L_PUBLIC int open (const char *file, int oflag, ...) +{ + int fd; + struct v4l2_capability cap; + int v4l_device = 0; + + /* check if we're opening a video4linux2 device */ + if (!strncmp(file, "/dev/video", 10) || !strncmp(file, "/dev/v4l/", 9)) { + /* Some apps open the device read only, but we need rw rights as the + buffers *MUST* be mapped rw */ + oflag = (oflag & ~O_ACCMODE) | O_RDWR; + v4l_device = 1; + } + + /* original open code */ + if (oflag & O_CREAT) + { + va_list ap; + mode_t mode; + + va_start (ap, oflag); + mode = va_arg (ap, mode_t); + + fd = syscall(SYS_open, file, oflag, mode); + + va_end(ap); + } else + fd = syscall(SYS_open, file, oflag); + /* end of original open code */ + + if (fd == -1 || !v4l_device) + return fd; + + /* check that this is an v4l2 device, libv4l2 only supports v4l2 devices */ + if (syscall(SYS_ioctl, fd, VIDIOC_QUERYCAP, &cap)) + return fd; + + /* libv4l2 only adds functionality to capture capable devices */ + if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) + return fd; + + /* Try to Register with libv4l2 (in case of failure pass the fd to the + application as is) */ + v4l2_fd_open(fd, V4L2_ENABLE_ENUM_FMT_EMULATION); + + return fd; +} + +LIBV4L_PUBLIC int open64(const char *file, int oflag, ...) +{ + int fd; + + /* original open code */ + if (oflag & O_CREAT) + { + va_list ap; + mode_t mode; + + va_start (ap, oflag); + mode = va_arg (ap, mode_t); + + fd = open(file, oflag | O_LARGEFILE, mode); + + va_end(ap); + } else + fd = open(file, oflag | O_LARGEFILE); + /* end of original open code */ + + return fd; +} + +LIBV4L_PUBLIC int close(int fd) +{ + return v4l2_close(fd); +} + +LIBV4L_PUBLIC int dup(int fd) +{ + return v4l2_dup(fd); +} + +LIBV4L_PUBLIC int ioctl (int fd, unsigned long int request, ...) +{ + void *arg; + va_list ap; + + va_start (ap, request); + arg = va_arg (ap, void *); + va_end (ap); + + return v4l2_ioctl (fd, request, arg); +} + +LIBV4L_PUBLIC ssize_t read (int fd, void* buffer, size_t n) +{ + return v4l2_read (fd, buffer, n); +} + +LIBV4L_PUBLIC void *mmap(void *start, size_t length, int prot, int flags, int fd, + __off_t offset) +{ + return v4l2_mmap(start, length, prot, flags, fd, offset); +} + +LIBV4L_PUBLIC void *mmap64(void *start, size_t length, int prot, int flags, int fd, + __off64_t offset) +{ + return v4l2_mmap(start, length, prot, flags, fd, offset); +} + +LIBV4L_PUBLIC int munmap(void *start, size_t length) +{ + return v4l2_munmap(start, length); +} + diff --git a/v4l2-apps/libv4l/libv4lconvert/Makefile b/v4l2-apps/libv4l/libv4lconvert/Makefile new file mode 100644 index 000000000..641d19d6e --- /dev/null +++ b/v4l2-apps/libv4l/libv4lconvert/Makefile @@ -0,0 +1,70 @@ +override CPPFLAGS += -I../include -I../../../include -fvisibility=hidden + +CFLAGS := -g -O1 +CFLAGS += -Wall -Wno-unused -Wpointer-arith -Wstrict-prototypes -Wmissing-prototypes + +ifeq ($(LINKTYPE),static) +CONVERT_LIB = libv4lconvert.a +else +CONVERT_LIB = libv4lconvert.so +override CPPFLAGS += -fPIC +endif + +CONVERT_OBJS = libv4lconvert.o tinyjpeg.o sn9c10x.o pac207.o flip.o \ + jidctflt.o spca561-decompress.o rgbyuv.o spca501.o bayer.o +TARGETS = $(CONVERT_LIB) libv4lconvert.pc +INCLUDES = ../include/libv4lconvert.h + +ifeq ($(LIB_RELEASE),) +LIB_RELEASE = 0 +endif + +ifeq ($(PREFIX),) +PREFIX = /usr/local +endif + +ifeq ($(LIBDIR),) +LIBDIR = $(PREFIX)/lib +endif + +all: $(TARGETS) + +$(CONVERT_LIB): $(CONVERT_OBJS) + +libv4lconvert.pc: + @echo prefix=$(PREFIX) > libv4lconvert.pc + @echo libdir=$(LIBDIR) >> libv4lconvert.pc + @echo >> libv4lconvert.pc + @echo 'Name: libv4lconvert' >> libv4lconvert.pc + @echo 'Description: v4l format conversion library' >> libv4lconvert.pc + @echo 'Version: '$(V4L2_LIB_VERSION) >> libv4lconvert.pc + @echo 'Libs: -L$${libdir} -lv4lconvert' >> libv4lconvert.pc + @echo 'Cflags: -I$${prefix}/include' >> libv4lconvert.pc + +install: all + mkdir -p $(DESTDIR)$(PREFIX)/include + install -p -m 644 $(INCLUDES) $(DESTDIR)$(PREFIX)/include + mkdir -p $(DESTDIR)$(LIBDIR) +ifeq ($(LINKTYPE),static) + mkdir -p $(DESTDIR)$(LIBDIR) + install -m 644 $(CONVERT_LIB) $(DESTDIR)$(LIBDIR) +else + install -m 755 $(CONVERT_LIB).$(LIB_RELEASE) $(DESTDIR)$(LIBDIR) + cd $(DESTDIR)$(LIBDIR) && \ + ln -f -s $(CONVERT_LIB).$(LIB_RELEASE) $(CONVERT_LIB) +endif + mkdir -p $(DESTDIR)$(LIBDIR)/pkgconfig + install -m 644 libv4lconvert.pc $(DESTDIR)$(LIBDIR)/pkgconfig + +clean:: + rm -f *.a *.so* *.o *.d libv4lconvert.pc log *~ + +%.o: %.c + $(CC) -c -MMD $(CPPFLAGS) $(CFLAGS) -o $@ $< + +%.so: + $(CC) -shared $(LDFLAGS) -Wl,-soname,$@.$(LIB_RELEASE) -o $@.$(LIB_RELEASE) $^ + ln -f -s $@.$(LIB_RELEASE) $@ + +%.a: + $(AR) cqs $@ $^ diff --git a/v4l2-apps/libv4l/libv4lconvert/bayer.c b/v4l2-apps/libv4l/libv4lconvert/bayer.c new file mode 100644 index 000000000..ca7bb486f --- /dev/null +++ b/v4l2-apps/libv4l/libv4lconvert/bayer.c @@ -0,0 +1,613 @@ +/* + * lib4lconvert, video4linux2 format conversion lib + * (C) 2008 Hans de Goede + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * Note: original bayer_to_bgr24 code from : + * 1394-Based Digital Camera Control Library + * + * Bayer pattern decoding functions + * + * Written by Damien Douxchamps and Frederic Devernay + * + * Note that the original bayer.c in libdc1394 supports many different + * bayer decode algorithms, for lib4lconvert the one in this file has been + * chosen (and optimized a bit) and the other algorithm's have been removed, + * see bayer.c from libdc1394 for all supported algorithms + */ + +#include +#include "libv4lconvert-priv.h" + +/************************************************************** + * Color conversion functions for cameras that can * + * output raw-Bayer pattern images, such as some Basler and * + * Point Grey camera. Most of the algos presented here come * + * from http://www-ise.stanford.edu/~tingchen/ and have been * + * converted from Matlab to C and extended to all elementary * + * patterns. * + **************************************************************/ + +/* insprired by OpenCV's Bayer decoding */ +static void v4lconvert_border_bayer_line_to_bgr24( + const unsigned char* bayer, const unsigned char* adjacent_bayer, + unsigned char *bgr, int width, int start_with_green, int blue_line) +{ + int t0, t1; + + if (start_with_green) { + /* First pixel */ + if (blue_line) { + *bgr++ = bayer[1]; + *bgr++ = bayer[0]; + *bgr++ = adjacent_bayer[0]; + } else { + *bgr++ = adjacent_bayer[0]; + *bgr++ = bayer[0]; + *bgr++ = bayer[1]; + } + /* Second pixel */ + t0 = (bayer[0] + bayer[2] + adjacent_bayer[1] + 1) / 3; + t1 = (adjacent_bayer[0] + adjacent_bayer[2] + 1) >> 1; + if (blue_line) { + *bgr++ = bayer[1]; + *bgr++ = t0; + *bgr++ = t1; + } else { + *bgr++ = t1; + *bgr++ = t0; + *bgr++ = bayer[1]; + } + bayer++; + adjacent_bayer++; + width -= 2; + } else { + /* First pixel */ + t0 = (bayer[1] + adjacent_bayer[0] + 1) >> 1; + if (blue_line) { + *bgr++ = bayer[0]; + *bgr++ = t0; + *bgr++ = adjacent_bayer[1]; + } else { + *bgr++ = adjacent_bayer[1]; + *bgr++ = t0; + *bgr++ = bayer[0]; + } + width--; + } + + if (blue_line) { + for ( ; width > 2; width -= 2) { + t0 = (bayer[0] + bayer[2] + 1) >> 1; + *bgr++ = t0; + *bgr++ = bayer[1]; + *bgr++ = adjacent_bayer[1]; + bayer++; + adjacent_bayer++; + + t0 = (bayer[0] + bayer[2] + adjacent_bayer[1] + 1) / 3; + t1 = (adjacent_bayer[0] + adjacent_bayer[2] + 1) >> 1; + *bgr++ = bayer[1]; + *bgr++ = t0; + *bgr++ = t1; + bayer++; + adjacent_bayer++; + } + } else { + for ( ; width > 2; width -= 2) { + t0 = (bayer[0] + bayer[2] + 1) >> 1; + *bgr++ = adjacent_bayer[1]; + *bgr++ = bayer[1]; + *bgr++ = t0; + bayer++; + adjacent_bayer++; + + t0 = (bayer[0] + bayer[2] + adjacent_bayer[1] + 1) / 3; + t1 = (adjacent_bayer[0] + adjacent_bayer[2] + 1) >> 1; + *bgr++ = t1; + *bgr++ = t0; + *bgr++ = bayer[1]; + bayer++; + adjacent_bayer++; + } + } + + if (width == 2) { + /* Second to last pixel */ + t0 = (bayer[0] + bayer[2] + 1) >> 1; + if (blue_line) { + *bgr++ = t0; + *bgr++ = bayer[1]; + *bgr++ = adjacent_bayer[1]; + } else { + *bgr++ = adjacent_bayer[1]; + *bgr++ = bayer[1]; + *bgr++ = t0; + } + /* Last pixel */ + t0 = (bayer[1] + adjacent_bayer[2] + 1) >> 1; + if (blue_line) { + *bgr++ = bayer[2]; + *bgr++ = t0; + *bgr++ = adjacent_bayer[1]; + } else { + *bgr++ = adjacent_bayer[1]; + *bgr++ = t0; + *bgr++ = bayer[2]; + } + } else { + /* Last pixel */ + if (blue_line) { + *bgr++ = bayer[0]; + *bgr++ = bayer[1]; + *bgr++ = adjacent_bayer[1]; + } else { + *bgr++ = adjacent_bayer[1]; + *bgr++ = bayer[1]; + *bgr++ = bayer[0]; + } + } +} + +/* From libdc1394, which on turn was based on OpenCV's Bayer decoding */ +static void bayer_to_rgbbgr24(const unsigned char *bayer, + unsigned char *bgr, int width, int height, unsigned int pixfmt, + int start_with_green, int blue_line) +{ + /* render the first line */ + v4lconvert_border_bayer_line_to_bgr24(bayer, bayer + width, bgr, width, + start_with_green, blue_line); + bgr += width * 3; + + /* reduce height by 2 because of the special case top/bottom line */ + for (height -= 2; height; height--) { + int t0, t1; + /* (width - 2) because of the border */ + const unsigned char *bayerEnd = bayer + (width - 2); + + if (start_with_green) { + /* OpenCV has a bug in the next line, which was + t0 = (bayer[0] + bayer[width * 2] + 1) >> 1; */ + t0 = (bayer[1] + bayer[width * 2 + 1] + 1) >> 1; + /* Write first pixel */ + t1 = (bayer[0] + bayer[width * 2] + bayer[width + 1] + 1) / 3; + if (blue_line) { + *bgr++ = t0; + *bgr++ = t1; + *bgr++ = bayer[width]; + } else { + *bgr++ = bayer[width]; + *bgr++ = t1; + *bgr++ = t0; + } + + /* Write second pixel */ + t1 = (bayer[width] + bayer[width + 2] + 1) >> 1; + if (blue_line) { + *bgr++ = t0; + *bgr++ = bayer[width + 1]; + *bgr++ = t1; + } else { + *bgr++ = t1; + *bgr++ = bayer[width + 1]; + *bgr++ = t0; + } + bayer++; + } else { + /* Write first pixel */ + t0 = (bayer[0] + bayer[width * 2] + 1) >> 1; + if (blue_line) { + *bgr++ = t0; + *bgr++ = bayer[width]; + *bgr++ = bayer[width + 1]; + } else { + *bgr++ = bayer[width + 1]; + *bgr++ = bayer[width]; + *bgr++ = t0; + } + } + + if (blue_line) { + for (; bayer <= bayerEnd - 2; bayer += 2) { + t0 = (bayer[0] + bayer[2] + bayer[width * 2] + + bayer[width * 2 + 2] + 2) >> 2; + t1 = (bayer[1] + bayer[width] + + bayer[width + 2] + bayer[width * 2 + 1] + + 2) >> 2; + *bgr++ = t0; + *bgr++ = t1; + *bgr++ = bayer[width + 1]; + + t0 = (bayer[2] + bayer[width * 2 + 2] + 1) >> 1; + t1 = (bayer[width + 1] + bayer[width + 3] + + 1) >> 1; + *bgr++ = t0; + *bgr++ = bayer[width + 2]; + *bgr++ = t1; + } + } else { + for (; bayer <= bayerEnd - 2; bayer += 2) { + t0 = (bayer[0] + bayer[2] + bayer[width * 2] + + bayer[width * 2 + 2] + 2) >> 2; + t1 = (bayer[1] + bayer[width] + + bayer[width + 2] + bayer[width * 2 + 1] + + 2) >> 2; + *bgr++ = bayer[width + 1]; + *bgr++ = t1; + *bgr++ = t0; + + t0 = (bayer[2] + bayer[width * 2 + 2] + 1) >> 1; + t1 = (bayer[width + 1] + bayer[width + 3] + + 1) >> 1; + *bgr++ = t1; + *bgr++ = bayer[width + 2]; + *bgr++ = t0; + } + } + + if (bayer < bayerEnd) { + /* write second to last pixel */ + t0 = (bayer[0] + bayer[2] + bayer[width * 2] + + bayer[width * 2 + 2] + 2) >> 2; + t1 = (bayer[1] + bayer[width] + + bayer[width + 2] + bayer[width * 2 + 1] + + 2) >> 2; + if (blue_line) { + *bgr++ = t0; + *bgr++ = t1; + *bgr++ = bayer[width + 1]; + } else { + *bgr++ = bayer[width + 1]; + *bgr++ = t1; + *bgr++ = t0; + } + /* write last pixel */ + t0 = (bayer[2] + bayer[width * 2 + 2] + 1) >> 1; + if (blue_line) { + *bgr++ = t0; + *bgr++ = bayer[width + 2]; + *bgr++ = bayer[width + 1]; + } else { + *bgr++ = bayer[width + 1]; + *bgr++ = bayer[width + 2]; + *bgr++ = t0; + } + bayer++; + } else { + /* write last pixel */ + t0 = (bayer[0] + bayer[width * 2] + 1) >> 1; + t1 = (bayer[1] + bayer[width * 2 + 1] + bayer[width] + 1) / 3; + if (blue_line) { + *bgr++ = t0; + *bgr++ = t1; + *bgr++ = bayer[width + 1]; + } else { + *bgr++ = bayer[width + 1]; + *bgr++ = t1; + *bgr++ = t0; + } + } + + /* skip 2 border pixels */ + bayer += 2; + + blue_line = !blue_line; + start_with_green = !start_with_green; + } + + /* render the last line */ + v4lconvert_border_bayer_line_to_bgr24(bayer + width, bayer, bgr, width, + !start_with_green, !blue_line); +} + +void v4lconvert_bayer_to_rgb24(const unsigned char *bayer, + unsigned char *bgr, int width, int height, unsigned int pixfmt) +{ + bayer_to_rgbbgr24(bayer, bgr, width, height, pixfmt, + pixfmt == V4L2_PIX_FMT_SGBRG8 /* start with green */ + || pixfmt == V4L2_PIX_FMT_SGRBG8, + pixfmt != V4L2_PIX_FMT_SBGGR8 /* blue line */ + && pixfmt != V4L2_PIX_FMT_SGBRG8); +} + +void v4lconvert_bayer_to_bgr24(const unsigned char *bayer, + unsigned char *bgr, int width, int height, unsigned int pixfmt) +{ + bayer_to_rgbbgr24(bayer, bgr, width, height, pixfmt, + pixfmt == V4L2_PIX_FMT_SGBRG8 /* start with green */ + || pixfmt == V4L2_PIX_FMT_SGRBG8, + pixfmt == V4L2_PIX_FMT_SBGGR8 /* blue line */ + || pixfmt == V4L2_PIX_FMT_SGBRG8); +} + +static void v4lconvert_border_bayer_line_to_y( + const unsigned char* bayer, const unsigned char* adjacent_bayer, + unsigned char *y, int width, int start_with_green, int blue_line) +{ + int t0, t1; + + if (start_with_green) { + /* First pixel */ + if (blue_line) { + *y++ = (8453*adjacent_bayer[0] + 16594*bayer[0] + 3223*bayer[1] + 524288) + >> 15; + } else { + *y++ = (8453*bayer[1] + 16594*bayer[0] + 3223*adjacent_bayer[0] + 524288) + >> 15; + } + /* Second pixel */ + t0 = bayer[0] + bayer[2] + adjacent_bayer[1]; + t1 = adjacent_bayer[0] + adjacent_bayer[2]; + if (blue_line) { + *y++ = (4226*t1 + 5531*t0 + 3223*bayer[1] + 524288) >> 15; + } else { + *y++ = (8453*bayer[1] + 5531*t0 + 1611*t1 + 524288) >> 15; + } + bayer++; + adjacent_bayer++; + width -= 2; + } else { + /* First pixel */ + t0 = bayer[1] + adjacent_bayer[0]; + if (blue_line) { + *y++ = (8453*adjacent_bayer[1] + 8297*t0 + 3223*bayer[0] + 524288) + >> 15; + } else { + *y++ = (8453*bayer[0] + 8297*t0 + 3223*adjacent_bayer[1] + 524288) + >> 15; + } + width--; + } + + if (blue_line) { + for ( ; width > 2; width -= 2) { + t0 = bayer[0] + bayer[2]; + *y++ = (8453*adjacent_bayer[1] + 16594*bayer[1] + 1611*t0 + 524288) + >> 15; + bayer++; + adjacent_bayer++; + + t0 = bayer[0] + bayer[2] + adjacent_bayer[1]; + t1 = adjacent_bayer[0] + adjacent_bayer[2]; + *y++ = (4226*t1 + 5531*t0 + 3223*bayer[1] + 524288) >> 15; + bayer++; + adjacent_bayer++; + } + } else { + for ( ; width > 2; width -= 2) { + t0 = bayer[0] + bayer[2]; + *y++ = (4226*t0 + 16594*bayer[1] + 3223*adjacent_bayer[1] + 524288) + >> 15; + bayer++; + adjacent_bayer++; + + t0 = bayer[0] + bayer[2] + adjacent_bayer[1]; + t1 = adjacent_bayer[0] + adjacent_bayer[2]; + *y++ = (8453*bayer[1] + 5531*t0 + 1611*t1 + 524288) >> 15; + bayer++; + adjacent_bayer++; + } + } + + if (width == 2) { + /* Second to last pixel */ + t0 = bayer[0] + bayer[2]; + if (blue_line) { + *y++ = (8453*adjacent_bayer[1] + 16594*bayer[1] + 1611*t0 + 524288) + >> 15; + } else { + *y++ = (4226*t0 + 16594*bayer[1] + 3223*adjacent_bayer[1] + 524288) + >> 15; + } + /* Last pixel */ + t0 = bayer[1] + adjacent_bayer[2]; + if (blue_line) { + *y++ = (8453*adjacent_bayer[1] + 8297*t0 + 3223*bayer[2] + 524288) + >> 15; + } else { + *y++ = (8453*bayer[2] + 8297*t0 + 3223*adjacent_bayer[1] + 524288) + >> 15; + } + } else { + /* Last pixel */ + if (blue_line) { + *y++ = (8453*adjacent_bayer[1] + 16594*bayer[1] + 3223*bayer[0] + 524288) + >> 15; + } else { + *y++ = (8453*bayer[0] + 16594*bayer[1] + 3223*adjacent_bayer[1] + 524288) + >> 15; + } + } +} + +void v4lconvert_bayer_to_yuv420(const unsigned char *bayer, + unsigned char *yuv, int width, int height, unsigned int pixfmt) +{ + int blue_line = 0, start_with_green = 0, x, y; + unsigned char *ydst = yuv; + unsigned char *udst = yuv + width * height; + unsigned char *vdst = udst + width * height / 4; + + /* First calculate the u and v planes 2x2 pixels at a time */ + switch (pixfmt) { + case V4L2_PIX_FMT_SBGGR8: + for (y = 0; y < height; y += 2) { + for (x = 0; x < width; x += 2) { + int b, g, r; + b = bayer[x]; + g = bayer[x+1]; + g += bayer[x+width]; + r = bayer[x+width+1]; + *udst++ = (-4878 * r - 4789 * g + 14456 * b + 4210688) >> 15; + *vdst++ = (14456 * r - 6052 * g - 2351 * b + 4210688) >> 15; + } + bayer += 2 * width; + } + blue_line = 1; + break; + + case V4L2_PIX_FMT_SRGGB8: + for (y = 0; y < height; y += 2) { + for (x = 0; x < width; x += 2) { + int b, g, r; + r = bayer[x]; + g = bayer[x+1]; + g += bayer[x+width]; + b = bayer[x+width+1]; + *udst++ = (-4878 * r - 4789 * g + 14456 * b + 4210688) >> 15; + *vdst++ = (14456 * r - 6052 * g - 2351 * b + 4210688) >> 15; + } + bayer += 2 * width; + } + break; + + case V4L2_PIX_FMT_SGBRG8: + for (y = 0; y < height; y += 2) { + for (x = 0; x < width; x += 2) { + int b, g, r; + g = bayer[x]; + b = bayer[x+1]; + r = bayer[x+width]; + g += bayer[x+width+1]; + *udst++ = (-4878 * r - 4789 * g + 14456 * b + 4210688) >> 15; + *vdst++ = (14456 * r - 6052 * g - 2351 * b + 4210688) >> 15; + } + bayer += 2 * width; + } + blue_line = 1; + start_with_green = 1; + break; + + case V4L2_PIX_FMT_SGRBG8: + for (y = 0; y < height; y += 2) { + for (x = 0; x < width; x += 2) { + int b, g, r; + g = bayer[x]; + r = bayer[x+1]; + b = bayer[x+width]; + g += bayer[x+width+1]; + *udst++ = (-4878 * r - 4789 * g + 14456 * b + 4210688) >> 15; + *vdst++ = (14456 * r - 6052 * g - 2351 * b + 4210688) >> 15; + } + bayer += 2 * width; + } + start_with_green = 1; + break; + } + + bayer -= width * height; + + /* render the first line */ + v4lconvert_border_bayer_line_to_y(bayer, bayer + width, ydst, width, + start_with_green, blue_line); + ydst += width; + + /* reduce height by 2 because of the border */ + for (height -= 2; height; height--) { + int t0, t1; + /* (width - 2) because of the border */ + const unsigned char *bayerEnd = bayer + (width - 2); + + if (start_with_green) { + t0 = bayer[1] + bayer[width * 2 + 1]; + /* Write first pixel */ + t1 = bayer[0] + bayer[width * 2] + bayer[width + 1]; + if (blue_line) + *ydst++ = (8453*bayer[width] + 5516*t1 + 1661*t0 + 524288) >> 15; + else + *ydst++ = (4226*t0 + 5516*t1 + 3223*bayer[width] + 524288) >> 15; + + /* Write second pixel */ + t1 = bayer[width] + bayer[width + 2]; + if (blue_line) + *ydst++ = (4226*t1 + 16594*bayer[width+1] + 1611*t0 + 524288) >> 15; + else + *ydst++ = (4226*t0 + 16594*bayer[width+1] + 1611*t1 + 524288) >> 15; + bayer++; + } else { + /* Write first pixel */ + t0 = bayer[0] + bayer[width * 2]; + if (blue_line) { + *ydst++ = (8453*bayer[width+1] + 16594*bayer[width] + 1661*t0 + + 524288) >> 15; + } else { + *ydst++ = (4226*t0 + 16594*bayer[width] + 3223*bayer[width+1] + + 524288) >> 15; + } + } + + if (blue_line) { + for (; bayer <= bayerEnd - 2; bayer += 2) { + t0 = bayer[0] + bayer[2] + bayer[width * 2] + bayer[width * 2 + 2]; + t1 = bayer[1] + bayer[width] + bayer[width + 2] + bayer[width * 2 + 1]; + *ydst++ = (8453*bayer[width+1] + 4148*t1 + 806*t0 + 524288) >> 15; + + t0 = bayer[2] + bayer[width * 2 + 2]; + t1 = bayer[width + 1] + bayer[width + 3]; + *ydst++ = (4226*t1 + 16594*bayer[width+2] + 1611*t0 + 524288) >> 15; + } + } else { + for (; bayer <= bayerEnd - 2; bayer += 2) { + t0 = bayer[0] + bayer[2] + bayer[width * 2] + bayer[width * 2 + 2]; + t1 = bayer[1] + bayer[width] + bayer[width + 2] + bayer[width * 2 + 1]; + *ydst++ = (2113*t0 + 4148*t1 + 3223*bayer[width+1] + 524288) >> 15; + + t0 = bayer[2] + bayer[width * 2 + 2]; + t1 = bayer[width + 1] + bayer[width + 3]; + *ydst++ = (4226*t0 + 16594*bayer[width+2] + 1611*t1 + 524288) >> 15; + } + } + + if (bayer < bayerEnd) { + /* Write second to last pixel */ + t0 = bayer[0] + bayer[2] + bayer[width * 2] + bayer[width * 2 + 2]; + t1 = bayer[1] + bayer[width] + bayer[width + 2] + bayer[width * 2 + 1]; + if (blue_line) + *ydst++ = (8453*bayer[width+1] + 4148*t1 + 806*t0 + 524288) >> 15; + else + *ydst++ = (2113*t0 + 4148*t1 + 3223*bayer[width+1] + 524288) >> 15; + + /* write last pixel */ + t0 = bayer[2] + bayer[width * 2 + 2]; + if (blue_line) { + *ydst++ = (8453*bayer[width+1] + 16594*bayer[width+2] + 1661*t0 + + 524288) >> 15; + } else { + *ydst++ = (4226*t0 + 16594*bayer[width+2] + 3223*bayer[width+1] + + 524288) >> 15; + } + bayer++; + } else { + /* write last pixel */ + t0 = bayer[0] + bayer[width * 2]; + t1 = bayer[1] + bayer[width * 2 + 1] + bayer[width]; + if (blue_line) + *ydst++ = (8453*bayer[width+1] + 5516*t1 + 1661*t0 + 524288) >> 15; + else + *ydst++ = (4226*t0 + 5516*t1 + 3223*bayer[width+1] + 524288) >> 15; + } + + /* skip 2 border pixels */ + bayer += 2; + + blue_line = !blue_line; + start_with_green = !start_with_green; + } + + /* render the last line */ + v4lconvert_border_bayer_line_to_y(bayer + width, bayer, ydst, width, + !start_with_green, !blue_line); +} diff --git a/v4l2-apps/libv4l/libv4lconvert/flip.c b/v4l2-apps/libv4l/libv4lconvert/flip.c new file mode 100644 index 000000000..cd3468a89 --- /dev/null +++ b/v4l2-apps/libv4l/libv4lconvert/flip.c @@ -0,0 +1,107 @@ +/* + +# RGB / YUV flip/rotate routines + +# (C) 2008 Hans de Goede + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "libv4lconvert-priv.h" + +void v4lconvert_rotate180_rgbbgr24(const unsigned char *src, unsigned char *dst, + int width, int height) +{ + int i; + + src += 3 * width * height - 3; + + for (i = 0; i < width * height; i++) { + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst += 3; + src -= 3; + } +} + +void v4lconvert_rotate180_yuv420(const unsigned char *src, unsigned char *dst, + int width, int height) +{ + int i; + + /* First flip x and y of the Y plane */ + src += width * height - 1; + for (i = 0; i < width * height; i++) + *dst++ = *src--; + + /* Now flip the U plane */ + src += width * height * 5 / 4; + for (i = 0; i < width * height / 4; i++) + *dst++ = *src--; + + /* Last flip the V plane */ + src += width * height / 2; + for (i = 0; i < width * height / 4; i++) + *dst++ = *src--; +} + +void v4lconvert_rotate90_rgbbgr24(const unsigned char *src, unsigned char *dst, + int destwidth, int destheight) +{ + int x, y; +#define srcwidth destheight +#define srcheight destwidth + + for (y = 0; y < destheight; y++) + for (x = 0; x < destwidth; x++) { + int offset = ((srcheight - x - 1) * srcwidth + y) * 3; + *dst++ = src[offset++]; + *dst++ = src[offset++]; + *dst++ = src[offset]; + } +} + +void v4lconvert_rotate90_yuv420(const unsigned char *src, unsigned char *dst, + int destwidth, int destheight) +{ + int x, y; + + /* Y-plane */ + for (y = 0; y < destheight; y++) + for (x = 0; x < destwidth; x++) { + int offset = (srcheight - x - 1) * srcwidth + y; + *dst++ = src[offset]; + } + + /* U-plane */ + src += srcwidth * srcheight; + destwidth /= 2; + destheight /= 2; + for (y = 0; y < destheight; y++) + for (x = 0; x < destwidth; x++) { + int offset = (srcheight - x - 1) * srcwidth + y; + *dst++ = src[offset]; + } + + /* V-plane */ + src += srcwidth * srcheight; + for (y = 0; y < destheight; y++) + for (x = 0; x < destwidth; x++) { + int offset = (srcheight - x - 1) * srcwidth + y; + *dst++ = src[offset]; + } +} diff --git a/v4l2-apps/libv4l/libv4lconvert/jidctflt.c b/v4l2-apps/libv4l/libv4lconvert/jidctflt.c new file mode 100644 index 000000000..532abc7ea --- /dev/null +++ b/v4l2-apps/libv4l/libv4lconvert/jidctflt.c @@ -0,0 +1,286 @@ +/* + * jidctflt.c + * + * Copyright (C) 1994-1998, Thomas G. Lane. + * This file is part of the Independent JPEG Group's software. + * + * The authors make NO WARRANTY or representation, either express or implied, + * with respect to this software, its quality, accuracy, merchantability, or + * fitness for a particular purpose. This software is provided "AS IS", and you, + * its user, assume the entire risk as to its quality and accuracy. + * + * This software is copyright (C) 1991-1998, Thomas G. Lane. + * All Rights Reserved except as specified below. + * + * Permission is hereby granted to use, copy, modify, and distribute this + * software (or portions thereof) for any purpose, without fee, subject to these + * conditions: + * (1) If any part of the source code for this software is distributed, then this + * README file must be included, with this copyright and no-warranty notice + * unaltered; and any additions, deletions, or changes to the original files + * must be clearly indicated in accompanying documentation. + * (2) If only executable code is distributed, then the accompanying + * documentation must state that "this software is based in part on the work of + * the Independent JPEG Group". + * (3) Permission for use of this software is granted only if the user accepts + * full responsibility for any undesirable consequences; the authors accept + * NO LIABILITY for damages of any kind. + * + * These conditions apply to any software derived from or based on the IJG code, + * not just to the unmodified library. If you use our work, you ought to + * acknowledge us. + * + * Permission is NOT granted for the use of any IJG author's name or company name + * in advertising or publicity relating to this software or products derived from + * it. This software may be referred to only as "the Independent JPEG Group's + * software". + * + * We specifically permit and encourage the use of this software as the basis of + * commercial products, provided that all warranty or liability claims are + * assumed by the product vendor. + * + * + * This file contains a floating-point implementation of the + * inverse DCT (Discrete Cosine Transform). In the IJG code, this routine + * must also perform dequantization of the input coefficients. + * + * This implementation should be more accurate than either of the integer + * IDCT implementations. However, it may not give the same results on all + * machines because of differences in roundoff behavior. Speed will depend + * on the hardware's floating point capacity. + * + * A 2-D IDCT can be done by 1-D IDCT on each column followed by 1-D IDCT + * on each row (or vice versa, but it's more convenient to emit a row at + * a time). Direct algorithms are also available, but they are much more + * complex and seem not to be any faster when reduced to code. + * + * This implementation is based on Arai, Agui, and Nakajima's algorithm for + * scaled DCT. Their original paper (Trans. IEICE E-71(11):1095) is in + * Japanese, but the algorithm is described in the Pennebaker & Mitchell + * JPEG textbook (see REFERENCES section in file README). The following code + * is based directly on figure 4-8 in P&M. + * While an 8-point DCT cannot be done in less than 11 multiplies, it is + * possible to arrange the computation so that many of the multiplies are + * simple scalings of the final outputs. These multiplies can then be + * folded into the multiplications or divisions by the JPEG quantization + * table entries. The AA&N method leaves only 5 multiplies and 29 adds + * to be done in the DCT itself. + * The primary disadvantage of this method is that with a fixed-point + * implementation, accuracy is lost due to imprecise representation of the + * scaled quantization values. However, that problem does not arise if + * we use floating point arithmetic. + */ + +#include +#include "tinyjpeg-internal.h" + +#define FAST_FLOAT float +#define DCTSIZE 8 +#define DCTSIZE2 (DCTSIZE*DCTSIZE) + +#define DEQUANTIZE(coef,quantval) (((FAST_FLOAT) (coef)) * (quantval)) + +#if defined(__GNUC__) && (defined(__i686__) || defined(__x86_64__)) + +static inline unsigned char descale_and_clamp(int x, int shift) +{ + __asm__ ( + "add %3,%1\n" + "\tsar %2,%1\n" + "\tsub $-128,%1\n" + "\tcmovl %5,%1\n" /* Use the sub to compare to 0 */ + "\tcmpl %4,%1\n" + "\tcmovg %4,%1\n" + : "=r"(x) + : "0"(x), "Ic"((unsigned char)shift), "ir"(1U<<(shift-1)), "r" (0xff), "r" (0) + ); + return x; +} + +#else +static inline unsigned char descale_and_clamp(int x, int shift) +{ + x += (1UL<<(shift-1)); + if (x<0) + x = (x >> shift) | ((~(0UL)) << (32-(shift))); + else + x >>= shift; + x += 128; + if (x>255) + return 255; + else if (x<0) + return 0; + else + return x; +} +#endif + +/* + * Perform dequantization and inverse DCT on one block of coefficients. + */ + +void +tinyjpeg_idct_float (struct component *compptr, uint8_t *output_buf, int stride) +{ + FAST_FLOAT tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7; + FAST_FLOAT tmp10, tmp11, tmp12, tmp13; + FAST_FLOAT z5, z10, z11, z12, z13; + int16_t *inptr; + FAST_FLOAT *quantptr; + FAST_FLOAT *wsptr; + uint8_t *outptr; + int ctr; + FAST_FLOAT workspace[DCTSIZE2]; /* buffers data between passes */ + + /* Pass 1: process columns from input, store into work array. */ + + inptr = compptr->DCT; + quantptr = compptr->Q_table; + wsptr = workspace; + for (ctr = DCTSIZE; ctr > 0; ctr--) { + /* Due to quantization, we will usually find that many of the input + * coefficients are zero, especially the AC terms. We can exploit this + * by short-circuiting the IDCT calculation for any column in which all + * the AC terms are zero. In that case each output is equal to the + * DC coefficient (with scale factor as needed). + * With typical images and quantization tables, half or more of the + * column DCT calculations can be simplified this way. + */ + + if (inptr[DCTSIZE*1] == 0 && inptr[DCTSIZE*2] == 0 && + inptr[DCTSIZE*3] == 0 && inptr[DCTSIZE*4] == 0 && + inptr[DCTSIZE*5] == 0 && inptr[DCTSIZE*6] == 0 && + inptr[DCTSIZE*7] == 0) { + /* AC terms all zero */ + FAST_FLOAT dcval = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + + wsptr[DCTSIZE*0] = dcval; + wsptr[DCTSIZE*1] = dcval; + wsptr[DCTSIZE*2] = dcval; + wsptr[DCTSIZE*3] = dcval; + wsptr[DCTSIZE*4] = dcval; + wsptr[DCTSIZE*5] = dcval; + wsptr[DCTSIZE*6] = dcval; + wsptr[DCTSIZE*7] = dcval; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + continue; + } + + /* Even part */ + + tmp0 = DEQUANTIZE(inptr[DCTSIZE*0], quantptr[DCTSIZE*0]); + tmp1 = DEQUANTIZE(inptr[DCTSIZE*2], quantptr[DCTSIZE*2]); + tmp2 = DEQUANTIZE(inptr[DCTSIZE*4], quantptr[DCTSIZE*4]); + tmp3 = DEQUANTIZE(inptr[DCTSIZE*6], quantptr[DCTSIZE*6]); + + tmp10 = tmp0 + tmp2; /* phase 3 */ + tmp11 = tmp0 - tmp2; + + tmp13 = tmp1 + tmp3; /* phases 5-3 */ + tmp12 = (tmp1 - tmp3) * ((FAST_FLOAT) 1.414213562) - tmp13; /* 2*c4 */ + + tmp0 = tmp10 + tmp13; /* phase 2 */ + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + tmp4 = DEQUANTIZE(inptr[DCTSIZE*1], quantptr[DCTSIZE*1]); + tmp5 = DEQUANTIZE(inptr[DCTSIZE*3], quantptr[DCTSIZE*3]); + tmp6 = DEQUANTIZE(inptr[DCTSIZE*5], quantptr[DCTSIZE*5]); + tmp7 = DEQUANTIZE(inptr[DCTSIZE*7], quantptr[DCTSIZE*7]); + + z13 = tmp6 + tmp5; /* phase 6 */ + z10 = tmp6 - tmp5; + z11 = tmp4 + tmp7; + z12 = tmp4 - tmp7; + + tmp7 = z11 + z13; /* phase 5 */ + tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); /* 2*c4 */ + + z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ + tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */ + tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; /* phase 2 */ + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + wsptr[DCTSIZE*0] = tmp0 + tmp7; + wsptr[DCTSIZE*7] = tmp0 - tmp7; + wsptr[DCTSIZE*1] = tmp1 + tmp6; + wsptr[DCTSIZE*6] = tmp1 - tmp6; + wsptr[DCTSIZE*2] = tmp2 + tmp5; + wsptr[DCTSIZE*5] = tmp2 - tmp5; + wsptr[DCTSIZE*4] = tmp3 + tmp4; + wsptr[DCTSIZE*3] = tmp3 - tmp4; + + inptr++; /* advance pointers to next column */ + quantptr++; + wsptr++; + } + + /* Pass 2: process rows from work array, store into output array. */ + /* Note that we must descale the results by a factor of 8 == 2**3. */ + + wsptr = workspace; + outptr = output_buf; + for (ctr = 0; ctr < DCTSIZE; ctr++) { + /* Rows of zeroes can be exploited in the same way as we did with columns. + * However, the column calculation has created many nonzero AC terms, so + * the simplification applies less often (typically 5% to 10% of the time). + * And testing floats for zero is relatively expensive, so we don't bother. + */ + + /* Even part */ + + tmp10 = wsptr[0] + wsptr[4]; + tmp11 = wsptr[0] - wsptr[4]; + + tmp13 = wsptr[2] + wsptr[6]; + tmp12 = (wsptr[2] - wsptr[6]) * ((FAST_FLOAT) 1.414213562) - tmp13; + + tmp0 = tmp10 + tmp13; + tmp3 = tmp10 - tmp13; + tmp1 = tmp11 + tmp12; + tmp2 = tmp11 - tmp12; + + /* Odd part */ + + z13 = wsptr[5] + wsptr[3]; + z10 = wsptr[5] - wsptr[3]; + z11 = wsptr[1] + wsptr[7]; + z12 = wsptr[1] - wsptr[7]; + + tmp7 = z11 + z13; + tmp11 = (z11 - z13) * ((FAST_FLOAT) 1.414213562); + + z5 = (z10 + z12) * ((FAST_FLOAT) 1.847759065); /* 2*c2 */ + tmp10 = ((FAST_FLOAT) 1.082392200) * z12 - z5; /* 2*(c2-c6) */ + tmp12 = ((FAST_FLOAT) -2.613125930) * z10 + z5; /* -2*(c2+c6) */ + + tmp6 = tmp12 - tmp7; + tmp5 = tmp11 - tmp6; + tmp4 = tmp10 + tmp5; + + /* Final output stage: scale down by a factor of 8 and range-limit */ + + outptr[0] = descale_and_clamp((int)(tmp0 + tmp7), 3); + outptr[7] = descale_and_clamp((int)(tmp0 - tmp7), 3); + outptr[1] = descale_and_clamp((int)(tmp1 + tmp6), 3); + outptr[6] = descale_and_clamp((int)(tmp1 - tmp6), 3); + outptr[2] = descale_and_clamp((int)(tmp2 + tmp5), 3); + outptr[5] = descale_and_clamp((int)(tmp2 - tmp5), 3); + outptr[4] = descale_and_clamp((int)(tmp3 + tmp4), 3); + outptr[3] = descale_and_clamp((int)(tmp3 - tmp4), 3); + + + wsptr += DCTSIZE; /* advance pointer to next row */ + outptr += stride; + } +} + diff --git a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h new file mode 100644 index 000000000..0c4eff6ce --- /dev/null +++ b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert-priv.h @@ -0,0 +1,166 @@ +/* +# (C) 2008 Hans de Goede + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#ifndef __LIBV4LCONVERT_PRIV_H +#define __LIBV4LCONVERT_PRIV_H + +#include +#include "libv4lconvert.h" +#include "tinyjpeg.h" + +#ifndef V4L2_PIX_FMT_SPCA501 +#define V4L2_PIX_FMT_SPCA501 v4l2_fourcc('S','5','0','1') /* YUYV per line */ +#endif + +#ifndef V4L2_PIX_FMT_SPCA505 +#define V4L2_PIX_FMT_SPCA505 v4l2_fourcc('S','5','0','5') /* YYUV per line */ +#endif + +#ifndef V4L2_PIX_FMT_SPCA508 +#define V4L2_PIX_FMT_SPCA508 v4l2_fourcc('S','5','0','8') /* YUVY per line */ +#endif + +#ifndef V4L2_PIX_FMT_SPCA561 +#define V4L2_PIX_FMT_SPCA561 v4l2_fourcc('S','5','6','1') +#endif + +#ifndef V4L2_PIX_FMT_PAC207 +#define V4L2_PIX_FMT_PAC207 v4l2_fourcc('P','2','0','7') +#endif + +#ifndef V4L2_PIX_FMT_PJPG +#define V4L2_PIX_FMT_PJPG v4l2_fourcc('P', 'J', 'P', 'G') +#endif + +#ifndef V4L2_PIX_FMT_SGBRG8 +#define V4L2_PIX_FMT_SGBRG8 v4l2_fourcc('G','B','R','G') +#endif + +#ifndef V4L2_PIX_FMT_SGRBG8 +#define V4L2_PIX_FMT_SGRBG8 v4l2_fourcc('G','R','B','G') +#endif + +#ifndef V4L2_PIX_FMT_SRGGB8 +#define V4L2_PIX_FMT_SRGGB8 v4l2_fourcc('R','G','G','B') +#endif + +#ifndef V4L2_PIX_FMT_YVYU +#define V4L2_PIX_FMT_YVYU v4l2_fourcc('Y', 'V', 'Y', 'U') +#endif + +#define V4LCONVERT_ERROR_MSG_SIZE 256 +#define V4LCONVERT_MAX_FRAMESIZES 16 + +#define V4LCONVERT_ERR(...) \ + snprintf(data->error_msg, V4LCONVERT_ERROR_MSG_SIZE, \ + "v4l-convert: error " __VA_ARGS__) + +/* Card flags */ +#define V4LCONVERT_UPSIDE_DOWN 0x01 + +/* Pixformat flags */ +#define V4LCONVERT_COMPRESSED 0x01 + +struct v4lconvert_data { + int fd; + int flags; /* bitfield */ + int supported_src_formats; /* bitfield */ + unsigned int no_formats; + char error_msg[V4LCONVERT_ERROR_MSG_SIZE]; + struct jdec_private *jdec; + struct v4l2_frmsizeenum framesizes[V4LCONVERT_MAX_FRAMESIZES]; + unsigned int no_framesizes; +}; + +struct v4lconvert_flags_info { + const char *card; + int flags; +}; + +struct v4lconvert_pixfmt { + unsigned int fmt; + int flags; +}; + +void v4lconvert_yuv420_to_rgb24(const unsigned char *src, unsigned char *dst, + int width, int height); + +void v4lconvert_yuv420_to_bgr24(const unsigned char *src, unsigned char *dst, + int width, int height); + +void v4lconvert_yuyv_to_rgb24(const unsigned char *src, unsigned char *dst, + int width, int height); + +void v4lconvert_yuyv_to_bgr24(const unsigned char *src, unsigned char *dst, + int width, int height); + +void v4lconvert_yuyv_to_yuv420(const unsigned char *src, unsigned char *dst, + int width, int height); + +void v4lconvert_yvyu_to_rgb24(const unsigned char *src, unsigned char *dst, + int width, int height); + +void v4lconvert_yvyu_to_bgr24(const unsigned char *src, unsigned char *dst, + int width, int height); + +void v4lconvert_yvyu_to_yuv420(const unsigned char *src, unsigned char *dst, + int width, int height); + +void v4lconvert_swap_rgb(const unsigned char *src, unsigned char *dst, + int width, int height); + +void v4lconvert_spca501_to_yuv420(const unsigned char *src, unsigned char *dst, + int width, int height); + +void v4lconvert_spca505_to_yuv420(const unsigned char *src, unsigned char *dst, + int width, int height); + +void v4lconvert_spca508_to_yuv420(const unsigned char *src, unsigned char *dst, + int width, int height); + +void v4lconvert_decode_spca561(const unsigned char *src, unsigned char *dst, + int width, int height); + +void v4lconvert_decode_sn9c10x(const unsigned char *src, unsigned char *dst, + int width, int height); + +void v4lconvert_decode_pac207(const unsigned char *src, unsigned char *dst, + int width, int height); + +void v4lconvert_bayer_to_rgb24(const unsigned char *bayer, + unsigned char *rgb, int width, int height, unsigned int pixfmt); + +void v4lconvert_bayer_to_bgr24(const unsigned char *bayer, + unsigned char *rgb, int width, int height, unsigned int pixfmt); + +void v4lconvert_bayer_to_yuv420(const unsigned char *bayer, + unsigned char *yuv, int width, int height, unsigned int pixfmt); + +void v4lconvert_rotate90_rgbbgr24(const unsigned char *src, unsigned char *dst, + int destwidth, int destheight); + +void v4lconvert_rotate90_yuv420(const unsigned char *src, unsigned char *dst, + int destwidth, int destheight); + +void v4lconvert_rotate180_rgbbgr24(const unsigned char *src, unsigned char *dst, + int width, int height); + +void v4lconvert_rotate180_yuv420(const unsigned char *src, unsigned char *dst, + int width, int height); + +#endif diff --git a/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c new file mode 100644 index 000000000..93bc67c7e --- /dev/null +++ b/v4l2-apps/libv4l/libv4lconvert/libv4lconvert.c @@ -0,0 +1,737 @@ +/* +# (C) 2008 Hans de Goede + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include +#include +#include +#include +#include +#include "libv4lconvert.h" +#include "libv4lconvert-priv.h" + +#define MIN(a,b) (((a)<(b))?(a):(b)) +#define ARRAY_SIZE(x) ((int)sizeof(x)/(int)sizeof((x)[0])) + +/* Note for proper functioning of v4lconvert_enum_fmt the first entries in + supported_src_pixfmts must match with the entries in supported_dst_pixfmts */ +#define SUPPORTED_DST_PIXFMTS \ + { V4L2_PIX_FMT_RGB24, 0 }, \ + { V4L2_PIX_FMT_BGR24, 0 }, \ + { V4L2_PIX_FMT_YUV420, 0 } + +static void v4lconvert_get_framesizes(struct v4lconvert_data *data, + unsigned int pixelformat); + +/* Note uncompressed formats must go first so that they are prefered by + v4lconvert_try_format for low resolutions */ +static const struct v4lconvert_pixfmt supported_src_pixfmts[] = { + SUPPORTED_DST_PIXFMTS, + { V4L2_PIX_FMT_YUYV, 0 }, + { V4L2_PIX_FMT_YVYU, 0 }, + { V4L2_PIX_FMT_SBGGR8, 0 }, + { V4L2_PIX_FMT_SGBRG8, 0 }, + { V4L2_PIX_FMT_SGRBG8, 0 }, + { V4L2_PIX_FMT_SRGGB8, 0 }, + { V4L2_PIX_FMT_SPCA501, 0 }, + { V4L2_PIX_FMT_SPCA505, 0 }, + { V4L2_PIX_FMT_SPCA508, 0 }, + { V4L2_PIX_FMT_MJPEG, V4LCONVERT_COMPRESSED }, + { V4L2_PIX_FMT_JPEG, V4LCONVERT_COMPRESSED }, + { V4L2_PIX_FMT_SPCA561, V4LCONVERT_COMPRESSED }, + { V4L2_PIX_FMT_SN9C10X, V4LCONVERT_COMPRESSED }, + { V4L2_PIX_FMT_PAC207, V4LCONVERT_COMPRESSED }, + { V4L2_PIX_FMT_PJPG, V4LCONVERT_COMPRESSED }, +}; + +static const struct v4lconvert_pixfmt supported_dst_pixfmts[] = { + SUPPORTED_DST_PIXFMTS +}; + +/* List of cams which need special flags */ +static const struct v4lconvert_flags_info v4lconvert_flags[] = { + { "SPC 200NC ", V4LCONVERT_UPSIDE_DOWN }, + { "SPC 300NC ", V4LCONVERT_UPSIDE_DOWN }, + { "USB Camera (0471:0325)", V4LCONVERT_UPSIDE_DOWN }, /* SPC200NC */ + { "USB Camera (0471:0326)", V4LCONVERT_UPSIDE_DOWN }, /* SPC300NC */ + { "USB Camera (093a:2476)", V4LCONVERT_UPSIDE_DOWN }, /* Genius E-M 112 */ +}; + +struct v4lconvert_data *v4lconvert_create(int fd) +{ + int i, j; + struct v4lconvert_data *data = calloc(1, sizeof(struct v4lconvert_data)); + struct v4l2_capability cap; + + if (!data) + return NULL; + + data->fd = fd; + data->jdec = NULL; + + /* Check supported formats */ + for (i = 0; ; i++) { + struct v4l2_fmtdesc fmt = { .type = V4L2_BUF_TYPE_VIDEO_CAPTURE }; + + fmt.index = i; + + if (syscall(SYS_ioctl, fd, VIDIOC_ENUM_FMT, &fmt)) + break; + + for (j = 0; j < ARRAY_SIZE(supported_src_pixfmts); j++) + if (fmt.pixelformat == supported_src_pixfmts[j].fmt) { + data->supported_src_formats |= 1 << j; + break; + } + + v4lconvert_get_framesizes(data, fmt.pixelformat); + } + + data->no_formats = i; + + /* Check if this cam has any special flags */ + if (syscall(SYS_ioctl, fd, VIDIOC_QUERYCAP, &cap) == 0) { + for (i = 0; i < ARRAY_SIZE(v4lconvert_flags); i++) + if (!strcmp((const char *)v4lconvert_flags[i].card, (char *)cap.card)) { + data->flags = v4lconvert_flags[i].flags; + break; + } + } + + return data; +} + +void v4lconvert_destroy(struct v4lconvert_data *data) +{ + if (data->jdec) { + unsigned char *comps[3] = { NULL, NULL, NULL }; + tinyjpeg_set_components(data->jdec, comps, 3); + tinyjpeg_free(data->jdec); + } + free(data); +} + +static int v4lconvert_supported_dst_format(unsigned int pixelformat) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) + if (supported_dst_pixfmts[i].fmt == pixelformat) + break; + + return i != ARRAY_SIZE(supported_dst_pixfmts); +} + +/* See libv4lconvert.h for description of in / out parameters */ +int v4lconvert_enum_fmt(struct v4lconvert_data *data, struct v4l2_fmtdesc *fmt) +{ + int i, no_faked_fmts = 0; + unsigned int faked_fmts[ARRAY_SIZE(supported_dst_pixfmts)]; + + if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE || + fmt->index < data->no_formats || + !data->supported_src_formats) + return syscall(SYS_ioctl, data->fd, VIDIOC_ENUM_FMT, fmt); + + for (i = 0; i < ARRAY_SIZE(supported_dst_pixfmts); i++) + if (!(data->supported_src_formats & (1 << i))) { + faked_fmts[no_faked_fmts] = supported_dst_pixfmts[i].fmt; + no_faked_fmts++; + } + + i = fmt->index - data->no_formats; + if (i >= no_faked_fmts) { + errno = EINVAL; + return -1; + } + + fmt->flags = 0; + fmt->pixelformat = faked_fmts[i]; + fmt->description[0] = faked_fmts[i] & 0xff; + fmt->description[1] = (faked_fmts[i] >> 8) & 0xff; + fmt->description[2] = (faked_fmts[i] >> 16) & 0xff; + fmt->description[3] = faked_fmts[i] >> 24; + fmt->description[4] = '\0'; + memset(fmt->reserved, 0, 4); + + return 0; +} + +/* See libv4lconvert.h for description of in / out parameters */ +int v4lconvert_try_format(struct v4lconvert_data *data, + struct v4l2_format *dest_fmt, struct v4l2_format *src_fmt) +{ + int i; + unsigned int closest_fmt_size_diff = -1; + unsigned int desired_pixfmt = dest_fmt->fmt.pix.pixelformat; + struct v4l2_format try_fmt, closest_fmt = { .type = 0 }; + + /* Can we do conversion to the requested format & type? */ + if (!v4lconvert_supported_dst_format(desired_pixfmt) || + dest_fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) { + int ret = syscall(SYS_ioctl, data->fd, VIDIOC_TRY_FMT, dest_fmt); + if (src_fmt) + *src_fmt = *dest_fmt; + return ret; + } + + for (i = 0; i < ARRAY_SIZE(supported_src_pixfmts); i++) { + /* is this format supported? */ + if (!(data->supported_src_formats & (1 << i))) + continue; + + try_fmt = *dest_fmt; + try_fmt.fmt.pix.pixelformat = supported_src_pixfmts[i].fmt; + + if (!syscall(SYS_ioctl, data->fd, VIDIOC_TRY_FMT, &try_fmt)) + { + if (try_fmt.fmt.pix.pixelformat == supported_src_pixfmts[i].fmt) { + int size_x_diff = abs((int)try_fmt.fmt.pix.width - + (int)dest_fmt->fmt.pix.width); + int size_y_diff = abs((int)try_fmt.fmt.pix.height - + (int)dest_fmt->fmt.pix.height); + unsigned int size_diff = size_x_diff * size_x_diff + + size_y_diff * size_y_diff; + if (size_diff < closest_fmt_size_diff || + (size_diff == closest_fmt_size_diff && + (supported_src_pixfmts[i].fmt == desired_pixfmt || + ((try_fmt.fmt.pix.width > 176 || try_fmt.fmt.pix.height > 144) && + (supported_src_pixfmts[i].flags & V4LCONVERT_COMPRESSED))))) { + closest_fmt_size_diff = size_diff; + closest_fmt = try_fmt; + } + } + } + } + + if (closest_fmt.type == 0) { + int ret = syscall(SYS_ioctl, data->fd, VIDIOC_TRY_FMT, dest_fmt); + if (src_fmt) + *src_fmt = *dest_fmt; + return ret; + } + + *dest_fmt = closest_fmt; + + /* Are we converting? */ + if (closest_fmt.fmt.pix.pixelformat != desired_pixfmt) { + dest_fmt->fmt.pix.pixelformat = desired_pixfmt; + switch (dest_fmt->fmt.pix.pixelformat) { + case V4L2_PIX_FMT_RGB24: + case V4L2_PIX_FMT_BGR24: + dest_fmt->fmt.pix.bytesperline = dest_fmt->fmt.pix.width * 3; + dest_fmt->fmt.pix.sizeimage = dest_fmt->fmt.pix.width * + dest_fmt->fmt.pix.height * 3; + break; + case V4L2_PIX_FMT_YUV420: + dest_fmt->fmt.pix.bytesperline = dest_fmt->fmt.pix.width; + dest_fmt->fmt.pix.sizeimage = (dest_fmt->fmt.pix.width * + dest_fmt->fmt.pix.height * 3) / 2; + break; + } + } + + if (src_fmt) + *src_fmt = closest_fmt; + + return 0; +} + +/* Is conversion necessary ? */ +int v4lconvert_needs_conversion(struct v4lconvert_data *data, + const struct v4l2_format *src_fmt, /* in */ + const struct v4l2_format *dest_fmt) /* in */ +{ + if(memcmp(src_fmt, dest_fmt, sizeof(*src_fmt))) + return 1; /* Formats differ */ + + if (!(data->flags & V4LCONVERT_UPSIDE_DOWN)) + return 0; /* Formats identical and we don't need flip */ + + /* Formats are identical, but we need flip, do we support the dest_fmt? */ + if (!v4lconvert_supported_dst_format(dest_fmt->fmt.pix.pixelformat)) + return 0; /* Needs flip but we cannot do it :( */ + else + return 1; /* Needs flip and thus conversion */ +} + +int v4lconvert_convert(struct v4lconvert_data *data, + const struct v4l2_format *src_fmt, /* in */ + const struct v4l2_format *dest_fmt, /* in */ + unsigned char *src, int src_size, unsigned char *_dest, int dest_size) +{ + unsigned int header_width, header_height; + int result, needed, rotate = 0, jpeg_flags = TINYJPEG_FLAGS_MJPEG_TABLE; + unsigned char *components[3]; + unsigned char *dest = _dest; + + /* Special case when no conversion is needed */ + if (!v4lconvert_needs_conversion(data, src_fmt, dest_fmt)) { + int to_copy = MIN(dest_size, src_size); + memcpy(dest, src, to_copy); + return to_copy; + } + + /* sanity check, is the dest buffer large enough? */ + switch (dest_fmt->fmt.pix.pixelformat) { + case V4L2_PIX_FMT_RGB24: + case V4L2_PIX_FMT_BGR24: + needed = dest_fmt->fmt.pix.width * dest_fmt->fmt.pix.height * 3; + break; + case V4L2_PIX_FMT_YUV420: + needed = (dest_fmt->fmt.pix.width * dest_fmt->fmt.pix.height * 3) / 2; + break; + default: + V4LCONVERT_ERR("Unknown dest format in conversion\n"); + errno = EINVAL; + return -1; + } + + if (dest_size < needed) { + V4LCONVERT_ERR("destination buffer too small\n"); + errno = EFAULT; + return -1; + } + + if (data->flags & V4LCONVERT_UPSIDE_DOWN) { + rotate = 180; + dest = alloca(needed); + } + + switch (src_fmt->fmt.pix.pixelformat) { + case V4L2_PIX_FMT_PJPG: + jpeg_flags |= TINYJPEG_FLAGS_PIXART_JPEG; + /* Fall through */ + case V4L2_PIX_FMT_MJPEG: + case V4L2_PIX_FMT_JPEG: + if (!data->jdec) { + data->jdec = tinyjpeg_init(); + if (!data->jdec) { + V4LCONVERT_ERR("out of memory!\n"); + errno = ENOMEM; + return -1; + } + } + tinyjpeg_set_flags(data->jdec, jpeg_flags); + if (tinyjpeg_parse_header(data->jdec, src, src_size)) { + V4LCONVERT_ERR("parsing JPEG header: %s\n", + tinyjpeg_get_errorstring(data->jdec)); + errno = EIO; + return -1; + } + tinyjpeg_get_size(data->jdec, &header_width, &header_height); + + if (header_width != dest_fmt->fmt.pix.width || + header_height != dest_fmt->fmt.pix.height) { + /* Check for (pixart) rotated JPEG */ + if (header_width == dest_fmt->fmt.pix.height || + header_height == dest_fmt->fmt.pix.width) { + if (!rotate) + dest = alloca(needed); + rotate += 90; + } else { + V4LCONVERT_ERR("unexpected width / height in JPEG header" + "expected: %ux%u, header: %ux%u\n", + dest_fmt->fmt.pix.width, dest_fmt->fmt.pix.height, + header_width, header_height); + errno = EIO; + return -1; + } + } + + components[0] = dest; + components[1] = components[0] + dest_fmt->fmt.pix.width * + dest_fmt->fmt.pix.height; + components[2] = components[1] + (dest_fmt->fmt.pix.width * + dest_fmt->fmt.pix.height) / 4; + + switch (dest_fmt->fmt.pix.pixelformat) { + case V4L2_PIX_FMT_RGB24: + tinyjpeg_set_components(data->jdec, components, 1); + result = tinyjpeg_decode(data->jdec, TINYJPEG_FMT_RGB24); + break; + case V4L2_PIX_FMT_BGR24: + tinyjpeg_set_components(data->jdec, components, 1); + result = tinyjpeg_decode(data->jdec, TINYJPEG_FMT_BGR24); + break; + default: + tinyjpeg_set_components(data->jdec, components, 3); + result = tinyjpeg_decode(data->jdec, TINYJPEG_FMT_YUV420P); + break; + } + + if (result) { + /* Pixart webcam's seem to regulary generate corrupt frames, which + are best thrown away to avoid flashes in the video stream. Tell + the upper layer this is an intermediate fault and it should try + again with a new buffer by setting errno to EAGAIN */ + if (src_fmt->fmt.pix.pixelformat == V4L2_PIX_FMT_PJPG) { + V4LCONVERT_ERR("Error decompressing JPEG: %s", + tinyjpeg_get_errorstring(data->jdec)); + errno = EAGAIN; + return -1; + } else { + /* If the JPEG header checked out ok and we get an error during actual + decompression, log the error, but don't return an errorcode to the + application, so that the user gets what we managed to decompress */ + fprintf(stderr, "libv4lconvert: Error decompressing JPEG: %s", + tinyjpeg_get_errorstring(data->jdec)); + } + } + break; + + case V4L2_PIX_FMT_SBGGR8: + case V4L2_PIX_FMT_SGBRG8: + case V4L2_PIX_FMT_SGRBG8: + case V4L2_PIX_FMT_SRGGB8: + switch (dest_fmt->fmt.pix.pixelformat) { + case V4L2_PIX_FMT_RGB24: + v4lconvert_bayer_to_rgb24(src, dest, dest_fmt->fmt.pix.width, + dest_fmt->fmt.pix.height, src_fmt->fmt.pix.pixelformat); + break; + case V4L2_PIX_FMT_BGR24: + v4lconvert_bayer_to_bgr24(src, dest, dest_fmt->fmt.pix.width, + dest_fmt->fmt.pix.height, src_fmt->fmt.pix.pixelformat); + break; + default: + v4lconvert_bayer_to_yuv420(src, dest, dest_fmt->fmt.pix.width, + dest_fmt->fmt.pix.height, src_fmt->fmt.pix.pixelformat); + break; + } + break; + + /* YUYV line by line formats */ + case V4L2_PIX_FMT_SPCA501: + case V4L2_PIX_FMT_SPCA505: + case V4L2_PIX_FMT_SPCA508: + { + unsigned char tmpbuf[dest_fmt->fmt.pix.width * dest_fmt->fmt.pix.height * + 3 / 2]; + unsigned char *my_dst = (dest_fmt->fmt.pix.pixelformat != + V4L2_PIX_FMT_YUV420) ? tmpbuf : dest; + + switch (src_fmt->fmt.pix.pixelformat) { + case V4L2_PIX_FMT_SPCA501: + v4lconvert_spca501_to_yuv420(src, my_dst, dest_fmt->fmt.pix.width, + dest_fmt->fmt.pix.height); + break; + case V4L2_PIX_FMT_SPCA505: + v4lconvert_spca505_to_yuv420(src, my_dst, dest_fmt->fmt.pix.width, + dest_fmt->fmt.pix.height); + break; + case V4L2_PIX_FMT_SPCA508: + v4lconvert_spca508_to_yuv420(src, my_dst, dest_fmt->fmt.pix.width, + dest_fmt->fmt.pix.height); + break; + } + + switch (dest_fmt->fmt.pix.pixelformat) { + case V4L2_PIX_FMT_RGB24: + v4lconvert_yuv420_to_rgb24(tmpbuf, dest, dest_fmt->fmt.pix.width, + dest_fmt->fmt.pix.height); + break; + case V4L2_PIX_FMT_BGR24: + v4lconvert_yuv420_to_bgr24(tmpbuf, dest, dest_fmt->fmt.pix.width, + dest_fmt->fmt.pix.height); + break; + } + break; + } + + /* compressed bayer formats */ + case V4L2_PIX_FMT_SPCA561: + case V4L2_PIX_FMT_SN9C10X: + case V4L2_PIX_FMT_PAC207: + { + unsigned char tmpbuf[dest_fmt->fmt.pix.width*dest_fmt->fmt.pix.height]; + unsigned int bayer_fmt = 0; + + switch (src_fmt->fmt.pix.pixelformat) { + case V4L2_PIX_FMT_SPCA561: + v4lconvert_decode_spca561(src, tmpbuf, dest_fmt->fmt.pix.width, + dest_fmt->fmt.pix.height); + bayer_fmt = V4L2_PIX_FMT_SGBRG8; + break; + case V4L2_PIX_FMT_SN9C10X: + v4lconvert_decode_sn9c10x(src, tmpbuf, dest_fmt->fmt.pix.width, + dest_fmt->fmt.pix.height); + bayer_fmt = V4L2_PIX_FMT_SBGGR8; + break; + case V4L2_PIX_FMT_PAC207: + v4lconvert_decode_pac207(src, tmpbuf, dest_fmt->fmt.pix.width, + dest_fmt->fmt.pix.height); + bayer_fmt = V4L2_PIX_FMT_SBGGR8; + break; + } + + switch (dest_fmt->fmt.pix.pixelformat) { + case V4L2_PIX_FMT_RGB24: + v4lconvert_bayer_to_rgb24(tmpbuf, dest, dest_fmt->fmt.pix.width, + dest_fmt->fmt.pix.height, bayer_fmt); + break; + case V4L2_PIX_FMT_BGR24: + v4lconvert_bayer_to_bgr24(tmpbuf, dest, dest_fmt->fmt.pix.width, + dest_fmt->fmt.pix.height, bayer_fmt); + break; + default: + v4lconvert_bayer_to_yuv420(tmpbuf, dest, dest_fmt->fmt.pix.width, + dest_fmt->fmt.pix.height, bayer_fmt); + break; + } + break; + } + + case V4L2_PIX_FMT_RGB24: + switch (dest_fmt->fmt.pix.pixelformat) { + case V4L2_PIX_FMT_BGR24: + v4lconvert_swap_rgb(src, dest, dest_fmt->fmt.pix.width, + dest_fmt->fmt.pix.height); + break; + case V4L2_PIX_FMT_YUV420: + printf("FIXME add rgb24 -> yuv420 conversion\n"); + break; + } + break; + case V4L2_PIX_FMT_BGR24: + switch (dest_fmt->fmt.pix.pixelformat) { + case V4L2_PIX_FMT_RGB24: + v4lconvert_swap_rgb(src, dest, dest_fmt->fmt.pix.width, + dest_fmt->fmt.pix.height); + break; + case V4L2_PIX_FMT_YUV420: + printf("FIXME add bgr24 -> yuv420 conversion\n"); + break; + } + break; + + case V4L2_PIX_FMT_YUV420: + switch (dest_fmt->fmt.pix.pixelformat) { + case V4L2_PIX_FMT_RGB24: + v4lconvert_yuv420_to_rgb24(src, dest, dest_fmt->fmt.pix.width, + dest_fmt->fmt.pix.height); + break; + case V4L2_PIX_FMT_BGR24: + v4lconvert_yuv420_to_bgr24(src, dest, dest_fmt->fmt.pix.width, + dest_fmt->fmt.pix.height); + break; + } + break; + + case V4L2_PIX_FMT_YUYV: + switch (dest_fmt->fmt.pix.pixelformat) { + case V4L2_PIX_FMT_RGB24: + v4lconvert_yuyv_to_rgb24(src, dest, dest_fmt->fmt.pix.width, + dest_fmt->fmt.pix.height); + break; + case V4L2_PIX_FMT_BGR24: + v4lconvert_yuyv_to_bgr24(src, dest, dest_fmt->fmt.pix.width, + dest_fmt->fmt.pix.height); + break; + default: + v4lconvert_yuyv_to_yuv420(src, dest, dest_fmt->fmt.pix.width, + dest_fmt->fmt.pix.height); + break; + } + break; + + case V4L2_PIX_FMT_YVYU: + switch (dest_fmt->fmt.pix.pixelformat) { + case V4L2_PIX_FMT_RGB24: + v4lconvert_yvyu_to_rgb24(src, dest, dest_fmt->fmt.pix.width, + dest_fmt->fmt.pix.height); + break; + case V4L2_PIX_FMT_BGR24: + v4lconvert_yvyu_to_bgr24(src, dest, dest_fmt->fmt.pix.width, + dest_fmt->fmt.pix.height); + break; + default: + v4lconvert_yvyu_to_yuv420(src, dest, dest_fmt->fmt.pix.width, + dest_fmt->fmt.pix.height); + break; + } + break; + + default: + V4LCONVERT_ERR("Unknown src format in conversion\n"); + errno = EINVAL; + return -1; + } + + /* Note when rotating dest is our temporary buffer to which our conversion + was done and _dest is the real dest! If the formats are identical no + conversion has been done! */ + if (rotate && dest_fmt->fmt.pix.pixelformat == src_fmt->fmt.pix.pixelformat) + dest = src; + + switch (rotate) { + case 0: + break; + case 90: + switch (dest_fmt->fmt.pix.pixelformat) { + case V4L2_PIX_FMT_RGB24: + case V4L2_PIX_FMT_BGR24: + v4lconvert_rotate90_rgbbgr24(dest, _dest, dest_fmt->fmt.pix.width, + dest_fmt->fmt.pix.height); + break; + case V4L2_PIX_FMT_YUV420: + v4lconvert_rotate90_yuv420(dest, _dest, dest_fmt->fmt.pix.width, + dest_fmt->fmt.pix.height); + break; + } + break; + case 180: + switch (dest_fmt->fmt.pix.pixelformat) { + case V4L2_PIX_FMT_RGB24: + case V4L2_PIX_FMT_BGR24: + v4lconvert_rotate180_rgbbgr24(dest, _dest, dest_fmt->fmt.pix.width, + dest_fmt->fmt.pix.height); + break; + case V4L2_PIX_FMT_YUV420: + v4lconvert_rotate180_yuv420(dest, _dest, dest_fmt->fmt.pix.width, + dest_fmt->fmt.pix.height); + break; + } + break; + default: + printf("FIXME add %d degrees rotation\n", rotate); + } + + return needed; +} + +const char *v4lconvert_get_error_message(struct v4lconvert_data *data) +{ + return data->error_msg; +} + +static void v4lconvert_get_framesizes(struct v4lconvert_data *data, + unsigned int pixelformat) +{ + int i, j, match; + struct v4l2_frmsizeenum frmsize = { .pixel_format = pixelformat }; + + for (i = 0; ; i++) { + frmsize.index = i; + if (syscall(SYS_ioctl, data->fd, VIDIOC_ENUM_FRAMESIZES, &frmsize)) + break; + + /* We got a framesize, check we don't have the same one already */ + match = 0; + for (j = 0; j < data->no_framesizes && !match; j++) { + if (frmsize.type != data->framesizes[j].type) + continue; + + switch(frmsize.type) { + case V4L2_FRMSIZE_TYPE_DISCRETE: + if(!memcmp(&frmsize.discrete, &data->framesizes[j].discrete, + sizeof(frmsize.discrete))) + match = 1; + break; + case V4L2_FRMSIZE_TYPE_CONTINUOUS: + case V4L2_FRMSIZE_TYPE_STEPWISE: + if(!memcmp(&frmsize.stepwise, &data->framesizes[j].stepwise, + sizeof(frmsize.stepwise))) + match = 1; + break; + } + } + /* Add this framesize if it is not already in our list */ + if (!match) { + if (data->no_framesizes == V4LCONVERT_MAX_FRAMESIZES) { + fprintf(stderr, + "libv4lconvert: warning more framesizes then I can handle!\n"); + return; + } + data->framesizes[data->no_framesizes].type = frmsize.type; + switch(frmsize.type) { + case V4L2_FRMSIZE_TYPE_DISCRETE: + data->framesizes[data->no_framesizes].discrete = frmsize.discrete; + break; + case V4L2_FRMSIZE_TYPE_CONTINUOUS: + case V4L2_FRMSIZE_TYPE_STEPWISE: + data->framesizes[data->no_framesizes].stepwise = frmsize.stepwise; + break; + } + data->no_framesizes++; + } + } +} + +int v4lconvert_enum_framesizes(struct v4lconvert_data *data, + struct v4l2_frmsizeenum *frmsize) +{ + if (!v4lconvert_supported_dst_format(frmsize->pixel_format)) + return syscall(SYS_ioctl, data->fd, VIDIOC_ENUM_FRAMESIZES, frmsize); + + if (frmsize->index >= data->no_framesizes) { + errno = EINVAL; + return -1; + } + + frmsize->type = data->framesizes[frmsize->index].type; + switch(frmsize->type) { + case V4L2_FRMSIZE_TYPE_DISCRETE: + frmsize->discrete = data->framesizes[frmsize->index].discrete; + break; + case V4L2_FRMSIZE_TYPE_CONTINUOUS: + case V4L2_FRMSIZE_TYPE_STEPWISE: + frmsize->stepwise = data->framesizes[frmsize->index].stepwise; + break; + } + + return 0; +} + +int v4lconvert_enum_frameintervals(struct v4lconvert_data *data, + struct v4l2_frmivalenum *frmival) +{ + int res; + struct v4l2_format src_fmt, dest_fmt; + + if (!v4lconvert_supported_dst_format(frmival->pixel_format)) + return syscall(SYS_ioctl, data->fd, VIDIOC_ENUM_FRAMEINTERVALS, frmival); + + /* Check which format we will be using to convert to frmival->pixel_format */ + memset(&dest_fmt, 0, sizeof(dest_fmt)); + dest_fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + dest_fmt.fmt.pix.pixelformat = frmival->pixel_format; + dest_fmt.fmt.pix.width = frmival->width; + dest_fmt.fmt.pix.height = frmival->height; + if ((res = v4lconvert_try_format(data, &dest_fmt, &src_fmt))) + return res; + + /* Check the requested format is supported exactly as requested */ + if (dest_fmt.fmt.pix.pixelformat != frmival->pixel_format || + dest_fmt.fmt.pix.width != frmival->width || + dest_fmt.fmt.pix.height != frmival->height) { + errno = EINVAL; + return -1; + } + + /* Enumerate the frameintervals of the source format we will be using */ + frmival->pixel_format = src_fmt.fmt.pix.pixelformat; + frmival->width = src_fmt.fmt.pix.width; + frmival->height = src_fmt.fmt.pix.height; + res = syscall(SYS_ioctl, data->fd, VIDIOC_ENUM_FRAMEINTERVALS, frmival); + + /* Restore the requested format in the frmival struct */ + frmival->pixel_format = dest_fmt.fmt.pix.pixelformat; + frmival->width = dest_fmt.fmt.pix.width; + frmival->height = dest_fmt.fmt.pix.height; + + return res; +} diff --git a/v4l2-apps/libv4l/libv4lconvert/pac207.c b/v4l2-apps/libv4l/libv4lconvert/pac207.c new file mode 100644 index 000000000..97ef4ebc0 --- /dev/null +++ b/v4l2-apps/libv4l/libv4lconvert/pac207.c @@ -0,0 +1,418 @@ +/* + +# PAC207 decoder +# Bertrik.Sikken. Thomas Kaiser (C) 2005 +# Copyright (C) 2003 2004 2005 Michel Xhaard + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +# Note this code was originally licensed under the GNU GPL instead of the +# GNU LGPL, its license has been changed with permission, see the permission +# mails at the end of this file. + +*/ + +#include +#include "libv4lconvert-priv.h" + +#define CLIP(color) (unsigned char)(((color)>0xFF)?0xff:(((color)<0)?0:(color))) + +/* FIXME not threadsafe */ +static int decoder_initialized = 0; + +static struct { + unsigned char is_abs; + unsigned char len; + signed char val; +} table[256]; + +static void init_pixart_decoder(void) +{ + int i; + int is_abs, val, len; + for (i = 0; i < 256; i++) { + is_abs = 0; + val = 0; + len = 0; + if ((i & 0xC0) == 0) { + /* code 00 */ + val = 0; + len = 2; + } else if ((i & 0xC0) == 0x40) { + /* code 01 */ + val = -5; + len = 2; + } else if ((i & 0xC0) == 0x80) { + /* code 10 */ + val = +5; + len = 2; + } else if ((i & 0xF0) == 0xC0) { + /* code 1100 */ + val = -10; + len = 4; + } else if ((i & 0xF0) == 0xD0) { + /* code 1101 */ + val = +10; + len = 4; + } else if ((i & 0xF8) == 0xE0) { + /* code 11100 */ + val = -15; + len = 5; + } else if ((i & 0xF8) == 0xE8) { + /* code 11101 */ + val = +15; + len = 5; + } else if ((i & 0xFC) == 0xF0) { + /* code 111100 */ + val = -20; + len = 6; + } else if ((i & 0xFC) == 0xF4) { + /* code 111101 */ + val = +20; + len = 6; + } else if ((i & 0xF8) == 0xF8) { + /* code 11111xxxxxx */ + is_abs = 1; + val = 0; + len = 5; + } + table[i].is_abs = is_abs; + table[i].val = val; + table[i].len = len; + } + decoder_initialized = 1; +} + +static inline unsigned char getByte(const unsigned char *inp, + unsigned int bitpos) +{ + const unsigned char *addr; + addr = inp + (bitpos >> 3); + return (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7))); +} + +static inline unsigned short getShort(const unsigned char *pt) +{ + return ((pt[0] << 8) | pt[1]); +} + +static int +pac_decompress_row(const unsigned char *inp, unsigned char *outp, int width) +{ + int col; + int val; + int bitpos; + unsigned char code; + + if (!decoder_initialized) + init_pixart_decoder(); + + /* first two pixels are stored as raw 8-bit */ + *outp++ = inp[2]; + *outp++ = inp[3]; + bitpos = 32; + + /* main decoding loop */ + for (col = 2; col < width; col++) { + /* get bitcode */ + + code = getByte(inp, bitpos); + bitpos += table[code].len; + + /* calculate pixel value */ + if (table[code].is_abs) { + /* absolute value: get 6 more bits */ + code = getByte(inp, bitpos); + bitpos += 6; + *outp++ = code & 0xFC; + } else { + /* relative to left pixel */ + val = outp[-2] + table[code].val; + *outp++ = CLIP(val); + } + } + + /* return line length, rounded up to next 16-bit word */ + return 2 * ((bitpos + 15) / 16); +} + +void v4lconvert_decode_pac207(const unsigned char *inp, unsigned char *outp, + int width, int height) +{ +/* we should received a whole frame with header and EOL marker +in myframe->data and return a GBRG pattern in frame->tmpbuffer +remove the header then copy line by line EOL is set with 0x0f 0xf0 marker +or 0x1e 0xe1 for compressed line*/ + unsigned short word; + int row; + + /* iterate over all rows */ + for (row = 0; row < height; row++) { + word = getShort(inp); + switch (word) { + case 0x0FF0: + memcpy(outp, inp + 2, width); + inp += (2 + width); + break; + case 0x1EE1: + inp += pac_decompress_row(inp, outp, width); + break; + + case 0x2DD2: /* prefix for "stronger" compressed lines, currently the + kernel driver programs the cam so that we should not + get any of these */ + + default: /* corrupt frame */ + /* FIXME add error reporting */ + return; + } + outp += width; + } + + return; +} + + + + +/* +Return-Path: +Received: from koko.hhs.nl ([145.52.2.16] verified) + by hhs.nl (CommuniGate Pro SMTP 4.3.6) + with ESMTP id 88906346 for j.w.r.degoede@hhs.nl; Thu, 26 Jun 2008 01:17:00 +0200 +Received: from exim (helo=koko) + by koko.hhs.nl with local-smtp (Exim 4.62) + (envelope-from ) + id 1KBeEW-0001qu-H6 + for j.w.r.degoede@hhs.nl; Thu, 26 Jun 2008 01:17:00 +0200 +Received: from [192.87.102.74] (port=41049 helo=filter6-ams.mf.surf.net) + by koko.hhs.nl with esmtp (Exim 4.62) + (envelope-from ) + id 1KBeEV-0001qn-2T + for j.w.r.degoede@hhs.nl; Thu, 26 Jun 2008 01:17:00 +0200 +Received: from smtp0.lie-comtel.li (smtp0.lie-comtel.li [217.173.238.80]) + by filter6-ams.mf.surf.net (8.13.8/8.13.8/Debian-3) with ESMTP id m5PNGwSF007539 + for ; Thu, 26 Jun 2008 01:16:58 +0200 +Received: from localhost (localhost.lie-comtel.li [127.0.0.1]) + by smtp0.lie-comtel.li (Postfix) with ESMTP id DDB609FEC1D; + Thu, 26 Jun 2008 00:16:56 +0100 (GMT-1) +X-Virus-Scanned: Virus scanned by amavis at smtp.lie-comtel.li +Received: from [192.168.0.16] (217-173-228-198.cmts.powersurf.li [217.173.228.198]) + by smtp0.lie-comtel.li (Postfix) with ESMTP id 80B589FEC19; + Thu, 26 Jun 2008 00:16:56 +0100 (GMT-1) +Message-ID: <4862D211.3000802@kaiser-linux.li> +Date: Thu, 26 Jun 2008 01:17:37 +0200 +From: Thomas Kaiser +User-Agent: Thunderbird 2.0.0.14 (X11/20080505) +MIME-Version: 1.0 +To: Hans de Goede +CC: Thomas Kaiser , bertrik@zonnet.nl, + mxhaard@magic.fr +Subject: Re: pac207 bayer decompression algorithm license question +References: <4862C0A4.3060003@hhs.nl> +In-Reply-To: <4862C0A4.3060003@hhs.nl> +Content-Type: text/plain; charset=ISO-8859-1; format=flowed +Content-Transfer-Encoding: 7bit +X-Canit-CHI2: 0.00 +X-Bayes-Prob: 0.0001 (Score 0, tokens from: @@RPTN) +X-Spam-Score: 0.00 () [Tag at 8.00] +X-CanItPRO-Stream: hhs:j.w.r.degoede@hhs.nl (inherits from hhs:default,base:default) +X-Canit-Stats-ID: 88604132 - 38b3b44cd798 +X-Scanned-By: CanIt (www . roaringpenguin . com) on 192.87.102.74 +X-Anti-Virus: Kaspersky Anti-Virus for MailServers 5.5.2/RELEASE, bases: 25062008 #787666, status: clean + +Hello Hans + +Hans de Goede wrote: +> Hi, +> +> As you may have seen on the mailinglist, I've created a userspace +> library to handle cam specific format handling in userspace where it +> belongs, see: +> http://hansdegoede.livejournal.com/ +Yes, I saw it on the mail list and I think it is a good idea :-) +> +> I would like to also add support for decompressing the pac207's +> compressed bayer to this lib (and remove it from the kernel driver) +> for this I need permission to relicense the decompress code under the +> LGPL (version 2 or later). +Actually, this was done by Bertrik Sikken (bertrik@zonnet.nl), Michel +Xhaard (mxhaard@magic.fr) and me. But Bertrik was the one who found out +how to decode the lines :-) +> +> Can you give me permission for this, or if the code is not yours put +> me in contact with someone who can? +For me it's no problem to release it with LGPL. Maybe you have to ask +the other one's also. +> +> Thanks & Regards, +> +> Hans + +Rgeards, Thomas +*/ + +/* +Return-Path: +Received: from koko.hhs.nl ([145.52.2.16] verified) + by hhs.nl (CommuniGate Pro SMTP 4.3.6) + with ESMTP id 88910192 for j.w.r.degoede@hhs.nl; Thu, 26 Jun 2008 09:15:37 +0200 +Received: from exim (helo=koko) + by koko.hhs.nl with local-smtp (Exim 4.62) + (envelope-from ) + id 1KBlhh-0006Fi-Oe + for j.w.r.degoede@hhs.nl; Thu, 26 Jun 2008 09:15:37 +0200 +Received: from [194.171.167.220] (port=54180 helo=filter4-til.mf.surf.net) + by koko.hhs.nl with esmtp (Exim 4.62) + (envelope-from ) + id 1KBlhh-0006Fd-FY + for j.w.r.degoede@hhs.nl; Thu, 26 Jun 2008 09:15:37 +0200 +Received: from smtp4-g19.free.fr (smtp4-g19.free.fr [212.27.42.30]) + by filter4-til.mf.surf.net (8.13.8/8.13.8/Debian-3) with ESMTP id m5Q7FY1I006360 + for ; Thu, 26 Jun 2008 09:15:34 +0200 +Received: from smtp4-g19.free.fr (localhost.localdomain [127.0.0.1]) + by smtp4-g19.free.fr (Postfix) with ESMTP id 51C683EA0E7; + Thu, 26 Jun 2008 09:15:34 +0200 (CEST) +Received: from [192.168.1.11] (lns-bzn-54-82-251-105-53.adsl.proxad.net [82.251.105.53]) + by smtp4-g19.free.fr (Postfix) with ESMTP id 1149E3EA0C7; + Thu, 26 Jun 2008 09:15:34 +0200 (CEST) +From: Michel Xhaard +To: Hans de Goede +Subject: Re: pac207 bayer decompression algorithm license question +Date: Thu, 26 Jun 2008 11:15:32 +0200 +User-Agent: KMail/1.9.5 +Cc: bertrik@zonnet.nl, spca5xx@kaiser-linux.li, + "Jean-Francois Moine" +References: <48633F02.3040108@hhs.nl> +In-Reply-To: <48633F02.3040108@hhs.nl> +MIME-Version: 1.0 +Content-Type: text/plain; + charset="iso-8859-1" +Content-Transfer-Encoding: quoted-printable +Content-Disposition: inline +Message-Id: <200806261115.32909.mxhaard@magic.fr> +X-Canit-CHI2: 0.00 +X-Bayes-Prob: 0.0001 (Score 0, tokens from: @@RPTN) +X-Spam-Score: 0.00 () [Tag at 8.00] +X-CanItPRO-Stream: hhs:j.w.r.degoede@hhs.nl (inherits from hhs:default,base:default) +X-Canit-Stats-ID: 88656338 - 0dde233cb8b5 +X-Scanned-By: CanIt (www . roaringpenguin . com) on 194.171.167.220 +X-Anti-Virus: Kaspersky Anti-Virus for MailServers 5.5.2/RELEASE, bases: 26062008 #787720, status: clean + +Le jeudi 26 juin 2008 09:02, Hans de Goede a =E9crit=A0: +> Hi, +> +> As you may have seen on the mailinglist, I've created a userspace library +> to handle cam specific format handling in userspace, see: +> http://hansdegoede.livejournal.com/ +> +> I would like to also add support for decompressing the pac207's compressed +> bayer to this lib (and remove it from the kernel driver) and I've heard +> from Thomas Kaiser that you are a co-author of the decompression code. In +> order to add support for decompressing pac207 compressed bayer to libv4l I +> need permission to relicense the decompression code under the LGPL (versi= +on +> 2 or later). +> +> Can you give me permission for this? +> +> Thanks & Regards, +> +> Hans +> +> +> +> p.s. +> +> Thomas has already given permission. + +=46or me it is ok and a good idea for all free world familly ;-). +Bests regards +=2D-=20 +Michel Xhaard +http://mxhaard.free.fr +*/ + +/* +Return-Path: +Received: from koko.hhs.nl ([145.52.2.16] verified) + by hhs.nl (CommuniGate Pro SMTP 4.3.6) + with ESMTP id 88940205 for j.w.r.degoede@hhs.nl; Thu, 26 Jun 2008 22:03:30 +0200 +Received: from exim (helo=koko) + by koko.hhs.nl with local-smtp (Exim 4.62) + (envelope-from ) + id 1KBxgo-0003Dj-ET + for j.w.r.degoede@hhs.nl; Thu, 26 Jun 2008 22:03:30 +0200 +Received: from [192.87.102.69] (port=51992 helo=filter1-ams.mf.surf.net) + by koko.hhs.nl with esmtp (Exim 4.62) + (envelope-from ) + id 1KBxgo-0003Dd-5i + for j.w.r.degoede@hhs.nl; Thu, 26 Jun 2008 22:03:30 +0200 +Received: from pelian.kabelfoon.nl (pelian3.kabelfoon.nl [62.45.45.106]) + by filter1-ams.mf.surf.net (8.13.8/8.13.8/Debian-3) with ESMTP id m5QK3ThE007720 + for ; Thu, 26 Jun 2008 22:03:29 +0200 +Received: from [192.168.1.1] (062-015-045-062.dynamic.caiway.nl [62.45.15.62]) + by pelian.kabelfoon.nl (Postfix) with ESMTP id 9239B428100 + for ; Thu, 26 Jun 2008 22:03:29 +0200 (CEST) +Message-ID: <4863F611.80104@sikken.nl> +Date: Thu, 26 Jun 2008 22:03:29 +0200 +From: Bertrik Sikken +User-Agent: Thunderbird 2.0.0.14 (Windows/20080421) +MIME-Version: 1.0 +To: Hans de Goede +Subject: Re: pac207 bayer decompression algorithm license question +References: <48633F02.3040108@hhs.nl> +In-Reply-To: <48633F02.3040108@hhs.nl> +X-Enigmail-Version: 0.95.6 +Content-Type: text/plain; charset=ISO-8859-1; format=flowed +Content-Transfer-Encoding: 7bit +X-Canit-CHI2: 0.00 +X-Bayes-Prob: 0.0001 (Score 0, tokens from: @@RPTN) +X-Spam-Score: 0.00 () [Tag at 8.00] +X-CanItPRO-Stream: hhs:j.w.r.degoede@hhs.nl (inherits from hhs:default,base:default) +X-Canit-Stats-ID: 88938005 - ef1f0836ffc7 +X-Scanned-By: CanIt (www . roaringpenguin . com) on 192.87.102.69 +X-Anti-Virus: Kaspersky Anti-Virus for MailServers 5.5.2/RELEASE, bases: 26062008 #787877, status: clean + +Hallo Hans, + +Hans de Goede wrote: +> Hi, +> +> As you may have seen on the mailinglist, I've created a userspace +> library to +> handle cam specific format handling in userspace, see: +> http://hansdegoede.livejournal.com/ + +O leuk, zoiets is naar mijn idee precies wat er nodig is voor webcam +support onder linux. Ik ben een jaar of 3 geleden heel actief geweest +met een aantal webcams, maar doe er tegenwoordig helemaal niets meer +aan. + +> I would like to also add support for decompressing the pac207's compressed +> bayer to this lib (and remove it from the kernel driver) and I've heard +> from Thomas Kaiser that you are a co-author of the decompression code. +> In order to add support for decompressing pac207 compressed bayer to +> libv4l I need +> permission to relicense the decompression code under the LGPL (version 2 +> or later). +> +> Can you give me permission for this? + +Ja, vind ik goed. + +Vriendelijke groet, +Bertrik +*/ diff --git a/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c b/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c new file mode 100644 index 000000000..0f26b227a --- /dev/null +++ b/v4l2-apps/libv4l/libv4lconvert/rgbyuv.c @@ -0,0 +1,316 @@ +/* + +# RGB <-> YUV conversion routines + +# (C) 2008 Hans de Goede + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +*/ + +#include "libv4lconvert-priv.h" + +#define RGB2YUV(r,g,b,y,u,v) \ + (y) = (( 8453*(r) + 16594*(g) + 3223*(b) + 524288) >> 15); \ + (u) = (( -4878*(r) - 9578*(g) + 14456*(b) + 4210688) >> 15); \ + (v) = (( 14456*(r) - 12105*(g) - 2351*(b) + 4210688) >> 15) + +#define YUV2R(y, u, v) ({ \ + int r = (y) + ((((v)-128)*1436) >> 10); r > 255 ? 255 : r < 0 ? 0 : r; }) +#define YUV2G(y, u, v) ({ \ + int g = (y) - ((((u)-128)*352 + ((v)-128)*731) >> 10); g > 255 ? 255 : g < 0 ? 0 : g; }) +#define YUV2B(y, u, v) ({ \ + int b = (y) + ((((u)-128)*1814) >> 10); b > 255 ? 255 : b < 0 ? 0 : b; }) + +#define CLIP(color) (unsigned char)(((color)>0xFF)?0xff:(((color)<0)?0:(color))) + +void v4lconvert_yuv420_to_bgr24(const unsigned char *src, unsigned char *dest, + int width, int height) +{ + int i,j; + + const unsigned char *ysrc = src; + const unsigned char *usrc = src + width * height; + const unsigned char *vsrc = usrc + (width * height) / 4; + + for (i = 0; i < height; i++) { + for (j = 0; j < width; j += 2) { +#if 1 /* fast slightly less accurate multiplication free code */ + int u1 = (((*usrc - 128) << 7) + (*usrc - 128)) >> 6; + int rg = (((*usrc - 128) << 1) + (*usrc - 128) + + ((*vsrc - 128) << 2) + ((*vsrc - 128) << 1)) >> 3; + int v1 = (((*vsrc - 128) << 1) + (*vsrc - 128)) >> 1; + + *dest++ = CLIP(*ysrc + u1); + *dest++ = CLIP(*ysrc - rg); + *dest++ = CLIP(*ysrc + v1); + ysrc++; + + *dest++ = CLIP(*ysrc + u1); + *dest++ = CLIP(*ysrc - rg); + *dest++ = CLIP(*ysrc + v1); +#else + *dest++ = YUV2B(*ysrc, *usrc, *vsrc); + *dest++ = YUV2G(*ysrc, *usrc, *vsrc); + *dest++ = YUV2R(*ysrc, *usrc, *vsrc); + ysrc++; + + *dest++ = YUV2B(*ysrc, *usrc, *vsrc); + *dest++ = YUV2G(*ysrc, *usrc, *vsrc); + *dest++ = YUV2R(*ysrc, *usrc, *vsrc); +#endif + ysrc++; + usrc++; + vsrc++; + } + /* Rewind u and v for next line */ + if (i&1) { + usrc -= width / 2; + vsrc -= width / 2; + } + } +} + +void v4lconvert_yuv420_to_rgb24(const unsigned char *src, unsigned char *dest, + int width, int height) +{ + int i,j; + + const unsigned char *ysrc = src; + const unsigned char *usrc = src + width * height; + const unsigned char *vsrc = usrc + (width * height) / 4; + + for (i = 0; i < height; i++) { + for (j = 0; j < width; j += 2) { +#if 1 /* fast slightly less accurate multiplication free code */ + int u1 = (((*usrc - 128) << 7) + (*usrc - 128)) >> 6; + int rg = (((*usrc - 128) << 1) + (*usrc - 128) + + ((*vsrc - 128) << 2) + ((*vsrc - 128) << 1)) >> 3; + int v1 = (((*vsrc - 128) << 1) + (*vsrc - 128)) >> 1; + + *dest++ = CLIP(*ysrc + v1); + *dest++ = CLIP(*ysrc - rg); + *dest++ = CLIP(*ysrc + u1); + ysrc++; + + *dest++ = CLIP(*ysrc + v1); + *dest++ = CLIP(*ysrc - rg); + *dest++ = CLIP(*ysrc + u1); +#else + *dest++ = YUV2R(*ysrc, *usrc, *vsrc); + *dest++ = YUV2G(*ysrc, *usrc, *vsrc); + *dest++ = YUV2B(*ysrc, *usrc, *vsrc); + ysrc++; + + *dest++ = YUV2R(*ysrc, *usrc, *vsrc); + *dest++ = YUV2G(*ysrc, *usrc, *vsrc); + *dest++ = YUV2B(*ysrc, *usrc, *vsrc); +#endif + ysrc++; + usrc++; + vsrc++; + } + /* Rewind u and v for next line */ + if (i&1) { + usrc -= width / 2; + vsrc -= width / 2; + } + } +} + +void v4lconvert_yuyv_to_bgr24(const unsigned char *src, unsigned char *dest, + int width, int height) +{ + int j; + + while (--height >= 0) { + for (j = 0; j < width; j += 2) { + int u = src[1]; + int v = src[3]; + int u1 = (((u - 128) << 7) + (u - 128)) >> 6; + int rg = (((u - 128) << 1) + (u - 128) + + ((v - 128) << 2) + ((v - 128) << 1)) >> 3; + int v1 = (((v - 128) << 1) + (v - 128)) >> 1; + + *dest++ = CLIP(src[0] + u1); + *dest++ = CLIP(src[0] - rg); + *dest++ = CLIP(src[0] + v1); + + *dest++ = CLIP(src[2] + u1); + *dest++ = CLIP(src[2] - rg); + *dest++ = CLIP(src[2] + v1); + src += 4; + } + } +} + +void v4lconvert_yuyv_to_rgb24(const unsigned char *src, unsigned char *dest, + int width, int height) +{ + int j; + + while (--height >= 0) { + for (j = 0; j < width; j += 2) { + int u = src[1]; + int v = src[3]; + int u1 = (((u - 128) << 7) + (u - 128)) >> 6; + int rg = (((u - 128) << 1) + (u - 128) + + ((v - 128) << 2) + ((v - 128) << 1)) >> 3; + int v1 = (((v - 128) << 1) + (v - 128)) >> 1; + + *dest++ = CLIP(src[0] + v1); + *dest++ = CLIP(src[0] - rg); + *dest++ = CLIP(src[0] + u1); + + *dest++ = CLIP(src[2] + v1); + *dest++ = CLIP(src[2] - rg); + *dest++ = CLIP(src[2] + u1); + src += 4; + } + } +} + +void v4lconvert_yuyv_to_yuv420(const unsigned char *src, unsigned char *dest, + int width, int height) +{ + int i, j; + const unsigned char *src1; + unsigned char *vdest; + + /* copy the Y values */ + src1 = src; + for (i = 0; i < height; i++) { + for (j = 0; j < width; j += 2) { + *dest++ = src1[0]; + *dest++ = src1[2]; + src1 += 4; + } + } + + /* copy the U and V values */ + src++; /* point to V */ + src1 = src + width * 2; /* next line */ + vdest = dest + width * height / 4; + for (i = 0; i < height; i += 2) { + for (j = 0; j < width; j += 2) { + *dest++ = ((int) src[0] + src1[0]) / 2; /* U */ + *vdest++ = ((int) src[2] + src1[2]) / 2; /* V */ + src += 4; + src1 += 4; + } + src = src1; + src1 += width * 2; + } +} + +void v4lconvert_yvyu_to_bgr24(const unsigned char *src, unsigned char *dest, + int width, int height) +{ + int j; + + while (--height >= 0) { + for (j = 0; j < width; j += 2) { + int u = src[3]; + int v = src[1]; + int u1 = (((u - 128) << 7) + (u - 128)) >> 6; + int rg = (((u - 128) << 1) + (u - 128) + + ((v - 128) << 2) + ((v - 128) << 1)) >> 3; + int v1 = (((v - 128) << 1) + (v - 128)) >> 1; + + *dest++ = CLIP(src[0] + u1); + *dest++ = CLIP(src[0] - rg); + *dest++ = CLIP(src[0] + v1); + + *dest++ = CLIP(src[2] + u1); + *dest++ = CLIP(src[2] - rg); + *dest++ = CLIP(src[2] + v1); + src += 4; + } + } +} + +void v4lconvert_yvyu_to_rgb24(const unsigned char *src, unsigned char *dest, + int width, int height) +{ + int j; + + while (--height >= 0) { + for (j = 0; j < width; j += 2) { + int u = src[3]; + int v = src[1]; + int u1 = (((u - 128) << 7) + (u - 128)) >> 6; + int rg = (((u - 128) << 1) + (u - 128) + + ((v - 128) << 2) + ((v - 128) << 1)) >> 3; + int v1 = (((v - 128) << 1) + (v - 128)) >> 1; + + *dest++ = CLIP(src[0] + v1); + *dest++ = CLIP(src[0] - rg); + *dest++ = CLIP(src[0] + u1); + + *dest++ = CLIP(src[2] + v1); + *dest++ = CLIP(src[2] - rg); + *dest++ = CLIP(src[2] + u1); + src += 4; + } + } +} + +void v4lconvert_yvyu_to_yuv420(const unsigned char *src, unsigned char *dest, + int width, int height) +{ + int i, j; + const unsigned char *src1; + unsigned char *vdest; + + /* copy the Y values */ + src1 = src; + for (i = 0; i < height; i++) { + for (j = 0; j < width; j += 2) { + *dest++ = src1[0]; + *dest++ = src1[2]; + src1 += 4; + } + } + + /* copy the U and V values */ + src++; /* point to V */ + src1 = src + width * 2; /* next line */ + vdest = dest + width * height / 4; + for (i = 0; i < height; i += 2) { + for (j = 0; j < width; j += 2) { + *dest++ = ((int) src[2] + src1[2]) / 2; /* U */ + *vdest++ = ((int) src[0] + src1[0]) / 2; /* V */ + src += 4; + src1 += 4; + } + src = src1; + src1 += width * 2; + } +} + +void v4lconvert_swap_rgb(const unsigned char *src, unsigned char *dst, + int width, int height) +{ + int i; + + for (i = 0; i < (width * height); i++) { + unsigned char tmp0, tmp1; + tmp0 = *src++; + tmp1 = *src++; + *dst++ = *src++; + *dst++ = tmp1; + *dst++ = tmp0; + } +} diff --git a/v4l2-apps/libv4l/libv4lconvert/sn9c10x.c b/v4l2-apps/libv4l/libv4lconvert/sn9c10x.c new file mode 100644 index 000000000..4ea526d49 --- /dev/null +++ b/v4l2-apps/libv4l/libv4lconvert/sn9c10x.c @@ -0,0 +1,287 @@ +/* +# sonix decoder +# Bertrik.Sikken. (C) 2005 + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +# Note this code was originally licensed under the GNU GPL instead of the +# GNU LGPL, its license has been changed with permission, see the permission +# mail at the end of this file. +*/ + +#include "libv4lconvert-priv.h" + +#define CLAMP(x) ((x)<0?0:((x)>255)?255:(x)) + +typedef struct { + int is_abs; + int len; + int val; + int unk; +} code_table_t; + + +/* local storage */ +/* FIXME not thread safe !! */ +static code_table_t table[256]; +static int init_done = 0; + +/* global variable */ +static int sonix_unknown = 0; + +/* + sonix_decompress_init + ===================== + pre-calculates a locally stored table for efficient huffman-decoding. + + Each entry at index x in the table represents the codeword + present at the MSB of byte x. + +*/ +static void sonix_decompress_init(void) +{ + int i; + int is_abs, val, len, unk; + + for (i = 0; i < 256; i++) { + is_abs = 0; + val = 0; + len = 0; + unk = 0; + if ((i & 0x80) == 0) { + /* code 0 */ + val = 0; + len = 1; + } + else if ((i & 0xE0) == 0x80) { + /* code 100 */ + val = +4; + len = 3; + } + else if ((i & 0xE0) == 0xA0) { + /* code 101 */ + val = -4; + len = 3; + } + else if ((i & 0xF0) == 0xD0) { + /* code 1101 */ + val = +11; + len = 4; + } + else if ((i & 0xF0) == 0xF0) { + /* code 1111 */ + val = -11; + len = 4; + } + else if ((i & 0xF8) == 0xC8) { + /* code 11001 */ + val = +20; + len = 5; + } + else if ((i & 0xFC) == 0xC0) { + /* code 110000 */ + val = -20; + len = 6; + } + else if ((i & 0xFC) == 0xC4) { + /* code 110001xx: unknown */ + val = 0; + len = 8; + unk = 1; + } + else if ((i & 0xF0) == 0xE0) { + /* code 1110xxxx */ + is_abs = 1; + val = (i & 0x0F) << 4; + len = 8; + } + table[i].is_abs = is_abs; + table[i].val = val; + table[i].len = len; + table[i].unk = unk; + } + + sonix_unknown = 0; + init_done = 1; +} + + +/* + sonix_decompress + ================ + decompresses an image encoded by a SN9C101 camera controller chip. + + IN width + height + inp pointer to compressed frame (with header already stripped) + OUT outp pointer to decompressed frame + + Returns 0 if the operation was successful. + Returns <0 if operation failed. + +*/ +void v4lconvert_decode_sn9c10x(const unsigned char *inp, unsigned char *outp, + int width, int height) +{ + int row, col; + int val; + int bitpos; + unsigned char code; + const unsigned char *addr; + + if (!init_done) + sonix_decompress_init(); + + bitpos = 0; + for (row = 0; row < height; row++) { + + col = 0; + + /* first two pixels in first two rows are stored as raw 8-bit */ + if (row < 2) { + addr = inp + (bitpos >> 3); + code = (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7))); + bitpos += 8; + *outp++ = code; + + addr = inp + (bitpos >> 3); + code = (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7))); + bitpos += 8; + *outp++ = code; + + col += 2; + } + + while (col < width) { + /* get bitcode from bitstream */ + addr = inp + (bitpos >> 3); + code = (addr[0] << (bitpos & 7)) | (addr[1] >> (8 - (bitpos & 7))); + + /* update bit position */ + bitpos += table[code].len; + + /* update code statistics */ + sonix_unknown += table[code].unk; + + /* calculate pixel value */ + val = table[code].val; + if (!table[code].is_abs) { + /* value is relative to top and left pixel */ + if (col < 2) { + /* left column: relative to top pixel */ + val += outp[-2*width]; + } + else if (row < 2) { + /* top row: relative to left pixel */ + val += outp[-2]; + } + else { + /* main area: average of left pixel and top pixel */ + val += (outp[-2] + outp[-2*width]) / 2; + } + } + + /* store pixel */ + *outp++ = CLAMP(val); + col++; + } + } +} + +/* +Return-Path: +Received: from koko.hhs.nl ([145.52.2.16] verified) + by hhs.nl (CommuniGate Pro SMTP 4.3.6) + with ESMTP id 89132066 for j.w.r.degoede@hhs.nl; Thu, 03 Jul 2008 15:19:55 +0200 +Received: from exim (helo=koko) + by koko.hhs.nl with local-smtp (Exim 4.62) + (envelope-from ) + id 1KEOj5-0000nq-KR + for j.w.r.degoede@hhs.nl; Thu, 03 Jul 2008 15:19:55 +0200 +Received: from [192.87.102.69] (port=33783 helo=filter1-ams.mf.surf.net) + by koko.hhs.nl with esmtp (Exim 4.62) + (envelope-from ) + id 1KEOj5-0000nj-7r + for j.w.r.degoede@hhs.nl; Thu, 03 Jul 2008 15:19:55 +0200 +Received: from cardassian.kabelfoon.nl (cardassian3.kabelfoon.nl [62.45.45.105]) + by filter1-ams.mf.surf.net (8.13.8/8.13.8/Debian-3) with ESMTP id m63DJsKW032598 + for ; Thu, 3 Jul 2008 15:19:54 +0200 +Received: from [192.168.1.1] (044-013-045-062.dynamic.caiway.nl [62.45.13.44]) + by cardassian.kabelfoon.nl (Postfix) with ESMTP id 77761341D9A + for ; Thu, 3 Jul 2008 15:19:54 +0200 (CEST) +Message-ID: <486CD1F9.8000307@sikken.nl> +Date: Thu, 03 Jul 2008 15:19:53 +0200 +From: Bertrik Sikken +User-Agent: Thunderbird 2.0.0.14 (Windows/20080421) +MIME-Version: 1.0 +To: Hans de Goede +Subject: Re: pac207 bayer decompression algorithm license question +References: <48633F02.3040108@hhs.nl> <4863F611.80104@sikken.nl> <486CC6AF.7050509@hhs.nl> +In-Reply-To: <486CC6AF.7050509@hhs.nl> +X-Enigmail-Version: 0.95.6 +Content-Type: text/plain; charset=ISO-8859-1; format=flowed +Content-Transfer-Encoding: 7bit +X-Canit-CHI2: 0.00 +X-Bayes-Prob: 0.0001 (Score 0, tokens from: @@RPTN) +X-Spam-Score: 0.00 () [Tag at 8.00] +X-CanItPRO-Stream: hhs:j.w.r.degoede@hhs.nl (inherits from hhs:default,base:default) +X-Canit-Stats-ID: 90943081 - 6a9ff19e8165 +X-Scanned-By: CanIt (www . roaringpenguin . com) on 192.87.102.69 +X-Anti-Virus: Kaspersky Anti-Virus for MailServers 5.5.2/RELEASE, bases: 03072008 #811719, status: clean + +-----BEGIN PGP SIGNED MESSAGE----- +Hash: SHA1 + +Hans de Goede wrote: +| Bertrik Sikken wrote: +|> Hallo Hans, +|> +|> Hans de Goede wrote: +|>> I would like to also add support for decompressing the pac207's +|>> compressed +|>> bayer to this lib (and remove it from the kernel driver) and I've +|>> heard from Thomas Kaiser that you are a co-author of the +|>> decompression code. In order to add support for decompressing pac207 +|>> compressed bayer to libv4l I need +|>> permission to relicense the decompression code under the LGPL +|>> (version 2 or later). +|>> +|>> Can you give me permission for this? +|> +|> Ja, vind ik goed. +|> +| +| Thanks! +| +| I'm currently working on adding support for the sn9c10x bayer +| compression to libv4l too, and I noticed this was written by you too. +| +| May I have your permission to relicense the sn9c10x bayer decompression +| code under the LGPL (version 2 or later)? + +I hereby grant you permission to relicense the sn9c10x bayer +decompression code under the LGPL (version 2 or later). + +Kind regards, +Bertrik +-----BEGIN PGP SIGNATURE----- +Version: GnuPG v1.4.7 (MingW32) +Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org + +iD8DBQFIbNH5ETD6mlrWxPURAipvAJ9sv1ZpHyb81NMFejr6x0wqHX3i7QCfRDoB +jZi2e5lUjEh5KvS0dqXbi9I= +=KQfR +-----END PGP SIGNATURE----- +*/ diff --git a/v4l2-apps/libv4l/libv4lconvert/spca501.c b/v4l2-apps/libv4l/libv4lconvert/spca501.c new file mode 100644 index 000000000..9157629e3 --- /dev/null +++ b/v4l2-apps/libv4l/libv4lconvert/spca501.c @@ -0,0 +1,126 @@ +/* +# (C) 2008 Hans de Goede + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include "libv4lconvert-priv.h" + +/* YUYV per line */ +void v4lconvert_spca501_to_yuv420(const unsigned char *src, unsigned char *dst, + int width, int height) +{ + int i,j; + unsigned long *lsrc = (unsigned long *)src; + + for (i = 0; i < height; i += 2) { + /* -128 - 127 --> 0 - 255 and copy first line Y */ + unsigned long *ldst = (unsigned long *)(dst + i * width); + for (j = 0; j < width; j += sizeof(long)) { + *ldst = *lsrc++; + *ldst++ ^= 0x8080808080808080ULL; + } + + /* -128 - 127 --> 0 - 255 and copy 1 line U */ + ldst = (unsigned long *)(dst + width * height + i * width / 4); + for (j = 0; j < width/2; j += sizeof(long)) { + *ldst = *lsrc++; + *ldst++ ^= 0x8080808080808080ULL; + } + + /* -128 - 127 --> 0 - 255 and copy second line Y */ + ldst = (unsigned long *)(dst + i * width + width); + for (j = 0; j < width; j += sizeof(long)) { + *ldst = *lsrc++; + *ldst++ ^= 0x8080808080808080ULL; + } + + /* -128 - 127 --> 0 - 255 and copy 1 line V */ + ldst = (unsigned long *)(dst + (width * height * 5) / 4 + i * width / 4); + for (j = 0; j < width/2; j += sizeof(long)) { + *ldst = *lsrc++; + *ldst++ ^= 0x8080808080808080ULL; + } + } +} + +/* YYUV per line */ +void v4lconvert_spca505_to_yuv420(const unsigned char *src, unsigned char *dst, + int width, int height) +{ + int i,j; + unsigned long *lsrc = (unsigned long *)src; + + for (i = 0; i < height; i += 2) { + /* -128 - 127 --> 0 - 255 and copy 2 lines of Y */ + unsigned long *ldst = (unsigned long *)(dst + i * width); + for (j = 0; j < width*2; j += sizeof(long)) { + *ldst = *lsrc++; + *ldst++ ^= 0x8080808080808080ULL; + } + + /* -128 - 127 --> 0 - 255 and copy 1 line U */ + ldst = (unsigned long *)(dst + width * height + i * width / 4); + for (j = 0; j < width/2; j += sizeof(long)) { + *ldst = *lsrc++; + *ldst++ ^= 0x8080808080808080ULL; + } + + /* -128 - 127 --> 0 - 255 and copy 1 line V */ + ldst = (unsigned long *)(dst + (width * height * 5) / 4 + i * width / 4); + for (j = 0; j < width/2; j += sizeof(long)) { + *ldst = *lsrc++; + *ldst++ ^= 0x8080808080808080ULL; + } + } +} + +/* YUVY per line */ +void v4lconvert_spca508_to_yuv420(const unsigned char *src, unsigned char *dst, + int width, int height) +{ + int i,j; + unsigned long *lsrc = (unsigned long *)src; + + for (i = 0; i < height; i += 2) { + /* -128 - 127 --> 0 - 255 and copy first line Y */ + unsigned long *ldst = (unsigned long *)(dst + i * width); + for (j = 0; j < width; j += sizeof(long)) { + *ldst = *lsrc++; + *ldst++ ^= 0x8080808080808080ULL; + } + + /* -128 - 127 --> 0 - 255 and copy 1 line U */ + ldst = (unsigned long *)(dst + width * height + i * width / 4); + for (j = 0; j < width/2; j += sizeof(long)) { + *ldst = *lsrc++; + *ldst++ ^= 0x8080808080808080ULL; + } + + /* -128 - 127 --> 0 - 255 and copy 1 line V */ + ldst = (unsigned long *)(dst + (width * height * 5) / 4 + i * width / 4); + for (j = 0; j < width/2; j += sizeof(long)) { + *ldst = *lsrc++; + *ldst++ ^= 0x8080808080808080ULL; + } + + /* -128 - 127 --> 0 - 255 and copy second line Y */ + ldst = (unsigned long *)(dst + i * width + width); + for (j = 0; j < width; j += sizeof(long)) { + *ldst = *lsrc++; + *ldst++ ^= 0x8080808080808080ULL; + } + } +} diff --git a/v4l2-apps/libv4l/libv4lconvert/spca561-decompress.c b/v4l2-apps/libv4l/libv4lconvert/spca561-decompress.c new file mode 100644 index 000000000..01eed4ec5 --- /dev/null +++ b/v4l2-apps/libv4l/libv4lconvert/spca561-decompress.c @@ -0,0 +1,1003 @@ +/* + +# Spca561decoder (C) 2005 Andrzej Szombierski [qq@kuku.eu.org] + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published by +# the Free Software Foundation; either version 2.1 of the License, or +# (at your option) any later version. +# +# 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 Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +# Note this code was originally licensed under the GNU GPL instead of the +# GNU LGPL, its license has been changed with permission, see the permission +# mail at the end of this file. + +*/ + +/* + * Decoder for compressed spca561 images + * It was developed for "Labtec WebCam Elch 2(SPCA561A)" (046d:0929) + * but it might work with other spca561 cameras + */ +#include +#include "libv4lconvert-priv.h" + +/*fixme: not reentrant */ +static unsigned int bit_bucket; +static const unsigned char *input_ptr; + +static inline void refill(int *bitfill) +{ + if (*bitfill < 8) { + bit_bucket = (bit_bucket << 8) | *(input_ptr++); + *bitfill += 8; + } +} + +static inline int nbits(int *bitfill, int n) +{ + bit_bucket = (bit_bucket << 8) | *(input_ptr++); + *bitfill -= n; + return (bit_bucket >> (*bitfill & 0xff)) & ((1 << n) - 1); +} + +static inline int _nbits(int *bitfill, int n) +{ + *bitfill -= n; + return (bit_bucket >> (*bitfill & 0xff)) & ((1 << n) - 1); +} + +static int fun_A(int *bitfill) +{ + int ret; + static int tab[] = { + 12, 13, 14, 15, 16, 17, 18, 19, -12, -13, -14, -15, + -16, -17, -18, -19, -19 + }; + + ret = tab[nbits(bitfill, 4)]; + + refill(bitfill); + return ret; +} +static int fun_B(int *bitfill) +{ + static int tab1[] = + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 31, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 16, 17, + 18, + 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30 + }; + static int tab[] = + { 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -5, + -6, -7, -8, -9, -10, -11, -12, -13, -14, -15, -16, -17, + -18, -19 + }; + unsigned int tmp; + + tmp = nbits(bitfill, 7) - 68; + refill(bitfill); + if (tmp > 47) + return 0xff; + return tab[tab1[tmp]]; +} +static int fun_C(int *bitfill, int gkw) +{ + static int tab1[] = + { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 23, 23, 23, 23, 23, 23, + 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, 23, + 12, 13, + 14, + 15, 16, 17, 18, 19, 20, 21, 22 + }; + static int tab[] = + { 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, -9, -10, -11, + -12, -13, -14, -15, -16, -17, -18, -19 + }; + unsigned int tmp; + + if (gkw == 0xfe) { + if (nbits(bitfill, 1) == 0) + return 7; + else + return -8; + } + + if (gkw != 0xff) + return 0xff; + + tmp = nbits(bitfill, 7) - 72; + if (tmp > 43) + return 0xff; + + refill(bitfill); + return tab[tab1[tmp]]; +} +static int fun_D(int *bitfill, int gkw) +{ + if (gkw == 0xfd) { + if (nbits(bitfill, 1) == 0) + return 12; + return -13; + } + + if (gkw == 0xfc) { + if (nbits(bitfill, 1) == 0) + return 13; + return -14; + } + + if (gkw == 0xfe) { + switch (nbits(bitfill, 2)) { + case 0: + return 14; + case 1: + return -15; + case 2: + return 15; + case 3: + return -16; + } + } + + if (gkw == 0xff) { + switch (nbits(bitfill, 3)) { + case 4: + return 16; + case 5: + return -17; + case 6: + return 17; + case 7: + return -18; + case 2: + return _nbits(bitfill, 1) ? 0xed : 0x12; + case 3: + (*bitfill)--; + return 18; + } + return 0xff; + } + return gkw; +} + +static int fun_E(int cur_byte, int *bitfill) +{ + static int tab0[] = { 0, -1, 1, -2, 2, -3, 3, -4 }; + static int tab1[] = { 4, -5, 5, -6, 6, -7, 7, -8 }; + static int tab2[] = { 8, -9, 9, -10, 10, -11, 11, -12 }; + static int tab3[] = { 12, -13, 13, -14, 14, -15, 15, -16 }; + static int tab4[] = { 16, -17, 17, -18, 18, -19, 19, -19 }; + + if ((cur_byte & 0xf0) >= 0x80) { + *bitfill -= 4; + return tab0[(cur_byte >> 4) & 7]; + } + if ((cur_byte & 0xc0) == 0x40) { + *bitfill -= 5; + return tab1[(cur_byte >> 3) & 7]; + + } + if ((cur_byte & 0xe0) == 0x20) { + *bitfill -= 6; + return tab2[(cur_byte >> 2) & 7]; + + } + if ((cur_byte & 0xf0) == 0x10) { + *bitfill -= 7; + return tab3[(cur_byte >> 1) & 7]; + + } + if ((cur_byte & 0xf8) == 8) { + *bitfill -= 8; + return tab4[cur_byte & 7]; + } + return 0xff; +} + +static int fun_F(int cur_byte, int *bitfill) +{ + *bitfill -= 5; + switch (cur_byte & 0xf8) { + case 0x80: + return 0; + case 0x88: + return -1; + case 0x90: + return 1; + case 0x98: + return -2; + case 0xa0: + return 2; + case 0xa8: + return -3; + case 0xb0: + return 3; + case 0xb8: + return -4; + case 0xc0: + return 4; + case 0xc8: + return -5; + case 0xd0: + return 5; + case 0xd8: + return -6; + case 0xe0: + return 6; + case 0xe8: + return -7; + case 0xf0: + return 7; + case 0xf8: + return -8; + } + + *bitfill -= 1; + switch (cur_byte & 0xfc) { + case 0x40: + return 8; + case 0x44: + return -9; + case 0x48: + return 9; + case 0x4c: + return -10; + case 0x50: + return 10; + case 0x54: + return -11; + case 0x58: + return 11; + case 0x5c: + return -12; + case 0x60: + return 12; + case 0x64: + return -13; + case 0x68: + return 13; + case 0x6c: + return -14; + case 0x70: + return 14; + case 0x74: + return -15; + case 0x78: + return 15; + case 0x7c: + return -16; + } + + *bitfill -= 1; + switch (cur_byte & 0xfe) { + case 0x20: + return 16; + case 0x22: + return -17; + case 0x24: + return 17; + case 0x26: + return -18; + case 0x28: + return 18; + case 0x2a: + return -19; + case 0x2c: + return 19; + } + + *bitfill += 7; + return 0xff; +} + +static int internal_spca561_decode(int width, int height, + const unsigned char *inbuf, + unsigned char *outbuf) +{ + /* buffers */ + static int accum[8 * 8 * 8]; + static int i_hits[8 * 8 * 8]; + + const int nbits_A[] = + { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, + 1, 1, 1, 1, 1, + 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 0, 0, 7, 7, + 7, 7, + 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, + 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, + 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 3, 3, 3, 3, 3, + 3, 3, + 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + }; + const int tab_A[] = + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, 11, -11, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, + 10, 10, + 255, 254, -4, + -4, -5, -5, -6, -6, -7, -7, -8, -8, -9, -9, -10, -10, -1, + -1, -1, + -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, + -1, -1, + -1, -1, -1, -1, -1, -1, -1, 2, 2, 2, 2, 2, 2, 2, 2, 3, 3, + 3, 3, 3, + 3, 3, 3, + -2, -2, -2, -2, -2, -2, -2, -2, -3, -3, -3, -3, -3, -3, -3, + -3, 1, + 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, + 1, 1, 1, 1, + 1 + }; + + const int nbits_B[] = + { 0, 8, 7, 7, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, + 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, + 2, 2, + 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, + 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, + 2, 2, 2, 2, 2, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, + 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + }; + const int tab_B[] = + { 0xff, -4, 3, 3, -3, -3, -3, -3, 2, 2, 2, 2, 2, 2, 2, 2, -2, + -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, + 1, 1, 1, 1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, + -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, + -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, + -1, -1, + -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, + }; + + const int nbits_C[] = + { 0, 0, 8, 8, 7, 7, 7, 7, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, + 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, + 3, 3, + 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, + 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, + 3, 3, 3, 3, 3, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, + 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, + 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, + 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, + 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + }; + const int tab_C[] = + { 0xff, 0xfe, 6, -7, 5, 5, -6, -6, 4, 4, 4, 4, -5, -5, -5, -5, + 3, 3, 3, 3, 3, 3, 3, 3, -4, -4, -4, -4, -4, -4, -4, -4, 2, + 2, 2, 2, + 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, -3, -3, -3, -3, -3, -3, -3, -3, + -3, -3, + -3, -3, -3, + -3, -3, -3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, + 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, -2, -2, -2, -2, -2, -2, -2, + -2, -2, + -2, -2, -2, + -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + -2, -2, + -2, -2, + -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, + -1, -1, + -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, + -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, + -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, + }; + + const int nbits_D[] = + { 0, 0, 0, 0, 8, 8, 8, 8, 7, 7, 7, 7, 7, 7, 7, 7, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 5, 5, 5, 5, 5, 5, 5, 5, + 5, 5, + 5, 5, 5, 5, 5, + 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 4, 4, 4, + 4, 4, + 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, + 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, + 4, 4, 4, 4, 4, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, + 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, + 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, + 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, + 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 + }; + const int tab_D[] = + { 0xff, 0xfe, 0xfd, 0xfc, 10, -11, 11, -12, 8, 8, -9, -9, 9, 9, + -10, -10, 6, 6, 6, 6, -7, -7, -7, -7, 7, 7, 7, 7, -8, -8, + -8, -8, + 4, 4, 4, 4, + 4, 4, 4, 4, -5, -5, -5, -5, -5, -5, -5, -5, 5, 5, 5, 5, 5, + 5, 5, 5, + -6, -6, + -6, -6, -6, -6, -6, -6, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, + 2, 2, -3, + -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, -3, + 3, 3, + 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, -4, -4, -4, -4, -4, -4, -4, + -4, -4, + -4, -4, -4, + -4, -4, -4, -4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, + 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, + -1, -1, + -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, + -1, -1, + -1, -1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, + 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, -2, -2, -2, -2, -2, -2, -2, -2, + -2, -2, + -2, -2, -2, + -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, -2, + -2, -2, + -2, -2 + }; + + /* a_curve[19 + i] = ... [-19..19] => [-160..160] */ + const int a_curve[] = + { -160, -144, -128, -112, -98, -88, -80, -72, -64, -56, -48, + -40, -32, -24, -18, -12, -8, -5, -2, 0, 2, 5, 8, 12, 18, + 24, 32, + 40, 48, 56, 64, + 72, 80, 88, 98, 112, 128, 144, 160 + }; + /* clamp0_255[256 + i] = min(max(i,255),0) */ + const unsigned char clamp0_255[] = + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 2, + 3, 4, 5, 6, 7, 8, 9, 10, + 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, + 28, 29, 30, 31, 32, 33, + 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, + 49, 50, + 51, 52, 53, 54, 55, 56, + 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, + 72, 73, + 74, 75, 76, 77, 78, 79, + 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, + 95, 96, + 97, 98, 99, 100, 101, + 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, + 114, + 115, 116, 117, 118, 119, + 120, 121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, + 132, + 133, 134, 135, 136, 137, + 138, 139, 140, 141, 142, 143, 144, 145, 146, 147, 148, 149, + 150, + 151, 152, 153, 154, 155, + 156, 157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, + 168, + 169, 170, 171, 172, 173, + 174, 175, 176, 177, 178, 179, 180, 181, 182, 183, 184, 185, + 186, + 187, 188, 189, 190, 191, + 192, 193, 194, 195, 196, 197, 198, 199, 200, 201, 202, 203, + 204, + 205, 206, 207, 208, 209, + 210, 211, 212, 213, 214, 215, 216, 217, 218, 219, 220, 221, + 222, + 223, 224, 225, 226, 227, + 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239, + 240, + 241, 242, 243, 244, 245, + 246, 247, 248, 249, 250, 251, 252, 253, 254, 255, 255, 255, + 255, + 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, + 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, + 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, + 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, + 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, + 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, + 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, + 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, + 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, + 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, + 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, + 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, + 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, + 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, + 255 + }; + /* abs_clamp15[19 + i] = min(abs(i), 15) */ + const int abs_clamp15[] = + { 15, 15, 15, 15, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, + 2, 1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, + 15, 15, + 15 + }; + /* diff_encoding[256 + i] = ... */ + const int diff_encoding[] = + { 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, + 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, + 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, + 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, + 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, + 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, + 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, + 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 5, 5, 5, 5, 5, 5, 5, + 5, 5, + 5, 5, 5, 5, 5, 3, 3, + 3, 3, 1, 1, 0, 2, 2, 4, 4, 4, 4, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, + 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, + 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, + 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, + 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, + 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, + 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, + 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, + 6, 6, 6, 6, 6, 6, 6, + 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, + 6, 6, + 6, 6, 6, 6, 6, 6 + }; + + int block; + int bitfill = 0; + int xwidth = width + 6; + int off_up_right = 2 - 2 * xwidth; + int off_up_left = -2 - 2 * xwidth; + int pixel_U = 0, saved_pixel_UR = 0; + int pixel_x = 0, pixel_y = 2; + unsigned char *output_ptr = outbuf; + + memset(i_hits, 0, sizeof(i_hits)); + memset(accum, 0, sizeof(accum)); + + memcpy(outbuf + xwidth * 2 + 3, inbuf + 0x14, width); + memcpy(outbuf + xwidth * 3 + 3, inbuf + 0x14 + width, width); + + input_ptr = inbuf + 0x14 + width * 2; + output_ptr = outbuf + (xwidth) * 4 + 3; + + bit_bucket = 0; + + for (block = 0; block < ((height - 2) * width) / 32; ++block) { + int b_it, var_7 = 0; + int cur_byte; + + refill(&bitfill); + + cur_byte = (bit_bucket >> (bitfill & 7)) & 0xff; + + if ((cur_byte & 0x80) == 0) { + var_7 = 0; + bitfill--; + } else if ((cur_byte & 0xC0) == 0x80) { + var_7 = 1; + bitfill -= 2; + } else if ((cur_byte & 0xc0) == 0xc0) { + var_7 = 2; + bitfill -= 2; + } + + for (b_it = 0; b_it < 32; b_it++) { + int index; + int pixel_L, pixel_UR, pixel_UL; + int multiplier; + int dL, dC, dR; + int gkw; /* God knows what */ + + refill(&bitfill); + cur_byte = bit_bucket >> (bitfill & 7) & 0xff; + + pixel_L = output_ptr[-2]; + pixel_UR = output_ptr[off_up_right]; + pixel_UL = output_ptr[off_up_left]; + + dL = diff_encoding[0x100 + pixel_UL - pixel_L]; + dC = diff_encoding[0x100 + pixel_U - pixel_UL]; + dR = diff_encoding[0x100 + pixel_UR - pixel_U]; + + if (pixel_x < 2) { + pixel_L = pixel_UL = pixel_U = + output_ptr[-xwidth * 2]; + pixel_UR = output_ptr[off_up_right]; + dL = dC = 0; + dR = diff_encoding[0x100 + pixel_UR - + pixel_U]; + } else if (pixel_x > width - 3) + dR = 0; + + multiplier = 4; + index = dR + dC * 8 + dL * 64; + + if (pixel_L + pixel_U * 2 <= 144 + && (pixel_y & 1) == 0 + && (b_it & 3) == 0 && (dR < 5) && (dC < 5) + && (dL < 5)) { + multiplier = 1; + } else if (pixel_L <= 48 + && dL <= 4 && dC <= 4 && dL >= 1 + && dC >= 1) { + multiplier = 2; + } else if (var_7 == 1) { + multiplier = 2; + } else if (dC + dL >= 11 || var_7 == 2) { + multiplier = 8; + } + + if (i_hits[index] < 7) { + bitfill -= nbits_A[cur_byte]; + gkw = tab_A[cur_byte]; + if (gkw == 0xfe) + gkw = fun_A(&bitfill); + } else if (i_hits[index] >= accum[index]) { + bitfill -= nbits_B[cur_byte]; + gkw = tab_B[cur_byte]; + if (cur_byte == 0) + gkw = fun_B(&bitfill); + } else if (i_hits[index] * 2 >= accum[index]) { + bitfill -= nbits_C[cur_byte]; + gkw = tab_C[cur_byte]; + if (cur_byte < 2) + gkw = fun_C(&bitfill, gkw); + } else if (i_hits[index] * 4 >= accum[index]) { + bitfill -= nbits_D[cur_byte]; + gkw = tab_D[cur_byte]; + if (cur_byte < 4) + gkw = fun_D(&bitfill, gkw); + } else if (i_hits[index] * 8 >= accum[index]) { + gkw = fun_E(cur_byte, &bitfill); + } else { + gkw = fun_F(cur_byte, &bitfill); + } + + if (gkw == 0xff) + return -3; + + { + int tmp1, tmp2; + + tmp1 = + (pixel_U + pixel_L) * 3 - pixel_UL * 2; + tmp1 += (tmp1 < 0) ? 3 : 0; + tmp2 = a_curve[19 + gkw] * multiplier; + tmp2 += (tmp2 < 0) ? 1 : 0; + + *(output_ptr++) = + clamp0_255[0x100 + (tmp1 >> 2) - + (tmp2 >> 1)]; + } + pixel_U = saved_pixel_UR; + saved_pixel_UR = pixel_UR; + + if (++pixel_x == width) { + output_ptr += 6; + pixel_x = 0; + pixel_y++; + } + + accum[index] += abs_clamp15[19 + gkw]; + + if (i_hits[index]++ == 15) { + i_hits[index] = 8; + accum[index] /= 2; + } + } + } + return 0; +} + +/* FIXME, change internal_spca561_decode not to need the extra border + around its dest buffer */ +void v4lconvert_decode_spca561(const unsigned char *inbuf, + unsigned char *outbuf, int width, int height) +{ + int i; + static unsigned char tmpbuf[650 * 490]; + if (internal_spca561_decode(width, height, inbuf, tmpbuf) != 0) + return; + for (i = 0; i < height; i++) + memcpy(outbuf + i * width, + tmpbuf + (i + 2) * (width + 6) + 3, width); +} + +/*************** License Change Permission Notice *************** + +Return-Path: +Received: from koko.hhs.nl ([145.52.2.16] verified) + by hhs.nl (CommuniGate Pro SMTP 4.3.6) + with ESMTP id 88574071 for j.w.r.degoede@hhs.nl; Mon, 16 Jun 2008 16:36:24 +0200 +Received: from exim (helo=koko) + by koko.hhs.nl with local-smtp (Exim 4.62) + (envelope-from ) + id 1K8Fom-0002iJ-3K + for j.w.r.degoede@hhs.nl; Mon, 16 Jun 2008 16:36:24 +0200 +Received: from [192.87.102.74] (port=41377 helo=filter6-ams.mf.surf.net) + by koko.hhs.nl with esmtp (Exim 4.62) + (envelope-from ) + id 1K8Fol-0002iC-Qo + for j.w.r.degoede@hhs.nl; Mon, 16 Jun 2008 16:36:23 +0200 +Received: from kuku.eu.org (pa90.wielkopole.sdi.tpnet.pl [217.99.123.90]) + by filter6-ams.mf.surf.net (8.13.8/8.13.8/Debian-3) with ESMTP id m5GEa55r001787 + for ; Mon, 16 Jun 2008 16:36:06 +0200 +Received: (qmail 2243 invoked by uid 500); 16 Jun 2008 14:29:37 -0000 +Date: Mon, 16 Jun 2008 16:29:37 +0200 (CEST) +From: Andrzej Szombierski +To: Hans de Goede +Subject: Re: spca561 decoder license question +In-Reply-To: <485673B6.4050003@hhs.nl> +Message-ID: +References: <485673B6.4050003@hhs.nl> +MIME-Version: 1.0 +Content-Type: TEXT/PLAIN; charset=iso-8859-2 +Content-Transfer-Encoding: QUOTED-PRINTABLE +X-Canit-CHI2: 0.00 +X-Bayes-Prob: 0.0001 (Score 0, tokens from: @@RPTN) +X-Spam-Score: 2.00 (**) [Tag at 6.00] RBL(uceprotect-blacklist.surfnet.nl,2.0) +X-CanItPRO-Stream: hhs:j.w.r.degoede@hhs.nl (inherits from hhs:default,base:default) +X-Canit-Stats-ID: 85673281 - 37e52c8b07bc +X-Scanned-By: CanIt (www . roaringpenguin . com) on 192.87.102.74 +X-Anti-Virus: Kaspersky Anti-Virus for MailServers 5.5.2/RELEASE, bases: 16062008 #776409, status: clean + +On Mon, 16 Jun 2008, Hans de Goede wrote: + +> Hi, +>=20 +> I don't know if you're still subscribed to the spca devel mailing list, s= +o let=20 +> me start with a short intro. +> +> I'm a Linux enthusiast / developer currently helping Jean-Fran=E7ois Moin= +e with=20 +> porting gspca to video4linux2 and cleaning up the code to get it ready fo= +r=20 +> mainline kernel inclusion. +>=20 +> As part of this process the decompression code for all supported cams mus= +t be=20 +> moved to userspace, as doing in kernel decompression is considered unwant= +ed by=20 +> the mainline people (I agree) as it should be done in userspace. +> + +Sounds reasonable. +=20 +> As such I'm working on a library which does decompression of custom cam f= +ormats=20 +> in userspace. +> + +Nice. I hope that the library won't be limited to spca-supported webcams,= +=20 +and as an application developer I would be able to just request RGB data=20 +from any /dev/video*, right? + +> I do not want to license this library as GPL (as the current spca code is= +), as=20 +> it should be usable by as much software as possible. Instead I want to li= +cense=20 +> it under the LGPL version 2.1 or later. + +Also sounds reasonable. + +>=20 +> So my question us my I have your permission to relicense your spca561=20 +> decompression code under the LGPL? +>=20 + +Yes, of course.=20 + +> Thanks & Regards, +>=20 +> Hans +>=20 +> + +--=20 +:: Andrzej Szombierski :: qq@kuku.eu.org :: http://kuku.eu.org :: +:: anszom@bezkitu.com :: radio bez kitu :: http://bezkitu.com :: + +*/ diff --git a/v4l2-apps/libv4l/libv4lconvert/tinyjpeg-internal.h b/v4l2-apps/libv4l/libv4lconvert/tinyjpeg-internal.h new file mode 100644 index 000000000..26844c28a --- /dev/null +++ b/v4l2-apps/libv4l/libv4lconvert/tinyjpeg-internal.h @@ -0,0 +1,121 @@ +/* + * Small jpeg decoder library (Internal header) + * + * Copyright (c) 2006, Luc Saillard + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * - Neither the name of the author nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#ifndef __TINYJPEG_INTERNAL_H_ +#define __TINYJPEG_INTERNAL_H_ + +#include + +#define SANITY_CHECK 1 + +struct jdec_private; + +#define HUFFMAN_HASH_NBITS 9 +#define HUFFMAN_HASH_SIZE (1UL< + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * - Neither the name of the author nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include +#include +#include +#include +#include + +#include "tinyjpeg.h" +#include "tinyjpeg-internal.h" + +enum std_markers { + DQT = 0xDB, /* Define Quantization Table */ + SOF = 0xC0, /* Start of Frame (size information) */ + DHT = 0xC4, /* Huffman Table */ + SOI = 0xD8, /* Start of Image */ + SOS = 0xDA, /* Start of Scan */ + RST = 0xD0, /* Reset Marker d0 -> .. */ + RST7 = 0xD7, /* Reset Marker .. -> d7 */ + EOI = 0xD9, /* End of Image */ + DRI = 0xDD, /* Define Restart Interval */ + APP0 = 0xE0, +}; + +#define cY 0 +#define cCb 1 +#define cCr 2 + +#define BLACK_Y 0 +#define BLACK_U 127 +#define BLACK_V 127 + +#if DEBUG +#if LOG2FILE + +#define trace(fmt, args...) do { \ + FILE *f = fopen("/tmp/jpeg.log", "a"); \ + fprintf(f, fmt, ## args); \ + fflush(f); \ + fclose(f); \ +} while(0) + +#else + +#define trace(fmt, args...) do { \ + fprintf(stderr, fmt, ## args); \ + fflush(stderr); \ +} while(0) +#endif + +#else +#define trace(fmt, args...) do { } while (0) +#endif + +#define error(fmt, args...) do { \ + snprintf(priv->error_string, sizeof(priv->error_string), fmt, ## args); \ + return -1; \ +} while(0) + + +#if 0 +static char *print_bits(unsigned int value, char *bitstr) +{ + int i, j; + i=31; + while (i>0) + { + if (value & (1UL<=0) + { + bitstr[j++] = (value & (1UL< + * Ex: 0000 0000 1010 0000 1111 0000 <== reservoir + * ^ + * bit 1 + * To get two bits from this example + * result = (reservoir >> 15) & 3 + * + */ +#define fill_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted) do { \ + while (nbits_in_reservoir= priv->stream_end) { \ + snprintf(priv->error_string, sizeof(priv->error_string), \ + "fill_nbits error: need %u more bits\n", \ + nbits_wanted - nbits_in_reservoir); \ + longjmp(priv->jump_state, -EIO); \ + } \ + c = *stream++; \ + reservoir <<= 8; \ + if (c == 0xff && *stream == 0x00) \ + stream++; \ + reservoir |= c; \ + nbits_in_reservoir+=8; \ + } \ +} while(0); + +/* Signed version !!!! */ +#define get_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted,result) do { \ + fill_nbits(reservoir,nbits_in_reservoir,stream,(nbits_wanted)); \ + result = ((reservoir)>>(nbits_in_reservoir-(nbits_wanted))); \ + nbits_in_reservoir -= (nbits_wanted); \ + reservoir &= ((1U<>(nbits_in_reservoir-(nbits_wanted))); \ +} while(0); + +/* To speed up the decoding, we assume that the reservoir have enough bit + * slow version: + * #define skip_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted) do { \ + * fill_nbits(reservoir,nbits_in_reservoir,stream,(nbits_wanted)); \ + * nbits_in_reservoir -= (nbits_wanted); \ + * reservoir &= ((1U<= priv->stream_end) { \ + snprintf(priv->error_string, sizeof(priv->error_string), \ + "fill_nbits error: need %u more bits\n", \ + nbits_wanted - nbits_in_reservoir); \ + longjmp(priv->jump_state, -EIO); \ + } \ + c = *stream++; \ + reservoir <<= 8; \ + if (c == 0xff) { \ + switch (stream[0]) { \ + case 0x00: \ + stream++; \ + break; \ + case 0xd9: /* EOF marker */ \ + stream++; \ + if (stream != priv->stream_end) { \ + snprintf(priv->error_string, sizeof(priv->error_string), \ + "Pixart JPEG error: premature EOF\n"); \ + longjmp(priv->jump_state, -EIO); \ + } \ + break; \ + case 0xff: \ + if (stream[1] == 0xff && (stream[2] < 7 || stream[2] == 0xff)) { \ + stream += 3; \ + c = *stream++; \ + break; \ + } \ + /* Error fall through */ \ + default: \ + snprintf(priv->error_string, sizeof(priv->error_string), \ + "Pixart JPEG error: invalid JPEG marker: 0xff 0x%02x 0x%02x 0x%02x\n", \ + (unsigned int)stream[0], (unsigned int)stream[1], \ + (unsigned int)stream[2]); \ + longjmp(priv->jump_state, -EIO); \ + } \ + } \ + reservoir |= c; \ + nbits_in_reservoir+=8; \ + } \ +} while(0); + +/* Signed version !!!! */ +#define pixart_get_nbits(reservoir,nbits_in_reservoir,stream,nbits_wanted,result) \ +do { \ + pixart_fill_nbits(reservoir,nbits_in_reservoir,stream,(nbits_wanted)); \ + result = ((reservoir)>>(nbits_in_reservoir-(nbits_wanted))); \ + nbits_in_reservoir -= (nbits_wanted); \ + reservoir &= ((1U<>(nbits_in_reservoir-(nbits_wanted))); \ +} while(0); + +/* Note skip_nbits is identical for both */ + + +#define be16_to_cpu(x) (((x)[0]<<8)|(x)[1]) + +static void resync(struct jdec_private *priv); + +/** + * Get the next (valid) huffman code in the stream. + * + * To speedup the procedure, we look HUFFMAN_HASH_NBITS bits and the code is + * lower than HUFFMAN_HASH_NBITS we have automaticaly the length of the code + * and the value by using two lookup table. + * Else if the value is not found, just search (linear) into an array for each + * bits is the code is present. + * + * If the code is not present for any reason, -1 is return. + */ +static int get_next_huffman_code(struct jdec_private *priv, struct huffman_table *huffman_table) +{ + int value, hcode; + unsigned int extra_nbits, nbits; + uint16_t *slowtable; + + look_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, HUFFMAN_HASH_NBITS, hcode); + value = huffman_table->lookup[hcode]; + if (value >= 0) + { + unsigned int code_size = huffman_table->code_size[value]; + skip_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, code_size); + return value; + } + + /* Decode more bits each time ... */ + for (extra_nbits=0; extra_nbits<16-HUFFMAN_HASH_NBITS; extra_nbits++) + { + nbits = HUFFMAN_HASH_NBITS + 1 + extra_nbits; + + look_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, nbits, hcode); + slowtable = huffman_table->slowtable[extra_nbits]; + /* Search if the code is in this array */ + while (slowtable[0]) { + if (slowtable[0] == hcode) { + skip_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, nbits); + return slowtable[1]; + } + slowtable+=2; + } + } + snprintf(priv->error_string, sizeof(priv->error_string), + "unknown huffman code: %08x\n", (unsigned int)hcode); + longjmp(priv->jump_state, -EIO); + return 0; +} + +/* identical as above but with *_nbits replaced with pixart_*_nbits */ +static int pixart_get_next_huffman_code(struct jdec_private *priv, + struct huffman_table *huffman_table) +{ + int value, hcode; + unsigned int extra_nbits, nbits; + uint16_t *slowtable; + + pixart_look_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, HUFFMAN_HASH_NBITS, hcode); + value = huffman_table->lookup[hcode]; + if (value >= 0) + { + unsigned int code_size = huffman_table->code_size[value]; + skip_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, code_size); + return value; + } + + /* Decode more bits each time ... */ + for (extra_nbits=0; extra_nbits<16-HUFFMAN_HASH_NBITS; extra_nbits++) + { + nbits = HUFFMAN_HASH_NBITS + 1 + extra_nbits; + + pixart_look_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, nbits, hcode); + slowtable = huffman_table->slowtable[extra_nbits]; + /* Search if the code is in this array */ + while (slowtable[0]) { + if (slowtable[0] == hcode) { + skip_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, nbits); + return slowtable[1]; + } + slowtable+=2; + } + } + snprintf(priv->error_string, sizeof(priv->error_string), + "unknown huffman code: %08x\n", (unsigned int)hcode); + longjmp(priv->jump_state, -EIO); + return 0; +} + + + +/** + * + * Decode a single block that contains the DCT coefficients. + * The table coefficients is already dezigzaged at the end of the operation. + * + */ +static void process_Huffman_data_unit(struct jdec_private *priv, int component) +{ + unsigned char j; + unsigned int huff_code; + unsigned char size_val, count_0; + + struct component *c = &priv->component_infos[component]; + short int DCT[64]; + + /* Initialize the DCT coef table */ + memset(DCT, 0, sizeof(DCT)); + + /* DC coefficient decoding */ + huff_code = get_next_huffman_code(priv, c->DC_table); + if (huff_code) { + get_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, huff_code, DCT[0]); + DCT[0] += c->previous_DC; + c->previous_DC = DCT[0]; + } else { + DCT[0] = c->previous_DC; + } + + + /* AC coefficient decoding */ + j = 1; + while (j<64) + { + huff_code = get_next_huffman_code(priv, c->AC_table); + + size_val = huff_code & 0xF; + count_0 = huff_code >> 4; + + if (size_val == 0) + { /* RLE */ + if (count_0 == 0) + break; /* EOB found, go out */ + else if (count_0 == 0xF) + j += 16; /* skip 16 zeros */ + } + else + { + j += count_0; /* skip count_0 zeroes */ + if (j < 64) { + get_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, size_val, DCT[j]); + j++; + } + } + } + + if (j > 64) { + snprintf(priv->error_string, sizeof(priv->error_string), + "error: more then 63 AC components (%d) in huffman unit\n", (int)j); + longjmp(priv->jump_state, -EIO); + } + + for (j = 0; j < 64; j++) + c->DCT[j] = DCT[zigzag[j]]; +} + +/* identical as above both with *_nbits replaced with pixart_*_nbits */ +static void pixart_process_Huffman_data_unit(struct jdec_private *priv, int component) +{ + unsigned char j; + unsigned int huff_code; + unsigned char size_val, count_0; + + struct component *c = &priv->component_infos[component]; + short int DCT[64]; + + /* Initialize the DCT coef table */ + memset(DCT, 0, sizeof(DCT)); + + /* DC coefficient decoding */ + huff_code = pixart_get_next_huffman_code(priv, c->DC_table); + if (huff_code) { + pixart_get_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, huff_code, DCT[0]); + DCT[0] += c->previous_DC; + c->previous_DC = DCT[0]; + } else { + DCT[0] = c->previous_DC; + } + + + /* AC coefficient decoding */ + j = 1; + while (j<64) + { + huff_code = pixart_get_next_huffman_code(priv, c->AC_table); + + size_val = huff_code & 0xF; + count_0 = huff_code >> 4; + + if (size_val == 0) + { /* RLE */ + if (count_0 == 0) + break; /* EOB found, go out */ + else if (count_0 == 0xF) + j += 16; /* skip 16 zeros */ + } + else + { + j += count_0; /* skip count_0 zeroes */ + if (j < 64 ) { + pixart_get_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, size_val, DCT[j]); + j++; + } + } + } + + if (j > 64) { + snprintf(priv->error_string, sizeof(priv->error_string), + "error: more then 63 AC components (%d) in huffman unit\n", (int)j); + longjmp(priv->jump_state, -EIO); + } + + for (j = 0; j < 64; j++) + c->DCT[j] = DCT[zigzag[j]]; +} + + +/* + * Takes two array of bits, and build the huffman table for size, and code + * + * lookup will return the symbol if the code is less or equal than HUFFMAN_HASH_NBITS. + * code_size will be used to known how many bits this symbol is encoded. + * slowtable will be used when the first lookup didn't give the result. + */ +static int build_huffman_table(struct jdec_private *priv, const unsigned char *bits, const unsigned char *vals, struct huffman_table *table) +{ + unsigned int i, j, code, code_size, val, nbits; + unsigned char huffsize[257], *hz; + unsigned int huffcode[257], *hc; + int next_free_entry; + int slowtable_used[16-HUFFMAN_HASH_NBITS]; + + /* + * Build a temp array + * huffsize[X] => numbers of bits to write vals[X] + */ + hz = huffsize; + for (i=1; i<=16; i++) + { + for (j=1; j<=bits[i]; j++) + *hz++ = i; + } + *hz = 0; + + memset(table->lookup, 0xff, sizeof(table->lookup)); + for (i=0; i<(16-HUFFMAN_HASH_NBITS); i++) + slowtable_used[i] = 0; + + /* Build a temp array + * huffcode[X] => code used to write vals[X] + */ + code = 0; + hc = huffcode; + hz = huffsize; + nbits = *hz; + while (*hz) + { + while (*hz == nbits) { + *hc++ = code++; + hz++; + } + code <<= 1; + nbits++; + } + + /* + * Build the lookup table, and the slowtable if needed. + */ + next_free_entry = -1; + for (i=0; huffsize[i]; i++) + { + val = vals[i]; + code = huffcode[i]; + code_size = huffsize[i]; + + trace("val=%2.2x code=%8.8x codesize=%2.2d\n", i, code, code_size); + + table->code_size[val] = code_size; + if (code_size <= HUFFMAN_HASH_NBITS) + { + /* + * Good: val can be put in the lookup table, so fill all value of this + * column with value val + */ + int repeat = 1UL<<(HUFFMAN_HASH_NBITS - code_size); + code <<= HUFFMAN_HASH_NBITS - code_size; + while ( repeat-- ) + table->lookup[code++] = val; + + } + else + { + /* Perhaps sorting the array will be an optimization */ + int slowtable_index = code_size-HUFFMAN_HASH_NBITS-1; + + if (slowtable_used[slowtable_index] == 254) + error("slow Huffman table overflow\n"); + + table->slowtable[slowtable_index][slowtable_used[slowtable_index]] + = code; + table->slowtable[slowtable_index][slowtable_used[slowtable_index] + 1] + = val; + slowtable_used[slowtable_index] += 2; + } + } + + for (i=0; i<(16-HUFFMAN_HASH_NBITS); i++) + table->slowtable[i][slowtable_used[i]] = 0; + + return 0; +} + +static int build_default_huffman_tables(struct jdec_private *priv) +{ + if ( (priv->flags & TINYJPEG_FLAGS_MJPEG_TABLE) + && priv->default_huffman_table_initialized) + return 0; + + if (build_huffman_table(priv, bits_dc_luminance, val_dc_luminance, &priv->HTDC[0])) + return -1; + if (build_huffman_table(priv, bits_ac_luminance, val_ac_luminance, &priv->HTAC[0])) + return -1; + + if (build_huffman_table(priv, bits_dc_chrominance, val_dc_chrominance, &priv->HTDC[1])) + return -1; + if (build_huffman_table(priv, bits_ac_chrominance, val_ac_chrominance, &priv->HTAC[1])) + return -1; + + priv->default_huffman_table_initialized = 1; + return 0; +} + + + +/******************************************************************************* + * + * Colorspace conversion routine + * + * + * Note: + * YCbCr is defined per CCIR 601-1, except that Cb and Cr are + * normalized to the range 0..MAXJSAMPLE rather than -0.5 .. 0.5. + * The conversion equations to be implemented are therefore + * R = Y + 1.40200 * Cr + * G = Y - 0.34414 * Cb - 0.71414 * Cr + * B = Y + 1.77200 * Cb + * + ******************************************************************************/ + +static unsigned char clamp(int i) +{ + if (i<0) + return 0; + else if (i>255) + return 255; + else + return i; +} + + +/** + * YCrCb -> YUV420P (1x1) + * .---. + * | 1 | + * `---' + */ +static void YCrCB_to_YUV420P_1x1(struct jdec_private *priv) +{ + const unsigned char *s, *y; + unsigned char *p; + int i,j; + + p = priv->plane[0]; + y = priv->Y; + for (i=0; i<8; i++) + { + memcpy(p, y, 8); + p+=priv->width; + y+=8; + } + + p = priv->plane[1]; + s = priv->Cb; + for (i=0; i<8; i+=2) + { + for (j=0; j<8; j+=2, s+=2) + *p++ = *s; + s += 8; /* Skip one line */ + p += priv->width/2 - 4; + } + + p = priv->plane[2]; + s = priv->Cr; + for (i=0; i<8; i+=2) + { + for (j=0; j<8; j+=2, s+=2) + *p++ = *s; + s += 8; /* Skip one line */ + p += priv->width/2 - 4; + } +} + +/** + * YCrCb -> YUV420P (2x1) + * .-------. + * | 1 | 2 | + * `-------' + */ +static void YCrCB_to_YUV420P_2x1(struct jdec_private *priv) +{ + unsigned char *p; + const unsigned char *s, *y1; + unsigned int i; + + p = priv->plane[0]; + y1 = priv->Y; + for (i=0; i<8; i++) + { + memcpy(p, y1, 16); + p += priv->width; + y1 += 16; + } + + p = priv->plane[1]; + s = priv->Cb; + for (i=0; i<8; i+=2) + { + memcpy(p, s, 8); + s += 16; /* Skip one line */ + p += priv->width/2; + } + + p = priv->plane[2]; + s = priv->Cr; + for (i=0; i<8; i+=2) + { + memcpy(p, s, 8); + s += 16; /* Skip one line */ + p += priv->width/2; + } +} + + +/** + * YCrCb -> YUV420P (1x2) + * .---. + * | 1 | + * |---| + * | 2 | + * `---' + */ +static void YCrCB_to_YUV420P_1x2(struct jdec_private *priv) +{ + const unsigned char *s, *y; + unsigned char *p; + int i,j; + + p = priv->plane[0]; + y = priv->Y; + for (i=0; i<16; i++) + { + memcpy(p, y, 8); + p+=priv->width; + y+=8; + } + + p = priv->plane[1]; + s = priv->Cb; + for (i=0; i<8; i++) + { + for (j=0; j<8; j+=2, s+=2) + *p++ = *s; + p += priv->width/2 - 4; + } + + p = priv->plane[2]; + s = priv->Cr; + for (i=0; i<8; i++) + { + for (j=0; j<8; j+=2, s+=2) + *p++ = *s; + p += priv->width/2 - 4; + } +} + +/** + * YCrCb -> YUV420P (2x2) + * .-------. + * | 1 | 2 | + * |---+---| + * | 3 | 4 | + * `-------' + */ +static void YCrCB_to_YUV420P_2x2(struct jdec_private *priv) +{ + unsigned char *p; + const unsigned char *s, *y1; + unsigned int i; + + p = priv->plane[0]; + y1 = priv->Y; + for (i=0; i<16; i++) + { + memcpy(p, y1, 16); + p += priv->width; + y1 += 16; + } + + p = priv->plane[1]; + s = priv->Cb; + for (i=0; i<8; i++) + { + memcpy(p, s, 8); + s += 8; + p += priv->width/2; + } + + p = priv->plane[2]; + s = priv->Cr; + for (i=0; i<8; i++) + { + memcpy(p, s, 8); + s += 8; + p += priv->width/2; + } +} + +/** + * YCrCb -> RGB24 (1x1) + * .---. + * | 1 | + * `---' + */ +static void YCrCB_to_RGB24_1x1(struct jdec_private *priv) +{ + const unsigned char *Y, *Cb, *Cr; + unsigned char *p; + int i,j; + int offset_to_next_row; + +#define SCALEBITS 10 +#define ONE_HALF (1UL << (SCALEBITS-1)) +#define FIX(x) ((int)((x) * (1UL<plane[0]; + Y = priv->Y; + Cb = priv->Cb; + Cr = priv->Cr; + offset_to_next_row = priv->width*3 - 8*3; + for (i=0; i<8; i++) { + + for (j=0; j<8; j++) { + + int y, cb, cr; + int add_r, add_g, add_b; + int r, g , b; + + y = (*Y++) << SCALEBITS; + cb = *Cb++ - 128; + cr = *Cr++ - 128; + add_r = FIX(1.40200) * cr + ONE_HALF; + add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; + add_b = FIX(1.77200) * cb + ONE_HALF; + + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + + } + + p += offset_to_next_row; + } + +#undef SCALEBITS +#undef ONE_HALF +#undef FIX + +} + +/** + * YCrCb -> BGR24 (1x1) + * .---. + * | 1 | + * `---' + */ +static void YCrCB_to_BGR24_1x1(struct jdec_private *priv) +{ + const unsigned char *Y, *Cb, *Cr; + unsigned char *p; + int i,j; + int offset_to_next_row; + +#define SCALEBITS 10 +#define ONE_HALF (1UL << (SCALEBITS-1)) +#define FIX(x) ((int)((x) * (1UL<plane[0]; + Y = priv->Y; + Cb = priv->Cb; + Cr = priv->Cr; + offset_to_next_row = priv->width*3 - 8*3; + for (i=0; i<8; i++) { + + for (j=0; j<8; j++) { + + int y, cb, cr; + int add_r, add_g, add_b; + int r, g , b; + + y = (*Y++) << SCALEBITS; + cb = *Cb++ - 128; + cr = *Cr++ - 128; + add_r = FIX(1.40200) * cr + ONE_HALF; + add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; + add_b = FIX(1.77200) * cb + ONE_HALF; + + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + + } + + p += offset_to_next_row; + } + +#undef SCALEBITS +#undef ONE_HALF +#undef FIX + +} + + +/** + * YCrCb -> RGB24 (2x1) + * .-------. + * | 1 | 2 | + * `-------' + */ +static void YCrCB_to_RGB24_2x1(struct jdec_private *priv) +{ + const unsigned char *Y, *Cb, *Cr; + unsigned char *p; + int i,j; + int offset_to_next_row; + +#define SCALEBITS 10 +#define ONE_HALF (1UL << (SCALEBITS-1)) +#define FIX(x) ((int)((x) * (1UL<plane[0]; + Y = priv->Y; + Cb = priv->Cb; + Cr = priv->Cr; + offset_to_next_row = priv->width*3 - 16*3; + for (i=0; i<8; i++) { + + for (j=0; j<8; j++) { + + int y, cb, cr; + int add_r, add_g, add_b; + int r, g , b; + + y = (*Y++) << SCALEBITS; + cb = *Cb++ - 128; + cr = *Cr++ - 128; + add_r = FIX(1.40200) * cr + ONE_HALF; + add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; + add_b = FIX(1.77200) * cb + ONE_HALF; + + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + + y = (*Y++) << SCALEBITS; + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + + } + + p += offset_to_next_row; + } + +#undef SCALEBITS +#undef ONE_HALF +#undef FIX + +} + +/* + * YCrCb -> BGR24 (2x1) + * .-------. + * | 1 | 2 | + * `-------' + */ +static void YCrCB_to_BGR24_2x1(struct jdec_private *priv) +{ + const unsigned char *Y, *Cb, *Cr; + unsigned char *p; + int i,j; + int offset_to_next_row; + +#define SCALEBITS 10 +#define ONE_HALF (1UL << (SCALEBITS-1)) +#define FIX(x) ((int)((x) * (1UL<plane[0]; + Y = priv->Y; + Cb = priv->Cb; + Cr = priv->Cr; + offset_to_next_row = priv->width*3 - 16*3; + for (i=0; i<8; i++) { + + for (j=0; j<8; j++) { + + int y, cb, cr; + int add_r, add_g, add_b; + int r, g , b; + + cb = *Cb++ - 128; + cr = *Cr++ - 128; + add_r = FIX(1.40200) * cr + ONE_HALF; + add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; + add_b = FIX(1.77200) * cb + ONE_HALF; + + y = (*Y++) << SCALEBITS; + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + + y = (*Y++) << SCALEBITS; + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + + } + + p += offset_to_next_row; + } + +#undef SCALEBITS +#undef ONE_HALF +#undef FIX + +} + +/** + * YCrCb -> RGB24 (1x2) + * .---. + * | 1 | + * |---| + * | 2 | + * `---' + */ +static void YCrCB_to_RGB24_1x2(struct jdec_private *priv) +{ + const unsigned char *Y, *Cb, *Cr; + unsigned char *p, *p2; + int i,j; + int offset_to_next_row; + +#define SCALEBITS 10 +#define ONE_HALF (1UL << (SCALEBITS-1)) +#define FIX(x) ((int)((x) * (1UL<plane[0]; + p2 = priv->plane[0] + priv->width*3; + Y = priv->Y; + Cb = priv->Cb; + Cr = priv->Cr; + offset_to_next_row = 2*priv->width*3 - 8*3; + for (i=0; i<8; i++) { + + for (j=0; j<8; j++) { + + int y, cb, cr; + int add_r, add_g, add_b; + int r, g , b; + + cb = *Cb++ - 128; + cr = *Cr++ - 128; + add_r = FIX(1.40200) * cr + ONE_HALF; + add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; + add_b = FIX(1.77200) * cb + ONE_HALF; + + y = (*Y++) << SCALEBITS; + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + + y = (Y[8-1]) << SCALEBITS; + r = (y + add_r) >> SCALEBITS; + *p2++ = clamp(r); + g = (y + add_g) >> SCALEBITS; + *p2++ = clamp(g); + b = (y + add_b) >> SCALEBITS; + *p2++ = clamp(b); + + } + Y += 8; + p += offset_to_next_row; + p2 += offset_to_next_row; + } + +#undef SCALEBITS +#undef ONE_HALF +#undef FIX + +} + +/* + * YCrCb -> BGR24 (1x2) + * .---. + * | 1 | + * |---| + * | 2 | + * `---' + */ +static void YCrCB_to_BGR24_1x2(struct jdec_private *priv) +{ + const unsigned char *Y, *Cb, *Cr; + unsigned char *p, *p2; + int i,j; + int offset_to_next_row; + +#define SCALEBITS 10 +#define ONE_HALF (1UL << (SCALEBITS-1)) +#define FIX(x) ((int)((x) * (1UL<plane[0]; + p2 = priv->plane[0] + priv->width*3; + Y = priv->Y; + Cb = priv->Cb; + Cr = priv->Cr; + offset_to_next_row = 2*priv->width*3 - 8*3; + for (i=0; i<8; i++) { + + for (j=0; j<8; j++) { + + int y, cb, cr; + int add_r, add_g, add_b; + int r, g , b; + + cb = *Cb++ - 128; + cr = *Cr++ - 128; + add_r = FIX(1.40200) * cr + ONE_HALF; + add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; + add_b = FIX(1.77200) * cb + ONE_HALF; + + y = (*Y++) << SCALEBITS; + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + + y = (Y[8-1]) << SCALEBITS; + b = (y + add_b) >> SCALEBITS; + *p2++ = clamp(b); + g = (y + add_g) >> SCALEBITS; + *p2++ = clamp(g); + r = (y + add_r) >> SCALEBITS; + *p2++ = clamp(r); + + } + Y += 8; + p += offset_to_next_row; + p2 += offset_to_next_row; + } + +#undef SCALEBITS +#undef ONE_HALF +#undef FIX + +} + + +/** + * YCrCb -> RGB24 (2x2) + * .-------. + * | 1 | 2 | + * |---+---| + * | 3 | 4 | + * `-------' + */ +static void YCrCB_to_RGB24_2x2(struct jdec_private *priv) +{ + const unsigned char *Y, *Cb, *Cr; + unsigned char *p, *p2; + int i,j; + int offset_to_next_row; + +#define SCALEBITS 10 +#define ONE_HALF (1UL << (SCALEBITS-1)) +#define FIX(x) ((int)((x) * (1UL<plane[0]; + p2 = priv->plane[0] + priv->width*3; + Y = priv->Y; + Cb = priv->Cb; + Cr = priv->Cr; + offset_to_next_row = (priv->width*3*2) - 16*3; + for (i=0; i<8; i++) { + + for (j=0; j<8; j++) { + + int y, cb, cr; + int add_r, add_g, add_b; + int r, g , b; + + cb = *Cb++ - 128; + cr = *Cr++ - 128; + add_r = FIX(1.40200) * cr + ONE_HALF; + add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; + add_b = FIX(1.77200) * cb + ONE_HALF; + + y = (*Y++) << SCALEBITS; + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + + y = (*Y++) << SCALEBITS; + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + + y = (Y[16-2]) << SCALEBITS; + r = (y + add_r) >> SCALEBITS; + *p2++ = clamp(r); + g = (y + add_g) >> SCALEBITS; + *p2++ = clamp(g); + b = (y + add_b) >> SCALEBITS; + *p2++ = clamp(b); + + y = (Y[16-1]) << SCALEBITS; + r = (y + add_r) >> SCALEBITS; + *p2++ = clamp(r); + g = (y + add_g) >> SCALEBITS; + *p2++ = clamp(g); + b = (y + add_b) >> SCALEBITS; + *p2++ = clamp(b); + } + Y += 16; + p += offset_to_next_row; + p2 += offset_to_next_row; + } + +#undef SCALEBITS +#undef ONE_HALF +#undef FIX + +} + + +/* + * YCrCb -> BGR24 (2x2) + * .-------. + * | 1 | 2 | + * |---+---| + * | 3 | 4 | + * `-------' + */ +static void YCrCB_to_BGR24_2x2(struct jdec_private *priv) +{ + const unsigned char *Y, *Cb, *Cr; + unsigned char *p, *p2; + int i,j; + int offset_to_next_row; + +#define SCALEBITS 10 +#define ONE_HALF (1UL << (SCALEBITS-1)) +#define FIX(x) ((int)((x) * (1UL<plane[0]; + p2 = priv->plane[0] + priv->width*3; + Y = priv->Y; + Cb = priv->Cb; + Cr = priv->Cr; + offset_to_next_row = (priv->width*3*2) - 16*3; + for (i=0; i<8; i++) { + + for (j=0; j<8; j++) { + + int y, cb, cr; + int add_r, add_g, add_b; + int r, g , b; + + cb = *Cb++ - 128; + cr = *Cr++ - 128; + add_r = FIX(1.40200) * cr + ONE_HALF; + add_g = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF; + add_b = FIX(1.77200) * cb + ONE_HALF; + + y = (*Y++) << SCALEBITS; + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + + y = (*Y++) << SCALEBITS; + b = (y + add_b) >> SCALEBITS; + *p++ = clamp(b); + g = (y + add_g) >> SCALEBITS; + *p++ = clamp(g); + r = (y + add_r) >> SCALEBITS; + *p++ = clamp(r); + + y = (Y[16-2]) << SCALEBITS; + b = (y + add_b) >> SCALEBITS; + *p2++ = clamp(b); + g = (y + add_g) >> SCALEBITS; + *p2++ = clamp(g); + r = (y + add_r) >> SCALEBITS; + *p2++ = clamp(r); + + y = (Y[16-1]) << SCALEBITS; + b = (y + add_b) >> SCALEBITS; + *p2++ = clamp(b); + g = (y + add_g) >> SCALEBITS; + *p2++ = clamp(g); + r = (y + add_r) >> SCALEBITS; + *p2++ = clamp(r); + } + Y += 16; + p += offset_to_next_row; + p2 += offset_to_next_row; + } + +#undef SCALEBITS +#undef ONE_HALF +#undef FIX + +} + + + +/** + * YCrCb -> Grey (1x1) + * .---. + * | 1 | + * `---' + */ +static void YCrCB_to_Grey_1x1(struct jdec_private *priv) +{ + const unsigned char *y; + unsigned char *p; + unsigned int i; + int offset_to_next_row; + + p = priv->plane[0]; + y = priv->Y; + offset_to_next_row = priv->width; + + for (i=0; i<8; i++) { + memcpy(p, y, 8); + y+=8; + p += offset_to_next_row; + } +} + +/** + * YCrCb -> Grey (2x1) + * .-------. + * | 1 | 2 | + * `-------' + */ +static void YCrCB_to_Grey_2x1(struct jdec_private *priv) +{ + const unsigned char *y; + unsigned char *p; + unsigned int i; + + p = priv->plane[0]; + y = priv->Y; + + for (i=0; i<8; i++) { + memcpy(p, y, 16); + y += 16; + p += priv->width; + } +} + + +/** + * YCrCb -> Grey (1x2) + * .---. + * | 1 | + * |---| + * | 2 | + * `---' + */ +static void YCrCB_to_Grey_1x2(struct jdec_private *priv) +{ + const unsigned char *y; + unsigned char *p; + unsigned int i; + + p = priv->plane[0]; + y = priv->Y; + + for (i=0; i<16; i++) { + memcpy(p, y, 8); + y += 8; + p += priv->width; + } +} + +/** + * YCrCb -> Grey (2x2) + * .-------. + * | 1 | 2 | + * |---+---| + * | 3 | 4 | + * `-------' + */ +static void YCrCB_to_Grey_2x2(struct jdec_private *priv) +{ + const unsigned char *y; + unsigned char *p; + unsigned int i; + + p = priv->plane[0]; + y = priv->Y; + + for (i=0; i<16; i++) { + memcpy(p, y, 16); + y += 16; + p += priv->width; + } +} + + +/* + * Decode all the 3 components for 1x1 + */ +static void decode_MCU_1x1_3planes(struct jdec_private *priv) +{ + // Y + process_Huffman_data_unit(priv, cY); + IDCT(&priv->component_infos[cY], priv->Y, 8); + + // Cb + process_Huffman_data_unit(priv, cCb); + IDCT(&priv->component_infos[cCb], priv->Cb, 8); + + // Cr + process_Huffman_data_unit(priv, cCr); + IDCT(&priv->component_infos[cCr], priv->Cr, 8); +} + +/* + * Decode a 1x1 directly in 1 color + */ +static void decode_MCU_1x1_1plane(struct jdec_private *priv) +{ + // Y + process_Huffman_data_unit(priv, cY); + IDCT(&priv->component_infos[cY], priv->Y, 8); + + // Cb + process_Huffman_data_unit(priv, cCb); + IDCT(&priv->component_infos[cCb], priv->Cb, 8); + + // Cr + process_Huffman_data_unit(priv, cCr); + IDCT(&priv->component_infos[cCr], priv->Cr, 8); +} + + +/* + * Decode a 2x1 + * .-------. + * | 1 | 2 | + * `-------' + */ +static void decode_MCU_2x1_3planes(struct jdec_private *priv) +{ + // Y + process_Huffman_data_unit(priv, cY); + IDCT(&priv->component_infos[cY], priv->Y, 16); + process_Huffman_data_unit(priv, cY); + IDCT(&priv->component_infos[cY], priv->Y+8, 16); + + // Cb + process_Huffman_data_unit(priv, cCb); + IDCT(&priv->component_infos[cCb], priv->Cb, 8); + + // Cr + process_Huffman_data_unit(priv, cCr); + IDCT(&priv->component_infos[cCr], priv->Cr, 8); +} + +static void pixart_decode_MCU_2x1_3planes(struct jdec_private *priv) +{ + unsigned char marker; + + pixart_look_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, + 8, marker); + /* I think the marker indicates which quantization table to use, iow + a Pixart JPEG may have a different quantization table per MCU, most + MCU's have 0x44 as marker for which our special Pixart quantization + tables are correct. Unfortunately with a 7302 some blocks also have 0x48, + and sometimes even other values. As 0x48 is quite common too, we really + need to find out the correct table for that, as currently the blocks + with a 0x48 marker look wrong. During normal operation the marker stays + within the range below, if it gets out of this range we're most likely + decoding garbage */ + if (marker < 0x20 || marker > 0x7f) { + snprintf(priv->error_string, sizeof(priv->error_string), + "Pixart JPEG error: invalid MCU marker: 0x%02x\n", + (unsigned int)marker); + longjmp(priv->jump_state, -EIO); + } + skip_nbits(priv->reservoir, priv->nbits_in_reservoir, priv->stream, 8); + + // Y + pixart_process_Huffman_data_unit(priv, cY); + IDCT(&priv->component_infos[cY], priv->Y, 16); + pixart_process_Huffman_data_unit(priv, cY); + IDCT(&priv->component_infos[cY], priv->Y+8, 16); + + // Cb + pixart_process_Huffman_data_unit(priv, cCb); + IDCT(&priv->component_infos[cCb], priv->Cb, 8); + + // Cr + pixart_process_Huffman_data_unit(priv, cCr); + IDCT(&priv->component_infos[cCr], priv->Cr, 8); +} + +/* + * Decode a 2x1 + * .-------. + * | 1 | 2 | + * `-------' + */ +static void decode_MCU_2x1_1plane(struct jdec_private *priv) +{ + // Y + process_Huffman_data_unit(priv, cY); + IDCT(&priv->component_infos[cY], priv->Y, 16); + process_Huffman_data_unit(priv, cY); + IDCT(&priv->component_infos[cY], priv->Y+8, 16); + + // Cb + process_Huffman_data_unit(priv, cCb); + + // Cr + process_Huffman_data_unit(priv, cCr); +} + + +/* + * Decode a 2x2 + * .-------. + * | 1 | 2 | + * |---+---| + * | 3 | 4 | + * `-------' + */ +static void decode_MCU_2x2_3planes(struct jdec_private *priv) +{ + // Y + process_Huffman_data_unit(priv, cY); + IDCT(&priv->component_infos[cY], priv->Y, 16); + process_Huffman_data_unit(priv, cY); + IDCT(&priv->component_infos[cY], priv->Y+8, 16); + process_Huffman_data_unit(priv, cY); + IDCT(&priv->component_infos[cY], priv->Y+64*2, 16); + process_Huffman_data_unit(priv, cY); + IDCT(&priv->component_infos[cY], priv->Y+64*2+8, 16); + + // Cb + process_Huffman_data_unit(priv, cCb); + IDCT(&priv->component_infos[cCb], priv->Cb, 8); + + // Cr + process_Huffman_data_unit(priv, cCr); + IDCT(&priv->component_infos[cCr], priv->Cr, 8); +} + +/* + * Decode a 2x2 directly in GREY format (8bits) + * .-------. + * | 1 | 2 | + * |---+---| + * | 3 | 4 | + * `-------' + */ +static void decode_MCU_2x2_1plane(struct jdec_private *priv) +{ + // Y + process_Huffman_data_unit(priv, cY); + IDCT(&priv->component_infos[cY], priv->Y, 16); + process_Huffman_data_unit(priv, cY); + IDCT(&priv->component_infos[cY], priv->Y+8, 16); + process_Huffman_data_unit(priv, cY); + IDCT(&priv->component_infos[cY], priv->Y+64*2, 16); + process_Huffman_data_unit(priv, cY); + IDCT(&priv->component_infos[cY], priv->Y+64*2+8, 16); + + // Cb + process_Huffman_data_unit(priv, cCb); + + // Cr + process_Huffman_data_unit(priv, cCr); +} + +/* + * Decode a 1x2 mcu + * .---. + * | 1 | + * |---| + * | 2 | + * `---' + */ +static void decode_MCU_1x2_3planes(struct jdec_private *priv) +{ + // Y + process_Huffman_data_unit(priv, cY); + IDCT(&priv->component_infos[cY], priv->Y, 8); + process_Huffman_data_unit(priv, cY); + IDCT(&priv->component_infos[cY], priv->Y+64, 8); + + // Cb + process_Huffman_data_unit(priv, cCb); + IDCT(&priv->component_infos[cCb], priv->Cb, 8); + + // Cr + process_Huffman_data_unit(priv, cCr); + IDCT(&priv->component_infos[cCr], priv->Cr, 8); +} + +/* + * Decode a 1x2 mcu + * .---. + * | 1 | + * |---| + * | 2 | + * `---' + */ +static void decode_MCU_1x2_1plane(struct jdec_private *priv) +{ + // Y + process_Huffman_data_unit(priv, cY); + IDCT(&priv->component_infos[cY], priv->Y, 8); + process_Huffman_data_unit(priv, cY); + IDCT(&priv->component_infos[cY], priv->Y+64, 8); + + // Cb + process_Huffman_data_unit(priv, cCb); + + // Cr + process_Huffman_data_unit(priv, cCr); +} + +static void print_SOF(const unsigned char *stream) +{ + int width, height, nr_components, precision; +#if DEBUG + const char *nr_components_to_string[] = { + "????", + "Grayscale", + "????", + "YCbCr", + "CYMK" + }; +#endif + + precision = stream[2]; + height = be16_to_cpu(stream+3); + width = be16_to_cpu(stream+5); + nr_components = stream[7]; + + trace("> SOF marker\n"); + trace("Size:%dx%d nr_components:%d (%s) precision:%d\n", + width, height, + nr_components, nr_components_to_string[nr_components], + precision); +} + +/******************************************************************************* + * + * JPEG/JFIF Parsing functions + * + * Note: only a small subset of the jpeg file format is supported. No markers, + * nor progressive stream is supported. + * + ******************************************************************************/ + +static void build_quantization_table(float *qtable, const unsigned char *ref_table) +{ + /* Taken from libjpeg. Copyright Independent JPEG Group's LLM idct. + * For float AA&N IDCT method, divisors are equal to quantization + * coefficients scaled by scalefactor[row]*scalefactor[col], where + * scalefactor[0] = 1 + * scalefactor[k] = cos(k*PI/16) * sqrt(2) for k=1..7 + * We apply a further scale factor of 8. + * What's actually stored is 1/divisor so that the inner loop can + * use a multiplication rather than a division. + */ + int i, j; + static const double aanscalefactor[8] = { + 1.0, 1.387039845, 1.306562965, 1.175875602, + 1.0, 0.785694958, 0.541196100, 0.275899379 + }; + const unsigned char *zz = zigzag; + + for (i=0; i<8; i++) { + for (j=0; j<8; j++) { + *qtable++ = ref_table[*zz++] * aanscalefactor[i] * aanscalefactor[j]; + } + } + +} + +static int parse_DQT(struct jdec_private *priv, const unsigned char *stream) +{ + int qi; + float *table; + const unsigned char *dqt_block_end; + + trace("> DQT marker\n"); + dqt_block_end = stream + be16_to_cpu(stream); + stream += 2; /* Skip length */ + + while (stream < dqt_block_end) + { + qi = *stream++; +#if SANITY_CHECK + if (qi>>4) + error("16 bits quantization table is not supported\n"); + if (qi >= COMPONENTS) + error("No more than %d quantization tables supported (got %d)\n", + COMPONENTS, qi + 1); +#endif + table = priv->Q_tables[qi]; + build_quantization_table(table, stream); + stream += 64; + } + trace("< DQT marker\n"); + return 0; +} + +static int parse_SOF(struct jdec_private *priv, const unsigned char *stream) +{ + int i, width, height, nr_components, cid, sampling_factor; + int Q_table; + struct component *c; + + trace("> SOF marker\n"); + print_SOF(stream); + + height = be16_to_cpu(stream+3); + width = be16_to_cpu(stream+5); + nr_components = stream[7]; +#if SANITY_CHECK + if (stream[2] != 8) + error("Precision other than 8 is not supported\n"); + if (width>JPEG_MAX_WIDTH || height>JPEG_MAX_HEIGHT) + error("Width and Height (%dx%d) seems suspicious\n", width, height); + if (nr_components != 3) + error("We only support YUV images\n"); + if (height%8) + error("Height need to be a multiple of 8 (current height is %d)\n", height); + if (width%16) + error("Width need to be a multiple of 16 (current Width is %d)\n", width); +#endif + stream += 8; + for (i=0; icomponent_infos[i]; +#if SANITY_CHECK + c->cid = cid; +#endif + c->Vfactor = sampling_factor&0xf; + c->Hfactor = sampling_factor>>4; + c->Q_table = priv->Q_tables[Q_table]; + trace("Component:%d factor:%dx%d Quantization table:%d\n", + cid, c->Hfactor, c->Hfactor, Q_table ); + + } + priv->width = width; + priv->height = height; + + trace("< SOF marker\n"); + + return 0; +} + +static int parse_SOS(struct jdec_private *priv, const unsigned char *stream) +{ + unsigned int i, cid, table; + unsigned int nr_components = stream[2]; + + trace("> SOS marker\n"); + +#if SANITY_CHECK + if (nr_components != 3) + error("We only support YCbCr image\n"); +#endif + + stream += 3; + for (i=0;i= HUFFMAN_TABLES) + error("We do not support more than %d AC Huffman table\n", + HUFFMAN_TABLES); + if ((table>>4) >= HUFFMAN_TABLES) + error("We do not support more than %d DC Huffman table\n", + HUFFMAN_TABLES); + if (cid != priv->component_infos[i].cid) + error("SOS cid order (%u:%u) isn't compatible with the SOF marker (%u:%u)\n", + i, cid, i, priv->component_infos[i].cid); + trace("ComponentId:%u tableAC:%d tableDC:%d\n", cid, table&0xf, table>>4); +#endif + priv->component_infos[i].AC_table = &priv->HTAC[table&0xf]; + priv->component_infos[i].DC_table = &priv->HTDC[table>>4]; + } + priv->stream = stream+3; + + /* ITU-T T.81 (9/92) chapter E.1.3 clearly states that RSTm is to be set to 0 at the beginning of each scan */ + priv->last_rst_marker_seen = 0; + + trace("< SOS marker\n"); + + return 0; +} + +static int parse_DHT(struct jdec_private *priv, const unsigned char *stream) +{ + unsigned int count, i; + unsigned char huff_bits[17]; + int length, index; + + length = be16_to_cpu(stream) - 2; + stream += 2; /* Skip length */ + + trace("> DHT marker (length=%d)\n", length); + + while (length>0) { + index = *stream++; + + /* We need to calculate the number of bytes 'vals' will takes */ + huff_bits[0] = 0; + count = 0; + for (i=1; i<17; i++) { + huff_bits[i] = *stream++; + count += huff_bits[i]; + } +#if SANITY_CHECK + if (count > 1024) + error("No more than 1024 bytes is allowed to describe a huffman table\n"); + if ( (index &0xf) >= HUFFMAN_TABLES) + error("No mode than %d Huffman tables is supported\n", HUFFMAN_TABLES); + trace("Huffman table %s n%d\n", (index&0xf0)?"AC":"DC", index&0xf); + trace("Length of the table: %d\n", count); +#endif + + if (index & 0xf0 ) { + if (build_huffman_table(priv, huff_bits, stream, &priv->HTAC[index&0xf])) + return -1; + } else { + if (build_huffman_table(priv, huff_bits, stream, &priv->HTDC[index&0xf])) + return -1; + } + + length -= 1; + length -= 16; + length -= count; + stream += count; + } + trace("< DHT marker\n"); + return 0; +} + +static int parse_DRI(struct jdec_private *priv, const unsigned char *stream) +{ + unsigned int length; + + trace("> DRI marker\n"); + + length = be16_to_cpu(stream); + +#if SANITY_CHECK + if (length != 4) + error("Length of DRI marker need to be 4\n"); +#endif + + priv->restart_interval = be16_to_cpu(stream+2); + +#if DEBUG + trace("Restart interval = %d\n", priv->restart_interval); +#endif + + trace("< DRI marker\n"); + + return 0; +} + + + +static void resync(struct jdec_private *priv) +{ + int i; + + /* Init DC coefficients */ + for (i=0; icomponent_infos[i].previous_DC = 0; + + priv->reservoir = 0; + priv->nbits_in_reservoir = 0; + if (priv->restart_interval > 0) + priv->restarts_to_go = priv->restart_interval; + else + priv->restarts_to_go = -1; +} + +static int find_next_rst_marker(struct jdec_private *priv) +{ + int rst_marker_found = 0; + int marker; + const unsigned char *stream = priv->stream; + + /* Parse marker */ + while (!rst_marker_found) + { + while (*stream++ != 0xff) + { + if (stream >= priv->stream_end) + error("EOF while search for a RST marker.\n"); + } + /* Skip any padding ff byte (this is normal) */ + while (*stream == 0xff) + stream++; + + marker = *stream++; + if ((RST+priv->last_rst_marker_seen) == marker) + rst_marker_found = 1; + else if (marker >= RST && marker <= RST7) + error("Wrong Reset marker found, abording\n"); + else if (marker == EOI) + return 0; + } + + priv->stream = stream; + priv->last_rst_marker_seen++; + priv->last_rst_marker_seen &= 7; + + return 0; +} + +static int parse_JFIF(struct jdec_private *priv, const unsigned char *stream) +{ + int chuck_len; + int marker; + int sof_marker_found = 0; + int dqt_marker_found = 0; + int sos_marker_found = 0; + int dht_marker_found = 0; + const unsigned char *next_chunck; + + /* Parse marker */ + while (!sos_marker_found) + { + if (*stream++ != 0xff) + goto bogus_jpeg_format; + /* Skip any padding ff byte (this is normal) */ + while (*stream == 0xff) + stream++; + + marker = *stream++; + chuck_len = be16_to_cpu(stream); + next_chunck = stream + chuck_len; + switch (marker) + { + case SOF: + if (parse_SOF(priv, stream) < 0) + return -1; + sof_marker_found = 1; + break; + case DQT: + if (parse_DQT(priv, stream) < 0) + return -1; + dqt_marker_found = 1; + break; + case SOS: + if (parse_SOS(priv, stream) < 0) + return -1; + sos_marker_found = 1; + break; + case DHT: + if (parse_DHT(priv, stream) < 0) + return -1; + dht_marker_found = 1; + break; + case DRI: + if (parse_DRI(priv, stream) < 0) + return -1; + break; + default: + trace("> Unknown marker %2.2x\n", marker); + break; + } + + stream = next_chunck; + } + + if ( !sof_marker_found || + (!dqt_marker_found && !(priv->flags & TINYJPEG_FLAGS_PIXART_JPEG))) + goto bogus_jpeg_format; + + if (priv->flags & TINYJPEG_FLAGS_PIXART_JPEG) { + if (!priv->default_huffman_table_initialized) { + build_quantization_table(priv->Q_tables[0], pixart_quantization[0]); + build_quantization_table(priv->Q_tables[1], pixart_quantization[1]); + } + + /* Pixart JPEG data starts with one unknown / unused byte */ + priv->stream++; + } + + if (!dht_marker_found) { + trace("No Huffman table loaded, using the default one\n"); + if (build_default_huffman_tables(priv)) + return -1; + } + +#ifdef SANITY_CHECK + if ( (priv->component_infos[cY].Hfactor < priv->component_infos[cCb].Hfactor) + || (priv->component_infos[cY].Hfactor < priv->component_infos[cCr].Hfactor)) + error("Horizontal sampling factor for Y should be greater than horitontal sampling factor for Cb or Cr\n"); + if ( (priv->component_infos[cY].Vfactor < priv->component_infos[cCb].Vfactor) + || (priv->component_infos[cY].Vfactor < priv->component_infos[cCr].Vfactor)) + error("Vertical sampling factor for Y should be greater than vertical sampling factor for Cb or Cr\n"); + if ( (priv->component_infos[cCb].Hfactor!=1) + || (priv->component_infos[cCr].Hfactor!=1) + || (priv->component_infos[cCb].Vfactor!=1) + || (priv->component_infos[cCr].Vfactor!=1)) + error("Sampling other than 1x1 for Cr and Cb is not supported\n"); +#endif + + return 0; +bogus_jpeg_format: + error("Bogus jpeg format\n"); + return -1; +} + +/******************************************************************************* + * + * Functions exported of the library. + * + * Note: Some applications can access directly to internal pointer of the + * structure. It's is not recommended, but if you have many images to + * uncompress with the same parameters, some functions can be called to speedup + * the decoding. + * + ******************************************************************************/ + +/** + * Allocate a new tinyjpeg decoder object. + * + * Before calling any other functions, an object need to be called. + */ +struct jdec_private *tinyjpeg_init(void) +{ + struct jdec_private *priv; + + priv = (struct jdec_private *)calloc(1, sizeof(struct jdec_private)); + if (priv == NULL) + return NULL; + return priv; +} + +/** + * Free a tinyjpeg object. + * + * No others function can be called after this one. + */ +void tinyjpeg_free(struct jdec_private *priv) +{ + int i; + for (i=0; icomponents[i]) + free(priv->components[i]); + priv->components[i] = NULL; + } + free(priv); +} + +/** + * Initialize the tinyjpeg object and prepare the decoding of the stream. + * + * Check if the jpeg can be decoded with this jpeg decoder. + * Fill some table used for preprocessing. + */ +int tinyjpeg_parse_header(struct jdec_private *priv, const unsigned char *buf, unsigned int size) +{ + int ret; + + /* Identify the file */ + if ((buf[0] != 0xFF) || (buf[1] != SOI)) + error("Not a JPG file ?\n"); + + priv->stream_begin = buf+2; + priv->stream_length = size-2; + priv->stream_end = priv->stream_begin + priv->stream_length; + + ret = parse_JFIF(priv, priv->stream_begin); + + return ret; +} + +static const decode_MCU_fct decode_mcu_3comp_table[4] = { + decode_MCU_1x1_3planes, + decode_MCU_1x2_3planes, + decode_MCU_2x1_3planes, + decode_MCU_2x2_3planes, +}; + +static const decode_MCU_fct pixart_decode_mcu_3comp_table[4] = { + NULL, + NULL, + pixart_decode_MCU_2x1_3planes, + NULL, +}; + +static const decode_MCU_fct decode_mcu_1comp_table[4] = { + decode_MCU_1x1_1plane, + decode_MCU_1x2_1plane, + decode_MCU_2x1_1plane, + decode_MCU_2x2_1plane, +}; + +static const convert_colorspace_fct convert_colorspace_yuv420p[4] = { + YCrCB_to_YUV420P_1x1, + YCrCB_to_YUV420P_1x2, + YCrCB_to_YUV420P_2x1, + YCrCB_to_YUV420P_2x2, +}; + +static const convert_colorspace_fct convert_colorspace_rgb24[4] = { + YCrCB_to_RGB24_1x1, + YCrCB_to_RGB24_1x2, + YCrCB_to_RGB24_2x1, + YCrCB_to_RGB24_2x2, +}; + +static const convert_colorspace_fct convert_colorspace_bgr24[4] = { + YCrCB_to_BGR24_1x1, + YCrCB_to_BGR24_1x2, + YCrCB_to_BGR24_2x1, + YCrCB_to_BGR24_2x2, +}; + +static const convert_colorspace_fct convert_colorspace_grey[4] = { + YCrCB_to_Grey_1x1, + YCrCB_to_Grey_1x2, + YCrCB_to_Grey_2x1, + YCrCB_to_Grey_2x2, +}; + +/** + * Decode and convert the jpeg image into @pixfmt@ image + * + * Note: components will be automaticaly allocated if no memory is attached. + */ +int tinyjpeg_decode(struct jdec_private *priv, int pixfmt) +{ + unsigned int x, y, xstride_by_mcu, ystride_by_mcu; + unsigned int bytes_per_blocklines[3], bytes_per_mcu[3]; + decode_MCU_fct decode_MCU; + const decode_MCU_fct *decode_mcu_table; + const convert_colorspace_fct *colorspace_array_conv; + convert_colorspace_fct convert_to_pixfmt; + + if (setjmp(priv->jump_state)) + return -1; + + /* To keep gcc happy initialize some array */ + bytes_per_mcu[1] = 0; + bytes_per_mcu[2] = 0; + bytes_per_blocklines[1] = 0; + bytes_per_blocklines[2] = 0; + + decode_mcu_table = decode_mcu_3comp_table; + if (priv->flags & TINYJPEG_FLAGS_PIXART_JPEG) + decode_mcu_table = pixart_decode_mcu_3comp_table; + + switch (pixfmt) { + case TINYJPEG_FMT_YUV420P: + colorspace_array_conv = convert_colorspace_yuv420p; + if (priv->components[0] == NULL) + priv->components[0] = (uint8_t *)malloc(priv->width * priv->height); + if (priv->components[1] == NULL) + priv->components[1] = (uint8_t *)malloc(priv->width * priv->height/4); + if (priv->components[2] == NULL) + priv->components[2] = (uint8_t *)malloc(priv->width * priv->height/4); + bytes_per_blocklines[0] = priv->width; + bytes_per_blocklines[1] = priv->width/4; + bytes_per_blocklines[2] = priv->width/4; + bytes_per_mcu[0] = 8; + bytes_per_mcu[1] = 4; + bytes_per_mcu[2] = 4; + break; + + case TINYJPEG_FMT_RGB24: + colorspace_array_conv = convert_colorspace_rgb24; + if (priv->components[0] == NULL) + priv->components[0] = (uint8_t *)malloc(priv->width * priv->height * 3); + bytes_per_blocklines[0] = priv->width * 3; + bytes_per_mcu[0] = 3*8; + break; + + case TINYJPEG_FMT_BGR24: + colorspace_array_conv = convert_colorspace_bgr24; + if (priv->components[0] == NULL) + priv->components[0] = (uint8_t *)malloc(priv->width * priv->height * 3); + bytes_per_blocklines[0] = priv->width * 3; + bytes_per_mcu[0] = 3*8; + break; + + case TINYJPEG_FMT_GREY: + decode_mcu_table = decode_mcu_1comp_table; + if (priv->flags & TINYJPEG_FLAGS_PIXART_JPEG) + error("Greyscale output not support for PIXART JPEG's\n"); + colorspace_array_conv = convert_colorspace_grey; + if (priv->components[0] == NULL) + priv->components[0] = (uint8_t *)malloc(priv->width * priv->height); + bytes_per_blocklines[0] = priv->width; + bytes_per_mcu[0] = 8; + break; + + default: + error("Bad pixel format\n"); + } + + xstride_by_mcu = ystride_by_mcu = 8; + if ((priv->component_infos[cY].Hfactor | priv->component_infos[cY].Vfactor) == 1) { + decode_MCU = decode_mcu_table[0]; + convert_to_pixfmt = colorspace_array_conv[0]; + trace("Use decode 1x1 sampling\n"); + } else if (priv->component_infos[cY].Hfactor == 1) { + decode_MCU = decode_mcu_table[1]; + convert_to_pixfmt = colorspace_array_conv[1]; + ystride_by_mcu = 16; + trace("Use decode 1x2 sampling (not supported)\n"); + } else if (priv->component_infos[cY].Vfactor == 2) { + decode_MCU = decode_mcu_table[3]; + convert_to_pixfmt = colorspace_array_conv[3]; + xstride_by_mcu = 16; + ystride_by_mcu = 16; + trace("Use decode 2x2 sampling\n"); + } else { + decode_MCU = decode_mcu_table[2]; + convert_to_pixfmt = colorspace_array_conv[2]; + xstride_by_mcu = 16; + trace("Use decode 2x1 sampling\n"); + } + + if (decode_MCU == NULL) + error("no decode MCU function for this JPEG format (PIXART?)\n"); + + resync(priv); + + /* Don't forget to that block can be either 8 or 16 lines */ + bytes_per_blocklines[0] *= ystride_by_mcu; + bytes_per_blocklines[1] *= ystride_by_mcu; + bytes_per_blocklines[2] *= ystride_by_mcu; + + bytes_per_mcu[0] *= xstride_by_mcu/8; + bytes_per_mcu[1] *= xstride_by_mcu/8; + bytes_per_mcu[2] *= xstride_by_mcu/8; + + /* Just the decode the image by macroblock (size is 8x8, 8x16, or 16x16) */ + for (y=0; y < priv->height/ystride_by_mcu; y++) + { + //trace("Decoding row %d\n", y); + priv->plane[0] = priv->components[0] + (y * bytes_per_blocklines[0]); + priv->plane[1] = priv->components[1] + (y * bytes_per_blocklines[1]); + priv->plane[2] = priv->components[2] + (y * bytes_per_blocklines[2]); + for (x=0; x < priv->width; x+=xstride_by_mcu) + { + decode_MCU(priv); + convert_to_pixfmt(priv); + priv->plane[0] += bytes_per_mcu[0]; + priv->plane[1] += bytes_per_mcu[1]; + priv->plane[2] += bytes_per_mcu[2]; + if (priv->restarts_to_go>0) + { + priv->restarts_to_go--; + if (priv->restarts_to_go == 0) + { + priv->stream -= (priv->nbits_in_reservoir/8); + resync(priv); + if (find_next_rst_marker(priv) < 0) + return -1; + } + } + } + } + + if (priv->flags & TINYJPEG_FLAGS_PIXART_JPEG) { + /* Additional sanity check for funky Pixart format */ + if ((priv->stream_end - priv->stream) > 5) + error("Pixart JPEG error, stream does not end with EOF marker\n"); + } + + return 0; +} + +const char *tinyjpeg_get_errorstring(struct jdec_private *priv) +{ + return priv->error_string; +} + +void tinyjpeg_get_size(struct jdec_private *priv, unsigned int *width, unsigned int *height) +{ + *width = priv->width; + *height = priv->height; +} + +int tinyjpeg_get_components(struct jdec_private *priv, unsigned char **components) +{ + int i; + for (i=0; priv->components[i] && icomponents[i]; + return 0; +} + +int tinyjpeg_set_components(struct jdec_private *priv, unsigned char **components, unsigned int ncomponents) +{ + unsigned int i; + if (ncomponents > COMPONENTS) + ncomponents = COMPONENTS; + for (i=0; icomponents[i] = components[i]; + return 0; +} + +int tinyjpeg_set_flags(struct jdec_private *priv, int flags) +{ + int oldflags = priv->flags; + priv->flags = flags; + return oldflags; +} + diff --git a/v4l2-apps/libv4l/libv4lconvert/tinyjpeg.h b/v4l2-apps/libv4l/libv4lconvert/tinyjpeg.h new file mode 100644 index 000000000..b0096f0de --- /dev/null +++ b/v4l2-apps/libv4l/libv4lconvert/tinyjpeg.h @@ -0,0 +1,74 @@ +/* + * Small jpeg decoder library (header file) + * + * Copyright (c) 2006, Luc Saillard + * All rights reserved. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * - Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * - Neither the name of the author nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + + +#ifndef __JPEGDEC_H__ +#define __JPEGDEC_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +struct jdec_private; + +/* Flags that can be set by any applications */ +#define TINYJPEG_FLAGS_MJPEG_TABLE (1<<1) +#define TINYJPEG_FLAGS_PIXART_JPEG (1<<2) + +/* Format accepted in outout */ +enum tinyjpeg_fmt { + TINYJPEG_FMT_GREY = 1, + TINYJPEG_FMT_BGR24, + TINYJPEG_FMT_RGB24, + TINYJPEG_FMT_YUV420P, +}; + +struct jdec_private *tinyjpeg_init(void); +void tinyjpeg_free(struct jdec_private *priv); + +int tinyjpeg_parse_header(struct jdec_private *priv, const unsigned char *buf, unsigned int size); +int tinyjpeg_decode(struct jdec_private *priv, int pixel_format); +const char *tinyjpeg_get_errorstring(struct jdec_private *priv); +void tinyjpeg_get_size(struct jdec_private *priv, unsigned int *width, unsigned int *height); +int tinyjpeg_get_components(struct jdec_private *priv, unsigned char **components); +int tinyjpeg_set_components(struct jdec_private *priv, unsigned char **components, unsigned int ncomponents); +int tinyjpeg_set_flags(struct jdec_private *priv, int flags); + +#ifdef __cplusplus +} +#endif + +#endif + + + diff --git a/v4l2-apps/libv4l2util/COPYING.LIB b/v4l2-apps/libv4l2util/COPYING.LIB new file mode 100644 index 000000000..1dd325d2b --- /dev/null +++ b/v4l2-apps/libv4l2util/COPYING.LIB @@ -0,0 +1,510 @@ + + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations +below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. +^L + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it +becomes a de-facto standard. To achieve this, non-free programs must +be allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. +^L + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control +compilation and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. +^L + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. +^L + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at least + three years, to give the same user the materials specified in + Subsection 6a, above, for a charge no more than the cost of + performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. +^L + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. +^L + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply, and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License +may add an explicit geographical distribution limitation excluding those +countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. +^L + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS +^L + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms +of the ordinary General Public License). + + To apply these terms, attach the following notices to the library. +It is safest to attach them to the start of each source file to most +effectively convey the exclusion of warranty; and each file should +have at least the "copyright" line and a pointer to where the full +notice is found. + + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or +your school, if any, to sign a "copyright disclaimer" for the library, +if necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James + Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/v4l2-apps/libv4l2util/Makefile b/v4l2-apps/libv4l2util/Makefile new file mode 100644 index 000000000..f3f413071 --- /dev/null +++ b/v4l2-apps/libv4l2util/Makefile @@ -0,0 +1,33 @@ +# Makefile for linuxtv.org v4l2-apps/lib + +CPPFLAGS += -I../include -I.. + +includes = libv4l2util.h + +objects = frequencies.o v4l2_driver.o + +sharedlib = libv4l2util.so +staticlib = libv4l2util.a + +ifeq ($(prefix),) +prefix = /usr +endif + +.PHONY: all clean install + +all: $(sharedlib) $(staticlib) + +$(sharedlib): $(objects) + +$(staticlib): $(objects) + +clean:: + rm -f $(objects) $(sharedlib) $(staticlib) + +install: + mkdir -p $(prefix)/include + cp $(includes) $(prefix)/include + mkdir -p $(prefix)/lib + cp $(sharedlib) $(staticlib) $(prefix)/lib + +include ../Make.rules diff --git a/v4l2-apps/libv4l2util/TODO b/v4l2-apps/libv4l2util/TODO new file mode 100644 index 000000000..456a916ce --- /dev/null +++ b/v4l2-apps/libv4l2util/TODO @@ -0,0 +1,81 @@ +The only capture method implemented currently is mmap. + +Missing V4L2 ioctls to be implemented at library: + Methods to change controls at V4L devices: + VIDIOC_QUERYCTRL + VIDIOC_QUERYMENU + VIDIOC_G_CTRL + VIDIOC_S_CTRL + VIDIOC_TRY_EXT_CTRLS + VIDIOC_G_EXT_CTRLS + VIDIOC_S_EXT_CTRLS + + Tuner control methods: + VIDIOC_G_TUNER + VIDIOC_S_TUNER + VIDIOC_S_FREQUENCY + VIDIOC_G_FREQUENCY + + Crop methods: + VIDIOC_CROPCAP + VIDIOC_S_CROP + VIDIOC_G_CROP + + Audio input/output: + VIDIOC_ENUMAUDIO + VIDIOC_ENUMAUDOUT + VIDIOC_G_AUDIO + VIDIOC_S_AUDIO + VIDIOC_G_AUDOUT + VIDIOC_S_AUDOUT + + Video output: + VIDIOC_ENUMOUTPUT + VIDIOC_G_OUTPUT + VIDIOC_S_OUTPUT + + Priority control: + VIDIOC_G_PRIORITY + VIDIOC_S_PRIORITY + + Sliced VBI control: + VIDIOC_G_SLICED_VBI_CAP + + The received video STD: + VIDIOC_QUERYSTD + + Streaming parameters: + VIDIOC_G_PARM + VIDIOC_S_PARM + + Output modulator (generally for TV): + VIDIOC_G_MODULATOR + VIDIOC_S_MODULATOR + + Those methods are brand new. Not yet used on drivers: + VIDIOC_ENUM_FRAMEINTERVALS + VIDIOC_ENUM_FRAMESIZES + + Overlay is somewhat legacy stuff those days: + VIDIOC_OVERLAY + VIDIOC_G_FBUF + VIDIOC_S_FBUF + + Those are unlikely to be implemented at API (legacy stuff, debug stuff or private): + VIDIOC_G_JPEGCOMP + VIDIOC_S_JPEGCOMP + VIDIOC_LOG_STATUS + VIDIOC_PRIVATE + VIDIOC_RESERVED + VIDIOC_OVERLAY_OLD + VIDIOC_S_PARM_OLD + VIDIOC_S_CTRL_OLD + VIDIOC_G_AUDIO_OLD + VIDIOC_G_AUDOUT_OLD + VIDIOC_CROPCAP_OLD + +Also missing V4L1 mmap method: + VIDIOCGMBUF + + This method is interesting only to be used by driver-test to check +API compliance to the legacy method. diff --git a/v4l2-apps/libv4l2util/frequencies.c b/v4l2-apps/libv4l2util/frequencies.c new file mode 100644 index 000000000..df8d47dba --- /dev/null +++ b/v4l2-apps/libv4l2util/frequencies.c @@ -0,0 +1,1502 @@ +/* Copyright (C) 2006 Nathan Laredo + Nathan contributed the frequency tables. + + Copyright (C) 2006 Hans Verkuil + Added the iso-std table. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include + +#include +#include "libv4l2util.h" + +/* This source was originally written by Nathan Laredo . + He kindly gave permission to release this source under the LGPL + license. */ + +/* --------------------------------------------------------------------- */ + +/* US broadcast */ +static const struct v4l2_channel_list ntsc_bcast[] = { + { "2", 55250 }, + { "3", 61250 }, + { "4", 67250 }, + { "5", 77250 }, + { "6", 83250 }, + { "7", 175250 }, + { "8", 181250 }, + { "9", 187250 }, + { "10", 193250 }, + { "11", 199250 }, + { "12", 205250 }, + { "13", 211250 }, + { "14", 471250 }, + { "15", 477250 }, + { "16", 483250 }, + { "17", 489250 }, + { "18", 495250 }, + { "19", 501250 }, + { "20", 507250 }, + { "21", 513250 }, + { "22", 519250 }, + { "23", 525250 }, + { "24", 531250 }, + { "25", 537250 }, + { "26", 543250 }, + { "27", 549250 }, + { "28", 555250 }, + { "29", 561250 }, + { "30", 567250 }, + { "31", 573250 }, + { "32", 579250 }, + { "33", 585250 }, + { "34", 591250 }, + { "35", 597250 }, + { "36", 603250 }, + { "37", 609250 }, + { "38", 615250 }, + { "39", 621250 }, + { "40", 627250 }, + { "41", 633250 }, + { "42", 639250 }, + { "43", 645250 }, + { "44", 651250 }, + { "45", 657250 }, + { "46", 663250 }, + { "47", 669250 }, + { "48", 675250 }, + { "49", 681250 }, + { "50", 687250 }, + { "51", 693250 }, + { "52", 699250 }, + { "53", 705250 }, + { "54", 711250 }, + { "55", 717250 }, + { "56", 723250 }, + { "57", 729250 }, + { "58", 735250 }, + { "59", 741250 }, + { "60", 747250 }, + { "61", 753250 }, + { "62", 759250 }, + { "63", 765250 }, + { "64", 771250 }, + { "65", 777250 }, + { "66", 783250 }, + { "67", 789250 }, + { "68", 795250 }, + { "69", 801250 }, + + { "70", 807250 }, + { "71", 813250 }, + { "72", 819250 }, + { "73", 825250 }, + { "74", 831250 }, + { "75", 837250 }, + { "76", 843250 }, + { "77", 849250 }, + { "78", 855250 }, + { "79", 861250 }, + { "80", 867250 }, + { "81", 873250 }, + { "82", 879250 }, + { "83", 885250 }, +}; + +/* US cable */ +static const struct v4l2_channel_list ntsc_cable[] = { + { "1", 73250 }, + { "2", 55250 }, + { "3", 61250 }, + { "4", 67250 }, + { "5", 77250 }, + { "6", 83250 }, + { "7", 175250 }, + { "8", 181250 }, + { "9", 187250 }, + { "10", 193250 }, + { "11", 199250 }, + { "12", 205250 }, + + { "13", 211250 }, + { "14", 121250 }, + { "15", 127250 }, + { "16", 133250 }, + { "17", 139250 }, + { "18", 145250 }, + { "19", 151250 }, + { "20", 157250 }, + + { "21", 163250 }, + { "22", 169250 }, + { "23", 217250 }, + { "24", 223250 }, + { "25", 229250 }, + { "26", 235250 }, + { "27", 241250 }, + { "28", 247250 }, + { "29", 253250 }, + { "30", 259250 }, + { "31", 265250 }, + { "32", 271250 }, + { "33", 277250 }, + { "34", 283250 }, + { "35", 289250 }, + { "36", 295250 }, + { "37", 301250 }, + { "38", 307250 }, + { "39", 313250 }, + { "40", 319250 }, + { "41", 325250 }, + { "42", 331250 }, + { "43", 337250 }, + { "44", 343250 }, + { "45", 349250 }, + { "46", 355250 }, + { "47", 361250 }, + { "48", 367250 }, + { "49", 373250 }, + { "50", 379250 }, + { "51", 385250 }, + { "52", 391250 }, + { "53", 397250 }, + { "54", 403250 }, + { "55", 409250 }, + { "56", 415250 }, + { "57", 421250 }, + { "58", 427250 }, + { "59", 433250 }, + { "60", 439250 }, + { "61", 445250 }, + { "62", 451250 }, + { "63", 457250 }, + { "64", 463250 }, + { "65", 469250 }, + { "66", 475250 }, + { "67", 481250 }, + { "68", 487250 }, + { "69", 493250 }, + + { "70", 499250 }, + { "71", 505250 }, + { "72", 511250 }, + { "73", 517250 }, + { "74", 523250 }, + { "75", 529250 }, + { "76", 535250 }, + { "77", 541250 }, + { "78", 547250 }, + { "79", 553250 }, + { "80", 559250 }, + { "81", 565250 }, + { "82", 571250 }, + { "83", 577250 }, + { "84", 583250 }, + { "85", 589250 }, + { "86", 595250 }, + { "87", 601250 }, + { "88", 607250 }, + { "89", 613250 }, + { "90", 619250 }, + { "91", 625250 }, + { "92", 631250 }, + { "93", 637250 }, + { "94", 643250 }, + { "95", 91250 }, + { "96", 97250 }, + { "97", 103250 }, + { "98", 109250 }, + { "99", 115250 }, + { "100", 649250 }, + { "101", 655250 }, + { "102", 661250 }, + { "103", 667250 }, + { "104", 673250 }, + { "105", 679250 }, + { "106", 685250 }, + { "107", 691250 }, + { "108", 697250 }, + { "109", 703250 }, + { "110", 709250 }, + { "111", 715250 }, + { "112", 721250 }, + { "113", 727250 }, + { "114", 733250 }, + { "115", 739250 }, + { "116", 745250 }, + { "117", 751250 }, + { "118", 757250 }, + { "119", 763250 }, + { "120", 769250 }, + { "121", 775250 }, + { "122", 781250 }, + { "123", 787250 }, + { "124", 793250 }, + { "125", 799250 }, + + { "T7", 8250 }, + { "T8", 14250 }, + { "T9", 20250 }, + { "T10", 26250 }, + { "T11", 32250 }, + { "T12", 38250 }, + { "T13", 44250 }, + { "T14", 50250 } +}; + +/* US HRC */ +static const struct v4l2_channel_list ntsc_hrc[] = { + { "1", 72000 }, + + { "2", 54000 }, + { "3", 60000 }, + { "4", 66000 }, + + { "5", 78000 }, + { "6", 84000 }, + + { "7", 174000 }, + { "8", 180000 }, + { "9", 186000 }, + { "10", 192000 }, + { "11", 198000 }, + { "12", 204000 }, + { "13", 210000 }, + { "14", 120000 }, + { "15", 126000 }, + { "16", 132000 }, + { "17", 138000 }, + { "18", 144000 }, + { "19", 150000 }, + { "20", 156000 }, + { "21", 162000 }, + { "22", 168000 }, + { "23", 216000 }, + { "24", 222000 }, + { "25", 228000 }, + { "26", 234000 }, + { "27", 240000 }, + { "28", 246000 }, + { "29", 252000 }, + { "30", 258000 }, + { "31", 264000 }, + { "32", 270000 }, + { "33", 276000 }, + { "34", 282000 }, + { "35", 288000 }, + { "36", 294000 }, + { "37", 300000 }, + { "38", 306000 }, + { "39", 312000 }, + { "40", 318000 }, + { "41", 324000 }, + { "42", 330000 }, + { "43", 336000 }, + { "44", 342000 }, + { "45", 348000 }, + { "46", 354000 }, + { "47", 360000 }, + { "48", 366000 }, + { "49", 372000 }, + { "50", 378000 }, + { "51", 384000 }, + { "52", 390000 }, + { "53", 396000 }, + { "54", 402000 }, + { "55", 408000 }, + { "56", 414000 }, + { "57", 420000 }, + { "58", 426000 }, + { "59", 432000 }, + { "60", 438000 }, + { "61", 444000 }, + { "62", 450000 }, + { "63", 456000 }, + { "64", 462000 }, + { "65", 468000 }, + { "66", 474000 }, + { "67", 480000 }, + { "68", 486000 }, + { "69", 492000 }, + { "70", 498000 }, + { "71", 504000 }, + { "72", 510000 }, + { "73", 516000 }, + { "74", 522000 }, + { "75", 528000 }, + { "76", 534000 }, + { "77", 540000 }, + { "78", 546000 }, + { "79", 552000 }, + { "80", 558000 }, + { "81", 564000 }, + { "82", 570000 }, + { "83", 576000 }, + { "84", 582000 }, + { "85", 588000 }, + { "86", 594000 }, + { "87", 600000 }, + { "88", 606000 }, + { "89", 612000 }, + { "90", 618000 }, + { "91", 624000 }, + { "92", 630000 }, + { "93", 636000 }, + { "94", 642000 }, + + { "95", 90000 }, + { "96", 96000 }, + { "97", 102000 }, + { "98", 108000 }, + { "99", 114000 }, + + { "100", 648000 }, + { "101", 654000 }, + { "102", 660000 }, + { "103", 666000 }, + { "104", 672000 }, + { "105", 678000 }, + { "106", 684000 }, + { "107", 690000 }, + { "108", 696000 }, + { "109", 702000 }, + { "110", 708000 }, + { "111", 714000 }, + { "112", 720000 }, + { "113", 726000 }, + { "114", 732000 }, + { "115", 738000 }, + { "116", 744000 }, + { "117", 750000 }, + { "118", 756000 }, + { "119", 762000 }, + { "120", 768000 }, + { "121", 774000 }, + { "122", 780000 }, + { "123", 786000 }, + { "124", 792000 }, + { "125", 798000 }, + + { "T7", 7000 }, + { "T8", 13000 }, + { "T9", 19000 }, + { "T10", 25000 }, + { "T11", 31000 }, + { "T12", 37000 }, + { "T13", 43000 }, + { "T14", 49000 }, +}; + +/* US IRC */ +static const struct v4l2_channel_list ntsc_irc[] = { + { "1", 73250 }, + { "2", 55250 }, + { "3", 61250 }, + { "4", 67250 }, + { "5", 79250 }, + { "6", 85250 }, + { "7", 175250 }, + { "8", 181250 }, + { "9", 187250 }, + { "10", 193250 }, + { "11", 199250 }, + { "12", 205250 }, + { "13", 211250 }, + + { "14", 121150 }, + { "15", 127150 }, + { "16", 133150 }, + { "17", 139150 }, + { "18", 145150 }, + { "19", 151150 }, + { "20", 157150 }, + { "21", 163150 }, + { "22", 169150 }, + + { "23", 217250 }, + { "24", 223250 }, + { "25", 229250 }, + { "26", 235250 }, + { "27", 241250 }, + { "28", 247250 }, + { "29", 253250 }, + { "30", 259250 }, + { "31", 265250 }, + { "32", 271250 }, + { "33", 277250 }, + { "34", 283250 }, + { "35", 289250 }, + { "36", 295250 }, + { "37", 301250 }, + { "38", 307250 }, + { "39", 313250 }, + { "40", 319250 }, + { "41", 325250 }, + { "42", 331250 }, + { "43", 337250 }, + { "44", 343250 }, + { "45", 349250 }, + { "46", 355250 }, + { "47", 361250 }, + { "48", 367250 }, + { "49", 373250 }, + { "50", 379250 }, + { "51", 385250 }, + { "52", 391250 }, + { "53", 397250 }, + { "54", 403250 }, + { "55", 409250 }, + { "56", 415250 }, + { "57", 421250 }, + { "58", 427250 }, + { "59", 433250 }, + { "60", 439250 }, + { "61", 445250 }, + { "62", 451250 }, + { "63", 457250 }, + { "64", 463250 }, + { "65", 469250 }, + { "66", 475250 }, + { "67", 481250 }, + { "68", 487250 }, + { "69", 493250 }, + { "70", 499250 }, + { "71", 505250 }, + { "72", 511250 }, + { "73", 517250 }, + { "74", 523250 }, + { "75", 529250 }, + { "76", 535250 }, + { "77", 541250 }, + { "78", 547250 }, + { "79", 553250 }, + { "80", 559250 }, + { "81", 565250 }, + { "82", 571250 }, + { "83", 577250 }, + { "84", 583250 }, + { "85", 589250 }, + { "86", 595250 }, + { "87", 601250 }, + { "88", 607250 }, + { "89", 613250 }, + { "90", 619250 }, + { "91", 625250 }, + { "92", 631250 }, + { "93", 637250 }, + { "94", 643250 }, + + { "95", 91250 }, + { "96", 97250 }, + { "97", 103250 }, + { "98", 109250 }, + { "99", 115250 }, + { "100", 649250 }, + { "101", 655250 }, + { "102", 661250 }, + { "103", 667250 }, + { "104", 673250 }, + { "105", 679250 }, + { "106", 685250 }, + { "107", 691250 }, + { "108", 697250 }, + { "109", 703250 }, + { "110", 709250 }, + { "111", 715250 }, + { "112", 721250 }, + { "113", 727250 }, + { "114", 733250 }, + { "115", 739250 }, + { "116", 745250 }, + { "117", 751250 }, + { "118", 757250 }, + { "119", 763250 }, + { "120", 769250 }, + { "121", 775250 }, + { "122", 781250 }, + { "123", 787250 }, + { "124", 793250 }, + { "125", 799250 }, + + { "T7", 8250 }, + { "T8", 14250 }, + { "T9", 20250 }, + { "T10", 26250 }, + { "T11", 32250 }, + { "T12", 38250 }, + { "T13", 44250 }, + { "T14", 50250 } +}; + + +/* --------------------------------------------------------------------- */ + +/* JP broadcast */ +static const struct v4l2_channel_list ntsc_bcast_jp[] = { + { "1", 91250 }, + { "2", 97250 }, + { "3", 103250 }, + { "4", 171250 }, + { "5", 177250 }, + { "6", 183250 }, + { "7", 189250 }, + { "8", 193250 }, + { "9", 199250 }, + { "10", 205250 }, + { "11", 211250 }, + { "12", 217250 }, + + { "13", 471250 }, + { "14", 477250 }, + { "15", 483250 }, + { "16", 489250 }, + { "17", 495250 }, + { "18", 501250 }, + { "19", 507250 }, + { "20", 513250 }, + { "21", 519250 }, + { "22", 525250 }, + { "23", 531250 }, + { "24", 537250 }, + { "25", 543250 }, + { "26", 549250 }, + { "27", 555250 }, + { "28", 561250 }, + { "29", 567250 }, + { "30", 573250 }, + { "31", 579250 }, + { "32", 585250 }, + { "33", 591250 }, + { "34", 597250 }, + { "35", 603250 }, + { "36", 609250 }, + { "37", 615250 }, + { "38", 621250 }, + { "39", 627250 }, + { "40", 633250 }, + { "41", 639250 }, + { "42", 645250 }, + { "43", 651250 }, + { "44", 657250 }, + + { "45", 663250 }, + { "46", 669250 }, + { "47", 675250 }, + { "48", 681250 }, + { "49", 687250 }, + { "50", 693250 }, + { "51", 699250 }, + { "52", 705250 }, + { "53", 711250 }, + { "54", 717250 }, + { "55", 723250 }, + { "56", 729250 }, + { "57", 735250 }, + { "58", 741250 }, + { "59", 747250 }, + { "60", 753250 }, + { "61", 759250 }, + { "62", 765250 }, +}; + +/* JP cable */ +static const struct v4l2_channel_list ntsc_cable_jp[] = { + { "13", 109250 }, + { "14", 115250 }, + { "15", 121250 }, + { "16", 127250 }, + { "17", 133250 }, + { "18", 139250 }, + { "19", 145250 }, + { "20", 151250 }, + + { "21", 157250 }, + { "22", 165250 }, + { "23", 223250 }, + { "24", 231250 }, + { "25", 237250 }, + { "26", 243250 }, + { "27", 249250 }, + { "28", 253250 }, + { "29", 259250 }, + { "30", 265250 }, + { "31", 271250 }, + { "32", 277250 }, + { "33", 283250 }, + { "34", 289250 }, + { "35", 295250 }, + { "36", 301250 }, + { "37", 307250 }, + { "38", 313250 }, + { "39", 319250 }, + { "40", 325250 }, + { "41", 331250 }, + { "42", 337250 }, + { "43", 343250 }, + { "44", 349250 }, + { "45", 355250 }, + { "46", 361250 }, + { "47", 367250 }, + { "48", 373250 }, + { "49", 379250 }, + { "50", 385250 }, + { "51", 391250 }, + { "52", 397250 }, + { "53", 403250 }, + { "54", 409250 }, + { "55", 415250 }, + { "56", 421250 }, + { "57", 427250 }, + { "58", 433250 }, + { "59", 439250 }, + { "60", 445250 }, + { "61", 451250 }, + { "62", 457250 }, + { "63", 463250 }, +}; + +/* --------------------------------------------------------------------- */ + +/* australia */ +static const struct v4l2_channel_list pal_australia[] = { + { "0", 46250 }, + { "1", 57250 }, + { "2", 64250 }, + { "3", 86250 }, + { "4", 95250 }, + { "5", 102250 }, + { "5A", 138250 }, + { "6", 175250 }, + { "7", 182250 }, + { "8", 189250 }, + { "9", 196250 }, + { "10", 209250 }, + { "11", 216250 }, + { "28", 527250 }, + { "29", 534250 }, + { "30", 541250 }, + { "31", 548250 }, + { "32", 555250 }, + { "33", 562250 }, + { "34", 569250 }, + { "35", 576250 }, + { "36", 591250 }, + { "39", 604250 }, + { "40", 611250 }, + { "41", 618250 }, + { "42", 625250 }, + { "43", 632250 }, + { "44", 639250 }, + { "45", 646250 }, + { "46", 653250 }, + { "47", 660250 }, + { "48", 667250 }, + { "49", 674250 }, + { "50", 681250 }, + { "51", 688250 }, + { "52", 695250 }, + { "53", 702250 }, + { "54", 709250 }, + { "55", 716250 }, + { "56", 723250 }, + { "57", 730250 }, + { "58", 737250 }, + { "59", 744250 }, + { "60", 751250 }, + { "61", 758250 }, + { "62", 765250 }, + { "63", 772250 }, + { "64", 779250 }, + { "65", 786250 }, + { "66", 793250 }, + { "67", 800250 }, + { "68", 807250 }, + { "69", 814250 }, +}; + +static const struct v4l2_channel_list pal_australia_optus[] = { + { "1", 138250 }, + { "2", 147250 }, + { "3", 154250 }, + { "4", 161250 }, + { "5", 168250 }, + { "6", 175250 }, + { "7", 182250 }, + { "8", 189250 }, + { "9", 196250 }, + { "10", 209250 }, + { "11", 216250 }, + { "12", 224250 }, + { "13", 231250 }, + { "14", 238250 }, + { "15", 245250 }, + { "16", 252250 }, + { "17", 259250 }, + { "18", 266250 }, + { "19", 273250 }, + { "20", 280250 }, + { "21", 287250 }, + { "22", 294250 }, + { "23", 303250 }, + { "24", 310250 }, + { "25", 317250 }, + { "26", 324250 }, + { "27", 338250 }, + { "28", 345250 }, + { "29", 352250 }, + { "30", 359250 }, + { "31", 366250 }, + { "32", 373250 }, + { "33", 380250 }, + { "34", 387250 }, + { "35", 394250 }, + { "36", 401250 }, + { "37", 408250 }, + { "38", 415250 }, + { "39", 422250 }, + { "40", 429250 }, + { "41", 436250 }, + { "42", 443250 }, + { "43", 450250 }, + { "44", 457250 }, + { "45", 464250 }, + { "46", 471250 }, + { "47", 478250 }, + { "48", 485250 }, + { "49", 492250 }, + { "50", 499250 }, + { "51", 506250 }, + { "52", 513250 }, + { "53", 520250 }, + { "54", 527250 }, + { "55", 534250 }, +}; + + +/* --------------------------------------------------------------------- */ +/* europe */ + +/* CCIR frequencies */ + +#define FREQ_CCIR_I_III \ + { "E2", 48250 }, \ + { "E3", 55250 }, \ + { "E4", 62250 }, \ + \ + { "S01", 69250 }, \ + { "S02", 76250 }, \ + { "S03", 83250 }, \ + \ + { "E5", 175250 }, \ + { "E6", 182250 }, \ + { "E7", 189250 }, \ + { "E8", 196250 }, \ + { "E9", 203250 }, \ + { "E10", 210250 }, \ + { "E11", 217250 }, \ + { "E12", 224250 } + +#define FREQ_CCIR_SL_SH \ + { "SE1", 105250 }, \ + { "SE2", 112250 }, \ + { "SE3", 119250 }, \ + { "SE4", 126250 }, \ + { "SE5", 133250 }, \ + { "SE6", 140250 }, \ + { "SE7", 147250 }, \ + { "SE8", 154250 }, \ + { "SE9", 161250 }, \ + { "SE10", 168250 }, \ + \ + { "SE11", 231250 }, \ + { "SE12", 238250 }, \ + { "SE13", 245250 }, \ + { "SE14", 252250 }, \ + { "SE15", 259250 }, \ + { "SE16", 266250 }, \ + { "SE17", 273250 }, \ + { "SE18", 280250 }, \ + { "SE19", 287250 }, \ + { "SE20", 294250 } + +#define FREQ_CCIR_H \ + { "S21", 303250 }, \ + { "S22", 311250 }, \ + { "S23", 319250 }, \ + { "S24", 327250 }, \ + { "S25", 335250 }, \ + { "S26", 343250 }, \ + { "S27", 351250 }, \ + { "S28", 359250 }, \ + { "S29", 367250 }, \ + { "S30", 375250 }, \ + { "S31", 383250 }, \ + { "S32", 391250 }, \ + { "S33", 399250 }, \ + { "S34", 407250 }, \ + { "S35", 415250 }, \ + { "S36", 423250 }, \ + { "S37", 431250 }, \ + { "S38", 439250 }, \ + { "S39", 447250 }, \ + { "S40", 455250 }, \ + { "S41", 463250 } + +/* OIRT frequencies */ + +#define FREQ_OIRT_I_III \ + { "R1", 49750 }, \ + { "R2", 59250 }, \ + \ + { "R3", 77250 }, \ + { "R4", 85250 }, \ + { "R5", 93250 }, \ + \ + { "R6", 175250 }, \ + { "R7", 183250 }, \ + { "R8", 191250 }, \ + { "R9", 199250 }, \ + { "R10", 207250 }, \ + { "R11", 215250 }, \ + { "R12", 223250 } + +#define FREQ_OIRT_SL_SH \ + { "SR1", 111250 }, \ + { "SR2", 119250 }, \ + { "SR3", 127250 }, \ + { "SR4", 135250 }, \ + { "SR5", 143250 }, \ + { "SR6", 151250 }, \ + { "SR7", 159250 }, \ + { "SR8", 167250 }, \ + \ + { "SR11", 231250 }, \ + { "SR12", 239250 }, \ + { "SR13", 247250 }, \ + { "SR14", 255250 }, \ + { "SR15", 263250 }, \ + { "SR16", 271250 }, \ + { "SR17", 279250 }, \ + { "SR18", 287250 }, \ + { "SR19", 295250 } + +#define FREQ_UHF \ + { "21", 471250 }, \ + { "22", 479250 }, \ + { "23", 487250 }, \ + { "24", 495250 }, \ + { "25", 503250 }, \ + { "26", 511250 }, \ + { "27", 519250 }, \ + { "28", 527250 }, \ + { "29", 535250 }, \ + { "30", 543250 }, \ + { "31", 551250 }, \ + { "32", 559250 }, \ + { "33", 567250 }, \ + { "34", 575250 }, \ + { "35", 583250 }, \ + { "36", 591250 }, \ + { "37", 599250 }, \ + { "38", 607250 }, \ + { "39", 615250 }, \ + { "40", 623250 }, \ + { "41", 631250 }, \ + { "42", 639250 }, \ + { "43", 647250 }, \ + { "44", 655250 }, \ + { "45", 663250 }, \ + { "46", 671250 }, \ + { "47", 679250 }, \ + { "48", 687250 }, \ + { "49", 695250 }, \ + { "50", 703250 }, \ + { "51", 711250 }, \ + { "52", 719250 }, \ + { "53", 727250 }, \ + { "54", 735250 }, \ + { "55", 743250 }, \ + { "56", 751250 }, \ + { "57", 759250 }, \ + { "58", 767250 }, \ + { "59", 775250 }, \ + { "60", 783250 }, \ + { "61", 791250 }, \ + { "62", 799250 }, \ + { "63", 807250 }, \ + { "64", 815250 }, \ + { "65", 823250 }, \ + { "66", 831250 }, \ + { "67", 839250 }, \ + { "68", 847250 }, \ + { "69", 855250 } + +static const struct v4l2_channel_list europe_west[] = { + FREQ_CCIR_I_III, + FREQ_CCIR_SL_SH, + FREQ_CCIR_H, + FREQ_UHF +}; + +static const struct v4l2_channel_list europe_east[] = { + FREQ_OIRT_I_III, + FREQ_OIRT_SL_SH, + FREQ_CCIR_I_III, + FREQ_CCIR_SL_SH, + FREQ_CCIR_H, + FREQ_UHF +}; + +static const struct v4l2_channel_list pal_italy[] = { + { "A", 53750 }, + { "B", 62250 }, + { "C", 82250 }, + { "D", 175250 }, + { "E", 183750 }, + { "F", 192250 }, + { "G", 201250 }, + { "H", 210250 }, + { "H1", 217250 }, + { "H2", 224250 }, + FREQ_UHF +}; + +static const struct v4l2_channel_list pal_ireland[] = { + { "A0", 45750 }, + { "A1", 48000 }, + { "A2", 53750 }, + { "A3", 56000 }, + { "A4", 61750 }, + { "A5", 64000 }, + { "A6", 175250 }, + { "A7", 176000 }, + { "A8", 183250 }, + { "A9", 184000 }, + { "A10", 191250 }, + { "A11", 192000 }, + { "A12", 199250 }, + { "A13", 200000 }, + { "A14", 207250 }, + { "A15", 208000 }, + { "A16", 215250 }, + { "A17", 216000 }, + { "A18", 224000 }, + { "A19", 232000 }, + { "A20", 248000 }, + { "A21", 256000 }, + { "A22", 264000 }, + { "A23", 272000 }, + { "A24", 280000 }, + { "A25", 288000 }, + { "A26", 296000 }, + { "A27", 304000 }, + { "A28", 312000 }, + { "A29", 320000 }, + { "A30", 344000 }, + { "A31", 352000 }, + { "A32", 408000 }, + { "A33", 416000 }, + { "A34", 448000 }, + { "A35", 480000 }, + { "A36", 520000 }, + FREQ_UHF, +}; + +static const struct v4l2_channel_list secam_france[] = { + { "K01", 47750 }, + { "K02", 55750 }, + { "K03", 60500 }, + { "K04", 63750 }, + { "K05", 176000 }, + { "K06", 184000 }, + { "K07", 192000 }, + { "K08", 200000 }, + { "K09", 208000 }, + { "K10", 216000 }, + { "KB", 116750 }, + { "KC", 128750 }, + { "KD", 140750 }, + { "KE", 159750 }, + { "KF", 164750 }, + { "KG", 176750 }, + { "KH", 188750 }, + { "KI", 200750 }, + { "KJ", 212750 }, + { "KK", 224750 }, + { "KL", 236750 }, + { "KM", 248750 }, + { "KN", 260750 }, + { "KO", 272750 }, + { "KP", 284750 }, + { "KQ", 296750 }, + { "H01", 303250 }, + { "H02", 311250 }, + { "H03", 319250 }, + { "H04", 327250 }, + { "H05", 335250 }, + { "H06", 343250 }, + { "H07", 351250 }, + { "H08", 359250 }, + { "H09", 367250 }, + { "H10", 375250 }, + { "H11", 383250 }, + { "H12", 391250 }, + { "H13", 399250 }, + { "H14", 407250 }, + { "H15", 415250 }, + { "H16", 423250 }, + { "H17", 431250 }, + { "H18", 439250 }, + { "H19", 447250 }, + FREQ_UHF, +}; + +/* --------------------------------------------------------------------- */ + +static const struct v4l2_channel_list pal_newzealand[] = { + { "1", 45250 }, + { "2", 55250 }, + { "3", 62250 }, + { "4", 175250 }, + { "5", 182250 }, + { "6", 189250 }, + { "7", 196250 }, + { "8", 203250 }, + { "9", 210250 }, + { "10", 217250 }, + { "11", 224250 }, + FREQ_UHF, +}; + +/* --------------------------------------------------------------------- */ + +/* China broadcast */ +static const struct v4l2_channel_list pal_bcast_cn[] = { + { "1", 49750 }, + { "2", 57750 }, + { "3", 65750 }, + { "4", 77250 }, + { "5", 85250 }, + { "6", 112250 }, + { "7", 120250 }, + { "8", 128250 }, + { "9", 136250 }, + { "10", 144250 }, + { "11", 152250 }, + { "12", 160250 }, + { "13", 168250 }, + { "14", 176250 }, + { "15", 184250 }, + { "16", 192250 }, + { "17", 200250 }, + { "18", 208250 }, + { "19", 216250 }, + { "20", 224250 }, + { "21", 232250 }, + { "22", 240250 }, + { "23", 248250 }, + { "24", 256250 }, + { "25", 264250 }, + { "26", 272250 }, + { "27", 280250 }, + { "28", 288250 }, + { "29", 296250 }, + { "30", 304250 }, + { "31", 312250 }, + { "32", 320250 }, + { "33", 328250 }, + { "34", 336250 }, + { "35", 344250 }, + { "36", 352250 }, + { "37", 360250 }, + { "38", 368250 }, + { "39", 376250 }, + { "40", 384250 }, + { "41", 392250 }, + { "42", 400250 }, + { "43", 408250 }, + { "44", 416250 }, + { "45", 424250 }, + { "46", 432250 }, + { "47", 440250 }, + { "48", 448250 }, + { "49", 456250 }, + { "50", 463250 }, + { "51", 471250 }, + { "52", 479250 }, + { "53", 487250 }, + { "54", 495250 }, + { "55", 503250 }, + { "56", 511250 }, + { "57", 519250 }, + { "58", 527250 }, + { "59", 535250 }, + { "60", 543250 }, + { "61", 551250 }, + { "62", 559250 }, + { "63", 607250 }, + { "64", 615250 }, + { "65", 623250 }, + { "66", 631250 }, + { "67", 639250 }, + { "68", 647250 }, + { "69", 655250 }, + { "70", 663250 }, + { "71", 671250 }, + { "72", 679250 }, + { "73", 687250 }, + { "74", 695250 }, + { "75", 703250 }, + { "76", 711250 }, + { "77", 719250 }, + { "78", 727250 }, + { "79", 735250 }, + { "80", 743250 }, + { "81", 751250 }, + { "82", 759250 }, + { "83", 767250 }, + { "84", 775250 }, + { "85", 783250 }, + { "86", 791250 }, + { "87", 799250 }, + { "88", 807250 }, + { "89", 815250 }, + { "90", 823250 }, + { "91", 831250 }, + { "92", 839250 }, + { "93", 847250 }, + { "94", 855250 }, +}; + +/* --------------------------------------------------------------------- */ +/* South Africa Broadcast */ + +static const struct v4l2_channel_list pal_bcast_za[] ={ + { "4", 175250 }, + { "5", 183250 }, + { "6", 191250 }, + { "7", 199250 }, + { "8", 207250 }, + { "9", 215250 }, + { "10", 223250 }, + { "11", 231250 }, + { "12", 239250 }, + { "13", 247250 }, + FREQ_UHF +}; + +/* --------------------------------------------------------------------- */ + +static const struct v4l2_channel_list argentina[] = { + { "001", 56250 }, + { "002", 62250 }, + { "003", 68250 }, + { "004", 78250 }, + { "005", 84250 }, + { "006", 176250 }, + { "007", 182250 }, + { "008", 188250 }, + { "009", 194250 }, + { "010", 200250 }, + { "011", 206250 }, + { "012", 212250 }, + { "013", 122250 }, + { "014", 128250 }, + { "015", 134250 }, + { "016", 140250 }, + { "017", 146250 }, + { "018", 152250 }, + { "019", 158250 }, + { "020", 164250 }, + { "021", 170250 }, + { "022", 218250 }, + { "023", 224250 }, + { "024", 230250 }, + { "025", 236250 }, + { "026", 242250 }, + { "027", 248250 }, + { "028", 254250 }, + { "029", 260250 }, + { "030", 266250 }, + { "031", 272250 }, + { "032", 278250 }, + { "033", 284250 }, + { "034", 290250 }, + { "035", 296250 }, + { "036", 302250 }, + { "037", 308250 }, + { "038", 314250 }, + { "039", 320250 }, + { "040", 326250 }, + { "041", 332250 }, + { "042", 338250 }, + { "043", 344250 }, + { "044", 350250 }, + { "045", 356250 }, + { "046", 362250 }, + { "047", 368250 }, + { "048", 374250 }, + { "049", 380250 }, + { "050", 386250 }, + { "051", 392250 }, + { "052", 398250 }, + { "053", 404250 }, + { "054", 410250 }, + { "055", 416250 }, + { "056", 422250 }, + { "057", 428250 }, + { "058", 434250 }, + { "059", 440250 }, + { "060", 446250 }, + { "061", 452250 }, + { "062", 458250 }, + { "063", 464250 }, + { "064", 470250 }, + { "065", 476250 }, + { "066", 482250 }, + { "067", 488250 }, + { "068", 494250 }, + { "069", 500250 }, + { "070", 506250 }, + { "071", 512250 }, + { "072", 518250 }, + { "073", 524250 }, + { "074", 530250 }, + { "075", 536250 }, + { "076", 542250 }, + { "077", 548250 }, + { "078", 554250 }, + { "079", 560250 }, + { "080", 566250 }, + { "081", 572250 }, + { "082", 578250 }, + { "083", 584250 }, + { "084", 590250 }, + { "085", 596250 }, + { "086", 602250 }, + { "087", 608250 }, + { "088", 614250 }, + { "089", 620250 }, + { "090", 626250 }, + { "091", 632250 }, + { "092", 638250 }, + { "093", 644250 }, +}; + +/* --------------------------------------------------------------------- */ + +#define CHAN_COUNT(x) (sizeof(x)/sizeof(struct v4l2_channel_list)) + +const struct v4l2_channel_lists v4l2_channel_lists[] = { + { "us-bcast", ntsc_bcast, CHAN_COUNT(ntsc_bcast) }, + { "us-cable", ntsc_cable, CHAN_COUNT(ntsc_cable) }, + { "us-cable-hrc", ntsc_hrc, CHAN_COUNT(ntsc_hrc) }, + { "us-cable-irc", ntsc_irc, CHAN_COUNT(ntsc_irc) }, + { "japan-bcast", ntsc_bcast_jp, CHAN_COUNT(ntsc_bcast_jp) }, + { "japan-cable", ntsc_cable_jp, CHAN_COUNT(ntsc_cable_jp) }, + { "europe-west", europe_west, CHAN_COUNT(europe_west) }, + { "europe-east", europe_east, CHAN_COUNT(europe_east) }, + { "italy", pal_italy, CHAN_COUNT(pal_italy) }, + { "newzealand", pal_newzealand, CHAN_COUNT(pal_newzealand) }, + { "australia", pal_australia, CHAN_COUNT(pal_australia) }, + { "ireland", pal_ireland, CHAN_COUNT(pal_ireland) }, + { "france", secam_france, CHAN_COUNT(secam_france) }, + { "china-bcast", pal_bcast_cn, CHAN_COUNT(pal_bcast_cn) }, + { "southafrica", pal_bcast_za, CHAN_COUNT(pal_bcast_za) }, + { "argentina", argentina, CHAN_COUNT(argentina) }, + { "australia-optus", pal_australia_optus, CHAN_COUNT(pal_australia_optus) }, + { NULL, NULL, 0 } /* EOF */ +}; + +/* This list contains omissions and almost certainly incorrect information. + Please provide me (Hans Verkuil, ) with corrections. */ +const struct v4l2_country_std_map v4l2_country_std_map[] = { + { "AE", V4L2_STD_PAL_BG }, /* United Arab Emirates */ + { "AF", V4L2_STD_SECAM_D }, /* Afghanistan */ + { "AG", V4L2_STD_NTSC_M }, /* Antigua */ + { "AL", V4L2_STD_PAL_BG }, /* Albania */ + { "AM", V4L2_STD_SECAM_DK }, /* Armenia */ + { "AN", V4L2_STD_NTSC_M }, /* Netherlands Antilles */ + { "AO", V4L2_STD_PAL_I }, /* Angola */ + { "AR", V4L2_STD_PAL_Nc }, /* Argentina */ + { "AT", V4L2_STD_PAL_BG }, /* Austria */ + { "AU", V4L2_STD_PAL_B }, /* Australia */ + { "AW", V4L2_STD_NTSC_M }, /* Aruba */ + { "AZ", V4L2_STD_SECAM_DK }, /* Azerbaijan */ + { "BA", V4L2_STD_PAL_BG }, /* Bosnia and Herzegovina */ + { "BB", V4L2_STD_NTSC_M }, /* Barbados */ + { "BD", V4L2_STD_PAL_B }, /* Bangladesh */ + { "BE", V4L2_STD_PAL_B | V4L2_STD_PAL_H }, /* Belgium */ + { "BF", V4L2_STD_SECAM_K1 }, /* Burkina Faso */ + { "BG", V4L2_STD_SECAM_DK }, /* Bulgaria */ + { "BH", V4L2_STD_PAL_BG }, /* Bahrain */ + { "BI", V4L2_STD_SECAM_K1 }, /* Burundi */ + { "BJ", V4L2_STD_SECAM_K1 }, /* Benin */ + { "BM", V4L2_STD_NTSC_M }, /* Bermuda */ + { "BN", V4L2_STD_PAL_B }, /* Brunei Darussalam */ + { "BO", V4L2_STD_NTSC_M }, /* Bolivia */ + { "BR", V4L2_STD_PAL_M }, /* Brazil */ + { "BS", V4L2_STD_NTSC_M }, /* Bahamas */ + { "BW", V4L2_STD_PAL_I }, /* Botswana */ + { "BY", V4L2_STD_SECAM_D }, /* Belarus */ + { "BZ", V4L2_STD_NTSC_M }, /* Belize */ + { "CA", V4L2_STD_NTSC_M }, /* Canada */ + { "CD", V4L2_STD_SECAM_K1 }, /* The Democratic Republic of the Congo */ + { "CF", V4L2_STD_SECAM_K1 }, /* Central African Republic */ + { "CG", V4L2_STD_SECAM_K1 }, /* Republic of the Congo */ + { "CH", V4L2_STD_PAL_BG }, /* Switzerland */ + { "CL", V4L2_STD_NTSC_M }, /* Chile */ + { "CM", V4L2_STD_PAL_BG }, /* Cameroon */ + { "CN", V4L2_STD_PAL_D }, /* China */ + { "CO", V4L2_STD_NTSC_M }, /* Colombia */ + { "CR", V4L2_STD_NTSC_M }, /* Costa Rica */ + { "CU", V4L2_STD_NTSC_M }, /* Cuba */ + { "CY", V4L2_STD_PAL_BG }, /* Cyprus */ + { "CZ", V4L2_STD_PAL_D }, /* Czech Republic */ + { "DE", V4L2_STD_PAL_BG }, /* Germany */ + { "DJ", V4L2_STD_SECAM_B }, /* Djibouti */ + { "DK", V4L2_STD_PAL_BG }, /* Denmark */ + { "DO", V4L2_STD_NTSC_M }, /* Dominican Republic */ + { "DZ", V4L2_STD_PAL_BG }, /* Algeria */ + { "EC", V4L2_STD_NTSC_M }, /* Ecuador */ + { "EE", V4L2_STD_SECAM_DK }, /* Estonia */ + { "EG", V4L2_STD_PAL_BG }, /* Egypt */ + { "ES", V4L2_STD_PAL_BG }, /* Spain */ + { "ET", V4L2_STD_PAL_BG }, /* Ethiopia */ + { "FI", V4L2_STD_PAL_BG }, /* Finland */ + { "FR", V4L2_STD_SECAM_L }, /* France */ + { "GA", V4L2_STD_SECAM_K1 }, /* Gabon */ + { "GB", V4L2_STD_PAL_I }, /* United Kingdom */ + { "GE", V4L2_STD_SECAM_DK }, /* Georgia */ + { "GH", V4L2_STD_PAL_B }, /* Ghana */ + { "GI", V4L2_STD_PAL_BG }, /* Gibraltar */ + { "GL", V4L2_STD_PAL_BG }, /* Greenland */ + { "GM", V4L2_STD_PAL_I }, /* Gambia */ + { "GQ", V4L2_STD_PAL_BG }, /* Equatorial Guinea */ + { "GR", V4L2_STD_SECAM_B }, /* Greece */ + { "GR", V4L2_STD_SECAM_G }, /* Greece */ + { "GT", V4L2_STD_NTSC_M }, /* Guatemala */ + { "GU", V4L2_STD_NTSC_M }, /* Guam */ + { "GW", V4L2_STD_PAL_I }, /* Guinea-Bissau */ + { "HK", V4L2_STD_PAL_I }, /* Hong Kong */ + { "HN", V4L2_STD_NTSC_M }, /* Honduras */ + { "HR", V4L2_STD_PAL_BG }, /* Croatia */ + { "HU", V4L2_STD_SECAM_DK }, /* Hungary */ + { "ID", V4L2_STD_PAL_B }, /* Indonesia */ + { "IE", V4L2_STD_PAL_I }, /* Ireland */ + { "IL", V4L2_STD_PAL_BG }, /* Israel */ + { "IN", V4L2_STD_PAL_B }, /* India */ + { "IQ", V4L2_STD_SECAM_B | V4L2_STD_SECAM_G }, /* Iraq */ + { "IR", V4L2_STD_SECAM_B | V4L2_STD_SECAM_G }, /* Iran */ + { "IS", V4L2_STD_PAL_BG }, /* Iceland */ + { "IT", V4L2_STD_PAL_BG }, /* Italy */ + { "JM", V4L2_STD_NTSC_M }, /* Jamaica */ + { "JO", V4L2_STD_PAL_BG }, /* Jordan */ + { "JP", V4L2_STD_NTSC_M_JP }, /* Japan */ + { "KE", V4L2_STD_PAL_BG }, /* Kenya */ + { "KH", V4L2_STD_PAL_BG }, /* Cambodia */ + { "KM", V4L2_STD_SECAM_K1 }, /* Comoros */ + { "KN", V4L2_STD_NTSC_M }, /* Saint Kitts and Nevis */ + { "KP", V4L2_STD_PAL_D }, /* North Korea */ + { "KR", V4L2_STD_NTSC_M_KR }, /* South Korea */ + { "KW", V4L2_STD_PAL_BG }, /* Kuwait */ + { "KZ", V4L2_STD_SECAM_D }, /* Kazakhstan */ + { "KZ", V4L2_STD_SECAM_K }, /* Kazakhstan */ + { "LB", V4L2_STD_SECAM_B }, /* Lebanon */ + { "LK", V4L2_STD_PAL_BG }, /* Sri Lanka */ + { "LR", V4L2_STD_PAL_BG }, /* Liberia */ + { "LS", V4L2_STD_PAL_I }, /* Lesotho */ + { "LT", V4L2_STD_SECAM_DK }, /* Lithuania */ + { "LU", V4L2_STD_PAL_BG }, /* Luxembourg */ + { "LY", V4L2_STD_PAL_BG }, /* Libya */ + { "MA", V4L2_STD_SECAM_B | V4L2_STD_SECAM_G }, /* Morocco */ + { "MC", V4L2_STD_PAL_G }, /* Monaco */ + { "MD", V4L2_STD_SECAM_DK }, /* Moldova */ + { "MG", V4L2_STD_SECAM_K | V4L2_STD_SECAM_K1 }, /* Madagascar */ + { "ML", V4L2_STD_SECAM_B | V4L2_STD_SECAM_G }, /* Mali */ + { "MM", V4L2_STD_NTSC_M }, /* Myanmar */ + { "MN", V4L2_STD_SECAM_D }, /* Mongolia */ + { "MR", V4L2_STD_SECAM_B }, /* Mauritania */ + { "MS", V4L2_STD_NTSC_M }, /* Montserrat */ + { "MT", V4L2_STD_PAL_B }, /* Malta */ + { "MU", V4L2_STD_SECAM_B | V4L2_STD_SECAM_G }, /* Mauritius */ + { "MV", V4L2_STD_PAL_B }, /* Maldives */ + { "MW", V4L2_STD_PAL_I }, /* Malawi */ + { "MX", V4L2_STD_NTSC_M }, /* Mexico */ + { "MY", V4L2_STD_PAL_BG }, /* Malaysia */ + { "MZ", V4L2_STD_PAL_G }, /* Mozambique */ + { "NA", V4L2_STD_PAL_I }, /* Namibia */ + { "NE", V4L2_STD_SECAM_K1 }, /* Niger */ + { "NG", V4L2_STD_PAL_BG }, /* Nigeria */ + { "NI", V4L2_STD_NTSC_M }, /* Nicaragua */ + { "NL", V4L2_STD_PAL_BG }, /* Netherlands */ + { "NO", V4L2_STD_PAL_BG }, /* Norway */ + { "NP", V4L2_STD_PAL_B }, /* Nepal */ + { "NZ", V4L2_STD_PAL_BG }, /* New Zealand */ + { "OM", V4L2_STD_PAL_BG }, /* Oman */ + { "PA", V4L2_STD_NTSC_M }, /* Panama */ + { "PE", V4L2_STD_NTSC_M }, /* Peru */ + { "PG", V4L2_STD_PAL_BG }, /* Papua New Guinea */ + { "PH", V4L2_STD_NTSC_M }, /* Philippines */ + { "PK", V4L2_STD_PAL_BG }, /* Pakistan */ + { "PL", V4L2_STD_SECAM_K }, /* Poland */ + { "PR", V4L2_STD_NTSC_M }, /* Puerto Rico */ + { "PT", V4L2_STD_PAL_BG }, /* Portugal */ + { "PY", V4L2_STD_PAL_N }, /* Paraguay */ + { "QA", V4L2_STD_PAL_BG }, /* Qatar */ + { "RO", V4L2_STD_PAL_DK }, /* Romania */ + { "RU", V4L2_STD_SECAM_DK }, /* Russia */ + { "RW", V4L2_STD_SECAM_K1 }, /* Rwanda */ + { "SA", V4L2_STD_PAL_BG | V4L2_STD_SECAM_B | V4L2_STD_SECAM_G }, /* Saudi Arabia */ + { "SC", V4L2_STD_PAL_B }, /* Seychelles */ + { "SD", V4L2_STD_PAL_BG }, /* Sudan */ + { "SE", V4L2_STD_PAL_BG }, /* Sweden */ + { "SG", V4L2_STD_PAL_BG }, /* Singapore */ + { "SI", V4L2_STD_PAL_BG }, /* Slovenia */ + { "SK", V4L2_STD_SECAM_DK }, /* Slovak Republic */ + { "SL", V4L2_STD_PAL_BG }, /* Sierra Leone */ + { "SN", V4L2_STD_SECAM_K1 }, /* Senegal */ + { "SO", V4L2_STD_PAL_BG }, /* Somalia */ + { "SR", V4L2_STD_NTSC_M }, /* Suriname */ + { "ST", V4L2_STD_PAL_B }, /* Sao Tome and Principe */ + { "SV", V4L2_STD_NTSC_M }, /* El Salvador */ + { "SY", V4L2_STD_PAL_BG }, /* Syria */ + { "SZ", V4L2_STD_PAL_BG }, /* Swaziland */ + { "TD", V4L2_STD_SECAM_K1 }, /* Chad */ + { "TG", V4L2_STD_SECAM_K1 }, /* Togo */ + { "TH", V4L2_STD_PAL_BG }, /* Thailand */ + { "TN", V4L2_STD_PAL_BG }, /* Tunisia */ + { "TR", V4L2_STD_PAL_BG }, /* Turkey */ + { "TT", V4L2_STD_NTSC_M }, /* Trinidad and Tobago */ + { "TW", V4L2_STD_NTSC_M }, /* Taiwan */ + { "TZ", V4L2_STD_PAL_I }, /* Tanzania */ + { "UA", V4L2_STD_SECAM_DK }, /* Ukraine */ + { "UG", V4L2_STD_PAL_B }, /* Uganda */ + { "US", V4L2_STD_NTSC_M }, /* United States */ + { "UY", V4L2_STD_PAL_N }, /* Uruguay */ + { "VC", V4L2_STD_SECAM_K1 }, /* Cape Verde */ + { "VE", V4L2_STD_NTSC_M }, /* Venezuela */ + { "VG", V4L2_STD_NTSC_M }, /* Virgin Islands, British */ + { "VI", V4L2_STD_NTSC_M }, /* Virgin Islands, U.S. */ + { "VN", V4L2_STD_SECAM_DK }, /* Vietnam */ + { "WS", V4L2_STD_NTSC_M }, /* Samoa */ + { "YE", V4L2_STD_PAL_BG }, /* Yemen */ + { "ZA", V4L2_STD_PAL_I }, /* South Africa */ + { "ZM", V4L2_STD_PAL_G }, /* Zambia */ + { "ZW", V4L2_STD_PAL_G }, /* Zimbabwe */ + { NULL, 0 } +}; diff --git a/v4l2-apps/libv4l2util/libv4l2util.h b/v4l2-apps/libv4l2util/libv4l2util.h new file mode 100644 index 000000000..fde7cdc75 --- /dev/null +++ b/v4l2-apps/libv4l2util/libv4l2util.h @@ -0,0 +1,45 @@ +/* Copyright (C) 2006 Hans Verkuil + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _V4L2UTIL_H_ +#define _V4L2UTIL_H_ + +/* --------------------------------------------------------------------- */ + +struct v4l2_channel_list { + const char * const name; /* channel name */ + unsigned freq; /* channel frequency in kHz */ +}; + +struct v4l2_channel_lists { + const char * const name; /* channel list name */ + const struct v4l2_channel_list * const list; + unsigned count; /* number of channels in channel list */ +}; + +extern const struct v4l2_channel_lists v4l2_channel_lists[]; + +/* This list is sorted alphabetically on ISO code. The last item is + denoted by a NULL pointer for the iso_code. */ +struct v4l2_country_std_map { + const char * const iso_code; /* The 2-character upper case ISO-3166 country code */ + v4l2_std_id std; /* The TV standard(s) in use */ +}; + +extern const struct v4l2_country_std_map v4l2_country_std_map[]; + +#endif diff --git a/v4l2-apps/libv4l2util/v4l2_driver.c b/v4l2-apps/libv4l2util/v4l2_driver.c new file mode 100644 index 000000000..94f826968 --- /dev/null +++ b/v4l2-apps/libv4l2util/v4l2_driver.c @@ -0,0 +1,804 @@ +/* + Copyright (C) 2006 Mauro Carvalho Chehab + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "v4l2_driver.h" + +/**************************************************************************** + Auxiliary routines + ****************************************************************************/ +static int xioctl (int fd, int request, void *arg) +{ + int r; + + do r = ioctl (fd, request, arg); + while (-1 == r && EINTR == errno); + + return r; +} + +static void free_list(struct drv_list **list_ptr) +{ + struct drv_list *prev,*cur; + + if (list_ptr==NULL) + return; + + prev=*list_ptr; + if (prev==NULL) + return; + + do { + cur=prev->next; + if (prev->curr) + free (prev->curr); // Free data + free (prev); // Free list + prev=cur; + } while (prev); + + *list_ptr=NULL; +} + +/**************************************************************************** + Auxiliary Arrays to aid debug messages + ****************************************************************************/ +char *v4l2_field_names[] = { + [V4L2_FIELD_ANY] = "any", + [V4L2_FIELD_NONE] = "none", + [V4L2_FIELD_TOP] = "top", + [V4L2_FIELD_BOTTOM] = "bottom", + [V4L2_FIELD_INTERLACED] = "interlaced", + [V4L2_FIELD_SEQ_TB] = "seq-tb", + [V4L2_FIELD_SEQ_BT] = "seq-bt", + [V4L2_FIELD_ALTERNATE] = "alternate", +}; + +char *v4l2_type_names[] = { + [V4L2_BUF_TYPE_VIDEO_CAPTURE] = "video-cap", + [V4L2_BUF_TYPE_VIDEO_OVERLAY] = "video-over", + [V4L2_BUF_TYPE_VIDEO_OUTPUT] = "video-out", + [V4L2_BUF_TYPE_VBI_CAPTURE] = "vbi-cap", + [V4L2_BUF_TYPE_VBI_OUTPUT] = "vbi-out", + [V4L2_BUF_TYPE_SLICED_VBI_CAPTURE] = "sliced-vbi-cap", + [V4L2_BUF_TYPE_SLICED_VBI_OUTPUT] = "slicec-vbi-out", +}; + +static char *v4l2_memory_names[] = { + [V4L2_MEMORY_MMAP] = "mmap", + [V4L2_MEMORY_USERPTR] = "userptr", + [V4L2_MEMORY_OVERLAY] = "overlay", +}; + +#define ARRAY_SIZE(arr) (sizeof(arr)/sizeof(*arr)) +#define prt_names(a,arr) (((a)timecode; + + printf ("%s: %02ld:%02d:%02d.%08ld index=%d, type=%s, " + "bytesused=%d, flags=0x%08x, " + "field=%s, sequence=%d, memory=%s, offset=0x%08x, length=%d\n", + name, (p->timestamp.tv_sec/3600), + (int)(p->timestamp.tv_sec/60)%60, + (int)(p->timestamp.tv_sec%60), + p->timestamp.tv_usec, + p->index, + prt_names(p->type,v4l2_type_names), + p->bytesused,p->flags, + prt_names(p->field,v4l2_field_names), + p->sequence, + prt_names(p->memory,v4l2_memory_names), + p->m.offset, + p->length); + tc=&p->timecode; + printf ("\tTIMECODE: %02d:%02d:%02d type=%d, " + "flags=0x%08x, frames=%d, userbits=0x%08x\n", + tc->hours,tc->minutes,tc->seconds, + tc->type, tc->flags, tc->frames, *(uint32_t *) tc->userbits); +} + +/**************************************************************************** + Open V4L2 devices + ****************************************************************************/ +int v4l2_open (char *device, int debug, struct v4l2_driver *drv) +{ + int ret; + + memset(drv,0,sizeof(*drv)); + + drv->debug=debug; + + if ((drv->fd = open(device, O_RDWR )) < 0) { + return(-errno); + } + + ret=xioctl(drv->fd,VIDIOC_QUERYCAP,(void *) &drv->cap); + if (!ret && drv->debug) { + printf ("driver=%s, card=%s, bus=%s, version=%d.%d.%d, " + "capabilities=%s\n", + drv->cap.driver,drv->cap.card,drv->cap.bus_info, + (drv->cap.version >> 16) & 0xff, + (drv->cap.version >> 8) & 0xff, + drv->cap.version & 0xff, + prt_caps(drv->cap.capabilities)); + + + } + return ret; +} + + +/**************************************************************************** + V4L2 Eumberations + ****************************************************************************/ +int v4l2_enum_stds (struct v4l2_driver *drv) +{ + struct v4l2_standard *p=NULL; + struct drv_list *list; + int ok=0,ret,i; + v4l2_std_id id; + + free_list(&drv->stds); + + list=drv->stds=calloc(1,sizeof(*drv->stds)); + assert (list!=NULL); + + for (i=0; ok==0; i++) { + p=calloc(1,sizeof(*p)); + assert (p); + + p->index=i; + ok=xioctl(drv->fd,VIDIOC_ENUMSTD,p); + if (ok<0) { + ok=-errno; + free(p); + break; + } + if (drv->debug) { + printf ("STANDARD: index=%d, id=0x%08x, name=%s, fps=%.3f, " + "framelines=%d\n", p->index, + (unsigned int)p->id, p->name, + 1.*p->frameperiod.denominator/p->frameperiod.numerator, + p->framelines); + } + if (list->curr) { + list->next=calloc(1,sizeof(*list->next)); + list=list->next; + assert (list!=NULL); + } + list->curr=p; + } + if (i>0 && ok==-EINVAL) + return 0; + + return ok; +} + +int v4l2_enum_input (struct v4l2_driver *drv) +{ + struct v4l2_input *p=NULL; + struct drv_list *list; + int ok=0,ret,i; + v4l2_std_id id; + + free_list(&drv->inputs); + + list=drv->inputs=calloc(1,sizeof(*drv->inputs)); + assert (list!=NULL); + + for (i=0; ok==0; i++) { + p=calloc(1,sizeof(*p)); + assert (p); + p->index=i; + ok=xioctl(drv->fd,VIDIOC_ENUMINPUT,p); + if (ok<0) { + ok=errno; + free(p); + break; + } + if (drv->debug) { + printf ("INPUT: index=%d, name=%s, type=%d, audioset=%d, " + "tuner=%d, std=%08x, status=%d\n", + p->index,p->name,p->type,p->audioset, p->tuner, + (unsigned int)p->std, p->status); + } + if (list->curr) { + list->next=calloc(1,sizeof(*list->next)); + list=list->next; + assert (list!=NULL); + } + list->curr=p; + } + if (i>0 && ok==-EINVAL) + return 0; + return ok; +} + +int v4l2_enum_fmt (struct v4l2_driver *drv, enum v4l2_buf_type type) +{ + struct v4l2_fmtdesc *p=NULL; + struct v4l2_format fmt; + struct drv_list *list; + int ok=0,ret,i; + v4l2_std_id id; + + free_list(&drv->fmt_caps); + + list=drv->fmt_caps=calloc(1,sizeof(*drv->fmt_caps)); + assert (list!=NULL); + + for (i=0; ok==0; i++) { + p=calloc(1,sizeof(*p)); + assert (p!=NULL); + + p->index=i; + p->type =type; + + ok=xioctl(drv->fd,VIDIOC_ENUM_FMT,p); + if (ok<0) { + ok=errno; + free(p); + break; + } + if (drv->debug) { + printf ("FORMAT: index=%d, type=%d, flags=%d, description='%s'\n\t" + "fourcc=%c%c%c%c\n", + p->index, p->type, p->flags,p->description, + p->pixelformat & 0xff, + (p->pixelformat >> 8) & 0xff, + (p->pixelformat >> 16) & 0xff, + (p->pixelformat >> 24) & 0xff + ); + } + if (list->curr) { + list->next=calloc(1,sizeof(*list->next)); + list=list->next; + assert (list!=NULL); + } + list->curr=p; + } + if (i>0 && ok==-EINVAL) + return 0; + return ok; +} + +/**************************************************************************** + Set routines - currently, it also checks results with Get + ****************************************************************************/ +int v4l2_setget_std (struct v4l2_driver *drv, enum v4l2_direction dir, v4l2_std_id *id) +{ + v4l2_std_id s_id=*id; + int ret=0; + char s[256]; + + if (dir & V4L2_SET) { + ret=xioctl(drv->fd,VIDIOC_S_STD,&s_id); + if (ret<0) { + ret=errno; + + sprintf (s,"while trying to set STD to %08x", + (unsigned int) *id); + perror(s); + } + } + + if (dir & V4L2_GET) { + ret=xioctl(drv->fd,VIDIOC_G_STD,&s_id); + if (ret<0) { + ret=errno; + perror ("while trying to get STD id"); + } + } + + if (dir == V4L2_SET_GET) { + if (*id & s_id) { + if (*id != s_id) { + printf ("Warning: Received a std subset (%08x" + " std) while trying to adjust to %08x\n", + (unsigned int) s_id,(unsigned int) *id); + } + } else { + fprintf (stderr,"Error: Received %08x std while trying" + " to adjust to %08x\n", + (unsigned int) s_id,(unsigned int) *id); + } + } + return ret; +} + +int v4l2_setget_input (struct v4l2_driver *drv, enum v4l2_direction dir, struct v4l2_input *input) +{ + int ok=0,ret,i; + unsigned int inp=input->index; + char s[256]; + + if (dir & V4L2_SET) { + ret=xioctl(drv->fd,VIDIOC_S_INPUT,input); + if (ret<0) { + ret=errno; + sprintf (s,"while trying to set INPUT to %d\n", inp); + perror(s); + } + } + + if (dir & V4L2_GET) { + ret=xioctl(drv->fd,VIDIOC_G_INPUT,input); + if (ret<0) { + perror ("while trying to get INPUT id\n"); + } + } + + if (dir & V4L2_SET_GET) { + if (input->index != inp) { + printf ("Input is different than expected (received %i, set %i)\n", + inp, input->index); + } + } + + return ok; +} + +int v4l2_gettryset_fmt_cap (struct v4l2_driver *drv, enum v4l2_direction dir, + struct v4l2_format *fmt,uint32_t width, uint32_t height, + uint32_t pixelformat, enum v4l2_field field) +{ + struct v4l2_pix_format *pix=&(fmt->fmt.pix); + int ret=0; + + fmt->type=V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (dir == V4L2_GET) { + ret=xioctl(drv->fd,VIDIOC_G_FMT,fmt); + if (ret < 0) { + ret=errno; + perror("VIDIOC_G_FMT failed\n"); + } + return ret; + } else if (dir & (~(V4L2_TRY|V4L2_SET)) ) { + perror ("Invalid direction\n"); + return EINVAL; + } + + if (dir & (V4L2_TRY|V4L2_SET)) { + pix->width = width; + pix->height = height; + pix->pixelformat = pixelformat; + pix->field = field; + /* + enum v4l2_colorspace colorspace; + */ + + if (dir & V4L2_TRY) { + ret=xioctl(drv->fd,VIDIOC_TRY_FMT,fmt); + if (ret < 0) { + perror("VIDIOC_TRY_FMT failed\n"); + } + } + + if (dir & V4L2_SET) { + ret=xioctl(drv->fd,VIDIOC_S_FMT,fmt); + if (ret < 0) { + perror("VIDIOC_S_FMT failed\n"); + } + drv->sizeimage=pix->sizeimage; + } + + if (pix->pixelformat != pixelformat) { + fprintf(stderr,"Error: asked for format %d, received %d",pixelformat, + pix->pixelformat); + } + + if (pix->width != width) { + fprintf(stderr,"Error: asked for format %d, received %d\n",width, + pix->width); + } + + if (pix->height != height) { + fprintf(stderr,"Error: asked for format %d, received %d\n",height, + pix->height); + } + + if (pix->bytesperline == 0 ) { + fprintf(stderr,"Error: bytesperline = 0\n"); + } + + if (pix->sizeimage == 0 ) { + fprintf(stderr,"Error: sizeimage = 0\n"); + } + } + + if (drv->debug) + printf( "FMT SET: %dx%d, fourcc=%c%c%c%c, %d bytes/line," + " %d bytes/frame, colorspace=0x%08x\n", + pix->width,pix->height, + pix->pixelformat & 0xff, + (pix->pixelformat >> 8) & 0xff, + (pix->pixelformat >> 16) & 0xff, + (pix->pixelformat >> 24) & 0xff, + pix->bytesperline, + pix->sizeimage, + pix->colorspace); + + return 0; +} + +/**************************************************************************** + Get routines + ****************************************************************************/ +int v4l2_get_parm (struct v4l2_driver *drv) +{ + int ret; + struct v4l2_captureparm *c; + + drv->parm.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if ((ret=xioctl(drv->fd,VIDIOC_G_PARM,&drv->parm))>=0) { + c=&drv->parm.parm.capture; + printf ("PARM: capability=%d, capturemode=%d, %.3f fps " + "ext=%x, readbuf=%d\n", + c->capability, + c->capturemode, + c->timeperframe.denominator*1./c->timeperframe.numerator, + c->extendedmode, c->readbuffers); + } else { + ret=errno; + + perror ("VIDIOC_G_PARM"); + } + + return ret; +} + +/**************************************************************************** + Queue and stream control + ****************************************************************************/ + +int v4l2_free_bufs(struct v4l2_driver *drv) +{ + unsigned int i; + + if (!drv->n_bufs) + return 0; + + /* Requests the driver to free all buffers */ + drv->reqbuf.count = 0; + drv->reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + drv->reqbuf.memory = V4L2_MEMORY_MMAP; + + /* stop capture */ + if (xioctl(drv->fd,VIDIOC_STREAMOFF,&drv->reqbuf.type)<0) + return errno; + + sleep (1); // FIXME: Should check if all buffers are stopped + +/* V4L2 API says REQBUFS with count=0 should be used to release buffer. + However, video-buf.c doesn't implement it. + */ +#if 0 + if (xioctl(drv->fd,VIDIOC_REQBUFS,&drv->reqbuf)<0) { + perror("reqbufs while freeing buffers"); + return errno; + } +#endif + + if (drv->reqbuf.count != 0) { + fprintf(stderr,"REQBUFS returned %d buffers while asking for freeing it!\n", + drv->reqbuf.count); + } + + for (i = 0; i < drv->n_bufs; i++) { + if (drv->bufs[i].length) + munmap(drv->bufs[i].start, drv->bufs[i].length); + if (drv->v4l2_bufs[i]) + free (drv->v4l2_bufs[i]); + } + + free(drv->v4l2_bufs); + free(drv->bufs); + + drv->v4l2_bufs=NULL; + drv->bufs=NULL; + drv->n_bufs=0; + + return 0; +} + +int v4l2_mmap_bufs(struct v4l2_driver *drv, unsigned int num_buffers) +{ + /* Frees previous allocations, if required */ + v4l2_free_bufs(drv); + + if (drv->sizeimage==0) { + fprintf(stderr,"Image size is zero! Can't proceed\n"); + return -1; + } + /* Requests the specified number of buffers */ + drv->reqbuf.count = num_buffers; + drv->reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + drv->reqbuf.memory = V4L2_MEMORY_MMAP; + + if (xioctl(drv->fd,VIDIOC_REQBUFS,&drv->reqbuf)<0) { + perror("reqbufs"); + return errno; + } + + if (drv->debug) + printf ("REQBUFS: count=%d, type=%s, memory=%s\n", + drv->reqbuf.count, + prt_names(drv->reqbuf.type,v4l2_type_names), + prt_names(drv->reqbuf.memory,v4l2_memory_names)); + + /* Allocates the required number of buffers */ + drv->v4l2_bufs=calloc(drv->reqbuf.count, sizeof(*drv->v4l2_bufs)); + assert(drv->v4l2_bufs!=NULL); + drv->bufs=calloc(drv->reqbuf.count, sizeof(*drv->bufs)); + assert(drv->bufs!=NULL); + + for (drv->n_bufs = 0; drv->n_bufs < drv->reqbuf.count; drv->n_bufs++) { + struct v4l2_buffer *p; + struct v4l2_timecode *tc; + + /* Requests kernel buffers to be mmapped */ + p=drv->v4l2_bufs[drv->n_bufs]=calloc(1,sizeof(*p)); + assert (p!=NULL); + p->index = drv->n_bufs; + p->type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + p->memory = V4L2_MEMORY_MMAP; + if (xioctl(drv->fd,VIDIOC_QUERYBUF,p)<0) { + int ret=errno; + perror("querybuf"); + + free (drv->v4l2_bufs[drv->n_bufs]); + + v4l2_free_bufs(drv); + return ret; + } + + if (drv->debug) + prt_buf_info("QUERYBUF",p); + + if (drv->sizeimage != p->length) { + if (drv->sizeimage < p->length) { + fprintf (stderr, "QUERYBUF: ERROR: VIDIOC_S_FMT said buffer should have %d size, but received %d from QUERYBUF!\n", + drv->sizeimage, p->length); + } else { + fprintf (stderr, "QUERYBUF: Expecting %d size, received %d buff length\n", + drv->sizeimage, p->length); + } + } + + drv->bufs[drv->n_bufs].length = p->length; + drv->bufs[drv->n_bufs].start = mmap (NULL, /* start anywhere */ + p->length, + PROT_READ | PROT_WRITE, /* required */ + MAP_SHARED, /* recommended */ + drv->fd, p->m.offset); + + + if (MAP_FAILED == drv->bufs[drv->n_bufs].start) { + perror("mmap"); + + free (drv->v4l2_bufs[drv->n_bufs]); + v4l2_free_bufs(drv); + return errno; + } + } + + return 0; +} + +int v4l2_rcvbuf(struct v4l2_driver *drv, v4l2_recebe_buffer *rec_buf) +{ + int ret; + + struct v4l2_buffer buf; + memset (&buf, 0, sizeof(buf)); + + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + + if (-1 == xioctl (drv->fd, VIDIOC_DQBUF, &buf)) { + switch (errno) { + case EAGAIN: + return 0; + + case EIO: + /* Could ignore EIO, see spec. */ + + /* fall through */ + + default: + perror ("dqbuf"); + return errno; + } + } + prt_buf_info("DQBUF",&buf); + + assert (buf.index < drv->n_bufs); + + ret = rec_buf (&buf,&drv->bufs[buf.index]); + + if (ret) { + v4l2_free_bufs(drv); + return ret; + } + + if (-1 == xioctl (drv->fd, VIDIOC_QBUF, &buf)) { + perror ("qbuf"); + return errno; + } + return 0; +} + + +int v4l2_start_streaming(struct v4l2_driver *drv) +{ + uint32_t i; + struct v4l2_buffer buf; + + if (drv->debug) + printf("Activating %d queues\n", drv->n_bufs); + for (i = 0; i < drv->n_bufs; i++) { + int res; + + memset(&buf, 0, sizeof(buf)); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = i; + + res = xioctl (drv->fd, VIDIOC_QBUF, &buf); + + if (!res) + prt_buf_info("QBUF",&buf); + else { + perror("qbuf"); + return errno; + } + } + + /* Activates stream */ + if (drv->debug) + printf("Enabling streaming\n"); + + if (xioctl(drv->fd,VIDIOC_STREAMON,&drv->reqbuf.type)<0) + return errno; + + return 0; +} + +int v4l2_stop_streaming(struct v4l2_driver *drv) +{ + v4l2_free_bufs(drv); + + return 0; +} + +/**************************************************************************** + Close V4L2, disallocating all structs + ****************************************************************************/ +int v4l2_close (struct v4l2_driver *drv) +{ + v4l2_free_bufs(drv); + + free_list(&drv->stds); + free_list(&drv->inputs); + free_list(&drv->fmt_caps); + + return (close(drv->fd)); +} + +/**************************************************************************** + Get/Set frequency + ****************************************************************************/ + +int v4l2_getset_freq (struct v4l2_driver *drv, enum v4l2_direction dir, + double *freq) +{ + struct v4l2_tuner tun; + struct v4l2_frequency frq; + double d = 62500; + unsigned int counter; + + memset(&tun, 0, sizeof(tun)); + + if (-1 == xioctl (drv->fd, VIDIOC_G_TUNER, &tun)) { + perror ("g_tuner"); + printf("Assuming 62.5 kHz step\n"); + } else { + if (tun.capability & V4L2_TUNER_CAP_LOW) + d=62.5; + } + + if (drv->debug) { + if (tun.capability & V4L2_TUNER_CAP_LOW) + printf("62.5 Hz step\n"); + else + printf("62.5 kHz step\n"); + } + + memset(&frq, 0, sizeof(frq)); + + frq.type = V4L2_TUNER_ANALOG_TV; + + if (dir & V4L2_GET) { + if (-1 == xioctl (drv->fd, VIDIOC_G_FREQUENCY, &frq)) { + perror ("s_frequency"); + return errno; + } + *freq = frq.frequency * d; + if (drv->debug) + printf("board is at freq %4.3f MHz (%d)\n", + *freq/1000000, frq.frequency); + } else { + frq.frequency = (uint32_t)(((*freq)+d/2) / d); + + if (-1 == xioctl (drv->fd, VIDIOC_S_FREQUENCY, &frq)) { + perror ("s_frequency"); + return errno; + } + if (drv->debug) + printf("board set to freq %4.3f MHz (%d)\n", + *freq/1000000, frq.frequency); + + } + return 0; +} diff --git a/v4l2-apps/libv4l2util/v4l2_driver.h b/v4l2-apps/libv4l2util/v4l2_driver.h new file mode 100644 index 000000000..b5d5dd22d --- /dev/null +++ b/v4l2-apps/libv4l2util/v4l2_driver.h @@ -0,0 +1,81 @@ +/* + Copyright (C) 2006 Mauro Carvalho Chehab + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library 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 + Lesser General Public License for more details. + */ + +#include +#include +#include +#include + +struct drv_list { + void *curr; + struct drv_list *next; +}; + +struct v4l2_t_buf { + void *start; + size_t length; +}; + +typedef int v4l2_recebe_buffer (struct v4l2_buffer *v4l2_buf, struct v4l2_t_buf *buf); + +struct v4l2_driver { + int fd; /* Driver descriptor */ + + int debug; + + /* V4L2 structs */ + struct v4l2_capability cap; + struct v4l2_streamparm parm; + + /* Several lists to be used to store enumbered values */ + struct drv_list *stds,*inputs,*fmt_caps; + + /* Stream control */ + struct v4l2_requestbuffers reqbuf; + struct v4l2_buffer **v4l2_bufs; + struct v4l2_t_buf *bufs; + uint32_t sizeimage,n_bufs; + + /* Queue control */ + uint32_t waitq, currq; +}; + +enum v4l2_direction { + V4L2_GET = 1, // Bit 1 + V4L2_SET = 2, // Bit 2 + V4L2_SET_GET = 3, // Bits 1 and 2 - sets then gets and compare + V4L2_TRY = 4, // Bit 3 + V4L2_TRY_SET = 6, // Bits 3 and 2 - try then sets + V4L2_TRY_SET_GET = 7, // Bits 3, 2 and 1- try, sets and gets +}; + +int v4l2_open (char *device, int debug, struct v4l2_driver *drv); +int v4l2_close (struct v4l2_driver *drv); +int v4l2_enum_stds (struct v4l2_driver *drv); +int v4l2_enum_input (struct v4l2_driver *drv); +int v4l2_enum_fmt (struct v4l2_driver *drv,enum v4l2_buf_type type); +int v4l2_get_parm (struct v4l2_driver *drv); +int v4l2_setget_std (struct v4l2_driver *drv, enum v4l2_direction dir, v4l2_std_id *id); +int v4l2_setget_input (struct v4l2_driver *drv, enum v4l2_direction dir, struct v4l2_input *input); +int v4l2_gettryset_fmt_cap (struct v4l2_driver *drv, enum v4l2_direction dir, + struct v4l2_format *fmt,uint32_t width, uint32_t height, + uint32_t pixelformat, enum v4l2_field field); +int v4l2_mmap_bufs(struct v4l2_driver *drv, unsigned int num_buffers); +int v4l2_free_bufs(struct v4l2_driver *drv); +int v4l2_start_streaming(struct v4l2_driver *drv); +int v4l2_stop_streaming(struct v4l2_driver *drv); +int v4l2_rcvbuf(struct v4l2_driver *drv, v4l2_recebe_buffer *v4l2_rec_buf); +int v4l2_getset_freq (struct v4l2_driver *drv, enum v4l2_direction dir, + double *freq); + diff --git a/v4l2-apps/test/Makefile b/v4l2-apps/test/Makefile index e3879bc5e..554940edd 100644 --- a/v4l2-apps/test/Makefile +++ b/v4l2-apps/test/Makefile @@ -21,10 +21,10 @@ clean:: install: -../lib/libv4l2util.a: ../lib/v4l2_driver.c ../lib/frequencies.c - make -C ../lib libv4l2util.a +../libv4l2util/libv4l2util.a: ../libv4l2util/v4l2_driver.c ../libv4l2util/frequencies.c + make -C ../libv4l2util libv4l2util.a -driver-test: driver-test.o ../lib/libv4l2util.a +driver-test: driver-test.o ../libv4l2util/libv4l2util.a pixfmt-test: pixfmt-test.o $(CC) $(LDFLAGS) $^ $(LOADLIBES) $(LDLIBS) -o $@ -lX11 diff --git a/v4l2-apps/test/driver-test.c b/v4l2-apps/test/driver-test.c index e4c16ed54..1f722e198 100644 --- a/v4l2-apps/test/driver-test.c +++ b/v4l2-apps/test/driver-test.c @@ -14,7 +14,7 @@ GNU General Public License for more details. */ -#include "../lib/v4l2_driver.h" +#include "../libv4l2util/v4l2_driver.h" #include #include #include diff --git a/v4l2-apps/util/Makefile b/v4l2-apps/util/Makefile index 80bffc50d..4bfe22aa1 100644 --- a/v4l2-apps/util/Makefile +++ b/v4l2-apps/util/Makefile @@ -34,13 +34,13 @@ v4l2-dbg: v4l2-dbg.o v4l2-chipids.o v4l2-dbg.o: v4l2-dbg.h v4l2-dbg-bttv.h v4l2-dbg-em28xx.h v4l2-dbg-saa7134.h -v4l2_sysfs_path.o: v4l2_sysfs_path.c ../lib/v4l2_driver.h +v4l2_sysfs_path.o: v4l2_sysfs_path.c ../libv4l2util/v4l2_driver.h -v4l2_sysfs_path: v4l2_sysfs_path.o ../lib/libv4l2util.a +v4l2_sysfs_path: v4l2_sysfs_path.o ../libv4l2util/libv4l2util.a $(CC) $^ -o $@ -lsysfs -../lib/libv4l2util.a: - $(MAKE) -C ../lib libv4l2util.a +../libv4l2util/libv4l2util.a: + $(MAKE) -C ../libv4l2util libv4l2util.a install: mkdir -p $(prefix)/bin diff --git a/v4l2-apps/util/qv4l2/qv4l2.pro b/v4l2-apps/util/qv4l2/qv4l2.pro index 770c2d702..96adb7260 100644 --- a/v4l2-apps/util/qv4l2/qv4l2.pro +++ b/v4l2-apps/util/qv4l2/qv4l2.pro @@ -3,10 +3,10 @@ ###################################################################### TEMPLATE = app -INCLUDEPATH += . ../../include ../../lib +INCLUDEPATH += . ../../include ../../libv4l2util CONFIG += debug # Input HEADERS += qv4l2.h general-tab.h SOURCES += qv4l2.cpp general-tab.cpp ctrl-tab.cpp -LIBS += -lv4l2util -L../../lib +LIBS += -lv4l2util -L../../libv4l2util diff --git a/v4l2-apps/util/v4l2_sysfs_path.c b/v4l2-apps/util/v4l2_sysfs_path.c index 2fe89b6c7..e3f3e63e8 100644 --- a/v4l2-apps/util/v4l2_sysfs_path.c +++ b/v4l2-apps/util/v4l2_sysfs_path.c @@ -16,7 +16,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "../lib/v4l2_driver.h" +#include "../libv4l2util/v4l2_driver.h" #include #include #include -- cgit v1.2.3 From 7b70d5201c08e37df21de0ac5152d7da6b85d4a9 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 13 Feb 2009 13:17:31 +0100 Subject: v4l2-apps: rename v4l2_sysfs_path to v4l2-sysfs-path From: Hans Verkuil All other tools use - instead of the awkward-to-type underscore, so rename v4l2_sysfs_path to be consistent with the others. Please pay attention to existing nameing conventions the next time someone adds a tool. Priority: normal Signed-off-by: Hans Verkuil --- v4l2-apps/util/Makefile | 6 +- v4l2-apps/util/v4l2-sysfs-path.c | 191 +++++++++++++++++++++++++++++++++++++++ v4l2-apps/util/v4l2_sysfs_path.c | 191 --------------------------------------- 3 files changed, 194 insertions(+), 194 deletions(-) create mode 100644 v4l2-apps/util/v4l2-sysfs-path.c delete mode 100644 v4l2-apps/util/v4l2_sysfs_path.c (limited to 'v4l2-apps') diff --git a/v4l2-apps/util/Makefile b/v4l2-apps/util/Makefile index 4bfe22aa1..6f9d1071a 100644 --- a/v4l2-apps/util/Makefile +++ b/v4l2-apps/util/Makefile @@ -7,7 +7,7 @@ endif CPPFLAGS += -I../include -D_GNU_SOURCE LDFLAGS += -lm -binaries = v4l2-ctl v4l2-dbg v4l2-compliance ivtv-ctl cx18-ctl v4l2_sysfs_path +binaries = v4l2-ctl v4l2-dbg v4l2-compliance ivtv-ctl cx18-ctl v4l2-sysfs-path ifeq ($(prefix),) prefix = /usr @@ -34,9 +34,9 @@ v4l2-dbg: v4l2-dbg.o v4l2-chipids.o v4l2-dbg.o: v4l2-dbg.h v4l2-dbg-bttv.h v4l2-dbg-em28xx.h v4l2-dbg-saa7134.h -v4l2_sysfs_path.o: v4l2_sysfs_path.c ../libv4l2util/v4l2_driver.h +v4l2-sysfs-path.o: v4l2-sysfs-path.c ../libv4l2util/v4l2_driver.h -v4l2_sysfs_path: v4l2_sysfs_path.o ../libv4l2util/libv4l2util.a +v4l2-sysfs-path: v4l2-sysfs-path.o ../libv4l2util/libv4l2util.a $(CC) $^ -o $@ -lsysfs ../libv4l2util/libv4l2util.a: diff --git a/v4l2-apps/util/v4l2-sysfs-path.c b/v4l2-apps/util/v4l2-sysfs-path.c new file mode 100644 index 000000000..e3f3e63e8 --- /dev/null +++ b/v4l2-apps/util/v4l2-sysfs-path.c @@ -0,0 +1,191 @@ +/* + Copyright (C) 2009 Mauro Carvalho Chehab + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation version 2 of the License. + + The sysfs logic were adapted from a C++/Boost snippet code sent by + + 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include "../libv4l2util/v4l2_driver.h" +#include +#include +#include +#include +#include +#include + +#define USB_ID "usb-" +#define PCI_ID "PCI:" +#define PCIe_ID "PCIe:" + +char *obtain_bus_sysfs_path(char *bus_info) +{ + struct sysfs_device *pcictl = NULL; + struct sysfs_bus *bus = NULL; + struct sysfs_device *busdev = NULL; + struct dlist *busdevs = NULL; + struct sysfs_device *pdev = NULL; + char *tmp = NULL, *busname, *buspath; + int pci; + + if (!strncmp(bus_info, USB_ID, strlen(USB_ID))) { + bus_info += strlen(USB_ID); + pci = 0; + } else if (!strncmp(bus_info, PCI_ID, strlen(PCI_ID))) { + bus_info += strlen(PCI_ID); + pci = 1; + } else if (!strncmp(bus_info, PCIe_ID, strlen(PCIe_ID))) { + bus_info += strlen(PCIe_ID); + pci = 1; + } else + return NULL; + + busname = strtok(bus_info, "-"); + if (!busname) + return NULL; + + buspath = strtok(NULL, "-"); + if (!buspath && !pci) + return NULL; + + /* open bus host controller */ + pcictl = sysfs_open_device("pci", busname); + if (!pcictl) + goto err; + + /* We have all we need for PCI devices */ + if (pci) { + char *name; + + asprintf(&name, "%s", pcictl->path); + return name; + } + + /* find matching usb bus */ + bus = sysfs_open_bus("usb"); + if (!bus) + goto err; + + busdevs = sysfs_get_bus_devices(bus); + if (!busdevs) + goto err; + + dlist_for_each_data(busdevs, busdev, struct sysfs_device) { + /* compare pathes of bus host controller and + parent of enumerated bus devices */ + + pdev = sysfs_get_device_parent(busdev); + if (!pdev) + continue; + + if (!strcmp(pcictl->path, pdev->path)) + break; + } + + if (!pdev) + goto err; + + sysfs_close_device(pcictl); + pcictl = NULL; + + /* assemble bus device path */ + if (busdev) { + struct sysfs_attribute *busnumattr; + unsigned int busnum; + char *name; + + busnumattr = sysfs_get_device_attr(busdev, "busnum"); + if (!busnumattr) + goto err; + + tmp = malloc(busnumattr->len + 1); + strncpy(tmp, busnumattr->value, busnumattr->len); + tmp[busnumattr->len] = '\0'; + + if (sscanf(tmp, "%u", &busnum) != 1) + goto err; + + asprintf(&name, "%s/%d-%s", busdev->path, + busnum, buspath); + + free(tmp); + sysfs_close_bus(bus); + + return name; + } + +err: + if (tmp) + free(tmp); + if (bus) + sysfs_close_bus(bus); + if (pcictl) + sysfs_close_device(pcictl); + + return NULL; +} + +void get_sysfs(char *fname) +{ + struct v4l2_driver drv; + char *path; + if (v4l2_open(fname, 0, &drv) < 0) { + perror(fname); + return; + } + + printf("device = %s\n", fname); + printf("bus info = %s\n", drv.cap.bus_info); + path = obtain_bus_sysfs_path((char *)drv.cap.bus_info); + if (path) { + printf("sysfs path = %s\n\n", path); + free(path); + } + + v4l2_close(&drv); +} + +void read_dir(char *dirname) +{ + DIR *dir; + struct dirent *entry; + const char *vid = "video"; + const char *rad = "radio"; + char *p, name[512]; + + dir = opendir(dirname); + if (!dir) + return; + + strcpy(name, dirname); + strcat(name, "/"); + p = name + strlen(name); + + entry = readdir(dir); + while (entry) { + if (!strncmp(entry->d_name, vid, strlen(vid)) || + !strncmp(entry->d_name, rad, strlen(rad))) { + strcpy(p, entry->d_name); + + get_sysfs(name); + } + entry = readdir(dir); + } + closedir(dir); +} + +int main(void) +{ + read_dir("/dev"); + return 0; +} diff --git a/v4l2-apps/util/v4l2_sysfs_path.c b/v4l2-apps/util/v4l2_sysfs_path.c deleted file mode 100644 index e3f3e63e8..000000000 --- a/v4l2-apps/util/v4l2_sysfs_path.c +++ /dev/null @@ -1,191 +0,0 @@ -/* - Copyright (C) 2009 Mauro Carvalho Chehab - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation version 2 of the License. - - The sysfs logic were adapted from a C++/Boost snippet code sent by - - 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, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include "../libv4l2util/v4l2_driver.h" -#include -#include -#include -#include -#include -#include - -#define USB_ID "usb-" -#define PCI_ID "PCI:" -#define PCIe_ID "PCIe:" - -char *obtain_bus_sysfs_path(char *bus_info) -{ - struct sysfs_device *pcictl = NULL; - struct sysfs_bus *bus = NULL; - struct sysfs_device *busdev = NULL; - struct dlist *busdevs = NULL; - struct sysfs_device *pdev = NULL; - char *tmp = NULL, *busname, *buspath; - int pci; - - if (!strncmp(bus_info, USB_ID, strlen(USB_ID))) { - bus_info += strlen(USB_ID); - pci = 0; - } else if (!strncmp(bus_info, PCI_ID, strlen(PCI_ID))) { - bus_info += strlen(PCI_ID); - pci = 1; - } else if (!strncmp(bus_info, PCIe_ID, strlen(PCIe_ID))) { - bus_info += strlen(PCIe_ID); - pci = 1; - } else - return NULL; - - busname = strtok(bus_info, "-"); - if (!busname) - return NULL; - - buspath = strtok(NULL, "-"); - if (!buspath && !pci) - return NULL; - - /* open bus host controller */ - pcictl = sysfs_open_device("pci", busname); - if (!pcictl) - goto err; - - /* We have all we need for PCI devices */ - if (pci) { - char *name; - - asprintf(&name, "%s", pcictl->path); - return name; - } - - /* find matching usb bus */ - bus = sysfs_open_bus("usb"); - if (!bus) - goto err; - - busdevs = sysfs_get_bus_devices(bus); - if (!busdevs) - goto err; - - dlist_for_each_data(busdevs, busdev, struct sysfs_device) { - /* compare pathes of bus host controller and - parent of enumerated bus devices */ - - pdev = sysfs_get_device_parent(busdev); - if (!pdev) - continue; - - if (!strcmp(pcictl->path, pdev->path)) - break; - } - - if (!pdev) - goto err; - - sysfs_close_device(pcictl); - pcictl = NULL; - - /* assemble bus device path */ - if (busdev) { - struct sysfs_attribute *busnumattr; - unsigned int busnum; - char *name; - - busnumattr = sysfs_get_device_attr(busdev, "busnum"); - if (!busnumattr) - goto err; - - tmp = malloc(busnumattr->len + 1); - strncpy(tmp, busnumattr->value, busnumattr->len); - tmp[busnumattr->len] = '\0'; - - if (sscanf(tmp, "%u", &busnum) != 1) - goto err; - - asprintf(&name, "%s/%d-%s", busdev->path, - busnum, buspath); - - free(tmp); - sysfs_close_bus(bus); - - return name; - } - -err: - if (tmp) - free(tmp); - if (bus) - sysfs_close_bus(bus); - if (pcictl) - sysfs_close_device(pcictl); - - return NULL; -} - -void get_sysfs(char *fname) -{ - struct v4l2_driver drv; - char *path; - if (v4l2_open(fname, 0, &drv) < 0) { - perror(fname); - return; - } - - printf("device = %s\n", fname); - printf("bus info = %s\n", drv.cap.bus_info); - path = obtain_bus_sysfs_path((char *)drv.cap.bus_info); - if (path) { - printf("sysfs path = %s\n\n", path); - free(path); - } - - v4l2_close(&drv); -} - -void read_dir(char *dirname) -{ - DIR *dir; - struct dirent *entry; - const char *vid = "video"; - const char *rad = "radio"; - char *p, name[512]; - - dir = opendir(dirname); - if (!dir) - return; - - strcpy(name, dirname); - strcat(name, "/"); - p = name + strlen(name); - - entry = readdir(dir); - while (entry) { - if (!strncmp(entry->d_name, vid, strlen(vid)) || - !strncmp(entry->d_name, rad, strlen(rad))) { - strcpy(p, entry->d_name); - - get_sysfs(name); - } - entry = readdir(dir); - } - closedir(dir); -} - -int main(void) -{ - read_dir("/dev"); - return 0; -} -- cgit v1.2.3 From 31eab17a63b92f738bcaa74a7355a345f9919378 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 13 Feb 2009 13:23:52 +0100 Subject: v4l2-apps: rename capture_example to capture-example From: Hans Verkuil Follow the existing naming conventions. Also did a few small cleanups in this source. Priority: normal Signed-off-by: Hans Verkuil --- v4l2-apps/test/Makefile | 2 +- v4l2-apps/test/capture-example.c | 657 ++++++++++++++++++++++++++++++++++++++ v4l2-apps/test/capture_example.c | 659 --------------------------------------- 3 files changed, 658 insertions(+), 660 deletions(-) create mode 100644 v4l2-apps/test/capture-example.c delete mode 100644 v4l2-apps/test/capture_example.c (limited to 'v4l2-apps') diff --git a/v4l2-apps/test/Makefile b/v4l2-apps/test/Makefile index 554940edd..d118b9210 100644 --- a/v4l2-apps/test/Makefile +++ b/v4l2-apps/test/Makefile @@ -10,7 +10,7 @@ binaries = ioctl-test \ driver-test \ pixfmt-test \ stress-buffer \ - capture_example + capture-example .PHONY: all clean install diff --git a/v4l2-apps/test/capture-example.c b/v4l2-apps/test/capture-example.c new file mode 100644 index 000000000..9d5b0d6ce --- /dev/null +++ b/v4l2-apps/test/capture-example.c @@ -0,0 +1,657 @@ +/* + * V4L2 video capture example + * + * This program can be used and distributed without restrictions. + * + * This program were got from V4L2 API, Draft 0.20 + * available at: http://v4l2spec.bytesex.org/ + */ + +#include +#include +#include +#include + +#include /* getopt_long() */ + +#include /* low-level i/o */ +#include +#include +#include +#include +#include +#include +#include + +#include + +#define CLEAR(x) memset(&(x), 0, sizeof(x)) + +enum io_method { + IO_METHOD_READ, + IO_METHOD_MMAP, + IO_METHOD_USERPTR, +}; + +struct buffer { + void *start; + size_t length; +}; + +static char *dev_name; +static enum io_method io = IO_METHOD_MMAP; +static int fd = -1; +struct buffer *buffers; +static unsigned int n_buffers; +static int out_buf; +static int force_format; +static int frame_count = 70; + +static void errno_exit(const char *s) +{ + fprintf(stderr, "%s error %d, %s\n", s, errno, strerror(errno)); + exit(EXIT_FAILURE); +} + +static int xioctl(int fh, int request, void *arg) +{ + int r; + + do { + r = ioctl(fh, request, arg); + } while (-1 == r && EINTR == errno); + + return r; +} + +static void process_image(const void *p, int size) +{ + if (out_buf) + fwrite(p, size, 1, stdout); + + fflush(stderr); + fprintf(stderr, "."); + fflush(stdout); +} + +static int read_frame(void) +{ + struct v4l2_buffer buf; + unsigned int i; + + switch (io) { + case IO_METHOD_READ: + if (-1 == read(fd, buffers[0].start, buffers[0].length)) { + switch (errno) { + case EAGAIN: + return 0; + + case EIO: + /* Could ignore EIO, see spec. */ + + /* fall through */ + + default: + errno_exit("read"); + } + } + + process_image(buffers[0].start, buffers[0].length); + break; + + case IO_METHOD_MMAP: + CLEAR(buf); + + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + + if (-1 == xioctl(fd, VIDIOC_DQBUF, &buf)) { + switch (errno) { + case EAGAIN: + return 0; + + case EIO: + /* Could ignore EIO, see spec. */ + + /* fall through */ + + default: + errno_exit("VIDIOC_DQBUF"); + } + } + + assert(buf.index < n_buffers); + + process_image(buffers[buf.index].start, buf.bytesused); + + if (-1 == xioctl(fd, VIDIOC_QBUF, &buf)) + errno_exit("VIDIOC_QBUF"); + break; + + case IO_METHOD_USERPTR: + CLEAR(buf); + + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_USERPTR; + + if (-1 == xioctl(fd, VIDIOC_DQBUF, &buf)) { + switch (errno) { + case EAGAIN: + return 0; + + case EIO: + /* Could ignore EIO, see spec. */ + + /* fall through */ + + default: + errno_exit("VIDIOC_DQBUF"); + } + } + + for (i = 0; i < n_buffers; ++i) + if (buf.m.userptr == (unsigned long)buffers[i].start + && buf.length == buffers[i].length) + break; + + assert(i < n_buffers); + + process_image((void *)buf.m.userptr, buf.bytesused); + + if (-1 == xioctl(fd, VIDIOC_QBUF, &buf)) + errno_exit("VIDIOC_QBUF"); + break; + } + + return 1; +} + +static void mainloop(void) +{ + unsigned int count; + + count = frame_count; + + while (count-- > 0) { + for (;;) { + fd_set fds; + struct timeval tv; + int r; + + FD_ZERO(&fds); + FD_SET(fd, &fds); + + /* Timeout. */ + tv.tv_sec = 2; + tv.tv_usec = 0; + + r = select(fd + 1, &fds, NULL, NULL, &tv); + + if (-1 == r) { + if (EINTR == errno) + continue; + errno_exit("select"); + } + + if (0 == r) { + fprintf(stderr, "select timeout\n"); + exit(EXIT_FAILURE); + } + + if (read_frame()) + break; + /* EAGAIN - continue select loop. */ + } + } +} + +static void stop_capturing(void) +{ + enum v4l2_buf_type type; + + switch (io) { + case IO_METHOD_READ: + /* Nothing to do. */ + break; + + case IO_METHOD_MMAP: + case IO_METHOD_USERPTR: + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (-1 == xioctl(fd, VIDIOC_STREAMOFF, &type)) + errno_exit("VIDIOC_STREAMOFF"); + break; + } +} + +static void start_capturing(void) +{ + unsigned int i; + enum v4l2_buf_type type; + + switch (io) { + case IO_METHOD_READ: + /* Nothing to do. */ + break; + + case IO_METHOD_MMAP: + for (i = 0; i < n_buffers; ++i) { + struct v4l2_buffer buf; + + CLEAR(buf); + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = i; + + if (-1 == xioctl(fd, VIDIOC_QBUF, &buf)) + errno_exit("VIDIOC_QBUF"); + } + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (-1 == xioctl(fd, VIDIOC_STREAMON, &type)) + errno_exit("VIDIOC_STREAMON"); + break; + + case IO_METHOD_USERPTR: + for (i = 0; i < n_buffers; ++i) { + 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; + + if (-1 == xioctl(fd, VIDIOC_QBUF, &buf)) + errno_exit("VIDIOC_QBUF"); + } + type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (-1 == xioctl(fd, VIDIOC_STREAMON, &type)) + errno_exit("VIDIOC_STREAMON"); + break; + } +} + +static void uninit_device(void) +{ + unsigned int i; + + switch (io) { + case IO_METHOD_READ: + free(buffers[0].start); + break; + + case IO_METHOD_MMAP: + for (i = 0; i < n_buffers; ++i) + if (-1 == munmap(buffers[i].start, buffers[i].length)) + errno_exit("munmap"); + break; + + case IO_METHOD_USERPTR: + for (i = 0; i < n_buffers; ++i) + free(buffers[i].start); + break; + } + + free(buffers); +} + +static void init_read(unsigned int buffer_size) +{ + buffers = calloc(1, sizeof(*buffers)); + + if (!buffers) { + fprintf(stderr, "Out of memory\n"); + exit(EXIT_FAILURE); + } + + buffers[0].length = buffer_size; + buffers[0].start = malloc(buffer_size); + + if (!buffers[0].start) { + fprintf(stderr, "Out of memory\n"); + exit(EXIT_FAILURE); + } +} + +static void init_mmap(void) +{ + struct v4l2_requestbuffers req; + + CLEAR(req); + + req.count = 4; + req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + req.memory = V4L2_MEMORY_MMAP; + + if (-1 == xioctl(fd, VIDIOC_REQBUFS, &req)) { + if (EINVAL == errno) { + fprintf(stderr, "%s does not support " + "memory mapping\n", dev_name); + exit(EXIT_FAILURE); + } else { + errno_exit("VIDIOC_REQBUFS"); + } + } + + if (req.count < 2) { + fprintf(stderr, "Insufficient buffer memory on %s\n", + dev_name); + exit(EXIT_FAILURE); + } + + buffers = calloc(req.count, sizeof(*buffers)); + + if (!buffers) { + fprintf(stderr, "Out of memory\n"); + exit(EXIT_FAILURE); + } + + for (n_buffers = 0; n_buffers < req.count; ++n_buffers) { + struct v4l2_buffer buf; + + CLEAR(buf); + + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = n_buffers; + + if (-1 == xioctl(fd, VIDIOC_QUERYBUF, &buf)) + errno_exit("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 */, + fd, buf.m.offset); + + if (MAP_FAILED == buffers[n_buffers].start) + errno_exit("mmap"); + } +} + +static void init_userp(unsigned int buffer_size) +{ + struct v4l2_requestbuffers req; + + CLEAR(req); + + req.count = 4; + req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + req.memory = V4L2_MEMORY_USERPTR; + + if (-1 == xioctl(fd, VIDIOC_REQBUFS, &req)) { + if (EINVAL == errno) { + fprintf(stderr, "%s does not support " + "user pointer i/o\n", dev_name); + exit(EXIT_FAILURE); + } else { + errno_exit("VIDIOC_REQBUFS"); + } + } + + buffers = calloc(4, sizeof(*buffers)); + + if (!buffers) { + fprintf(stderr, "Out of memory\n"); + exit(EXIT_FAILURE); + } + + for (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); + } + } +} + +static void init_device(void) +{ + struct v4l2_capability cap; + struct v4l2_cropcap cropcap; + struct v4l2_crop crop; + struct v4l2_format fmt; + unsigned int min; + + if (-1 == xioctl(fd, VIDIOC_QUERYCAP, &cap)) { + if (EINVAL == errno) { + fprintf(stderr, "%s is no V4L2 device\n", + dev_name); + exit(EXIT_FAILURE); + } else { + errno_exit("VIDIOC_QUERYCAP"); + } + } + + if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { + fprintf(stderr, "%s is no video capture device\n", + dev_name); + exit(EXIT_FAILURE); + } + + switch (io) { + case IO_METHOD_READ: + if (!(cap.capabilities & V4L2_CAP_READWRITE)) { + fprintf(stderr, "%s does not support read i/o\n", + dev_name); + 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", + dev_name); + exit(EXIT_FAILURE); + } + break; + } + + + /* Select video input, video standard and tune here. */ + + + CLEAR(cropcap); + + cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + if (0 == xioctl(fd, VIDIOC_CROPCAP, &cropcap)) { + crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + crop.c = cropcap.defrect; /* reset to default */ + + if (-1 == xioctl(fd, VIDIOC_S_CROP, &crop)) { + switch (errno) { + case EINVAL: + /* Cropping not supported. */ + break; + default: + /* Errors ignored. */ + break; + } + } + } else { + /* Errors ignored. */ + } + + + CLEAR(fmt); + + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (force_format) { + fmt.fmt.pix.width = 640; + fmt.fmt.pix.height = 480; + fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; + fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; + + if (-1 == xioctl(fd, VIDIOC_S_FMT, &fmt)) + errno_exit("VIDIOC_S_FMT"); + + /* Note VIDIOC_S_FMT may change width and height. */ + } else { + /* Preserve original settings as set by v4l2-ctl for example */ + if (-1 == xioctl(fd, VIDIOC_G_FMT, &fmt)) + errno_exit("VIDIOC_G_FMT"); + } + + /* Buggy driver paranoia. */ + min = fmt.fmt.pix.width * 2; + if (fmt.fmt.pix.bytesperline < min) + fmt.fmt.pix.bytesperline = min; + min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height; + if (fmt.fmt.pix.sizeimage < min) + fmt.fmt.pix.sizeimage = min; + + switch (io) { + 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; + } +} + +static void close_device(void) +{ + if (-1 == close(fd)) + errno_exit("close"); + + fd = -1; +} + +static void open_device(void) +{ + struct stat st; + + if (-1 == stat(dev_name, &st)) { + fprintf(stderr, "Cannot identify '%s': %d, %s\n", + dev_name, errno, strerror(errno)); + exit(EXIT_FAILURE); + } + + if (!S_ISCHR(st.st_mode)) { + fprintf(stderr, "%s is no device\n", dev_name); + exit(EXIT_FAILURE); + } + + fd = open(dev_name, O_RDWR /* required */ | O_NONBLOCK, 0); + + if (-1 == fd) { + fprintf(stderr, "Cannot open '%s': %d, %s\n", + dev_name, errno, strerror(errno)); + exit(EXIT_FAILURE); + } +} + +static void usage(FILE *fp, int argc, char **argv) +{ + fprintf(fp, + "Usage: %s [options]\n\n" + "Version 1.3\n" + "Options:\n" + "-d | --device name Video device name [%s]\n" + "-h | --help Print this message\n" + "-m | --mmap Use memory mapped buffers [default]\n" + "-r | --read Use read() calls\n" + "-u | --userp Use application allocated buffers\n" + "-o | --output Outputs stream to stdout\n" + "-f | --format Force format to 640x480 YUYV\n" + "-c | --count Number of frames to grab [%i]\n" + "", + argv[0], dev_name, frame_count); +} + +static const char short_options[] = "d:hmruofc:"; + +static const struct option +long_options[] = { + { "device", required_argument, NULL, 'd' }, + { "help", no_argument, NULL, 'h' }, + { "mmap", no_argument, NULL, 'm' }, + { "read", no_argument, NULL, 'r' }, + { "userp", no_argument, NULL, 'u' }, + { "output", no_argument, NULL, 'o' }, + { "format", no_argument, NULL, 'f' }, + { "count", required_argument, NULL, 'c' }, + { 0, 0, 0, 0 } +}; + +int main(int argc, char **argv) +{ + dev_name = "/dev/video0"; + + for (;;) { + int idx; + int c; + + c = getopt_long(argc, argv, + short_options, long_options, &idx); + + if (-1 == c) + break; + + switch (c) { + case 0: /* getopt_long() flag */ + break; + + case 'd': + dev_name = optarg; + break; + + case 'h': + usage(stdout, argc, argv); + exit(EXIT_SUCCESS); + + case 'm': + io = IO_METHOD_MMAP; + break; + + case 'r': + io = IO_METHOD_READ; + break; + + case 'u': + io = IO_METHOD_USERPTR; + break; + + case 'o': + out_buf++; + break; + + case 'f': + force_format++; + break; + + case 'c': + errno = 0; + frame_count = strtol(optarg, NULL, 0); + if (errno) + errno_exit(optarg); + break; + + default: + usage(stderr, argc, argv); + exit(EXIT_FAILURE); + } + } + + open_device(); + init_device(); + start_capturing(); + mainloop(); + stop_capturing(); + uninit_device(); + close_device(); + fprintf(stderr, "\n"); + return 0; +} diff --git a/v4l2-apps/test/capture_example.c b/v4l2-apps/test/capture_example.c deleted file mode 100644 index 0cd129885..000000000 --- a/v4l2-apps/test/capture_example.c +++ /dev/null @@ -1,659 +0,0 @@ -/* - * V4L2 video capture example - * - * This program can be used and distributed without restrictions. - * - * This program were got from V4L2 API, Draft 0.20 - * available at: http://v4l2spec.bytesex.org/ - */ - -#include -#include -#include -#include - -#include /* getopt_long() */ - -#include /* low-level i/o */ -#include -#include -#include -#include -#include -#include -#include - -#include /* for videodev2.h */ - -#include - -#define CLEAR(x) memset(&(x), 0, sizeof(x)) - -typedef enum { - IO_METHOD_READ, - IO_METHOD_MMAP, - IO_METHOD_USERPTR, -} io_method; - -struct buffer { - void *start; - size_t length; -}; - -static char *dev_name; -static io_method io = IO_METHOD_MMAP; -static int fd = -1; -struct buffer *buffers; -static unsigned int n_buffers; -static int out_buf; -static int force_format; -static int frame_count = 70; - -static void errno_exit(const char *s) -{ - fprintf(stderr, "%s error %d, %s\n", s, errno, strerror(errno)); - exit(EXIT_FAILURE); -} - -static int xioctl(int fh, int request, void *arg) -{ - int r; - - do { - r = ioctl(fh, request, arg); - } while (-1 == r && EINTR == errno); - - return r; -} - -static void process_image(const void *p, int size) -{ - if (out_buf) - fwrite(p, size, 1, stdout); - - fflush(stderr); - fprintf(stderr, "."); - fflush(stdout); -} - -static int read_frame(void) -{ - struct v4l2_buffer buf; - unsigned int i; - - switch (io) { - case IO_METHOD_READ: - if (-1 == read(fd, buffers[0].start, buffers[0].length)) { - switch (errno) { - case EAGAIN: - return 0; - - case EIO: - /* Could ignore EIO, see spec. */ - - /* fall through */ - - default: - errno_exit("read"); - } - } - - process_image(buffers[0].start, buffers[0].length); - break; - - case IO_METHOD_MMAP: - CLEAR(buf); - - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; - - if (-1 == xioctl(fd, VIDIOC_DQBUF, &buf)) { - switch (errno) { - case EAGAIN: - return 0; - - case EIO: - /* Could ignore EIO, see spec. */ - - /* fall through */ - - default: - errno_exit("VIDIOC_DQBUF"); - } - } - - assert(buf.index < n_buffers); - - process_image(buffers[buf.index].start, buf.bytesused); - - if (-1 == xioctl(fd, VIDIOC_QBUF, &buf)) - errno_exit("VIDIOC_QBUF"); - break; - - case IO_METHOD_USERPTR: - CLEAR(buf); - - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_USERPTR; - - if (-1 == xioctl(fd, VIDIOC_DQBUF, &buf)) { - switch (errno) { - case EAGAIN: - return 0; - - case EIO: - /* Could ignore EIO, see spec. */ - - /* fall through */ - - default: - errno_exit("VIDIOC_DQBUF"); - } - } - - for (i = 0; i < n_buffers; ++i) - if (buf.m.userptr == (unsigned long)buffers[i].start - && buf.length == buffers[i].length) - break; - - assert(i < n_buffers); - - process_image((void *)buf.m.userptr, buf.bytesused); - - if (-1 == xioctl(fd, VIDIOC_QBUF, &buf)) - errno_exit("VIDIOC_QBUF"); - break; - } - - return 1; -} - -static void mainloop(void) -{ - unsigned int count; - - count = frame_count; - - while (count-- > 0) { - for (;;) { - fd_set fds; - struct timeval tv; - int r; - - FD_ZERO(&fds); - FD_SET(fd, &fds); - - /* Timeout. */ - tv.tv_sec = 2; - tv.tv_usec = 0; - - r = select(fd + 1, &fds, NULL, NULL, &tv); - - if (-1 == r) { - if (EINTR == errno) - continue; - errno_exit("select"); - } - - if (0 == r) { - fprintf(stderr, "select timeout\n"); - exit(EXIT_FAILURE); - } - - if (read_frame()) - break; - /* EAGAIN - continue select loop. */ - } - } -} - -static void stop_capturing(void) -{ - enum v4l2_buf_type type; - - switch (io) { - case IO_METHOD_READ: - /* Nothing to do. */ - break; - - case IO_METHOD_MMAP: - case IO_METHOD_USERPTR: - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (-1 == xioctl(fd, VIDIOC_STREAMOFF, &type)) - errno_exit("VIDIOC_STREAMOFF"); - break; - } -} - -static void start_capturing(void) -{ - unsigned int i; - enum v4l2_buf_type type; - - switch (io) { - case IO_METHOD_READ: - /* Nothing to do. */ - break; - - case IO_METHOD_MMAP: - for (i = 0; i < n_buffers; ++i) { - struct v4l2_buffer buf; - - CLEAR(buf); - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; - buf.index = i; - - if (-1 == xioctl(fd, VIDIOC_QBUF, &buf)) - errno_exit("VIDIOC_QBUF"); - } - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (-1 == xioctl(fd, VIDIOC_STREAMON, &type)) - errno_exit("VIDIOC_STREAMON"); - break; - - case IO_METHOD_USERPTR: - for (i = 0; i < n_buffers; ++i) { - 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; - - if (-1 == xioctl(fd, VIDIOC_QBUF, &buf)) - errno_exit("VIDIOC_QBUF"); - } - type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (-1 == xioctl(fd, VIDIOC_STREAMON, &type)) - errno_exit("VIDIOC_STREAMON"); - break; - } -} - -static void uninit_device(void) -{ - unsigned int i; - - switch (io) { - case IO_METHOD_READ: - free(buffers[0].start); - break; - - case IO_METHOD_MMAP: - for (i = 0; i < n_buffers; ++i) - if (-1 == munmap(buffers[i].start, buffers[i].length)) - errno_exit("munmap"); - break; - - case IO_METHOD_USERPTR: - for (i = 0; i < n_buffers; ++i) - free(buffers[i].start); - break; - } - - free(buffers); -} - -static void init_read(unsigned int buffer_size) -{ - buffers = calloc(1, sizeof(*buffers)); - - if (!buffers) { - fprintf(stderr, "Out of memory\n"); - exit(EXIT_FAILURE); - } - - buffers[0].length = buffer_size; - buffers[0].start = malloc(buffer_size); - - if (!buffers[0].start) { - fprintf(stderr, "Out of memory\n"); - exit(EXIT_FAILURE); - } -} - -static void init_mmap(void) -{ - struct v4l2_requestbuffers req; - - CLEAR(req); - - req.count = 4; - req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - req.memory = V4L2_MEMORY_MMAP; - - if (-1 == xioctl(fd, VIDIOC_REQBUFS, &req)) { - if (EINVAL == errno) { - fprintf(stderr, "%s does not support " - "memory mapping\n", dev_name); - exit(EXIT_FAILURE); - } else { - errno_exit("VIDIOC_REQBUFS"); - } - } - - if (req.count < 2) { - fprintf(stderr, "Insufficient buffer memory on %s\n", - dev_name); - exit(EXIT_FAILURE); - } - - buffers = calloc(req.count, sizeof(*buffers)); - - if (!buffers) { - fprintf(stderr, "Out of memory\n"); - exit(EXIT_FAILURE); - } - - for (n_buffers = 0; n_buffers < req.count; ++n_buffers) { - struct v4l2_buffer buf; - - CLEAR(buf); - - buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - buf.memory = V4L2_MEMORY_MMAP; - buf.index = n_buffers; - - if (-1 == xioctl(fd, VIDIOC_QUERYBUF, &buf)) - errno_exit("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 */, - fd, buf.m.offset); - - if (MAP_FAILED == buffers[n_buffers].start) - errno_exit("mmap"); - } -} - -static void init_userp(unsigned int buffer_size) -{ - struct v4l2_requestbuffers req; - - CLEAR(req); - - req.count = 4; - req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - req.memory = V4L2_MEMORY_USERPTR; - - if (-1 == xioctl(fd, VIDIOC_REQBUFS, &req)) { - if (EINVAL == errno) { - fprintf(stderr, "%s does not support " - "user pointer i/o\n", dev_name); - exit(EXIT_FAILURE); - } else { - errno_exit("VIDIOC_REQBUFS"); - } - } - - buffers = calloc(4, sizeof(*buffers)); - - if (!buffers) { - fprintf(stderr, "Out of memory\n"); - exit(EXIT_FAILURE); - } - - for (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); - } - } -} - -static void init_device(void) -{ - struct v4l2_capability cap; - struct v4l2_cropcap cropcap; - struct v4l2_crop crop; - struct v4l2_format fmt; - unsigned int min; - - if (-1 == xioctl(fd, VIDIOC_QUERYCAP, &cap)) { - if (EINVAL == errno) { - fprintf(stderr, "%s is no V4L2 device\n", - dev_name); - exit(EXIT_FAILURE); - } else { - errno_exit("VIDIOC_QUERYCAP"); - } - } - - if (!(cap.capabilities & V4L2_CAP_VIDEO_CAPTURE)) { - fprintf(stderr, "%s is no video capture device\n", - dev_name); - exit(EXIT_FAILURE); - } - - switch (io) { - case IO_METHOD_READ: - if (!(cap.capabilities & V4L2_CAP_READWRITE)) { - fprintf(stderr, "%s does not support read i/o\n", - dev_name); - 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", - dev_name); - exit(EXIT_FAILURE); - } - break; - } - - - /* Select video input, video standard and tune here. */ - - - CLEAR(cropcap); - - cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - - if (0 == xioctl(fd, VIDIOC_CROPCAP, &cropcap)) { - crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - crop.c = cropcap.defrect; /* reset to default */ - - if (-1 == xioctl(fd, VIDIOC_S_CROP, &crop)) { - switch (errno) { - case EINVAL: - /* Cropping not supported. */ - break; - default: - /* Errors ignored. */ - break; - } - } - } else { - /* Errors ignored. */ - } - - - CLEAR(fmt); - - fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; - if (force_format) { - fmt.fmt.pix.width = 640; - fmt.fmt.pix.height = 480; - fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUYV; - fmt.fmt.pix.field = V4L2_FIELD_INTERLACED; - - if (-1 == xioctl(fd, VIDIOC_S_FMT, &fmt)) - errno_exit("VIDIOC_S_FMT"); - - /* Note VIDIOC_S_FMT may change width and height. */ - } else { - /* Preserve original settings as set by v4l2-ctl for example */ - if (-1 == xioctl(fd, VIDIOC_G_FMT, &fmt)) - errno_exit("VIDIOC_G_FMT"); - } - - /* Buggy driver paranoia. */ - min = fmt.fmt.pix.width * 2; - if (fmt.fmt.pix.bytesperline < min) - fmt.fmt.pix.bytesperline = min; - min = fmt.fmt.pix.bytesperline * fmt.fmt.pix.height; - if (fmt.fmt.pix.sizeimage < min) - fmt.fmt.pix.sizeimage = min; - - switch (io) { - 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; - } -} - -static void close_device(void) -{ - if (-1 == close(fd)) - errno_exit("close"); - - fd = -1; -} - -static void open_device(void) -{ - struct stat st; - - if (-1 == stat(dev_name, &st)) { - fprintf(stderr, "Cannot identify '%s': %d, %s\n", - dev_name, errno, strerror(errno)); - exit(EXIT_FAILURE); - } - - if (!S_ISCHR(st.st_mode)) { - fprintf(stderr, "%s is no device\n", dev_name); - exit(EXIT_FAILURE); - } - - fd = open(dev_name, O_RDWR /* required */ | O_NONBLOCK, 0); - - if (-1 == fd) { - fprintf(stderr, "Cannot open '%s': %d, %s\n", - dev_name, errno, strerror(errno)); - exit(EXIT_FAILURE); - } -} - -static void usage(FILE *fp, int argc, char **argv) -{ - fprintf(fp, - "Usage: %s [options]\n\n" - "Version 1.3\n" - "Options:\n" - "-d | --device name Video device name [%s]\n" - "-h | --help Print this message\n" - "-m | --mmap Use memory mapped buffers [default]\n" - "-r | --read Use read() calls\n" - "-u | --userp Use application allocated buffers\n" - "-o | --output Outputs stream to stdout\n" - "-f | --format Force format to 640x480 YUYV\n" - "-c | --count Number of frames to grab [%i]\n" - "", - argv[0],dev_name,frame_count ); -} - -static const char short_options[] = "d:hmruofc:"; - -static const struct option -long_options[] = { - { "device", required_argument, NULL, 'd' }, - { "help", no_argument, NULL, 'h' }, - { "mmap", no_argument, NULL, 'm' }, - { "read", no_argument, NULL, 'r' }, - { "userp", no_argument, NULL, 'u' }, - { "output", no_argument, NULL, 'o' }, - { "format", no_argument, NULL, 'f' }, - { "count", required_argument, NULL, 'c' }, - { 0, 0, 0, 0 } -}; - -int main(int argc, char **argv) -{ - dev_name = "/dev/video0"; - - for (;;) { - int idx; - int c; - - c = getopt_long(argc, argv, - short_options, long_options, &idx); - - if (-1 == c) - break; - - switch (c) { - case 0: /* getopt_long() flag */ - break; - - case 'd': - dev_name = optarg; - break; - - case 'h': - usage(stdout, argc, argv); - exit(EXIT_SUCCESS); - - case 'm': - io = IO_METHOD_MMAP; - break; - - case 'r': - io = IO_METHOD_READ; - break; - - case 'u': - io = IO_METHOD_USERPTR; - break; - - case 'o': - out_buf++; - break; - - case 'f': - force_format++; - break; - - case 'c': - errno = 0; - frame_count = strtol(optarg, NULL, 0); - if (errno) - errno_exit(optarg); - break; - - default: - usage(stderr, argc, argv); - exit(EXIT_FAILURE); - } - } - - open_device(); - init_device(); - start_capturing(); - mainloop(); - stop_capturing(); - uninit_device(); - close_device(); - fprintf(stderr, "\n"); - return 0; -} -- cgit v1.2.3 From 27bdf53f81e7783e79bcd334e4d3d5d329708694 Mon Sep 17 00:00:00 2001 From: Hans Verkuil Date: Fri, 13 Feb 2009 14:00:19 +0100 Subject: v4l2-apps: rename parse_sniffusb2.pl to parse-sniffusb2.pl From: Hans Verkuil Priority: normal Signed-off-by: Hans Verkuil --- v4l2-apps/test/parse-sniffusb2.pl | 84 +++++++++++++++++++++++++++++++++++++++ v4l2-apps/test/parse_sniffusb2.pl | 84 --------------------------------------- 2 files changed, 84 insertions(+), 84 deletions(-) create mode 100644 v4l2-apps/test/parse-sniffusb2.pl delete mode 100644 v4l2-apps/test/parse_sniffusb2.pl (limited to 'v4l2-apps') diff --git a/v4l2-apps/test/parse-sniffusb2.pl b/v4l2-apps/test/parse-sniffusb2.pl new file mode 100644 index 000000000..34406b0ea --- /dev/null +++ b/v4l2-apps/test/parse-sniffusb2.pl @@ -0,0 +1,84 @@ +#!/usr/bin/perl +# +# Author: Franklin Meng +# Parser for USB snoops captured from SniffUSB 2.0. +# + +use strict; +use warnings; +use Data::Dumper; + +foreach my $curfile (@ARGV) { + parsefile($curfile); + #we can only process 1 file + exit; +} + +sub parsefile { + my $curfile = shift; + my $SetupPacket =''; + my $preS = ''; + my $TransferBuffer =''; + my $preT = ''; + my $Direction =''; + my $preD = ''; + my @tmpsplit; + my $t=0; + my $s=0; + + open(FD, $curfile) || die("Error: $!\n"); + + while() { + chomp; + if($t==1 && /^\s+\d{8}/) { +# print $_ . "\n"; + @tmpsplit = split(/\:\s/,$_); + $TransferBuffer = $TransferBuffer . $tmpsplit[1] . " "; + } elsif($s==1 && /^\s+\d{8}/) { +# print $_ . "\n"; + @tmpsplit = split(/\:\s/,$_); + $SetupPacket = $SetupPacket . $tmpsplit[1] ; + } else { + $t=0; + $s=0; + } + if(/[<>]{3}/){ + #print out last packet if valid + if($SetupPacket) { + if($preT) { + print "$SetupPacket $preD $preT\n"; + + } else { + print "$SetupPacket $Direction $TransferBuffer\n"; + } + } +# print "$SetupPacket $Direction $TransferBuffer\n"; + #clear variables + $preT = $TransferBuffer; + $TransferBuffer = ''; + $preS = $SetupPacket; + $SetupPacket = ''; + $preD = $Direction; + $t = 0; + $s = 0; + # get direction + @tmpsplit = split(/\s+/, $_); + $Direction = $tmpsplit[2]; +# print $_ . "\n"; + } elsif(/TransferBufferMDL/) { + $t = 1 + } elsif(/SetupPacket/) { + $s = 1; + } + } + #print last packet +# print "$SetupPacket $Direction $TransferBuffer\n"; + if($SetupPacket) { + if($preT) { + print "$SetupPacket $preD $preT\n"; + } else { + print "$SetupPacket $Direction $TransferBuffer\n"; + } + } +} + diff --git a/v4l2-apps/test/parse_sniffusb2.pl b/v4l2-apps/test/parse_sniffusb2.pl deleted file mode 100644 index 34406b0ea..000000000 --- a/v4l2-apps/test/parse_sniffusb2.pl +++ /dev/null @@ -1,84 +0,0 @@ -#!/usr/bin/perl -# -# Author: Franklin Meng -# Parser for USB snoops captured from SniffUSB 2.0. -# - -use strict; -use warnings; -use Data::Dumper; - -foreach my $curfile (@ARGV) { - parsefile($curfile); - #we can only process 1 file - exit; -} - -sub parsefile { - my $curfile = shift; - my $SetupPacket =''; - my $preS = ''; - my $TransferBuffer =''; - my $preT = ''; - my $Direction =''; - my $preD = ''; - my @tmpsplit; - my $t=0; - my $s=0; - - open(FD, $curfile) || die("Error: $!\n"); - - while() { - chomp; - if($t==1 && /^\s+\d{8}/) { -# print $_ . "\n"; - @tmpsplit = split(/\:\s/,$_); - $TransferBuffer = $TransferBuffer . $tmpsplit[1] . " "; - } elsif($s==1 && /^\s+\d{8}/) { -# print $_ . "\n"; - @tmpsplit = split(/\:\s/,$_); - $SetupPacket = $SetupPacket . $tmpsplit[1] ; - } else { - $t=0; - $s=0; - } - if(/[<>]{3}/){ - #print out last packet if valid - if($SetupPacket) { - if($preT) { - print "$SetupPacket $preD $preT\n"; - - } else { - print "$SetupPacket $Direction $TransferBuffer\n"; - } - } -# print "$SetupPacket $Direction $TransferBuffer\n"; - #clear variables - $preT = $TransferBuffer; - $TransferBuffer = ''; - $preS = $SetupPacket; - $SetupPacket = ''; - $preD = $Direction; - $t = 0; - $s = 0; - # get direction - @tmpsplit = split(/\s+/, $_); - $Direction = $tmpsplit[2]; -# print $_ . "\n"; - } elsif(/TransferBufferMDL/) { - $t = 1 - } elsif(/SetupPacket/) { - $s = 1; - } - } - #print last packet -# print "$SetupPacket $Direction $TransferBuffer\n"; - if($SetupPacket) { - if($preT) { - print "$SetupPacket $preD $preT\n"; - } else { - print "$SetupPacket $Direction $TransferBuffer\n"; - } - } -} - -- cgit v1.2.3