You can subscribe to this list here.
2007 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(32) |
Oct
(26) |
Nov
(8) |
Dec
(17) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2008 |
Jan
|
Feb
|
Mar
|
Apr
(8) |
May
|
Jun
(1) |
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2009 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
(1) |
Sep
(2) |
Oct
(1) |
Nov
|
Dec
|
2010 |
Jan
|
Feb
(5) |
Mar
(2) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: libvidcap c. <lib...@li...> - 2010-03-09 18:35:51
|
Revision: 107 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=107&view=rev Author: kretikus Date: 2010-03-09 18:35:43 +0000 (Tue, 09 Mar 2010) Log Message: ----------- * first commit to get v4l2 support for libvidcap What is working: - Detection if device supports v4l2 - Scanning device capabilities - Setting desired video format Modified Paths: -------------- branches/v4l2_support/src/Makefile.am branches/v4l2_support/src/sapi_v4l.c Added Paths: ----------- branches/v4l2_support/src/v4l/ branches/v4l2_support/src/v4l/v4l1_backend.c branches/v4l2_support/src/v4l/v4l2_backend.c branches/v4l2_support/src/v4l/v4l_ctx.h Modified: branches/v4l2_support/src/Makefile.am =================================================================== --- branches/v4l2_support/src/Makefile.am 2010-03-09 18:21:45 UTC (rev 106) +++ branches/v4l2_support/src/Makefile.am 2010-03-09 18:35:43 UTC (rev 107) @@ -34,7 +34,11 @@ vidcap.c if HAVE_V4L -libvidcap_la_SOURCES += sapi_v4l.c +libvidcap_la_SOURCES += \ + v4l/v4l_ctx.h \ + v4l/v4l1_backend.c \ + v4l/v4l2_backend.c \ + sapi_v4l.c endif if HAVE_QUICKTIME Modified: branches/v4l2_support/src/sapi_v4l.c =================================================================== --- branches/v4l2_support/src/sapi_v4l.c 2010-03-09 18:21:45 UTC (rev 106) +++ branches/v4l2_support/src/sapi_v4l.c 2010-03-09 18:35:43 UTC (rev 107) @@ -25,56 +25,16 @@ #include <errno.h> #include <fcntl.h> -#include <linux/videodev.h> #include <stdlib.h> #include <string.h> -#include <sys/ioctl.h> -#include <sys/mman.h> -#include <unistd.h> -#include "conv.h" -#include "hotlist.h" -#include "logging.h" -#include "sapi.h" +#include "v4l/v4l_ctx.h" + static const char * identifier = "video4linux"; static const char * description = "Video for Linux (v4l) video capture API"; -enum -{ - device_path_max = 128, - device_num_max = 16, - v4l_fps_mask = 0x003f0000, - v4l_fps_shift = 16, -}; -struct sapi_v4l_context -{ - vc_mutex mutex; - vc_thread notify_thread; - unsigned int notify_thread_id; - int notifying; - struct sapi_src_list acquired_src_list; -}; - -struct sapi_v4l_src_context -{ - struct sapi_v4l_context * v4l_ctx; - - int fd; - char device_path[device_path_max]; - int channel; - - struct video_capability caps; - struct video_picture picture; - struct video_window window; - struct video_mbuf mbuf; - - int capturing; - vc_thread capture_thread; - unsigned int capture_thread_id; -}; - static int parse_src_identifier(const char * identifier, char * device_path, @@ -118,81 +78,7 @@ return 0; } -static int -map_fourcc_to_palette(int fourcc, __u16 * palette) -{ - switch ( fourcc ) - { - case VIDCAP_FOURCC_I420: - *palette = VIDEO_PALETTE_YUV420P; - break; - case VIDCAP_FOURCC_RGB24: - *palette = VIDEO_PALETTE_RGB24; - break; - - case VIDCAP_FOURCC_YUY2: - *palette = VIDEO_PALETTE_YUYV; - break; - - case VIDCAP_FOURCC_2VUY: - *palette = VIDEO_PALETTE_UYVY; - break; - - case VIDCAP_FOURCC_RGB32: - *palette = VIDEO_PALETTE_RGB32; - break; - - case VIDCAP_FOURCC_RGB555: - *palette = VIDEO_PALETTE_RGB555; - break; - - case VIDCAP_FOURCC_YVU9: - return 1; - - default: - return -1; - } - - return 0; -} - -static int -map_palette_to_fourcc(__u16 palette, int * fourcc) -{ - switch ( palette ) - { - case VIDEO_PALETTE_YUV420P: - *fourcc = VIDCAP_FOURCC_I420; - break; - - case VIDEO_PALETTE_RGB24: - *fourcc = VIDCAP_FOURCC_RGB24; - break; - - case VIDEO_PALETTE_YUYV: - *fourcc = VIDCAP_FOURCC_YUY2; - break; - - case VIDEO_PALETTE_UYVY: - *fourcc = VIDCAP_FOURCC_2VUY; - break; - - case VIDEO_PALETTE_RGB32: - *fourcc = VIDCAP_FOURCC_RGB32; - break; - - case VIDEO_PALETTE_RGB555: - *fourcc = VIDCAP_FOURCC_RGB555; - break; - - default: - return -1; - } - - return 0; -} - #if 0 static void src_list_debug(const struct sapi_src_list * src_list, const char * name) @@ -314,7 +200,7 @@ return 0; } -static int +int src_list_device_append(struct sapi_src_list * src_list, const char * device_path, int channel, const char * device_name, const char * channel_name) @@ -332,6 +218,7 @@ return src_list_src_append(src_list, &src_info); } + static int src_list_device_scan(struct sapi_src_list * src_list, const char * device_path) @@ -339,56 +226,24 @@ int ret = 0; int fd; int i; - struct video_capability caps; - fd = open(device_path, O_RDONLY); + fd = open(device_path, O_RDONLY); - if ( fd == -1 ) + if ( fd == -1 ) { return 1; + } /* Ensures file descriptor is closed on exec() */ fcntl(fd, F_SETFD, FD_CLOEXEC); - memset(&caps, 0, sizeof(caps)); - if ( ioctl(fd, VIDIOCGCAP, &caps) == -1 ) - { - log_warn("failed to get capabilities for %s\n", device_path); - ret = -1; - goto bail; - } + if( is_v4l2_device(fd) ) { - if ( caps.type != VID_TYPE_CAPTURE ) - { - ret = -1; - goto bail; + ret = v4l2_src_list_device_scan( fd, src_list, device_path ); + } else { + ret = v4l1_src_list_device_scan( fd, src_list, device_path ); } - for ( i = 0; i < caps.channels; ++i ) - { - struct video_channel channel; - - memset(&channel, 0, sizeof(channel)); - - channel.channel = i; - - if ( ioctl(fd, VIDIOCGCHAN, &channel) == -1 ) - { - log_warn("failed VIDIOCGCHAN for %s\n", device_path); - continue; - } - - if ( src_list_device_append(src_list, device_path, - channel.channel, caps.name, - channel.name) ) - { - ret = -1; - goto bail; - } - } - -bail: - if ( close(fd) == -1 ) log_warn("failed to close fd %d for %s (%s)\n", fd, device_path, strerror(errno)); @@ -511,249 +366,9 @@ return src_list->len; } -static int -capture_kickoff(struct sapi_src_context * src_ctx, - unsigned int frame_count) -{ - struct sapi_v4l_src_context * v4l_src_ctx = - (struct sapi_v4l_src_context *)src_ctx->priv; - struct video_mmap vmap; - - vmap.frame = frame_count % v4l_src_ctx->mbuf.frames; - vmap.height = v4l_src_ctx->window.height; - vmap.width = v4l_src_ctx->window.width; - vmap.format = v4l_src_ctx->picture.palette; - - if ( ioctl(v4l_src_ctx->fd, VIDIOCMCAPTURE, &vmap) == -1 ) - { - log_error("failed VIDIOCMCAPTURE %d\n", errno); - return -1; - } - - return 0; -} - -static unsigned int -capture_thread_proc(void * data) +int common_source_release(struct sapi_src_context * src_ctx) { - struct sapi_src_context * src_ctx = - (struct sapi_src_context *)data; - struct sapi_v4l_src_context * v4l_src_ctx = - (struct sapi_v4l_src_context *)src_ctx->priv; - const int capture_size = conv_fmt_size_get( - src_ctx->fmt_native.width, - src_ctx->fmt_native.height, - src_ctx->fmt_native.fourcc); - - const char * fb_base = mmap(0, v4l_src_ctx->mbuf.size, - PROT_READ, MAP_SHARED, v4l_src_ctx->fd, 0); - - unsigned int started_frame_count = 0; - unsigned int capture_frame_count = 0; - - if ( fb_base == (void *)-1 ) - { - log_error("failed mmap() %d\n", errno); - return -1; - } - - if ( capture_kickoff(src_ctx, started_frame_count) ) - goto bail; - - while ( v4l_src_ctx->capturing ) - { - const unsigned int capture_frame = - capture_frame_count % v4l_src_ctx->mbuf.frames; - - if ( capture_kickoff(src_ctx, ++started_frame_count) ) - goto bail; - - if ( ioctl( v4l_src_ctx->fd, VIDIOCSYNC, - &capture_frame ) == -1 ) - { - log_error("failed VIDIOCSYNC %d\n", errno); - goto bail; - } - - sapi_src_capture_notify(src_ctx, (char *)(fb_base + - v4l_src_ctx->mbuf.offsets[capture_frame]), - capture_size, - 0, - 0); - - ++capture_frame_count; - } - - /* Sync with the last frame when capture has stopped (since we - * have overlapped capture kickoffs). - */ - { - const unsigned int capture_frame = - capture_frame_count % v4l_src_ctx->mbuf.frames; - - if ( ioctl( v4l_src_ctx->fd, VIDIOCSYNC, - &capture_frame ) == -1 ) - { - log_error("failed VIDIOCSYNC (2) %d\n", errno); - goto bail; - } - } - - - if ( munmap((void *)fb_base, v4l_src_ctx->mbuf.size) == -1 ) - { - log_error("failed munmap() %d\n", errno); - return -1; - } - - return 0; - -bail: - if ( munmap((void *)fb_base, v4l_src_ctx->mbuf.size) == -1 ) - log_warn("failed munmap() %d\n", errno); - - return -1; -} - -static int -source_capture_start(struct sapi_src_context * src_ctx) -{ - struct sapi_v4l_src_context * v4l_src_ctx = - (struct sapi_v4l_src_context *)src_ctx->priv; - int ret; - - v4l_src_ctx->capturing = 1; - - if ( (ret = vc_create_thread(&v4l_src_ctx->capture_thread, - capture_thread_proc, src_ctx, - &v4l_src_ctx->capture_thread_id)) ) - { - log_error("failed vc_create_thread() for capture thread %d\n", - ret); - return -1; - } - - return 0; -} - -static int -source_capture_stop(struct sapi_src_context * src_ctx) -{ - struct sapi_v4l_src_context * v4l_src_ctx = - (struct sapi_v4l_src_context *)src_ctx->priv; - int ret; - - v4l_src_ctx->capturing = 0; - - if ( (ret = vc_thread_join(&v4l_src_ctx->capture_thread)) ) - { - log_error("failed vc_thread_join() %d\n", ret); - return -1; - } - - return 0; -} - -static int -source_format_validate(struct sapi_src_context * src_ctx, - const struct vidcap_fmt_info * fmt_nominal, - struct vidcap_fmt_info * fmt_native, int forBinding ) -{ - struct sapi_v4l_src_context * v4l_src_ctx = - (struct sapi_v4l_src_context *)src_ctx->priv; - - *fmt_native = *fmt_nominal; - - __u16 palette; - - if ( fmt_nominal->width < v4l_src_ctx->caps.minwidth || - fmt_nominal->width > v4l_src_ctx->caps.maxwidth || - fmt_nominal->height < v4l_src_ctx->caps.minheight || - fmt_nominal->height > v4l_src_ctx->caps.maxheight ) - return 0; - - if ( map_fourcc_to_palette(fmt_nominal->fourcc, &palette) ) - return 0; - - if ( map_palette_to_fourcc(v4l_src_ctx->picture.palette, - &fmt_native->fourcc) ) - return 0; - - if ( !sapi_can_convert_native_to_nominal(fmt_native, fmt_nominal) ) - return 0; - - return 1; -} - -static int -source_format_bind(struct sapi_src_context * src_ctx, - const struct vidcap_fmt_info * fmt_info) -{ - struct sapi_v4l_src_context * v4l_src_ctx = - (struct sapi_v4l_src_context *)src_ctx->priv; - - memcpy(&src_ctx->fmt_native, fmt_info, sizeof(*fmt_info)); - - if ( map_palette_to_fourcc(v4l_src_ctx->picture.palette, - &src_ctx->fmt_native.fourcc) ) - { - log_warn("failed map_palette_to_fourcc %d\n", - v4l_src_ctx->picture.palette); - return -1; - } - - if ( ioctl(v4l_src_ctx->fd, VIDIOCSPICT, &v4l_src_ctx->picture) == -1 ) - { - log_warn("failed to set v4l picture parameters\n"); - return -1; - } - - /* Only set the parameters we know/care about. */ - v4l_src_ctx->window.x = 0; - v4l_src_ctx->window.y = 0; - v4l_src_ctx->window.width = fmt_info->width; - v4l_src_ctx->window.height = fmt_info->height; - /* TODO: for pwc, framerate is encoded in flags. For other - * cameras, who knows. - */ - v4l_src_ctx->window.flags = - (v4l_src_ctx->window.flags & ~v4l_fps_mask) | - (((src_ctx->fmt_native.fps_numerator / - src_ctx->fmt_native.fps_denominator) << v4l_fps_shift) & - v4l_fps_mask); - - if ( ioctl(v4l_src_ctx->fd, VIDIOCSWIN, &v4l_src_ctx->window) == -1 ) - { - log_warn("failed to set v4l window parameters x=%d y=%d " - "w=%d h=%d fl=0x%08x\n", - v4l_src_ctx->window.x, - v4l_src_ctx->window.y, - v4l_src_ctx->window.width, - v4l_src_ctx->window.height, - v4l_src_ctx->window.flags); - return -1; - } - - if ( ioctl(v4l_src_ctx->fd, VIDIOCGWIN, &v4l_src_ctx->window) == -1 ) - { - log_warn("failed to get v4l window parameters\n"); - return -1; - } - - if ( ioctl(v4l_src_ctx->fd, VIDIOCGMBUF, &v4l_src_ctx->mbuf) == -1 ) - { - log_warn("failed to get v4l memory info for %s\n", - v4l_src_ctx->device_path); - return -1; - } - - return 0; -} - -static int -source_release(struct sapi_src_context * src_ctx) -{ int ret = 0; struct sapi_v4l_src_context * v4l_src_ctx = @@ -786,6 +401,8 @@ return ret; } + + static int source_acquire(struct sapi_context * sapi_ctx, struct sapi_src_context * src_ctx, @@ -865,7 +482,7 @@ goto bail; } - v4l_src_ctx->fd = open(v4l_src_ctx->device_path, O_RDONLY); + v4l_src_ctx->fd = open(v4l_src_ctx->device_path, O_RDWR ); if ( v4l_src_ctx->fd == -1 ) { @@ -875,24 +492,14 @@ goto bail; } - if ( ioctl(v4l_src_ctx->fd, VIDIOCGCAP, &v4l_src_ctx->caps) == -1 ) - { - log_warn("failed to get v4l capability parameters for %s\n", - v4l_src_ctx->device_path); - goto bail; - } + int ret = 0; + if( is_v4l2_device(v4l_src_ctx->fd) ) { + ret = v4l2_source_acquire( src_ctx, v4l_src_ctx ); + } else { - if ( ioctl(v4l_src_ctx->fd, VIDIOCGWIN, &v4l_src_ctx->window) == -1 ) - { - log_warn("failed to get v4l window parameters for %s\n", - v4l_src_ctx->device_path); - goto bail; + ret = v4l1_source_acquire( src_ctx, v4l_src_ctx ); } - - if ( ioctl(v4l_src_ctx->fd, VIDIOCGPICT, &v4l_src_ctx->picture) == -1 ) - { - log_warn("failed to get v4l picture parameters for %s\n", - v4l_src_ctx->device_path); + if( ret == -1 ) { goto bail; } @@ -910,21 +517,17 @@ } v4l_src_ctx->capturing = 0; - - src_ctx->release = source_release; - src_ctx->format_validate = source_format_validate; - src_ctx->format_bind = source_format_bind; - src_ctx->start_capture = source_capture_start; - src_ctx->stop_capture = source_capture_stop; src_ctx->priv = v4l_src_ctx; return 0; + bail: free(v4l_src_ctx); return -1; } + static unsigned int notify_thread_proc(void * data) { @@ -955,6 +558,7 @@ return 0; } + static int notify_thread_stop(struct sapi_context * sapi_ctx) { @@ -973,6 +577,7 @@ return 0; } + static int monitor_sources(struct sapi_context * sapi_ctx) { @@ -997,6 +602,7 @@ return 0; } + static void sapi_v4l_destroy(struct sapi_context * sapi_ctx) { @@ -1009,6 +615,7 @@ free(v4l_ctx); } + int sapi_v4l_initialize(struct sapi_context * sapi_ctx) { @@ -1043,4 +650,3 @@ return 0; } - Added: branches/v4l2_support/src/v4l/v4l1_backend.c =================================================================== --- branches/v4l2_support/src/v4l/v4l1_backend.c (rev 0) +++ branches/v4l2_support/src/v4l/v4l1_backend.c 2010-03-09 18:35:43 UTC (rev 107) @@ -0,0 +1,433 @@ +#include "v4l_ctx.h" + +#include <errno.h> +#include <fcntl.h> +#include <linux/videodev.h> +#include <stdlib.h> +#include <string.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <unistd.h> + +struct sapi_v4l1_backend_context +{ + struct video_capability caps; + struct video_picture picture; + struct video_window window; + struct video_mbuf mbuf; +}; + + +static int +map_fourcc_to_palette(int fourcc, __u16 * palette) +{ + switch ( fourcc ) + { + case VIDCAP_FOURCC_I420: + *palette = VIDEO_PALETTE_YUV420P; + break; + + case VIDCAP_FOURCC_RGB24: + *palette = VIDEO_PALETTE_RGB24; + break; + + case VIDCAP_FOURCC_YUY2: + *palette = VIDEO_PALETTE_YUYV; + break; + + case VIDCAP_FOURCC_2VUY: + *palette = VIDEO_PALETTE_UYVY; + break; + + case VIDCAP_FOURCC_RGB32: + *palette = VIDEO_PALETTE_RGB32; + break; + + case VIDCAP_FOURCC_RGB555: + *palette = VIDEO_PALETTE_RGB555; + break; + + case VIDCAP_FOURCC_YVU9: + return 1; + + default: + return -1; + } + + return 0; +} + +static int +map_palette_to_fourcc(__u16 palette, int * fourcc) +{ + switch ( palette ) + { + case VIDEO_PALETTE_YUV420P: + *fourcc = VIDCAP_FOURCC_I420; + break; + + case VIDEO_PALETTE_RGB24: + *fourcc = VIDCAP_FOURCC_RGB24; + break; + + case VIDEO_PALETTE_YUYV: + *fourcc = VIDCAP_FOURCC_YUY2; + break; + + case VIDEO_PALETTE_UYVY: + *fourcc = VIDCAP_FOURCC_2VUY; + break; + + case VIDEO_PALETTE_RGB32: + *fourcc = VIDCAP_FOURCC_RGB32; + break; + + case VIDEO_PALETTE_RGB555: + *fourcc = VIDCAP_FOURCC_RGB555; + break; + + default: + return -1; + } + + return 0; +} + + +int v4l1_src_list_device_scan(int fd, struct sapi_src_list * src_list, const char * device_path) +{ + int ret = 0; + int i = 0; + struct video_capability caps; + memset(&caps, 0, sizeof(caps)); + + if ( ioctl(fd, VIDIOCGCAP, &caps) == -1 ) + { + log_warn("failed to get capabilities for %s\n", device_path); + ret = -1; + goto bail; + } + + if ( caps.type != VID_TYPE_CAPTURE ) + { + ret = -1; + goto bail; + } + + for( i = 0; i < caps.channels; ++i ) + { + struct video_channel channel; + + memset(&channel, 0, sizeof(channel)); + + channel.channel = i; + + if ( ioctl(fd, VIDIOCGCHAN, &channel) == -1 ) + { + log_warn("failed VIDIOCGCHAN for %s\n", device_path); + continue; + } + + if ( src_list_device_append(src_list, device_path, + channel.channel, caps.name, + channel.name) ) + { + ret = -1; + } + } + +bail: + return ret; +} + + +static int capture_kickoff(struct sapi_src_context * src_ctx, + unsigned int frame_count) +{ + struct sapi_v4l_src_context * v4l_src_ctx = + (struct sapi_v4l_src_context *)src_ctx->priv; + + struct video_mmap vmap; + + vmap.frame = frame_count % v4l_src_ctx->v4l1_ctx->mbuf.frames; + vmap.height = v4l_src_ctx->v4l1_ctx->window.height; + vmap.width = v4l_src_ctx->v4l1_ctx->window.width; + vmap.format = v4l_src_ctx->v4l1_ctx->picture.palette; + + if ( ioctl(v4l_src_ctx->fd, VIDIOCMCAPTURE, &vmap) == -1 ) + { + log_error("failed VIDIOCMCAPTURE %d\n", errno); + return -1; + } + + return 0; +} + + +static unsigned int capture_thread_proc(void * data) +{ + struct sapi_src_context * src_ctx = + (struct sapi_src_context *)data; + struct sapi_v4l_src_context * v4l_src_ctx = + (struct sapi_v4l_src_context *)src_ctx->priv; + const int capture_size = conv_fmt_size_get( + src_ctx->fmt_native.width, + src_ctx->fmt_native.height, + src_ctx->fmt_native.fourcc); + + const char * fb_base = mmap(0, v4l_src_ctx->v4l1_ctx->mbuf.size, PROT_READ, MAP_SHARED, v4l_src_ctx->fd, 0); + + unsigned int started_frame_count = 0; + unsigned int capture_frame_count = 0; + + if ( fb_base == (void *)-1 ) + { + log_error("failed mmap() %d\n", errno); + return -1; + } + + if ( capture_kickoff(src_ctx, started_frame_count) ) + goto bail; + + while ( v4l_src_ctx->capturing ) + { + const unsigned int capture_frame = + capture_frame_count % v4l_src_ctx->v4l1_ctx->mbuf.frames; + + if ( capture_kickoff(src_ctx, ++started_frame_count) ) + goto bail; + + if ( ioctl( v4l_src_ctx->fd, VIDIOCSYNC, &capture_frame ) == -1 ) + { + log_error("failed VIDIOCSYNC %d\n", errno); + goto bail; + } + + sapi_src_capture_notify(src_ctx, (char *)(fb_base + + v4l_src_ctx->v4l1_ctx->mbuf.offsets[capture_frame]), + capture_size, + 0, + 0); + + ++capture_frame_count; + } + + /* Sync with the last frame when capture has stopped (since we + * have overlapped capture kickoffs). + */ + { + const unsigned int capture_frame = + capture_frame_count % v4l_src_ctx->v4l1_ctx->mbuf.frames; + + if ( ioctl( v4l_src_ctx->fd, VIDIOCSYNC, + &capture_frame ) == -1 ) + { + log_error("failed VIDIOCSYNC (2) %d\n", errno); + goto bail; + } + } + + + if ( munmap((void *)fb_base, v4l_src_ctx->v4l1_ctx->mbuf.size) == -1 ) + { + log_error("failed munmap() %d\n", errno); + return -1; + } + + return 0; + +bail: + if ( munmap((void *)fb_base, v4l_src_ctx->v4l1_ctx->mbuf.size) == -1 ) + log_warn("failed munmap() %d\n", errno); + + return -1; +} + + + +static int +v4l1_source_release(struct sapi_src_context * src_ctx) +{ + struct sapi_v4l_src_context * v4l_src_ctx = + (struct sapi_v4l_src_context *)src_ctx->priv; + free( v4l_src_ctx->v4l1_ctx ); + return common_source_release( src_ctx ); +} + + +static int +v4l1_source_format_validate(struct sapi_src_context * src_ctx, + const struct vidcap_fmt_info * fmt_nominal, + struct vidcap_fmt_info * fmt_native, int forBinding ) +{ + struct sapi_v4l_src_context * v4l_src_ctx = + (struct sapi_v4l_src_context *)src_ctx->priv; + + *fmt_native = *fmt_nominal; + + __u16 palette; + + if ( fmt_nominal->width < v4l_src_ctx->v4l1_ctx->caps.minwidth || + fmt_nominal->width > v4l_src_ctx->v4l1_ctx->caps.maxwidth || + fmt_nominal->height < v4l_src_ctx->v4l1_ctx->caps.minheight || + fmt_nominal->height > v4l_src_ctx->v4l1_ctx->caps.maxheight ) + return 0; + + if ( map_fourcc_to_palette(fmt_nominal->fourcc, &palette) ) + return 0; + + if ( map_palette_to_fourcc(v4l_src_ctx->v4l1_ctx->picture.palette, + &fmt_native->fourcc) ) + return 0; + + if ( !sapi_can_convert_native_to_nominal(fmt_native, fmt_nominal) ) + return 0; + + return 1; +} + +static int +v4l1_source_format_bind(struct sapi_src_context * src_ctx, + const struct vidcap_fmt_info * fmt_info) +{ + struct sapi_v4l_src_context * v4l_src_ctx = + (struct sapi_v4l_src_context *)src_ctx->priv; + + memcpy(&src_ctx->fmt_native, fmt_info, sizeof(*fmt_info)); + + if ( map_palette_to_fourcc(v4l_src_ctx->v4l1_ctx->picture.palette, + &src_ctx->fmt_native.fourcc) ) + { + log_warn("failed map_palette_to_fourcc %d\n", + v4l_src_ctx->v4l1_ctx->picture.palette); + return -1; + } + + if ( ioctl(v4l_src_ctx->fd, VIDIOCSPICT, &v4l_src_ctx->v4l1_ctx->picture) == -1 ) + { + log_warn("failed to set v4l picture parameters\n"); + return -1; + } + + /* Only set the parameters we know/care about. */ + v4l_src_ctx->v4l1_ctx->window.x = 0; + v4l_src_ctx->v4l1_ctx->window.y = 0; + v4l_src_ctx->v4l1_ctx->window.width = fmt_info->width; + v4l_src_ctx->v4l1_ctx->window.height = fmt_info->height; + /* TODO: for pwc, framerate is encoded in flags. For other + * cameras, who knows. + */ + v4l_src_ctx->v4l1_ctx->window.flags = + (v4l_src_ctx->v4l1_ctx->window.flags & ~v4l_fps_mask) | + (((src_ctx->fmt_native.fps_numerator / + src_ctx->fmt_native.fps_denominator) << v4l_fps_shift) & + v4l_fps_mask); + + if ( ioctl(v4l_src_ctx->fd, VIDIOCSWIN, &v4l_src_ctx->v4l1_ctx->window) == -1 ) + { + log_warn("failed to set v4l window parameters x=%d y=%d " + "w=%d h=%d fl=0x%08x\n", + v4l_src_ctx->v4l1_ctx->window.x, + v4l_src_ctx->v4l1_ctx->window.y, + v4l_src_ctx->v4l1_ctx->window.width, + v4l_src_ctx->v4l1_ctx->window.height, + v4l_src_ctx->v4l1_ctx->window.flags); + return -1; + } + + if ( ioctl(v4l_src_ctx->fd, VIDIOCGWIN, &v4l_src_ctx->v4l1_ctx->window) == -1 ) + { + log_warn("failed to get v4l window parameters\n"); + return -1; + } + + if ( ioctl(v4l_src_ctx->fd, VIDIOCGMBUF, &v4l_src_ctx->v4l1_ctx->mbuf) == -1 ) + { + log_warn("failed to get v4l memory info for %s\n", + v4l_src_ctx->device_path); + return -1; + } + + return 0; +} + + +static int +v4l1_source_capture_start(struct sapi_src_context * src_ctx) +{ + struct sapi_v4l_src_context * v4l_src_ctx = + (struct sapi_v4l_src_context *)src_ctx->priv; + int ret; + + v4l_src_ctx->capturing = 1; + + if ( (ret = vc_create_thread(&v4l_src_ctx->capture_thread, + capture_thread_proc, src_ctx, + &v4l_src_ctx->capture_thread_id)) ) + { + log_error("failed vc_create_thread() for capture thread %d\n", + ret); + return -1; + } + + return 0; +} + + +static int +v4l1_source_capture_stop(struct sapi_src_context * src_ctx) +{ + struct sapi_v4l_src_context * v4l_src_ctx = + (struct sapi_v4l_src_context *)src_ctx->priv; + int ret; + + v4l_src_ctx->capturing = 0; + + if ( (ret = vc_thread_join(&v4l_src_ctx->capture_thread)) ) + { + log_error("failed vc_thread_join() %d\n", ret); + return -1; + } + + return 0; +} + + +int v4l1_source_acquire( struct sapi_src_context * src_ctx, struct sapi_v4l_src_context * v4l_src_ctx ) +{ + int ret = 0; + v4l_src_ctx->v4l1_ctx = (struct sapi_v4l1_backend_context*) calloc( 1, sizeof( struct sapi_v4l1_backend_context ) ); + + if ( ioctl(v4l_src_ctx->fd, VIDIOCGCAP, &v4l_src_ctx->v4l1_ctx->caps) == -1 ) + { + log_warn("failed to get v4l capability parameters for %s\n", + v4l_src_ctx->device_path); + ret = -1; + goto bail; + } + + if ( ioctl(v4l_src_ctx->fd, VIDIOCGWIN, &v4l_src_ctx->v4l1_ctx->window) == -1 ) + { + log_warn("failed to get v4l window parameters for %s\n", + v4l_src_ctx->device_path); + ret = -1; + goto bail; + } + + if ( ioctl(v4l_src_ctx->fd, VIDIOCGPICT, &v4l_src_ctx->v4l1_ctx->picture) == -1 ) + { + log_warn("failed to get v4l picture parameters for %s\n", + v4l_src_ctx->device_path); + ret = -1; + goto bail; + } + + src_ctx->release = v4l1_source_release; + src_ctx->format_validate = v4l1_source_format_validate; + src_ctx->format_bind = v4l1_source_format_bind; + src_ctx->start_capture = v4l1_source_capture_start; + src_ctx->stop_capture = v4l1_source_capture_stop; + +bail: + return ret; +} Added: branches/v4l2_support/src/v4l/v4l2_backend.c =================================================================== --- branches/v4l2_support/src/v4l/v4l2_backend.c (rev 0) +++ branches/v4l2_support/src/v4l/v4l2_backend.c 2010-03-09 18:35:43 UTC (rev 107) @@ -0,0 +1,617 @@ +#include "v4l_ctx.h" + +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <stdlib.h> +#include <string.h> +#include <sys/ioctl.h> +#include <sys/mman.h> +#include <unistd.h> + +#include <asm/types.h> /* for videodev2.h */ +#include <linux/videodev2.h> +#define CLEAR(x) memset (&(x), 0, sizeof (x)) + + +typedef enum { + IO_METHOD_READ, + IO_METHOD_MMAP, + IO_METHOD_USERPTR, +} io_method; + +struct pic_buffer { + void* data; + int length; +}; + +struct sapi_v4l2_backend_context +{ + struct v4l2_capability caps; + struct v4l2_cropcap cropcap; + struct v4l2_crop crop; + struct v4l2_format fmt; + + struct v4l2_buffer readBuffer; + + io_method method; + + struct pic_buffer* buffers; + int buffercnt; +}; + +int is_v4l2_device( int fd ) +{ + int isV4l = 1; + + struct v4l2_capability caps; + memset(&caps, 0, sizeof(caps)); + if( ioctl( fd, VIDIOC_QUERYCAP, &caps ) == -1 ) + { + isV4l = 0; + } + + return isV4l; +} + +static unsigned int v4l2_capture_thread_proc(void * data); + + +static void errno_exit( const char * s ) +{ + fprintf( stderr, "%s error %d, %s\n",s, errno, strerror (errno) ); + exit( EXIT_FAILURE ); +} + + +static int xioctl( int fd, int request, void* arg ) +{ + int r; + do { + r = ioctl ( fd, request, arg ); + } while (-1 == r && EINTR == errno ); + return r; +} + + +static int + v4l2_map_fourcc_to_palette( int fourcc, unsigned int *palette) +{ + switch ( fourcc ) + { + case VIDCAP_FOURCC_I420: + *palette = V4L2_PIX_FMT_YVU420; + break; + + case VIDCAP_FOURCC_RGB24: + *palette = V4L2_PIX_FMT_RGB24; + break; + + case VIDCAP_FOURCC_YUY2: + *palette = V4L2_PIX_FMT_YUYV; + break; + + case VIDCAP_FOURCC_2VUY: + *palette = V4L2_PIX_FMT_UYVY; + break; + + case VIDCAP_FOURCC_RGB32: + *palette = V4L2_PIX_FMT_RGB32; + break; + + case VIDCAP_FOURCC_RGB555: + *palette = V4L2_PIX_FMT_RGB555; + break; + + case VIDCAP_FOURCC_YVU9: + *palette = V4L2_PIX_FMT_YVU410; + break; + + default: + return -1; + } + + return 0; +} + + +static int + v4l2_map_palette_to_fourcc( unsigned int palette, int * fourcc) +{ + switch ( palette ) + { + case V4L2_PIX_FMT_YVU420: + *fourcc = VIDCAP_FOURCC_I420; + break; + + case V4L2_PIX_FMT_RGB24: + *fourcc = VIDCAP_FOURCC_RGB24; + break; + + case V4L2_PIX_FMT_YUYV: + *fourcc = VIDCAP_FOURCC_YUY2; + break; + + case V4L2_PIX_FMT_UYVY: + *fourcc = VIDCAP_FOURCC_2VUY; + break; + + case V4L2_PIX_FMT_RGB32: + *fourcc = VIDCAP_FOURCC_RGB32; + break; + + case V4L2_PIX_FMT_RGB555: + *fourcc = VIDCAP_FOURCC_RGB555; + break; + + case V4L2_PIX_FMT_YVU410: + *fourcc = VIDCAP_FOURCC_YVU9; + + default: + return -1; + } + + return 0; +} + + +void get_fourcc_string( int sapi_fourcc, char* dst) +{ + unsigned int v4l2_fourcc; + v4l2_map_fourcc_to_palette( sapi_fourcc, &v4l2_fourcc ); + memcpy( dst, (char*) &v4l2_fourcc, 4); +} + + +int v4l2_src_list_device_scan(int fd, struct sapi_src_list * src_list, const char * device_path) +{ + int ret = 0; + struct v4l2_capability deviceCaps; + + memset(&deviceCaps, 0, sizeof(deviceCaps)); + if( ioctl( fd, VIDIOC_QUERYCAP, &deviceCaps ) == -1 ) + { + ret = -1; + goto bail; + } + + log_info( "Driver: %s\n", deviceCaps.driver ); + log_info( "Card: %s\n", deviceCaps.card ); + log_info( "BusInfo: %s\n", deviceCaps.bus_info ); + log_info ("Version: %u.%u.%u\n", (deviceCaps.version >> 16) & 0xFF + , (deviceCaps.version >> 8) & 0xFF + , deviceCaps.version & 0xFF); + + log_info( "Video cpabilities flag: %u\n", deviceCaps.capabilities ); + log_info( "Video Capture support: %s\n", ( (deviceCaps.capabilities & V4L2_CAP_VIDEO_CAPTURE) > 0) ? "yes" : "no" ); +/* + log_info( "Video Output support: %s\n", ( (deviceCaps.capabilities & V4L2_CAP_VIDEO_OUTPUT) > 0) ? "yes" : "no" ); + log_info( "Video Overlay support: %s\n", ( (deviceCaps.capabilities & V4L2_CAP_VIDEO_OVERLAY) > 0) ? "yes" : "no" ); + + log_info( "Video VBI Capture support: %s\n", ( (deviceCaps.capabilities & V4L2_CAP_VBI_CAPTURE) > 0) ? "yes" : "no" ); + log_info( "Video VBI Output support: %s\n", ( (deviceCaps.capabilities & V4L2_CAP_VBI_OUTPUT) > 0) ? "yes" : "no" ); + log_info( "Video Sliced VBI capture support: %s\n", ( (deviceCaps.capabilities & V4L2_CAP_SLICED_VBI_CAPTURE) > 0) ? "yes" : "no" ); + log_info( "Video Sliced VBI output support: %s\n", ( (deviceCaps.capabilities & V4L2_CAP_SLICED_VBI_OUTPUT) > 0) ? "yes" : "no" ); + log_info( "Video RDS capture support: %s\n", ( (deviceCaps.capabilities & V4L2_CAP_RDS_CAPTURE) > 0) ? "yes" : "no" ); + + log_info( "Video Output Overlay support: %s\n", ( (deviceCaps.capabilities & V4L2_CAP_VIDEO_OUTPUT_OVERLAY) > 0) ? "yes" : "no" ); + + log_info( "Video Tuner support: %s\n", ( (deviceCaps.capabilities & V4L2_CAP_TUNER) > 0) ? "yes" : "no" ); + log_info( "Video Audio support: %s\n", ( (deviceCaps.capabilities & V4L2_CAP_AUDIO) > 0) ? "yes" : "no" ); + log_info( "Video Radio support: %s\n", ( (deviceCaps.capabilities & V4L2_CAP_RADIO) > 0) ? "yes" : "no" ); +*/ + log_info( "Video ReadWrite support: %s\n", ( (deviceCaps.capabilities & V4L2_CAP_READWRITE) > 0) ? "yes" : "no" ); + log_info( "Video AsyncI/O support: %s\n", ( (deviceCaps.capabilities & V4L2_CAP_ASYNCIO) > 0) ? "yes" : "no" ); + log_info( "Video Streaming support: %s\n", ( (deviceCaps.capabilities & V4L2_CAP_STREAMING) > 0) ? "yes" : "no" ); + + + if( (deviceCaps.capabilities & V4L2_CAP_VIDEO_CAPTURE) == 0 ) { + ret = -1; + goto bail; + } + if( src_list_device_append( src_list, device_path, + 0, (char *)deviceCaps.driver + , (char *) deviceCaps.card ) ) + { + ret = -1; + goto bail; + } + + bail: + return ret; +} + + +static int v4l2_source_release(struct sapi_src_context * src_ctx) +{ + struct sapi_v4l_src_context * v4l_src_ctx = (struct sapi_v4l_src_context *)src_ctx->priv; + free( v4l_src_ctx->v4l2_ctx ); + return common_source_release( src_ctx ); +} + + +void set_picture_format( struct v4l2_format* v4l2_fmt, const struct vidcap_fmt_info * vidcap_fmt ) +{ + struct v4l2_pix_format* pix = (struct v4l2_pix_format*)&v4l2_fmt->fmt; + pix->height = vidcap_fmt->height; + pix->width = vidcap_fmt->width; + v4l2_map_fourcc_to_palette( vidcap_fmt->fourcc, &pix->pixelformat ); + pix->bytesperline = 0; + pix->field = V4L2_FIELD_ANY; +} + + +static int v4l2_source_format_validate( struct sapi_src_context * src_ctx + , const struct vidcap_fmt_info * fmt_nominal + , struct vidcap_fmt_info * fmt_native + , int forBinding ) +{ + struct sapi_v4l_src_context * v4l_src_ctx = (struct sapi_v4l_src_context *)src_ctx->priv; + struct sapi_v4l2_backend_context* v4l2_ctx = v4l_src_ctx->v4l2_ctx; + + *fmt_native = *fmt_nominal; + + char fourcc[5]; +/* + unsigned int reqPalette; + v4l2_map_fourcc_to_palette( fmt_native->fourcc, &reqPalette ); + memcpy( fourcc, (char*)&reqPalette, 4); + fourcc[4] = '\0'; + printf("Requested fourcc: %s\n", fourcc ); +*/ + /* let the structure be filled by the driver... */ + struct v4l2_format fmt; + fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + if( ioctl( v4l_src_ctx->fd, VIDIOC_G_FMT, &fmt ) == -1 ) { + printf( "Failed to get the video format. Error was: %d\n", errno ); + return 0; + } + /* now set the new data */ + + set_picture_format( &fmt, fmt_nominal ); + + if( ioctl( v4l_src_ctx->fd, VIDIOC_TRY_FMT, &fmt ) == -1 ) + { + /*log_warn("Failed to query the video format. Error was: %d\n", errno );*/ + return 0; + } + + struct v4l2_pix_format* pix = (struct v4l2_pix_format*)&fmt.fmt; + memcpy( fourcc, (char*)&pix->pixelformat, 4); + fourcc[4] = '\0'; + + /* + printf("Driver Returned:\n"); + printf( "Width: %d, Heith %d, Pixelformat: %s, Field: %d, BytesPerLine: %d, imgSize: %d, ColorSpace: %d\n" + , pix->width, pix->height, fourcc, pix->field, pix->bytesperline + , pix->sizeimage, pix->colorspace ); + */ + + if( v4l2_map_palette_to_fourcc( pix->pixelformat, &fmt_native->fourcc ) ) + { + return 0; + } + if ( !sapi_can_convert_native_to_nominal(fmt_native, fmt_nominal) ) + return 0; + + return 1; +} + + +static int v4l2_source_format_bind( struct sapi_src_context * src_ctx + , const struct vidcap_fmt_info * fmt_info ) +{ + struct sapi_v4l_src_context * v4l_src_ctx = (struct sapi_v4l_src_context *)src_ctx->priv; + struct sapi_v4l2_backend_context* v4l2_ctx = v4l_src_ctx->v4l2_ctx; + + char fourcc[5]; + get_fourcc_string( fmt_info->fourcc, fourcc ); + fourcc[4] = '\0'; + log_info("Binding format: Size: %dx%d, Format: %s\n", fmt_info->width, fmt_info->height, fourcc ); + + /* let the structure be filled by the driver...*/ + v4l2_ctx->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + if( ioctl( v4l_src_ctx->fd, VIDIOC_G_FMT, &v4l2_ctx->fmt ) == -1 ) { + log_error( "Failed to get the video format. Error was: %d\n", errno ); + return 0; + } + + /* now set the new data */ + set_picture_format( &v4l2_ctx->fmt, fmt_info ); + if( ioctl( v4l_src_ctx->fd, VIDIOC_TRY_FMT, &v4l2_ctx->fmt ) == -1 ) + { + log_error( "Failed to query the video format. Error was: %d\n", errno ); + return -1; + } + return 0; +} + + +static int v4l2_source_capture_start( struct sapi_src_context * src_ctx ) +{ + log_info("Start capturing\n"); + struct sapi_v4l_src_context * v4l_src_ctx = (struct sapi_v4l_src_context *)src_ctx->priv; + struct sapi_v4l2_backend_context* v4l2_ctx = v4l_src_ctx->v4l2_ctx; + struct v4l2_requestbuffers rbufs; + int ret, cnt; + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + + struct v4l2_pix_format* pix = (struct v4l2_pix_format*)&v4l2_ctx->fmt; + + if( v4l2_ctx->method == IO_METHOD_READ ) { + log_info("USING READ METHOD\n"); + int i=0; + /* take a fixed count of buffers */ + v4l2_ctx->buffercnt = 5; + v4l2_ctx->buffers = (struct pic_buffer*)calloc( v4l2_ctx->buffercnt, sizeof(struct pic_buffer) ); + for( i=0; i < v4l2_ctx->buffercnt; ++i ) { + v4l2_ctx->buffers[i].data = malloc( pix->sizeimage ); + } + } else { + log_info("USING MMAP METHOD\n"); + int i=0; + /* take a fixed count of buffers */ + v4l2_ctx->buffercnt = 5; + rbufs.count = v4l2_ctx->buffercnt; + rbufs.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + rbufs.memory = V4L2_MEMORY_MMAP; + if( ioctl( v4l_src_ctx->fd, VIDIOC_REQBUFS, &rbufs ) == -1 ) { + /* \TODO implement userptr */ + log_error("MMAP is not supported by this device and USERPTRs are not yet implemented.\n"); + return -1; + } + + if( rbufs.count < 2 ) { + log_error("Isufficient bufer memory\n"); + return -1; + } + v4l2_ctx->buffercnt = rbufs.count; + + v4l2_ctx->buffers = (struct pic_buffer*)calloc( v4l2_ctx->buffercnt, sizeof(*v4l2_ctx->buffers) ); + if( !v4l2_ctx->buffers ) { + log_error("Out of memory\n"); + return -1; + } + + log_info("Mapping memory for %d pictures.\n", v4l2_ctx->buffercnt); + + for( i = 0; i < v4l2_ctx->buffercnt; ++i ) { + struct v4l2_buffer buf; + CLEAR( buf ); + + buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + buf.memory = V4L2_MEMORY_MMAP; + buf.index = i; + if( ioctl( v4l_src_ctx->fd, VIDIOC_QUERYBUF, &buf) == -1 ) { + log_error("Could not map memory\n"); + // TODO clear structures + return -1; + } + + v4l2_ctx->buffers[i].length = buf.length; + v4l2_ctx->buffers[i].data = mmap( NULL, buf.length + , PROT_READ | PROT_WRITE + , MAP_SHARED + , v4l_src_ctx->fd, buf.m.offset ); + if( v4l2_ctx->buffers[i].data == MAP_FAILED ) { + log_error("Error mapping memory at memory chunk %d with error: %d, %s\n" + , i, errno, strerror( errno ) ); + return -1; + } + } + } + + + v4l_src_ctx->capturing = 1; + + if ( (ret = vc_create_thread( &v4l_src_ctx->capture_thread + , v4l2_capture_thread_proc, src_ctx + , &v4l_src_ctx->capture_thread_id ) ) ) + { + log_error("failed vc_create_thread() for capture thread %d\n", ret); + return -1; + } + + switch( v4l_src_ctx->v4l2_ctx->method ) + { + case IO_METHOD_READ: + /* nothing to do*/ + break; + case IO_METHOD_MMAP: + case IO_METHOD_USERPTR: + + for( cnt = 0; cnt < v4l2_ctx->buffercnt; ++cnt) { + CLEAR( v4l2_ctx->readBuffer ); + v4l2_ctx->readBuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + v4l2_ctx->readBuffer.memory = V4L2_MEMORY_MMAP; + v4l2_ctx->readBuffer.index = cnt; + if( -1 == xioctl( v4l_src_ctx->fd, VIDIOC_QBUF, &v4l2_ctx->readBuffer ) ) { + log_error("Could not queue image buffers\n"); + } + } + + if( -1 == xioctl( v4l_src_ctx->fd, VIDIOC_STREAMON, &type ) ) { + log_error("failed to start the capture stream. ErrNr: %d\n", errno); + return -1; + } + } + return 0; +} + + +static int v4l2_source_capture_stop( struct sapi_src_context* src_ctx ) +{ + log_info("Stop capturing\n"); + struct sapi_v4l_src_context * v4l_src_ctx = (struct sapi_v4l_src_context *)src_ctx->priv; + int ret; + v4l_src_ctx->capturing = 0; + if ( (ret = vc_thread_join( &v4l_src_ctx->capture_thread) ) ) + { + log_error("failed vc_thread_join() %d\n", ret); + return -1; + } + + enum v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + switch( v4l_src_ctx->v4l2_ctx->method ) + { + case IO_METHOD_READ: // nothing to do + break; + case IO_METHOD_MMAP: + case IO_METHOD_USERPTR: + if( -1 == xioctl( v4l_src_ctx->fd, VIDIOC_STREAMOFF, &type) ) { + log_error("failed to stop stream %d\n", errno); + return -1; + } + } + + return 0; +} + + +int v4l2_source_acquire( struct sapi_src_context * src_ctx, struct sapi_v4l_src_context * v4l_src_ctx ) +{ + int ret = 0; + + v4l_src_ctx->v4l2_ctx = (struct sapi_v4l2_backend_context*) calloc( 1, sizeof( struct sapi_v4l2_backend_context ) ); + + if( ioctl( v4l_src_ctx->fd, VIDIOC_QUERYCAP, &v4l_src_ctx->v4l2_ctx->caps ) == -1 ) + { + log_warn("failed to get v4l2 capability parameters for %s\n", v4l_src_ctx->device_path); + ret = -1; + goto bail; + + } + + /* set method:*/ + if( ( v4l_src_ctx->v4l2_ctx->caps.capabilities & V4L2_CAP_READWRITE ) > 0 ) v4l_src_ctx->v4l2_ctx->method = IO_METHOD_READ; + /*if( (v4l_src_ctx->v4l2_ctx->caps.capabilities & V4L2_CAP_ASYNCIO ) > 0 ) */ /* not yet specified*/ + if( ( v4l_src_ctx->v4l2_ctx->caps.capabilities & V4L2_CAP_STREAMING ) > 0 ) v4l_src_ctx->v4l2_ctx->method = IO_METHOD_MMAP; + + CLEAR( v4l_src_ctx->v4l2_ctx->cropcap ); + v4l_src_ctx->v4l2_ctx->cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if (0 == ioctl( v4l_src_ctx->fd, VIDIOC_CROPCAP, &v4l_src_ctx->v4l2_ctx->cropcap ) ) { + v4l_src_ctx->v4l2_ctx->crop.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + v4l_src_ctx->v4l2_ctx->crop.c = v4l_src_ctx->v4l2_ctx->cropcap.defrect; /* reset to default */ + if ( ioctl(v4l_src_ctx->fd, VIDIOC_S_CROP, &v4l_src_ctx->v4l2_ctx->crop) == -1 ) { + switch (errno) { + case EINVAL: + log_warn("Cropping not supported on %s\n", v4l_src_ctx->device_path); + break; + default: + /* Errors ignored. */ + break; + } + } + } else { + /* Errors ignored. */ + } + + CLEAR( v4l_src_ctx->v4l2_ctx->fmt ); + v4l_src_ctx->v4l2_ctx->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + if( ioctl(v4l_src_ctx->fd, VIDIOC_G_FMT, &v4l_src_ctx->v4l2_ctx->fmt) == -1 ) + { + log_warn("failed to get v4l2 picture format for %s\n", v4l_src_ctx->device_path); + ret = -1; + goto bail; + } + + src_ctx->release = v4l2_source_release; + src_ctx->format_validate = v4l2_source_format_validate; + src_ctx->format_bind = v4l2_source_format_bind; + src_ctx->start_capture = v4l2_source_capture_start; + src_ctx->stop_capture = v4l2_source_capture_stop; + +bail: + return ret; +} + + +static unsigned int v4l2_read_frame( struct sapi_src_context* src_ctx ) +{ + int ret = 0; + struct sapi_v4l_src_context * v4l_src_ctx =(struct sapi_v4l_src_context *)src_ctx->priv; + struct sapi_v4l2_backend_context* v4l2_ctx = v4l_src_ctx->v4l2_ctx; + + switch( v4l2_ctx->method ) + { + case IO_METHOD_READ: + case IO_METHOD_USERPTR: + ret = 0; + printf("Method not supported yet.\n"); + break; + + case IO_METHOD_MMAP: + CLEAR( v4l2_ctx->readBuffer ); + v4l2_ctx->readBuffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; + v4l2_ctx->readBuffer.memory = V4L2_MEMORY_MMAP; + + if (-1 == xioctl( v4l_src_ctx->fd, VIDIOC_DQBUF, &v4l2_ctx->readBuffer ) ) + { + switch (errno) { + case EAGAIN: + return 0; + case EIO: + /* Could ignore EIO, see spec. */ + /* fall through */ + default: + log_error("Error while calling DQBUF. Msg was: %d, %s\n", errno, strerror( errno ) ); + return -1; + } + } + assert( v4l2_ctx->readBuffer.index < v4l2_ctx->buffercnt ); + + sapi_src_capture_notify( src_ctx + , (char *)(v4l2_ctx->buffers[v4l2_ctx->readBuffer.index].data) + , v4l2_ctx->readBuffer.bytesused, 0, 0 ); + + ret = 1; + + if (-1 == xioctl( v4l_src_ctx->fd, VIDIOC_QBUF, &v4l2_ctx->readBuffer)) { + errno_exit( "VIDIOC_QBUF" ); + } + + }; + return ret; +} + + +static unsigned int v4l2_capture_thread_proc(void * data) +{ + struct sapi_src_context* src_ctx =(struct sapi_src_context *)data; + struct sapi_v4l_src_context* v4l_src_ctx =(struct sapi_v4l_src_context *)src_ctx->priv; + + unsigned int started_frame_count = 0; + unsigned int capture_frame_count = 0; + + while( v4l_src_ctx->capturing ) + { + for( ;; ) + { + fd_set fds; + struct timeval tv; + int r = 0; + FD_ZERO( &fds ); + FD_SET( v4l_src_ctx->fd, &fds ); + tv.tv_sec = 2; + tv.tv_usec = 0; + r = select( v4l_src_ctx->fd +1, &fds, NULL, NULL, &tv ); + if( r == -1) { + if( errno == EINTR ) + continue; + errno_exit ("select"); + } + if( r == 0 ) { + fprintf (stderr, "select timeout\n"); + exit (EXIT_FAILURE); + } + if( v4l2_read_frame( src_ctx ) ) { + ++capture_frame_count; + break; + } + /* EAGAIN - continue select loop. */ + } + } + return 0; +} Added: branches/v4l2_support/src/v4l/v4l_ctx.h =================================================================== --- branches/v4l2_support/src/v4l/v4l_ctx.h (rev 0) +++ branches/v4l2_support/src/v4l/v4l_ctx.h 2010-03-09 18:35:43 UTC (rev 107) @@ -0,0 +1,59 @@ +#ifndef _V4L_CTX_H +#define _V4L_CTX_H + +#include "conv.h" +#include "hotlist.h" +#include "logging.h" +#include "sapi.h" + +/* fwd declarations;*/ +struct sapi_v4l1_backend_context* v4l1_ctx; +struct sapi_v4l2_backend_context* v4l2_ctx; + +enum +{ + device_path_max = 128, + device_num_max = 16, + v4l_fps_mask = 0x003f0000, + v4l_fps_shift = 16, +}; + + +struct sapi_v4l_context +{ + vc_mutex mutex; + vc_thread notify_thread; + unsigned int notify_thread_id; + int notifying; + struct sapi_src_list acquired_src_list; +}; + + +struct sapi_v4l_src_context +{ + struct sapi_v4l_context * v4l_ctx; + + struct sapi_v4l1_backend_context* v4l1_ctx; + struct sapi_v4l2_backend_context* v4l2_ctx; + + int fd; + char device_path[device_path_max]; + int channel; + + int capturing; + vc_thread capture_thread; + unsigned int capture_thread_id; +}; + + +int src_list_device_append( struct sapi_src_list * src_list + , const char * device_path, int channel + , const char * device_name, const char * channel_name ); +int common_source_release(struct sapi_src_context * src_ctx); +int is_v4l2_device( int fd ); +int v4l1_source_acquire( struct sapi_src_context * src_ctx, struct sapi_v4l_src_context * v4l_src_ctx ); +int v4l2_source_acquire( struct sapi_src_context * src_ctx, struct sapi_v4l_src_context * v4l_src_ctx ); +int v4l1_src_list_device_scan(int fd, struct sapi_src_list * src_list, const char * device_path); +int v4l2_src_list_device_scan(int fd, struct sapi_src_list * src_list, const char * device_path); + +#endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. <lib...@li...> - 2010-03-09 18:21:52
|
Revision: 106 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=106&view=rev Author: kretikus Date: 2010-03-09 18:21:45 +0000 (Tue, 09 Mar 2010) Log Message: ----------- Creating a branch to develop v4l2 support Added Paths: ----------- branches/v4l2_support/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. <lib...@li...> - 2010-02-01 19:48:31
|
Revision: 105 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=105&view=rev Author: bcholew Date: 2010-02-01 19:48:25 +0000 (Mon, 01 Feb 2010) Log Message: ----------- Add convenience parameter 'format' to the capture callback 'vidcap_capture_info' structure. This parameter represents the vidcap_fmt_info structure describing the frame returned by the capture callback. NOTE: This change alters libvidcap's public interface. Modified Paths: -------------- trunk/include/vidcap/vidcap.h trunk/src/sapi.c Modified: trunk/include/vidcap/vidcap.h =================================================================== --- trunk/include/vidcap/vidcap.h 2010-02-01 19:37:31 UTC (rev 104) +++ trunk/include/vidcap/vidcap.h 2010-02-01 19:48:25 UTC (rev 105) @@ -78,6 +78,7 @@ int error_status; long capture_time_sec; long capture_time_usec; + struct vidcap_fmt_info format; }; typedef int (*vidcap_src_capture_callback) (vidcap_src *, Modified: trunk/src/sapi.c =================================================================== --- trunk/src/sapi.c 2010-02-01 19:37:31 UTC (rev 104) +++ trunk/src/sapi.c 2010-02-01 19:48:25 UTC (rev 105) @@ -302,6 +302,8 @@ cap_info.video_data_size = buf_data_size; } + cap_info.format = src_ctx->fmt_nominal; + if ( ( send_frame || error_status ) && cap_callback && cap_data != VIDCAP_INVALID_USER_DATA ) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. <lib...@li...> - 2010-02-01 19:37:38
|
Revision: 104 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=104&view=rev Author: bcholew Date: 2010-02-01 19:37:31 +0000 (Mon, 01 Feb 2010) Log Message: ----------- Set libvidcap version to 0.2.2 in tag. Modified Paths: -------------- tags/0.2.2/configure.ac Modified: tags/0.2.2/configure.ac =================================================================== --- tags/0.2.2/configure.ac 2010-02-01 19:34:57 UTC (rev 103) +++ tags/0.2.2/configure.ac 2010-02-01 19:37:31 UTC (rev 104) @@ -3,7 +3,7 @@ AC_PREREQ(2.59) dnl package version -m4_define(VIDCAP_VERSION, [0.3-svn]) +m4_define(VIDCAP_VERSION, [0.2.2]) AC_INIT([libvidcap], VIDCAP_VERSION, [jpg...@gm...]) AC_CONFIG_SRCDIR([include/vidcap/vidcap.h]) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. <lib...@li...> - 2010-02-01 19:35:03
|
Revision: 103 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=103&view=rev Author: bcholew Date: 2010-02-01 19:34:57 +0000 (Mon, 01 Feb 2010) Log Message: ----------- Tagging libvidcap 0.2.2 Added Paths: ----------- tags/0.2.2/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. <lib...@li...> - 2010-02-01 19:29:06
|
Revision: 102 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=102&view=rev Author: bcholew Date: 2010-02-01 19:29:00 +0000 (Mon, 01 Feb 2010) Log Message: ----------- Merge Chris Cooksey's branches/framesize_enhancements back into trunk. Added support for DV cameras. In addition, added support for any frame size, any frame rate, or any of three color spaces requested by the client, regardless of whether they are physically supported by the device. NOTE: these enhancements have NOT been added to the Linux source. Also note that device aspect ratios are not preserved. If a 4:3 frame size is requested from a device that has a 16:9 resolution, the image will be scaled to fit. These changes do NOT alter the public interface. Modified Paths: -------------- trunk/examples/vidcapTester/Grabber.cpp trunk/src/conv.c trunk/src/directshow/DirectShowSource.cpp trunk/src/directshow/DirectShowSource.h trunk/src/directshow/SourceStateMachine.cpp trunk/src/directshow/SourceStateMachine.h trunk/src/sapi.c trunk/src/sapi_context.h trunk/src/sapi_dshow.cpp trunk/src/sapi_qt.c trunk/src/sapi_v4l.c trunk/src/vidcap.c Modified: trunk/examples/vidcapTester/Grabber.cpp =================================================================== --- trunk/examples/vidcapTester/Grabber.cpp 2010-02-01 19:00:34 UTC (rev 101) +++ trunk/examples/vidcapTester/Grabber.cpp 2010-02-01 19:29:00 UTC (rev 102) @@ -132,7 +132,6 @@ case VIDCAP_FOURCC_I420: rgb_buf.resize(width_ * height_ * 4); - vidcap_i420_to_rgb32(width_, height_, cap_info->video_data, rgb_buf.data()); break; Modified: trunk/src/conv.c =================================================================== --- trunk/src/conv.c 2010-02-01 19:00:34 UTC (rev 101) +++ trunk/src/conv.c 2010-02-01 19:29:00 UTC (rev 102) @@ -23,6 +23,10 @@ * */ +#if HAVE_QUICKTIME +#include <QuickTime/ImageCodec.h> +#endif + #include "string.h" #include "conv.h" #include "logging.h" @@ -101,7 +105,8 @@ int u_width, int u_height, int v_width, int v_height, int y_stride, int u_stride, int v_stride, - const char * src, char * dst) + const char * src_y, const char * src_u, const char * src_v, + char * dst) { char * dst_y_even = dst; char * dst_y_odd = dst + width; @@ -109,12 +114,12 @@ char * dst_u_odd = dst_u_even + u_width; char * dst_v_even = dst_u_even + u_width * u_height; char * dst_v_odd = dst_v_even + v_width; - const char * src_y_even = src; - const char * src_y_odd = src + y_stride; - const char * src_u_even = src + y_stride * height; - const char * src_u_odd = src_u_even + u_stride; - const char * src_v_even = src_u_even + u_stride * u_height; - const char * src_v_odd = src_v_even + v_stride; + const char * src_y_even = src_y; + const char * src_y_odd = src_y + y_stride; + const char * src_u_even = src_u; + const char * src_u_odd = src_u + u_stride; + const char * src_v_even = src_v; + const char * src_v_odd = src_v + v_stride; int i; @@ -164,15 +169,34 @@ switch ( fourcc ) { - case VIDCAP_FOURCC_I420: + case VIDCAP_FOURCC_I420: { + #if HAVE_QUICKTIME + /* src points to a PlanarPixmapInfoYUV420 struct, not raw data */ + PlanarPixmapInfoYUV420 *pmInfo = (PlanarPixmapInfoYUV420 *)src; + SInt32 y_offset = EndianS32_BtoN( pmInfo->componentInfoY.offset ); + SInt32 u_offset = EndianS32_BtoN( pmInfo->componentInfoCb.offset ); + SInt32 v_offset = EndianS32_BtoN( pmInfo->componentInfoCr.offset ); + UInt32 y_rowBytes = EndianU32_BtoN( pmInfo->componentInfoY.rowBytes ); + UInt32 u_rowBytes = EndianU32_BtoN( pmInfo->componentInfoCb.rowBytes ); + UInt32 v_rowBytes = EndianU32_BtoN( pmInfo->componentInfoCr.rowBytes ); + return destride_planar(width, height, + width / 2, height / 2, width / 2, height / 2, + y_rowBytes, u_rowBytes, v_rowBytes, + src + y_offset, src + u_offset, src + v_offset, dst); + #else + /* FIXME: only destride if necessary */ + const char * src_y = src; + const char * src_u = src_y + height * stride; + const char * src_v = src_u + (height * stride) / 4; log_error("UNTESTED: destriding i420\n"); - /* FIXME: only destride if necessary */ return destride_planar(width, height, /* fix these u and v strides to be 32-bit aligned? */ width / 2, height / 2, width / 2, height / 2, stride, stride / 2, stride / 2, - src, dst); + src_y, src_u, src_v, dst); + #endif break; + } case VIDCAP_FOURCC_YUY2: if ( stride == 2 * width ) return -1; @@ -198,15 +222,19 @@ return -1; return destride_packed(3 * width, height, stride, src, dst); break; - case VIDCAP_FOURCC_YVU9: + case VIDCAP_FOURCC_YVU9: { + /* FIXME: only destride if necessary */ + const char * src_y = src; + const char * src_u = src_y + height * stride; + const char * src_v = src_u + (height * stride) / 4; log_error("UNTESTED: destriding yvu9\n"); - /* FIXME: only destride if necessary */ return destride_planar(width, height, width / 4, height / 4, width / 4, height / 4, /* fix u and v strides to be 32-bit aligned? */ stride, stride / 4, stride / 4, - src, dst); + src_y, src_u, src_v, dst); break; + } default: log_error("Invalid fourcc [%s]\n", vidcap_fourcc_string_get(fourcc)); Modified: trunk/src/directshow/DirectShowSource.cpp =================================================================== --- trunk/src/directshow/DirectShowSource.cpp 2010-02-01 19:00:34 UTC (rev 101) +++ trunk/src/directshow/DirectShowSource.cpp 2010-02-01 19:29:00 UTC (rev 102) @@ -53,11 +53,16 @@ pMediaControlIF_(0), nativeMediaType_(0), graphIsSetup_(false), - graphHandle_(0) + graphHandle_(0), + nativeMediaTypeSufficient_(true), + buffer_(NULL), + bufferSize_(0) { IBindCtx * pBindCtx = 0; IMoniker * pMoniker = 0; + ZeroMemory( &outputMediaType_, sizeof( AM_MEDIA_TYPE ) ); + // Get the capture device - identified by it's long display name if ( !getCaptureDevice(getID(), &pBindCtx, &pMoniker) ){ log_warn("Failed to get device '%s'.\n", getID()); @@ -112,6 +117,9 @@ if ( nativeMediaType_ ) freeMediaType(*nativeMediaType_); + if( buffer_ != NULL ) + CoTaskMemFree( (PVOID)buffer_ ); + destroyCapGraphFoo(); pSource_->Release(); @@ -338,6 +346,7 @@ if ( !graphIsSetup_ ) { // set the stream's media type + // this tells the capture graph what output to produce HRESULT hr = pStreamConfig_->SetFormat(nativeMediaType_); if ( FAILED(hr) ) { @@ -347,6 +356,10 @@ } // Set sample grabber's media type + // this tells the sample grabber which output to produce. + if( !nativeMediaTypeSufficient_ ) + hr = pSampleGrabberIF_->SetMediaType(&outputMediaType_); + else hr = pSampleGrabberIF_->SetMediaType(nativeMediaType_); if ( FAILED(hr) ) { @@ -354,6 +367,7 @@ return -1; } + // add the sample grabber to the graph hr = pFilterGraph_->AddFilter(pSampleGrabber_, L"Sample Grabber"); if ( FAILED(hr) ) { @@ -361,6 +375,9 @@ return -1; } + // Set up a capture graph of type video. Source is the capture device. + // It will run data through our sample grabber object (which has a + // callback to us), and then discard the data in the Null renderer. hr = pCapGraphBuilder_->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, pSource_, @@ -424,50 +441,109 @@ int DirectShowSource::validateFormat(const vidcap_fmt_info * fmtNominal, - vidcap_fmt_info * fmtNative) const + vidcap_fmt_info * fmtNative, int forBinding ) const { +/* This is called both when checking the hot list and when binding to a specific */ +/* format. fmtNative is ignored when checking the hot list, but when binding it */ +/* indicates the format of the sample buffer that will be generated. */ +/* forBinding indicates how this function is being used. If it is 0, we are */ +/* looking for formats that are natively, or very nearly natively supported by the */ +/* device, i.e. we are building the supported formats list. If it is 1, we are */ +/* attempting to bind to a format, i.e. a client is asking for a specific format. */ +/* In that case, we may relax the rules, and be more flexible about what can be */ +/* accepted. The quality in this latter case may suffer, but it will still work. */ +/* The function result is a bool. True on success. */ + AM_MEDIA_TYPE *mediaFormat; - if ( !findBestFormat(fmtNominal, fmtNative, &mediaFormat) ) - return 0; + if ( findBestFormat( fmtNominal, fmtNative, &mediaFormat ) ) + { + freeMediaType( *mediaFormat ); + return 1; + } + else + if( forBinding ) + { + nativeMediaTypeSufficient_ = false; + if( findUsableFormat( fmtNominal, fmtNative, &mediaFormat, false ) ) + { + freeMediaType( *mediaFormat ); + return 1; + } + } - freeMediaType(*mediaFormat); - return 1; + return 0; } int DirectShowSource::bindFormat(const vidcap_fmt_info * fmtNominal) { +/* Given the desired sample format in fmtNominal, find a device native format we can */ +/* use to get there. The native format does not have to match the nominal format, but */ +/* must be convertible to it. If we can't use a simple native format, we will need to */ +/* look for something that can get us part of the way there, and then potentially scale */ +/* the samples as they arrive in the callback. Further conversion from RGB may also be */ +/* needed. Basically we are setting the field nativeMediaType_ to an actual media */ +/* format that the device may legally be set to. If that can't get us to the nominal */ +/* format, we may need to further create a sample grabber media format that will */ +/* convert the data to RGB, which we will scale in the callback function. Note that */ +/* libvidcap gets information about the format of the sample buffer by calling */ +/* validateFormat(), not bindFormat(). The two functions need to mirror one another */ +/* when binding, so that they agree on how the samples will be processed. */ +/* The function result is an error code. 0 on success. */ + vidcap_fmt_info fmtNative; - // If we've already got one, free it + /* Create input format */ if ( nativeMediaType_ ) { freeMediaType(*nativeMediaType_); nativeMediaType_ = 0; } - if ( !findBestFormat(fmtNominal, &fmtNative, &nativeMediaType_) ) - return 1; - - // set the framerate - VIDEOINFOHEADER * vih = (VIDEOINFOHEADER *) nativeMediaType_->pbFormat; + /* If nativeMediaTypeSufficient_ is true, fmtNative will be the device format and */ + /* the sample grabber format. If nativeMediaTypeSufficient_ is false, fmtNative */ + /* will only describe the sample grabber format, it will not reflect what we */ + /* apply to the device internally. nativeMediaType_ should be applied to the sample */ + /* grabber element so that it will produce the samples in the format needed by the */ + /* sample callback. */ + if ( findBestFormat( fmtNominal, &fmtNative, &nativeMediaType_ ) ) + { + nativeMediaTypeSufficient_ = true; + // Adjust the native media type to match the desired fps, height and width + // We could actually do this in findBestFormat. It wouldn't affect hot + // list creation. But let's keep the changes to a minimum for now. + VIDEOINFOHEADER * vih = (VIDEOINFOHEADER *)nativeMediaType_->pbFormat; vih->AvgTimePerFrame = 10000000 * fmtNative.fps_denominator / fmtNative.fps_numerator; - - // set the dimensions vih->bmiHeader.biWidth = fmtNative.width; vih->bmiHeader.biHeight = fmtNative.height; + return 0; + } + else + { + /* We could not find a perfect or close match. Now we must do some work. */ + /* Indicate that the native media type is not sufficient to get the format we */ + /* want. Ask DirectShow for RGB samples, (which appears to be legal), and */ + /* allocate buffers into which we can scale the samples received to the correct */ + /* size (or simply flip them if that is sufficient). */ + nativeMediaTypeSufficient_ = false; + if( findUsableFormat( fmtNominal, &fmtNative, &nativeMediaType_, true ) ) + return 0; + } - return 0; + return 1; } bool DirectShowSource::findBestFormat(const vidcap_fmt_info * fmtNominal, vidcap_fmt_info * fmtNative, AM_MEDIA_TYPE **mediaFormat) const +{ +/* Given the nominal format, fill in the AM_MEDIA_TYPE structure with */ +/* the native device format to use as the filter graph source device */ +/* format. It has to be something the device actually supports. */ -{ bool needsFpsEnforcement = false; bool needsFmtConv = false; @@ -598,10 +674,8 @@ // take note of native media type, fps, dimensions, fourcc *mediaFormat = candidateFmtProps[bestFmtNum].mediaFormat; - fmtNative->fps_numerator = - fmtsNative[bestFmtNum].fps_numerator; - fmtNative->fps_denominator = - fmtsNative[bestFmtNum].fps_denominator; + fmtNative->fps_numerator = fmtsNative[bestFmtNum].fps_numerator; + fmtNative->fps_denominator = fmtsNative[bestFmtNum].fps_denominator; fmtNative->width = fmtsNative[bestFmtNum].width; fmtNative->height = fmtsNative[bestFmtNum].height; fmtNative->fourcc = fmtsNative[bestFmtNum].fourcc; @@ -613,6 +687,172 @@ return itCanWork; } + +bool +DirectShowSource::findUsableFormat( const vidcap_fmt_info *fmtNominal, + vidcap_fmt_info * fmtNative, AM_MEDIA_TYPE **mediaFormat, bool forSampling ) const +{ +/* Ask the device for RGB samples at any size (preferably one bigger than or equal */ +/* to what we want). We will resample and flip the frames received before passing */ +/* them on to the host. Note that fmtNative is set up as though the device actually */ +/* produced the resized RGB samples. This method could probably be combined with */ +/* findBestFormat but that one is too complex at this point. forSampling will be true */ +/* if we need to create the sample scaling / flipping buffer. */ + + /* Look for a capability that can provide equal or more data than requested */ + int bestFormat = 0; + if( !findBestCapability( fmtNominal, bestFormat ) ) + { + log_error("failed to find any suitable device interface\n"); + return false; + } + + /* Use the most suitable capability on the capture device */ + VIDEO_STREAM_CONFIG_CAPS scc; + HRESULT hr = pStreamConfig_->GetStreamCaps( bestFormat, mediaFormat, (BYTE *)&scc ); + if ( FAILED(hr) ) + { + log_error("failed to get device capabilities (%d)\n", hr); + return false; + } + + /* Pick maximum frame rate and maximum frame size. DV does not use FORMAT_VideoInfo */ + /* header. In theory. I have seen it there though so I don't know what that is all */ + /* about. */ + if( (*mediaFormat)->formattype == FORMAT_VideoInfo ) + { + VIDEOINFOHEADER *vih = (VIDEOINFOHEADER *)(*mediaFormat)->pbFormat; + vih->AvgTimePerFrame = scc.MinFrameInterval; + vih->bmiHeader.biWidth = scc.MaxOutputSize.cx; + vih->bmiHeader.biHeight = scc.MaxOutputSize.cy; + } + + /* Set special sample grabber media format to produce RGB32 */ + ZeroMemory( &outputMediaType_, sizeof( AM_MEDIA_TYPE ) ); + outputMediaType_.majortype = MEDIATYPE_Video; + outputMediaType_.subtype = MEDIASUBTYPE_RGB32; + + /* Allocate buffers into which we can convert and vertically flip the RGB sample to */ + /* then hand back to the client. We only need this buffer allocated if we plan to */ + /* sample frames. */ + if( forSampling ) + { + if( buffer_ != NULL ) + CoTaskMemFree( (PVOID)buffer_ ); + bufferSize_ = fmtNominal->width * fmtNominal->height * 4; + buffer_ = (BYTE *)CoTaskMemAlloc( bufferSize_ ); + if( buffer_ == NULL ) + { + freeMediaType( **mediaFormat ); + return 0; + } + ZeroMemory( buffer_, bufferSize_ ); + } + + /* Tell the caller what our faux native output will look like (remember, we will be */ + /* secretly resizing and vertically flipping the data before handing the sample to */ + /* the client). */ + fmtNative->fourcc = VIDCAP_FOURCC_RGB32; + fmtNative->fps_denominator = 100; + fmtNative->fps_numerator = (int)(1000000000 / scc.MinFrameInterval); + fmtNative->width = fmtNominal->width; + fmtNative->height = fmtNominal->height; + + /* For our secret converter, remember what we are getting from the device, and */ + /* remember what we promised to our client. */ + fmtRealSample_ = *fmtNative; + fmtRealSample_.width = scc.MaxOutputSize.cx; + fmtRealSample_.height = scc.MaxOutputSize.cy; + fmtFauxSample_ = *fmtNative; + + return 1; +} + +bool +DirectShowSource::findBestCapability( const vidcap_fmt_info *fmtNominal, int &bestFormat ) const +{ +/* Look through the device capabilities, and make sure we are using the largest */ +/* available size that satisfies the format we want. Our goal is to scale down, but to */ +/* scale the least possible amount of data down. Failing that, we will settle for */ +/* scaling the largest output format up. Frame size is preferred over framerate. Frames */ +/* that are large enough will always beat frames that are too small, regardless of the */ +/* frame rate. */ + + int i; + HRESULT hr; + VIDEO_STREAM_CONFIG_CAPS scc; + AM_MEDIA_TYPE *pMediaType; + int desiredWidth = fmtNominal->width; + int desiredHeight = fmtNominal->height; + LONGLONG desiredInterval = 1000000000 * fmtNominal->fps_denominator / fmtNominal->fps_numerator / 100; + + bestFormat = 0; + + /* Get device capability count */ + int iCount = 0; + int iSize = 0; + hr = pStreamConfig_->GetNumberOfCapabilities( &iCount, &iSize ); + if( hr != S_OK ) + { + log_error( "could not get device capability count\n" ); + return false; + } + if( iSize != sizeof( VIDEO_STREAM_CONFIG_CAPS ) ) + { + log_error( "capabilities struct is wrong size (%d not %d)\n", + iSize, sizeof( VIDEO_STREAM_CONFIG_CAPS ) ); + return false; + } + + /* Get first interface. Use as base for comparison */ + hr = pStreamConfig_->GetStreamCaps( 0, &pMediaType, (BYTE *)&scc ); + if ( FAILED(hr) ) + { + log_error("failed to get device capabilities (0, %d)\n", hr); + return false; + } + freeMediaType( *pMediaType ); + + int bestWidth = scc.MaxOutputSize.cx; + int bestHeight = scc.MaxOutputSize.cy; + LONGLONG bestInterval = scc.MinFrameInterval; + + for( i = 1; i < iCount; i++ ) + { + HRESULT hr = pStreamConfig_->GetStreamCaps( i, &pMediaType, (BYTE *)&scc ); + if( !FAILED( hr ) ) + freeMediaType( *pMediaType ); + + if( hr == S_OK ) + { + bool bestSizeSmallerThanDesired = bestWidth < desiredWidth || bestHeight < desiredHeight; + bool currentSizeBiggerThanOrEqualToDesired = scc.MaxOutputSize.cx >= desiredWidth && scc.MaxOutputSize.cy >= desiredHeight; + bool currentSizeSmallerThanBest = scc.MaxOutputSize.cx < bestWidth || scc.MaxOutputSize.cx < bestHeight; + bool currentSizeEqualToBest = scc.MaxOutputSize.cx == bestWidth && scc.MaxOutputSize.cy == bestHeight; + bool currentSizeBiggerThanBest = scc.MaxOutputSize.cx >= bestWidth && scc.MaxOutputSize.cy >= bestHeight && !currentSizeEqualToBest; + + bool bestRateSlowerThanDesired = bestInterval > desiredInterval; + bool currentRateFasterThanOrEqualToDesired = scc.MinFrameInterval <= desiredInterval; + bool currentRateSlowerThanBest = scc.MinFrameInterval > bestInterval; + bool currentRateFasterThanBestRate = scc.MinFrameInterval < bestInterval; + + if( bestSizeSmallerThanDesired && currentSizeBiggerThanBest || + currentSizeBiggerThanOrEqualToDesired && currentSizeSmallerThanBest || + currentSizeEqualToBest && ( + bestRateSlowerThanDesired && currentRateFasterThanBestRate || + currentRateFasterThanOrEqualToDesired && currentRateSlowerThanBest) ) + { + bestWidth = scc.MaxOutputSize.cx; + bestHeight = scc.MaxOutputSize.cy; + bestInterval = scc.MinFrameInterval; + bestFormat = i; + } + } + } + + return true; +} + // Evaluate one of perhaps several native formats for // suitability for providing the nominal format. // Fill-in output parameter 'mediaFormat'. @@ -676,10 +916,8 @@ } // calculate range of supported frame rates - double fpsMin = static_cast<double>( 1000000000 / scc.MaxFrameInterval) - / 100.0; - double fpsMax = static_cast<double>( 1000000000 / scc.MinFrameInterval) - / 100.0; + double fpsMin = static_cast<double>(1000000000 / scc.MaxFrameInterval) / 100.0; + double fpsMax = static_cast<double>(1000000000 / scc.MinFrameInterval) / 100.0; double fps = static_cast<double>(fmtNominal->fps_numerator) / static_cast<double>(fmtNominal->fps_denominator); @@ -772,9 +1010,84 @@ STDMETHODIMP DirectShowSource::BufferCB( double dblSampleTime, BYTE * pBuff, long buffSize ) { + /* I can find nothing in the DirectShow documentation about scaling an image. Not */ + /* a thing -after hours of searching. I can only conclude that it isn't an exposed */ + /* API. It may not even exist. If the native format does not match the output */ + /* format, and we need to, scale the sample */ + if( !nativeMediaTypeSufficient_ ) + { + /* If we are here, the nativeMediaType used was not sufficient to get us to the */ + /* desired output to which we bound. So we asked DirectShow to give us RGB */ + /* samples at any size it could manage. So now we have an RGB sample buffer */ + /* described by fmtRealSample_ and we wish to convert it to a sample buffer */ + /* that matches fmtFauxSample_ (which is what we told the client we would give */ + /* it). Note one more twist to the story -DirectShow vertically flips the */ + /* sample buffer, so even if the frame size matches, we need to copy it anyway. */ + ScaleAndFlipImage( + pBuff, fmtRealSample_.width, fmtRealSample_.height, + buffer_, fmtFauxSample_.width, fmtFauxSample_.height ); + pBuff = buffer_; + buffSize = bufferSize_; + } + return bufferCB_(dblSampleTime, pBuff, buffSize, parent_); } +void DirectShowSource::ScaleAndFlipImage( + const BYTE * inBuff, int inWidth, int inHeight, + BYTE * outBuff, int outWidth, int outHeight ) +{ + int i; + int j; + + if( inBuff != NULL && outBuff != NULL ) + { + if( inWidth == outWidth && + inHeight == outHeight ) + { + /* Just vertically flip the data */ + for( i = 0; i < outHeight; i++ ) + { + memcpy( + outBuff + i * outWidth * 4, + inBuff + (inHeight - i - 1) * inWidth * 4, + outWidth * 4 ); + } + } + else + { + /* Nearest neighbor. Not awesome, but not bad */ + int heightTally = max( inHeight, outHeight ); + int srcRowIndex = 0; + for( i = 0; i < outHeight; i++ ) + { + while( heightTally < inHeight ) + { + heightTally += outHeight; + srcRowIndex++; + } + heightTally -= inHeight; + + int widthTally = max( inWidth, outWidth ); + int srcColIndex = 0; + for( j = 0; j < outWidth; j++ ) + { + while( widthTally < inWidth ) + { + widthTally += outWidth; + srcColIndex++; + } + widthTally -= inWidth; + + *(__int32 *)(outBuff + (i * outWidth + j) * 4) = + *(__int32 *)(inBuff + ((inHeight - srcRowIndex - 1) * + inWidth + srcColIndex) * 4); + } + } + } + } +} + int DirectShowSource::mapDirectShowMediaTypeToVidcapFourcc(DWORD data, int & fourcc) { Modified: trunk/src/directshow/DirectShowSource.h =================================================================== --- trunk/src/directshow/DirectShowSource.h 2010-02-01 19:00:34 UTC (rev 101) +++ trunk/src/directshow/DirectShowSource.h 2010-02-01 19:29:00 UTC (rev 102) @@ -48,7 +48,7 @@ void stop(); int bindFormat(const vidcap_fmt_info * fmtInfo); int validateFormat(const vidcap_fmt_info * fmtNominal, - vidcap_fmt_info * fmtNative) const; + vidcap_fmt_info * fmtNative, int forBinding) const; typedef void (*graphEventCBFunc)(void *); static void processGraphEvent(void *); @@ -70,10 +70,15 @@ AM_MEDIA_TYPE **candidateMediaFormat) const; bool findBestFormat(const vidcap_fmt_info * fmtNominal, vidcap_fmt_info * fmtNative, AM_MEDIA_TYPE **mediaFormat) const; + bool findUsableFormat( const vidcap_fmt_info *fmtNominal, + vidcap_fmt_info * fmtNative, AM_MEDIA_TYPE **mediaFormat, bool forSampling ) const; + bool findBestCapability( const vidcap_fmt_info *fmtNominal, int &bestFormat ) const; void freeMediaType(AM_MEDIA_TYPE &) const; bool getCaptureDevice(const char *devLongName, IBindCtx **ppBindCtx, IMoniker **ppMoniker) const; + void ScaleAndFlipImage( const BYTE * inBuff, int inWidth, int inHeight, + BYTE * outBuff, int outWidth, int outHeight ); // Fake out COM STDMETHODIMP_(ULONG) AddRef() { return 2; } @@ -110,6 +115,13 @@ AM_MEDIA_TYPE *nativeMediaType_; HANDLE *graphHandle_; bool graphIsSetup_; + + mutable bool nativeMediaTypeSufficient_; + mutable AM_MEDIA_TYPE outputMediaType_; + mutable BYTE * buffer_; + mutable long bufferSize_; + mutable vidcap_fmt_info fmtRealSample_; + mutable vidcap_fmt_info fmtFauxSample_; }; #endif Modified: trunk/src/directshow/SourceStateMachine.cpp =================================================================== --- trunk/src/directshow/SourceStateMachine.cpp 2010-02-01 19:00:34 UTC (rev 101) +++ trunk/src/directshow/SourceStateMachine.cpp 2010-02-01 19:29:00 UTC (rev 102) @@ -427,9 +427,9 @@ int SourceStateMachine::validateFormat(const vidcap_fmt_info * fmtNominal, - vidcap_fmt_info * fmtNative) const + vidcap_fmt_info * fmtNative, int forBinding) const { - return src_->validateFormat(fmtNominal, fmtNative); + return src_->validateFormat(fmtNominal, fmtNative, forBinding); } int Modified: trunk/src/directshow/SourceStateMachine.h =================================================================== --- trunk/src/directshow/SourceStateMachine.h 2010-02-01 19:00:34 UTC (rev 101) +++ trunk/src/directshow/SourceStateMachine.h 2010-02-01 19:29:00 UTC (rev 102) @@ -39,7 +39,7 @@ int stop(); int bindFormat(const vidcap_fmt_info * fmtInfo); int validateFormat(const vidcap_fmt_info * fmtNominal, - vidcap_fmt_info * fmtNative) const; + vidcap_fmt_info * fmtNative, int forBinding) const; const char * getID() const { Modified: trunk/src/sapi.c =================================================================== --- trunk/src/sapi.c 2010-02-01 19:00:34 UTC (rev 101) +++ trunk/src/sapi.c 2010-02-01 19:29:00 UTC (rev 102) @@ -131,6 +131,11 @@ int sapi_src_format_list_build(struct sapi_src_context * src_ctx) { +/* Go through the "hot list" and see which ones are natively supported by the device. */ +/* Note that QuickTime supports all formats within reason (it only checks for sensible */ +/* framerates and frame sizes). Windows will do the same -all formats within reason. */ +/* Don't know what Linux will do for now. */ + struct vidcap_fmt_info fmt_info; struct vidcap_fmt_info * list = 0; int list_len = 0; @@ -138,7 +143,7 @@ if ( src_ctx->fmt_list ) { - log_error("source alread has format list\n"); + log_error("source already has format list\n"); return -1; } @@ -162,7 +167,8 @@ if ( !src_ctx->format_validate(src_ctx, &fmt_info, - &fmt_native) ) + &fmt_native, + 0) ) continue; list = realloc(list, Modified: trunk/src/sapi_context.h =================================================================== --- trunk/src/sapi_context.h 2010-02-01 19:00:34 UTC (rev 101) +++ trunk/src/sapi_context.h 2010-02-01 19:29:00 UTC (rev 102) @@ -49,7 +49,7 @@ int (*format_validate)(struct sapi_src_context *, const struct vidcap_fmt_info * fmt_nominal, - struct vidcap_fmt_info * fmt_native); + struct vidcap_fmt_info * fmt_native, int forBinding); int (*format_bind)(struct sapi_src_context *, const struct vidcap_fmt_info *); Modified: trunk/src/sapi_dshow.cpp =================================================================== --- trunk/src/sapi_dshow.cpp 2010-02-01 19:00:34 UTC (rev 101) +++ trunk/src/sapi_dshow.cpp 2010-02-01 19:29:00 UTC (rev 102) @@ -40,12 +40,12 @@ static int source_format_validate(struct sapi_src_context * src_ctx, const struct vidcap_fmt_info * fmt_nominal, - struct vidcap_fmt_info * fmt_native) + struct vidcap_fmt_info * fmt_native, int forBinding) { SourceStateMachine * dshow_src = static_cast<SourceStateMachine *>(src_ctx->priv); - return dshow_src->validateFormat(fmt_nominal, fmt_native); + return dshow_src->validateFormat(fmt_nominal, fmt_native, forBinding); } static int Modified: trunk/src/sapi_qt.c =================================================================== --- trunk/src/sapi_qt.c 2010-02-01 19:00:34 UTC (rev 101) +++ trunk/src/sapi_qt.c 2010-02-01 19:29:00 UTC (rev 102) @@ -151,6 +151,28 @@ } static int +map_nominal_fourcc_to_native_fourcc(int nominal_fourcc) +{ +/* Convert the format we want to the format to ask for from the device. */ + + switch ( nominal_fourcc ) + { + case VIDCAP_FOURCC_RGB32: + case VIDCAP_FOURCC_YUY2: + case VIDCAP_FOURCC_2VUY: + return nominal_fourcc; + + case VIDCAP_FOURCC_RGB555: + case VIDCAP_FOURCC_RGB24: + case VIDCAP_FOURCC_YVU9: + case VIDCAP_FOURCC_I420: + default: + return VIDCAP_FOURCC_RGB32; + } +} + + +static int src_info_from_src(struct vidcap_src_info * src_info, const struct sg_source * src) { @@ -516,28 +538,61 @@ static int source_format_validate(struct sapi_src_context * src_ctx, const struct vidcap_fmt_info * fmt_nominal, - struct vidcap_fmt_info * fmt_native) + struct vidcap_fmt_info * fmt_native, int forBinding) { +/* This is called in two cases: */ +/* 1) when the "hot list" of supported formats is built, i.e. those that libvidcap */ +/* tells the client the digitizer can offer. */ +/* 2) when the actual desired format is bound. */ +/* forBinding indicates how this function is being used. If it is 0, we are */ +/* looking for formats that are natively, or very nearly natively supported by the */ +/* device, i.e. we are building the supported formats list. If it is 1, we are */ +/* attempting to bind to a format, i.e. a client is asking for a specific format. */ +/* In that case, we may relax the rules, and be more flexible about what can be */ +/* accepted. The quality in this latter case may suffer, but it will still work. */ +/* The function result is a bool. True on success. */ + struct sapi_qt_src_context * qt_src_ctx = (struct sapi_qt_src_context *)src_ctx->priv; + /* Set the native device format to the requested format */ *fmt_native = *fmt_nominal; - if ( map_ostype_to_fourcc(qt_src_ctx->src->native_pixel_format, - &fmt_native->fourcc) ) - /* We can always squeeze RGB32 out of quicktime */ + if( !forBinding ) + { + /* Convert the QuickTime constant representing the device native color space */ + /* into an equivalent libvidcap constant. If the function returns non-zero, */ + /* that means we don't directly support the device native color space, and the */ + /* device should be asked for RGB instead (via behind the scenes QuickTime */ + /* translation) */ + if ( map_ostype_to_fourcc( qt_src_ctx->src->native_pixel_format, &fmt_native->fourcc ) ) fmt_native->fourcc = VIDCAP_FOURCC_RGB32; + /* If building the format list, we want strict validation of nominal format */ if ( !sg_source_format_validate(qt_src_ctx->src, fmt_native->width, fmt_native->height, (float)fmt_native->fps_numerator / (float)fmt_native->fps_denominator) ) return 0; - if ( !sapi_can_convert_native_to_nominal(fmt_native, fmt_nominal) ) return 0; + } + else + { + /* If binding, pretty much any format will be fine */ + if( fmt_native->width < 16 || fmt_native->width > 65536 ) + return 0; + if( fmt_native->height < 16 || fmt_native->height > 65536 ) + return 0; + if( (float)fmt_native->fps_numerator / + (float)fmt_native->fps_denominator <= 0 ) + return 0; + /* Find out what we can best set the device to to get the desired color space */ + fmt_native->fourcc = map_nominal_fourcc_to_native_fourcc( fmt_nominal->fourcc ); + } + return 1; } Modified: trunk/src/sapi_v4l.c =================================================================== --- trunk/src/sapi_v4l.c 2010-02-01 19:00:34 UTC (rev 101) +++ trunk/src/sapi_v4l.c 2010-02-01 19:29:00 UTC (rev 102) @@ -658,7 +658,7 @@ static int source_format_validate(struct sapi_src_context * src_ctx, const struct vidcap_fmt_info * fmt_nominal, - struct vidcap_fmt_info * fmt_native) + struct vidcap_fmt_info * fmt_native, int forBinding ) { struct sapi_v4l_src_context * v4l_src_ctx = (struct sapi_v4l_src_context *)src_ctx->priv; Modified: trunk/src/vidcap.c =================================================================== --- trunk/src/vidcap.c 2010-02-01 19:00:34 UTC (rev 101) +++ trunk/src/vidcap.c 2010-02-01 19:29:00 UTC (rev 102) @@ -454,7 +454,7 @@ fmt_info = &src_ctx->fmt_list[0]; } - if ( !src_ctx->format_validate(src_ctx, fmt_info, &fmt_native) ) + if ( !src_ctx->format_validate(src_ctx, fmt_info, &fmt_native, 1) ) { log_error("format not supported by source: %dx%d %s %d/%d fps\n", fmt_info->width, fmt_info->height, This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. <lib...@li...> - 2010-02-01 19:00:40
|
Revision: 101 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=101&view=rev Author: bcholew Date: 2010-02-01 19:00:34 +0000 (Mon, 01 Feb 2010) Log Message: ----------- Fix bug/crash in DirectShow-specific code (not reached by most devices). Use height instead of width when stepping through rows of the source image buffer - in function ScaleAndFlipImage(). Courtesy of Chris Cooksey Modified Paths: -------------- branches/framesize_enhancements/src/directshow/DirectShowSource.cpp Modified: branches/framesize_enhancements/src/directshow/DirectShowSource.cpp =================================================================== --- branches/framesize_enhancements/src/directshow/DirectShowSource.cpp 2009-10-01 18:41:23 UTC (rev 100) +++ branches/framesize_enhancements/src/directshow/DirectShowSource.cpp 2010-02-01 19:00:34 UTC (rev 101) @@ -1050,7 +1050,7 @@ { memcpy( outBuff + i * outWidth * 4, - inBuff + (inWidth - i - 1) * inWidth * 4, + inBuff + (inHeight - i - 1) * inWidth * 4, outWidth * 4 ); } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. <lib...@li...> - 2009-10-01 18:41:37
|
Revision: 100 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=100&view=rev Author: bcholew Date: 2009-10-01 18:41:23 +0000 (Thu, 01 Oct 2009) Log Message: ----------- sync with trunk (revs 97, 98) Modified Paths: -------------- branches/framesize_enhancements/configure.ac branches/framesize_enhancements/examples/Makefile.am branches/framesize_enhancements/examples/vidcapTester/GrabberManager.h branches/framesize_enhancements/examples/vidcapTester/vidcapTester.cpp branches/framesize_enhancements/vidcap.pc.in Modified: branches/framesize_enhancements/configure.ac =================================================================== --- branches/framesize_enhancements/configure.ac 2009-09-30 14:17:38 UTC (rev 99) +++ branches/framesize_enhancements/configure.ac 2009-10-01 18:41:23 UTC (rev 100) @@ -61,6 +61,7 @@ if test "x$have_quicktime" = "xyes"; then AC_DEFINE(HAVE_QUICKTIME, [], [quicktime headers present]) + LIBS="-framework Carbon -framework QuartzCore -framework QuickTime" fi if test "x$have_directshow" = "xyes"; then Modified: branches/framesize_enhancements/examples/Makefile.am =================================================================== --- branches/framesize_enhancements/examples/Makefile.am 2009-09-30 14:17:38 UTC (rev 99) +++ branches/framesize_enhancements/examples/Makefile.am 2009-10-01 18:41:23 UTC (rev 100) @@ -9,11 +9,4 @@ simplegrab_SOURCES = simplegrab.c -if HAVE_QUICKTIME -AM_LDFLAGS += \ - -framework Carbon \ - -framework QuartzCore \ - -framework QuickTime -endif - EXTRA_DIST = vidcapTester Modified: branches/framesize_enhancements/examples/vidcapTester/GrabberManager.h =================================================================== --- branches/framesize_enhancements/examples/vidcapTester/GrabberManager.h 2009-09-30 14:17:38 UTC (rev 99) +++ branches/framesize_enhancements/examples/vidcapTester/GrabberManager.h 2009-10-01 18:41:23 UTC (rev 100) @@ -27,7 +27,7 @@ void rescanDevices(); private: - typedef struct mySourceContext + struct mySourceContext { Grabber * grabber; MainWindow * window; Modified: branches/framesize_enhancements/examples/vidcapTester/vidcapTester.cpp =================================================================== --- branches/framesize_enhancements/examples/vidcapTester/vidcapTester.cpp 2009-09-30 14:17:38 UTC (rev 99) +++ branches/framesize_enhancements/examples/vidcapTester/vidcapTester.cpp 2009-10-01 18:41:23 UTC (rev 100) @@ -1,3 +1,4 @@ +#include <cstdlib> #include <stdexcept> #include <QApplication> @@ -109,7 +110,7 @@ } catch ( const std::runtime_error & e ) { - qCritical(e.what()); + qCritical("%s", e.what()); usage(); return 1; } Modified: branches/framesize_enhancements/vidcap.pc.in =================================================================== --- branches/framesize_enhancements/vidcap.pc.in 2009-09-30 14:17:38 UTC (rev 99) +++ branches/framesize_enhancements/vidcap.pc.in 2009-10-01 18:41:23 UTC (rev 100) @@ -6,7 +6,7 @@ Name: vidcap Description: Cross-platform video capture library Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lvidcap @PTHREAD_LIBS@ +Libs: -L${libdir} -lvidcap @LIBS@ @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. <lib...@li...> - 2009-09-29 19:50:27
|
Revision: 98 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=98&view=rev Author: bcholew Date: 2009-09-29 19:33:31 +0000 (Tue, 29 Sep 2009) Log Message: ----------- Fix vidcapTester to build against gcc-4.3. Remove unneeded typedef. Changes courtesy of Pete Grayson. Modified Paths: -------------- trunk/examples/vidcapTester/GrabberManager.h trunk/examples/vidcapTester/vidcapTester.cpp Modified: trunk/examples/vidcapTester/GrabberManager.h =================================================================== --- trunk/examples/vidcapTester/GrabberManager.h 2009-09-29 19:25:28 UTC (rev 97) +++ trunk/examples/vidcapTester/GrabberManager.h 2009-09-29 19:33:31 UTC (rev 98) @@ -27,7 +27,7 @@ void rescanDevices(); private: - typedef struct mySourceContext + struct mySourceContext { Grabber * grabber; MainWindow * window; Modified: trunk/examples/vidcapTester/vidcapTester.cpp =================================================================== --- trunk/examples/vidcapTester/vidcapTester.cpp 2009-09-29 19:25:28 UTC (rev 97) +++ trunk/examples/vidcapTester/vidcapTester.cpp 2009-09-29 19:33:31 UTC (rev 98) @@ -1,3 +1,4 @@ +#include <cstdlib> #include <stdexcept> #include <QApplication> @@ -109,7 +110,7 @@ } catch ( const std::runtime_error & e ) { - qCritical(e.what()); + qCritical("%s", e.what()); usage(); return 1; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. <lib...@li...> - 2009-09-29 19:25:38
|
Revision: 97 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=97&view=rev Author: bcholew Date: 2009-09-29 19:25:28 +0000 (Tue, 29 Sep 2009) Log Message: ----------- Set LIBS appropriately in configure.ac and use LIBS in vidcap.pc.in. This allows users of libvidcap to be able to get the correct link-time flags on Mac from vidcap.pc. This is modeled after portaudio. This change courtesy of Pete Grayson. Modified Paths: -------------- trunk/configure.ac trunk/examples/Makefile.am trunk/vidcap.pc.in Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2009-08-07 19:39:26 UTC (rev 96) +++ trunk/configure.ac 2009-09-29 19:25:28 UTC (rev 97) @@ -61,6 +61,7 @@ if test "x$have_quicktime" = "xyes"; then AC_DEFINE(HAVE_QUICKTIME, [], [quicktime headers present]) + LIBS="-framework Carbon -framework QuartzCore -framework QuickTime" fi if test "x$have_directshow" = "xyes"; then Modified: trunk/examples/Makefile.am =================================================================== --- trunk/examples/Makefile.am 2009-08-07 19:39:26 UTC (rev 96) +++ trunk/examples/Makefile.am 2009-09-29 19:25:28 UTC (rev 97) @@ -9,11 +9,4 @@ simplegrab_SOURCES = simplegrab.c -if HAVE_QUICKTIME -AM_LDFLAGS += \ - -framework Carbon \ - -framework QuartzCore \ - -framework QuickTime -endif - EXTRA_DIST = vidcapTester Modified: trunk/vidcap.pc.in =================================================================== --- trunk/vidcap.pc.in 2009-08-07 19:39:26 UTC (rev 96) +++ trunk/vidcap.pc.in 2009-09-29 19:25:28 UTC (rev 97) @@ -6,7 +6,7 @@ Name: vidcap Description: Cross-platform video capture library Version: @PACKAGE_VERSION@ -Libs: -L${libdir} -lvidcap @PTHREAD_LIBS@ +Libs: -L${libdir} -lvidcap @LIBS@ @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. <lib...@li...> - 2009-08-07 19:39:34
|
Revision: 96 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=96&view=rev Author: bcholew Date: 2009-08-07 19:39:26 +0000 (Fri, 07 Aug 2009) Log Message: ----------- branch for Chris Cooksey's work on honoring requests for framesizes that aren't natively supported by a device Added Paths: ----------- branches/framesize_enhancements/ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. <lib...@li...> - 2008-06-25 15:19:58
|
Revision: 95 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=95&view=rev Author: jpgrayson Date: 2008-06-25 08:19:55 -0700 (Wed, 25 Jun 2008) Log Message: ----------- Fix log message. Modified Paths: -------------- trunk/examples/simplegrab.c Modified: trunk/examples/simplegrab.c =================================================================== --- trunk/examples/simplegrab.c 2008-04-28 19:16:42 UTC (rev 94) +++ trunk/examples/simplegrab.c 2008-06-25 15:19:55 UTC (rev 95) @@ -530,7 +530,7 @@ char * fmt_str; - log_info("Starting defaults\n"); + log_info("Starting double defaults\n"); if ( !(vc = vidcap_initialize()) ) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. <lib...@li...> - 2008-04-28 19:17:51
|
Revision: 94 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=94&view=rev Author: bcholew Date: 2008-04-28 12:16:42 -0700 (Mon, 28 Apr 2008) Log Message: ----------- fix to detect video device insertion/removal on Vista Modified Paths: -------------- trunk/src/directshow/DevMonitor.cpp trunk/src/directshow/DevMonitor.h Modified: trunk/src/directshow/DevMonitor.cpp =================================================================== --- trunk/src/directshow/DevMonitor.cpp 2008-04-04 15:20:27 UTC (rev 93) +++ trunk/src/directshow/DevMonitor.cpp 2008-04-28 19:16:42 UTC (rev 94) @@ -26,7 +26,6 @@ #include <dbt.h> #include <process.h> #include <string> -#include "sapi_context.h" #include "DevMonitor.h" #include "logging.h" @@ -148,6 +147,9 @@ WPARAM wParam, LPARAM lParam) { + static DevMonitor *pDevMon = 0; + LPCREATESTRUCT lpcstr = 0; + switch (message) { case WM_CLOSE: @@ -168,6 +170,19 @@ PostQuitMessage(0); break; + case WM_CREATE: + // hold on to context for use when WM_DEVICECHANGE occurs + lpcstr = (LPCREATESTRUCT)lParam; + pDevMon = (DevMonitor *)lpcstr->lpCreateParams; + break; + + case WM_DEVICECHANGE: + if ( !pDevMon ) + log_error("Got WM_DEVICECHANGE event, but have no context!\n"); + else + pDevMon->handleDeviceChange(wParam); + break; + default: return DefWindowProc(hWnd, message, wParam, lParam); } @@ -175,6 +190,77 @@ return 0; } +void +DevMonitor::handleDeviceChange(WPARAM wParam) +{ + std::string str; + + switch (wParam) + { + case DBT_CONFIGCHANGECANCELED: + str.assign("DBT_CONFIGCHANGECANCELED"); + break; + case DBT_CONFIGCHANGED: + str.assign("DBT_CONFIGCHANGED"); + break; + case DBT_CUSTOMEVENT: + str.assign("DBT_CUSTOMEVENT"); + break; + case DBT_DEVICEARRIVAL: + str.assign("DBT_DEVICEARRIVAL"); + break; + case DBT_DEVICEQUERYREMOVE: + str.assign("DBT_DEVICEQUERYREMOVE"); + break; + case DBT_DEVICEQUERYREMOVEFAILED: + str.assign("DBT_DEVICEQUERYREMOVEFAILED"); + break; + case DBT_DEVICEREMOVECOMPLETE: + str.assign("DBT_DEVICEREMOVECOMPLETE"); + break; + case DBT_DEVICEREMOVEPENDING: + str.assign("DBT_DEVICEREMOVEPENDING"); + break; + case DBT_DEVICETYPESPECIFIC: + str.assign("DBT_DEVICETYPESPECIFIC"); + break; + case DBT_DEVNODES_CHANGED: + str.assign("DBT_DEVNODES_CHANGED"); + break; + case DBT_QUERYCHANGECONFIG: + str.assign("DBT_QUERYCHANGECONFIG"); + break; + case DBT_USERDEFINED: + str.assign("DBT_USERDEFINED"); + break; + default: + str.assign("default"); + break; + } + + log_info("[[ Device event: %s ]]\n", str.c_str()); + + vc_mutex_lock(®istrationMutex_); + + if ( sapiCtx_ && + sapiCtx_->notify_callback ) + { + // TODO: If the user returns non-zero from + // their callback, maybe that should have + // some semantic meaning. For example, maybe + // that should be a way that the user can + // cancel further notification callbacks. + sapiCtx_->notify_callback(sapiCtx_, sapiCtx_->notify_data); + } + else + { + log_info("[[ no user-defined handler registered ]]\n"); + } + + vc_mutex_unlock(®istrationMutex_); + +} + unsigned int DevMonitor::monitorDevices(void * param) { @@ -183,7 +269,8 @@ // extract instance DevMonitor * pDevMon = (DevMonitor *)param; - // Create a window, so main thread can communicate with us + // Create a window, so we can receive device events. + // Pass context for delivery via WM_CREATE event pDevMon->windowHandle_ = CreateWindow( pDevMon->szWindowClass_, pDevMon->szTitle_, @@ -195,7 +282,7 @@ NULL, NULL, (HINSTANCE)0, - NULL); + param); if ( !pDevMon->windowHandle_ ) { @@ -225,83 +312,18 @@ // Main message loop // Breaks out when PostQuitMessage() is called MSG msg; - while (GetMessage(&msg, NULL, 0, 0)) + int ret; + while ( (ret = GetMessage(&msg, NULL, 0, 0)) != 0 ) { - std::string str; - - sapi_context * sapiCtx = - static_cast<sapi_context *>(pDevMon->sapiCtx_); - - switch (msg.message) + if ( ret == -1 ) { - case WM_DEVICECHANGE: - switch(msg.wParam) - { - case DBT_CONFIGCHANGECANCELED: - str.assign("DBT_CONFIGCHANGECANCELED"); + log_error("[[ GetMessage() returned error. [%d] ]]\n", + GetLastError()); break; - case DBT_CONFIGCHANGED: - str.assign("DBT_CONFIGCHANGED"); - break; - case DBT_CUSTOMEVENT: - str.assign("DBT_CUSTOMEVENT"); - break; - case DBT_DEVICEARRIVAL: - str.assign("DBT_DEVICEARRIVAL"); - break; - case DBT_DEVICEQUERYREMOVE: - str.assign("DBT_DEVICEQUERYREMOVE"); - break; - case DBT_DEVICEQUERYREMOVEFAILED: - str.assign("DBT_DEVICEQUERYREMOVEFAILED"); - break; - case DBT_DEVICEREMOVECOMPLETE: - str.assign("DBT_DEVICEREMOVECOMPLETE"); - break; - case DBT_DEVICEREMOVEPENDING: - str.assign("DBT_DEVICEREMOVEPENDING"); - break; - case DBT_DEVICETYPESPECIFIC: - str.assign("DBT_DEVICETYPESPECIFIC"); - break; - case DBT_DEVNODES_CHANGED: - str.assign("DBT_DEVNODES_CHANGED"); - break; - case DBT_QUERYCHANGECONFIG: - str.assign("DBT_QUERYCHANGECONFIG"); - break; - case DBT_USERDEFINED: - str.assign("DBT_USERDEFINED"); - break; - default: - str.assign("default"); - break; } - log_info("[[ Device event: %s ]]\n", str.c_str()); - - vc_mutex_lock(&pDevMon->registrationMutex_); - - if ( sapiCtx && - sapiCtx->notify_callback ) - { - // TODO: If the user returns non-zero from - // their callback, maybe that should have - // some semantic meaning. For example, maybe - // that should be a way that the user can - // cancel further notification callbacks. - sapiCtx->notify_callback(sapiCtx, sapiCtx->notify_data); - } else { - log_info("[[ no user-defined handler registered ]]\n"); - } - - vc_mutex_unlock(&pDevMon->registrationMutex_); - - default: - str.assign(""); DispatchMessage(&msg); - break; } } @@ -317,7 +339,7 @@ vc_mutex_lock(®istrationMutex_); - sapiCtx_ = sapiCtx; + sapiCtx_ = static_cast<sapi_context *>(sapiCtx); vc_mutex_unlock(®istrationMutex_); Modified: trunk/src/directshow/DevMonitor.h =================================================================== --- trunk/src/directshow/DevMonitor.h 2008-04-04 15:20:27 UTC (rev 93) +++ trunk/src/directshow/DevMonitor.h 2008-04-28 19:16:42 UTC (rev 94) @@ -26,6 +26,7 @@ #define _DEVMONITOR_H_ #include <vidcap/vidcap.h> +#include "sapi_context.h" class DevMonitor { @@ -38,6 +39,7 @@ private: static LRESULT __stdcall processWindowsMsgs(HWND, UINT, WPARAM, LPARAM); static unsigned int STDCALL monitorDevices(void * lpParam); + void handleDeviceChange(WPARAM wParam); private: HANDLE initDoneEvent_; @@ -50,7 +52,7 @@ TCHAR * szTitle_; TCHAR * szWindowClass_; - void * sapiCtx_; + sapi_context * sapiCtx_; vc_mutex registrationMutex_; }; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. <lib...@li...> - 2008-04-04 15:21:28
|
Revision: 93 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=93&view=rev Author: jpgrayson Date: 2008-04-04 08:20:27 -0700 (Fri, 04 Apr 2008) Log Message: ----------- Set libvidcap version to 0.2.1 in tag. Modified Paths: -------------- tags/0.2.1/configure.ac Modified: tags/0.2.1/configure.ac =================================================================== --- tags/0.2.1/configure.ac 2008-04-04 15:03:54 UTC (rev 92) +++ tags/0.2.1/configure.ac 2008-04-04 15:20:27 UTC (rev 93) @@ -3,7 +3,7 @@ AC_PREREQ(2.59) dnl package version -m4_define(VIDCAP_VERSION, [0.3-svn]) +m4_define(VIDCAP_VERSION, [0.2.1]) AC_INIT([libvidcap], VIDCAP_VERSION, [jpg...@gm...]) AC_CONFIG_SRCDIR([include/vidcap/vidcap.h]) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. <lib...@li...> - 2008-04-04 15:03:58
|
Revision: 92 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=92&view=rev Author: jpgrayson Date: 2008-04-04 08:03:54 -0700 (Fri, 04 Apr 2008) Log Message: ----------- Tagging libvidcap 0.2.1. Added Paths: ----------- tags/0.2.1/ Copied: tags/0.2.1 (from rev 91, trunk) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. <lib...@li...> - 2008-04-04 15:01:47
|
Revision: 91 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=91&view=rev Author: jpgrayson Date: 2008-04-04 08:01:46 -0700 (Fri, 04 Apr 2008) Log Message: ----------- Add EXTRA_DIST so that contrib directory is included in release tarballs. Modified Paths: -------------- trunk/Makefile.am Modified: trunk/Makefile.am =================================================================== --- trunk/Makefile.am 2008-04-03 23:23:32 UTC (rev 90) +++ trunk/Makefile.am 2008-04-04 15:01:46 UTC (rev 91) @@ -3,5 +3,9 @@ pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = vidcap.pc +EXTRA_DIST = \ + autogen.sh \ + contrib + dist-hook: find $(distdir) -name ".svn" -type d -print0 | xargs -0 rm -rf This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. <lib...@li...> - 2008-04-03 23:23:35
|
Revision: 90 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=90&view=rev Author: jpgrayson Date: 2008-04-03 16:23:32 -0700 (Thu, 03 Apr 2008) Log Message: ----------- Get the trunk version ready for the next release. Update to latest libtool version (1:0:0). Modified Paths: -------------- trunk/configure.ac Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2008-04-03 23:22:34 UTC (rev 89) +++ trunk/configure.ac 2008-04-03 23:23:32 UTC (rev 90) @@ -3,7 +3,7 @@ AC_PREREQ(2.59) dnl package version -m4_define(VIDCAP_VERSION, [0.2-svn]) +m4_define(VIDCAP_VERSION, [0.3-svn]) AC_INIT([libvidcap], VIDCAP_VERSION, [jpg...@gm...]) AC_CONFIG_SRCDIR([include/vidcap/vidcap.h]) @@ -12,7 +12,7 @@ AM_MAINTAINER_MODE dnl libtool library version -VC_LT_CURRENT=0 +VC_LT_CURRENT=1 VC_LT_REVISION=0 VC_LT_AGE=0 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. <lib...@li...> - 2008-04-03 23:22:38
|
Revision: 89 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=89&view=rev Author: jpgrayson Date: 2008-04-03 16:22:34 -0700 (Thu, 03 Apr 2008) Log Message: ----------- Update package version number for release. Update libtool version to 1:0:0. Modified Paths: -------------- tags/0.2/configure.ac Modified: tags/0.2/configure.ac =================================================================== --- tags/0.2/configure.ac 2008-04-03 23:18:45 UTC (rev 88) +++ tags/0.2/configure.ac 2008-04-03 23:22:34 UTC (rev 89) @@ -3,7 +3,7 @@ AC_PREREQ(2.59) dnl package version -m4_define(VIDCAP_VERSION, [0.2-svn]) +m4_define(VIDCAP_VERSION, [0.2]) AC_INIT([libvidcap], VIDCAP_VERSION, [jpg...@gm...]) AC_CONFIG_SRCDIR([include/vidcap/vidcap.h]) @@ -12,7 +12,7 @@ AM_MAINTAINER_MODE dnl libtool library version -VC_LT_CURRENT=0 +VC_LT_CURRENT=1 VC_LT_REVISION=0 VC_LT_AGE=0 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. <lib...@li...> - 2008-04-03 23:18:47
|
Revision: 88 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=88&view=rev Author: jpgrayson Date: 2008-04-03 16:18:45 -0700 (Thu, 03 Apr 2008) Log Message: ----------- Tag for a 0.2 release. Added Paths: ----------- tags/0.2/ Copied: tags/0.2 (from rev 87, trunk) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. <lib...@li...> - 2008-04-03 23:16:41
|
Revision: 87 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=87&view=rev Author: jpgrayson Date: 2008-04-03 16:16:39 -0700 (Thu, 03 Apr 2008) Log Message: ----------- Remove some cruft from reference vcproj file. Modified Paths: -------------- trunk/contrib/win/vs2005/libvidcap.vcproj Modified: trunk/contrib/win/vs2005/libvidcap.vcproj =================================================================== --- trunk/contrib/win/vs2005/libvidcap.vcproj 2007-12-12 21:00:27 UTC (rev 86) +++ trunk/contrib/win/vs2005/libvidcap.vcproj 2008-04-03 23:16:39 UTC (rev 87) @@ -20,7 +20,6 @@ OutputDirectory="$(SolutionDir)\$(ConfigurationName)\$(ProjectName)" IntermediateDirectory="$(OutDir)" ConfigurationType="4" - UseOfATL="0" CharacterSet="1" > <Tool @@ -330,24 +329,6 @@ <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 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 21:00:43
|
Revision: 86 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=86&view=rev Author: bcholew Date: 2007-12-12 13:00:27 -0800 (Wed, 12 Dec 2007) Log Message: ----------- Turn off the capture timer thread. It's not useful right now. Modified Paths: -------------- trunk/src/vidcap.c Modified: trunk/src/vidcap.c =================================================================== --- trunk/src/vidcap.c 2007-12-12 20:58:59 UTC (rev 85) +++ trunk/src/vidcap.c 2007-12-12 21:00:27 UTC (rev 86) @@ -311,7 +311,7 @@ * allow an application to choose to forego this feature * and the associated overhead */ - src_ctx->use_timer_thread = 1; + src_ctx->use_timer_thread = 0; if ( src_ctx->use_timer_thread ) { 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:59:36
|
Revision: 85 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=85&view=rev Author: bcholew Date: 2007-12-12 12:58:59 -0800 (Wed, 12 Dec 2007) Log Message: ----------- Taybin Rutkin's mod for compiling under mingw. Modified Paths: -------------- trunk/src/os_funcs.h Modified: trunk/src/os_funcs.h =================================================================== --- trunk/src/os_funcs.h 2007-12-12 20:55:11 UTC (rev 84) +++ trunk/src/os_funcs.h 2007-12-12 20:58:59 UTC (rev 85) @@ -50,7 +50,7 @@ #include <process.h> #endif -#if defined(__MINGW32__) +#ifdef HAVE_STDINT_H #include <stdint.h> #endif 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. |
From: libvidcap c. <lib...@li...> - 2007-12-12 20:46:24
|
Revision: 83 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=83&view=rev Author: bcholew Date: 2007-12-12 12:46:06 -0800 (Wed, 12 Dec 2007) Log Message: ----------- Fixup help message to include -2 option. Improve command line argument parsing. Thanks Pete Grayson. Modified Paths: -------------- trunk/examples/simplegrab.c Modified: trunk/examples/simplegrab.c =================================================================== --- trunk/examples/simplegrab.c 2007-12-12 20:43:46 UTC (rev 82) +++ trunk/examples/simplegrab.c 2007-12-12 20:46:06 UTC (rev 83) @@ -210,6 +210,7 @@ " -q -- decrease libvidcap verbosity\n" " -e -- do enumeration test\n" " -d -- do defaults test\n" + " -2 -- do double default test\n" " -c -- do capture test\n" " -n -- do notification test\n"); } @@ -218,15 +219,6 @@ { int i; - if ( argc == 1 ) - { - opt_do_enumeration = 1; - opt_do_defaults = 1; - opt_do_double_default = 1; - opt_do_captures = 1; - opt_do_notifies = 1; - } - for ( i = 1; i < argc; ++i ) { if ( !strcmp(argv[i], "-e") ) @@ -253,6 +245,22 @@ } } + /* If none of the tests are explicitly set, then we go ahead + * and do all of them. + */ + if ( !(opt_do_enumeration || + opt_do_defaults || + opt_do_double_default || + opt_do_captures || + opt_do_notifies) ) + { + opt_do_enumeration = 1; + opt_do_defaults = 1; + opt_do_double_default = 1; + opt_do_captures = 1; + opt_do_notifies = 1; + } + return 0; } 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:43:52
|
Revision: 82 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=82&view=rev Author: bcholew Date: 2007-12-12 12:43:46 -0800 (Wed, 12 Dec 2007) Log Message: ----------- whitespace Modified Paths: -------------- trunk/src/sapi_qt.c Modified: trunk/src/sapi_qt.c =================================================================== --- trunk/src/sapi_qt.c 2007-12-12 20:25:17 UTC (rev 81) +++ trunk/src/sapi_qt.c 2007-12-12 20:43:46 UTC (rev 82) @@ -455,9 +455,9 @@ if ( errno != -EINTR ) { log_error("failed nanosleep() %d\n", errno); - ret = -8; - sapi_src_capture_notify(src_ctx, 0, 0, 0, ret); - goto bail; + ret = -8; + sapi_src_capture_notify(src_ctx, 0, 0, 0, ret); + goto bail; } } } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |