|
From: libvidcap c. m. <lib...@li...> - 2007-09-06 15:39:55
|
Revision: 4
http://libvidcap.svn.sourceforge.net/libvidcap/?rev=4&view=rev
Author: jpgrayson
Date: 2007-09-06 08:39:40 -0700 (Thu, 06 Sep 2007)
Log Message:
-----------
Add pkg-config file.
Fix installation directory for header files.
No longer use multibyte constants for fourcc values.
Add api function for mapping fourcc values to strings.
Modified Paths:
--------------
trunk/Makefile.am
trunk/configure.ac
trunk/examples/simplegrab.c
trunk/examples/vidcapTester/Grabber.cpp
trunk/include/vidcap/Makefile.am
trunk/include/vidcap/vidcap.h
trunk/src/Makefile.am
trunk/src/conv.h
trunk/src/directshow/DirectShowSource.cpp
trunk/src/sapi_qt.c
trunk/src/vidcap.c
Added Paths:
-----------
trunk/vidcap.pc.in
Modified: trunk/Makefile.am
===================================================================
--- trunk/Makefile.am 2007-09-03 20:34:33 UTC (rev 3)
+++ trunk/Makefile.am 2007-09-06 15:39:40 UTC (rev 4)
@@ -1,4 +1,7 @@
SUBDIRS = include src examples
+pkgconfigdir = $(libdir)/pkgconfig
+pkgconfig_DATA = vidcap.pc
+
dist-hook:
find $(distdir) -name ".svn" -type d -print0 | xargs -0 rm -rf
Modified: trunk/configure.ac
===================================================================
--- trunk/configure.ac 2007-09-03 20:34:33 UTC (rev 3)
+++ trunk/configure.ac 2007-09-06 15:39:40 UTC (rev 4)
@@ -1,11 +1,11 @@
+dnl Copyright (C) 2007 Wimba, Inc.
+
AC_PREREQ(2.59)
dnl package version
-m4_define(VC_MAJOR, [0])
-m4_define(VC_MINOR, [1])
-m4_define(VC_MICRO, [0])
+m4_define(VIDCAP_VERSION, [0.1])
-AC_INIT([libvidcap], VC_MAJOR.VC_MINOR.VC_MICRO, [jpgrayson (at) gmail (dot) com])
+AC_INIT([libvidcap], VIDCAP_VERSION, [jpg...@gm...])
AC_CONFIG_SRCDIR([include/vidcap/vidcap.h])
AC_CONFIG_HEADERS([config.h])
AM_INIT_AUTOMAKE([foreign -Wall])
@@ -36,6 +36,14 @@
ACX_PTHREAD
+AC_CHECK_PROG(have_pkg_config, pkg-config, yes, no)
+
+if test x"$have_pkg_config" = "xno"; then
+ AC_MSG_ERROR(pkg-config is required to install this program)
+fi
+
+PKG_PROG_PKG_CONFIG
+
AC_CHECK_FUNCS(nanosleep gettimeofday snprintf Sleep)
AC_CHECK_HEADER(linux/videodev.h,
@@ -63,11 +71,15 @@
AM_CONDITIONAL(HAVE_QUICKTIME, test "x$have_quicktime" = "xyes")
AM_CONDITIONAL(HAVE_DIRECTSHOW, test "x$have_directshow" = "xyes")
+dnl TODO: how do we make the various quicktime frameworks fit in?
+AC_SUBST(PKG_REQUIRES)
+
AC_CONFIG_FILES([
Makefile
include/Makefile
include/vidcap/Makefile
examples/Makefile
+ vidcap.pc
src/Makefile
])
Modified: trunk/examples/simplegrab.c
===================================================================
--- trunk/examples/simplegrab.c 2007-09-03 20:34:33 UTC (rev 3)
+++ trunk/examples/simplegrab.c 2007-09-06 15:39:40 UTC (rev 4)
@@ -150,13 +150,10 @@
{
const int size = 255;
char * s = malloc(size);
- snprintf(s, size, "%3dx%3d %c%c%c%c %.2f %d/%d",
+ snprintf(s, size, "%3dx%3d %s %.2f %d/%d",
fmt_info->width,
fmt_info->height,
- (fmt_info->fourcc >> 24) & 0xff,
- (fmt_info->fourcc >> 16) & 0xff,
- (fmt_info->fourcc >> 8) & 0xff,
- (fmt_info->fourcc >> 0) & 0xff,
+ vidcap_fourcc_string_get(fmt_info->fourcc),
(float)fmt_info->fps_numerator /
(float)fmt_info->fps_denominator,
fmt_info->fps_numerator,
Modified: trunk/examples/vidcapTester/Grabber.cpp
===================================================================
--- trunk/examples/vidcapTester/Grabber.cpp 2007-09-03 20:34:33 UTC (rev 3)
+++ trunk/examples/vidcapTester/Grabber.cpp 2007-09-06 15:39:40 UTC (rev 4)
@@ -65,14 +65,10 @@
throw std::runtime_error("failed vidcap_format_info_get()");
qDebug() << " bind fmt:"
- << QString("%2x%3 %4%5%6%7 (0x%8) %9 %10/%11")
+ << QString("%2x%3 %4 %5 %6/%7")
.arg(fmt_info.width, 3)
.arg(fmt_info.height, 3)
- .arg(QChar(static_cast<uchar>(fmt_info.fourcc >> 24)))
- .arg(QChar(static_cast<uchar>(fmt_info.fourcc >> 16)))
- .arg(QChar(static_cast<uchar>(fmt_info.fourcc >> 8)))
- .arg(QChar(static_cast<uchar>(fmt_info.fourcc >> 0)))
- .arg(static_cast<uint>(fmt_info.fourcc), 8, 16, QChar('0'))
+ .arg(vidcap_fourcc_string_get(fmt_info.fourcc))
.arg(static_cast<double>(fmt_info.fps_numerator) /
static_cast<double>(fmt_info.fps_denominator),
0, 'f', 2)
Modified: trunk/include/vidcap/Makefile.am
===================================================================
--- trunk/include/vidcap/Makefile.am 2007-09-03 20:34:33 UTC (rev 3)
+++ trunk/include/vidcap/Makefile.am 2007-09-06 15:39:40 UTC (rev 4)
@@ -1,3 +1,5 @@
-pkginclude_HEADERS = \
+pkgincludedir = $(includedir)/vidcap
+
+pkginclude_HEADERS = \
vidcap.h \
converters.h
Modified: trunk/include/vidcap/vidcap.h
===================================================================
--- trunk/include/vidcap/vidcap.h 2007-09-03 20:34:33 UTC (rev 3)
+++ trunk/include/vidcap/vidcap.h 2007-09-06 15:39:40 UTC (rev 4)
@@ -33,9 +33,9 @@
#define VIDCAP_NAME_LENGTH 256
enum vidcap_fourccs {
- VIDCAP_FOURCC_I420 = 'i420',
- VIDCAP_FOURCC_YUY2 = 'yuy2',
- VIDCAP_FOURCC_RGB32 = ' rgb',
+ VIDCAP_FOURCC_I420 = 100,
+ VIDCAP_FOURCC_YUY2 = 101,
+ VIDCAP_FOURCC_RGB32 = 102,
};
typedef void vidcap_state;
@@ -143,6 +143,9 @@
int
vidcap_src_capture_stop(vidcap_src *);
+const char *
+vidcap_fourcc_string_get(int fourcc);
+
#ifdef __cplusplus
}
#endif
Modified: trunk/src/Makefile.am
===================================================================
--- trunk/src/Makefile.am 2007-09-03 20:34:33 UTC (rev 3)
+++ trunk/src/Makefile.am 2007-09-06 15:39:40 UTC (rev 4)
@@ -3,10 +3,8 @@
lib_LTLIBRARIES = libvidcap.la
libvidcap_la_CPPFLAGS = -I$(top_srcdir)/include
-libvidcap_la_CFLAGS = -Wall -Wextra -Wno-unused-parameter -Wno-multichar \
- $(PTHREAD_CFLAGS)
-libvidcap_la_CXXFLAGS = -Wall -Wextra -Wno-unused-parameter -Wno-multichar \
- $(PTHREAD_CFLAGS)
+libvidcap_la_CFLAGS = -Wall -Wextra -Wno-unused-parameter $(PTHREAD_CFLAGS)
+libvidcap_la_CXXFLAGS = -Wall -Wextra -Wno-unused-parameter $(PTHREAD_CFLAGS)
libvidcap_la_LIBADD = $(PTHREAD_LIBS)
Modified: trunk/src/conv.h
===================================================================
--- trunk/src/conv.h 2007-09-03 20:34:33 UTC (rev 3)
+++ trunk/src/conv.h 2007-09-06 15:39:40 UTC (rev 4)
@@ -31,10 +31,10 @@
enum vidcap_fourccs_extra
{
- VIDCAP_FOURCC_RGB24 = ' r24',
- VIDCAP_FOURCC_RGB555 = 'r555',
- VIDCAP_FOURCC_YVU9 = 'yvu9',
- VIDCAP_FOURCC_2VUY = '2vuy',
+ VIDCAP_FOURCC_RGB24 = 200,
+ VIDCAP_FOURCC_RGB555 = 201,
+ VIDCAP_FOURCC_YVU9 = 202,
+ VIDCAP_FOURCC_2VUY = 203,
};
typedef int (*conv_func)(int width, int height,
Modified: trunk/src/directshow/DirectShowSource.cpp
===================================================================
--- trunk/src/directshow/DirectShowSource.cpp 2007-09-03 20:34:33 UTC (rev 3)
+++ trunk/src/directshow/DirectShowSource.cpp 2007-09-06 15:39:40 UTC (rev 4)
@@ -1011,11 +1011,8 @@
data = 0x32595559;
break;
default:
- log_warn("failed to map '%c%c%c%c' to DS media type\n",
- (char)((fourcc >> 24) & 0xff),
- (char)((fourcc >> 16) & 0xff),
- (char)((fourcc >> 8) & 0xff),
- (char)((fourcc >> 0) & 0xff));
+ log_warn("failed to map '%s' to DS media type\n",
+ vidcap_fourcc_string_get(fourcc));
return -1;
}
Modified: trunk/src/sapi_qt.c
===================================================================
--- trunk/src/sapi_qt.c 2007-09-03 20:34:33 UTC (rev 3)
+++ trunk/src/sapi_qt.c 2007-09-06 15:39:40 UTC (rev 4)
@@ -202,19 +202,15 @@
}
if ( qt_src_ctx->frame_count == 1 )
- log_info("capture time: %c%c%c%c %c%c%c%c %c%c%c%c %s\n",
+ log_info("capture time: %c%c%c%c %s %s %s\n",
(char)(pixel_format >> 24),
(char)(pixel_format >> 16),
(char)(pixel_format >> 8),
(char)(pixel_format >> 0),
- (char)(src_ctx->fmt_native.fourcc >> 24),
- (char)(src_ctx->fmt_native.fourcc >> 16),
- (char)(src_ctx->fmt_native.fourcc >> 8),
- (char)(src_ctx->fmt_native.fourcc >> 0),
- (char)(src_ctx->fmt_nominal.fourcc >> 24),
- (char)(src_ctx->fmt_nominal.fourcc >> 16),
- (char)(src_ctx->fmt_nominal.fourcc >> 8),
- (char)(src_ctx->fmt_nominal.fourcc >> 0),
+ vidcap_fourcc_string_get(
+ src_ctx->fmt_native.fourcc),
+ vidcap_fourcc_string_get(
+ src_ctx->fmt_nominal.fourcc),
src_ctx->src_info.identifier);
sapi_src_capture_notify(src_ctx,
@@ -285,27 +281,19 @@
if ( map_fourcc_to_ostype(src_ctx->fmt_native.fourcc, &pixel_format) )
{
- log_error("invalid bound fourcc '%c%c%c%c'\n",
- (char)(src_ctx->fmt_native.fourcc >> 24),
- (char)(src_ctx->fmt_native.fourcc >> 16),
- (char)(src_ctx->fmt_native.fourcc >> 8),
- (char)(src_ctx->fmt_native.fourcc >> 0));
+ log_error("invalid bound fourcc '%s'\n",
+ vidcap_fourcc_string_get(
+ src_ctx->fmt_native.fourcc));
return -1;
}
- log_info("setup decomp: %c%c%c%c %c%c%c%c %c%c%c%c %s\n",
+ log_info("setup decomp: %c%c%c%c %s %s %s\n",
(char)(pixel_format >> 24),
(char)(pixel_format >> 16),
(char)(pixel_format >> 8),
(char)(pixel_format >> 0),
- (char)(src_ctx->fmt_native.fourcc >> 24),
- (char)(src_ctx->fmt_native.fourcc >> 16),
- (char)(src_ctx->fmt_native.fourcc >> 8),
- (char)(src_ctx->fmt_native.fourcc >> 0),
- (char)(src_ctx->fmt_nominal.fourcc >> 24),
- (char)(src_ctx->fmt_nominal.fourcc >> 16),
- (char)(src_ctx->fmt_nominal.fourcc >> 8),
- (char)(src_ctx->fmt_nominal.fourcc >> 0),
+ vidcap_fourcc_string_get(src_ctx->fmt_native.fourcc),
+ vidcap_fourcc_string_get(src_ctx->fmt_nominal.fourcc),
src_ctx->src_info.identifier);
n = CFNumberCreate(0, kCFNumberSInt32Type, &pixel_format);
@@ -403,12 +391,9 @@
if ( map_fourcc_to_ostype(src_ctx->fmt_native.fourcc, &pixel_format) )
{
- log_error("invalid pixel format '%c%c%c%c' (0x%08x)\n",
- (char)(src_ctx->fmt_native.fourcc >> 24),
- (char)(src_ctx->fmt_native.fourcc >> 16),
- (char)(src_ctx->fmt_native.fourcc >> 8),
- (char)(src_ctx->fmt_native.fourcc >> 0),
- src_ctx->fmt_native.fourcc);
+ log_error("invalid pixel format '%s'\n",
+ vidcap_fourcc_string_get(
+ src_ctx->fmt_native.fourcc));
return (void *)-1;
}
Modified: trunk/src/vidcap.c
===================================================================
--- trunk/src/vidcap.c 2007-09-03 20:34:33 UTC (rev 3)
+++ trunk/src/vidcap.c 2007-09-06 15:39:40 UTC (rev 4)
@@ -369,12 +369,9 @@
if ( !src_ctx->format_validate(src_ctx, fmt_info, &fmt_native) )
{
- log_error("invalid format %dx%d %c%c%c%c %d/%d\n",
+ log_error("invalid format %dx%d %s %d/%d\n",
fmt_info->width, fmt_info->height,
- (char)(fmt_info->fourcc >> 24),
- (char)(fmt_info->fourcc >> 16),
- (char)(fmt_info->fourcc >> 8),
- (char)(fmt_info->fourcc >> 0),
+ vidcap_fourcc_string_get(fmt_info->fourcc),
fmt_info->fps_numerator,
fmt_info->fps_denominator);
return -1;
@@ -405,11 +402,9 @@
if ( !src_ctx->fmt_conv_buf_size )
{
- log_error("failed to get buffer size for %c%c%c%c\n",
- (char)(fmt_info->fourcc >> 24),
- (char)(fmt_info->fourcc >> 16),
- (char)(fmt_info->fourcc >> 8),
- (char)(fmt_info->fourcc >> 0));
+ log_error("failed to get buffer size for %s\n",
+ vidcap_fourcc_string_get(
+ fmt_info->fourcc));
return -1;
}
@@ -492,3 +487,26 @@
return ret;
}
+const char *
+vidcap_fourcc_string_get(int fourcc)
+{
+ switch ( fourcc )
+ {
+ case VIDCAP_FOURCC_I420:
+ return "i420";
+ case VIDCAP_FOURCC_YUY2:
+ return "yuy2";
+ case VIDCAP_FOURCC_RGB32:
+ return " rgb";
+ case VIDCAP_FOURCC_RGB24:
+ return " r24";
+ case VIDCAP_FOURCC_RGB555:
+ return "r555";
+ case VIDCAP_FOURCC_YVU9:
+ return "yvu9";
+ case VIDCAP_FOURCC_2VUY:
+ return "2vuy";
+ default:
+ return "????";
+ }
+}
Added: trunk/vidcap.pc.in
===================================================================
--- trunk/vidcap.pc.in (rev 0)
+++ trunk/vidcap.pc.in 2007-09-06 15:39:40 UTC (rev 4)
@@ -0,0 +1,12 @@
+prefix=@prefix@
+exec_prefix=${prefix}
+libdir=@libdir@
+includedir=${prefix}/include
+
+Name: vidcap
+Description: Cross-platform video capture library
+Version: @PACKAGE_VERSION@
+Libs: -L${libdir} -lvidcap @PTHREAD_LIBS@
+Libs.private:
+Cflags: -I${includedir}
+Requires.private: @PKG_REQUIRES@
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: libvidcap c. m. <lib...@li...> - 2007-09-11 15:31:21
|
Revision: 14
http://libvidcap.svn.sourceforge.net/libvidcap/?rev=14&view=rev
Author: bcholew
Date: 2007-09-11 08:31:16 -0700 (Tue, 11 Sep 2007)
Log Message:
-----------
Remove all destination buffer size checks in conversion functions. Replace with notices for each class of conversion function.
Modified Paths:
--------------
trunk/examples/vidcapTester/Grabber.cpp
trunk/include/vidcap/converters.h
trunk/src/conv.c
trunk/src/conv.h
trunk/src/conv_to_i420.c
trunk/src/conv_to_rgb.c
trunk/src/conv_to_yuy2.c
trunk/src/sapi.c
Modified: trunk/examples/vidcapTester/Grabber.cpp
===================================================================
--- trunk/examples/vidcapTester/Grabber.cpp 2007-09-11 14:46:28 UTC (rev 13)
+++ trunk/examples/vidcapTester/Grabber.cpp 2007-09-11 15:31:16 UTC (rev 14)
@@ -134,13 +134,13 @@
rgb_buf.resize(width_ * height_ * 4);
vidcap_i420_to_rgb32(width_, height_, cap_info->video_data,
- rgb_buf.data(), rgb_buf.size());
+ rgb_buf.data());
break;
case VIDCAP_FOURCC_YUY2:
rgb_buf.resize(width_ * height_ * 4);
vidcap_yuy2_to_rgb32(width_, height_, cap_info->video_data,
- rgb_buf.data(), rgb_buf.size());
+ rgb_buf.data());
break;
Modified: trunk/include/vidcap/converters.h
===================================================================
--- trunk/include/vidcap/converters.h 2007-09-11 14:46:28 UTC (rev 13)
+++ trunk/include/vidcap/converters.h 2007-09-11 15:31:16 UTC (rev 14)
@@ -32,27 +32,27 @@
int
vidcap_i420_to_rgb32(int width, int height, const char * src,
- char * dest, int dest_size);
+ char * dest);
int
vidcap_i420_to_yuy2(int width, int height, const char * src,
- char * dest, int dest_size);
+ char * dest);
int
vidcap_yuy2_to_i420(int width, int height, const char * src,
- char * dest, int dest_size);
+ char * dest);
int
vidcap_yuy2_to_rgb32(int width, int height, const char * src,
- char * dest, int dest_size);
+ char * dest);
int
vidcap_rgb32_to_i420(int width, int height, const char * src,
- char * dest, int dest_size);
+ char * dest);
int
vidcap_rgb32_to_yuy2(int width, int height, const char * src,
- char * dest, int dest_size);
+ char * dest);
#ifdef __cplusplus
}
Modified: trunk/src/conv.c
===================================================================
--- trunk/src/conv.c 2007-09-11 14:46:28 UTC (rev 13)
+++ trunk/src/conv.c 2007-09-11 15:31:16 UTC (rev 14)
@@ -25,11 +25,11 @@
#include "conv.h"
-int conv_2vuy_to_i420(int w, int h, const char * s, char * d, int ds);
-int conv_2vuy_to_yuy2(int w, int h, const char * s, char * d, int ds);
-int conv_rgb24_to_rgb32(int w, int h, const char * s, char * d, int ds);
-int conv_yvu9_to_i420(int w, int h, const char * s, char * d, int ds);
-int conv_bottom_up_rgb24_to_rgb32(int w, int h, const char * s, char * d, int ds);
+int conv_2vuy_to_i420(int w, int h, const char * s, char * d);
+int conv_2vuy_to_yuy2(int w, int h, const char * s, char * d);
+int conv_rgb24_to_rgb32(int w, int h, const char * s, char * d);
+int conv_yvu9_to_i420(int w, int h, const char * s, char * d);
+int conv_bottom_up_rgb24_to_rgb32(int w, int h, const char * s, char * d);
struct conv_info
{
Modified: trunk/src/conv.h
===================================================================
--- trunk/src/conv.h 2007-09-11 14:46:28 UTC (rev 13)
+++ trunk/src/conv.h 2007-09-11 15:31:16 UTC (rev 14)
@@ -39,7 +39,7 @@
};
typedef int (*conv_func)(int width, int height,
- const char * src, char * dst, int dst_size);
+ const char * src, char * dst);
#ifdef __cplusplus
extern "C" {
Modified: trunk/src/conv_to_i420.c
===================================================================
--- trunk/src/conv_to_i420.c 2007-09-11 14:46:28 UTC (rev 13)
+++ trunk/src/conv_to_i420.c 2007-09-11 15:31:16 UTC (rev 14)
@@ -27,10 +27,13 @@
#include <vidcap/converters.h>
#include "logging.h"
+/* NOTE: size of dest must be >= width * height * 3 / 2
+ */
+
int
vidcap_rgb32_to_i420(int width, int height,
const char * src,
- char * dst, int dest_size)
+ char * dst)
{
log_error("vidcap_rgb32_to_i420() not implemented\n");
return -1;
@@ -39,7 +42,7 @@
int
vidcap_yuy2_to_i420(int width, int height,
const char * src,
- char * dst, int dest_size)
+ char * dst)
{
/* convert from a packed structure to a planar structure */
char * dst_y_even = dst;
@@ -51,9 +54,6 @@
int i, j;
- if ( dest_size < width * height * 3 / 2 )
- return -1;
-
/* yuy2 has a vertical sampling period (for u and v)
* half that for i420. Will toss half of the
* U and V data during repackaging.
@@ -88,7 +88,7 @@
int
conv_2vuy_to_i420(int width, int height,
const char * src,
- char * dst, int dest_size)
+ char * dst)
{
char * dst_y_even = dst;
char * dst_y_odd = dst + width;
@@ -99,9 +99,6 @@
int i, j;
- if ( dest_size < width * height * 3 / 2 )
- return -1;
-
for ( i = 0; i < height / 2; ++i )
{
for ( j = 0; j < width / 2; ++j )
@@ -132,7 +129,7 @@
int
conv_yvu9_to_i420(int width, int height,
const char * src,
- char * dst, int dest_size)
+ char * dst)
{
char * dst_y = dst;
char * dst_u_even = dst + width * height;
@@ -145,9 +142,6 @@
int i, j;
- if ( dest_size < width * height * 3 / 2 )
- return -1;
-
memcpy(dst_y, src_y, height * width);
for ( i = 0; i < height / 4; ++i )
Modified: trunk/src/conv_to_rgb.c
===================================================================
--- trunk/src/conv_to_rgb.c 2007-09-11 14:46:28 UTC (rev 13)
+++ trunk/src/conv_to_rgb.c 2007-09-11 15:31:16 UTC (rev 14)
@@ -23,7 +23,6 @@
*
*/
-//#include <string.h>
#include <vidcap/converters.h>
enum {
@@ -98,9 +97,13 @@
*
* Based on the formulas found at http://en.wikipedia.org/wiki/YUV
*/
+
+/* NOTE: size of dest buffer must be >= width * height * 4
+ */
+
int
vidcap_i420_to_rgb32(int width, int height, const char * src,
- char * dest, int dest_size)
+ char * dest)
{
const unsigned char * y_even;
const unsigned char * y_odd;
@@ -110,9 +113,6 @@
unsigned int *dst_odd;
int i, j;
- if ( dest_size < width * height * 4 )
- return -1;
-
if ( !tables_initialized )
init_yuv2rgb_tables();
@@ -159,14 +159,11 @@
* chroma (Cr and Cb aka v and u) sample use for both pixels.
*/
int vidcap_yuy2_to_rgb32(int width, int height, const char * src,
- char * dest, int dest_size)
+ char * dest)
{
unsigned int * d = (unsigned int *)dest;
int i, j;
- if ( dest_size < width * height * 4 )
- return -1;
-
if ( !tables_initialized )
init_yuv2rgb_tables();
@@ -193,14 +190,11 @@
}
int conv_rgb24_to_rgb32(int width, int height, const char * src,
- char * dest, int dest_size)
+ char * dest)
{
int i;
unsigned int * d = (unsigned int *)dest;
- if ( dest_size < width * height * 4 )
- return -1;
-
for ( i = 0; i < width * height; ++i )
{
*d = 0xff000000;
@@ -214,15 +208,12 @@
int conv_bottom_up_rgb24_to_rgb32(int width, int height,
const char * src,
- char * dest, int dest_size)
+ char * dest)
{
int i;
unsigned int * d = (unsigned int *)dest;
const unsigned char *src_end = src - 1 + width * height * 3;
- if ( dest_size < width * height * 4 )
- return -1;
-
for ( i = 0; i < width * height; ++i )
{
*d = 0xff000000;
Modified: trunk/src/conv_to_yuy2.c
===================================================================
--- trunk/src/conv_to_yuy2.c 2007-09-11 14:46:28 UTC (rev 13)
+++ trunk/src/conv_to_yuy2.c 2007-09-11 15:31:16 UTC (rev 14)
@@ -26,9 +26,12 @@
#include <vidcap/converters.h>
#include "logging.h"
+/* NOTE: size of dest buffer must be >= width * height * 2
+ */
+
int
vidcap_rgb32_to_yuy2(int width, int height, const char * src,
- char * dest, int dest_size)
+ char * dest)
{
log_error("vidcap_rgb32_to_yuy2() not implemented\n");
return -1;
@@ -36,7 +39,7 @@
int
vidcap_i420_to_yuy2(int width, int height, const char * src,
- char * dest, int dest_size)
+ char * dest)
{
log_error("vidcap_i420_to_yuy2() not implemented\n");
return -1;
@@ -44,15 +47,12 @@
int
conv_2vuy_to_yuy2(int width, int height, const char * src,
- char * dest, int dest_size)
+ char * dest)
{
int i;
unsigned int * d = (unsigned int *)dest;
const unsigned int * s = (const unsigned int *)src;
- if ( dest_size < width * height * 2 )
- return -1;
-
for ( i = 0; i < width * height / 2; ++i )
{
*d++ = ((*s & 0xff000000) >> 8) |
Modified: trunk/src/sapi.c
===================================================================
--- trunk/src/sapi.c 2007-09-11 14:46:28 UTC (rev 13)
+++ trunk/src/sapi.c 2007-09-11 15:31:16 UTC (rev 14)
@@ -236,8 +236,7 @@
src_ctx->fmt_nominal.width,
src_ctx->fmt_nominal.height,
video_data,
- src_ctx->fmt_conv_buf,
- src_ctx->fmt_conv_buf_size) )
+ src_ctx->fmt_conv_buf) )
{
log_error("failed format conversion\n");
cap_info.error_status = -1;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: libvidcap c. m. <lib...@li...> - 2007-10-06 19:10:19
|
Revision: 40
http://libvidcap.svn.sourceforge.net/libvidcap/?rev=40&view=rev
Author: jpgrayson
Date: 2007-10-06 12:10:17 -0700 (Sat, 06 Oct 2007)
Log Message:
-----------
Fixup 'make dist'.
vidcapTester makes it into source tarball.
directshow sources fixed-up in Makefile.am.
Modified Paths:
--------------
trunk/examples/Makefile.am
trunk/src/Makefile.am
Modified: trunk/examples/Makefile.am
===================================================================
--- trunk/examples/Makefile.am 2007-10-01 21:47:31 UTC (rev 39)
+++ trunk/examples/Makefile.am 2007-10-06 19:10:17 UTC (rev 40)
@@ -16,3 +16,4 @@
-framework QuickTime
endif
+EXTRA_DIST = vidcapTester
Modified: trunk/src/Makefile.am
===================================================================
--- trunk/src/Makefile.am 2007-10-01 21:47:31 UTC (rev 39)
+++ trunk/src/Makefile.am 2007-10-06 19:10:17 UTC (rev 40)
@@ -51,15 +51,18 @@
endif
if HAVE_DIRECTSHOW
-libvidcap_la_SOURCES += \
- sapi_dshow.cpp \
- directshow/DShowSrcManager.cpp \
- directshow/DShowSrcManager.h \
- directshow/DevMonitor.cpp \
- directshow/DevMonitor.h \
- directshow/DirectShowSource.cpp \
- directshow/DirectShowSource.h \
- directshow/GraphMonitor.cpp \
- directshow/GraphMonitor.h \
- directshow/LocklessQueue.h
+libvidcap_la_SOURCES += \
+ directshow/DShowSrcManager.cpp \
+ directshow/DShowSrcManager.h \
+ directshow/DevMonitor.cpp \
+ directshow/DevMonitor.h \
+ directshow/DirectShowObject.cpp \
+ directshow/DirectShowObject.h \
+ directshow/DirectShowSource.cpp \
+ directshow/DirectShowSource.h \
+ directshow/GraphMonitor.cpp \
+ directshow/GraphMonitor.h \
+ directshow/SourceStateMachine.cpp \
+ directshow/SourceStateMachine.h \
+ sapi_dshow.cpp
endif
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: libvidcap c. m. <lib...@li...> - 2007-10-06 19:43:25
|
Revision: 41
http://libvidcap.svn.sourceforge.net/libvidcap/?rev=41&view=rev
Author: jpgrayson
Date: 2007-10-06 12:43:23 -0700 (Sat, 06 Oct 2007)
Log Message:
-----------
Add vidcap_log_level_set() function to the api.
Set the default log level to VIDCAP_LOG_INFO.
Change some quicktime messages to debug level.
Modified Paths:
--------------
trunk/include/vidcap/vidcap.h
trunk/src/logging.c
trunk/src/quicktime/sg_source.c
trunk/src/sapi_qt.c
trunk/src/vidcap.c
Modified: trunk/include/vidcap/vidcap.h
===================================================================
--- trunk/include/vidcap/vidcap.h 2007-10-06 19:10:17 UTC (rev 40)
+++ trunk/include/vidcap/vidcap.h 2007-10-06 19:43:23 UTC (rev 41)
@@ -38,6 +38,14 @@
VIDCAP_FOURCC_RGB32 = 102,
};
+enum vidcap_log_level {
+ VIDCAP_LOG_NONE = 0,
+ VIDCAP_LOG_ERROR = 10,
+ VIDCAP_LOG_WARN = 20,
+ VIDCAP_LOG_INFO = 30,
+ VIDCAP_LOG_DEBUG = 40
+};
+
typedef void vidcap_state;
typedef void vidcap_sapi;
typedef void vidcap_src;
@@ -83,6 +91,9 @@
vidcap_destroy(vidcap_state *);
int
+vidcap_log_level_set(enum vidcap_log_level level);
+
+int
vidcap_sapi_enumerate(vidcap_state *,
int index,
struct vidcap_sapi_info *);
Modified: trunk/src/logging.c
===================================================================
--- trunk/src/logging.c 2007-10-06 19:10:17 UTC (rev 40)
+++ trunk/src/logging.c 2007-10-06 19:43:23 UTC (rev 41)
@@ -38,7 +38,7 @@
static FILE * logging_file = 0;
-static enum log_level logging_level = log_level_debug;
+static enum log_level logging_level = log_level_info;
static void do_log(enum log_level level, const char * fmt, va_list ap)
{
Modified: trunk/src/quicktime/sg_source.c
===================================================================
--- trunk/src/quicktime/sg_source.c 2007-10-06 19:10:17 UTC (rev 40)
+++ trunk/src/quicktime/sg_source.c 2007-10-06 19:43:23 UTC (rev 41)
@@ -149,7 +149,7 @@
src->native_pixel_format = (*compression_list)->cType;
- log_info("native pixel format %c%c%c%c\n",
+ log_debug("native pixel format %c%c%c%c\n",
(char)(src->native_pixel_format >> 24),
(char)(src->native_pixel_format >> 16),
(char)(src->native_pixel_format >> 8),
Modified: trunk/src/sapi_qt.c
===================================================================
--- trunk/src/sapi_qt.c 2007-10-06 19:10:17 UTC (rev 40)
+++ trunk/src/sapi_qt.c 2007-10-06 19:43:23 UTC (rev 41)
@@ -202,7 +202,7 @@
}
if ( qt_src_ctx->frame_count == 1 )
- log_info("capture time: %c%c%c%c %s %s %s\n",
+ log_debug("capture time: %c%c%c%c %s %s %s\n",
(char)(pixel_format >> 24),
(char)(pixel_format >> 16),
(char)(pixel_format >> 8),
@@ -287,7 +287,7 @@
return -1;
}
- log_info("setup decomp: %c%c%c%c %s %s %s\n",
+ log_debug("setup decomp: %c%c%c%c %s %s %s\n",
(char)(pixel_format >> 24),
(char)(pixel_format >> 16),
(char)(pixel_format >> 8),
Modified: trunk/src/vidcap.c
===================================================================
--- trunk/src/vidcap.c 2007-10-06 19:10:17 UTC (rev 40)
+++ trunk/src/vidcap.c 2007-10-06 19:43:23 UTC (rev 41)
@@ -133,6 +133,36 @@
}
int
+vidcap_log_level_set(enum vidcap_log_level level)
+{
+ int log_level;
+
+ switch ( level )
+ {
+ case VIDCAP_LOG_NONE:
+ log_level = log_level_none;
+ break;
+ case VIDCAP_LOG_ERROR:
+ log_level = log_level_error;
+ break;
+ case VIDCAP_LOG_WARN:
+ log_level = log_level_warn;
+ break;
+ case VIDCAP_LOG_INFO:
+ log_level = log_level_info;
+ break;
+ case VIDCAP_LOG_DEBUG:
+ log_level = log_level_debug;
+ default:
+ return -1;
+ }
+
+ log_level_set(log_level);
+
+ return 0;
+}
+
+int
vidcap_sapi_enumerate(vidcap_state * state,
int index,
struct vidcap_sapi_info * sapi_info)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: libvidcap c. m. <lib...@li...> - 2007-10-09 14:30:42
|
Revision: 42
http://libvidcap.svn.sourceforge.net/libvidcap/?rev=42&view=rev
Author: jpgrayson
Date: 2007-10-09 07:30:40 -0700 (Tue, 09 Oct 2007)
Log Message:
-----------
Whitespace, comments
Modified Paths:
--------------
trunk/include/vidcap/converters.h
trunk/src/sapi.c
Modified: trunk/include/vidcap/converters.h
===================================================================
--- trunk/include/vidcap/converters.h 2007-10-06 19:43:23 UTC (rev 41)
+++ trunk/include/vidcap/converters.h 2007-10-09 14:30:40 UTC (rev 42)
@@ -31,28 +31,22 @@
#endif
int
-vidcap_i420_to_rgb32(int width, int height, const char * src,
- char * dest);
+vidcap_i420_to_rgb32(int width, int height, const char * src, char * dest);
int
-vidcap_i420_to_yuy2(int width, int height, const char * src,
- char * dest);
+vidcap_i420_to_yuy2(int width, int height, const char * src, char * dest);
int
-vidcap_yuy2_to_i420(int width, int height, const char * src,
- char * dest);
+vidcap_yuy2_to_i420(int width, int height, const char * src, char * dest);
int
-vidcap_yuy2_to_rgb32(int width, int height, const char * src,
- char * dest);
+vidcap_yuy2_to_rgb32(int width, int height, const char * src, char * dest);
int
-vidcap_rgb32_to_i420(int width, int height, const char * src,
- char * dest);
+vidcap_rgb32_to_i420(int width, int height, const char * src, char * dest);
int
-vidcap_rgb32_to_yuy2(int width, int height, const char * src,
- char * dest);
+vidcap_rgb32_to_yuy2(int width, int height, const char * src, char * dest);
#ifdef __cplusplus
}
Modified: trunk/src/sapi.c
===================================================================
--- trunk/src/sapi.c 2007-10-06 19:43:23 UTC (rev 41)
+++ trunk/src/sapi.c 2007-10-09 14:30:40 UTC (rev 42)
@@ -217,9 +217,10 @@
{
struct vidcap_capture_info cap_info;
- // NOTE: We may be called here by a notification thread while
- // the main thread is clearing the src_ctx ->capture_data and
- // ->capture_callback from within vidcap_src_capture_stop()
+ /* NOTE: We may be called here by a notification thread while the
+ * main thread is clearing capture_data and capture_callback from
+ * within vidcap_src_capture_stop().
+ */
vidcap_src_capture_callback cap_callback = src_ctx->capture_callback;
void * cap_data = src_ctx->capture_data;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: libvidcap c. m. <lib...@li...> - 2007-10-09 16:28:31
|
Revision: 43
http://libvidcap.svn.sourceforge.net/libvidcap/?rev=43&view=rev
Author: bcholew
Date: 2007-10-09 09:28:27 -0700 (Tue, 09 Oct 2007)
Log Message:
-----------
Added vcproj file.
Added Paths:
-----------
trunk/contrib/
trunk/contrib/win/
trunk/contrib/win/vs2005/
trunk/contrib/win/vs2005/libvidcap.vcproj
Added: trunk/contrib/win/vs2005/libvidcap.vcproj
===================================================================
--- trunk/contrib/win/vs2005/libvidcap.vcproj (rev 0)
+++ trunk/contrib/win/vs2005/libvidcap.vcproj 2007-10-09 16:28:27 UTC (rev 43)
@@ -0,0 +1,372 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="libvidcap"
+ ProjectGUID="{F5166D99-32BB-40D5-BE95-6F97F72C44CE}"
+ RootNamespace="libvidcap"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="..\..\..\..\build-win32\$(ProjectName)\$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="4"
+ UseOfATL="0"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories="..\..\..\src;..\..\..\src\directshow;..\..\..\include;"$(DXSDK_DIR)\Include""
+ PreprocessorDefinitions="WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;HAVE_DIRECTSHOW;HAVE_SLEEP"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ CompileAs="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="..\..\..\..\build-win32\$(ProjectName)\$(ConfigurationName)"
+ IntermediateDirectory="$(OutDir)"
+ ConfigurationType="4"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories="..\..\..\src;..\..\..\src\directshow;..\..\..\include;"$(DXSDK_DIR)\Include""
+ PreprocessorDefinitions="WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;HAVE_DIRECTSHOW;HAVE_SLEEP"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ CompileAs="1"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLibrarianTool"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath="..\..\..\src\conv.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\conv_to_i420.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\conv_to_rgb.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\conv_to_yuy2.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\directshow\DevMonitor.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ CompileAs="2"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ CompileAs="2"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\..\src\directshow\DirectShowSource.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ CompileAs="2"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ CompileAs="2"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\..\src\directshow\DShowSrcManager.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ CompileAs="2"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ CompileAs="2"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\..\src\directshow\GraphMonitor.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ CompileAs="2"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ CompileAs="2"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\..\src\hotlist.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\logging.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\sapi.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\sapi_dshow.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ CompileAs="2"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ CompileAs="2"
+ />
+ </FileConfiguration>
+ </File>
+ <File
+ RelativePath="..\..\..\src\sliding_window.c"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\vidcap.c"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ <FileConfiguration
+ Name="Release|Win32"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ ObjectFile="$(IntDir)\$(InputName)1.obj"
+ XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc"
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath="..\..\..\src\conv.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\include\vidcap\converters.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\directshow\DevMonitor.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\directshow\DirectShowSource.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\directshow\DShowSrcManager.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\directshow\GraphMonitor.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\hotlist.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\logging.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\sapi.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\sapi_context.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\src\sliding_window.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\include\vidcap\vidcap.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
Property changes on: trunk/contrib/win/vs2005/libvidcap.vcproj
___________________________________________________________________
Name: svn:executable
+ *
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: libvidcap c. <lib...@li...> - 2007-11-26 17:59:41
|
Revision: 65
http://libvidcap.svn.sourceforge.net/libvidcap/?rev=65&view=rev
Author: bcholew
Date: 2007-11-26 09:59:33 -0800 (Mon, 26 Nov 2007)
Log Message:
-----------
Add a capture timer thread to strictly enforce framerate (but preserve code for use without this thread). Add a double buffer to pass frames between threads. Abstract threading and mutexes for linux, mac and windows. Add new double_buffer and os_funcs files to vcproj and Makefiles. Simplify and rearrange some includes.
Modified Paths:
--------------
trunk/contrib/win/vs2005/libvidcap.vcproj
trunk/src/Makefile.am
trunk/src/directshow/DShowSrcManager.cpp
trunk/src/directshow/DevMonitor.cpp
trunk/src/directshow/DevMonitor.h
trunk/src/directshow/DirectShowSource.cpp
trunk/src/directshow/SourceStateMachine.cpp
trunk/src/sapi.c
trunk/src/sapi_context.h
trunk/src/sapi_dshow.cpp
trunk/src/vidcap.c
Added Paths:
-----------
trunk/src/double_buffer.c
trunk/src/double_buffer.h
trunk/src/os_funcs.h
Modified: trunk/contrib/win/vs2005/libvidcap.vcproj
===================================================================
--- trunk/contrib/win/vs2005/libvidcap.vcproj 2007-11-20 17:51:57 UTC (rev 64)
+++ trunk/contrib/win/vs2005/libvidcap.vcproj 2007-11-26 17:59:33 UTC (rev 65)
@@ -228,6 +228,10 @@
</FileConfiguration>
</File>
<File
+ RelativePath="..\..\..\src\double_buffer.c"
+ >
+ </File>
+ <File
RelativePath="..\..\..\src\directshow\DShowSrcManager.cpp"
>
<FileConfiguration
@@ -372,6 +376,10 @@
>
</File>
<File
+ RelativePath="..\..\..\src\double_buffer.h"
+ >
+ </File>
+ <File
RelativePath="..\..\..\src\directshow\DShowSrcManager.h"
>
</File>
@@ -388,6 +396,10 @@
>
</File>
<File
+ RelativePath="..\..\..\src\os_funcs.h"
+ >
+ </File>
+ <File
RelativePath="..\..\..\src\sapi.h"
>
</File>
Modified: trunk/src/Makefile.am
===================================================================
--- trunk/src/Makefile.am 2007-11-20 17:51:57 UTC (rev 64)
+++ trunk/src/Makefile.am 2007-11-26 17:59:33 UTC (rev 65)
@@ -19,10 +19,13 @@
conv_to_rgb.c \
conv_to_i420.c \
conv_to_yuy2.c \
+ double_buffer.c \
+ double_buffer.h \
hotlist.c \
hotlist.h \
logging.c \
logging.h \
+ os_funcs.h \
sapi.c \
sapi.h \
sapi_context.h \
Modified: trunk/src/directshow/DShowSrcManager.cpp
===================================================================
--- trunk/src/directshow/DShowSrcManager.cpp 2007-11-20 17:51:57 UTC (rev 64)
+++ trunk/src/directshow/DShowSrcManager.cpp 2007-11-26 17:59:33 UTC (rev 65)
@@ -22,7 +22,7 @@
// <http://www.gnu.org/licenses/>.
//
-#include <windows.h>
+#include "os_funcs.h"
#include <cstring>
#include <cstdio>
#include <cwchar>
Modified: trunk/src/directshow/DevMonitor.cpp
===================================================================
--- trunk/src/directshow/DevMonitor.cpp 2007-11-20 17:51:57 UTC (rev 64)
+++ trunk/src/directshow/DevMonitor.cpp 2007-11-26 17:59:33 UTC (rev 65)
@@ -22,11 +22,12 @@
// <http://www.gnu.org/licenses/>.
//
-#include "DevMonitor.h"
+#include "os_funcs.h"
#include <dbt.h>
#include <process.h>
#include <string>
#include "sapi_context.h"
+#include "DevMonitor.h"
#include "logging.h"
DevMonitor::DevMonitor()
Modified: trunk/src/directshow/DevMonitor.h
===================================================================
--- trunk/src/directshow/DevMonitor.h 2007-11-20 17:51:57 UTC (rev 64)
+++ trunk/src/directshow/DevMonitor.h 2007-11-26 17:59:33 UTC (rev 65)
@@ -25,21 +25,8 @@
#ifndef _DEVMONITOR_H_
#define _DEVMONITOR_H_
-#include <windows.h>
#include <vidcap/vidcap.h>
-// Allow use of features specific to Windows XP or later.
-#ifndef _WIN32_WINNT
-
-// Change this to the appropriate value to target other versions of Windows.
-// see: http://msdn2.microsoft.com/en-us/library/aa383745.aspx
-#define _WIN32_WINNT 0x0501
-
-#endif
-
-// Exclude rarely-used stuff from Windows headers
-#define WIN32_LEAN_AND_MEAN
-
class DevMonitor
{
Modified: trunk/src/directshow/DirectShowSource.cpp
===================================================================
--- trunk/src/directshow/DirectShowSource.cpp 2007-11-20 17:51:57 UTC (rev 64)
+++ trunk/src/directshow/DirectShowSource.cpp 2007-11-26 17:59:33 UTC (rev 65)
@@ -22,7 +22,7 @@
// <http://www.gnu.org/licenses/>.
//
-#include <windows.h>
+#include "os_funcs.h"
#include <cstring>
#include <cstdio>
#include <cwchar>
@@ -686,6 +686,9 @@
static_cast<double>(fmtNominal->fps_denominator);
// check framerate
+ // TODO: a timer thread could enforce this framerate,
+ // but would need to pass src_ctx->use_timer_thread here
+ // to know that
if ( fps > fpsMax )
{
freeMediaType(*pMediaType);
Modified: trunk/src/directshow/SourceStateMachine.cpp
===================================================================
--- trunk/src/directshow/SourceStateMachine.cpp 2007-11-20 17:51:57 UTC (rev 64)
+++ trunk/src/directshow/SourceStateMachine.cpp 2007-11-26 17:59:33 UTC (rev 65)
@@ -22,11 +22,9 @@
// <http://www.gnu.org/licenses/>.
//
-#include <windows.h>
-
+#include "sapi.h"
#include "hotlist.h"
#include "logging.h"
-#include "sapi.h"
#include "SourceStateMachine.h"
SourceStateMachine::SourceStateMachine(struct sapi_src_context *src,
Added: trunk/src/double_buffer.c
===================================================================
--- trunk/src/double_buffer.c (rev 0)
+++ trunk/src/double_buffer.c 2007-11-26 17:59:33 UTC (rev 65)
@@ -0,0 +1,200 @@
+/*
+ * libvidcap - a cross-platform video capture library
+ *
+ * Copyright 2007 Wimba, Inc.
+ *
+ * Contributors:
+ * Peter Grayson <jpg...@gm...>
+ * Bill Cholewka <bc...@gm...>
+ *
+ * libvidcap 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.
+ *
+ * libvidcap 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, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "double_buffer.h"
+
+#include "logging.h"
+
+/* The write thread inserts (and frees) objects.
+ * The read thread reads (copies) objects
+ *
+ * It is the responsibility of the read thread's 'application' to
+ * free the copied objects.
+ *
+ * If the read thread 'application' blocks for too long (doesn't
+ * read often enough), the write thread will free a buffered object
+ * to make room for an incoming object
+ */
+
+/* NOTE: This function is passed function pointers to call when
+ * necessary to free or copy an object
+ */
+struct double_buffer *
+double_buffer_create( void (*free_me)(void *), void * (*copy_me)(void *) )
+{
+
+ struct double_buffer * db_buff;
+
+ if ( !free_me || !copy_me )
+ return 0;
+
+ db_buff = calloc(1, sizeof(*db_buff));
+
+ if ( !db_buff )
+ {
+ log_oom(__FILE__, __LINE__);
+ return 0;
+ }
+
+ db_buff->read_count = 0;
+ db_buff->write_count = 0;
+ db_buff->count[0] = -1;
+ db_buff->count[1] = -1;
+ db_buff->objects[0] = 0;
+ db_buff->objects[1] = 0;
+
+ db_buff->free_object = free_me;
+ db_buff->copy_object = copy_me;
+
+ vc_mutex_init(&db_buff->locks[0]);
+ vc_mutex_init(&db_buff->locks[1]);
+
+ /* TODO: remove this (debug) counter */
+ db_buff->num_insert_too_far_failures = 0;
+
+ return db_buff;
+}
+
+void
+double_buffer_destroy(struct double_buffer * db_buff)
+{
+ vc_mutex_destroy(&db_buff->locks[1]);
+ vc_mutex_destroy(&db_buff->locks[0]);
+
+ if ( db_buff->write_count > 0 )
+ db_buff->free_object(db_buff->objects[0]);
+
+ if ( db_buff->write_count > 1 )
+ db_buff->free_object(db_buff->objects[1]);
+
+ free(db_buff);
+}
+
+void
+double_buffer_insert(struct double_buffer * db_buff, void * new_object)
+{
+ const int insertion_index = db_buff->write_count % 2;
+
+ /* TODO: we could eliminate a copy by having the reader free
+ * all buffered objects. This would require that a failed
+ * check below result in the object being freed. This
+ * would ensure that the reader sees all BUFFERED objects.
+ *
+ * The reader would then need to take care to free objects
+ * as they become outdated.
+ *
+ * The tradeoff is the occasional dropped object when
+ * the writer gets ahead a little. The counter can help
+ * to evaluate the cost of this tradeoff
+ */
+ /* don't get far ahead of the reader*/
+ if ( db_buff->write_count > ( db_buff->read_count + 2 ) )
+ {
+ db_buff->num_insert_too_far_failures++;
+ /* return; */
+ }
+
+ /* get exclusive access to the correct buffer */
+ if ( vc_mutex_trylock(&db_buff->locks[insertion_index] ))
+ {
+ /* failed to obtain lock */
+ /* drop incoming object */
+ db_buff->free_object(new_object);
+ return;
+ }
+
+ /* free the slot object if something is already there */
+ if ( db_buff->write_count > 1 )
+ db_buff->free_object(db_buff->objects[insertion_index]);
+
+ /* insert object */
+ db_buff->objects[insertion_index] = new_object;
+
+ /* stamp the buffer with the write count */
+ db_buff->count[insertion_index] = db_buff->write_count;
+
+ /* advance the write count */
+ ++db_buff->write_count;
+
+ /* unlock the correct lock */
+ vc_mutex_unlock(&db_buff->locks[insertion_index]);
+}
+
+void *
+double_buffer_read(struct double_buffer * db_buff)
+{
+ int copy_index = 1;
+ void * buff;
+
+ if ( db_buff->write_count < 1 )
+ return 0;
+
+ /* NOTE: Try the newest buffer first
+ * IF that lock fails THEN try other
+ */
+ if ( db_buff->count[0] > db_buff->count[1] )
+ copy_index = 0;
+
+ if ( vc_mutex_trylock(&db_buff->locks[copy_index] ) )
+ {
+ /* failed to obtain lock */
+ /* try the other (older) slot? */
+ if ( db_buff->write_count < 2 )
+ return 0;
+
+ copy_index = 1 - copy_index;
+
+ /* Failed to obtain other lock? */
+ /* This should be pretty rare */
+ if ( vc_mutex_trylock(&db_buff->locks[copy_index] ) )
+ return 0;
+ }
+
+ /* Is this buffer older than the last-read?
+ * TODO: could this happen?
+ */
+ if ( db_buff->count[copy_index] < db_buff->read_count )
+ {
+ vc_mutex_unlock(&db_buff->locks[copy_index]);
+ return 0;
+ }
+
+ buff = db_buff->copy_object(db_buff->objects[copy_index]);
+
+ db_buff->read_count = db_buff->count[copy_index];
+
+ vc_mutex_unlock(&db_buff->locks[copy_index]);
+
+ return buff;
+}
+
+int
+double_buffer_count(struct double_buffer * db_buff)
+{
+ return db_buff->write_count;
+}
Property changes on: trunk/src/double_buffer.c
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/src/double_buffer.h
===================================================================
--- trunk/src/double_buffer.h (rev 0)
+++ trunk/src/double_buffer.h 2007-11-26 17:59:33 UTC (rev 65)
@@ -0,0 +1,65 @@
+/*
+ * libvidcap - a cross-platform video capture library
+ *
+ * Copyright 2007 Wimba, Inc.
+ *
+ * Contributors:
+ * Peter Grayson <jpg...@gm...>
+ * Bill Cholewka <bc...@gm...>
+ *
+ * libvidcap 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.
+ *
+ * libvidcap 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, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef _DOUBLE_BUFFER_H
+#define _DOUBLE_BUFFER_H
+
+#include "os_funcs.h"
+
+#define _DOUBLE_MEANS_TWO_ 2
+
+struct double_buffer
+{
+ int read_count;
+ int write_count;
+ void * objects[_DOUBLE_MEANS_TWO_];
+ vc_mutex locks[_DOUBLE_MEANS_TWO_];
+
+ int count[_DOUBLE_MEANS_TWO_];
+
+ void * (*copy_object)(void *);
+ void (*free_object)(void *);
+
+ /* TODO: remove */
+ int num_insert_too_far_failures;
+};
+
+struct double_buffer *
+double_buffer_create( void (*free_obj_func)(void *),
+ void * (*copy_object)(void *));
+
+void
+double_buffer_destroy(struct double_buffer * db_buff);
+
+void
+double_buffer_insert(struct double_buffer * db_buff, void * object);
+
+void *
+double_buffer_read(struct double_buffer * db_buff);
+
+int
+double_buffer_count(struct double_buffer * db_buff);
+
+#endif
Property changes on: trunk/src/double_buffer.h
___________________________________________________________________
Name: svn:executable
+ *
Added: trunk/src/os_funcs.h
===================================================================
--- trunk/src/os_funcs.h (rev 0)
+++ trunk/src/os_funcs.h 2007-11-26 17:59:33 UTC (rev 65)
@@ -0,0 +1,219 @@
+/*
+ * libvidcap - a cross-platform video capture library
+ *
+ * Copyright 2007 Wimba, Inc.
+ *
+ * Contributors:
+ * Peter Grayson <jpg...@gm...>
+ * Bill Cholewka <bc...@gm...>
+ *
+ * libvidcap 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.
+ *
+ * libvidcap 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, see
+ * <http://www.gnu.org/licenses/>.
+ *
+ */
+
+#ifndef _OS_FUNCS_H
+#define _OS_FUNCS_H
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#if defined(HAVE_NANOSLEEP) || defined(HAVE_GETTIMEOFDAY)
+#include <sys/time.h>
+#include <time.h>
+#endif
+
+/* os-dependent macros */
+#if defined(WIN32) || defined(_WIN32_WCE)
+
+#ifndef _WIN32_WINNT
+// Change this to the appropriate value to target other versions of Windows.
+// see: http://msdn2.microsoft.com/en-us/library/aa383745.aspx
+#define _WIN32_WINNT 0x0500
+#endif
+
+#include <windows.h>
+
+#if !defined(_WIN32_WCE)
+#include <process.h>
+#endif
+
+#define STDCALL __stdcall
+typedef CRITICAL_SECTION vc_mutex;
+typedef uintptr_t vc_thread;
+
+#else
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/time.h>
+#include <pthread.h>
+
+#define STDCALL
+typedef pthread_mutex_t vc_mutex;
+typedef pthread_t vc_thread;
+
+#endif
+
+#ifdef MACOSX
+#include <mach/mach_init.h>
+#include <mach/thread_policy.h>
+#include <sched.h>
+#include <sys/sysctl.h>
+#endif
+
+#ifndef HAVE_GETTIMEOFDAY
+static __inline int
+gettimeofday(struct timeval * tv, struct timezone * tz)
+#ifdef WIN32
+{
+ FILETIME ft;
+ LARGE_INTEGER li;
+ __int64 t;
+ static int tzflag;
+ const __int64 EPOCHFILETIME = 116444736000000000i64;
+ if ( tv )
+ {
+ GetSystemTimeAsFileTime(&ft);
+ li.LowPart = ft.dwLowDateTime;
+ li.HighPart = ft.dwHighDateTime;
+ t = li.QuadPart; /* In 100-nanosecond intervals */
+ t -= EPOCHFILETIME; /* Offset to the Epoch time */
+ t /= 10; /* In microseconds */
+ tv->tv_sec = (long)(t / 1000000);
+ tv->tv_usec = (long)(t % 1000000);
+ }
+
+ return 0;
+
+#else /* !defined(_WINDOWS) */
+ errno = ENOSYS;
+ return -1;
+#endif
+}
+#endif /* !defined(HAVE_GETTIMEOFDAY) */
+
+
+static __inline int
+vc_create_thread(vc_thread *thread,
+ unsigned int (STDCALL * thread_func)(void *),
+ void *args, unsigned int *thread_id)
+{
+#ifdef WIN32
+ *thread = (uintptr_t)_beginthreadex(NULL, 0, thread_func,
+ (void *)args, 0, thread_id);
+
+ /* FIXME: log the error */
+ if ( thread == 0 )
+ return -1;
+#else
+ int ret;
+ void * (*func)(void *) = (void * (*)(void *))thread_func;
+
+ ret = pthread_create(thread, NULL, func, args);
+
+ /* FIXME: log the error */
+ if ( ret )
+ return -1;
+#endif
+
+ return 0;
+}
+
+static __inline void
+vc_thread_join(vc_thread *thread)
+{
+#ifdef WIN32
+ HANDLE _thread = (HANDLE)thread;
+
+ WaitForSingleObject(_thread, INFINITE);
+#else
+ pthread_t *_thread = (pthread_t *)thread;
+
+ pthread_join(*_thread, 0);
+#endif
+}
+
+static __inline void
+vc_mutex_init(vc_mutex *m)
+{
+#ifdef WIN32
+ InitializeCriticalSection(m);
+#else
+ pthread_mutex_init(m, NULL);
+#endif
+}
+
+static __inline void
+vc_mutex_lock(vc_mutex *m)
+{
+#ifdef WIN32
+ EnterCriticalSection(m);
+#else
+ pthread_mutex_lock(m);
+#endif
+}
+
+static __inline int
+vc_mutex_trylock(vc_mutex *m)
+{
+#ifdef WIN32
+ return !TryEnterCriticalSection(m);
+#else
+ return pthread_mutex_trylock(m);
+#endif
+}
+
+static __inline void
+vc_mutex_unlock(vc_mutex *m)
+{
+#ifdef WIN32
+ LeaveCriticalSection(m);
+#else
+ pthread_mutex_unlock(m);
+#endif
+}
+
+static __inline void
+vc_mutex_destroy(vc_mutex *m)
+{
+#ifdef WIN32
+ DeleteCriticalSection(m);
+#else
+ pthread_mutex_destroy(m);
+#endif
+}
+
+static __inline void
+vc_millisleep(long ms)
+{
+#ifdef WIN32
+
+ Sleep(ms);
+
+#else
+
+ struct timespec req;
+
+ req.tv_nsec = (ms % 1000) * 1000000;
+ req.tv_sec = ms / 1000;
+
+ nanosleep(&req, NULL);
+
+#endif
+}
+
+#endif
Property changes on: trunk/src/os_funcs.h
___________________________________________________________________
Name: svn:executable
+ *
Modified: trunk/src/sapi.c
===================================================================
--- trunk/src/sapi.c 2007-11-20 17:51:57 UTC (rev 64)
+++ trunk/src/sapi.c 2007-11-26 17:59:33 UTC (rev 65)
@@ -30,36 +30,9 @@
#include "logging.h"
#include "sapi.h"
-#ifndef HAVE_GETTIMEOFDAY
-static __inline int gettimeofday(struct timeval * tv, struct timezone * tz)
-#ifdef WIN32
-{
- FILETIME ft;
- LARGE_INTEGER li;
- __int64 t;
- static int tzflag;
- const __int64 EPOCHFILETIME = 116444736000000000i64;
- if ( tv )
- {
- GetSystemTimeAsFileTime(&ft);
- li.LowPart = ft.dwLowDateTime;
- li.HighPart = ft.dwHighDateTime;
- t = li.QuadPart; /* In 100-nanosecond intervals */
- t -= EPOCHFILETIME; /* Offset to the Epoch time */
- t /= 10; /* In microseconds */
- tv->tv_sec = (long)(t / 1000000);
- tv->tv_usec = (long)(t % 1000000);
- }
+static int
+deliver_frame(struct sapi_src_context * src_ctx);
- return 0;
-
-#else /* !defined(_WINDOWS) */
- errno = ENOSYS;
- return -1;
-#endif
-}
-#endif
-
static __inline int
tv_greater_or_equal(struct timeval * t1, struct timeval * t0)
{
@@ -76,7 +49,7 @@
}
static __inline void
-tv_add_usecs(struct timeval *t1, struct timeval *t0, int usecs)
+tv_add_usecs(struct timeval *t1, struct timeval *t0, long usecs)
{
int secs_carried = 0;
@@ -216,6 +189,19 @@
return 0;
}
+static void
+wait_for_error_ack(struct sapi_src_context * src_ctx)
+{
+ while ( !src_ctx->capture_error_ack )
+ vc_millisleep(10);
+}
+
+static void
+acknowledge_error(struct sapi_src_context * src_ctx)
+{
+ src_ctx->capture_error_ack = 1;
+}
+
/* NOTE: stride-ignorant sapis should pass a stride of zero */
int
sapi_src_capture_notify(struct sapi_src_context * src_ctx,
@@ -223,25 +209,121 @@
int stride,
int error_status)
{
- struct vidcap_capture_info cap_info;
-
/* NOTE: We may be called here by the capture thread while the
* main thread is clearing capture_data and capture_callback
* from within vidcap_src_capture_stop().
*/
+
+ /* Package the video information */
+ struct frame_info * frame = malloc(sizeof(*frame));
+ if ( !frame )
+ return -1;
+
+ frame->cap_info = malloc(sizeof(struct vidcap_capture_info));
+ if ( !frame->cap_info )
+ {
+ free(frame);
+ return -1;
+ }
+
+ frame->cap_info->video_data_size = video_data_size;
+ frame->cap_info->error_status = error_status;
+ frame->stride = stride;
+
+ if ( src_ctx->use_timer_thread )
+ {
+ /* Copy this buffer. It might not exist long enough for
+ * read thread (capture timer thread) to copy it
+ */
+ frame->cap_info->video_data = malloc(video_data_size);
+ if ( !frame->cap_info->video_data )
+ {
+ free(frame->cap_info);
+ free(frame);
+ return -1;
+ }
+
+ memcpy(frame->cap_info->video_data, video_data, video_data_size);
+
+ /* buffer the frame - for processing by the timer thread */
+ double_buffer_insert(src_ctx->double_buff, frame);
+
+ /* If there's an error, wait here until it's acknowledged
+ * by the timer thread (after having delivered it to the app).
+ */
+ if ( error_status )
+ wait_for_error_ack(src_ctx);
+ }
+ else
+ {
+ frame->cap_info->video_data = video_data;
+
+ /* process the frame now */
+ src_ctx->no_timer_thread_frame = frame;
+ deliver_frame(src_ctx);
+ }
+
+ if ( error_status )
+ {
+ src_ctx->src_state = src_bound;
+ src_ctx->capture_callback = 0;
+ src_ctx->capture_data = VIDCAP_INVALID_USER_DATA;
+ }
+
+ return 0;
+}
+
+static int
+deliver_frame(struct sapi_src_context * src_ctx)
+{
vidcap_src_capture_callback cap_callback = src_ctx->capture_callback;
void * cap_data = src_ctx->capture_data;
void * buf = 0;
int buf_data_size = 0;
-
int send_frame = 0;
- if ( !error_status )
- send_frame = enforce_framerate(src_ctx);
+ struct vidcap_capture_info cap_info;
- if ( send_frame < 0 )
- error_status = -1000;
+ struct frame_info * frame;
+ const char * video_data;
+ int video_data_size;
+ int stride;
+ int error_status;
+ if ( src_ctx->use_timer_thread )
+ {
+ frame = (struct frame_info *)
+ double_buffer_read(src_ctx->double_buff);
+
+ if ( !frame )
+ return -1;
+ }
+ else
+ {
+ frame = src_ctx->no_timer_thread_frame;
+ }
+
+ video_data = frame->cap_info->video_data;
+ video_data_size = frame->cap_info->video_data_size;
+ stride = frame->stride;
+ error_status = frame->cap_info->error_status;
+
+ /* FIXME: right now enforce_framerate() and the capture timer
+ * thread's main loop BOTH use the frame_time_next field
+ */
+ if ( src_ctx->use_timer_thread )
+ {
+ send_frame = 1;
+ }
+ else
+ {
+ if ( !error_status )
+ send_frame = enforce_framerate(src_ctx);
+
+ if ( send_frame < 0 )
+ error_status = -1000;
+ }
+
cap_info.error_status = error_status;
if ( !cap_info.error_status && stride &&
@@ -290,22 +372,143 @@
if ( ( send_frame || error_status ) && cap_callback &&
cap_data != VIDCAP_INVALID_USER_DATA )
{
- /* FIXME: Need to check return code.
- * Application may want capture to stop
+ /* FIXME: Need to check return code (and pass it back).
+ * Application may want capture to stop.
+ * Ensure we don't perform any more callbacks.
*/
cap_callback(src_ctx, cap_data, &cap_info);
- if ( cap_info.error_status )
+ if ( src_ctx->use_timer_thread )
{
- src_ctx->src_state = src_bound;
- src_ctx->capture_callback = 0;
- src_ctx->capture_data = VIDCAP_INVALID_USER_DATA;
+ /* delete frame */
+ free(frame->cap_info->video_data);
+ free(frame->cap_info);
+ free(frame);
+
+ if ( error_status )
+ {
+ /* Let capture thread know that the app
+ * Has received the error status.
+ * Ensure we don't deliver any more frames.
+ */
+ acknowledge_error(src_ctx);
+
+ /* inform calling function of error */
+ return 1;
+ }
}
}
return 0;
}
+unsigned int
+STDCALL sapi_src_timer_thread_func(void *args)
+{
+ struct sapi_src_context * src_ctx = args;
+ struct timeval tv_now;
+
+ /* change to faster rate at capture time, and reduce when capture stopped */
+ const long idle_state_sleep_period_ms = 100;
+ long sleep_ms = idle_state_sleep_period_ms;
+ int first_time = 1;
+ const int sleeps_per_capture = 1;
+ int got_frame = 0;
+ int ret;
+ int capture_error = 0; /* FIXME: perhaps should exit on error */
+
+ src_ctx->timer_thread_idle = 1;
+
+ if ( gettimeofday(&tv_now, 0) )
+ {
+ src_ctx->capture_timer_thread_started = -1;
+ log_error("gettimeofday not supported\n");
+ return -1;
+ }
+
+ src_ctx->frame_time_next.tv_sec = tv_now.tv_sec;
+ src_ctx->frame_time_next.tv_usec = tv_now.tv_usec;
+
+ log_info("capture timer thread now running\n");
+ src_ctx->capture_timer_thread_started = 1;
+
+ while ( !src_ctx->kill_timer_thread )
+ {
+ gettimeofday(&tv_now, 0);
+
+ /* time to attempt to read a frame? */
+ if ( capture_error || src_ctx->src_state != src_capturing ||
+ !tv_greater_or_equal(&tv_now, &src_ctx->frame_time_next) )
+ {
+ if ( src_ctx->src_state != src_capturing )
+ {
+ sleep_ms = idle_state_sleep_period_ms;
+ first_time = 1;
+ }
+
+ vc_millisleep(sleep_ms);
+ }
+ else
+ {
+ src_ctx->timer_thread_idle = 0;
+ /* FIXME: memory barrier needed? */
+
+ /* attempt to read and deliver a frame */
+ ret = deliver_frame(src_ctx);
+
+ got_frame = !ret;
+ capture_error = ret > 0;
+
+ /* Is this the first frame? */
+ if ( got_frame && first_time )
+ {
+ first_time = 0;
+
+ /* re-initialize when next to check for a frame */
+ src_ctx->frame_time_next.tv_sec = tv_now.tv_sec;
+ src_ctx->frame_time_next.tv_usec = tv_now.tv_usec;
+
+ sleep_ms = (1000 / sleeps_per_capture) *
+ src_ctx->fmt_nominal.fps_denominator /
+ src_ctx->fmt_nominal.fps_numerator;
+ }
+
+ if ( !first_time )
+ {
+ /* update when next to check for a frame */
+ /* FIXME: reduce round-off */
+ tv_add_usecs(&src_ctx->frame_time_next, &src_ctx->frame_time_next,
+ 1000000 *
+ src_ctx->fmt_nominal.fps_denominator /
+ src_ctx->fmt_nominal.fps_numerator);
+ }
+ else
+ {
+ /* still no first frame */
+ /* update when next to check for a frame */
+ tv_add_usecs(&src_ctx->frame_time_next, &tv_now,
+ 1000000 *
+ src_ctx->fmt_nominal.fps_denominator /
+ src_ctx->fmt_nominal.fps_numerator);
+ }
+ }
+
+ /* FIXME: memory barrier needed? */
+ src_ctx->timer_thread_idle = 1;
+ }
+
+ log_info("capture timer thread now exiting...\n");
+
+ return 0;
+}
+
+void
+sapi_src_timer_thread_idled(struct sapi_src_context * src_ctx)
+{
+ while ( !src_ctx->timer_thread_idle )
+ vc_millisleep(10);
+}
+
int
sapi_can_convert_native_to_nominal(const struct vidcap_fmt_info * fmt_native,
const struct vidcap_fmt_info * fmt_nominal)
@@ -333,3 +536,4 @@
return 0;
}
+
Modified: trunk/src/sapi_context.h
===================================================================
--- trunk/src/sapi_context.h 2007-11-20 17:51:57 UTC (rev 64)
+++ trunk/src/sapi_context.h 2007-11-26 17:59:33 UTC (rev 65)
@@ -26,26 +26,20 @@
#ifndef _SAPI_CONTEXT_H
#define _SAPI_CONTEXT_H
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#ifdef WIN32
-#include <windows.h>
-#endif
-
-#if defined(HAVE_NANOSLEEP) || defined(HAVE_GETTIMEOFDAY)
-#include <sys/time.h>
-#include <time.h>
-#endif
-
#include <vidcap/vidcap.h>
+#include "double_buffer.h"
#include "sliding_window.h"
#include "conv.h"
struct sapi_context;
+struct frame_info
+{
+ struct vidcap_capture_info *cap_info;
+ int stride;
+};
+
struct sapi_src_context
{
int (*release)(struct sapi_src_context *);
@@ -64,6 +58,7 @@
struct vidcap_src_info src_info;
struct sliding_window * frame_times;
struct timeval frame_time_next;
+ struct double_buffer * double_buff;
struct vidcap_fmt_info fmt_nominal;
struct vidcap_fmt_info fmt_native;
@@ -82,6 +77,15 @@
vidcap_src_capture_callback capture_callback;
void * capture_data;
+ int use_timer_thread;
+ struct frame_info * no_timer_thread_frame;
+ vc_thread capture_timer_thread;
+ unsigned int capture_timer_thread_id;
+ int capture_timer_thread_started;
+ int timer_thread_idle;
+ int kill_timer_thread;
+ int capture_error_ack;
+
void * priv;
};
@@ -124,4 +128,10 @@
void
sapi_src_fps_info_clean(struct sapi_src_context *);
+void
+sapi_src_timer_thread_idled(struct sapi_src_context * src_ctx);
+
+unsigned int
+STDCALL sapi_src_timer_thread_func(void *);
+
#endif
Modified: trunk/src/sapi_dshow.cpp
===================================================================
--- trunk/src/sapi_dshow.cpp 2007-11-20 17:51:57 UTC (rev 64)
+++ trunk/src/sapi_dshow.cpp 2007-11-26 17:59:33 UTC (rev 65)
@@ -22,14 +22,12 @@
// <http://www.gnu.org/licenses/>.
//
-#include <windows.h>
#include <stdio.h>
+#include "sapi.h"
#include "SourceStateMachine.h"
#include "DShowSrcManager.h"
-
#include "logging.h"
-#include "sapi.h"
static const char * identifier = "DirectShow";
static const char * description = "DirectShow video capture API";
@@ -177,7 +175,7 @@
return -1;
}
- if ( src_ctx->priv == 0 )
+ if ( src_ctx->priv == (void *)0 )
{
log_warn("failed constructing source state machine for '%s'\n",
src_info->identifier);
Modified: trunk/src/vidcap.c
===================================================================
--- trunk/src/vidcap.c 2007-11-20 17:51:57 UTC (rev 64)
+++ trunk/src/vidcap.c 2007-11-26 17:59:33 UTC (rev 65)
@@ -26,12 +26,6 @@
#include <stdlib.h>
#include <string.h>
-#include <vidcap/vidcap.h>
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
#include "logging.h"
#include "sapi_context.h"
#include "sapi.h"
@@ -312,6 +306,41 @@
return 0;
}
+ /* TODO: right now we always use the timer thread to enforce
+ * a very accurate framerate. Alternatively, we could
+ * allow an application to choose to forego this feature
+ * and the associated overhead
+ */
+ src_ctx->use_timer_thread = 1;
+
+ if ( src_ctx->use_timer_thread )
+ {
+ src_ctx->kill_timer_thread = 0;
+ src_ctx->capture_timer_thread_started = 0;
+ src_ctx->capture_timer_thread = 0;
+ /* FIXME: memory barrier needed? */
+
+ if ( vc_create_thread(&src_ctx->capture_timer_thread,
+ sapi_src_timer_thread_func, src_ctx,
+ &src_ctx->capture_timer_thread_id) )
+ {
+ src_ctx->capture_timer_thread = 0;
+ goto bail;
+ }
+
+ /* ens...
[truncated message content] |
|
From: libvidcap c. <lib...@li...> - 2007-11-26 18:33:10
|
Revision: 68
http://libvidcap.svn.sourceforge.net/libvidcap/?rev=68&view=rev
Author: bcholew
Date: 2007-11-26 10:32:38 -0800 (Mon, 26 Nov 2007)
Log Message:
-----------
De-constify the vidcap buffer - removing compile-time warnings.
Modified Paths:
--------------
trunk/include/vidcap/vidcap.h
trunk/src/directshow/SourceStateMachine.cpp
trunk/src/sapi.c
trunk/src/sapi.h
Modified: trunk/include/vidcap/vidcap.h
===================================================================
--- trunk/include/vidcap/vidcap.h 2007-11-26 18:22:32 UTC (rev 67)
+++ trunk/include/vidcap/vidcap.h 2007-11-26 18:32:38 UTC (rev 68)
@@ -73,7 +73,7 @@
struct vidcap_capture_info
{
- const char * video_data;
+ char * video_data;
int video_data_size;
int error_status;
};
Modified: trunk/src/directshow/SourceStateMachine.cpp
===================================================================
--- trunk/src/directshow/SourceStateMachine.cpp 2007-11-26 18:22:32 UTC (rev 67)
+++ trunk/src/directshow/SourceStateMachine.cpp 2007-11-26 18:32:38 UTC (rev 68)
@@ -521,7 +521,7 @@
}
int ret = sapi_src_capture_notify(instance->sourceContext_,
- reinterpret_cast<const char *>(pBuff),
+ reinterpret_cast<char *>(pBuff),
static_cast<int>(buffSize), 0, 0);
instance->callbackInProgress_ = false;
Modified: trunk/src/sapi.c
===================================================================
--- trunk/src/sapi.c 2007-11-26 18:22:32 UTC (rev 67)
+++ trunk/src/sapi.c 2007-11-26 18:32:38 UTC (rev 68)
@@ -205,7 +205,7 @@
/* NOTE: stride-ignorant sapis should pass a stride of zero */
int
sapi_src_capture_notify(struct sapi_src_context * src_ctx,
- const char * video_data, int video_data_size,
+ char * video_data, int video_data_size,
int stride,
int error_status)
{
Modified: trunk/src/sapi.h
===================================================================
--- trunk/src/sapi.h 2007-11-26 18:22:32 UTC (rev 67)
+++ trunk/src/sapi.h 2007-11-26 18:32:38 UTC (rev 68)
@@ -46,7 +46,7 @@
int
sapi_src_capture_notify(struct sapi_src_context * src_ctx,
- const char * video_data, int video_data_size,
+ char * video_data, int video_data_size,
int stride,
int error_status);
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: libvidcap c. <lib...@li...> - 2007-11-26 19:33:09
|
Revision: 69
http://libvidcap.svn.sourceforge.net/libvidcap/?rev=69&view=rev
Author: bcholew
Date: 2007-11-26 11:32:59 -0800 (Mon, 26 Nov 2007)
Log Message:
-----------
Keep public video data const, and the internal not.
Modified Paths:
--------------
trunk/include/vidcap/vidcap.h
trunk/src/sapi.c
trunk/src/sapi_context.h
trunk/src/vidcap.c
Modified: trunk/include/vidcap/vidcap.h
===================================================================
--- trunk/include/vidcap/vidcap.h 2007-11-26 18:32:38 UTC (rev 68)
+++ trunk/include/vidcap/vidcap.h 2007-11-26 19:32:59 UTC (rev 69)
@@ -73,7 +73,7 @@
struct vidcap_capture_info
{
- char * video_data;
+ const char * video_data;
int video_data_size;
int error_status;
};
Modified: trunk/src/sapi.c
===================================================================
--- trunk/src/sapi.c 2007-11-26 18:32:38 UTC (rev 68)
+++ trunk/src/sapi.c 2007-11-26 19:32:59 UTC (rev 69)
@@ -219,15 +219,8 @@
if ( !frame )
return -1;
- frame->cap_info = malloc(sizeof(struct vidcap_capture_info));
- if ( !frame->cap_info )
- {
- free(frame);
- return -1;
- }
-
- frame->cap_info->video_data_size = video_data_size;
- frame->cap_info->error_status = error_status;
+ frame->video_data_size = video_data_size;
+ frame->error_status = error_status;
frame->stride = stride;
if ( src_ctx->use_timer_thread )
@@ -235,15 +228,14 @@
/* Copy this buffer. It might not exist long enough for
* read thread (capture timer thread) to copy it
*/
- frame->cap_info->video_data = malloc(video_data_size);
- if ( !frame->cap_info->video_data )
+ frame->video_data = malloc(video_data_size);
+ if ( !frame->video_data )
{
- free(frame->cap_info);
free(frame);
return -1;
}
- memcpy(frame->cap_info->video_data, video_data, video_data_size);
+ memcpy(frame->video_data, video_data, video_data_size);
/* buffer the frame - for processing by the timer thread */
double_buffer_insert(src_ctx->double_buff, frame);
@@ -256,7 +248,7 @@
}
else
{
- frame->cap_info->video_data = video_data;
+ frame->video_data = video_data;
/* process the frame now */
src_ctx->no_timer_thread_frame = frame;
@@ -303,10 +295,10 @@
frame = src_ctx->no_timer_thread_frame;
}
- video_data = frame->cap_info->video_data;
- video_data_size = frame->cap_info->video_data_size;
+ video_data = frame->video_data;
+ video_data_size = frame->video_data_size;
stride = frame->stride;
- error_status = frame->cap_info->error_status;
+ error_status = frame->error_status;
/* FIXME: right now enforce_framerate() and the capture timer
* thread's main loop BOTH use the frame_time_next field
@@ -381,8 +373,7 @@
if ( src_ctx->use_timer_thread )
{
/* delete frame */
- free(frame->cap_info->video_data);
- free(frame->cap_info);
+ free(frame->video_data);
free(frame);
if ( error_status )
Modified: trunk/src/sapi_context.h
===================================================================
--- trunk/src/sapi_context.h 2007-11-26 18:32:38 UTC (rev 68)
+++ trunk/src/sapi_context.h 2007-11-26 19:32:59 UTC (rev 69)
@@ -36,7 +36,9 @@
struct frame_info
{
- struct vidcap_capture_info *cap_info;
+ char * video_data;
+ int video_data_size;
+ int error_status;
int stride;
};
Modified: trunk/src/vidcap.c
===================================================================
--- trunk/src/vidcap.c 2007-11-26 18:32:38 UTC (rev 68)
+++ trunk/src/vidcap.c 2007-11-26 19:32:59 UTC (rev 69)
@@ -551,9 +551,7 @@
{
struct frame_info *frame = (struct frame_info *)fr;
- /* FIXME: unconstify video_data */
- free(frame->cap_info->video_data);
- free(frame->cap_info);
+ free(frame->video_data);
free(frame);
}
@@ -567,28 +565,19 @@
if ( !dup_frame )
return 0;
- dup_frame->cap_info = calloc(1, sizeof(*dup_frame->cap_info));
- if ( !dup_frame->cap_info )
- {
- free(dup_frame);
- return 0;
- }
-
dup_frame->stride = frame->stride;
- dup_frame->cap_info->error_status = frame->cap_info->error_status;
- dup_frame->cap_info->video_data_size = frame->cap_info->video_data_size;
- dup_frame->cap_info->video_data = malloc(frame->cap_info->video_data_size);
- if ( !dup_frame->cap_info->video_data )
+ dup_frame->error_status = frame->error_status;
+ dup_frame->video_data_size = frame->video_data_size;
+ dup_frame->video_data = malloc(frame->video_data_size);
+ if ( !dup_frame->video_data )
{
- free(dup_frame->cap_info);
free(dup_frame);
return 0;
}
- /* FIXME: unconstify cap_info->video_data */
- memcpy(dup_frame->cap_info->video_data,
- frame->cap_info->video_data,
- frame->cap_info->video_data_size);
+ memcpy(dup_frame->video_data,
+ frame->video_data,
+ frame->video_data_size);
return dup_frame;
}
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: libvidcap c. <lib...@li...> - 2007-12-03 17:18:54
|
Revision: 75
http://libvidcap.svn.sourceforge.net/libvidcap/?rev=75&view=rev
Author: bcholew
Date: 2007-12-03 09:18:46 -0800 (Mon, 03 Dec 2007)
Log Message:
-----------
Patch by Taybin Rutkin to compile under cygwin. Thanks.
Modified Paths:
--------------
trunk/configure.ac
trunk/examples/simplegrab.c
Modified: trunk/configure.ac
===================================================================
--- trunk/configure.ac 2007-12-03 14:11:12 UTC (rev 74)
+++ trunk/configure.ac 2007-12-03 17:18:46 UTC (rev 75)
@@ -44,7 +44,7 @@
PKG_PROG_PKG_CONFIG
-AC_CHECK_FUNCS(nanosleep gettimeofday snprintf Sleep)
+AC_CHECK_FUNCS(nanosleep gettimeofday snprintf)
AC_CHECK_HEADER(linux/videodev.h,
have_v4l=yes, have_v4l=no)
Modified: trunk/examples/simplegrab.c
===================================================================
--- trunk/examples/simplegrab.c 2007-12-03 14:11:12 UTC (rev 74)
+++ trunk/examples/simplegrab.c 2007-12-03 17:18:46 UTC (rev 75)
@@ -135,7 +135,7 @@
nanosleep(&tv, 0);
-#elif defined(HAVE_SLEEP)
+#elif defined(_WIN32)
Sleep(milliseconds);
#else
#error No sleep function available.
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|
|
From: libvidcap c. <lib...@li...> - 2007-12-12 20:55:27
|
Revision: 84
http://libvidcap.svn.sourceforge.net/libvidcap/?rev=84&view=rev
Author: bcholew
Date: 2007-12-12 12:55:11 -0800 (Wed, 12 Dec 2007)
Log Message:
-----------
A bunch of changes - including some from Pete Grayson. Add capture time to capture callback data. Wrap gettimeofday() with new vc_now() function. Log malloc errors with log_oom(). Make some functions static. Replace double-buffer malloc()s with memcpy()s. Renamed double_buffer_insert() to double_buffer_write(). Change some info messages to debug. Some cleanup.
Modified Paths:
--------------
trunk/include/vidcap/vidcap.h
trunk/src/double_buffer.c
trunk/src/double_buffer.h
trunk/src/os_funcs.h
trunk/src/sapi.c
trunk/src/sapi_context.h
trunk/src/vidcap.c
Modified: trunk/include/vidcap/vidcap.h
===================================================================
--- trunk/include/vidcap/vidcap.h 2007-12-12 20:46:06 UTC (rev 83)
+++ trunk/include/vidcap/vidcap.h 2007-12-12 20:55:11 UTC (rev 84)
@@ -76,6 +76,8 @@
const char * video_data;
int video_data_size;
int error_status;
+ long capture_time_sec;
+ long capture_time_usec;
};
typedef int (*vidcap_src_capture_callback) (vidcap_src *,
Modified: trunk/src/double_buffer.c
===================================================================
--- trunk/src/double_buffer.c 2007-12-12 20:46:06 UTC (rev 83)
+++ trunk/src/double_buffer.c 2007-12-12 20:55:11 UTC (rev 84)
@@ -41,16 +41,15 @@
* to make room for an incoming object
*/
-/* NOTE: This function is passed function pointers to call when
- * necessary to free or copy an object
+/* NOTE: This function is passed a function pointer to
+ * call when necessary to copy an object
*/
struct double_buffer *
-double_buffer_create( void (*free_me)(void *), void * (*copy_me)(void *) )
+double_buffer_create( void (*copy_func)(void *, const void *), void *object1, void *object2 )
{
-
struct double_buffer * db_buff;
- if ( !free_me || !copy_me )
+ if ( !copy_func )
return 0;
db_buff = calloc(1, sizeof(*db_buff));
@@ -65,11 +64,10 @@
db_buff->write_count = 0;
db_buff->count[0] = -1;
db_buff->count[1] = -1;
- db_buff->objects[0] = 0;
- db_buff->objects[1] = 0;
+ db_buff->objects[0] = object1;
+ db_buff->objects[1] = object2;
- db_buff->free_object = free_me;
- db_buff->copy_object = copy_me;
+ db_buff->copy_object = copy_func;
vc_mutex_init(&db_buff->locks[0]);
vc_mutex_init(&db_buff->locks[1]);
@@ -86,33 +84,18 @@
vc_mutex_destroy(&db_buff->locks[1]);
vc_mutex_destroy(&db_buff->locks[0]);
- if ( db_buff->write_count > 0 )
- db_buff->free_object(db_buff->objects[0]);
+ log_debug("Double buffer had counter reading of %d\n",
+ db_buff->num_insert_too_far_failures);
- if ( db_buff->write_count > 1 )
- db_buff->free_object(db_buff->objects[1]);
-
free(db_buff);
}
void
-double_buffer_insert(struct double_buffer * db_buff, void * new_object)
+double_buffer_write(struct double_buffer * db_buff, const void * new_object)
{
const int insertion_index = db_buff->write_count % 2;
- /* TODO: we could eliminate a copy by having the reader free
- * all buffered objects. This would require that a failed
- * check below result in the object being freed. This
- * would ensure that the reader sees all BUFFERED objects.
- *
- * The reader would then need to take care to free objects
- * as they become outdated.
- *
- * The tradeoff is the occasional dropped object when
- * the writer gets ahead a little. The counter can help
- * to evaluate the cost of this tradeoff
- */
- /* don't get far ahead of the reader*/
+ /* don't get far ahead of the reader */
if ( db_buff->write_count > ( db_buff->read_count + 2 ) )
{
db_buff->num_insert_too_far_failures++;
@@ -124,18 +107,13 @@
{
/* failed to obtain lock */
/* drop incoming object */
- log_info("vidcap callback failed to write a frame\n");
- db_buff->free_object(new_object);
+ log_info("callback is skipping a frame\n");
return;
}
- /* free the slot object if something is already there */
- if ( db_buff->write_count > 1 )
- db_buff->free_object(db_buff->objects[insertion_index]);
+ /* copy object */
+ db_buff->copy_object(db_buff->objects[insertion_index], new_object);
- /* insert object */
- db_buff->objects[insertion_index] = new_object;
-
/* stamp the buffer with the write count */
db_buff->count[insertion_index] = db_buff->write_count;
@@ -146,14 +124,13 @@
vc_mutex_unlock(&db_buff->locks[insertion_index]);
}
-void *
-double_buffer_read(struct double_buffer * db_buff)
+int
+double_buffer_read(struct double_buffer * db_buff, void *dest_buffer)
{
int copy_index = db_buff->read_count % 2;
- void * buff;
if ( db_buff->write_count < 1 )
- return 0;
+ return -1;
/* try the next buffer */
if ( db_buff->count[copy_index] < db_buff->read_count )
@@ -162,14 +139,13 @@
copy_index = 1 - copy_index;
}
-
if ( vc_mutex_trylock(&db_buff->locks[copy_index] ) )
{
- /* Failed to obtain lock.
- * Try the other slot?
+ /* Failed to obtain buffer's lock.
+ * Try the other buffer?
*/
if ( db_buff->write_count < 2 )
- return 0;
+ return -1;
copy_index = 1 - copy_index;
@@ -177,14 +153,15 @@
{
/* Too old. Don't read this buffer */
vc_mutex_unlock(&db_buff->locks[copy_index]);
- return 0;
+ log_info("Capture timer thread failed to obtain lock\n");
+ return -1;
}
/* Try other lock. Failure should be rare */
if ( vc_mutex_trylock(&db_buff->locks[copy_index] ) )
{
log_info("Capture timer thread failed to obtain 2nd lock\n");
- return 0;
+ return -1;
}
}
@@ -195,16 +172,17 @@
* This needs to be rare.
*/
vc_mutex_unlock(&db_buff->locks[copy_index]);
- return 0;
+ log_info("Capture timer thread won't read stale buffer\n");
+ return -1;
}
- buff = db_buff->copy_object(db_buff->objects[copy_index]);
+ db_buff->copy_object(dest_buffer, db_buff->objects[copy_index]);
db_buff->read_count = db_buff->count[copy_index] + 1;
vc_mutex_unlock(&db_buff->locks[copy_index]);
- return buff;
+ return 0;
}
int
Modified: trunk/src/double_buffer.h
===================================================================
--- trunk/src/double_buffer.h 2007-12-12 20:46:06 UTC (rev 83)
+++ trunk/src/double_buffer.h 2007-12-12 20:55:11 UTC (rev 84)
@@ -39,25 +39,23 @@
int count[_DOUBLE_MEANS_TWO_];
- void * (*copy_object)(void *);
- void (*free_object)(void *);
+ void (*copy_object)(void *, const void *);
/* TODO: remove */
int num_insert_too_far_failures;
};
struct double_buffer *
-double_buffer_create( void (*free_obj_func)(void *),
- void * (*copy_object)(void *));
+double_buffer_create(void (*copy_object)(void *, const void *), void *, void *);
void
double_buffer_destroy(struct double_buffer * db_buff);
void
-double_buffer_insert(struct double_buffer * db_buff, void * object);
+double_buffer_write(struct double_buffer * db_buff, const void * object);
-void *
-double_buffer_read(struct double_buffer * db_buff);
+int
+double_buffer_read(struct double_buffer * db_buff, void * object);
int
double_buffer_count(struct double_buffer * db_buff);
Modified: trunk/src/os_funcs.h
===================================================================
--- trunk/src/os_funcs.h 2007-12-12 20:46:06 UTC (rev 83)
+++ trunk/src/os_funcs.h 2007-12-12 20:55:11 UTC (rev 84)
@@ -79,38 +79,33 @@
#include <sys/sysctl.h>
#endif
-#ifndef HAVE_GETTIMEOFDAY
-static __inline int
-gettimeofday(struct timeval * tv, struct timezone * tz)
-#ifdef WIN32
+static __inline struct timeval
+vc_now(void)
{
+ struct timeval tv;
+#ifdef HAVE_GETTIMEOFDAY
+ gettimeofday(&tv, 0);
+#elif defined(WIN32)
FILETIME ft;
LARGE_INTEGER li;
__int64 t;
static int tzflag;
const __int64 EPOCHFILETIME = 116444736000000000i64;
- if ( tv )
- {
- GetSystemTimeAsFileTime(&ft);
- li.LowPart = ft.dwLowDateTime;
- li.HighPart = ft.dwHighDateTime;
- t = li.QuadPart; /* In 100-nanosecond intervals */
- t -= EPOCHFILETIME; /* Offset to the Epoch time */
- t /= 10; /* In microseconds */
- tv->tv_sec = (long)(t / 1000000);
- tv->tv_usec = (long)(t % 1000000);
- }
- return 0;
-
-#else /* !defined(_WINDOWS) */
- errno = ENOSYS;
- return -1;
+ GetSystemTimeAsFileTime(&ft);
+ li.LowPart = ft.dwLowDateTime;
+ li.HighPart = ft.dwHighDateTime;
+ t = li.QuadPart; /* In 100-nanosecond intervals */
+ t -= EPOCHFILETIME; /* Offset to the Epoch time */
+ t /= 10; /* In microseconds */
+ tv.tv_sec = (long)(t / 1000000);
+ tv.tv_usec = (long)(t % 1000000);
+#else
+#error no gettimeofday or equivalent available
#endif
+ return tv;
}
-#endif /* !defined(HAVE_GETTIMEOFDAY) */
-
static __inline int
vc_create_thread(vc_thread *thread,
unsigned int (STDCALL * thread_func)(void *),
Modified: trunk/src/sapi.c
===================================================================
--- trunk/src/sapi.c 2007-12-12 20:46:06 UTC (rev 83)
+++ trunk/src/sapi.c 2007-12-12 20:55:11 UTC (rev 84)
@@ -30,9 +30,6 @@
#include "logging.h"
#include "sapi.h"
-static int
-deliver_frame(struct sapi_src_context * src_ctx);
-
static __inline int
tv_greater_or_equal(struct timeval * t1, struct timeval * t0)
{
@@ -73,8 +70,7 @@
first_time = !sliding_window_count(src_ctx->frame_times);
- if ( gettimeofday(&tv_now, 0) )
- return -1;
+ tv_now = vc_now();
if ( !first_time && !tv_greater_or_equal(
&tv_now, &src_ctx->frame_time_next) )
@@ -202,76 +198,6 @@
src_ctx->capture_error_ack = 1;
}
-/* NOTE: stride-ignorant sapis should pass a stride of zero */
-int
-sapi_src_capture_notify(struct sapi_src_context * src_ctx,
- char * video_data, int video_data_size,
- int stride,
- int error_status)
-{
- /* NOTE: We may be called here by the capture thread while the
- * main thread is clearing capture_data and capture_callback
- * from within vidcap_src_capture_stop().
- */
-
- /* Package the video information */
- struct frame_info * frame = malloc(sizeof(*frame));
- if ( !frame )
- return -1;
-
- /* Screen-out useless callbacks */
- if ( video_data_size < 1 && !error_status )
- {
- log_info("callback with no data?\n");
- return 0;
- }
-
- frame->video_data_size = video_data_size;
- frame->error_status = error_status;
- frame->stride = stride;
-
- if ( src_ctx->use_timer_thread )
- {
- /* Copy this buffer. It might not exist long enough for
- * read thread (capture timer thread) to copy it
- */
- frame->video_data = malloc(video_data_size);
- if ( !frame->video_data )
- {
- free(frame);
- return -1;
- }
-
- memcpy(frame->video_data, video_data, video_data_size);
-
- /* buffer the frame - for processing by the timer thread */
- double_buffer_insert(src_ctx->double_buff, frame);
-
- /* If there's an error, wait here until it's acknowledged
- * by the timer thread (after having delivered it to the app).
- */
- if ( error_status )
- wait_for_error_ack(src_ctx);
- }
- else
- {
- frame->video_data = video_data;
-
- /* process the frame now */
- src_ctx->no_timer_thread_frame = frame;
- deliver_frame(src_ctx);
- }
-
- if ( error_status )
- {
- src_ctx->src_state = src_bound;
- src_ctx->capture_callback = 0;
- src_ctx->capture_data = VIDCAP_INVALID_USER_DATA;
- }
-
- return 0;
-}
-
static int
deliver_frame(struct sapi_src_context * src_ctx)
{
@@ -283,7 +209,7 @@
struct vidcap_capture_info cap_info;
- struct frame_info * frame;
+ const struct frame_info * frame;
const char * video_data;
int video_data_size;
int stride;
@@ -291,21 +217,23 @@
if ( src_ctx->use_timer_thread )
{
- frame = (struct frame_info *)
- double_buffer_read(src_ctx->double_buff);
-
- if ( !frame )
+ if ( double_buffer_read(src_ctx->double_buff,
+ &src_ctx->timer_thread_frame) )
return -1;
+
+ frame = &src_ctx->timer_thread_frame;
}
else
{
- frame = src_ctx->no_timer_thread_frame;
+ frame = &src_ctx->callback_frame;
}
video_data = frame->video_data;
video_data_size = frame->video_data_size;
stride = frame->stride;
error_status = frame->error_status;
+ cap_info.capture_time_sec = frame->capture_time.tv_sec;
+ cap_info.capture_time_usec = frame->capture_time.tv_usec;
/* FIXME: right now enforce_framerate() and the capture timer
* thread's main loop BOTH use the frame_time_next field
@@ -379,10 +307,6 @@
if ( src_ctx->use_timer_thread )
{
- /* delete frame */
- free(frame->video_data);
- free(frame);
-
if ( error_status )
{
/* Let capture thread know that the app
@@ -400,11 +324,66 @@
return 0;
}
+/* NOTE: stride-ignorant sapis should pass a stride of zero */
+int
+sapi_src_capture_notify(struct sapi_src_context * src_ctx,
+ char * video_data, int video_data_size,
+ int stride,
+ int error_status)
+{
+ /* NOTE: We may be called here by the capture thread while the
+ * main thread is clearing capture_data and capture_callback
+ * from within vidcap_src_capture_stop().
+ */
+
+ struct frame_info *frame = &src_ctx->callback_frame;
+
+ /* Screen-out useless callbacks */
+ if ( video_data_size < 1 && !error_status )
+ {
+ log_info("callback with no data?\n");
+ return 0;
+ }
+
+ /* Package the video information */
+ frame->video_data_size = video_data_size;
+ frame->error_status = error_status;
+ frame->stride = stride;
+ frame->capture_time = vc_now();
+ frame->video_data = video_data;
+
+ if ( src_ctx->use_timer_thread )
+ {
+ /* buffer the frame - for processing by the timer thread */
+ double_buffer_write(src_ctx->double_buff, frame);
+
+ /* If there's an error, wait here until it's acknowledged
+ * by the timer thread (after having delivered it to the app).
+ */
+ if ( error_status )
+ wait_for_error_ack(src_ctx);
+ }
+ else
+ {
+ /* process the frame now */
+ deliver_frame(src_ctx);
+ }
+
+ if ( error_status )
+ {
+ src_ctx->src_state = src_bound;
+ src_ctx->capture_callback = 0;
+ src_ctx->capture_data = VIDCAP_INVALID_USER_DATA;
+ }
+
+ return 0;
+}
+
unsigned int
STDCALL sapi_src_timer_thread_func(void *args)
{
struct sapi_src_context * src_ctx = args;
- struct timeval tv_now;
+ struct timeval tv_now;
const long idle_state_sleep_period_ms = 100;
long sleep_ms = idle_state_sleep_period_ms;
int first_time = 1;
@@ -414,12 +393,7 @@
src_ctx->timer_thread_idle = 1;
- if ( gettimeofday(&tv_now, 0) )
- {
- src_ctx->capture_timer_thread_started = -1;
- log_error("gettimeofday not supported\n");
- return -1;
- }
+ tv_now = vc_now();
src_ctx->frame_time_next.tv_sec = tv_now.tv_sec;
src_ctx->frame_time_next.tv_usec = tv_now.tv_usec;
@@ -428,7 +402,7 @@
while ( !src_ctx->kill_timer_thread )
{
- gettimeofday(&tv_now, 0);
+ tv_now = vc_now();
/* sleep or read? */
if ( capture_error || src_ctx->src_state != src_capturing ||
Modified: trunk/src/sapi_context.h
===================================================================
--- trunk/src/sapi_context.h 2007-12-12 20:46:06 UTC (rev 83)
+++ trunk/src/sapi_context.h 2007-12-12 20:55:11 UTC (rev 84)
@@ -40,6 +40,7 @@
int video_data_size;
int error_status;
int stride;
+ struct timeval capture_time;
};
struct sapi_src_context
@@ -79,8 +80,11 @@
vidcap_src_capture_callback capture_callback;
void * capture_data;
+ struct frame_info buffered_frames[2];
+ struct frame_info timer_thread_frame;
+
int use_timer_thread;
- struct frame_info * no_timer_thread_frame;
+ struct frame_info callback_frame;
vc_thread capture_timer_thread;
unsigned int capture_timer_thread_id;
int capture_timer_thread_started;
Modified: trunk/src/vidcap.c
===================================================================
--- trunk/src/vidcap.c 2007-12-12 20:46:06 UTC (rev 83)
+++ trunk/src/vidcap.c 2007-12-12 20:55:11 UTC (rev 84)
@@ -338,7 +338,7 @@
goto bail;
}
- log_info("using a capture timer thread for this source\n");
+ log_debug("using a capture timer thread for this source\n");
}
if ( sapi_ctx->acquire_source(sapi_ctx, src_ctx, src_info) )
@@ -528,7 +528,7 @@
return -1;
}
- log_info("format bind requires conversion: %s\n",
+ log_debug("format bind requires conversion: %s\n",
conv_conversion_name_get(src_ctx->fmt_conv_func));
}
@@ -546,40 +546,20 @@
return 0;
}
-void
-free_frame_info(void * fr)
+static __inline void
+copy_frame_info(void * fr2, const void *fr1)
{
- struct frame_info *frame = (struct frame_info *)fr;
+ const struct frame_info *frame_orig = (struct frame_info *)fr1;
+ struct frame_info *frame_dup = (struct frame_info *)fr2;
- free(frame->video_data);
- free(frame);
-}
+ frame_dup->capture_time = frame_orig->capture_time;
+ frame_dup->error_status = frame_orig->error_status;
+ frame_dup->stride = frame_orig->stride;
+ frame_dup->video_data_size = frame_orig->video_data_size;
-void *
-copy_frame_info(void * fr)
-{
- struct frame_info *frame = (struct frame_info *)fr;
-
- struct frame_info *dup_frame = malloc(sizeof(*dup_frame));
-
- if ( !dup_frame )
- return 0;
-
- dup_frame->stride = frame->stride;
- dup_frame->error_status = frame->error_status;
- dup_frame->video_data_size = frame->video_data_size;
- dup_frame->video_data = malloc(frame->video_data_size);
- if ( !dup_frame->video_data )
- {
- free(dup_frame);
- return 0;
- }
-
- memcpy(dup_frame->video_data,
- frame->video_data,
- frame->video_data_size);
-
- return dup_frame;
+ memcpy(frame_dup->video_data,
+ frame_orig->video_data,
+ frame_orig->video_data_size);
}
int
@@ -587,54 +567,108 @@
vidcap_src_capture_callback callback,
void * user_data)
{
- int ret;
+ int ret = 0;
struct sapi_src_context * src_ctx = (struct sapi_src_context *)src;
const int sliding_window_seconds = 4;
+ /* Assume worst-case video data with stride is 50%
+ * bigger than without a stride.
+ */
+ /* FIXME: Defer measurement of stride-full
+ * buffer until first capture callback
+ */
+ const int stride_full_buf_size = src_ctx->stride_free_buf_size * 3 / 2;
+
if ( user_data == VIDCAP_INVALID_USER_DATA )
return -3;
if ( src_ctx->src_state != src_bound )
return -4;
- src_ctx->frame_time_next.tv_sec = 0;
- src_ctx->frame_time_next.tv_usec = 0;
- src_ctx->frame_times = sliding_window_create(sliding_window_seconds *
- src_ctx->fmt_nominal.fps_numerator /
- src_ctx->fmt_nominal.fps_denominator,
- sizeof(struct timeval));
+ memset(src_ctx->buffered_frames, 0, sizeof(src_ctx->buffered_frames));
+ src_ctx->timer_thread_frame.video_data = 0;
+ src_ctx->frame_times = 0;
+ src_ctx->double_buff = 0;
- if ( !src_ctx->frame_times )
- return -2;
+ if ( src_ctx->use_timer_thread )
+ {
+ /* allocate space for double-buffering video buffers */
+ src_ctx->buffered_frames[0].video_data =
+ malloc(2 * stride_full_buf_size);
+ if ( !src_ctx->buffered_frames[0].video_data )
+ {
+ log_oom(__FILE__, __LINE__);
+ ret = -6;
+ goto capture_start_bail;
+ }
- src_ctx->double_buff = double_buffer_create(&free_frame_info,
- ©_frame_info);
+ src_ctx->buffered_frames[1].video_data =
+ src_ctx->buffered_frames[0].video_data +
+ stride_full_buf_size;
- if ( !src_ctx->double_buff )
+ src_ctx->timer_thread_frame.video_data =
+ malloc(stride_full_buf_size);
+ if ( !src_ctx->timer_thread_frame.video_data )
+ {
+ log_oom(__FILE__, __LINE__);
+ ret = -6;
+ goto capture_start_bail;
+ }
+
+ src_ctx->double_buff = double_buffer_create(©_frame_info,
+ &src_ctx->buffered_frames[0], &src_ctx->buffered_frames[1]);
+ if ( !src_ctx->double_buff )
+ {
+ ret = -5;
+ goto capture_start_bail;
+ }
+ }
+ else
{
- sliding_window_destroy(src_ctx->frame_times);
- src_ctx->frame_times = 0;
- return -5;
+ src_ctx->frame_time_next.tv_sec = 0;
+ src_ctx->frame_time_next.tv_usec = 0;
+ src_ctx->frame_times = sliding_window_create(sliding_window_seconds *
+ src_ctx->fmt_nominal.fps_numerator /
+ src_ctx->fmt_nominal.fps_denominator,
+ sizeof(struct timeval));
+
+ if ( !src_ctx->frame_times )
+ return -2;
}
src_ctx->capture_callback = callback;
src_ctx->capture_data = user_data;
if ( (ret = src_ctx->start_capture(src_ctx)) )
- {
- src_ctx->capture_callback = 0;
- src_ctx->capture_data = VIDCAP_INVALID_USER_DATA;
+ goto capture_start_bail;
+ src_ctx->src_state = src_capturing;
+ return 0;
+
+capture_start_bail:
+
+ src_ctx->capture_callback = 0;
+ src_ctx->capture_data = VIDCAP_INVALID_USER_DATA;
+
+ if ( src_ctx->double_buff )
double_buffer_destroy(src_ctx->double_buff);
- src_ctx->double_buff = 0;
+ if ( src_ctx->buffered_frames[0].video_data )
+ free(src_ctx->buffered_frames[0].video_data);
+
+ if ( src_ctx->buffered_frames[1].video_data )
+ free(src_ctx->buffered_frames[1].video_data);
+
+ if ( src_ctx->timer_thread_frame.video_data )
+ free(src_ctx->timer_thread_frame.video_data);
+
+ if ( src_ctx->frame_times )
sliding_window_destroy(src_ctx->frame_times);
- src_ctx->frame_times = 0;
- return ret;
- }
- src_ctx->src_state = src_capturing;
- return 0;
+ src_ctx->double_buff = 0;
+ src_ctx->frame_times = 0;
+
+ return ret;
}
int
@@ -657,10 +691,21 @@
sapi_src_timer_thread_idled(src_ctx);
}
- double_buffer_destroy(src_ctx->double_buff);
+ if ( src_ctx->double_buff )
+ double_buffer_destroy(src_ctx->double_buff);
src_ctx->double_buff = 0;
- sliding_window_destroy(src_ctx->frame_times);
+ if ( src_ctx->buffered_frames[0].video_data )
+ free(src_ctx->buffered_frames[0].video_data);
+
+ if ( src_ctx->buffered_frames[1].video_data )
+ free(src_ctx->buffered_frames[1].video_data);
+
+ if ( src_ctx->timer_thread_frame.video_data )
+ free(src_ctx->timer_thread_frame.video_data);
+
+ if ( src_ctx->frame_times )
+ sliding_window_destroy(src_ctx->frame_times);
src_ctx->frame_times = 0;
src_ctx->capture_callback = 0;
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|