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...> - 2007-10-25 21:25:47
|
Revision: 56 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=56&view=rev Author: jpgrayson Date: 2007-10-25 14:25:46 -0700 (Thu, 25 Oct 2007) Log Message: ----------- Run with debug logging by default. Add -q option to run in quiet mode. Add -h option to print usage info. Modified Paths: -------------- trunk/examples/simplegrab.c Modified: trunk/examples/simplegrab.c =================================================================== --- trunk/examples/simplegrab.c 2007-10-25 21:23:37 UTC (rev 55) +++ trunk/examples/simplegrab.c 2007-10-25 21:25:46 UTC (rev 56) @@ -49,6 +49,7 @@ static int ctrl_c_pressed = 0; +static int opt_quiet = 0; static int opt_do_enumeration = 0; static int opt_do_defaults = 0; static int opt_do_captures = 0; @@ -201,6 +202,17 @@ ctrl_c_pressed = 1; } +static void usage(void) +{ + fprintf(stderr, "Usage: simplegrab [OPTIONS]\n" + " -h -- show this help message\n" + " -q -- decrease libvidcap verbosity\n" + " -e -- do enumeration test\n" + " -d -- do defaults test\n" + " -c -- do capture test\n" + " -n -- do notification test\n"); +} + static int process_command_line(int argc, char * argv[]) { int i; @@ -223,6 +235,13 @@ opt_do_captures = 1; else if ( !strcmp(argv[i], "-n") ) opt_do_notifies = 1; + else if ( !strcmp(argv[i], "-q") ) + opt_quiet += 1; + else if ( !strcmp(argv[i], "-h") ) + { + usage(); + exit(0); + } else { log_error("unknown option '%s'\n", argv[i]); @@ -742,8 +761,18 @@ int main(int argc, char * argv[]) { if ( process_command_line(argc, argv) ) + { + usage(); return 1; + } + if ( opt_quiet > 1 ) + vidcap_log_level_set(VIDCAP_LOG_WARN); + else if ( opt_quiet > 0 ) + vidcap_log_level_set(VIDCAP_LOG_INFO); + else + vidcap_log_level_set(VIDCAP_LOG_DEBUG); + if ( opt_do_enumeration && do_enumeration() ) 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...> - 2007-10-25 21:23:38
|
Revision: 55 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=55&view=rev Author: jpgrayson Date: 2007-10-25 14:23:37 -0700 (Thu, 25 Oct 2007) Log Message: ----------- Fix problem where it was impossible to set VIDCAP_LOG_LEVEL_DEBUG. Modified Paths: -------------- trunk/src/vidcap.c Modified: trunk/src/vidcap.c =================================================================== --- trunk/src/vidcap.c 2007-10-25 18:10:50 UTC (rev 54) +++ trunk/src/vidcap.c 2007-10-25 21:23:37 UTC (rev 55) @@ -153,6 +153,7 @@ break; case VIDCAP_LOG_DEBUG: log_level = log_level_debug; + break; default: return -1; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. m. <lib...@li...> - 2007-10-25 18:10:52
|
Revision: 54 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=54&view=rev Author: jpgrayson Date: 2007-10-25 11:10:50 -0700 (Thu, 25 Oct 2007) Log Message: ----------- Ensure that the members of sg_source are initialized properly in sg_source_anon_init(). There was a chance that during sg_source_acquire() a failure of one of the SG*() functions would lead to sg_source_release() being called with non-null members of the sg_source structure. Specifically, the gworld pointer would be non-null and then subsequently UnlockPixels would be called on a garbage pointer. Modified Paths: -------------- trunk/src/quicktime/sg_source.c Modified: trunk/src/quicktime/sg_source.c =================================================================== --- trunk/src/quicktime/sg_source.c 2007-10-18 14:25:11 UTC (rev 53) +++ trunk/src/quicktime/sg_source.c 2007-10-25 18:10:50 UTC (rev 54) @@ -44,6 +44,7 @@ int sg_source_anon_init(struct sg_source * src) { + memset(src, 0, sizeof(*src)); src->device_id = -1; src->input_id = -1; return 0; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. m. <lib...@li...> - 2007-10-18 14:25:17
|
Revision: 53 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=53&view=rev Author: bcholew Date: 2007-10-18 07:25:11 -0700 (Thu, 18 Oct 2007) Log Message: ----------- Update VIDCAP_VERSION for trunk. Modified Paths: -------------- trunk/configure.ac Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2007-10-18 14:21:52 UTC (rev 52) +++ trunk/configure.ac 2007-10-18 14:25:11 UTC (rev 53) @@ -3,7 +3,7 @@ AC_PREREQ(2.59) dnl package version -m4_define(VIDCAP_VERSION, [0.1]) +m4_define(VIDCAP_VERSION, [0.2-svn]) 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. m. <lib...@li...> - 2007-10-18 14:22:07
|
Revision: 52 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=52&view=rev Author: bcholew Date: 2007-10-18 07:21:52 -0700 (Thu, 18 Oct 2007) Log Message: ----------- First release: version 0.1 Added Paths: ----------- tags/0.1/ Copied: tags/0.1 (from rev 51, trunk) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. m. <lib...@li...> - 2007-10-18 13:45:55
|
Revision: 51 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=51&view=rev Author: bcholew Date: 2007-10-18 06:45:53 -0700 (Thu, 18 Oct 2007) Log Message: ----------- Windows builds: look for libvidcap.lib in new place. All builds: if qmake is run with an added 'CONFIG+=special_config', look for libvidcap.lib in an entirely different place. Modified Paths: -------------- trunk/examples/vidcapTester/vidcapTester.pro Modified: trunk/examples/vidcapTester/vidcapTester.pro =================================================================== --- trunk/examples/vidcapTester/vidcapTester.pro 2007-10-18 13:35:39 UTC (rev 50) +++ trunk/examples/vidcapTester/vidcapTester.pro 2007-10-18 13:45:53 UTC (rev 51) @@ -17,7 +17,12 @@ unix:{ INCLUDEPATH += ../../include - local_lib_path = ../../../local-$$platform/lib + CONFIG(special_config): { + local_lib_path = ../../../local-$$platform/lib + } + else { + local_lib_path = ../../src/.libs + } LIBS += $$local_lib_path/libvidcap.a } @@ -40,7 +45,12 @@ INCLUDEPATH += ../../include LIBS += -L\"$(PSDK_DIR)/Lib\" - LIBS += -L../../../build-win32/libvidcap/$$config_name + CONFIG(special_config): { + LIBS += -L../../../build-win32/libvidcap/$$config_name + } + else { + LIBS += -L../../contrib/win/vs2005/$$config_name/libvidcap + } LIBS += strmiids.lib LIBS += comsuppw.lib @@ -71,7 +81,12 @@ vidcapTester.cpp \ unix:{ - build_dir = ../../../build-$$platform/$$TARGET + CONFIG(special_config): { + build_dir = ../../../build-$$platform/$$TARGET + } + else { + build_dir = ../../build/$$TARGET + } DESTDIR = $$build_dir MOC_DIR = $$build_dir This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. m. <lib...@li...> - 2007-10-18 13:35:41
|
Revision: 50 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=50&view=rev Author: bcholew Date: 2007-10-18 06:35:39 -0700 (Thu, 18 Oct 2007) Log Message: ----------- Place the resultant lib in a better place. Modified Paths: -------------- trunk/contrib/win/vs2005/libvidcap.vcproj Modified: trunk/contrib/win/vs2005/libvidcap.vcproj =================================================================== --- trunk/contrib/win/vs2005/libvidcap.vcproj 2007-10-16 18:59:56 UTC (rev 49) +++ trunk/contrib/win/vs2005/libvidcap.vcproj 2007-10-18 13:35:39 UTC (rev 50) @@ -17,7 +17,7 @@ <Configurations> <Configuration Name="Debug|Win32" - OutputDirectory="..\..\..\..\build-win32\$(ProjectName)\$(ConfigurationName)" + OutputDirectory="$(SolutionDir)\$(ConfigurationName)\$(ProjectName)" IntermediateDirectory="$(OutDir)" ConfigurationType="4" UseOfATL="0" @@ -82,7 +82,7 @@ </Configuration> <Configuration Name="Release|Win32" - OutputDirectory="..\..\..\..\build-win32\$(ProjectName)\$(ConfigurationName)" + OutputDirectory="$(SolutionDir)\$(ConfigurationName)\$(ProjectName)" IntermediateDirectory="$(OutDir)" ConfigurationType="4" CharacterSet="1" This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. m. <lib...@li...> - 2007-10-16 19:00:03
|
Revision: 49 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=49&view=rev Author: bcholew Date: 2007-10-16 11:59:56 -0700 (Tue, 16 Oct 2007) Log Message: ----------- Handle failure to create new DShowSrcManager. Modified Paths: -------------- trunk/src/directshow/GraphMonitor.cpp trunk/src/sapi_dshow.cpp Modified: trunk/src/directshow/GraphMonitor.cpp =================================================================== --- trunk/src/directshow/GraphMonitor.cpp 2007-10-16 18:36:13 UTC (rev 48) +++ trunk/src/directshow/GraphMonitor.cpp 2007-10-16 18:59:56 UTC (rev 49) @@ -86,8 +86,6 @@ DWORD rc = WaitForSingleObject(initDoneEvent_, INFINITE); - return; - } GraphMonitor::~GraphMonitor() Modified: trunk/src/sapi_dshow.cpp =================================================================== --- trunk/src/sapi_dshow.cpp 2007-10-16 18:36:13 UTC (rev 48) +++ trunk/src/sapi_dshow.cpp 2007-10-16 18:59:56 UTC (rev 49) @@ -214,6 +214,12 @@ return -1; } + if ( sapi_ctx->priv == 0 ) + { + log_error("failed constructing DShowSrcManager\n"); + return -1; + } + sapi_ctx->identifier = identifier; sapi_ctx->description = description; sapi_ctx->acquire = sapi_acquire; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. m. <lib...@li...> - 2007-10-16 18:36:22
|
Revision: 48 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=48&view=rev Author: bcholew Date: 2007-10-16 11:36:13 -0700 (Tue, 16 Oct 2007) Log Message: ----------- Handle failure to create new SourceStateMachine. Remove 'signed' modifier for stride. Modified Paths: -------------- trunk/src/conv.c trunk/src/sapi.c trunk/src/sapi.h trunk/src/sapi_dshow.cpp Modified: trunk/src/conv.c =================================================================== --- trunk/src/conv.c 2007-10-12 18:09:35 UTC (rev 47) +++ trunk/src/conv.c 2007-10-16 18:36:13 UTC (rev 48) @@ -72,7 +72,7 @@ static const int conv_list_len = sizeof(conv_list) / sizeof(struct conv_info); static int -destride_packed(int image_byte_width, int height, signed int stride, +destride_packed(int image_byte_width, int height, int stride, const char * src, char * dst) { /* destride a packed structure */ @@ -100,7 +100,7 @@ destride_planar(int width, int height, int u_width, int u_height, int v_width, int v_height, - signed int y_stride, signed int u_stride, signed int v_stride, + int y_stride, int u_stride, int v_stride, const char * src, char * dst) { char * dst_y_even = dst; Modified: trunk/src/sapi.c =================================================================== --- trunk/src/sapi.c 2007-10-12 18:09:35 UTC (rev 47) +++ trunk/src/sapi.c 2007-10-16 18:36:13 UTC (rev 48) @@ -220,7 +220,7 @@ int sapi_src_capture_notify(struct sapi_src_context * src_ctx, const char * video_data, int video_data_size, - signed int stride, + int stride, int error_status) { struct vidcap_capture_info cap_info; Modified: trunk/src/sapi.h =================================================================== --- trunk/src/sapi.h 2007-10-12 18:09:35 UTC (rev 47) +++ trunk/src/sapi.h 2007-10-16 18:36:13 UTC (rev 48) @@ -47,7 +47,7 @@ int sapi_src_capture_notify(struct sapi_src_context * src_ctx, const char * video_data, int video_data_size, - signed int stride, + int stride, int error_status); int Modified: trunk/src/sapi_dshow.cpp =================================================================== --- trunk/src/sapi_dshow.cpp 2007-10-12 18:09:35 UTC (rev 47) +++ trunk/src/sapi_dshow.cpp 2007-10-16 18:36:13 UTC (rev 48) @@ -177,6 +177,13 @@ return -1; } + if ( src_ctx->priv == 0 ) + { + log_warn("failed constructing source state machine for '%s'\n", + src_info->identifier); + return -1; + } + // Save acquired source to the dshow-specific source context src_ctx->release = source_release; src_ctx->format_validate = source_format_validate; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. m. <lib...@li...> - 2007-10-12 18:09:37
|
Revision: 47 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=47&view=rev Author: bcholew Date: 2007-10-12 11:09:35 -0700 (Fri, 12 Oct 2007) Log Message: ----------- Add bottom-up rgb24 to conv_fmt_size_get(). Use proper fourcc in error message. Modified Paths: -------------- trunk/src/conv.c trunk/src/vidcap.c Modified: trunk/src/conv.c =================================================================== --- trunk/src/conv.c 2007-10-12 16:30:09 UTC (rev 46) +++ trunk/src/conv.c 2007-10-12 18:09:35 UTC (rev 47) @@ -243,6 +243,7 @@ return pixels * 3 / 2; case VIDCAP_FOURCC_RGB24: + case VIDCAP_FOURCC_BOTTOM_UP_RGB24: return pixels * 3; case VIDCAP_FOURCC_RGB32: Modified: trunk/src/vidcap.c =================================================================== --- trunk/src/vidcap.c 2007-10-12 16:30:09 UTC (rev 46) +++ trunk/src/vidcap.c 2007-10-12 18:09:35 UTC (rev 47) @@ -438,7 +438,7 @@ { log_error("failed to get stride-free buffer size for %s\n", vidcap_fourcc_string_get( - fmt_info->fourcc)); + src_ctx->fmt_native.fourcc)); return -1; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. m. <lib...@li...> - 2007-10-12 16:30:12
|
Revision: 46 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=46&view=rev Author: bcholew Date: 2007-10-12 09:30:09 -0700 (Fri, 12 Oct 2007) Log Message: ----------- Add generic support for images with strides. Make Mac version stride-aware. Keep linux and Windows builds stride-ignorant. Modified Paths: -------------- trunk/src/conv.c trunk/src/conv.h trunk/src/directshow/SourceStateMachine.cpp trunk/src/sapi.c trunk/src/sapi.h trunk/src/sapi_context.h trunk/src/sapi_qt.c trunk/src/sapi_v4l.c trunk/src/vidcap.c Modified: trunk/src/conv.c =================================================================== --- trunk/src/conv.c 2007-10-10 18:31:30 UTC (rev 45) +++ trunk/src/conv.c 2007-10-12 16:30:09 UTC (rev 46) @@ -23,7 +23,9 @@ * */ +#include "string.h" #include "conv.h" +#include "logging.h" int conv_2vuy_to_i420(int w, int h, const char * s, char * d); int conv_2vuy_to_yuy2(int w, int h, const char * s, char * d); @@ -69,6 +71,150 @@ static const int conv_list_len = sizeof(conv_list) / sizeof(struct conv_info); +static int +destride_packed(int image_byte_width, int height, signed int stride, + const char * src, char * dst) +{ + /* destride a packed structure */ + char * dst_even = dst; + char * dst_odd = dst + image_byte_width; + const char * src_even = src; + const char * src_odd = src + stride; + + int i; + for ( i = 0; i < height / 2; ++i ) + { + memcpy(dst_even, src_even, image_byte_width); + memcpy(dst_odd, src_odd, image_byte_width); + + dst_even += 2 * image_byte_width; + dst_odd += 2 * image_byte_width; + src_even += 2 * stride; + src_odd += 2 * stride; + } + + return 0; +} + +static int +destride_planar(int width, int height, + int u_width, int u_height, + int v_width, int v_height, + signed int y_stride, signed int u_stride, signed int v_stride, + const char * src, char * dst) +{ + char * dst_y_even = dst; + char * dst_y_odd = dst + width; + char * dst_u_even = dst + width * height; + 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; + + int i; + + for ( i = 0; i < height / 2; ++i ) + { + memcpy(dst_y_even, src_y_even, width); + memcpy(dst_y_odd, src_y_odd, width); + + dst_y_even += 2 * width; + dst_y_odd += 2 * width; + src_y_even += 2 * y_stride; + src_y_odd += 2 * y_stride; + } + + for ( i = 0; i < u_height / 2; ++i ) + { + memcpy(dst_u_even, src_u_even, u_width); + memcpy(dst_u_odd, src_u_odd, u_width); + + dst_u_even += 2 * u_width; + dst_u_odd += 2 * u_width; + src_u_even += 2 * u_stride; + src_u_odd += 2 * u_stride; + } + + for ( i = 0; i < v_height / 2; ++i ) + { + memcpy(dst_v_even, src_v_even, v_width); + memcpy(dst_v_odd, src_v_odd, v_width); + + dst_v_even += 2 * v_width; + dst_v_odd += 2 * v_width; + src_v_even += 2 * v_stride; + src_v_odd += 2 * v_stride; + } + + return 0; +} + +int +destridify(int width, int height, int fourcc, int stride, + const char * src, char * dst) +{ + /* NOTE: we're making-up the u and v strides for planar formats, + * rather than pass them in. + */ + + switch ( fourcc ) + { + case VIDCAP_FOURCC_I420: + 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); + break; + case VIDCAP_FOURCC_YUY2: + if ( stride == 2 * width ) + return -1; + return destride_packed(2 * width, height, stride, src, dst); + break; + case VIDCAP_FOURCC_RGB32: + if ( stride == 4 * width ) + return -1; + return destride_packed(4 * width, height, stride, src, dst); + break; + case VIDCAP_FOURCC_2VUY: + if ( stride == 2 * width ) + return -1; + return destride_packed(2 * width, height, stride, src, dst); + break; + case VIDCAP_FOURCC_RGB24: + if ( stride == 3 * width ) + return -1; + return destride_packed(3 * width, height, stride, src, dst); + break; + case VIDCAP_FOURCC_BOTTOM_UP_RGB24: + if ( stride == 3 * width ) + return -1; + return destride_packed(3 * width, height, stride, src, dst); + break; + case VIDCAP_FOURCC_YVU9: + 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); + break; + default: + log_error("Invalid fourcc [%s]\n", + vidcap_fourcc_string_get(fourcc)); + return -1; + break; + } +} + conv_func conv_conversion_func_get(int src_fourcc, int dst_fourcc) { Modified: trunk/src/conv.h =================================================================== --- trunk/src/conv.h 2007-10-10 18:31:30 UTC (rev 45) +++ trunk/src/conv.h 2007-10-12 16:30:09 UTC (rev 46) @@ -53,6 +53,10 @@ const char * conv_conversion_name_get(conv_func function); +int +destridify(int width, int height, int fourcc, int stride, + const char * src, char * dst); + #ifdef __cplusplus } #endif Modified: trunk/src/directshow/SourceStateMachine.cpp =================================================================== --- trunk/src/directshow/SourceStateMachine.cpp 2007-10-10 18:31:30 UTC (rev 45) +++ trunk/src/directshow/SourceStateMachine.cpp 2007-10-12 16:30:09 UTC (rev 46) @@ -367,7 +367,7 @@ okToSendStart_ = true; // final capture callback - with error status - sapi_src_capture_notify(sourceContext_, 0, 0, -1); + sapi_src_capture_notify(sourceContext_, 0, 0, 0, -1); } else { @@ -469,7 +469,7 @@ Sleep(10); // final capture callback - with error status - sapi_src_capture_notify(sourceContext_, 0, 0, -1); + sapi_src_capture_notify(sourceContext_, 0, 0, 0, -1); } } @@ -496,7 +496,7 @@ src_->stop(); // final capture callback - with error status - sapi_src_capture_notify(sourceContext_, 0, 0, -1); + sapi_src_capture_notify(sourceContext_, 0, 0, 0, -1); callbackCancellationInProgress_ = false; } @@ -519,7 +519,7 @@ int ret = sapi_src_capture_notify(instance->sourceContext_, reinterpret_cast<const char *>(pBuff), - static_cast<int>(buffSize), 0); + static_cast<int>(buffSize), 0, 0); instance->callbackInProgress_ = false; Modified: trunk/src/sapi.c =================================================================== --- trunk/src/sapi.c 2007-10-10 18:31:30 UTC (rev 45) +++ trunk/src/sapi.c 2007-10-12 16:30:09 UTC (rev 46) @@ -216,9 +216,11 @@ return 0; } +/* NOTE: stride-ignorant sapis should pass a stride of zero */ int sapi_src_capture_notify(struct sapi_src_context * src_ctx, const char * video_data, int video_data_size, + signed int stride, int error_status) { struct vidcap_capture_info cap_info; @@ -229,6 +231,8 @@ */ vidcap_src_capture_callback cap_callback = src_ctx->capture_callback; void * cap_data = src_ctx->capture_data; + void * buf = 0; + int buf_data_size = 0; int send_frame = 0; @@ -240,6 +244,23 @@ cap_info.error_status = error_status; + if ( !cap_info.error_status && stride && + !destridify(src_ctx->fmt_native.width, + src_ctx->fmt_native.height, + src_ctx->fmt_native.fourcc, + stride, + video_data, + src_ctx->stride_free_buf) ) + { + buf = src_ctx->stride_free_buf; + buf_data_size = src_ctx->stride_free_buf_size; + } + else + { + buf = (void *)video_data; + buf_data_size = video_data_size; + } + if ( cap_info.error_status ) { cap_info.video_data = 0; @@ -248,9 +269,9 @@ else if ( src_ctx->fmt_conv_func ) { if ( src_ctx->fmt_conv_func( - src_ctx->fmt_nominal.width, - src_ctx->fmt_nominal.height, - video_data, + src_ctx->fmt_native.width, + src_ctx->fmt_native.height, + buf, src_ctx->fmt_conv_buf) ) { log_error("failed format conversion\n"); @@ -262,8 +283,8 @@ } else { - cap_info.video_data = video_data; - cap_info.video_data_size = video_data_size; + cap_info.video_data = buf; + cap_info.video_data_size = buf_data_size; } if ( ( send_frame || error_status ) && cap_callback && cap_data != VIDCAP_INVALID_USER_DATA ) Modified: trunk/src/sapi.h =================================================================== --- trunk/src/sapi.h 2007-10-10 18:31:30 UTC (rev 45) +++ trunk/src/sapi.h 2007-10-12 16:30:09 UTC (rev 46) @@ -47,6 +47,7 @@ int sapi_src_capture_notify(struct sapi_src_context * src_ctx, const char * video_data, int video_data_size, + signed int stride, int error_status); int Modified: trunk/src/sapi_context.h =================================================================== --- trunk/src/sapi_context.h 2007-10-10 18:31:30 UTC (rev 45) +++ trunk/src/sapi_context.h 2007-10-12 16:30:09 UTC (rev 46) @@ -71,6 +71,9 @@ char * fmt_conv_buf; int fmt_conv_buf_size; + char * stride_free_buf; + int stride_free_buf_size; + struct vidcap_fmt_info * fmt_list; int fmt_list_len; Modified: trunk/src/sapi_qt.c =================================================================== --- trunk/src/sapi_qt.c 2007-10-10 18:31:30 UTC (rev 45) +++ trunk/src/sapi_qt.c 2007-10-12 16:30:09 UTC (rev 46) @@ -215,7 +215,8 @@ sapi_src_capture_notify(src_ctx, CVPixelBufferGetBaseAddress(pixel_buffer), - CVPixelBufferGetDataSize(pixel_buffer), 0); + CVPixelBufferGetDataSize(pixel_buffer), + CVPixelBufferGetBytesPerRow(pixel_buffer), 0); if ( (err = CVPixelBufferUnlockBaseAddress(pixel_buffer, 0)) ) { @@ -425,7 +426,7 @@ if ( sg_source_capture_poll(qt_src_ctx->src) ) { - sapi_src_capture_notify(src_ctx, 0, 0, -1); + sapi_src_capture_notify(src_ctx, 0, 0, 0, -1); ret = -1; goto bail; } Modified: trunk/src/sapi_v4l.c =================================================================== --- trunk/src/sapi_v4l.c 2007-10-10 18:31:30 UTC (rev 45) +++ trunk/src/sapi_v4l.c 2007-10-12 16:30:09 UTC (rev 46) @@ -352,6 +352,7 @@ sapi_src_capture_notify(src_ctx, fb_base + v4l_src_ctx->mbuf.offsets[capture_frame], capture_size, + 0, 0); ++capture_frame_count; Modified: trunk/src/vidcap.c =================================================================== --- trunk/src/vidcap.c 2007-10-10 18:31:30 UTC (rev 45) +++ trunk/src/vidcap.c 2007-10-12 16:30:09 UTC (rev 46) @@ -356,6 +356,9 @@ if ( src_ctx->fmt_conv_buf ) free(src_ctx->fmt_conv_buf); + if ( src_ctx->stride_free_buf ) + free(src_ctx->stride_free_buf); + if ( src_ctx->frame_times ) sliding_window_destroy(src_ctx->frame_times); @@ -420,6 +423,32 @@ src_ctx->fmt_native.fourcc, src_ctx->fmt_nominal.fourcc); + if ( src_ctx->stride_free_buf ) + { + free(src_ctx->stride_free_buf); + src_ctx->stride_free_buf = 0; + } + + src_ctx->stride_free_buf_size = conv_fmt_size_get( + src_ctx->fmt_native.width, + src_ctx->fmt_native.height, + src_ctx->fmt_native.fourcc); + + if ( !src_ctx->stride_free_buf_size ) + { + log_error("failed to get stride-free buffer size for %s\n", + vidcap_fourcc_string_get( + fmt_info->fourcc)); + return -1; + } + + if ( !(src_ctx->stride_free_buf = + malloc(src_ctx->stride_free_buf_size)) ) + { + log_oom(__FILE__, __LINE__); + return -1; + } + if ( src_ctx->fmt_conv_buf ) { free(src_ctx->fmt_conv_buf); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. m. <lib...@li...> - 2007-10-10 18:31:40
|
Revision: 45 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=45&view=rev Author: bcholew Date: 2007-10-10 11:31:30 -0700 (Wed, 10 Oct 2007) Log Message: ----------- Add missing modules to vcproj file: DirectShowObject and SourceStateMachine. Modified Paths: -------------- trunk/contrib/win/vs2005/libvidcap.vcproj Modified: trunk/contrib/win/vs2005/libvidcap.vcproj =================================================================== --- trunk/contrib/win/vs2005/libvidcap.vcproj 2007-10-10 18:04:18 UTC (rev 44) +++ trunk/contrib/win/vs2005/libvidcap.vcproj 2007-10-10 18:31:30 UTC (rev 45) @@ -188,6 +188,26 @@ </FileConfiguration> </File> <File + RelativePath="..\..\..\src\directshow\DirectShowObject.cpp" + > + <FileConfiguration + Name="Debug|Win32" + > + <Tool + Name="VCCLCompilerTool" + CompileAs="2" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + > + <Tool + Name="VCCLCompilerTool" + CompileAs="2" + /> + </FileConfiguration> + </File> + <File RelativePath="..\..\..\src\directshow\DirectShowSource.cpp" > <FileConfiguration @@ -284,6 +304,26 @@ > </File> <File + RelativePath="..\..\..\src\directshow\SourceStateMachine.cpp" + > + <FileConfiguration + Name="Debug|Win32" + > + <Tool + Name="VCCLCompilerTool" + CompileAs="2" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + > + <Tool + Name="VCCLCompilerTool" + CompileAs="2" + /> + </FileConfiguration> + </File> + <File RelativePath="..\..\..\src\vidcap.c" > <FileConfiguration @@ -324,6 +364,10 @@ > </File> <File + RelativePath="..\..\..\src\directshow\DirectShowObject.h" + > + </File> + <File RelativePath="..\..\..\src\directshow\DirectShowSource.h" > </File> @@ -356,6 +400,10 @@ > </File> <File + RelativePath="..\..\..\src\directshow\SourceStateMachine.h" + > + </File> + <File RelativePath="..\..\..\include\vidcap\vidcap.h" > </File> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. m. <lib...@li...> - 2007-10-10 18:04:28
|
Revision: 44 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=44&view=rev Author: bcholew Date: 2007-10-10 11:04:18 -0700 (Wed, 10 Oct 2007) Log Message: ----------- Prevent reference to sliding window of frame_times while processing a residual capture callback (after capture has been stopped and callback structures have been freed). Plug leak: if capture start fails, destroy sliding window of frame_times. Ensure sliding window (yes, frame_times) is destroyed when source is released. Return unique error code if capture fails due to incorrect source state. Modified Paths: -------------- trunk/src/sapi.c trunk/src/vidcap.c Modified: trunk/src/sapi.c =================================================================== --- trunk/src/sapi.c 2007-10-09 16:28:27 UTC (rev 43) +++ trunk/src/sapi.c 2007-10-10 18:04:18 UTC (rev 44) @@ -92,17 +92,23 @@ { struct timeval tv_earliest_next; struct timeval tv_now; - struct timeval *tv_oldest; - const int first_time = !sliding_window_count(src_ctx->frame_times); + struct timeval *tv_oldest = 0; + int first_time = 0; + if ( !src_ctx->frame_times ) + return 0; + + first_time = !sliding_window_count(src_ctx->frame_times); + if ( gettimeofday(&tv_now, 0) ) return -1; if ( !first_time && !tv_greater_or_equal( &tv_now, &src_ctx->frame_time_next) ) - /* Allow frame through */ return 0; + /* Allow frame through */ + tv_oldest = sliding_window_peek_front(src_ctx->frame_times); if ( !tv_oldest ) @@ -217,9 +223,9 @@ { struct vidcap_capture_info cap_info; - /* NOTE: We may be called here by a notification thread while the - * main thread is clearing capture_data and capture_callback from - * within vidcap_src_capture_stop(). + /* 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(). */ vidcap_src_capture_callback cap_callback = src_ctx->capture_callback; void * cap_data = src_ctx->capture_data; Modified: trunk/src/vidcap.c =================================================================== --- trunk/src/vidcap.c 2007-10-09 16:28:27 UTC (rev 43) +++ trunk/src/vidcap.c 2007-10-10 18:04:18 UTC (rev 44) @@ -356,6 +356,9 @@ if ( src_ctx->fmt_conv_buf ) free(src_ctx->fmt_conv_buf); + if ( src_ctx->frame_times ) + sliding_window_destroy(src_ctx->frame_times); + free(src_ctx); return ret; @@ -476,7 +479,7 @@ return -3; if ( src_ctx->src_state != src_bound ) - return -1; + return -4; src_ctx->frame_time_next.tv_sec = 0; src_ctx->frame_time_next.tv_usec = 0; @@ -495,6 +498,8 @@ { src_ctx->capture_callback = 0; src_ctx->capture_data = VIDCAP_INVALID_USER_DATA; + sliding_window_destroy(src_ctx->frame_times); + src_ctx->frame_times = 0; return ret; } @@ -511,14 +516,14 @@ if ( src_ctx->src_state != src_capturing ) return -1; - src_ctx->src_state = src_bound; - ret = src_ctx->stop_capture(src_ctx); sliding_window_destroy(src_ctx->frame_times); + src_ctx->frame_times = 0; src_ctx->capture_callback = 0; src_ctx->capture_data = VIDCAP_INVALID_USER_DATA; + src_ctx->src_state = src_bound; return ret; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. m. <lib...@li...> - 2007-10-09 16:28:31
|
Revision: 43 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=43&view=rev Author: bcholew Date: 2007-10-09 09:28:27 -0700 (Tue, 09 Oct 2007) Log Message: ----------- Added vcproj file. Added Paths: ----------- trunk/contrib/ trunk/contrib/win/ trunk/contrib/win/vs2005/ trunk/contrib/win/vs2005/libvidcap.vcproj Added: trunk/contrib/win/vs2005/libvidcap.vcproj =================================================================== --- trunk/contrib/win/vs2005/libvidcap.vcproj (rev 0) +++ trunk/contrib/win/vs2005/libvidcap.vcproj 2007-10-09 16:28:27 UTC (rev 43) @@ -0,0 +1,372 @@ +<?xml version="1.0" encoding="Windows-1252"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="libvidcap" + ProjectGUID="{F5166D99-32BB-40D5-BE95-6F97F72C44CE}" + RootNamespace="libvidcap" + Keyword="Win32Proj" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + OutputDirectory="..\..\..\..\build-win32\$(ProjectName)\$(ConfigurationName)" + IntermediateDirectory="$(OutDir)" + ConfigurationType="4" + UseOfATL="0" + CharacterSet="1" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + Optimization="0" + AdditionalIncludeDirectories="..\..\..\src;..\..\..\src\directshow;..\..\..\include;"$(DXSDK_DIR)\Include"" + PreprocessorDefinitions="WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;HAVE_DIRECTSHOW;HAVE_SLEEP" + MinimalRebuild="true" + BasicRuntimeChecks="3" + RuntimeLibrary="3" + UsePrecompiledHeader="0" + WarningLevel="3" + Detect64BitPortabilityProblems="true" + DebugInformationFormat="4" + CompileAs="1" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLibrarianTool" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + <Configuration + Name="Release|Win32" + OutputDirectory="..\..\..\..\build-win32\$(ProjectName)\$(ConfigurationName)" + IntermediateDirectory="$(OutDir)" + ConfigurationType="4" + CharacterSet="1" + WholeProgramOptimization="1" + > + <Tool + Name="VCPreBuildEventTool" + /> + <Tool + Name="VCCustomBuildTool" + /> + <Tool + Name="VCXMLDataGeneratorTool" + /> + <Tool + Name="VCWebServiceProxyGeneratorTool" + /> + <Tool + Name="VCMIDLTool" + /> + <Tool + Name="VCCLCompilerTool" + AdditionalIncludeDirectories="..\..\..\src;..\..\..\src\directshow;..\..\..\include;"$(DXSDK_DIR)\Include"" + PreprocessorDefinitions="WIN32;_CRT_SECURE_NO_DEPRECATE;_CRT_NONSTDC_NO_DEPRECATE;HAVE_DIRECTSHOW;HAVE_SLEEP" + RuntimeLibrary="2" + UsePrecompiledHeader="0" + WarningLevel="3" + Detect64BitPortabilityProblems="true" + DebugInformationFormat="3" + CompileAs="1" + /> + <Tool + Name="VCManagedResourceCompilerTool" + /> + <Tool + Name="VCResourceCompilerTool" + /> + <Tool + Name="VCPreLinkEventTool" + /> + <Tool + Name="VCLibrarianTool" + /> + <Tool + Name="VCALinkTool" + /> + <Tool + Name="VCXDCMakeTool" + /> + <Tool + Name="VCBscMakeTool" + /> + <Tool + Name="VCFxCopTool" + /> + <Tool + Name="VCPostBuildEventTool" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Source Files" + Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" + UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" + > + <File + RelativePath="..\..\..\src\conv.c" + > + </File> + <File + RelativePath="..\..\..\src\conv_to_i420.c" + > + </File> + <File + RelativePath="..\..\..\src\conv_to_rgb.c" + > + </File> + <File + RelativePath="..\..\..\src\conv_to_yuy2.c" + > + </File> + <File + RelativePath="..\..\..\src\directshow\DevMonitor.cpp" + > + <FileConfiguration + Name="Debug|Win32" + > + <Tool + Name="VCCLCompilerTool" + CompileAs="2" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + > + <Tool + Name="VCCLCompilerTool" + CompileAs="2" + /> + </FileConfiguration> + </File> + <File + RelativePath="..\..\..\src\directshow\DirectShowSource.cpp" + > + <FileConfiguration + Name="Debug|Win32" + > + <Tool + Name="VCCLCompilerTool" + CompileAs="2" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + > + <Tool + Name="VCCLCompilerTool" + CompileAs="2" + /> + </FileConfiguration> + </File> + <File + RelativePath="..\..\..\src\directshow\DShowSrcManager.cpp" + > + <FileConfiguration + Name="Debug|Win32" + > + <Tool + Name="VCCLCompilerTool" + CompileAs="2" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + > + <Tool + Name="VCCLCompilerTool" + CompileAs="2" + /> + </FileConfiguration> + </File> + <File + RelativePath="..\..\..\src\directshow\GraphMonitor.cpp" + > + <FileConfiguration + Name="Debug|Win32" + > + <Tool + Name="VCCLCompilerTool" + CompileAs="2" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + > + <Tool + Name="VCCLCompilerTool" + CompileAs="2" + /> + </FileConfiguration> + </File> + <File + RelativePath="..\..\..\src\hotlist.c" + > + </File> + <File + RelativePath="..\..\..\src\logging.c" + > + </File> + <File + RelativePath="..\..\..\src\sapi.c" + > + </File> + <File + RelativePath="..\..\..\src\sapi_dshow.cpp" + > + <FileConfiguration + Name="Debug|Win32" + > + <Tool + Name="VCCLCompilerTool" + CompileAs="2" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + > + <Tool + Name="VCCLCompilerTool" + CompileAs="2" + /> + </FileConfiguration> + </File> + <File + RelativePath="..\..\..\src\sliding_window.c" + > + </File> + <File + RelativePath="..\..\..\src\vidcap.c" + > + <FileConfiguration + Name="Debug|Win32" + > + <Tool + Name="VCCLCompilerTool" + ObjectFile="$(IntDir)\$(InputName)1.obj" + XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc" + /> + </FileConfiguration> + <FileConfiguration + Name="Release|Win32" + > + <Tool + Name="VCCLCompilerTool" + ObjectFile="$(IntDir)\$(InputName)1.obj" + XMLDocumentationFileName="$(IntDir)\$(InputName)1.xdc" + /> + </FileConfiguration> + </File> + </Filter> + <Filter + Name="Header Files" + Filter="h;hpp;hxx;hm;inl;inc;xsd" + UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" + > + <File + RelativePath="..\..\..\src\conv.h" + > + </File> + <File + RelativePath="..\..\..\include\vidcap\converters.h" + > + </File> + <File + RelativePath="..\..\..\src\directshow\DevMonitor.h" + > + </File> + <File + RelativePath="..\..\..\src\directshow\DirectShowSource.h" + > + </File> + <File + RelativePath="..\..\..\src\directshow\DShowSrcManager.h" + > + </File> + <File + RelativePath="..\..\..\src\directshow\GraphMonitor.h" + > + </File> + <File + RelativePath="..\..\..\src\hotlist.h" + > + </File> + <File + RelativePath="..\..\..\src\logging.h" + > + </File> + <File + RelativePath="..\..\..\src\sapi.h" + > + </File> + <File + RelativePath="..\..\..\src\sapi_context.h" + > + </File> + <File + RelativePath="..\..\..\src\sliding_window.h" + > + </File> + <File + RelativePath="..\..\..\include\vidcap\vidcap.h" + > + </File> + </Filter> + <Filter + Name="Resource Files" + Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav" + UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}" + > + </Filter> + </Files> + <Globals> + </Globals> +</VisualStudioProject> Property changes on: trunk/contrib/win/vs2005/libvidcap.vcproj ___________________________________________________________________ Name: svn:executable + * This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. m. <lib...@li...> - 2007-10-09 14:30:42
|
Revision: 42 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=42&view=rev Author: jpgrayson Date: 2007-10-09 07:30:40 -0700 (Tue, 09 Oct 2007) Log Message: ----------- Whitespace, comments Modified Paths: -------------- trunk/include/vidcap/converters.h trunk/src/sapi.c Modified: trunk/include/vidcap/converters.h =================================================================== --- trunk/include/vidcap/converters.h 2007-10-06 19:43:23 UTC (rev 41) +++ trunk/include/vidcap/converters.h 2007-10-09 14:30:40 UTC (rev 42) @@ -31,28 +31,22 @@ #endif int -vidcap_i420_to_rgb32(int width, int height, const char * src, - char * dest); +vidcap_i420_to_rgb32(int width, int height, const char * src, char * dest); int -vidcap_i420_to_yuy2(int width, int height, const char * src, - char * dest); +vidcap_i420_to_yuy2(int width, int height, const char * src, char * dest); int -vidcap_yuy2_to_i420(int width, int height, const char * src, - char * dest); +vidcap_yuy2_to_i420(int width, int height, const char * src, char * dest); int -vidcap_yuy2_to_rgb32(int width, int height, const char * src, - char * dest); +vidcap_yuy2_to_rgb32(int width, int height, const char * src, char * dest); int -vidcap_rgb32_to_i420(int width, int height, const char * src, - char * dest); +vidcap_rgb32_to_i420(int width, int height, const char * src, char * dest); int -vidcap_rgb32_to_yuy2(int width, int height, const char * src, - char * dest); +vidcap_rgb32_to_yuy2(int width, int height, const char * src, char * dest); #ifdef __cplusplus } Modified: trunk/src/sapi.c =================================================================== --- trunk/src/sapi.c 2007-10-06 19:43:23 UTC (rev 41) +++ trunk/src/sapi.c 2007-10-09 14:30:40 UTC (rev 42) @@ -217,9 +217,10 @@ { struct vidcap_capture_info cap_info; - // NOTE: We may be called here by a notification thread while - // the main thread is clearing the src_ctx ->capture_data and - // ->capture_callback from within vidcap_src_capture_stop() + /* NOTE: We may be called here by a notification thread while the + * main thread is clearing capture_data and capture_callback from + * within vidcap_src_capture_stop(). + */ vidcap_src_capture_callback cap_callback = src_ctx->capture_callback; void * cap_data = src_ctx->capture_data; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. m. <lib...@li...> - 2007-10-06 19:43:25
|
Revision: 41 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=41&view=rev Author: jpgrayson Date: 2007-10-06 12:43:23 -0700 (Sat, 06 Oct 2007) Log Message: ----------- Add vidcap_log_level_set() function to the api. Set the default log level to VIDCAP_LOG_INFO. Change some quicktime messages to debug level. Modified Paths: -------------- trunk/include/vidcap/vidcap.h trunk/src/logging.c trunk/src/quicktime/sg_source.c trunk/src/sapi_qt.c trunk/src/vidcap.c Modified: trunk/include/vidcap/vidcap.h =================================================================== --- trunk/include/vidcap/vidcap.h 2007-10-06 19:10:17 UTC (rev 40) +++ trunk/include/vidcap/vidcap.h 2007-10-06 19:43:23 UTC (rev 41) @@ -38,6 +38,14 @@ VIDCAP_FOURCC_RGB32 = 102, }; +enum vidcap_log_level { + VIDCAP_LOG_NONE = 0, + VIDCAP_LOG_ERROR = 10, + VIDCAP_LOG_WARN = 20, + VIDCAP_LOG_INFO = 30, + VIDCAP_LOG_DEBUG = 40 +}; + typedef void vidcap_state; typedef void vidcap_sapi; typedef void vidcap_src; @@ -83,6 +91,9 @@ vidcap_destroy(vidcap_state *); int +vidcap_log_level_set(enum vidcap_log_level level); + +int vidcap_sapi_enumerate(vidcap_state *, int index, struct vidcap_sapi_info *); Modified: trunk/src/logging.c =================================================================== --- trunk/src/logging.c 2007-10-06 19:10:17 UTC (rev 40) +++ trunk/src/logging.c 2007-10-06 19:43:23 UTC (rev 41) @@ -38,7 +38,7 @@ static FILE * logging_file = 0; -static enum log_level logging_level = log_level_debug; +static enum log_level logging_level = log_level_info; static void do_log(enum log_level level, const char * fmt, va_list ap) { Modified: trunk/src/quicktime/sg_source.c =================================================================== --- trunk/src/quicktime/sg_source.c 2007-10-06 19:10:17 UTC (rev 40) +++ trunk/src/quicktime/sg_source.c 2007-10-06 19:43:23 UTC (rev 41) @@ -149,7 +149,7 @@ src->native_pixel_format = (*compression_list)->cType; - log_info("native pixel format %c%c%c%c\n", + log_debug("native pixel format %c%c%c%c\n", (char)(src->native_pixel_format >> 24), (char)(src->native_pixel_format >> 16), (char)(src->native_pixel_format >> 8), Modified: trunk/src/sapi_qt.c =================================================================== --- trunk/src/sapi_qt.c 2007-10-06 19:10:17 UTC (rev 40) +++ trunk/src/sapi_qt.c 2007-10-06 19:43:23 UTC (rev 41) @@ -202,7 +202,7 @@ } if ( qt_src_ctx->frame_count == 1 ) - log_info("capture time: %c%c%c%c %s %s %s\n", + log_debug("capture time: %c%c%c%c %s %s %s\n", (char)(pixel_format >> 24), (char)(pixel_format >> 16), (char)(pixel_format >> 8), @@ -287,7 +287,7 @@ return -1; } - log_info("setup decomp: %c%c%c%c %s %s %s\n", + log_debug("setup decomp: %c%c%c%c %s %s %s\n", (char)(pixel_format >> 24), (char)(pixel_format >> 16), (char)(pixel_format >> 8), Modified: trunk/src/vidcap.c =================================================================== --- trunk/src/vidcap.c 2007-10-06 19:10:17 UTC (rev 40) +++ trunk/src/vidcap.c 2007-10-06 19:43:23 UTC (rev 41) @@ -133,6 +133,36 @@ } int +vidcap_log_level_set(enum vidcap_log_level level) +{ + int log_level; + + switch ( level ) + { + case VIDCAP_LOG_NONE: + log_level = log_level_none; + break; + case VIDCAP_LOG_ERROR: + log_level = log_level_error; + break; + case VIDCAP_LOG_WARN: + log_level = log_level_warn; + break; + case VIDCAP_LOG_INFO: + log_level = log_level_info; + break; + case VIDCAP_LOG_DEBUG: + log_level = log_level_debug; + default: + return -1; + } + + log_level_set(log_level); + + return 0; +} + +int vidcap_sapi_enumerate(vidcap_state * state, int index, struct vidcap_sapi_info * sapi_info) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. m. <lib...@li...> - 2007-10-06 19:10:19
|
Revision: 40 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=40&view=rev Author: jpgrayson Date: 2007-10-06 12:10:17 -0700 (Sat, 06 Oct 2007) Log Message: ----------- Fixup 'make dist'. vidcapTester makes it into source tarball. directshow sources fixed-up in Makefile.am. Modified Paths: -------------- trunk/examples/Makefile.am trunk/src/Makefile.am Modified: trunk/examples/Makefile.am =================================================================== --- trunk/examples/Makefile.am 2007-10-01 21:47:31 UTC (rev 39) +++ trunk/examples/Makefile.am 2007-10-06 19:10:17 UTC (rev 40) @@ -16,3 +16,4 @@ -framework QuickTime endif +EXTRA_DIST = vidcapTester Modified: trunk/src/Makefile.am =================================================================== --- trunk/src/Makefile.am 2007-10-01 21:47:31 UTC (rev 39) +++ trunk/src/Makefile.am 2007-10-06 19:10:17 UTC (rev 40) @@ -51,15 +51,18 @@ endif if HAVE_DIRECTSHOW -libvidcap_la_SOURCES += \ - sapi_dshow.cpp \ - directshow/DShowSrcManager.cpp \ - directshow/DShowSrcManager.h \ - directshow/DevMonitor.cpp \ - directshow/DevMonitor.h \ - directshow/DirectShowSource.cpp \ - directshow/DirectShowSource.h \ - directshow/GraphMonitor.cpp \ - directshow/GraphMonitor.h \ - directshow/LocklessQueue.h +libvidcap_la_SOURCES += \ + directshow/DShowSrcManager.cpp \ + directshow/DShowSrcManager.h \ + directshow/DevMonitor.cpp \ + directshow/DevMonitor.h \ + directshow/DirectShowObject.cpp \ + directshow/DirectShowObject.h \ + directshow/DirectShowSource.cpp \ + directshow/DirectShowSource.h \ + directshow/GraphMonitor.cpp \ + directshow/GraphMonitor.h \ + directshow/SourceStateMachine.cpp \ + directshow/SourceStateMachine.h \ + sapi_dshow.cpp endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. m. <lib...@li...> - 2007-10-01 21:47:33
|
Revision: 39 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=39&view=rev Author: bcholew Date: 2007-10-01 14:47:31 -0700 (Mon, 01 Oct 2007) Log Message: ----------- Remove function sprintDeviceInfo(), in favor of function getDeviceInfo(). Alter DShowSrcManager::scan() to use getDeviceInfo(). Move function getJustCapDevice from DShowSrcManager to DirectShowSource. Move getDeviceInfo from DShowSrcManager to new base class DirectShowObject. Derive DirectShowSource and DShowSrcManager from this new class. Remove references to DShowSrcMgr in DirectShowSource. Modified Paths: -------------- trunk/src/directshow/DShowSrcManager.cpp trunk/src/directshow/DShowSrcManager.h trunk/src/directshow/DirectShowSource.cpp trunk/src/directshow/DirectShowSource.h trunk/src/directshow/GraphMonitor.cpp trunk/src/directshow/SourceStateMachine.cpp Added Paths: ----------- trunk/src/directshow/DirectShowObject.cpp trunk/src/directshow/DirectShowObject.h Modified: trunk/src/directshow/DShowSrcManager.cpp =================================================================== --- trunk/src/directshow/DShowSrcManager.cpp 2007-10-01 19:42:06 UTC (rev 38) +++ trunk/src/directshow/DShowSrcManager.cpp 2007-10-01 21:47:31 UTC (rev 39) @@ -158,12 +158,19 @@ srcInfo = &srcList->list[newListLen - 1]; - //FIXME: rename to getDeviceId() - sprintDeviceInfo(pM, pbc, - srcInfo->identifier, srcInfo->description, - min(sizeof(srcInfo->identifier), - sizeof(srcInfo->description))); + // get device description and ID + char *tempDesc; + char *tempID; + getDeviceInfo(pM, pbc, &tempDesc, &tempID); + sprintf_s(srcInfo->description, sizeof(srcInfo->description), + "%s", tempDesc); + sprintf_s(srcInfo->identifier, sizeof(srcInfo->identifier), + "%s", tempID); + + free(tempID); + free(tempDesc); + clean_continue: if ( pCaptureFilter ) pCaptureFilter->Release(); @@ -233,150 +240,7 @@ log_warn("couldn't find source '%s' to release\n", id); } -bool -DShowSrcManager::getJustCapDevice(const char *devLongName, - IBindCtx **ppBindCtx, - IMoniker **ppMoniker) const -{ - HRESULT hr; - // Create an enumerator - CComPtr<ICreateDevEnum> pCreateDevEnum; - - pCreateDevEnum.CoCreateInstance(CLSID_SystemDeviceEnum); - - if ( !pCreateDevEnum ) - { - log_error("failed creating device enumerator - to get a source\n"); - return false; - } - - // Enumerate video capture devices - CComPtr<IEnumMoniker> pEm; - - pCreateDevEnum->CreateClassEnumerator( - CLSID_VideoInputDeviceCategory, &pEm, 0); - - if ( !pEm ) - { - log_error("failed creating enumerator moniker\n"); - return false; - } - - pEm->Reset(); - - ULONG ulFetched; - IMoniker * pM; - - // Iterate over all video capture devices - int i=0; - while ( pEm->Next(1, &pM, &ulFetched) == S_OK ) - { - IBindCtx *pbc; - - hr = CreateBindCtx(0, &pbc); - - if ( FAILED(hr) ) - { - log_error("failed CreateBindCtx\n"); - pM->Release(); - return false; - } - - // Get the device names - char *shortName; - char *longName; - if ( getDeviceInfo(pM, pbc, &shortName, &longName) ) - { - log_warn("failed to get device info.\n"); - pbc->Release(); - continue; - } - - // Compare with the desired dev name - if ( !strcmp(longName, devLongName) ) - { - // Got the correct device - *ppMoniker = pM; - *ppBindCtx = pbc; - - free(shortName); - free(longName); - return true; - } - - // Wrong device. Cleanup and try again - free(shortName); - free(longName); - - pbc->Release(); - } - - pM->Release(); - - return false; -} - -void -DShowSrcManager::sprintDeviceInfo(IMoniker * pM, IBindCtx * pbc, - char* idBuff, char *descBuff, int buffsSize) const -{ - USES_CONVERSION; - - HRESULT hr; - - CComPtr< IMalloc > pMalloc; - - hr = CoGetMalloc(1, &pMalloc); - - if ( FAILED(hr) ) - { - log_error("failed CoGetMalloc\n"); - return; - } - - LPOLESTR pDisplayName; - - hr = pM->GetDisplayName(pbc, 0, &pDisplayName); - - if ( FAILED(hr) ) - { - log_warn("failed GetDisplayName\n"); - return; - } - - // This gets stack memory, no dealloc needed. - char * pszDisplayName = OLE2A(pDisplayName); - - pMalloc->Free(pDisplayName); - - CComPtr< IPropertyBag > pPropBag; - - hr = pM->BindToStorage(pbc, 0, IID_IPropertyBag, - (void **)&pPropBag); - - if ( FAILED(hr) ) - { - log_error("failed getting video device property bag\n"); - return; - } - - VARIANT v; - VariantInit(&v); - - char * pszFriendlyName = 0; - - hr = pPropBag->Read(L"FriendlyName", &v, 0); - - if ( SUCCEEDED(hr) ) - pszFriendlyName = _com_util::ConvertBSTRToString(v.bstrVal); - - sprintf_s(descBuff, buffsSize, "%s", pszFriendlyName); - sprintf_s(idBuff, buffsSize, "%s", pszDisplayName); - - delete [] pszFriendlyName; -} - IPin * DShowSrcManager::getOutPin( IBaseFilter * pFilter, int nPin ) const { @@ -428,68 +292,3 @@ return hr; } -// Allocates and returns the friendlyName and displayName for a device -int -DShowSrcManager::getDeviceInfo(IMoniker * pM, IBindCtx * pbc, - char** easyName, char **longName) const -{ - USES_CONVERSION; - - HRESULT hr; - - CComPtr< IMalloc > pMalloc; - - hr = CoGetMalloc(1, &pMalloc); - - if ( FAILED(hr) ) - { - log_error("failed CoGetMalloc\n"); - return 1; - } - - LPOLESTR pDisplayName; - - hr = pM->GetDisplayName(pbc, 0, &pDisplayName); - - if ( FAILED(hr) ) - { - log_warn("failed GetDisplayName\n"); - return 1; - } - - // This gets stack memory, no dealloc needed. - char * pszDisplayName = OLE2A(pDisplayName); - - // Allocate a copy of this long name - *longName = _strdup(pszDisplayName); - - pMalloc->Free(pDisplayName); - - CComPtr< IPropertyBag > pPropBag; - - hr = pM->BindToStorage(pbc, 0, IID_IPropertyBag, - (void **)&pPropBag); - - if ( FAILED(hr) ) - { - log_warn("failed getting video device property bag\n"); - return 1; - } - - VARIANT v; - VariantInit(&v); - - char * pszFriendlyName = 0; - - hr = pPropBag->Read(L"FriendlyName", &v, 0); - - if ( SUCCEEDED(hr) ) - pszFriendlyName = - _com_util::ConvertBSTRToString(v.bstrVal); - - // Allocate a copy of this short name - *easyName = _strdup(pszFriendlyName); - - delete [] pszFriendlyName; - return 0; -} Modified: trunk/src/directshow/DShowSrcManager.h =================================================================== --- trunk/src/directshow/DShowSrcManager.h 2007-10-01 19:42:06 UTC (rev 38) +++ trunk/src/directshow/DShowSrcManager.h 2007-10-01 21:47:31 UTC (rev 39) @@ -26,9 +26,10 @@ #define _DSHOWSRCMANAGER_H_ #include <vector> +#include "DirectShowObject.h" #include "DevMonitor.h" -class DShowSrcManager +class DShowSrcManager : public DirectShowObject { protected: @@ -42,9 +43,6 @@ // for device event notifications (additions and removals) int registerNotifyCallback(void *); - bool getJustCapDevice(const char *devLongName, - IBindCtx **ppBindCtx, - IMoniker **ppMoniker) const; bool okayToBuildSource(const char *); void sourceReleased(const char *id); void release(); @@ -67,9 +65,6 @@ private: IPin * getOutPin( IBaseFilter *, int) const; HRESULT getPin( IBaseFilter *, PIN_DIRECTION, int, IPin **) const; - int getDeviceInfo(IMoniker * pM, IBindCtx * pbc, - char** easyName, char **longName) const; - void sprintDeviceInfo(IMoniker *, IBindCtx *, char *, char *, int) const; }; #endif Added: trunk/src/directshow/DirectShowObject.cpp =================================================================== --- trunk/src/directshow/DirectShowObject.cpp (rev 0) +++ trunk/src/directshow/DirectShowObject.cpp 2007-10-01 21:47:31 UTC (rev 39) @@ -0,0 +1,97 @@ +// +// libvidcap - a cross-platform video capture library +// +// Copyright 2007 Wimba, Inc. +// +// Contributors: +// Peter Grayson <jpg...@gm...> +// Bill Cholewka <bc...@gm...> +// +// libvidcap is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// libvidcap is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this program. If not, see +// <http://www.gnu.org/licenses/>. +// + +#include <windows.h> +#include <atlbase.h> +#include <comutil.h> + +#include "DirectShowObject.h" +#include "logging.h" + +// Allocates and returns the description and ID for a given device +int +DirectShowObject::getDeviceInfo(IMoniker * pM, IBindCtx * pbc, + char ** description, char **ID) const +{ + USES_CONVERSION; + + HRESULT hr; + + CComPtr< IMalloc > pMalloc; + + hr = CoGetMalloc(1, &pMalloc); + + if ( FAILED(hr) ) + { + log_error("failed CoGetMalloc\n"); + return 1; + } + + LPOLESTR pDisplayName; + + hr = pM->GetDisplayName(pbc, 0, &pDisplayName); + + if ( FAILED(hr) ) + { + log_warn("failed GetDisplayName\n"); + return 1; + } + + // This gets stack memory, no dealloc needed. + char * pszDisplayName = OLE2A(pDisplayName); + + // Allocate a copy of this identifier + *ID = _strdup(pszDisplayName); + + pMalloc->Free(pDisplayName); + + CComPtr< IPropertyBag > pPropBag; + + hr = pM->BindToStorage(pbc, 0, IID_IPropertyBag, + (void **)&pPropBag); + + if ( FAILED(hr) ) + { + log_warn("failed getting video device property bag\n"); + return 1; + } + + VARIANT v; + VariantInit(&v); + + char * pszFriendlyName = 0; + + hr = pPropBag->Read(L"FriendlyName", &v, 0); + + if ( SUCCEEDED(hr) ) + pszFriendlyName = + _com_util::ConvertBSTRToString(v.bstrVal); + + // Allocate a copy of this description + *description = _strdup(pszFriendlyName); + + delete [] pszFriendlyName; + return 0; +} + Added: trunk/src/directshow/DirectShowObject.h =================================================================== --- trunk/src/directshow/DirectShowObject.h (rev 0) +++ trunk/src/directshow/DirectShowObject.h 2007-10-01 21:47:31 UTC (rev 39) @@ -0,0 +1,41 @@ +// +// libvidcap - a cross-platform video capture library +// +// Copyright 2007 Wimba, Inc. +// +// Contributors: +// Peter Grayson <jpg...@gm...> +// Bill Cholewka <bc...@gm...> +// +// libvidcap is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// libvidcap is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this program. If not, see +// <http://www.gnu.org/licenses/>. +// + +#ifndef _DIRECTSHOWOBJECT_H_ +#define _DIRECTSHOWOBJECT_H_ + +class DirectShowObject +{ + +public: + DirectShowObject() { }; + ~DirectShowObject() { }; + +protected: + int getDeviceInfo(IMoniker * pM, IBindCtx * pbc, + char ** descr, char **ID) const; +}; + +#endif + Modified: trunk/src/directshow/DirectShowSource.cpp =================================================================== --- trunk/src/directshow/DirectShowSource.cpp 2007-10-01 19:42:06 UTC (rev 38) +++ trunk/src/directshow/DirectShowSource.cpp 2007-10-01 21:47:31 UTC (rev 39) @@ -37,9 +37,8 @@ #include "DirectShowSource.h" DirectShowSource::DirectShowSource(struct sapi_src_context *src, - DShowSrcManager *mgr, bufferCallbackFunc cbFunc, cancelCaptureFunc cancelCaptureCB, void * parent) + bufferCallbackFunc cbFunc, cancelCaptureFunc cancelCaptureCB, void * parent) : sourceContext_(src), - dshowMgr_(mgr), bufferCB_(cbFunc), cancelCaptureCB_(cancelCaptureCB), parent_(parent), @@ -61,8 +60,7 @@ IMoniker * pMoniker = 0; // Get the capture device - identified by it's long display name - if ( !dshowMgr_->getJustCapDevice(getID(), &pBindCtx, &pMoniker) ) - { + if ( !getCaptureDevice(getID(), &pBindCtx, &pMoniker) ){ log_warn("Failed to get device '%s'.\n", getID()); throw std::runtime_error("failed to get device"); } @@ -280,9 +278,6 @@ if ( pCapGraphBuilder_ ) pCapGraphBuilder_->Release(); - - if ( graphHandle_ ) - CloseHandle(graphHandle_); } int @@ -1111,3 +1106,86 @@ } } +bool +DirectShowSource::getCaptureDevice(const char *devLongName, + IBindCtx **ppBindCtx, + IMoniker **ppMoniker) const +{ + HRESULT hr; + + // Create an enumerator + CComPtr<ICreateDevEnum> pCreateDevEnum; + + pCreateDevEnum.CoCreateInstance(CLSID_SystemDeviceEnum); + + if ( !pCreateDevEnum ) + { + log_error("failed creating device enumerator - to get a source\n"); + return false; + } + + // Enumerate video capture devices + CComPtr<IEnumMoniker> pEm; + + pCreateDevEnum->CreateClassEnumerator( + CLSID_VideoInputDeviceCategory, &pEm, 0); + + if ( !pEm ) + { + log_error("failed creating enumerator moniker\n"); + return false; + } + + pEm->Reset(); + + ULONG ulFetched; + IMoniker * pM; + + // Iterate over all video capture devices + int i=0; + while ( pEm->Next(1, &pM, &ulFetched) == S_OK ) + { + IBindCtx *pbc; + + hr = CreateBindCtx(0, &pbc); + + if ( FAILED(hr) ) + { + log_error("failed CreateBindCtx\n"); + pM->Release(); + return false; + } + + // Get the device names + char *shortName; + char *longName; + if ( getDeviceInfo(pM, pbc, &shortName, &longName) ) + { + log_warn("failed to get device info.\n"); + pbc->Release(); + continue; + } + + // Compare with the desired dev name + if ( !strcmp(longName, devLongName) ) + { + // Got the correct device + *ppMoniker = pM; + *ppBindCtx = pbc; + + free(shortName); + free(longName); + return true; + } + + // Wrong device. Cleanup and try again + free(shortName); + free(longName); + + pbc->Release(); + } + + pM->Release(); + + return false; +} Modified: trunk/src/directshow/DirectShowSource.h =================================================================== --- trunk/src/directshow/DirectShowSource.h 2007-10-01 19:42:06 UTC (rev 38) +++ trunk/src/directshow/DirectShowSource.h 2007-10-01 21:47:31 UTC (rev 39) @@ -34,14 +34,14 @@ #include "sapi_context.h" #include "GraphMonitor.h" -class DirectShowSource : public ISampleGrabberCB +class DirectShowSource : public ISampleGrabberCB, public DirectShowObject { public: typedef int (*bufferCallbackFunc)(double, BYTE *, long, void *); typedef void (*cancelCaptureFunc)(void *); - DirectShowSource(struct sapi_src_context *, DShowSrcManager *, + DirectShowSource(struct sapi_src_context *, bufferCallbackFunc, cancelCaptureFunc, void *); ~DirectShowSource(); @@ -69,11 +69,12 @@ int formatNum, bool *needsFramerateEnforcing, bool *needsFormatConversion, AM_MEDIA_TYPE **candidateMediaFormat) const; - bool findBestFormat(const vidcap_fmt_info * fmtNominal, vidcap_fmt_info * fmtNative, AM_MEDIA_TYPE **mediaFormat) const; - void freeMediaType(AM_MEDIA_TYPE &) const; + bool getCaptureDevice(const char *devLongName, + IBindCtx **ppBindCtx, + IMoniker **ppMoniker) const; // Fake out COM STDMETHODIMP_(ULONG) AddRef() { return 2; } Modified: trunk/src/directshow/GraphMonitor.cpp =================================================================== --- trunk/src/directshow/GraphMonitor.cpp 2007-10-01 19:42:06 UTC (rev 38) +++ trunk/src/directshow/GraphMonitor.cpp 2007-10-01 21:47:31 UTC (rev 39) @@ -85,7 +85,6 @@ } DWORD rc = WaitForSingleObject(initDoneEvent_, INFINITE); - //FIXME: consider a timeout return; @@ -144,7 +143,6 @@ DWORD rc = WaitForMultipleObjects(static_cast<DWORD>(numHandles), waitHandles, false, INFINITE); - // get index of object that signaled unsigned int index = rc - WAIT_OBJECT_0; Modified: trunk/src/directshow/SourceStateMachine.cpp =================================================================== --- trunk/src/directshow/SourceStateMachine.cpp 2007-10-01 19:42:06 UTC (rev 38) +++ trunk/src/directshow/SourceStateMachine.cpp 2007-10-01 21:47:31 UTC (rev 39) @@ -70,7 +70,6 @@ try { src_ = new DirectShowSource(src, - mgr, (bufferCallbackFunc)&SourceStateMachine::bufferCB, (cancelCaptureFunc)&SourceStateMachine::cancelCaptureCB, this); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. m. <lib...@li...> - 2007-10-01 19:42:18
|
Revision: 38 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=38&view=rev Author: bcholew Date: 2007-10-01 12:42:06 -0700 (Mon, 01 Oct 2007) Log Message: ----------- whitespace cleanup Modified Paths: -------------- trunk/src/directshow/DirectShowSource.cpp Modified: trunk/src/directshow/DirectShowSource.cpp =================================================================== --- trunk/src/directshow/DirectShowSource.cpp 2007-10-01 19:37:33 UTC (rev 37) +++ trunk/src/directshow/DirectShowSource.cpp 2007-10-01 19:42:06 UTC (rev 38) @@ -808,305 +808,306 @@ return 0; } -// Direct Show filter graph has signaled an event -// Device may have been removed -// Error may have occurred -void -DirectShowSource::processGraphEvent(void *context) -{ - DirectShowSource * pSrc = static_cast<DirectShowSource *>(context); - - HRESULT hr; - long evCode, param1, param2; - hr = pSrc->pMediaEventIF_->GetEvent(&evCode, ¶m1, ¶m2, 0); - - if ( SUCCEEDED(hr) ) - { - // Event codes taken from: - // http://msdn2.microsoft.com/en-us/library/ms783649.aspx - // Embedded reference not used: - // http://msdn2.microsoft.com/en-us/library/aa921722.aspx - - std::string str; - - switch(evCode) - { - case EC_DEVICE_LOST: - if ( (int)param2 == 0 ) - { - str.assign("EC_DEVICE_LOST\n"); - log_info("device removal detected\n"); - - // shutdown capture - pSrc->cancelCaptureCB_(pSrc->parent_); - } - else - { - str.assign("EC_DEVICE_LOST - (device re-inserted)\n"); - } - break; - - case EC_ACTIVATE: - str.assign("EC_ACTIVATE\n"); - break; - -/* case EC_BANDWIDTHCHANGE: - str.assign("EC_BANDWIDTHCHANGE\n"); - break; -*/ - case EC_BUFFERING_DATA: - str.assign("EC_BUFFERING_DATA\n"); - break; - - case EC_BUILT: - str.assign("EC_BUILT\n"); - break; - - case EC_CLOCK_CHANGED: - str.assign("EC_CLOCK_CHANGED\n"); - break; - - case EC_CLOCK_UNSET: - str.assign("EC_CLOCK_UNSET\n"); - break; - - case EC_CODECAPI_EVENT: - str.assign("EC_CODECAPI_EVENT\n"); - break; - - case EC_COMPLETE: - str.assign("EC_COMPLETE\n"); - break; - -/* case EC_CONTENTPROPERTY_CHANGED: - str.assign("EC_CONTENTPROPERTY_CHANGED\n"); - break; -*/ - case EC_DISPLAY_CHANGED: - str.assign("EC_DISPLAY_CHANGED\n"); - break; - - case EC_END_OF_SEGMENT: - str.assign("EC_END_OF_SEGMENT\n"); - break; - -/* case EC_EOS_SOON: - str.assign("EC_EOS_SOON\n"); - break; -*/ - case EC_ERROR_STILLPLAYING: - str.assign("EC_ERROR_STILLPLAYING\n"); - break; - - case EC_ERRORABORT: - str.assign("EC_ERRORABORT\n"); - - log_info("graph monitor stopping capture...\n"); - - // shutdown capture - pSrc->cancelCaptureCB_(pSrc->parent_); - - break; - -/* case EC_ERRORABORTEX: - str.assign("EC_ERRORABORTEX\n"); - break; -*/ - case EC_EXTDEVICE_MODE_CHANGE: - str.assign("EC_EXTDEVICE_MODE_CHANGE\n"); - break; - -/* case EC_FILE_CLOSED: - str.assign("EC_FILE_CLOSED\n"); - break; -*/ - case EC_FULLSCREEN_LOST: - str.assign("EC_FULLSCREEN_LOST\n"); - break; - - case EC_GRAPH_CHANGED: - str.assign("EC_GRAPH_CHANGED\n"); - break; - - case EC_LENGTH_CHANGED: - str.assign("EC_LENGTH_CHANGED\n"); - break; - -/* case EC_LOADSTATUS: - str.assign("EC_LOADSTATUS\n"); - break; -*/ -/* case EC_MARKER_HIT: - str.assign("EC_MARKER_HIT\n"); - break; -*/ - case EC_NEED_RESTART: - str.assign("EC_NEED_RESTART\n"); - break; - -/* case EC_NEW_PIN: - str.assign("EC_NEW_PIN\n"); - break; -*/ - case EC_NOTIFY_WINDOW: - str.assign("EC_NOTIFY_WINDOW\n"); - break; - - case EC_OLE_EVENT: - str.assign("EC_OLE_EVENT\n"); - break; - - case EC_OPENING_FILE: - str.assign("EC_OPENING_FILE\n"); - break; - - case EC_PALETTE_CHANGED: - str.assign("EC_PALETTE_CHANGED\n"); - break; - - case EC_PAUSED: - str.assign("EC_PAUSED\n"); - break; - -/* case EC_PLEASE_REOPEN: - str.assign("EC_PLEASE_REOPEN\n"); - break; -*/ - case EC_PREPROCESS_COMPLETE: - str.assign("EC_PREPROCESS_COMPLETE\n"); - break; - -/* case EC_PROCESSING_LATENCY: - str.assign("EC_PROCESSING_LATENCY\n"); - break; -*/ - case EC_QUALITY_CHANGE: - str.assign("EC_QUALITY_CHANGE\n"); - break; - -/* case EC_RENDER_FINISHED: - str.assign("EC_RENDER_FINISHED\n"); - break; -*/ - case EC_REPAINT: - str.assign("EC_REPAINT\n"); - break; - -/* case EC_SAMPLE_LATENCY: - str.assign("EC_SAMPLE_LATENCY\n"); - break; - - case EC_SAMPLE_NEEDED: - str.assign("EC_SAMPLE_NEEDED\n"); - break; - - case EC_SCRUB_TIME: - str.assign("EC_SCRUB_TIME\n"); - break; -*/ - case EC_SEGMENT_STARTED: - str.assign("EC_SEGMENT_STARTED\n"); - break; - - case EC_SHUTTING_DOWN: - str.assign("EC_SHUTTING_DOWN\n"); - break; - - case EC_SNDDEV_IN_ERROR: - str.assign("EC_SNDDEV_IN_ERROR\n"); - break; - - case EC_SNDDEV_OUT_ERROR: - str.assign("EC_SNDDEV_OUT_ERROR\n"); - break; - - case EC_STARVATION: - str.assign("EC_STARVATION\n"); - break; - - case EC_STATE_CHANGE: - str.assign("EC_STATE_CHANGE\n"); - break; - -/* case EC_STATUS: - str.assign("EC_STATUS\n"); - break; -*/ - case EC_STEP_COMPLETE: - str.assign("EC_STEP_COMPLETE\n"); - break; - - case EC_STREAM_CONTROL_STARTED: - str.assign("EC_STREAM_CONTROL_STARTED\n"); - break; - - case EC_STREAM_CONTROL_STOPPED: - str.assign("EC_STREAM_CONTROL_STOPPED\n"); - break; - - case EC_STREAM_ERROR_STILLPLAYING: - str.assign("EC_STREAM_ERROR_STILLPLAYING\n"); - break; - - case EC_STREAM_ERROR_STOPPED: - str.assign("EC_STREAM_ERROR_STOPPED\n"); - break; - - case EC_TIMECODE_AVAILABLE: - str.assign("EC_TIMECODE_AVAILABLE\n"); - break; - - case EC_UNBUILT: - str.assign("EC_UNBUILT\n"); - break; - - case EC_USERABORT: - str.assign("EC_USERABORT\n"); - break; - - case EC_VIDEO_SIZE_CHANGED: - str.assign("EC_VIDEO_SIZE_CHANGED\n"); - break; - -/* case EC_VIDEOFRAMEREADY: - str.assign("EC_VIDEOFRAMEREADY\n"); - break; -*/ - case EC_VMR_RECONNECTION_FAILED: - str.assign("EC_VMR_RECONNECTION_FAILED\n"); - break; - - case EC_VMR_RENDERDEVICE_SET: - str.assign("EC_VMR_RENDERDEVICE_SET\n"); - break; - - case EC_VMR_SURFACE_FLIPPED: - str.assign("EC_VMR_SURFACE_FLIPPED\n"); - break; - - case EC_WINDOW_DESTROYED: - str.assign("EC_WINDOW_DESTROYED\n"); - break; - - case EC_WMT_EVENT: - str.assign("EC_WMT_EVENT\n"); - break; - - case EC_WMT_INDEX_EVENT: - str.assign("EC_WMT_INDEX_EVENT\n"); - break; - - default: - str.assign("unknown graph event code (%ld)\n", evCode); - break; - } - - log_info("graph processed event: %s", str.c_str()); - - hr = pSrc->pMediaEventIF_->FreeEventParams(evCode, param1, param2); - } - else - { - log_error("failed getting event for a graph\n"); - } -} +// Direct Show filter graph has signaled an event +// Device may have been removed +// Error may have occurred +void +DirectShowSource::processGraphEvent(void *context) +{ + DirectShowSource * pSrc = static_cast<DirectShowSource *>(context); + + HRESULT hr; + long evCode, param1, param2; + hr = pSrc->pMediaEventIF_->GetEvent(&evCode, ¶m1, ¶m2, 0); + + if ( SUCCEEDED(hr) ) + { + // Event codes taken from: + // http://msdn2.microsoft.com/en-us/library/ms783649.aspx + // Embedded reference not used: + // http://msdn2.microsoft.com/en-us/library/aa921722.aspx + + std::string str; + + switch(evCode) + { + case EC_DEVICE_LOST: + if ( (int)param2 == 0 ) + { + str.assign("EC_DEVICE_LOST\n"); + log_info("device removal detected\n"); + + // shutdown capture + pSrc->cancelCaptureCB_(pSrc->parent_); + } + else + { + str.assign("EC_DEVICE_LOST - (device re-inserted)\n"); + } + break; + + case EC_ACTIVATE: + str.assign("EC_ACTIVATE\n"); + break; + +/* case EC_BANDWIDTHCHANGE: + str.assign("EC_BANDWIDTHCHANGE\n"); + break; +*/ + case EC_BUFFERING_DATA: + str.assign("EC_BUFFERING_DATA\n"); + break; + + case EC_BUILT: + str.assign("EC_BUILT\n"); + break; + + case EC_CLOCK_CHANGED: + str.assign("EC_CLOCK_CHANGED\n"); + break; + + case EC_CLOCK_UNSET: + str.assign("EC_CLOCK_UNSET\n"); + break; + + case EC_CODECAPI_EVENT: + str.assign("EC_CODECAPI_EVENT\n"); + break; + + case EC_COMPLETE: + str.assign("EC_COMPLETE\n"); + break; + +/* case EC_CONTENTPROPERTY_CHANGED: + str.assign("EC_CONTENTPROPERTY_CHANGED\n"); + break; +*/ + case EC_DISPLAY_CHANGED: + str.assign("EC_DISPLAY_CHANGED\n"); + break; + + case EC_END_OF_SEGMENT: + str.assign("EC_END_OF_SEGMENT\n"); + break; + +/* case EC_EOS_SOON: + str.assign("EC_EOS_SOON\n"); + break; +*/ + case EC_ERROR_STILLPLAYING: + str.assign("EC_ERROR_STILLPLAYING\n"); + break; + + case EC_ERRORABORT: + str.assign("EC_ERRORABORT\n"); + + log_info("graph monitor stopping capture...\n"); + + // shutdown capture + pSrc->cancelCaptureCB_(pSrc->parent_); + + break; + +/* case EC_ERRORABORTEX: + str.assign("EC_ERRORABORTEX\n"); + break; +*/ + case EC_EXTDEVICE_MODE_CHANGE: + str.assign("EC_EXTDEVICE_MODE_CHANGE\n"); + break; + +/* case EC_FILE_CLOSED: + str.assign("EC_FILE_CLOSED\n"); + break; +*/ + case EC_FULLSCREEN_LOST: + str.assign("EC_FULLSCREEN_LOST\n"); + break; + + case EC_GRAPH_CHANGED: + str.assign("EC_GRAPH_CHANGED\n"); + break; + + case EC_LENGTH_CHANGED: + str.assign("EC_LENGTH_CHANGED\n"); + break; + +/* case EC_LOADSTATUS: + str.assign("EC_LOADSTATUS\n"); + break; +*/ +/* case EC_MARKER_HIT: + str.assign("EC_MARKER_HIT\n"); + break; +*/ + case EC_NEED_RESTART: + str.assign("EC_NEED_RESTART\n"); + break; + +/* case EC_NEW_PIN: + str.assign("EC_NEW_PIN\n"); + break; +*/ + case EC_NOTIFY_WINDOW: + str.assign("EC_NOTIFY_WINDOW\n"); + break; + + case EC_OLE_EVENT: + str.assign("EC_OLE_EVENT\n"); + break; + + case EC_OPENING_FILE: + str.assign("EC_OPENING_FILE\n"); + break; + + case EC_PALETTE_CHANGED: + str.assign("EC_PALETTE_CHANGED\n"); + break; + + case EC_PAUSED: + str.assign("EC_PAUSED\n"); + break; + +/* case EC_PLEASE_REOPEN: + str.assign("EC_PLEASE_REOPEN\n"); + break; +*/ + case EC_PREPROCESS_COMPLETE: + str.assign("EC_PREPROCESS_COMPLETE\n"); + break; + +/* case EC_PROCESSING_LATENCY: + str.assign("EC_PROCESSING_LATENCY\n"); + break; +*/ + case EC_QUALITY_CHANGE: + str.assign("EC_QUALITY_CHANGE\n"); + break; + +/* case EC_RENDER_FINISHED: + str.assign("EC_RENDER_FINISHED\n"); + break; +*/ + case EC_REPAINT: + str.assign("EC_REPAINT\n"); + break; + +/* case EC_SAMPLE_LATENCY: + str.assign("EC_SAMPLE_LATENCY\n"); + break; + + case EC_SAMPLE_NEEDED: + str.assign("EC_SAMPLE_NEEDED\n"); + break; + + case EC_SCRUB_TIME: + str.assign("EC_SCRUB_TIME\n"); + break; +*/ + case EC_SEGMENT_STARTED: + str.assign("EC_SEGMENT_STARTED\n"); + break; + + case EC_SHUTTING_DOWN: + str.assign("EC_SHUTTING_DOWN\n"); + break; + + case EC_SNDDEV_IN_ERROR: + str.assign("EC_SNDDEV_IN_ERROR\n"); + break; + + case EC_SNDDEV_OUT_ERROR: + str.assign("EC_SNDDEV_OUT_ERROR\n"); + break; + + case EC_STARVATION: + str.assign("EC_STARVATION\n"); + break; + + case EC_STATE_CHANGE: + str.assign("EC_STATE_CHANGE\n"); + break; + +/* case EC_STATUS: + str.assign("EC_STATUS\n"); + break; +*/ + case EC_STEP_COMPLETE: + str.assign("EC_STEP_COMPLETE\n"); + break; + + case EC_STREAM_CONTROL_STARTED: + str.assign("EC_STREAM_CONTROL_STARTED\n"); + break; + + case EC_STREAM_CONTROL_STOPPED: + str.assign("EC_STREAM_CONTROL_STOPPED\n"); + break; + + case EC_STREAM_ERROR_STILLPLAYING: + str.assign("EC_STREAM_ERROR_STILLPLAYING\n"); + break; + + case EC_STREAM_ERROR_STOPPED: + str.assign("EC_STREAM_ERROR_STOPPED\n"); + break; + + case EC_TIMECODE_AVAILABLE: + str.assign("EC_TIMECODE_AVAILABLE\n"); + break; + + case EC_UNBUILT: + str.assign("EC_UNBUILT\n"); + break; + + case EC_USERABORT: + str.assign("EC_USERABORT\n"); + break; + + case EC_VIDEO_SIZE_CHANGED: + str.assign("EC_VIDEO_SIZE_CHANGED\n"); + break; + +/* case EC_VIDEOFRAMEREADY: + str.assign("EC_VIDEOFRAMEREADY\n"); + break; +*/ + case EC_VMR_RECONNECTION_FAILED: + str.assign("EC_VMR_RECONNECTION_FAILED\n"); + break; + + case EC_VMR_RENDERDEVICE_SET: + str.assign("EC_VMR_RENDERDEVICE_SET\n"); + break; + + case EC_VMR_SURFACE_FLIPPED: + str.assign("EC_VMR_SURFACE_FLIPPED\n"); + break; + + case EC_WINDOW_DESTROYED: + str.assign("EC_WINDOW_DESTROYED\n"); + break; + + case EC_WMT_EVENT: + str.assign("EC_WMT_EVENT\n"); + break; + + case EC_WMT_INDEX_EVENT: + str.assign("EC_WMT_INDEX_EVENT\n"); + break; + + default: + str.assign("unknown graph event code (%ld)\n", evCode); + break; + } + + log_info("graph processed event: %s", str.c_str()); + + hr = pSrc->pMediaEventIF_->FreeEventParams(evCode, param1, param2); + } + else + { + log_error("failed getting event for a graph\n"); + } +} + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. m. <lib...@li...> - 2007-10-01 19:37:38
|
Revision: 37 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=37&view=rev Author: bcholew Date: 2007-10-01 12:37:33 -0700 (Mon, 01 Oct 2007) Log Message: ----------- Pull out threading- and state-related members from DirectShowSource into new class SourceStateMachine. Modified Paths: -------------- trunk/src/directshow/DShowSrcManager.cpp trunk/src/directshow/DirectShowSource.cpp trunk/src/directshow/DirectShowSource.h trunk/src/sapi_dshow.cpp Added Paths: ----------- trunk/src/directshow/SourceStateMachine.cpp trunk/src/directshow/SourceStateMachine.h Modified: trunk/src/directshow/DShowSrcManager.cpp =================================================================== --- trunk/src/directshow/DShowSrcManager.cpp 2007-10-01 16:58:11 UTC (rev 36) +++ trunk/src/directshow/DShowSrcManager.cpp 2007-10-01 19:37:33 UTC (rev 37) @@ -35,7 +35,7 @@ #include "logging.h" #include "DShowSrcManager.h" -#include "DirectShowSource.h" +#include "SourceStateMachine.h" DShowSrcManager * DShowSrcManager::instance_ = 0; Modified: trunk/src/directshow/DirectShowSource.cpp =================================================================== --- trunk/src/directshow/DirectShowSource.cpp 2007-10-01 16:58:11 UTC (rev 36) +++ trunk/src/directshow/DirectShowSource.cpp 2007-10-01 19:37:33 UTC (rev 37) @@ -37,9 +37,12 @@ #include "DirectShowSource.h" DirectShowSource::DirectShowSource(struct sapi_src_context *src, - DShowSrcManager *mgr) + DShowSrcManager *mgr, bufferCallbackFunc cbFunc, cancelCaptureFunc cancelCaptureCB, void * parent) : sourceContext_(src), dshowMgr_(mgr), + bufferCB_(cbFunc), + cancelCaptureCB_(cancelCaptureCB), + parent_(parent), graphMon_(0), pSource_(0), pCapGraphBuilder_(0), @@ -51,41 +54,9 @@ pNullRenderer_(0), pMediaControlIF_(0), nativeMediaType_(0), - graphHandle_(0), graphIsSetup_(false), - eventInitDone_(0), - eventStart_(0), - eventStop_(0), - eventTerminate_(0), - eventCancel_(0), - sourceThread_(0), - sourceThreadID_(0), - okToSendStart_(true), - okToSendStop_(true), - allowCallbacks_(false), - callbackInProgress_(false), - callbackCancellationInProgress_(false), - captureStopped_(true) + graphHandle_(0) { - if ( !dshowMgr_ ) - { - log_error("NULL manager passed to DirectShowSource constructor."); - throw std::runtime_error("NULL manager passed to DirectShowSource"); - } - - if ( !sourceContext_ ) - { - log_error("NULL source context passed to DirectShowSource ctor."); - throw std::runtime_error("NULL source context passed to constructor"); - } - - if ( !dshowMgr_->okayToBuildSource( getID() ) ) - { - log_warn("Mgr won't permit construction of DirectShowSource w/id '%s'." - " It's already been acquired.\n", getID()); - throw std::runtime_error("source already acquired"); - } - IBindCtx * pBindCtx = 0; IMoniker * pMoniker = 0; @@ -120,32 +91,8 @@ goto constructionFailure; } - if ( createEvents() ) - { - log_error("failed creating events for source thread"); - goto constructionFailure; - } + return; - // pass instance to thread - sourceThread_ = CreateThread( - NULL, - 0, - (LPTHREAD_START_ROUTINE)(&DirectShowSource::waitForCmd), - this, - 0, - &sourceThreadID_); - - if ( sourceThread_ != NULL ) - { - // wait for signal from thread that it is ready - WaitForSingleObject(eventInitDone_, INFINITE); - - return; - } - - log_error("failed spinning source thread (%d)\n", - GetLastError()); - constructionFailure: destroyCapGraphFoo(); @@ -156,40 +103,19 @@ pMoniker->Release(); pBindCtx->Release(); - dshowMgr_->sourceReleased( getID() ); - throw std::runtime_error("failed source construction"); } DirectShowSource::~DirectShowSource() { - log_info("Signaling source '%s' to terminate...\n", - sourceContext_->src_info.description); + stop(); - // signal thread to shutdown - if ( !SetEvent(eventTerminate_) ) - { - log_error("failed to signal graph monitor thread to terminate (%d)\n", - GetLastError()); - return; - } + if ( nativeMediaType_ ) + freeMediaType(*nativeMediaType_); - // wait for thread to shutdown - DWORD rc = WaitForSingleObject(sourceThread_, INFINITE); + destroyCapGraphFoo(); - if ( rc == WAIT_FAILED ) - { - log_error("DirectShowSource: failed waiting for thread to return (%d)\n", - GetLastError()); - } - - log_info("source '%s' has terminated\n", - sourceContext_->src_info.description); - - CloseHandle(eventInitDone_); - CloseHandle(eventStart_); - CloseHandle(eventStop_); - CloseHandle(eventTerminate_); + pSource_->Release(); } int @@ -318,12 +244,12 @@ return -1; } - hr = pMediaEventIF_->GetEventHandle((OAEVENT *)&graphHandle_); - if ( FAILED(hr) ) - { - log_error("failed to get handle for filter graph\n"); + hr = pMediaEventIF_->GetEventHandle((OAEVENT *)&graphHandle_); + if ( FAILED(hr) ) + { + log_error("failed to get handle for filter graph\n"); return -1; - } + } return 0; } @@ -360,192 +286,6 @@ } int -DirectShowSource::createEvents() -{ - // create an event used to signal that the thread has been created - eventInitDone_ = CreateEvent( - NULL, // default security attributes - TRUE, // manual-reset event - FALSE, // initial state is clear - NULL // no name - ); - - if ( eventInitDone_ == NULL) - { - log_error("DirectShowSource: failed creating initDone event (%d)\n", - GetLastError()); - return -1; - } - - // create an event used to signal thread to start capture - eventStart_ = CreateEvent( - NULL, // default security attributes - TRUE, // manual-reset event - FALSE, // initial state is clear - NULL // no name - ); - - if ( eventStart_ == NULL) - { - log_error("DirectShowSource: failed creating start event (%d)\n", - GetLastError()); - CloseHandle(eventInitDone_); - return -1; - } - - // create an event used to signal thread to stop capture - eventStop_ = CreateEvent( - NULL, // default security attributes - TRUE, // manual-reset event - FALSE, // initial state is clear - NULL // no name - ); - - if ( eventStop_ == NULL) - { - log_error("DirectShowSource: failed creating stop event (%d)\n", - GetLastError()); - CloseHandle(eventInitDone_); - CloseHandle(eventStart_); - return -1; - } - - // create an event used to signal thread to terminate - eventTerminate_ = CreateEvent( - NULL, // default security attributes - TRUE, // manual-reset event - FALSE, // initial state is clear - NULL // no name - ); - - if ( eventTerminate_ == NULL) - { - log_error("DirectShowSource: failed creating terminate event (%d)\n", - GetLastError()); - CloseHandle(eventInitDone_); - CloseHandle(eventStart_); - CloseHandle(eventStop_); - return -1; - } - - // create an event used to signal thread to cancel capture - eventCancel_ = CreateEvent( - NULL, // default security attributes - TRUE, // manual-reset event - FALSE, // initial state is clear - NULL // no name - ); - - if ( eventCancel_ == NULL) - { - log_error("DirectShowSource: failed creating cancel event (%d)\n", - GetLastError()); - CloseHandle(eventInitDone_); - CloseHandle(eventStart_); - CloseHandle(eventStop_); - CloseHandle(eventTerminate_); - return -1; - } - - return 0; -} - -DWORD WINAPI -DirectShowSource::waitForCmd(LPVOID lpParam) -{ - // extract instance - DirectShowSource * pSrc = static_cast<DirectShowSource *>(lpParam); - - // signal to main thread that we are ready for commands - if ( !SetEvent(pSrc->eventInitDone_) ) - { - log_error("failed to signal that source thread is ready (%d)\n", - GetLastError()); - return -1; - } - - enum { cancelEventIndex = 0, startEventIndex, stopEventIndex, - terminateEventIndex }; - - size_t numHandles = terminateEventIndex + 1; - HANDLE * waitHandles = new HANDLE [numHandles]; - - waitHandles[cancelEventIndex] = pSrc->eventCancel_; - waitHandles[startEventIndex] = pSrc->eventStart_; - waitHandles[stopEventIndex] = pSrc->eventStop_; - waitHandles[terminateEventIndex] = pSrc->eventTerminate_; - - while ( true ) - { - // wait until signaled to start or stop capture - // OR to terminate - DWORD rc = WaitForMultipleObjects(static_cast<DWORD>(numHandles), - waitHandles, false, INFINITE); - - // get index of object that signaled - unsigned int index = rc - WAIT_OBJECT_0; - - if ( rc == WAIT_FAILED ) - { - log_warn("source wait failed. (0x%x)\n", GetLastError()); - } - else if ( index == terminateEventIndex ) - { - // give terminate the highest priority - - pSrc->terminate(); - break; - } - else if ( index == cancelEventIndex ) - { - // give cancel a higher priority than start/stop - - if ( !ResetEvent(pSrc->eventCancel_) ) - { - log_error("failed to reset source start event flag." - "Terminating.\n"); - // terminate - break; - } - - pSrc->doCancelCallbacks(); - } - else if ( index == startEventIndex ) - { - if ( !ResetEvent(pSrc->eventStart_) ) - { - log_error("failed to reset source start event flag." - "Terminating.\n"); - // terminate - break; - } - - pSrc->okToSendStop_ = true; - - pSrc->doStart(); - } - else if ( index == stopEventIndex ) - { - if ( !ResetEvent(pSrc->eventStop_) ) - { - log_error("failed to reset source stop event flag." - "Terminating.\n"); - // terminate - break; - } - - pSrc->okToSendStart_ = true; - - pSrc->doStop(); - } - } - - delete [] waitHandles; - - return 0; -} - -int DirectShowSource::resetCapGraphFoo() { if ( graphIsSetup_ ) @@ -643,105 +383,29 @@ return 0; } -void -DirectShowSource::terminate() -{ - doStop(); - - if ( nativeMediaType_ ) - freeMediaType(*nativeMediaType_); - - destroyCapGraphFoo(); - - pSource_->Release(); - - dshowMgr_->sourceReleased( getID() ); -} - int DirectShowSource::start() { - if ( !okToSendStart_ ) - return -1; - - okToSendStart_ = false; - - // signal source thread to start capturing - if ( !SetEvent(eventStart_) ) - { - log_error("failed to signal source to start (%d)\n", - GetLastError()); - return -1; - } - - return 0; -} - -void -DirectShowSource::doStart() -{ if ( !setupCapGraphFoo() ) { - allowCallbacks_ = true; - HRESULT hr = pMediaControlIF_->Run(); if ( SUCCEEDED(hr) ) - return; + return 0; log_error("failed to run filter graph for source '%s' (%ul 0x%x)\n", sourceContext_->src_info.description, hr, hr); } - else - okToSendStart_ = true; - allowCallbacks_ = false; - - // final capture callback - with error status - sapi_src_capture_notify(sourceContext_, 0, 0, -1); + return -1; } // NOTE: This function will block until capture is // completely stopped. // Even when returning failure, it guarantees // no more callbacks will occur -int +void DirectShowSource::stop() { - while ( !okToSendStop_ ) - Sleep(10); - - okToSendStop_ = false; - - captureStopped_ = false; - - // signal source thread to stop capturing - if ( !SetEvent(eventStop_) ) - { - log_error("failed to signal source to stop (%d)\n", - GetLastError()); - - // Need to ensure no more callbacks arrive - // Do this the hard way - allowCallbacks_ = false; - while ( callbackInProgress_ || callbackCancellationInProgress_ ) - Sleep(10); - - return -1; - } - - // wait for source thread to indicate that capture has stopped - // guaranteeing no more callbacks will occur after this returns - while ( !captureStopped_ ) - Sleep(10); - - return 0; -} - -void -DirectShowSource::doStop() -{ - allowCallbacks_ = false; - if ( graphIsSetup_ ) { HRESULT hr = pMediaControlIF_->Stop(); @@ -760,13 +424,6 @@ // RenderStream(), but before graph's Run()? resetCapGraphFoo(); } - - // make sure we're not in a callback - while ( callbackInProgress_ ) - Sleep(10); - - // signal back to main thread that capture has stopped - captureStopped_ = true; } int @@ -1095,58 +752,6 @@ mediaType.pUnk->Release(); } -void -DirectShowSource::cancelCallbacks() -{ - // signal source thread to cancel capturing - if ( !SetEvent(eventCancel_) ) - { - log_error("failed to signal source to cancel (%d)\n", - GetLastError()); - - // Need to ensure app is notified - // Do it the hard way - - // prevent future callbacks - allowCallbacks_ = false; - - // wait for current callback to finish - while ( callbackInProgress_ ) - Sleep(10); - - // final capture callback - with error status - sapi_src_capture_notify(sourceContext_, 0, 0, -1); - } -} - -void -DirectShowSource::doCancelCallbacks() -{ - callbackCancellationInProgress_ = true; - - // has capture been stopped already? - if ( !allowCallbacks_ ) - { - callbackCancellationInProgress_ = false; - return; - } - - // prevent future callbacks - allowCallbacks_ = false; - - // block until current callback is not in progress - while ( callbackInProgress_ ) - Sleep(10); - - // stop callbacks before sending final callback - doStop(); - - // final capture callback - with error status - sapi_src_capture_notify(sourceContext_, 0, 0, -1); - - callbackCancellationInProgress_ = false; -} - STDMETHODIMP DirectShowSource::QueryInterface(REFIID riid, void ** ppv) { @@ -1168,21 +773,7 @@ STDMETHODIMP DirectShowSource::BufferCB( double dblSampleTime, BYTE * pBuff, long buffSize ) { - callbackInProgress_ = true; - - if ( !allowCallbacks_ ) - { - callbackInProgress_ = false; - return 0; - } - - int ret = sapi_src_capture_notify(sourceContext_, - reinterpret_cast<const char *>(pBuff), - static_cast<int>(buffSize), 0); - - callbackInProgress_ = false; - - return ret; + return bufferCB_(dblSampleTime, pBuff, buffSize, parent_); } int @@ -1247,7 +838,7 @@ log_info("device removal detected\n"); // shutdown capture - pSrc->cancelCallbacks(); + pSrc->cancelCaptureCB_(pSrc->parent_); } else { @@ -1313,7 +904,7 @@ log_info("graph monitor stopping capture...\n"); // shutdown capture - pSrc->cancelCallbacks(); + pSrc->cancelCaptureCB_(pSrc->parent_); break; Modified: trunk/src/directshow/DirectShowSource.h =================================================================== --- trunk/src/directshow/DirectShowSource.h 2007-10-01 16:58:11 UTC (rev 36) +++ trunk/src/directshow/DirectShowSource.h 2007-10-01 19:37:33 UTC (rev 37) @@ -38,12 +38,15 @@ { public: - DirectShowSource(struct sapi_src_context *src, DShowSrcManager *); + typedef int (*bufferCallbackFunc)(double, BYTE *, long, void *); + typedef void (*cancelCaptureFunc)(void *); + + DirectShowSource(struct sapi_src_context *, DShowSrcManager *, + bufferCallbackFunc, cancelCaptureFunc, void *); ~DirectShowSource(); int start(); - int stop(); - void cancelCallbacks(); + void stop(); int bindFormat(const vidcap_fmt_info * fmtInfo); int validateFormat(const vidcap_fmt_info * fmtNominal, vidcap_fmt_info * fmtNative) const; @@ -57,13 +60,6 @@ } private: - static DWORD WINAPI waitForCmd(LPVOID); - void terminate(); - void doStart(); - void doStop(); - void doCancelCallbacks(); - int createEvents(); - int createCapGraphFoo(); void destroyCapGraphFoo(); int setupCapGraphFoo(); @@ -85,20 +81,22 @@ STDMETHODIMP QueryInterface(REFIID riid, void ** ppv); // Not used - STDMETHODIMP SampleCB( double SampleTime, IMediaSample * pSample ) + STDMETHODIMP SampleCB( double, IMediaSample *) { return S_OK; } // The sample grabber calls us back from its deliver thread - STDMETHODIMP - BufferCB( double dblSampleTime, BYTE * pBuffer, long lBufferSize ); + STDMETHODIMP BufferCB( double, BYTE *, long ); static int mapDirectShowMediaTypeToVidcapFourcc(DWORD data, int & fourcc); private: struct sapi_src_context * sourceContext_; DShowSrcManager * dshowMgr_; + bufferCallbackFunc bufferCB_; + cancelCaptureFunc cancelCaptureCB_; + void * parent_; GraphMonitor *graphMon_; IBaseFilter * pSource_; @@ -113,21 +111,6 @@ AM_MEDIA_TYPE *nativeMediaType_; HANDLE *graphHandle_; bool graphIsSetup_; - - HANDLE eventInitDone_; - HANDLE eventStart_; - HANDLE eventStop_; - HANDLE eventTerminate_; - HANDLE eventCancel_; - void * sourceThread_; - DWORD sourceThreadID_; - - bool okToSendStart_; - bool okToSendStop_; - bool allowCallbacks_; - bool callbackInProgress_; - bool callbackCancellationInProgress_; - bool captureStopped_; }; #endif Added: trunk/src/directshow/SourceStateMachine.cpp =================================================================== --- trunk/src/directshow/SourceStateMachine.cpp (rev 0) +++ trunk/src/directshow/SourceStateMachine.cpp 2007-10-01 19:37:33 UTC (rev 37) @@ -0,0 +1,529 @@ +// +// libvidcap - a cross-platform video capture library +// +// Copyright 2007 Wimba, Inc. +// +// Contributors: +// Peter Grayson <jpg...@gm...> +// Bill Cholewka <bc...@gm...> +// +// libvidcap is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// libvidcap is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this program. If not, see +// <http://www.gnu.org/licenses/>. +// + +#include <windows.h> + +#include "hotlist.h" +#include "logging.h" +#include "sapi.h" +#include "SourceStateMachine.h" + +SourceStateMachine::SourceStateMachine(struct sapi_src_context *src, + DShowSrcManager *mgr) + : sourceContext_(src), + dshowMgr_(mgr), + src_(0), + eventInitDone_(0), + eventStart_(0), + eventStop_(0), + eventTerminate_(0), + eventCancel_(0), + sourceThread_(0), + sourceThreadID_(0), + okToSendStart_(true), + okToSendStop_(true), + allowCallbacks_(false), + callbackInProgress_(false), + callbackCancellationInProgress_(false), + captureStopped_(true) +{ + if ( !dshowMgr_ ) + { + log_error("NULL manager passed to SourceStateMachine constructor."); + throw std::runtime_error("NULL manager passed to SourceStateMachine"); + } + + if ( !sourceContext_ ) + { + log_error("NULL source context passed to SourceStateMachine ctor."); + throw std::runtime_error("NULL source context passed to constructor"); + } + + if ( !dshowMgr_->okayToBuildSource( getID() ) ) + { + log_warn("Mgr won't permit construction of SourceStateMachine w/id '%s'." + " It's already been acquired.\n", getID()); + throw std::runtime_error("source already acquired"); + } + + try + { + src_ = new DirectShowSource(src, + mgr, + (bufferCallbackFunc)&SourceStateMachine::bufferCB, + (cancelCaptureFunc)&SourceStateMachine::cancelCaptureCB, + this); + } + catch (std::runtime_error &) //check + { + log_error("failed creating dshow source\n"); + goto constructionFailure; + } + + if ( createEvents() ) + { + log_error("failed creating events for source thread"); + goto constructionFailure; + } + + // pass instance to thread + sourceThread_ = CreateThread( + NULL, + 0, + (LPTHREAD_START_ROUTINE)(&SourceStateMachine::waitForCmd), + this, + 0, + &sourceThreadID_); + + if ( sourceThread_ != NULL ) + { + // wait for signal from thread that it is ready + WaitForSingleObject(eventInitDone_, INFINITE); + + return; + } + + log_error("failed spinning source thread (%d)\n", + GetLastError()); + +constructionFailure: + + throw std::runtime_error("failed source construction"); +} + +SourceStateMachine::~SourceStateMachine() +{ + log_info("Signaling source '%s' to terminate...\n", + sourceContext_->src_info.description); + + // signal thread to shutdown + if ( !SetEvent(eventTerminate_) ) + { + log_error("failed to signal graph monitor thread to terminate (%d)\n", + GetLastError()); + return; + } + + // wait for thread to shutdown + DWORD rc = WaitForSingleObject(sourceThread_, INFINITE); + + if ( rc == WAIT_FAILED ) + { + log_error("SourceStateMachine: failed waiting for thread to return (%d)\n", + GetLastError()); + } + + log_info("source '%s' has terminated\n", + sourceContext_->src_info.description); + + CloseHandle(eventInitDone_); + CloseHandle(eventStart_); + CloseHandle(eventStop_); + CloseHandle(eventTerminate_); +} + +int +SourceStateMachine::createEvents() +{ + // create an event used to signal that the thread has been created + eventInitDone_ = CreateEvent( + NULL, // default security attributes + TRUE, // manual-reset event + FALSE, // initial state is clear + NULL // no name + ); + + if ( eventInitDone_ == NULL) + { + log_error("SourceStateMachine: failed creating initDone event (%d)\n", + GetLastError()); + return -1; + } + + // create an event used to signal thread to start capture + eventStart_ = CreateEvent( + NULL, // default security attributes + TRUE, // manual-reset event + FALSE, // initial state is clear + NULL // no name + ); + + if ( eventStart_ == NULL) + { + log_error("SourceStateMachine: failed creating start event (%d)\n", + GetLastError()); + CloseHandle(eventInitDone_); + return -1; + } + + // create an event used to signal thread to stop capture + eventStop_ = CreateEvent( + NULL, // default security attributes + TRUE, // manual-reset event + FALSE, // initial state is clear + NULL // no name + ); + + if ( eventStop_ == NULL) + { + log_error("SourceStateMachine: failed creating stop event (%d)\n", + GetLastError()); + CloseHandle(eventInitDone_); + CloseHandle(eventStart_); + return -1; + } + + // create an event used to signal thread to terminate + eventTerminate_ = CreateEvent( + NULL, // default security attributes + TRUE, // manual-reset event + FALSE, // initial state is clear + NULL // no name + ); + + if ( eventTerminate_ == NULL) + { + log_error("SourceStateMachine: failed creating terminate event (%d)\n", + GetLastError()); + CloseHandle(eventInitDone_); + CloseHandle(eventStart_); + CloseHandle(eventStop_); + return -1; + } + + // create an event used to signal thread to cancel capture + eventCancel_ = CreateEvent( + NULL, // default security attributes + TRUE, // manual-reset event + FALSE, // initial state is clear + NULL // no name + ); + + if ( eventCancel_ == NULL) + { + log_error("SourceStateMachine: failed creating cancel event (%d)\n", + GetLastError()); + CloseHandle(eventInitDone_); + CloseHandle(eventStart_); + CloseHandle(eventStop_); + CloseHandle(eventTerminate_); + return -1; + } + + return 0; +} + +DWORD WINAPI +SourceStateMachine::waitForCmd(LPVOID lpParam) +{ + // extract instance + SourceStateMachine * pSrc = (SourceStateMachine *)lpParam; + + // signal to main thread that we are ready for commands + if ( !SetEvent(pSrc->eventInitDone_) ) + { + log_error("failed to signal that source thread is ready (%d)\n", + GetLastError()); + return -1; + } + + enum { cancelEventIndex = 0, startEventIndex, stopEventIndex, + terminateEventIndex }; + + size_t numHandles = terminateEventIndex + 1; + HANDLE * waitHandles = new HANDLE [numHandles]; + + waitHandles[cancelEventIndex] = pSrc->eventCancel_; + waitHandles[startEventIndex] = pSrc->eventStart_; + waitHandles[stopEventIndex] = pSrc->eventStop_; + waitHandles[terminateEventIndex] = pSrc->eventTerminate_; + + while ( true ) + { + // wait until signaled to start or stop capture + // OR to terminate + DWORD rc = WaitForMultipleObjects(static_cast<DWORD>(numHandles), + waitHandles, false, INFINITE); + + // get index of object that signaled + unsigned int index = rc - WAIT_OBJECT_0; + + if ( rc == WAIT_FAILED ) + { + log_warn("source wait failed. (0x%x)\n", GetLastError()); + } + else if ( index == terminateEventIndex ) + { + // give terminate the highest priority + + pSrc->terminate(); + break; + } + else if ( index == cancelEventIndex ) + { + // give cancel a higher priority than start/stop + + if ( !ResetEvent(pSrc->eventCancel_) ) + { + log_error("failed to reset source start event flag." + "Terminating.\n"); + // terminate + break; + } + + pSrc->doCancelCapture(); + } + else if ( index == startEventIndex ) + { + if ( !ResetEvent(pSrc->eventStart_) ) + { + log_error("failed to reset source start event flag." + "Terminating.\n"); + // terminate + break; + } + + pSrc->okToSendStop_ = true; + + pSrc->doStart(); + } + else if ( index == stopEventIndex ) + { + if ( !ResetEvent(pSrc->eventStop_) ) + { + log_error("failed to reset source stop event flag." + "Terminating.\n"); + // terminate + break; + } + + pSrc->okToSendStart_ = true; + + pSrc->doStop(); + } + } + + delete [] waitHandles; + + return 0; +} + +void +SourceStateMachine::terminate() +{ + delete src_; + + dshowMgr_->sourceReleased( getID() ); +} + +int +SourceStateMachine::start() +{ + if ( !okToSendStart_ ) + return -1; + + okToSendStart_ = false; + + // signal source thread to start capturing + if ( !SetEvent(eventStart_) ) + { + log_error("failed to signal source to start (%d)\n", + GetLastError()); + return -1; + } + + return 0; +} + +void +SourceStateMachine::doStart() +{ + if ( src_->start() ) + { + log_error("failed to run filter graph for source '%s'\n", + sourceContext_->src_info.description); + + allowCallbacks_ = false; + okToSendStart_ = true; + + // final capture callback - with error status + sapi_src_capture_notify(sourceContext_, 0, 0, -1); + } + else + { + allowCallbacks_ = true; + } + +} + +// NOTE: This function will block until capture is +// completely stopped. +// Even when returning failure, it guarantees +// no more callbacks will occur +int +SourceStateMachine::stop() +{ + while ( !okToSendStop_ ) + Sleep(10); + + okToSendStop_ = false; + + captureStopped_ = false; + + // signal source thread to stop capturing + if ( !SetEvent(eventStop_) ) + { + log_error("failed to signal source to stop (%d)\n", + GetLastError()); + + // Need to ensure no more callbacks arrive + // Do this the hard way + allowCallbacks_ = false; + while ( callbackInProgress_ || callbackCancellationInProgress_ ) + Sleep(10); + + return -1; + } + + // wait for source thread to indicate that capture has stopped + // guaranteeing no more callbacks will occur after this returns + while ( !captureStopped_ ) + Sleep(10); + + return 0; +} + +void +SourceStateMachine::doStop() +{ + allowCallbacks_ = false; + + src_->stop(); + + // make sure we're not in a callback + while ( callbackInProgress_ ) + Sleep(10); + + // signal back to main thread that capture has stopped + captureStopped_ = true; +} + +int +SourceStateMachine::validateFormat(const vidcap_fmt_info * fmtNominal, + vidcap_fmt_info * fmtNative) const +{ + return src_->validateFormat(fmtNominal, fmtNative); +} + +int +SourceStateMachine::bindFormat(const vidcap_fmt_info * fmtNominal) +{ + return src_->bindFormat(fmtNominal); +} + +void +SourceStateMachine::cancelCaptureCB(void *parent) +{ + SourceStateMachine *instance = static_cast<SourceStateMachine *>(parent); + + instance->cancelCapture(); +} + +void +SourceStateMachine::cancelCapture() +{ + // signal source thread to cancel capturing + if ( !SetEvent(eventCancel_) ) + { + log_error("failed to signal source to cancel (%d)\n", + GetLastError()); + + // Need to ensure app is notified + // Do it the hard way + + // prevent future callbacks + allowCallbacks_ = false; + + // wait for current callback to finish + while ( callbackInProgress_ ) + Sleep(10); + + // final capture callback - with error status + sapi_src_capture_notify(sourceContext_, 0, 0, -1); + } +} + +void +SourceStateMachine::doCancelCapture() +{ + callbackCancellationInProgress_ = true; + + // has capture been stopped already? + if ( !allowCallbacks_ ) + { + callbackCancellationInProgress_ = false; + return; + } + + // prevent future callbacks + allowCallbacks_ = false; + + // block until current callback is not in progress + while ( callbackInProgress_ ) + Sleep(10); + + // stop callbacks before sending final callback + src_->stop(); + + // final capture callback - with error status + sapi_src_capture_notify(sourceContext_, 0, 0, -1); + + callbackCancellationInProgress_ = false; +} + +// The sample grabber calls this from its deliver thread +// NOTE: This function must not block, else it will cause a +// graph's Stop() to block - which could result in a deadlock +int +SourceStateMachine::bufferCB( double dblSampleTime, BYTE * pBuff, long buffSize, void *context ) +{ + SourceStateMachine *instance = static_cast<SourceStateMachine *>(context); + + instance->callbackInProgress_ = true; + + if ( !instance->allowCallbacks_ ) + { + instance->callbackInProgress_ = false; + return 0; + } + + int ret = sapi_src_capture_notify(instance->sourceContext_, + reinterpret_cast<const char *>(pBuff), + static_cast<int>(buffSize), 0); + + instance->callbackInProgress_ = false; + + return ret; +} + Added: trunk/src/directshow/SourceStateMachine.h =================================================================== --- trunk/src/directshow/SourceStateMachine.h (rev 0) +++ trunk/src/directshow/SourceStateMachine.h 2007-10-01 19:37:33 UTC (rev 37) @@ -0,0 +1,84 @@ +// +// libvidcap - a cross-platform video capture library +// +// Copyright 2007 Wimba, Inc. +// +// Contributors: +// Peter Grayson <jpg...@gm...> +// Bill Cholewka <bc...@gm...> +// +// libvidcap is free software; you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as +// published by the Free Software Foundation; either version 2.1 of +// the License, or (at your option) any later version. +// +// libvidcap is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public +// License along with this program. If not, see +// <http://www.gnu.org/licenses/>. +// + +#ifndef _SOURCESTATEMACHINE_H_ +#define _SOURCESTATEMACHINE_H_ + +#include "DirectShowSource.h" +#include "sapi_context.h" + +class SourceStateMachine +{ + +public: + SourceStateMachine(struct sapi_src_context *src, DShowSrcManager *); + ~SourceStateMachine(); + + int start(); + int stop(); + int bindFormat(const vidcap_fmt_info * fmtInfo); + int validateFormat(const vidcap_fmt_info * fmtNominal, + vidcap_fmt_info * fmtNative) const; + + const char * getID() const + { + return sourceContext_->src_info.identifier; + } + +private: + static DWORD WINAPI waitForCmd(LPVOID); + void terminate(); + void doStart(); + void doStop(); + void doCancelCapture(); + int createEvents(); + void cancelCapture(); + + typedef int (*bufferCallbackFunc)(double, BYTE *, long, void *); + static int bufferCB( double dblSampleTime, BYTE * pBuff, long buffSize, void *parent); + + typedef void (*cancelCaptureFunc)(void *); + static void cancelCaptureCB(void *parent); + +private: + struct sapi_src_context * sourceContext_; + DShowSrcManager * dshowMgr_; + DirectShowSource * src_; + HANDLE eventInitDone_; + HANDLE eventStart_; + HANDLE eventStop_; + HANDLE eventTerminate_; + HANDLE eventCancel_; + void * sourceThread_; + DWORD sourceThreadID_; + + bool okToSendStart_; + bool okToSendStop_; + bool allowCallbacks_; + bool callbackInProgress_; + bool callbackCancellationInProgress_; + bool captureStopped_; +}; + +#endif Modified: trunk/src/sapi_dshow.cpp =================================================================== --- trunk/src/sapi_dshow.cpp 2007-10-01 16:58:11 UTC (rev 36) +++ trunk/src/sapi_dshow.cpp 2007-10-01 19:37:33 UTC (rev 37) @@ -25,7 +25,7 @@ #include <windows.h> #include <stdio.h> -#include "DirectShowSource.h" +#include "SourceStateMachine.h" #include "DShowSrcManager.h" #include "logging.h" @@ -44,8 +44,8 @@ const struct vidcap_fmt_info * fmt_nominal, struct vidcap_fmt_info * fmt_native) { - DirectShowSource * dshow_src = - static_cast<DirectShowSource *>(src_ctx->priv); + SourceStateMachine * dshow_src = + static_cast<SourceStateMachine *>(src_ctx->priv); return dshow_src->validateFormat(fmt_nominal, fmt_native); } @@ -54,8 +54,8 @@ source_format_bind(struct sapi_src_context * src_ctx, const struct vidcap_fmt_info * fmtInfo) { - DirectShowSource * dshow_src = - static_cast<DirectShowSource *>(src_ctx->priv); + SourceStateMachine * dshow_src = + static_cast<SourceStateMachine *>(src_ctx->priv); return dshow_src->bindFormat(fmtInfo); } @@ -77,8 +77,8 @@ static int source_capture_start(struct sapi_src_context * src_ctx) { - DirectShowSource * dshow_src = - static_cast<DirectShowSource *>(src_ctx->priv); + SourceStateMachine * dshow_src = + static_cast<SourceStateMachine *>(src_ctx->priv); return dshow_src->start(); } @@ -86,8 +86,8 @@ static int source_capture_stop(struct sapi_src_context *src_ctx) { - DirectShowSource * dshow_src = - static_cast<DirectShowSource *>(src_ctx->priv); + SourceStateMachine *dshow_src = + static_cast<SourceStateMachine *>(src_ctx->priv); return dshow_src->stop(); } @@ -125,7 +125,7 @@ static int source_release(struct sapi_src_context * src_ctx) { - delete static_cast<DirectShowSource *>(src_ctx->priv); + delete static_cast<SourceStateMachine *>(src_ctx->priv); return 0; } @@ -162,7 +162,7 @@ try { - src_ctx->priv = new DirectShowSource(src_ctx, src_manager); + src_ctx->priv = new SourceStateMachine(src_ctx, src_manager); } catch ( std::runtime_error & e ) { This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. m. <lib...@li...> - 2007-10-01 16:58:21
|
Revision: 36 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=36&view=rev Author: bcholew Date: 2007-10-01 09:58:11 -0700 (Mon, 01 Oct 2007) Log Message: ----------- Simplify things: move from one graphMonitor (owned by source manager) monitoring every source, to a graphMonitor per source. No longer need LocklessQueue class. Move processing of graph events from graphMonitor to source. Modified Paths: -------------- trunk/src/directshow/DShowSrcManager.cpp trunk/src/directshow/DShowSrcManager.h trunk/src/directshow/DirectShowSource.cpp trunk/src/directshow/DirectShowSource.h trunk/src/directshow/GraphMonitor.cpp trunk/src/directshow/GraphMonitor.h Removed Paths: ------------- trunk/src/directshow/LocklessQueue.h Modified: trunk/src/directshow/DShowSrcManager.cpp =================================================================== --- trunk/src/directshow/DShowSrcManager.cpp 2007-09-28 21:20:58 UTC (rev 35) +++ trunk/src/directshow/DShowSrcManager.cpp 2007-10-01 16:58:11 UTC (rev 36) @@ -38,18 +38,10 @@ #include "DirectShowSource.h" DShowSrcManager * DShowSrcManager::instance_ = 0; -CRITICAL_SECTION DShowSrcManager::sourceDestructionMutex_; DShowSrcManager::DShowSrcManager() : numRefs_(0) { - // one mutex for all graphMonitors - InitializeCriticalSection(&sourceDestructionMutex_); - - graphMon_ = new GraphMonitor( - (cancelCallbackFunc)&DShowSrcManager::cancelSrcCaptureCallback, - this); - HRESULT hr = CoInitialize(NULL); if ( FAILED(hr) ) @@ -60,13 +52,9 @@ DShowSrcManager::~DShowSrcManager() { - delete graphMon_; - srcGraphList_.erase( srcGraphList_.begin(), srcGraphList_.end() ); CoUninitialize(); - - DeleteCriticalSection(&sourceDestructionMutex_); } DShowSrcManager * @@ -97,64 +85,6 @@ return devMon_.registerCallback(static_cast<sapi_context *>(sapiCtx)); } -void -DShowSrcManager::registerSrcGraph(const char *id, void *src, IMediaEventEx *pME) -{ - // find appropriate source id in list - for ( unsigned int i = 0; i < srcGraphList_.size(); i++ ) - { - // found matching id? - if ( srcGraphList_[i]->sourceId == id ) - { - // fill-in relevant info - srcGraphList_[i]->pSrc = src; - srcGraphList_[i]->pME = pME; - - // request that GraphMonitor monitor the graph for errors - graphMon_->addGraph(pME); - } - } -} - -bool -DShowSrcManager::cancelSrcCaptureCallback(IMediaEventEx *pME, void *ctx) -{ - bool ret = false; - DShowSrcManager *self = static_cast<DShowSrcManager *>(ctx); - - // NOTE: A source removal can be detected by both DevMonitor thread, - // and GraphMonitor thread. This can lead to cancellation of - // capture callbacks at the same time that the application - // is attempting to destroy the source. - // - // GraphMon -> cancelSrcCaptureCallback (this code) cancels callbacks - // DevMonitor -> app -> source destructor calls sourceReleased() - // - // Grab mutex to prevent concurrent access from this function and - // sourceReleased() - EnterCriticalSection(&sourceDestructionMutex_); - - // find appropriate source in list - for ( unsigned int i = 0; i < self->srcGraphList_.size(); i++ ) - { - // found matching MediaEvent interface? - if ( self->srcGraphList_[i]->pME == pME ) - { - // Found source to cancel callbacks for - DirectShowSource * pSrc = - static_cast<DirectShowSource *>(self->srcGraphList_[i]->pSrc); - - // cancel the source's callback - pSrc->cancelCallbacks(); - ret = true; - break; - } - } - LeaveCriticalSection(&sourceDestructionMutex_); - - return ret; -} - int DShowSrcManager::scan(struct sapi_src_list * srcList) const { @@ -267,7 +197,6 @@ pSrcGraphContext->sourceId = id; // these will be filled in later by registerSrcGraph() - pSrcGraphContext->pME = 0; pSrcGraphContext->pSrc = 0; // add source to collection @@ -279,7 +208,6 @@ void DShowSrcManager::sourceReleased(const char *id) { // NOTE: see note in function cancelSrcCaptureCallback() - EnterCriticalSection(&sourceDestructionMutex_); // find appropriate source id in list for ( unsigned int i = 0; i < srcGraphList_.size(); i++ ) @@ -295,17 +223,13 @@ srcGraphList_.erase( srcGraphList_.begin() + i ); // request that GraphMonitor stop monitoring the graph for errors - graphMon_->removeGraph(pSrcGraphContext->pME); delete pSrcGraphContext; - LeaveCriticalSection(&sourceDestructionMutex_); return; } } - LeaveCriticalSection(&sourceDestructionMutex_); - log_warn("couldn't find source '%s' to release\n", id); } @@ -393,8 +317,6 @@ return false; } -///// Private functions ///// - void DShowSrcManager::sprintDeviceInfo(IMoniker * pM, IBindCtx * pbc, char* idBuff, char *descBuff, int buffsSize) const Modified: trunk/src/directshow/DShowSrcManager.h =================================================================== --- trunk/src/directshow/DShowSrcManager.h 2007-09-28 21:20:58 UTC (rev 35) +++ trunk/src/directshow/DShowSrcManager.h 2007-10-01 16:58:11 UTC (rev 36) @@ -27,7 +27,6 @@ #include <vector> #include "DevMonitor.h" -#include "GraphMonitor.h" class DShowSrcManager { @@ -43,13 +42,6 @@ // for device event notifications (additions and removals) int registerNotifyCallback(void *); - // to monitor for graph errors during capture - void registerSrcGraph(const char *, void *, IMediaEventEx *); - - // graphMon_ callback to request capture abort - typedef bool (*cancelCallbackFunc)(IMediaEventEx *, void *); - static bool cancelSrcCaptureCallback(IMediaEventEx *, void *); - bool getJustCapDevice(const char *devLongName, IBindCtx **ppBindCtx, IMoniker **ppMoniker) const; @@ -62,23 +54,16 @@ int numRefs_; DevMonitor devMon_; - GraphMonitor *graphMon_; struct srcGraphContext { - IMediaEventEx * pME; void * pSrc; const char * sourceId; }; - // list of acquired sources, their filter graphs, and IDs + // list of acquired sources and IDs std::vector<srcGraphContext *> srcGraphList_; - // prevent DevMonitor -> app -> src destructor from destroying - // source while GraphMon -> cancelSrcCaptureCallback - // is in the midst of cancelling callbacks - static CRITICAL_SECTION sourceDestructionMutex_; - private: IPin * getOutPin( IBaseFilter *, int) const; HRESULT getPin( IBaseFilter *, PIN_DIRECTION, int, IPin **) const; Modified: trunk/src/directshow/DirectShowSource.cpp =================================================================== --- trunk/src/directshow/DirectShowSource.cpp 2007-09-28 21:20:58 UTC (rev 35) +++ trunk/src/directshow/DirectShowSource.cpp 2007-10-01 16:58:11 UTC (rev 36) @@ -29,7 +29,6 @@ #include <atlbase.h> #include <qedit.h> #include <comutil.h> -#include <DShow.h> #include <vidcap/converters.h> #include "hotlist.h" @@ -41,6 +40,7 @@ DShowSrcManager *mgr) : sourceContext_(src), dshowMgr_(mgr), + graphMon_(0), pSource_(0), pCapGraphBuilder_(0), pStreamConfig_(0), @@ -51,6 +51,7 @@ pNullRenderer_(0), pMediaControlIF_(0), nativeMediaType_(0), + graphHandle_(0), graphIsSetup_(false), eventInitDone_(0), eventStart_(0), @@ -107,8 +108,17 @@ if ( createCapGraphFoo() ) goto constructionFailure; - // register filter graph - to monitor for errors during capture - dshowMgr_->registerSrcGraph(src->src_info.identifier, this, pMediaEventIF_); + try + { + graphMon_ = new GraphMonitor(graphHandle_, + (graphEventCBFunc)&DirectShowSource::processGraphEvent, + this); + } + catch (std::runtime_error &) + { + log_error("failed to create graph monitor for source\n"); + goto constructionFailure; + } if ( createEvents() ) { @@ -308,6 +318,13 @@ return -1; } + hr = pMediaEventIF_->GetEventHandle((OAEVENT *)&graphHandle_); + if ( FAILED(hr) ) + { + log_error("failed to get handle for filter graph\n"); + return -1; + } + return 0; } @@ -337,6 +354,9 @@ if ( pCapGraphBuilder_ ) pCapGraphBuilder_->Release(); + + if ( graphHandle_ ) + CloseHandle(graphHandle_); } int @@ -434,7 +454,7 @@ DirectShowSource::waitForCmd(LPVOID lpParam) { // extract instance - DirectShowSource * pSrc = (DirectShowSource *)lpParam; + DirectShowSource * pSrc = static_cast<DirectShowSource *>(lpParam); // signal to main thread that we are ready for commands if ( !SetEvent(pSrc->eventInitDone_) ) @@ -1196,3 +1216,306 @@ return 0; } + +// Direct Show filter graph has signaled an event +// Device may have been removed +// Error may have occurred +void +DirectShowSource::processGraphEvent(void *context) +{ + DirectShowSource * pSrc = static_cast<DirectShowSource *>(context); + + HRESULT hr; + long evCode, param1, param2; + hr = pSrc->pMediaEventIF_->GetEvent(&evCode, ¶m1, ¶m2, 0); + + if ( SUCCEEDED(hr) ) + { + // Event codes taken from: + // http://msdn2.microsoft.com/en-us/library/ms783649.aspx + // Embedded reference not used: + // http://msdn2.microsoft.com/en-us/library/aa921722.aspx + + std::string str; + + switch(evCode) + { + case EC_DEVICE_LOST: + if ( (int)param2 == 0 ) + { + str.assign("EC_DEVICE_LOST\n"); + log_info("device removal detected\n"); + + // shutdown capture + pSrc->cancelCallbacks(); + } + else + { + str.assign("EC_DEVICE_LOST - (device re-inserted)\n"); + } + break; + + case EC_ACTIVATE: + str.assign("EC_ACTIVATE\n"); + break; + +/* case EC_BANDWIDTHCHANGE: + str.assign("EC_BANDWIDTHCHANGE\n"); + break; +*/ + case EC_BUFFERING_DATA: + str.assign("EC_BUFFERING_DATA\n"); + break; + + case EC_BUILT: + str.assign("EC_BUILT\n"); + break; + + case EC_CLOCK_CHANGED: + str.assign("EC_CLOCK_CHANGED\n"); + break; + + case EC_CLOCK_UNSET: + str.assign("EC_CLOCK_UNSET\n"); + break; + + case EC_CODECAPI_EVENT: + str.assign("EC_CODECAPI_EVENT\n"); + break; + + case EC_COMPLETE: + str.assign("EC_COMPLETE\n"); + break; + +/* case EC_CONTENTPROPERTY_CHANGED: + str.assign("EC_CONTENTPROPERTY_CHANGED\n"); + break; +*/ + case EC_DISPLAY_CHANGED: + str.assign("EC_DISPLAY_CHANGED\n"); + break; + + case EC_END_OF_SEGMENT: + str.assign("EC_END_OF_SEGMENT\n"); + break; + +/* case EC_EOS_SOON: + str.assign("EC_EOS_SOON\n"); + break; +*/ + case EC_ERROR_STILLPLAYING: + str.assign("EC_ERROR_STILLPLAYING\n"); + break; + + case EC_ERRORABORT: + str.assign("EC_ERRORABORT\n"); + + log_info("graph monitor stopping capture...\n"); + + // shutdown capture + pSrc->cancelCallbacks(); + + break; + +/* case EC_ERRORABORTEX: + str.assign("EC_ERRORABORTEX\n"); + break; +*/ + case EC_EXTDEVICE_MODE_CHANGE: + str.assign("EC_EXTDEVICE_MODE_CHANGE\n"); + break; + +/* case EC_FILE_CLOSED: + str.assign("EC_FILE_CLOSED\n"); + break; +*/ + case EC_FULLSCREEN_LOST: + str.assign("EC_FULLSCREEN_LOST\n"); + break; + + case EC_GRAPH_CHANGED: + str.assign("EC_GRAPH_CHANGED\n"); + break; + + case EC_LENGTH_CHANGED: + str.assign("EC_LENGTH_CHANGED\n"); + break; + +/* case EC_LOADSTATUS: + str.assign("EC_LOADSTATUS\n"); + break; +*/ +/* case EC_MARKER_HIT: + str.assign("EC_MARKER_HIT\n"); + break; +*/ + case EC_NEED_RESTART: + str.assign("EC_NEED_RESTART\n"); + break; + +/* case EC_NEW_PIN: + str.assign("EC_NEW_PIN\n"); + break; +*/ + case EC_NOTIFY_WINDOW: + str.assign("EC_NOTIFY_WINDOW\n"); + break; + + case EC_OLE_EVENT: + str.assign("EC_OLE_EVENT\n"); + break; + + case EC_OPENING_FILE: + str.assign("EC_OPENING_FILE\n"); + break; + + case EC_PALETTE_CHANGED: + str.assign("EC_PALETTE_CHANGED\n"); + break; + + case EC_PAUSED: + str.assign("EC_PAUSED\n"); + break; + +/* case EC_PLEASE_REOPEN: + str.assign("EC_PLEASE_REOPEN\n"); + break; +*/ + case EC_PREPROCESS_COMPLETE: + str.assign("EC_PREPROCESS_COMPLETE\n"); + break; + +/* case EC_PROCESSING_LATENCY: + str.assign("EC_PROCESSING_LATENCY\n"); + break; +*/ + case EC_QUALITY_CHANGE: + str.assign("EC_QUALITY_CHANGE\n"); + break; + +/* case EC_RENDER_FINISHED: + str.assign("EC_RENDER_FINISHED\n"); + break; +*/ + case EC_REPAINT: + str.assign("EC_REPAINT\n"); + break; + +/* case EC_SAMPLE_LATENCY: + str.assign("EC_SAMPLE_LATENCY\n"); + break; + + case EC_SAMPLE_NEEDED: + str.assign("EC_SAMPLE_NEEDED\n"); + break; + + case EC_SCRUB_TIME: + str.assign("EC_SCRUB_TIME\n"); + break; +*/ + case EC_SEGMENT_STARTED: + str.assign("EC_SEGMENT_STARTED\n"); + break; + + case EC_SHUTTING_DOWN: + str.assign("EC_SHUTTING_DOWN\n"); + break; + + case EC_SNDDEV_IN_ERROR: + str.assign("EC_SNDDEV_IN_ERROR\n"); + break; + + case EC_SNDDEV_OUT_ERROR: + str.assign("EC_SNDDEV_OUT_ERROR\n"); + break; + + case EC_STARVATION: + str.assign("EC_STARVATION\n"); + break; + + case EC_STATE_CHANGE: + str.assign("EC_STATE_CHANGE\n"); + break; + +/* case EC_STATUS: + str.assign("EC_STATUS\n"); + break; +*/ + case EC_STEP_COMPLETE: + str.assign("EC_STEP_COMPLETE\n"); + break; + + case EC_STREAM_CONTROL_STARTED: + str.assign("EC_STREAM_CONTROL_STARTED\n"); + break; + + case EC_STREAM_CONTROL_STOPPED: + str.assign("EC_STREAM_CONTROL_STOPPED\n"); + break; + + case EC_STREAM_ERROR_STILLPLAYING: + str.assign("EC_STREAM_ERROR_STILLPLAYING\n"); + break; + + case EC_STREAM_ERROR_STOPPED: + str.assign("EC_STREAM_ERROR_STOPPED\n"); + break; + + case EC_TIMECODE_AVAILABLE: + str.assign("EC_TIMECODE_AVAILABLE\n"); + break; + + case EC_UNBUILT: + str.assign("EC_UNBUILT\n"); + break; + + case EC_USERABORT: + str.assign("EC_USERABORT\n"); + break; + + case EC_VIDEO_SIZE_CHANGED: + str.assign("EC_VIDEO_SIZE_CHANGED\n"); + break; + +/* case EC_VIDEOFRAMEREADY: + str.assign("EC_VIDEOFRAMEREADY\n"); + break; +*/ + case EC_VMR_RECONNECTION_FAILED: + str.assign("EC_VMR_RECONNECTION_FAILED\n"); + break; + + case EC_VMR_RENDERDEVICE_SET: + str.assign("EC_VMR_RENDERDEVICE_SET\n"); + break; + + case EC_VMR_SURFACE_FLIPPED: + str.assign("EC_VMR_SURFACE_FLIPPED\n"); + break; + + case EC_WINDOW_DESTROYED: + str.assign("EC_WINDOW_DESTROYED\n"); + break; + + case EC_WMT_EVENT: + str.assign("EC_WMT_EVENT\n"); + break; + + case EC_WMT_INDEX_EVENT: + str.assign("EC_WMT_INDEX_EVENT\n"); + break; + + default: + str.assign("unknown graph event code (%ld)\n", evCode); + break; + } + + log_info("graph processed event: %s", str.c_str()); + + hr = pSrc->pMediaEventIF_->FreeEventParams(evCode, param1, param2); + } + else + { + log_error("failed getting event for a graph\n"); + } +} Modified: trunk/src/directshow/DirectShowSource.h =================================================================== --- trunk/src/directshow/DirectShowSource.h 2007-09-28 21:20:58 UTC (rev 35) +++ trunk/src/directshow/DirectShowSource.h 2007-10-01 16:58:11 UTC (rev 36) @@ -28,9 +28,11 @@ #include <stdexcept> #include <atlbase.h> #include <qedit.h> +#include <DShow.h> #include "DShowSrcManager.h" #include "sapi_context.h" +#include "GraphMonitor.h" class DirectShowSource : public ISampleGrabberCB { @@ -46,6 +48,9 @@ int validateFormat(const vidcap_fmt_info * fmtNominal, vidcap_fmt_info * fmtNative) const; + typedef void (*graphEventCBFunc)(void *); + static void processGraphEvent(void *); + const char * getID() const { return sourceContext_->src_info.identifier; @@ -94,6 +99,8 @@ private: struct sapi_src_context * sourceContext_; DShowSrcManager * dshowMgr_; + GraphMonitor *graphMon_; + IBaseFilter * pSource_; ICaptureGraphBuilder2 *pCapGraphBuilder_; IAMStreamConfig * pStreamConfig_; @@ -104,6 +111,7 @@ IBaseFilter * pNullRenderer_; IMediaControl * pMediaControlIF_; AM_MEDIA_TYPE *nativeMediaType_; + HANDLE *graphHandle_; bool graphIsSetup_; HANDLE eventInitDone_; Modified: trunk/src/directshow/GraphMonitor.cpp =================================================================== --- trunk/src/directshow/GraphMonitor.cpp 2007-09-28 21:20:58 UTC (rev 35) +++ trunk/src/directshow/GraphMonitor.cpp 2007-10-01 16:58:11 UTC (rev 36) @@ -25,33 +25,20 @@ // This thread will monitor a DirectShow filter graph for a capture device. // If the device is removed or encounters an error, the capture callback will // be called with a special status code, indicating it's the last callback -#include <sstream> + +#include <stdexcept> #include "GraphMonitor.h" #include "logging.h" -GraphMonitor::GraphMonitor(cancelCallbackFunc cb, void * parentCtx) - : cancelCBFunc_(cb), +GraphMonitor::GraphMonitor(HANDLE *graphHandle, + graphEventCBFunc cb, void * parentCtx) + : graphHandle_(graphHandle), + processGraphEvent_(cb), parentContext_(parentCtx), graphMonitorThread_(0), graphMonitorThreadID_(0) { // create an event used to wake up thread - // when graphs must be added or removed - // FIXME: how does one free these events? - listEvent_ = CreateEvent( - NULL, // default security attributes - TRUE, // manual-reset event - FALSE, // initial state is clear - NULL // no name - ); - - if ( listEvent_ == NULL) - { - log_error("CreateEvent failed (%d)\n", GetLastError()); - throw std::runtime_error("GraphMonitor: failed creating list event"); - } - - // create an event used to wake up thread // when thread must terminate terminateEvent_ = CreateEvent( NULL, // default security attributes @@ -84,7 +71,7 @@ graphMonitorThread_ = CreateThread( NULL, 0, - (LPTHREAD_START_ROUTINE)(&GraphMonitor::monitorGraphs), + (LPTHREAD_START_ROUTINE)(&GraphMonitor::monitorGraph), this, 0, &graphMonitorThreadID_); @@ -123,148 +110,11 @@ GetLastError()); } - for ( unsigned int i = 0; i < graphContextList_.size(); i++ ) - { - graphContextList_.erase( graphContextList_.begin() + i ); - } - - const graphListEvent * pListEvent; - while ( graphListEventQueue_.dequeue(&pListEvent) ) - { - delete pListEvent; - } - log_info("graph monitor thread destroyed\n"); } -// graph removals and additions dequeued by graph monitor thread -void -GraphMonitor::processListEvent() -{ - const graphListEvent * pListEvent; - - // take event off queue - // either add or remove graph - if ( !graphListEventQueue_.dequeue(&pListEvent) ) - { - log_info("failed to dequeue a graph list event\n"); - return; - } - - // get the Media Event interface - IMediaEventEx *pME = pListEvent->graph; - - switch ( pListEvent->eventType ) - { - case graphListEvent::add: - { - // get event handle, on which we can wait - HANDLE *hEvent = new HANDLE; - HRESULT hr = pME->GetEventHandle((OAEVENT *)&hEvent); - if ( FAILED(hr) ) - { - log_warn("failed to get handle for filter graph\n"); - break; - } - - // create a context with all relevant info - graphContext *pGraphContext = new graphContext(); - pGraphContext->pME = pME; - pGraphContext->waitHandle = hEvent; - - // add graph context to list - log_info("adding device #%d to graphMonitor list\n", - graphContextList_.size()); - - graphContextList_.push_back(pGraphContext); - } - break; - - case graphListEvent::remove: - { - // remove from vector - int i = findContext(pME); - if ( i >= 0 ) - { - graphContext *pGraphContext = graphContextList_[i]; - - graphContextList_.erase( graphContextList_.begin() + i ); - - std::ostringstream strm; - strm << "removed device #" << i << - " from graphMonitor list"; - - if ( (unsigned int)i < graphContextList_.size() ) - strm << " (device numbers " << i + 1 << - "+ will slide down 1 slot)"; - - log_info("%s\n", strm.str().c_str()); - - delete pGraphContext; - - //FIXME: how does one free the waitHandle? - return; - } - log_warn("failed to find MediaEvent interface to remove\n"); - } - break; - - default: - log_error("got a graph list UNKNOWN event\n"); - break; - } - - delete pListEvent; -} - -// graph addition enqueued by main thread -void -GraphMonitor::addGraph(IMediaEventEx *pME) -{ - graphListEvent * pListEvent = new graphListEvent; - - pListEvent->eventType = graphListEvent::add; - pListEvent->graph = pME; - - // queue-up graph to be added, - if ( !graphListEventQueue_.enqueue(pListEvent) ) - { - log_warn("failed to add graph to event queue\n"); - } - - // signal thread to wake up and add it - if ( !SetEvent(listEvent_) ) - { - log_error("failed to signal graph monitor thread of new graph (%d)\n", - GetLastError()); - } -} - -// graph removal enqueued by main thread -void -GraphMonitor::removeGraph(IMediaEventEx *pME) -{ - graphListEvent * pListEvent = new graphListEvent; - - pListEvent->eventType = graphListEvent::remove; - pListEvent->graph = pME; - - // queue-up graph to be removed, - if ( !graphListEventQueue_.enqueue(pListEvent) ) - { - log_warn("failed to add graph to the event queue\n"); - } - - // signal thread to wake up and remove it - if ( !SetEvent(listEvent_) ) - { - log_error("failed to signal graph monitor thread to " - "remove graph (%d)\n", GetLastError()); - } -} - DWORD WINAPI -GraphMonitor::monitorGraphs(LPVOID lpParam) +GraphMonitor::monitorGraph(LPVOID lpParam) { // extract instance GraphMonitor * pGraphMon = (GraphMonitor *)lpParam; @@ -277,69 +127,41 @@ return -1; } - while ( true ) - { - // Setup array of handles to wait on... - enum { terminateIndex = 0, listEventIndex, graphEventIndex_0 }; - size_t numHandles = pGraphMon->graphContextList_.size() + - graphEventIndex_0; - HANDLE * waitHandles = new HANDLE [numHandles]; + // Setup array of handles to wait on... + enum { terminateIndex = 0, graphEventIndex }; + const size_t numHandles = graphEventIndex + 1; + HANDLE * waitHandles = new HANDLE [numHandles]; - // ...plus something to break-out when a handle must be - // added or removed, or when thread must die - waitHandles[listEventIndex] = pGraphMon->listEvent_; - waitHandles[terminateIndex] = pGraphMon->terminateEvent_; + waitHandles[terminateIndex] = pGraphMon->terminateEvent_; - // complete the array of handles - for ( unsigned int i = 0; i < pGraphMon->graphContextList_.size(); i++ ) - { - waitHandles[i + graphEventIndex_0] = - pGraphMon->graphContextList_[i]->waitHandle; - } + // complete the array of handles + waitHandles[graphEventIndex] = pGraphMon->graphHandle_; - // wait until a graph signals an event OR - // a graph is added or removed OR + while ( true ) + { + // wait until the graph signals an event OR // the thread must die DWORD rc = WaitForMultipleObjects(static_cast<DWORD>(numHandles), waitHandles, false, INFINITE); - delete [] waitHandles; // get index of object that signaled unsigned int index = rc - WAIT_OBJECT_0; - // get index of graph that MAY have had an event - unsigned int handleIndex = index - graphEventIndex_0; - if ( rc == WAIT_FAILED ) { log_warn("graph monitor wait failed. (0x%x)\n", GetLastError()); } - else if ( index == listEventIndex ) - { - // process addition or removal of a graph - pGraphMon->processListEvent(); - if ( !ResetEvent(pGraphMon->listEvent_) ) - { - log_error("failed to reset graph monitor eventFlag." - "Terminating.\n"); - - // terminate - break; - } - } else if ( index == terminateIndex ) { // terminate break; } - // check if it was a filter graph handle that signaled - else if ( 0 <= handleIndex && - handleIndex < pGraphMon->graphContextList_.size() ) + // check if it was the filter graph handle that signaled + else if ( index == graphEventIndex ) { - // handle event of appropriate graph - pGraphMon->processGraphEvent( - pGraphMon->graphContextList_[handleIndex]->pME); + // have parent handle the graph event + pGraphMon->processGraphEvent_(pGraphMon->parentContext_); } else { @@ -347,325 +169,7 @@ } } + delete [] waitHandles; + return 0; } - -// Direct Show filter graph has signaled an event -// Device may have been removed -// Error may have occurred -void -GraphMonitor::processGraphEvent(IMediaEventEx *pME) -{ - HRESULT hr; - long evCode, param1, param2; - hr = pME->GetEvent(&evCode, ¶m1, ¶m2, 0); - - if ( SUCCEEDED(hr) ) - { - // Event codes taken from: - // http://msdn2.microsoft.com/en-us/library/ms783649.aspx - // Embedded reference not used: - // http://msdn2.microsoft.com/en-us/library/aa921722.aspx - - std::string str; - - switch(evCode) - { - case EC_DEVICE_LOST: - if ( (int)param2 == 0 ) - { - str.assign("EC_DEVICE_LOST\n"); - log_info("device removal detected\n"); - - // shutdown capture - if ( !cancelCBFunc_(pME, parentContext_) ) - log_warn("failed to find graph for final callback\n"); - } - else - { - str.assign("EC_DEVICE_LOST - (device re-inserted)\n"); - } - break; - - case EC_ACTIVATE: - str.assign("EC_ACTIVATE\n"); - break; - -/* case EC_BANDWIDTHCHANGE: - str.assign("EC_BANDWIDTHCHANGE\n"); - break; -*/ - case EC_BUFFERING_DATA: - str.assign("EC_BUFFERING_DATA\n"); - break; - - case EC_BUILT: - str.assign("EC_BUILT\n"); - break; - - case EC_CLOCK_CHANGED: - str.assign("EC_CLOCK_CHANGED\n"); - break; - - case EC_CLOCK_UNSET: - str.assign("EC_CLOCK_UNSET\n"); - break; - - case EC_CODECAPI_EVENT: - str.assign("EC_CODECAPI_EVENT\n"); - break; - - case EC_COMPLETE: - str.assign("EC_COMPLETE\n"); - break; - -/* case EC_CONTENTPROPERTY_CHANGED: - str.assign("EC_CONTENTPROPERTY_CHANGED\n"); - break; -*/ - case EC_DISPLAY_CHANGED: - str.assign("EC_DISPLAY_CHANGED\n"); - break; - - case EC_END_OF_SEGMENT: - str.assign("EC_END_OF_SEGMENT\n"); - break; - -/* case EC_EOS_SOON: - str.assign("EC_EOS_SOON\n"); - break; -*/ - case EC_ERROR_STILLPLAYING: - str.assign("EC_ERROR_STILLPLAYING\n"); - break; - - case EC_ERRORABORT: - str.assign("EC_ERRORABORT\n"); - - log_info("graph monitor stopping capture...\n"); - - // shutdown capture - if ( !cancelCBFunc_(pME, parentContext_) ) - log_warn("failed to find graph for the final callback\n"); - - break; - -/* case EC_ERRORABORTEX: - str.assign("EC_ERRORABORTEX\n"); - break; -*/ - case EC_EXTDEVICE_MODE_CHANGE: - str.assign("EC_EXTDEVICE_MODE_CHANGE\n"); - break; - -/* case EC_FILE_CLOSED: - str.assign("EC_FILE_CLOSED\n"); - break; -*/ - case EC_FULLSCREEN_LOST: - str.assign("EC_FULLSCREEN_LOST\n"); - break; - - case EC_GRAPH_CHANGED: - str.assign("EC_GRAPH_CHANGED\n"); - break; - - case EC_LENGTH_CHANGED: - str.assign("EC_LENGTH_CHANGED\n"); - break; - -/* case EC_LOADSTATUS: - str.assign("EC_LOADSTATUS\n"); - break; -*/ -/* case EC_MARKER_HIT: - str.assign("EC_MARKER_HIT\n"); - break; -*/ - case EC_NEED_RESTART: - str.assign("EC_NEED_RESTART\n"); - break; - -/* case EC_NEW_PIN: - str.assign("EC_NEW_PIN\n"); - break; -*/ - case EC_NOTIFY_WINDOW: - str.assign("EC_NOTIFY_WINDOW\n"); - break; - - case EC_OLE_EVENT: - str.assign("EC_OLE_EVENT\n"); - break; - - case EC_OPENING_FILE: - str.assign("EC_OPENING_FILE\n"); - break; - - case EC_PALETTE_CHANGED: - str.assign("EC_PALETTE_CHANGED\n"); - break; - - case EC_PAUSED: - str.assign("EC_PAUSED\n"); - break; - -/* case EC_PLEASE_REOPEN: - str.assign("EC_PLEASE_REOPEN\n"); - break; -*/ - case EC_PREPROCESS_COMPLETE: - str.assign("EC_PREPROCESS_COMPLETE\n"); - break; - -/* case EC_PROCESSING_LATENCY: - str.assign("EC_PROCESSING_LATENCY\n"); - break; -*/ - case EC_QUALITY_CHANGE: - str.assign("EC_QUALITY_CHANGE\n"); - break; - -/* case EC_RENDER_FINISHED: - str.assign("EC_RENDER_FINISHED\n"); - break; -*/ - case EC_REPAINT: - str.assign("EC_REPAINT\n"); - break; - -/* case EC_SAMPLE_LATENCY: - str.assign("EC_SAMPLE_LATENCY\n"); - break; - - case EC_SAMPLE_NEEDED: - str.assign("EC_SAMPLE_NEEDED\n"); - break; - - case EC_SCRUB_TIME: - str.assign("EC_SCRUB_TIME\n"); - break; -*/ - case EC_SEGMENT_STARTED: - str.assign("EC_SEGMENT_STARTED\n"); - break; - - case EC_SHUTTING_DOWN: - str.assign("EC_SHUTTING_DOWN\n"); - break; - - case EC_SNDDEV_IN_ERROR: - str.assign("EC_SNDDEV_IN_ERROR\n"); - break; - - case EC_SNDDEV_OUT_ERROR: - str.assign("EC_SNDDEV_OUT_ERROR\n"); - break; - - case EC_STARVATION: - str.assign("EC_STARVATION\n"); - break; - - case EC_STATE_CHANGE: - str.assign("EC_STATE_CHANGE\n"); - break; - -/* case EC_STATUS: - str.assign("EC_STATUS\n"); - break; -*/ - case EC_STEP_COMPLETE: - str.assign("EC_STEP_COMPLETE\n"); - break; - - case EC_STREAM_CONTROL_STARTED: - str.assign("EC_STREAM_CONTROL_STARTED\n"); - break; - - case EC_STREAM_CONTROL_STOPPED: - str.assign("EC_STREAM_CONTROL_STOPPED\n"); - break; - - case EC_STREAM_ERROR_STILLPLAYING: - str.assign("EC_STREAM_ERROR_STILLPLAYING\n"); - break; - - case EC_STREAM_ERROR_STOPPED: - str.assign("EC_STREAM_ERROR_STOPPED\n"); - break; - - case EC_TIMECODE_AVAILABLE: - str.assign("EC_TIMECODE_AVAILABLE\n"); - break; - - case EC_UNBUILT: - str.assign("EC_UNBUILT\n"); - break; - - case EC_USERABORT: - str.assign("EC_USERABORT\n"); - break; - - case EC_VIDEO_SIZE_CHANGED: - str.assign("EC_VIDEO_SIZE_CHANGED\n"); - break; - -/* case EC_VIDEOFRAMEREADY: - str.assign("EC_VIDEOFRAMEREADY\n"); - break; -*/ - case EC_VMR_RECONNECTION_FAILED: - str.assign("EC_VMR_RECONNECTION_FAILED\n"); - break; - - case EC_VMR_RENDERDEVICE_SET: - str.assign("EC_VMR_RENDERDEVICE_SET\n"); - break; - - case EC_VMR_SURFACE_FLIPPED: - str.assign("EC_VMR_SURFACE_FLIPPED\n"); - break; - - case EC_WINDOW_DESTROYED: - str.assign("EC_WINDOW_DESTROYED\n"); - break; - - case EC_WMT_EVENT: - str.assign("EC_WMT_EVENT\n"); - break; - - case EC_WMT_INDEX_EVENT: - str.assign("EC_WMT_INDEX_EVENT\n"); - break; - - default: - str.assign("unknown graph event code (%ld)\n", evCode); - break; - } - - log_info("graph #%d processed event: %s", - findContext(pME), str.c_str()); - - hr = pME->FreeEventParams(evCode, param1, param2); - } - else - { - log_error("failed getting event for a graph\n"); - } -} - -int -GraphMonitor::findContext(IMediaEventEx *pME) -{ - for ( unsigned int i = 0; i < graphContextList_.size(); i++ ) - { - // found matching MediaEvent interface? - if ( graphContextList_[i]->pME == pME ) - { - return i; - } - } - - // failed to find MediaEvent interface - return -1; -} Modified: trunk/src/directshow/GraphMonitor.h =================================================================== --- trunk/src/directshow/GraphMonitor.h 2007-09-28 21:20:58 UTC (rev 35) +++ trunk/src/directshow/GraphMonitor.h 2007-10-01 16:58:11 UTC (rev 36) @@ -26,53 +26,27 @@ #define _GRAPHMONITOR_H_ #include <windows.h> -#include <DShow.h> -#include <vector> -#include "LocklessQueue.h" class GraphMonitor { public: - typedef bool (*cancelCallbackFunc)(IMediaEventEx *, void *); + typedef void (*graphEventCBFunc)(void *); - GraphMonitor(cancelCallbackFunc, void *); + GraphMonitor(HANDLE *, graphEventCBFunc, void *); ~GraphMonitor(); - void addGraph(IMediaEventEx *); - void removeGraph(IMediaEventEx *); private: - static DWORD WINAPI monitorGraphs(LPVOID lpParam); - void processListEvent(); - void processGraphEvent(IMediaEventEx *); - int findContext(IMediaEventEx *); + static DWORD WINAPI monitorGraph(LPVOID lpParam); private: + HANDLE *graphHandle_; void * parentContext_; - cancelCallbackFunc cancelCBFunc_; + graphEventCBFunc processGraphEvent_; + HANDLE initDoneEvent_; - HANDLE listEvent_; HANDLE terminateEvent_; - struct graphContext - { - IMediaEventEx * pME; - HANDLE * waitHandle; - }; - - // used to generate array of handles on which to wait - std::vector<graphContext *> graphContextList_; - - struct graphListEvent - { - enum graphListEventType { add = 0, remove } eventType; - IMediaEventEx * graph; - }; - - // enqueued by main thread - // dequeued by graph monitor thread - LocklessQueue<graphListEvent> graphListEventQueue_; - void * graphMonitorThread_; DWORD graphMonitorThreadID_; }; Deleted: trunk/src/directshow/LocklessQueue.h =================================================================== --- trunk/src/directshow/LocklessQueue.h 2007-09-28 21:20:58 UTC (rev 35) +++ trunk/src/directshow/LocklessQueue.h 2007-10-01 16:58:11 UTC (rev 36) @@ -1,89 +0,0 @@ -// -// libvidcap - a cross-platform video capture library -// -// Copyright 2007 Wimba, Inc. -// -// Contributors: -// Peter Grayson <jpg...@gm...> -// Bill Cholewka <bc...@gm...> -// -// libvidcap is free software; you can redistribute it and/or modify -// it under the terms of the GNU Lesser General Public License as -// published by the Free Software Foundation; either version 2.1 of -// the License, or (at your option) any later version. -// -// libvidcap is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public -// License along with this program. If not, see -// <http://www.gnu.org/licenses/>. -// - -#ifndef __LOCKLESSQUEUE_H__ -#define __LOCKLESSQUEUE_H__ - -template<typename T> -class LocklessQueue -{ -public: - LocklessQueue(int size = 512) - : max_(size), - head_(0), - tail_(0) - { - pData_ = new const T * [max_]; - }; - - ~LocklessQueue() - { - delete[] pData_; - }; - - bool enqueue(const T *buffer) - { - // take note of future head value - unsigned int nextHead = (head_ + 1) % max_; - - // safe to push? - if ( nextHead == tail_ ) - return false; - - // push the data - pData_[head_] = buffer; - - // NOW advance the head - head_ = nextHead; - - return true; - }; - - bool dequeue(const T **pBuffer) - { - if ( head_ == tail_ ) - return false; - - // take note of future tail value - unsigned int next = (tail_ + 1) % max_; - - // get data - *pBuffer = pData_[tail_]; - - // NOW advance the tail - tail_ = next; - - return true; - }; - -private: - const int max_; - - volatile unsigned int head_; - volatile unsigned int tail_; - - const T ** pData_; -}; - -#endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. m. <lib...@li...> - 2007-09-28 21:21:03
|
Revision: 35 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=35&view=rev Author: bcholew Date: 2007-09-28 14:20:58 -0700 (Fri, 28 Sep 2007) Log Message: ----------- Make capture stop synchronous. Move callback cancellation to source thread. Enforce state to prevent loss of rapid start/stop command events. Synchronize main, capture and source threads to prevent callbacks after capture stop. Give terminate command highest priority in source thread processing - followed by callback cancellation. Reduce chance of blocking indefinitely when attempting to start capture while source is being removed. No longer necessary to reset capture graph foo following a bind. If reset of capture graph foo fails, repeat graph stop attempt immediately. Modified Paths: -------------- trunk/src/directshow/DirectShowSource.cpp trunk/src/directshow/DirectShowSource.h Modified: trunk/src/directshow/DirectShowSource.cpp =================================================================== --- trunk/src/directshow/DirectShowSource.cpp 2007-09-28 17:44:03 UTC (rev 34) +++ trunk/src/directshow/DirectShowSource.cpp 2007-09-28 21:20:58 UTC (rev 35) @@ -56,8 +56,15 @@ eventStart_(0), eventStop_(0), eventTerminate_(0), + eventCancel_(0), sourceThread_(0), - sourceThreadID_(0) + sourceThreadID_(0), + okToSendStart_(true), + okToSendStop_(true), + allowCallbacks_(false), + callbackInProgress_(false), + callbackCancellationInProgress_(false), + captureStopped_(true) { if ( !dshowMgr_ ) { @@ -401,6 +408,25 @@ return -1; } + // create an event used to signal thread to cancel capture + eventCancel_ = CreateEvent( + NULL, // default security attributes + TRUE, // manual-reset event + FALSE, // initial state is clear + NULL // no name + ); + + if ( eventCancel_ == NULL) + { + log_error("DirectShowSource: failed creating cancel event (%d)\n", + GetLastError()); + CloseHandle(eventInitDone_); + CloseHandle(eventStart_); + CloseHandle(eventStop_); + CloseHandle(eventTerminate_); + return -1; + } + return 0; } @@ -418,14 +444,13 @@ return -1; } - enum { startEventIndex = 0, stopEventIndex, + enum { cancelEventIndex = 0, startEventIndex, stopEventIndex, terminateEventIndex }; size_t numHandles = terminateEventIndex + 1; HANDLE * waitHandles = new HANDLE [numHandles]; - // ...plus something to break-out when a handle must be - // added or removed, or when thread must die + waitHandles[cancelEventIndex] = pSrc->eventCancel_; waitHandles[startEventIndex] = pSrc->eventStart_; waitHandles[stopEventIndex] = pSrc->eventStop_; waitHandles[terminateEventIndex] = pSrc->eventTerminate_; @@ -444,10 +469,29 @@ { log_warn("source wait failed. (0x%x)\n", GetLastError()); } + else if ( index == terminateEventIndex ) + { + // give terminate the highest priority + + pSrc->terminate(); + break; + } + else if ( index == cancelEventIndex ) + { + // give cancel a higher priority than start/stop + + if ( !ResetEvent(pSrc->eventCancel_) ) + { + log_error("failed to reset source start event flag." + "Terminating.\n"); + // terminate + break; + } + + pSrc->doCancelCallbacks(); + } else if ( index == startEventIndex ) { - pSrc->doStart(); - if ( !ResetEvent(pSrc->eventStart_) ) { log_error("failed to reset source start event flag." @@ -455,11 +499,13 @@ // terminate break; } + + pSrc->okToSendStop_ = true; + + pSrc->doStart(); } else if ( index == stopEventIndex ) { - pSrc->doStop(); - if ( !ResetEvent(pSrc->eventStop_) ) { log_error("failed to reset source stop event flag." @@ -467,12 +513,11 @@ // terminate break; } + + pSrc->okToSendStart_ = true; + + pSrc->doStop(); } - else if ( index == terminateEventIndex ) - { - pSrc->terminate(); - break; - } } delete [] waitHandles; @@ -491,11 +536,32 @@ if ( FAILED(hr) ) { log_error("failed to remove Sample Grabber (%d)\n", hr); + + //FIXME: is this still necessary? Does it still work? if ( hr == VFW_E_NOT_STOPPED ) { - log_error("Capture wasn't stopped. " - "Repeating STOP request...\n"); - stop(); + log_error("Capture wasn't stopped. Repeating STOP...\n"); + + HRESULT hr = pMediaControlIF_->Stop(); + if ( FAILED(hr) ) + { + log_error("failed in 2nd STOP attempt (0x%0x)\n", hr); + } + else + { + HRESULT hr = pFilterGraph_->RemoveFilter(pSampleGrabber_); + if ( FAILED(hr) ) + { + // this is silly + log_error("failed twice to remove sample grabber (%d)", + hr); + } + else + { + graphIsSetup_ = false; + return 0; + } + } } else { @@ -575,7 +641,12 @@ int DirectShowSource::start() { - // signal to source thread to start capturing + if ( !okToSendStart_ ) + return -1; + + okToSendStart_ = false; + + // signal source thread to start capturing if ( !SetEvent(eventStart_) ) { log_error("failed to signal source to start (%d)\n", @@ -591,36 +662,66 @@ { if ( !setupCapGraphFoo() ) { + allowCallbacks_ = true; + HRESULT hr = pMediaControlIF_->Run(); if ( SUCCEEDED(hr) ) return; - else - log_error("failed to run filter graph for source '%s' (%ul 0x%x)\n", - sourceContext_->src_info.description, hr, hr); + + log_error("failed to run filter graph for source '%s' (%ul 0x%x)\n", + sourceContext_->src_info.description, hr, hr); } + else + okToSendStart_ = true; - // call capture callback - with error status - // (vidcap will reset capture_callback) + allowCallbacks_ = false; + + // final capture callback - with error status sapi_src_capture_notify(sourceContext_, 0, 0, -1); } +// NOTE: This function will block until capture is +// completely stopped. +// Even when returning failure, it guarantees +// no more callbacks will occur int DirectShowSource::stop() { - // signal to source thread to stop capturing + while ( !okToSendStop_ ) + Sleep(10); + + okToSendStop_ = false; + + captureStopped_ = false; + + // signal source thread to stop capturing if ( !SetEvent(eventStop_) ) { log_error("failed to signal source to stop (%d)\n", GetLastError()); + + // Need to ensure no more callbacks arrive + // Do this the hard way + allowCallbacks_ = false; + while ( callbackInProgress_ || callbackCancellationInProgress_ ) + Sleep(10); + return -1; } + // wait for source thread to indicate that capture has stopped + // guaranteeing no more callbacks will occur after this returns + while ( !captureStopped_ ) + Sleep(10); + return 0; } void DirectShowSource::doStop() { + allowCallbacks_ = false; + if ( graphIsSetup_ ) { HRESULT hr = pMediaControlIF_->Stop(); @@ -628,7 +729,24 @@ { log_error("failed to STOP the filter graph (0x%0x)\n", hr); } + + // If source was removed while not capturing (following a stop), + // graph's Run() could block forever. The RenderStream(), however, + // would fail. Therefore, call resetCapGraphFoo() whenever + // stopping, to force RenderStream() to validate setup before + // any start (and reduce likelihood of Run() blocking forever). + // + // And if source is effectively removed after + // RenderStream(), but before graph's Run()? + resetCapGraphFoo(); } + + // make sure we're not in a callback + while ( callbackInProgress_ ) + Sleep(10); + + // signal back to main thread that capture has stopped + captureStopped_ = true; } int @@ -669,7 +787,7 @@ vih->bmiHeader.biWidth = fmtNative.width; vih->bmiHeader.biHeight = fmtNative.height; - return resetCapGraphFoo(); + return 0; } bool @@ -960,18 +1078,53 @@ void DirectShowSource::cancelCallbacks() { - // have buffer callbacks already been cancelled? - if ( !sourceContext_->capture_callback ) + // signal source thread to cancel capturing + if ( !SetEvent(eventCancel_) ) + { + log_error("failed to signal source to cancel (%d)\n", + GetLastError()); + + // Need to ensure app is notified + // Do it the hard way + + // prevent future callbacks + allowCallbacks_ = false; + + // wait for current callback to finish + while ( callbackInProgress_ ) + Sleep(10); + + // final capture callback - with error status + sapi_src_capture_notify(sourceContext_, 0, 0, -1); + } +} + +void +DirectShowSource::doCancelCallbacks() +{ + callbackCancellationInProgress_ = true; + + // has capture been stopped already? + if ( !allowCallbacks_ ) + { + callbackCancellationInProgress_ = false; return; + } - // stop callbacks before thinking of - // touching sourceContext_->capture_callback - stop(); + // prevent future callbacks + allowCallbacks_ = false; - // call capture callback - but let vidcap and the - // app know that this is the last time - // (vidcap will reset capture_callback) + // block until current callback is not in progress + while ( callbackInProgress_ ) + Sleep(10); + + // stop callbacks before sending final callback + doStop(); + + // final capture callback - with error status sapi_src_capture_notify(sourceContext_, 0, 0, -1); + + callbackCancellationInProgress_ = false; } STDMETHODIMP @@ -989,16 +1142,27 @@ return E_NOINTERFACE; } -// The sample grabber calls us back from its deliver thread +// The sample grabber calls this from its deliver thread +// NOTE: This function must not block, else it will cause a +// graph's Stop() to block - which could result in a deadlock STDMETHODIMP DirectShowSource::BufferCB( double dblSampleTime, BYTE * pBuff, long buffSize ) { - if ( !sourceContext_->capture_callback ) + callbackInProgress_ = true; + + if ( !allowCallbacks_ ) + { + callbackInProgress_ = false; return 0; + } - return sapi_src_capture_notify(sourceContext_, + int ret = sapi_src_capture_notify(sourceContext_, reinterpret_cast<const char *>(pBuff), static_cast<int>(buffSize), 0); + + callbackInProgress_ = false; + + return ret; } int Modified: trunk/src/directshow/DirectShowSource.h =================================================================== --- trunk/src/directshow/DirectShowSource.h 2007-09-28 17:44:03 UTC (rev 34) +++ trunk/src/directshow/DirectShowSource.h 2007-09-28 21:20:58 UTC (rev 35) @@ -41,12 +41,11 @@ int start(); int stop(); + void cancelCallbacks(); int bindFormat(const vidcap_fmt_info * fmtInfo); int validateFormat(const vidcap_fmt_info * fmtNominal, vidcap_fmt_info * fmtNative) const; - void cancelCallbacks(); - const char * getID() const { return sourceContext_->src_info.identifier; @@ -57,6 +56,7 @@ void terminate(); void doStart(); void doStop(); + void doCancelCallbacks(); int createEvents(); int createCapGraphFoo(); @@ -110,8 +110,16 @@ HANDLE eventStart_; HANDLE eventStop_; HANDLE eventTerminate_; + HANDLE eventCancel_; void * sourceThread_; DWORD sourceThreadID_; + + bool okToSendStart_; + bool okToSendStop_; + bool allowCallbacks_; + bool callbackInProgress_; + bool callbackCancellationInProgress_; + bool captureStopped_; }; #endif This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. m. <lib...@li...> - 2007-09-28 17:44:09
|
Revision: 34 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=34&view=rev Author: bcholew Date: 2007-09-28 10:44:03 -0700 (Fri, 28 Sep 2007) Log Message: ----------- Have window render frames in the callback thread - so they won't back-up due to a blocked main thread. Modified Paths: -------------- trunk/examples/vidcapTester/GrabberManager.cpp Modified: trunk/examples/vidcapTester/GrabberManager.cpp =================================================================== --- trunk/examples/vidcapTester/GrabberManager.cpp 2007-09-26 15:55:16 UTC (rev 33) +++ trunk/examples/vidcapTester/GrabberManager.cpp 2007-09-28 17:44:03 UTC (rev 34) @@ -1,345 +1,346 @@ -#include <stdexcept> - -#include <QApplication> -#include <QDebug> -#include <QIcon> -#include <QMutexLocker> - -#include "GrabberManager.h" - -GrabberManager::GrabberManager(QObject * parent, const QString & title, - int width, int height, int framerate) - : QObject(parent), - title_(title), - width_(width), - height_(height), - framerate_(framerate), - vc_(vidcap_initialize()), - sapi_(0), - ctxList_(0), - srcList_(0), - srcListLen_(0) -{ - qDebug() << "Starting grabber for each capture device..."; - - if ( !vc_ ) - throw std::runtime_error("failed vidcap_initialize()"); - - if ( !(sapi_ = vidcap_sapi_acquire(vc_, 0)) ) - throw std::runtime_error("failed to acquire default sapi"); - - if ( vidcap_sapi_info_get(sapi_, &sapiInfo_) ) - throw std::runtime_error("failed to get default sapi info"); - - qDebug() << "sapi:" << sapiInfo_.identifier - << "|" << sapiInfo_.description; - - if ( vidcap_srcs_notify(sapi_, &GrabberManager::userNotificationCallback, this) ) - throw std::runtime_error("failed vidcap_srcs_notify()"); - - srcListLen_ = vidcap_src_list_update(sapi_); - - if ( srcListLen_ < 0 ) - throw std::runtime_error("failed vidcap_src_list_update()"); - - srcList_ = new vidcap_src_info[srcListLen_]; - - if ( vidcap_src_list_get(sapi_, srcListLen_, srcList_) ) - throw std::runtime_error("failed vidcap_srcList_get()"); - - ctxList_ = new mySourceContext[srcListLen_]; - - // Rescan on notification - // NOTE: connecting before mgr construction is complete - connect(this, SIGNAL(deviceNotification()), - this, SLOT(rescanDevices())); - - // create a grabber for each video capture device - for ( int i = 0; i < srcListLen_; ++i ) - { - qDebug() << "src:" << srcList_[i].identifier - << "|" << srcList_[i].description; - - createContext(&ctxList_[i], &srcList_[i]); - } -} - -GrabberManager::~GrabberManager() -{ - qDebug() << "Destroying all grabbers..."; - - { - QMutexLocker locker(&sourceMutex_); - - for ( int i = srcListLen_ - 1; i >= 0; --i ) - { - if ( ctxList_[i].grabber ) - delete ctxList_[i].grabber; - - if ( ctxList_[i].window ) - delete ctxList_[i].window; - } - - delete [] ctxList_; - delete [] srcList_; - } - - if ( vidcap_sapi_release(sapi_) ) - qWarning() << "failed vidcap_sapi_release()"; - - vidcap_destroy(vc_); -} - -void -GrabberManager::killGrabber(Grabber *grabber) -{ - // protect context list and srcListLen_ from concurrent access - // (from notification callback) - QMutexLocker locker(&sourceMutex_); - - for ( int i = 0; i < srcListLen_; ++i ) - { - if ( ctxList_[i].grabber == grabber ) - { - if ( ctxList_[i].grabber ) - delete ctxList_[i].grabber; - ctxList_[i].grabber = 0; - - if ( ctxList_[i].window ) - delete ctxList_[i].window; - ctxList_[i].window = 0; - break; - } - } -} - -void -GrabberManager::shutdown() -{ - qDebug() << "grabber manager got signal to shutdown"; - - // cause message loop to exit - QApplication::quit(); -} - -int -GrabberManager::userNotificationCallback(vidcap_sapi *, void * user_context) -{ - GrabberManager *grabMgr = (GrabberManager *)user_context; - - // trigger main thread to handle this - rescan the devices - emit grabMgr->deviceNotification(); - - return 0; -} - -void -GrabberManager::rescanDevices() -{ - vidcap_src_info * newSrcList; - int newSrcListLen; - - // query for device list - try - { - getFreshSrcList(newSrcList, newSrcListLen); - } - catch (std::runtime_error &e) - { - qCritical() << "exception while rescanning devices:" << e.what(); - return; - } - - bool removal = false; - bool addition = false; - // compare each existing device to new list - // If it's not there, clean it up - for ( int oldIdx = 0; oldIdx < srcListLen_; ++oldIdx ) - { - bool found = false; - for ( int newIdx = 0; newIdx < newSrcListLen; ++newIdx ) - { - if ( !strcmp(srcList_[oldIdx].identifier, - newSrcList[newIdx].identifier) ) - { - found = true; - break; - } - } - - if ( !found ) - { - removal = true; - qDebug() << "source removed:" - << srcList_[oldIdx].description; - - // NOTE: Source might not be capturing when - // removed, so don't rely on capture callback - // to clean up after a device removal. - // - // cleanup after this device removal - killGrabber(ctxList_[oldIdx].grabber); - } - } - - mySourceContext * newCtxList = new mySourceContext[newSrcListLen]; - - // Compare each device in new list to old list - // If it's new, add it to the new context list - for ( int newIdx = 0; newIdx < newSrcListLen; ++newIdx ) - { - bool found = false; - for ( int oldIdx = 0; oldIdx < srcListLen_; ++oldIdx ) - { - if ( !strcmp(srcList_[oldIdx].identifier, - newSrcList[newIdx].identifier) ) - { - // Add unchanged device to new context list - // Take from existing context list to new - newCtxList[newIdx].grabber = ctxList_[oldIdx].grabber; - newCtxList[newIdx].window = ctxList_[oldIdx].window; - - found = true; - break; - } - } - - if ( !found ) - { - addition = true; - qDebug() << "source added:" - << newSrcList[newIdx].description; - - // create grabber and window (& record in ctxList) - createContext(&newCtxList[newIdx], &newSrcList[newIdx]); - } - } - - // Don't grab mutex if not necessary - if ( !removal && !addition ) - { - delete [] newSrcList; - delete [] newCtxList; - return; - } - - qDebug() << "New list of sources: there were" << srcListLen_ - << "now there are" << newSrcListLen; - - QMutexLocker locker(&sourceMutex_); - - // replace old lists with new - delete [] srcList_; - delete [] ctxList_; - srcList_ = newSrcList; - ctxList_ = newCtxList; - srcListLen_ = newSrcListLen; -} - -// get a fresh list of devices -void -GrabberManager::getFreshSrcList(vidcap_src_info * &pNewSrcList, int & newSrcListLen) -{ - newSrcListLen = vidcap_src_list_update(sapi_); - - if ( newSrcListLen < 0 ) - throw std::runtime_error("failed vidcap_src_list_update()"); - else if ( newSrcListLen == 0 ) - qDebug() << "no sources available"; - - pNewSrcList = new vidcap_src_info[newSrcListLen]; - - if ( vidcap_src_list_get(sapi_, newSrcListLen, pNewSrcList) ) - throw std::runtime_error("failed vidcap_srcList_get()"); -} - -// used by constructor and notification callback -void -GrabberManager::createContext(mySourceContext *mySrcCtxt, - vidcap_src_info *srcList) -{ - QMutexLocker locker(&sourceMutex_); - - mySrcCtxt->grabber = 0; - mySrcCtxt->window = 0; - - try - { - mySrcCtxt->grabber = new Grabber(this, sapi_, srcList, - width_, height_, 0, framerate_); - } - catch (std::runtime_error &) - { - qWarning() << "Could not find a suitable format for device " - << srcList->description << "-" << srcList->identifier; - return; - } - - // Cleanup if capture stopped due to error or device removal - // NOTE: may be connecting before mgr construction is complete. - connect(mySrcCtxt->grabber, SIGNAL(captureAborted(Grabber *)), - this, SLOT(killGrabber(Grabber *))); - - try - { - mySrcCtxt->window = new MainWindow(QString("%1 - %2") - .arg(title_).arg(srcList->description), - width_, height_); - mySrcCtxt->window->show(); - } - catch (std::exception &) - { - qDebug() << "Could not create window for device '" - << srcList->description << "' (" - << srcList->identifier << ")"; - - delete mySrcCtxt->grabber; - mySrcCtxt->grabber = 0; - - return; - } - - // Start capture AFTER window is created. - // If capture fails, both grabber and window will be deleted. - try - { - mySrcCtxt->grabber->capture(); - } - catch ( std::runtime_error & e ) - { - qCritical() << "failed to start capture for grabber (" - << e.what() << ")"; - - delete mySrcCtxt->window; - mySrcCtxt->window = 0; - - delete mySrcCtxt->grabber; - mySrcCtxt->grabber = 0; - - return; - } - - mySrcCtxt->window->show(); - - // connect video to window - QObject::connect(mySrcCtxt->grabber, - SIGNAL(videoFrame(int, int, QByteArray)), - mySrcCtxt->window, - SLOT(displayVideo(int, int, QByteArray)), - Qt::AutoConnection); - - // Set the Application icon - QIcon app_icon(":/app_icon.png"); - - // Windows and Linux need to have the icon set for the - // main window so it will appear in the top left corner - // as well as in taskbar - // Mac OSX windows do not usually have an icon in the title - // bar, so we disable that -#ifdef MACOSX - mySrcCtxt->window->setWindowIcon(QPixmap()); -#else - mySrcCtxt->window->setWindowIcon(app_icon); -#endif -} - +#include <stdexcept> + +#include <QApplication> +#include <QDebug> +#include <QIcon> +#include <QMutexLocker> + +#include "GrabberManager.h" + +GrabberManager::GrabberManager(QObject * parent, const QString & title, + int width, int height, int framerate) + : QObject(parent), + title_(title), + width_(width), + height_(height), + framerate_(framerate), + vc_(vidcap_initialize()), + sapi_(0), + ctxList_(0), + srcList_(0), + srcListLen_(0) +{ + qDebug() << "Starting grabber for each capture device..."; + + if ( !vc_ ) + throw std::runtime_error("failed vidcap_initialize()"); + + if ( !(sapi_ = vidcap_sapi_acquire(vc_, 0)) ) + throw std::runtime_error("failed to acquire default sapi"); + + if ( vidcap_sapi_info_get(sapi_, &sapiInfo_) ) + throw std::runtime_error("failed to get default sapi info"); + + qDebug() << "sapi:" << sapiInfo_.identifier + << "|" << sapiInfo_.description; + + if ( vidcap_srcs_notify(sapi_, &GrabberManager::userNotificationCallback, this) ) + throw std::runtime_error("failed vidcap_srcs_notify()"); + + srcListLen_ = vidcap_src_list_update(sapi_); + + if ( srcListLen_ < 0 ) + throw std::runtime_error("failed vidcap_src_list_update()"); + + srcList_ = new vidcap_src_info[srcListLen_]; + + if ( vidcap_src_list_get(sapi_, srcListLen_, srcList_) ) + throw std::runtime_error("failed vidcap_srcList_get()"); + + ctxList_ = new mySourceContext[srcListLen_]; + + // Rescan on notification + // NOTE: connecting before mgr construction is complete + connect(this, SIGNAL(deviceNotification()), + this, SLOT(rescanDevices())); + + // create a grabber for each video capture device + for ( int i = 0; i < srcListLen_; ++i ) + { + qDebug() << "src:" << srcList_[i].identifier + << "|" << srcList_[i].description; + + createContext(&ctxList_[i], &srcList_[i]); + } +} + +GrabberManager::~GrabberManager() +{ + qDebug() << "Destroying all grabbers..."; + + { + QMutexLocker locker(&sourceMutex_); + + for ( int i = srcListLen_ - 1; i >= 0; --i ) + { + if ( ctxList_[i].grabber ) + delete ctxList_[i].grabber; + + if ( ctxList_[i].window ) + delete ctxList_[i].window; + } + + delete [] ctxList_; + delete [] srcList_; + } + + if ( vidcap_sapi_release(sapi_) ) + qWarning() << "failed vidcap_sapi_release()"; + + vidcap_destroy(vc_); +} + +void +GrabberManager::killGrabber(Grabber *grabber) +{ + // protect context list and srcListLen_ from concurrent access + // (from notification callback) + QMutexLocker locker(&sourceMutex_); + + for ( int i = 0; i < srcListLen_; ++i ) + { + if ( ctxList_[i].grabber == grabber ) + { + if ( ctxList_[i].grabber ) + delete ctxList_[i].grabber; + ctxList_[i].grabber = 0; + + if ( ctxList_[i].window ) + delete ctxList_[i].window; + ctxList_[i].window = 0; + break; + } + } +} + +void +GrabberManager::shutdown() +{ + qDebug() << "grabber manager got signal to shutdown"; + + // cause message loop to exit + QApplication::quit(); +} + +int +GrabberManager::userNotificationCallback(vidcap_sapi *, void * user_context) +{ + GrabberManager *grabMgr = (GrabberManager *)user_context; + + // trigger main thread to handle this - rescan the devices + emit grabMgr->deviceNotification(); + + return 0; +} + +void +GrabberManager::rescanDevices() +{ + vidcap_src_info * newSrcList; + int newSrcListLen; + + // query for device list + try + { + getFreshSrcList(newSrcList, newSrcListLen); + } + catch (std::runtime_error &e) + { + qCritical() << "exception while rescanning devices:" << e.what(); + return; + } + + bool removal = false; + bool addition = false; + // compare each existing device to new list + // If it's not there, clean it up + for ( int oldIdx = 0; oldIdx < srcListLen_; ++oldIdx ) + { + bool found = false; + for ( int newIdx = 0; newIdx < newSrcListLen; ++newIdx ) + { + if ( !strcmp(srcList_[oldIdx].identifier, + newSrcList[newIdx].identifier) ) + { + found = true; + break; + } + } + + if ( !found ) + { + removal = true; + qDebug() << "source removed:" + << srcList_[oldIdx].description; + + // NOTE: Source might not be capturing when + // removed, so don't rely on capture callback + // to clean up after a device removal. + // + // cleanup after this device removal + killGrabber(ctxList_[oldIdx].grabber); + } + } + + mySourceContext * newCtxList = new mySourceContext[newSrcListLen]; + + // Compare each device in new list to old list + // If it's new, add it to the new context list + for ( int newIdx = 0; newIdx < newSrcListLen; ++newIdx ) + { + bool found = false; + for ( int oldIdx = 0; oldIdx < srcListLen_; ++oldIdx ) + { + if ( !strcmp(srcList_[oldIdx].identifier, + newSrcList[newIdx].identifier) ) + { + // Add unchanged device to new context list + // Take from existing context list to new + newCtxList[newIdx].grabber = ctxList_[oldIdx].grabber; + newCtxList[newIdx].window = ctxList_[oldIdx].window; + + found = true; + break; + } + } + + if ( !found ) + { + addition = true; + qDebug() << "source added:" + << newSrcList[newIdx].description; + + // create grabber and window (& record in ctxList) + createContext(&newCtxList[newIdx], &newSrcList[newIdx]); + } + } + + // Don't grab mutex if not necessary + if ( !removal && !addition ) + { + delete [] newSrcList; + delete [] newCtxList; + return; + } + + qDebug() << "New list of sources: there were" << srcListLen_ + << "now there are" << newSrcListLen; + + QMutexLocker locker(&sourceMutex_); + + // replace old lists with new + delete [] srcList_; + delete [] ctxList_; + srcList_ = newSrcList; + ctxList_ = newCtxList; + srcListLen_ = newSrcListLen; +} + +// get a fresh list of devices +void +GrabberManager::getFreshSrcList(vidcap_src_info * &pNewSrcList, int & newSrcListLen) +{ + newSrcListLen = vidcap_src_list_update(sapi_); + + if ( newSrcListLen < 0 ) + throw std::runtime_error("failed vidcap_src_list_update()"); + else if ( newSrcListLen == 0 ) + qDebug() << "no sources available"; + + pNewSrcList = new vidcap_src_info[newSrcListLen]; + + if ( vidcap_src_list_get(sapi_, newSrcListLen, pNewSrcList) ) + throw std::runtime_error("failed vidcap_srcList_get()"); +} + +// used by constructor and notification callback +void +GrabberManager::createContext(mySourceContext *mySrcCtxt, + vidcap_src_info *srcList) +{ + QMutexLocker locker(&sourceMutex_); + + mySrcCtxt->grabber = 0; + mySrcCtxt->window = 0; + + try + { + mySrcCtxt->grabber = new Grabber(this, sapi_, srcList, + width_, height_, 0, framerate_); + } + catch (std::runtime_error &) + { + qWarning() << "Could not find a suitable format for device " + << srcList->description << "-" << srcList->identifier; + return; + } + + // Cleanup if capture stopped due to error or device removal + // NOTE: may be connecting before mgr construction is complete. + connect(mySrcCtxt->grabber, SIGNAL(captureAborted(Grabber *)), + this, SLOT(killGrabber(Grabber *))); + + try + { + mySrcCtxt->window = new MainWindow(QString("%1 - %2") + .arg(title_).arg(srcList->description), + width_, height_); + mySrcCtxt->window->show(); + } + catch (std::exception &) + { + qDebug() << "Could not create window for device '" + << srcList->description << "' (" + << srcList->identifier << ")"; + + delete mySrcCtxt->grabber; + mySrcCtxt->grabber = 0; + + return; + } + + // Start capture AFTER window is created. + // If capture fails, both grabber and window will be deleted. + try + { + mySrcCtxt->grabber->capture(); + } + catch ( std::runtime_error & e ) + { + qCritical() << "failed to start capture for grabber (" + << e.what() << ")"; + + delete mySrcCtxt->window; + mySrcCtxt->window = 0; + + delete mySrcCtxt->grabber; + mySrcCtxt->grabber = 0; + + return; + } + + mySrcCtxt->window->show(); + + // connect video directly to window, so that a blocked + // main thread won't result in a pile-up of frames + QObject::connect(mySrcCtxt->grabber, + SIGNAL(videoFrame(int, int, QByteArray)), + mySrcCtxt->window, + SLOT(displayVideo(int, int, QByteArray)), + Qt::DirectConnection); + + // Set the Application icon + QIcon app_icon(":/app_icon.png"); + + // Windows and Linux need to have the icon set for the + // main window so it will appear in the top left corner + // as well as in taskbar + // Mac OSX windows do not usually have an icon in the title + // bar, so we disable that +#ifdef MACOSX + mySrcCtxt->window->setWindowIcon(QPixmap()); +#else + mySrcCtxt->window->setWindowIcon(app_icon); +#endif +} + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. m. <lib...@li...> - 2007-09-26 15:55:31
|
Revision: 33 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=33&view=rev Author: bcholew Date: 2007-09-26 08:55:16 -0700 (Wed, 26 Sep 2007) Log Message: ----------- Add function to convert rgb32 to yuy2. Modified Paths: -------------- trunk/src/conv.c trunk/src/conv_to_yuy2.c Modified: trunk/src/conv.c =================================================================== --- trunk/src/conv.c 2007-09-26 13:54:23 UTC (rev 32) +++ trunk/src/conv.c 2007-09-26 15:55:16 UTC (rev 33) @@ -52,7 +52,7 @@ { VIDCAP_FOURCC_I420, VIDCAP_FOURCC_YUY2, vidcap_i420_to_yuy2, "i420->yuy2" }, { VIDCAP_FOURCC_RGB32, VIDCAP_FOURCC_YUY2, vidcap_rgb32_to_yuy2, - "rgb32->yuy2 (not implemented!)" }, + "rgb32->yuy2" }, { VIDCAP_FOURCC_2VUY, VIDCAP_FOURCC_YUY2, conv_2vuy_to_yuy2, "2vuy->yuy2" }, Modified: trunk/src/conv_to_yuy2.c =================================================================== --- trunk/src/conv_to_yuy2.c 2007-09-26 13:54:23 UTC (rev 32) +++ trunk/src/conv_to_yuy2.c 2007-09-26 15:55:16 UTC (rev 33) @@ -28,11 +28,62 @@ /* NOTE: size of dest buffer must be >= width * height * 2 */ +/* Based on formulas found at http://en.wikipedia.org/wiki/YUV */ int vidcap_rgb32_to_yuy2(int width, int height, const char * src, char * dest) { - log_error("vidcap_rgb32_to_yuy2() not implemented\n"); - return -1; + unsigned char * dst_even, * dst_odd; + const unsigned char * src_even, * src_odd; + int i, j; + + src_even = (const unsigned char *)src; + src_odd = src_even + width * 4; + dst_even = (unsigned char *)dest; + dst_odd = dest + width * 2; + + for ( i = 0; i < height / 2; ++i ) + { + for ( j = 0; j < width / 2; ++j ) + { + /* NOTE: u and v are taken from different src samples */ + + short r, g, b; + b = *src_even++; + g = *src_even++; + r = *src_even++; + ++src_even; + *dst_even++ = (( r * 66 + g * 129 + b * 25 + 128 ) >> 8 ) + 16; + *dst_even++ = (( r * -38 - g * 74 + b * 112 + 128 ) >> 8 ) + 128; + + b = *src_even++; + g = *src_even++; + r = *src_even++; + ++src_even; + *dst_even++ = (( r * 66 + g * 129 + b * 25 + 128 ) >> 8 ) + 16; + *dst_even++ = (( r * 112 - g * 94 - b * 18 + 128 ) >> 8 ) + 128; + + b = *src_odd++; + g = *src_odd++; + r = *src_odd++; + ++src_odd; + *dst_odd++ = (( r * 66 + g * 129 + b * 25 + 128 ) >> 8 ) + 16; + *dst_odd++ = (( r * -38 - g * 74 + b * 112 + 128 ) >> 8 ) + 128; + + b = *src_odd++; + g = *src_odd++; + r = *src_odd++; + ++src_odd; + *dst_odd++ = (( r * 66 + g * 129 + b * 25 + 128 ) >> 8 ) + 16; + *dst_odd++ = (( r * 112 - g * 94 - b * 18 + 128 ) >> 8 ) + 128; + } + + dst_even += width * 2; + dst_odd += width * 2; + src_even += width * 4; + src_odd += width * 4; + } + + return 0; } int This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. m. <lib...@li...> - 2007-09-26 13:55:16
|
Revision: 32 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=32&view=rev Author: bcholew Date: 2007-09-26 06:54:23 -0700 (Wed, 26 Sep 2007) Log Message: ----------- Give each conversion function a descriptive name. Add function to retrieve name. Log the conversion name at bind time. Modified Paths: -------------- trunk/src/conv.c trunk/src/conv.h trunk/src/vidcap.c Modified: trunk/src/conv.c =================================================================== --- trunk/src/conv.c 2007-09-26 13:50:10 UTC (rev 31) +++ trunk/src/conv.c 2007-09-26 13:54:23 UTC (rev 32) @@ -36,23 +36,35 @@ int src_fourcc; int dst_fourcc; conv_func func; + const char *name; }; static const struct conv_info conv_list[] = { - { VIDCAP_FOURCC_I420, VIDCAP_FOURCC_RGB32, vidcap_i420_to_rgb32 }, - { VIDCAP_FOURCC_YUY2, VIDCAP_FOURCC_RGB32, vidcap_yuy2_to_rgb32 }, - { VIDCAP_FOURCC_RGB32, VIDCAP_FOURCC_I420, vidcap_rgb32_to_i420 }, - { VIDCAP_FOURCC_YUY2, VIDCAP_FOURCC_I420, vidcap_yuy2_to_i420 }, - { VIDCAP_FOURCC_I420, VIDCAP_FOURCC_YUY2, vidcap_i420_to_yuy2 }, - { VIDCAP_FOURCC_RGB32, VIDCAP_FOURCC_YUY2, vidcap_rgb32_to_yuy2 }, + { VIDCAP_FOURCC_I420, VIDCAP_FOURCC_RGB32, vidcap_i420_to_rgb32, + "i420->rgb32" }, + { VIDCAP_FOURCC_YUY2, VIDCAP_FOURCC_RGB32, vidcap_yuy2_to_rgb32, + "yuy2->rgb32" }, + { VIDCAP_FOURCC_RGB32, VIDCAP_FOURCC_I420, vidcap_rgb32_to_i420, + "rgb32->i420" }, + { VIDCAP_FOURCC_YUY2, VIDCAP_FOURCC_I420, vidcap_yuy2_to_i420, + "yuy2->i420" }, + { VIDCAP_FOURCC_I420, VIDCAP_FOURCC_YUY2, vidcap_i420_to_yuy2, + "i420->yuy2" }, + { VIDCAP_FOURCC_RGB32, VIDCAP_FOURCC_YUY2, vidcap_rgb32_to_yuy2, + "rgb32->yuy2 (not implemented!)" }, - { VIDCAP_FOURCC_2VUY, VIDCAP_FOURCC_YUY2, conv_2vuy_to_yuy2 }, - { VIDCAP_FOURCC_2VUY, VIDCAP_FOURCC_I420, conv_2vuy_to_i420 }, - { VIDCAP_FOURCC_RGB24, VIDCAP_FOURCC_RGB32, conv_rgb24_to_rgb32 }, - { VIDCAP_FOURCC_BOTTOM_UP_RGB24, VIDCAP_FOURCC_RGB32, conv_bottom_up_rgb24_to_rgb32 }, + { VIDCAP_FOURCC_2VUY, VIDCAP_FOURCC_YUY2, conv_2vuy_to_yuy2, + "2vuy->yuy2" }, + { VIDCAP_FOURCC_2VUY, VIDCAP_FOURCC_I420, conv_2vuy_to_i420, + "2vuy->i420" }, + { VIDCAP_FOURCC_RGB24, VIDCAP_FOURCC_RGB32, conv_rgb24_to_rgb32, + "rgb24->rgb32" }, + { VIDCAP_FOURCC_BOTTOM_UP_RGB24, VIDCAP_FOURCC_RGB32, + conv_bottom_up_rgb24_to_rgb32, "bottom-up rgb24->rgb32" }, - { VIDCAP_FOURCC_YVU9, VIDCAP_FOURCC_I420, conv_yvu9_to_i420 }, + { VIDCAP_FOURCC_YVU9, VIDCAP_FOURCC_I420, conv_yvu9_to_i420, + "yvu9->i420" }, }; static const int conv_list_len = sizeof(conv_list) / sizeof(struct conv_info); @@ -99,3 +111,18 @@ } } +const char * +conv_conversion_name_get(conv_func function) +{ + int i; + + for ( i = 0; i < conv_list_len; ++i ) + { + const struct conv_info * ci = &conv_list[i]; + + if ( ci->func == function ) + return ci->name; + } + + return "(ERROR: Conversion name not found)"; +} Modified: trunk/src/conv.h =================================================================== --- trunk/src/conv.h 2007-09-26 13:50:10 UTC (rev 31) +++ trunk/src/conv.h 2007-09-26 13:54:23 UTC (rev 32) @@ -50,6 +50,9 @@ int conv_fmt_size_get(int width, int height, int fourcc); +const char * +conv_conversion_name_get(conv_func function); + #ifdef __cplusplus } #endif Modified: trunk/src/vidcap.c =================================================================== --- trunk/src/vidcap.c 2007-09-26 13:50:10 UTC (rev 31) +++ trunk/src/vidcap.c 2007-09-26 13:54:23 UTC (rev 32) @@ -414,6 +414,9 @@ log_oom(__FILE__, __LINE__); return -1; } + + log_info("format bind requires conversion: %s\n", + conv_conversion_name_get(src_ctx->fmt_conv_func)); } src_ctx->src_state = src_bound; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |