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-12-12 20:26:59
|
Revision: 81 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=81&view=rev Author: bcholew Date: 2007-12-12 12:25:17 -0800 (Wed, 12 Dec 2007) Log Message: ----------- add usage information Modified Paths: -------------- trunk/examples/vidcapTester/vidcapTester.cpp Modified: trunk/examples/vidcapTester/vidcapTester.cpp =================================================================== --- trunk/examples/vidcapTester/vidcapTester.cpp 2007-12-12 19:45:41 UTC (rev 80) +++ trunk/examples/vidcapTester/vidcapTester.cpp 2007-12-12 20:25:17 UTC (rev 81) @@ -1,6 +1,7 @@ #include <stdexcept> #include <QApplication> +#include <QDebug> #include <QIcon> #include "GrabberManager.h" @@ -33,6 +34,13 @@ level_string.toAscii().constData(), msg); } +static void usage() +{ + qDebug() << "usage: vidcapTester " << + "[-f FRAMESPERSECOND] " << + "[-w WIDTH] [-h HEIGHT]"; +} + static void parse_args(int argc, char * argv[], int & width, int & height, int & framerate) { @@ -102,6 +110,7 @@ catch ( const std::runtime_error & e ) { qCritical(e.what()); + usage(); return 1; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. <lib...@li...> - 2007-12-12 19:45:51
|
Revision: 80 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=80&view=rev Author: bcholew Date: 2007-12-12 11:45:41 -0800 (Wed, 12 Dec 2007) Log Message: ----------- remove unnecessary includes Modified Paths: -------------- trunk/src/directshow/DirectShowSource.cpp trunk/src/directshow/DirectShowSource.h Modified: trunk/src/directshow/DirectShowSource.cpp =================================================================== --- trunk/src/directshow/DirectShowSource.cpp 2007-12-04 21:34:32 UTC (rev 79) +++ trunk/src/directshow/DirectShowSource.cpp 2007-12-12 19:45:41 UTC (rev 80) @@ -27,7 +27,6 @@ #include <cstdio> #include <cwchar> #include <atlbase.h> -#include <qedit.h> #include <comutil.h> #include <vidcap/converters.h> Modified: trunk/src/directshow/DirectShowSource.h =================================================================== --- trunk/src/directshow/DirectShowSource.h 2007-12-04 21:34:32 UTC (rev 79) +++ trunk/src/directshow/DirectShowSource.h 2007-12-12 19:45:41 UTC (rev 80) @@ -26,7 +26,6 @@ #define _DIRECTSHOWSOURCE_H_ #include <stdexcept> -#include <atlbase.h> #include <qedit.h> #include <DShow.h> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. <lib...@li...> - 2007-12-04 21:34:33
|
Revision: 79 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=79&view=rev Author: bcholew Date: 2007-12-04 13:34:32 -0800 (Tue, 04 Dec 2007) Log Message: ----------- Patch by Taybin Rutkin to compile in mingw. Thanks. Modified Paths: -------------- trunk/src/os_funcs.h Modified: trunk/src/os_funcs.h =================================================================== --- trunk/src/os_funcs.h 2007-12-04 19:24:16 UTC (rev 78) +++ trunk/src/os_funcs.h 2007-12-04 21:34:32 UTC (rev 79) @@ -50,6 +50,10 @@ #include <process.h> #endif +#if defined(__MINGW32__) +#include <stdint.h> +#endif + #define STDCALL __stdcall typedef CRITICAL_SECTION vc_mutex; typedef uintptr_t vc_thread; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. <lib...@li...> - 2007-12-04 19:24:18
|
Revision: 78 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=78&view=rev Author: bcholew Date: 2007-12-04 11:24:16 -0800 (Tue, 04 Dec 2007) Log Message: ----------- Change execute permissions. Property Changed: ---------------- trunk/src/double_buffer.c trunk/src/double_buffer.h trunk/src/os_funcs.h Property changes on: trunk/src/double_buffer.c ___________________________________________________________________ Name: svn:executable - * Property changes on: trunk/src/double_buffer.h ___________________________________________________________________ Name: svn:executable - * Property changes on: trunk/src/os_funcs.h ___________________________________________________________________ Name: svn:executable - * This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. <lib...@li...> - 2007-12-04 16:04:16
|
Revision: 77 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=77&view=rev Author: bcholew Date: 2007-12-04 08:04:00 -0800 (Tue, 04 Dec 2007) Log Message: ----------- Have capture timer thread alternate buffers when reading - don't just take the newest frame. Modified Paths: -------------- trunk/src/double_buffer.c Modified: trunk/src/double_buffer.c =================================================================== --- trunk/src/double_buffer.c 2007-12-03 17:20:14 UTC (rev 76) +++ trunk/src/double_buffer.c 2007-12-04 16:04:00 UTC (rev 77) @@ -124,6 +124,7 @@ { /* failed to obtain lock */ /* drop incoming object */ + log_info("vidcap callback failed to write a frame\n"); db_buff->free_object(new_object); return; } @@ -148,45 +149,58 @@ void * double_buffer_read(struct double_buffer * db_buff) { - int copy_index = 1; + int copy_index = db_buff->read_count % 2; void * buff; if ( db_buff->write_count < 1 ) return 0; - /* NOTE: Try the newest buffer first - * IF that lock fails THEN try other - */ - if ( db_buff->count[0] > db_buff->count[1] ) - copy_index = 0; + /* try the next buffer */ + if ( db_buff->count[copy_index] < db_buff->read_count ) + { + /* Next buffer isn't ready. Use the previous buffer */ + copy_index = 1 - copy_index; + } + if ( vc_mutex_trylock(&db_buff->locks[copy_index] ) ) { - /* failed to obtain lock */ - /* try the other (older) slot? */ + /* Failed to obtain lock. + * Try the other slot? + */ if ( db_buff->write_count < 2 ) return 0; copy_index = 1 - copy_index; - /* Failed to obtain other lock? */ - /* This should be pretty rare */ + if ( db_buff->count[copy_index] < db_buff->read_count ) + { + /* Too old. Don't read this buffer */ + vc_mutex_unlock(&db_buff->locks[copy_index]); + return 0; + } + + /* Try other lock. Failure should be rare */ if ( vc_mutex_trylock(&db_buff->locks[copy_index] ) ) + { + log_info("Capture timer thread failed to obtain 2nd lock\n"); return 0; + } } - /* Is this buffer older than the last-read? - * TODO: could this happen? - */ - if ( db_buff->count[copy_index] < db_buff->read_count ) + /* Is this buffer older than the last-read? */ + if ( db_buff->count[copy_index] < (db_buff->read_count - 1)) { + /* vidcap buffer is too old. Don't read it. + * This needs to be rare. + */ vc_mutex_unlock(&db_buff->locks[copy_index]); return 0; } buff = db_buff->copy_object(db_buff->objects[copy_index]); - db_buff->read_count = db_buff->count[copy_index]; + db_buff->read_count = db_buff->count[copy_index] + 1; vc_mutex_unlock(&db_buff->locks[copy_index]); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. <lib...@li...> - 2007-12-03 17:20:26
|
Revision: 76 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=76&view=rev Author: bcholew Date: 2007-12-03 09:20:14 -0800 (Mon, 03 Dec 2007) Log Message: ----------- Unused variable. Modified Paths: -------------- trunk/src/sapi.c Modified: trunk/src/sapi.c =================================================================== --- trunk/src/sapi.c 2007-12-03 17:18:46 UTC (rev 75) +++ trunk/src/sapi.c 2007-12-03 17:20:14 UTC (rev 76) @@ -408,7 +408,6 @@ const long idle_state_sleep_period_ms = 100; long sleep_ms = idle_state_sleep_period_ms; int first_time = 1; - const int sleeps_per_capture = 1; int got_frame = 0; int ret; int capture_error = 0; /* FIXME: perhaps should exit on error */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. <lib...@li...> - 2007-12-03 17:18:54
|
Revision: 75 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=75&view=rev Author: bcholew Date: 2007-12-03 09:18:46 -0800 (Mon, 03 Dec 2007) Log Message: ----------- Patch by Taybin Rutkin to compile under cygwin. Thanks. Modified Paths: -------------- trunk/configure.ac trunk/examples/simplegrab.c Modified: trunk/configure.ac =================================================================== --- trunk/configure.ac 2007-12-03 14:11:12 UTC (rev 74) +++ trunk/configure.ac 2007-12-03 17:18:46 UTC (rev 75) @@ -44,7 +44,7 @@ PKG_PROG_PKG_CONFIG -AC_CHECK_FUNCS(nanosleep gettimeofday snprintf Sleep) +AC_CHECK_FUNCS(nanosleep gettimeofday snprintf) AC_CHECK_HEADER(linux/videodev.h, have_v4l=yes, have_v4l=no) Modified: trunk/examples/simplegrab.c =================================================================== --- trunk/examples/simplegrab.c 2007-12-03 14:11:12 UTC (rev 74) +++ trunk/examples/simplegrab.c 2007-12-03 17:18:46 UTC (rev 75) @@ -135,7 +135,7 @@ nanosleep(&tv, 0); -#elif defined(HAVE_SLEEP) +#elif defined(_WIN32) Sleep(milliseconds); #else #error No sleep function available. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. <lib...@li...> - 2007-12-03 14:11:20
|
Revision: 74 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=74&view=rev Author: bcholew Date: 2007-12-03 06:11:12 -0800 (Mon, 03 Dec 2007) Log Message: ----------- Improve cleanup when can't create enumerator moniker. This prevents bad things from happening when the last vidcap device is removed. Modified Paths: -------------- trunk/src/directshow/DShowSrcManager.cpp Modified: trunk/src/directshow/DShowSrcManager.cpp =================================================================== --- trunk/src/directshow/DShowSrcManager.cpp 2007-12-03 14:09:55 UTC (rev 73) +++ trunk/src/directshow/DShowSrcManager.cpp 2007-12-03 14:11:12 UTC (rev 74) @@ -100,7 +100,8 @@ if ( !pCreateDevEnum ) { log_error("failed creating device enumerator - to scan\n"); - return -1; + srcList->len = newListLen; + return 0; } // Enumerate video capture devices @@ -112,7 +113,8 @@ if ( !pEm ) { log_error("Failed creating enumerator moniker\n"); - return -1; + srcList->len = newListLen; + return 0; } pEm->Reset(); @@ -128,7 +130,9 @@ if ( FAILED(hr) ) { log_error("failed CreateBindCtx\n"); - return -1; + pM->Release(); + srcList->len = newListLen; + return srcList->len; } IBaseFilter * pCaptureFilter = 0; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. <lib...@li...> - 2007-12-03 14:09:59
|
Revision: 73 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=73&view=rev Author: bcholew Date: 2007-12-03 06:09:55 -0800 (Mon, 03 Dec 2007) Log Message: ----------- Use abstracted thread and mutex functions in directshow sapi. Modified Paths: -------------- trunk/src/directshow/DevMonitor.cpp trunk/src/directshow/DevMonitor.h trunk/src/directshow/GraphMonitor.cpp trunk/src/directshow/GraphMonitor.h trunk/src/directshow/SourceStateMachine.cpp trunk/src/directshow/SourceStateMachine.h Modified: trunk/src/directshow/DevMonitor.cpp =================================================================== --- trunk/src/directshow/DevMonitor.cpp 2007-12-03 14:09:08 UTC (rev 72) +++ trunk/src/directshow/DevMonitor.cpp 2007-12-03 14:09:55 UTC (rev 73) @@ -39,7 +39,7 @@ szWindowClass_(0), sapiCtx_(0) { - InitializeCriticalSection(®istrationMutex_); + vc_mutex_init(®istrationMutex_); // create an event used to signal that the thread has been created initDoneEvent_ = CreateEvent( @@ -86,15 +86,9 @@ } // pass instance to thread - devMonitorThread_ = CreateThread( - NULL, - 0, - (LPTHREAD_START_ROUTINE)(&DevMonitor::monitorDevices), - this, - 0, - &devMonitorThreadID_); - - if ( devMonitorThread_ == NULL ) + if ( vc_create_thread(&devMonitorThread_, + &DevMonitor::monitorDevices, + this, &devMonitorThreadID_) ) { log_error("DevMonitor: failed spinning DevMonitor thread (%d)\n", GetLastError()); @@ -131,7 +125,7 @@ return; } - DWORD rc = WaitForSingleObject(devMonitorThread_, INFINITE); + DWORD rc = WaitForSingleObject((HANDLE)devMonitorThread_, INFINITE); if ( rc == WAIT_FAILED ) { @@ -145,7 +139,7 @@ GetLastError()); } - DeleteCriticalSection(®istrationMutex_); + vc_mutex_destroy(®istrationMutex_); } LRESULT CALLBACK @@ -181,13 +175,13 @@ return 0; } -DWORD WINAPI -DevMonitor::monitorDevices(LPVOID lpParam) +unsigned int +DevMonitor::monitorDevices(void * param) { //FIXME: move window creation to constructor // extract instance - DevMonitor * pDevMon = (DevMonitor *)lpParam; + DevMonitor * pDevMon = (DevMonitor *)param; // Create a window, so main thread can communicate with us pDevMon->windowHandle_ = CreateWindow( @@ -285,7 +279,7 @@ } log_info("[[ Device event: %s ]]\n", str.c_str()); - EnterCriticalSection(&pDevMon->registrationMutex_); + vc_mutex_lock(&pDevMon->registrationMutex_); if ( sapiCtx && sapiCtx->notify_callback ) @@ -302,7 +296,7 @@ log_info("[[ no user-defined handler registered ]]\n"); } - LeaveCriticalSection(&pDevMon->registrationMutex_); + vc_mutex_unlock(&pDevMon->registrationMutex_); default: str.assign(""); @@ -321,11 +315,11 @@ if ( !sapiCtx ) return -1; - EnterCriticalSection(®istrationMutex_); + vc_mutex_lock(®istrationMutex_); sapiCtx_ = sapiCtx; - LeaveCriticalSection(®istrationMutex_); + vc_mutex_unlock(®istrationMutex_); return 0; } Modified: trunk/src/directshow/DevMonitor.h =================================================================== --- trunk/src/directshow/DevMonitor.h 2007-12-03 14:09:08 UTC (rev 72) +++ trunk/src/directshow/DevMonitor.h 2007-12-03 14:09:55 UTC (rev 73) @@ -36,26 +36,23 @@ int registerCallback(void *); private: - static LRESULT __stdcall - processWindowsMsgs(HWND, UINT, WPARAM, LPARAM); + static LRESULT __stdcall processWindowsMsgs(HWND, UINT, WPARAM, LPARAM); + static unsigned int STDCALL monitorDevices(void * lpParam); - static DWORD WINAPI - monitorDevices(LPVOID lpParam); - private: HANDLE initDoneEvent_; enum threadStatusEnum { initializing=0, initFailed, initDone }; threadStatusEnum threadStatus_; HWND windowHandle_; - void * devMonitorThread_; - DWORD devMonitorThreadID_; + vc_thread devMonitorThread_; + unsigned int devMonitorThreadID_; TCHAR * szTitle_; TCHAR * szWindowClass_; void * sapiCtx_; - CRITICAL_SECTION registrationMutex_; + vc_mutex registrationMutex_; }; #endif Modified: trunk/src/directshow/GraphMonitor.cpp =================================================================== --- trunk/src/directshow/GraphMonitor.cpp 2007-12-03 14:09:08 UTC (rev 72) +++ trunk/src/directshow/GraphMonitor.cpp 2007-12-03 14:09:55 UTC (rev 73) @@ -68,15 +68,9 @@ } // create thread, pass instance - graphMonitorThread_ = CreateThread( - NULL, - 0, - (LPTHREAD_START_ROUTINE)(&GraphMonitor::monitorGraph), - this, - 0, - &graphMonitorThreadID_); - - if ( graphMonitorThread_ == NULL ) + if ( vc_create_thread(&graphMonitorThread_, + &GraphMonitor::monitorGraph, + this, &graphMonitorThreadID_) ) { log_error("GraphMonitor: failed spinning GraphMonitor thread (%d)\n", GetLastError()); @@ -99,7 +93,7 @@ } // wait for thread to shutdown - DWORD rc = WaitForSingleObject(graphMonitorThread_, INFINITE); + DWORD rc = WaitForSingleObject((HANDLE)graphMonitorThread_, INFINITE); if ( rc == WAIT_FAILED ) { @@ -110,11 +104,11 @@ log_info("graph monitor thread destroyed\n"); } -DWORD WINAPI -GraphMonitor::monitorGraph(LPVOID lpParam) +unsigned int +GraphMonitor::monitorGraph(void * param) { // extract instance - GraphMonitor * pGraphMon = (GraphMonitor *)lpParam; + GraphMonitor * pGraphMon = (GraphMonitor *)param; // signal that thread is ready if ( !SetEvent(pGraphMon->initDoneEvent_) ) Modified: trunk/src/directshow/GraphMonitor.h =================================================================== --- trunk/src/directshow/GraphMonitor.h 2007-12-03 14:09:08 UTC (rev 72) +++ trunk/src/directshow/GraphMonitor.h 2007-12-03 14:09:55 UTC (rev 73) @@ -25,7 +25,7 @@ #ifndef _GRAPHMONITOR_H_ #define _GRAPHMONITOR_H_ -#include <windows.h> +#include "os_funcs.h" class GraphMonitor { @@ -37,7 +37,7 @@ ~GraphMonitor(); private: - static DWORD WINAPI monitorGraph(LPVOID lpParam); + static unsigned int STDCALL monitorGraph(void * param); private: HANDLE *graphHandle_; @@ -47,8 +47,8 @@ HANDLE initDoneEvent_; HANDLE terminateEvent_; - void * graphMonitorThread_; - DWORD graphMonitorThreadID_; + vc_thread graphMonitorThread_; + unsigned int graphMonitorThreadID_; }; #endif Modified: trunk/src/directshow/SourceStateMachine.cpp =================================================================== --- trunk/src/directshow/SourceStateMachine.cpp 2007-12-03 14:09:08 UTC (rev 72) +++ trunk/src/directshow/SourceStateMachine.cpp 2007-12-03 14:09:55 UTC (rev 73) @@ -85,15 +85,9 @@ } // pass instance to thread - sourceThread_ = CreateThread( - NULL, - 0, - (LPTHREAD_START_ROUTINE)(&SourceStateMachine::waitForCmd), - this, - 0, - &sourceThreadID_); - - if ( sourceThread_ != NULL ) + if ( !vc_create_thread(&sourceThread_, + &SourceStateMachine::waitForCmd, + this, &sourceThreadID_) ) { // wait for signal from thread that it is ready WaitForSingleObject(eventInitDone_, INFINITE); @@ -123,7 +117,7 @@ } // wait for thread to shutdown - DWORD rc = WaitForSingleObject(sourceThread_, INFINITE); + DWORD rc = WaitForSingleObject((HANDLE)sourceThread_, INFINITE); if ( rc == WAIT_FAILED ) { @@ -231,11 +225,11 @@ return 0; } -DWORD WINAPI -SourceStateMachine::waitForCmd(LPVOID lpParam) +unsigned int +SourceStateMachine::waitForCmd(void *param) { // extract instance - SourceStateMachine * pSrc = (SourceStateMachine *)lpParam; + SourceStateMachine * pSrc = (SourceStateMachine *)param; // signal to main thread that we are ready for commands if ( !SetEvent(pSrc->eventInitDone_) ) Modified: trunk/src/directshow/SourceStateMachine.h =================================================================== --- trunk/src/directshow/SourceStateMachine.h 2007-12-03 14:09:08 UTC (rev 72) +++ trunk/src/directshow/SourceStateMachine.h 2007-12-03 14:09:55 UTC (rev 73) @@ -47,7 +47,7 @@ } private: - static DWORD WINAPI waitForCmd(LPVOID); + static unsigned int STDCALL waitForCmd(void *); void terminate(); void doStart(); void doStop(); @@ -70,8 +70,8 @@ HANDLE eventStop_; HANDLE eventTerminate_; HANDLE eventCancel_; - void * sourceThread_; - DWORD sourceThreadID_; + vc_thread sourceThread_; + unsigned int sourceThreadID_; bool okToSendStart_; bool okToSendStop_; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. <lib...@li...> - 2007-12-03 14:09:10
|
Revision: 72 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=72&view=rev Author: bcholew Date: 2007-12-03 06:09:08 -0800 (Mon, 03 Dec 2007) Log Message: ----------- Use abstracted thread and mutex functions in v4l and qt sapis. Modified Paths: -------------- trunk/src/sapi_qt.c trunk/src/sapi_v4l.c Modified: trunk/src/sapi_qt.c =================================================================== --- trunk/src/sapi_qt.c 2007-12-03 14:07:46 UTC (rev 71) +++ trunk/src/sapi_qt.c 2007-12-03 14:09:08 UTC (rev 72) @@ -23,7 +23,6 @@ * */ -#include <pthread.h> #include <stdlib.h> #include <strings.h> @@ -40,8 +39,9 @@ struct sapi_qt_context { - pthread_mutex_t mutex; - pthread_t notify_thread; + vc_mutex mutex; + vc_thread notify_thread; + unsigned int notify_thread_id; int notifying; struct sg_manager mgr; @@ -52,7 +52,8 @@ struct sg_source * src; int capturing; - pthread_t capture_thread; + vc_thread capture_thread; + unsigned int capture_thread_id; TimeValue last_time; long frame_count; @@ -61,20 +62,20 @@ }; static int -mutex_lock(pthread_mutex_t * mutex) +mutex_lock(vc_mutex * mutex) { - int err = pthread_mutex_lock(mutex); + int err = vc_mutex_lock(mutex); if ( err ) - log_error("failed pthread_mutex_lock() %d\n", err); + log_error("failed vc_mutex_lock() %d\n", err); return err; } static int -mutex_unlock(pthread_mutex_t * mutex) +mutex_unlock(vc_mutex * mutex) { - int err = pthread_mutex_unlock(mutex); + int err = vc_mutex_unlock(mutex); if ( err ) - log_error("failed pthread_mutex_unlock() %d\n", err); + log_error("failed vc_mutex_unlock() %d\n", err); return err; } @@ -372,7 +373,7 @@ return ts; } -static void * +static unsigned int capture_thread_proc(void * data) { struct sapi_src_context * src_ctx = @@ -392,22 +393,32 @@ if ( map_fourcc_to_ostype(src_ctx->fmt_native.fourcc, &pixel_format) ) { - log_error("invalid pixel format '%s'\n", + log_error("invalid pixel format '%s' (0x%0x)\n", vidcap_fourcc_string_get( - src_ctx->fmt_native.fourcc)); - return (void *)-1; + src_ctx->fmt_native.fourcc), + src_ctx->fmt_native.fourcc); + + ret = -2; + sapi_src_capture_notify(src_ctx, 0, 0, 0, ret); + return ret; } if ( sg_source_format_set(qt_src_ctx->src, src_ctx->fmt_native.width, src_ctx->fmt_native.height, fps, pixel_format) ) - return (void *)-1; + { + ret = -3; + sapi_src_capture_notify(src_ctx, 0, 0, 0, ret); + return ret; + } if ( qt_src_ctx->decomp_session ) { log_error("decomp session already setup\n"); - return (void *)-1; + ret = -4; + sapi_src_capture_notify(src_ctx, 0, 0, 0, ret); + return ret; } qt_src_ctx->last_time = 0; @@ -415,10 +426,18 @@ if ( sg_source_capture_start(qt_src_ctx->src, source_capture_callback, (long)src_ctx) ) - return (void *)-1; + { + ret = -5; + sapi_src_capture_notify(src_ctx, 0, 0, 0, ret); + return ret; + } if ( source_decomp_session_setup(src_ctx) ) - return (void *)-1; + { + ret = -6; + sapi_src_capture_notify(src_ctx, 0, 0, 0, ret); + return ret; + } while ( qt_src_ctx->capturing ) { @@ -426,8 +445,8 @@ if ( sg_source_capture_poll(qt_src_ctx->src) ) { - sapi_src_capture_notify(src_ctx, 0, 0, 0, -1); - ret = -1; + ret = -7; + sapi_src_capture_notify(src_ctx, 0, 0, 0, ret); goto bail; } @@ -436,8 +455,9 @@ if ( errno != -EINTR ) { log_error("failed nanosleep() %d\n", errno); - ret = -1; - goto bail; + ret = -8; + sapi_src_capture_notify(src_ctx, 0, 0, 0, ret); + goto bail; } } } @@ -445,12 +465,12 @@ bail: if ( source_decomp_session_takedown(src_ctx) ) - ret = -1; + ret -= 100; if ( sg_source_capture_stop(qt_src_ctx->src) ) - ret = -1; + ret -= -1000; - return (void *)ret; + return ret; } static int @@ -462,10 +482,11 @@ qt_src_ctx->capturing = 1; - if ( (ret = pthread_create(&qt_src_ctx->capture_thread, 0, - capture_thread_proc, src_ctx)) ) + if ( (ret = vc_create_thread(&qt_src_ctx->capture_thread, + capture_thread_proc, + src_ctx, &qt_src_ctx->capture_thread_id)) ) { - log_error("failed pthread_create() for capture thread %d\n", + log_error("failed vc_thread_create() for capture thread %d\n", ret); return -1; } @@ -480,20 +501,15 @@ (struct sapi_qt_src_context *)src_ctx->priv; int ret; - int thread_ret; qt_src_ctx->capturing = 0; - if ( (ret = pthread_join(qt_src_ctx->capture_thread, - (void *)&thread_ret)) ) + if ( (ret = vc_thread_join(&qt_src_ctx->capture_thread)) ) { - log_error("failed pthread_join() %d\n", ret); + log_error("failed vc_thread_join() %d\n", ret); return -1; } - if ( thread_ret ) - log_warn("capture_thread_proc returned %d\n", thread_ret); - return 0; } @@ -674,7 +690,7 @@ return -1; } -static void * +static unsigned int notify_thread_proc(void * data) { struct sapi_context * sapi_ctx = (struct sapi_context *)data; @@ -690,18 +706,18 @@ int source_count; if ( mutex_lock(&qt_ctx->mutex) ) - return (void *)-1; + return -1; if ( sg_manager_update(&qt_ctx->mgr) ) { mutex_unlock(&qt_ctx->mutex); - return (void *)-1; + return -1; } source_count = sg_manager_source_count(&qt_ctx->mgr); if ( mutex_unlock(&qt_ctx->mutex) ) - return (void *)-1; + return -1; if ( source_count != last_source_count && sapi_ctx->notify_callback ) @@ -716,7 +732,7 @@ if ( errno != -EINTR ) { log_error("failed nanosleep() %d\n", errno); - return (void *)-1; + return -1; } } } @@ -729,20 +745,16 @@ { struct sapi_qt_context * qt_ctx = (struct sapi_qt_context *)sapi_ctx->priv; - int thread_ret; int ret; qt_ctx->notifying = 0; - if ( (ret = pthread_join(qt_ctx->notify_thread, (void *)&thread_ret)) ) + if ( (ret = vc_thread_join(&qt_ctx->notify_thread)) ) { - log_error("failed pthread_join() notify thread %d\n", ret); + log_error("failed vc_thread_join() notify thread %d\n", ret); return -1; } - if ( thread_ret ) - log_warn("notify_thread_proc returned %d\n", thread_ret); - return 0; } @@ -758,10 +770,10 @@ qt_ctx->notifying = 1; - if ( (ret = pthread_create(&qt_ctx->notify_thread, 0, - notify_thread_proc, sapi_ctx)) ) + if ( (ret = vc_create_thread(&qt_ctx->notify_thread, notify_thread_proc, + sapi_ctx, &qt_ctx->notify_thread_id)) ) { - log_error("failed pthread_create() for notify thread %d\n", + log_error("failed vc_thread_create() for notify thread %d\n", ret); return -1; } @@ -791,7 +803,7 @@ ExitMovies(); - pthread_mutex_destroy(&qt_ctx->mutex); + vc_mutex_destroy(&qt_ctx->mutex); free(sapi_ctx->user_src_list.list); free(qt_ctx); @@ -810,9 +822,9 @@ return -1; } - if ( pthread_mutex_init(&qt_ctx->mutex, 0) ) + if ( vc_mutex_init(&qt_ctx->mutex) ) { - log_error("failed pthread_mutex_init()\n"); + log_error("failed vc_mutex_init()\n"); return -1; } Modified: trunk/src/sapi_v4l.c =================================================================== --- trunk/src/sapi_v4l.c 2007-12-03 14:07:46 UTC (rev 71) +++ trunk/src/sapi_v4l.c 2007-12-03 14:09:08 UTC (rev 72) @@ -26,7 +26,6 @@ #include <errno.h> #include <fcntl.h> #include <linux/videodev.h> -#include <pthread.h> #include <stdlib.h> #include <string.h> #include <sys/ioctl.h> @@ -51,8 +50,9 @@ struct sapi_v4l_context { - pthread_mutex_t mutex; - pthread_t notify_thread; + vc_mutex mutex; + vc_thread notify_thread; + unsigned int notify_thread_id; int notifying; struct sapi_src_list acquired_src_list; }; @@ -71,7 +71,8 @@ struct video_mbuf mbuf; int capturing; - pthread_t capture_thread; + vc_thread capture_thread; + unsigned int capture_thread_id; }; static int @@ -533,7 +534,7 @@ return 0; } -static void * +static unsigned int capture_thread_proc(void * data) { struct sapi_src_context * src_ctx = @@ -554,7 +555,7 @@ if ( fb_base == (void *)-1 ) { log_error("failed mmap() %d\n", errno); - return (void *)-1; + return -1; } if ( capture_kickoff(src_ctx, started_frame_count) ) @@ -575,8 +576,8 @@ goto bail; } - sapi_src_capture_notify(src_ctx, fb_base + - v4l_src_ctx->mbuf.offsets[capture_frame], + sapi_src_capture_notify(src_ctx, (char *)(fb_base + + v4l_src_ctx->mbuf.offsets[capture_frame]), capture_size, 0, 0); @@ -603,7 +604,7 @@ if ( munmap((void *)fb_base, v4l_src_ctx->mbuf.size) == -1 ) { log_error("failed munmap() %d\n", errno); - return (void *)-1; + return -1; } return 0; @@ -612,7 +613,7 @@ if ( munmap((void *)fb_base, v4l_src_ctx->mbuf.size) == -1 ) log_warn("failed munmap() %d\n", errno); - return (void *)-1; + return -1; } static int @@ -624,10 +625,11 @@ v4l_src_ctx->capturing = 1; - if ( (ret = pthread_create(&v4l_src_ctx->capture_thread, 0, - capture_thread_proc, src_ctx)) ) + if ( (ret = vc_create_thread(&v4l_src_ctx->capture_thread, + capture_thread_proc, src_ctx, + &v4l_src_ctx->capture_thread_id)) ) { - log_error("failed pthread_create() for capture thread %d\n", + log_error("failed vc_create_thread() for capture thread %d\n", ret); return -1; } @@ -641,20 +643,15 @@ struct sapi_v4l_src_context * v4l_src_ctx = (struct sapi_v4l_src_context *)src_ctx->priv; int ret; - int thread_ret; v4l_src_ctx->capturing = 0; - if ( (ret = pthread_join(v4l_src_ctx->capture_thread, - (void *)&thread_ret)) ) + if ( (ret = vc_thread_join(&v4l_src_ctx->capture_thread)) ) { - log_error("failed pthread_join() %d\n", ret); + log_error("failed vc_thread_join() %d\n", ret); return -1; } - if ( thread_ret ) - log_warn("capture_thread_proc returned %d\n", thread_ret); - return 0; } @@ -928,7 +925,7 @@ return -1; } -static void * +static unsigned int notify_thread_proc(void * data) { struct sapi_context * sapi_ctx = (struct sapi_context *)data; @@ -939,18 +936,18 @@ while ( v4l_ctx->notifying ) { - pthread_mutex_lock(&v4l_ctx->mutex); + vc_mutex_lock(&v4l_ctx->mutex); /* TODO: look for devices */ - pthread_mutex_unlock(&v4l_ctx->mutex); + vc_mutex_unlock(&v4l_ctx->mutex); if ( nanosleep(&wait_ts, 0) ) { if ( errno != -EINTR ) { log_error("failed nanosleep() %d\n", errno); - return (void *)-1; + return -1; } } } @@ -963,20 +960,16 @@ { struct sapi_v4l_context * v4l_ctx = (struct sapi_v4l_context *)sapi_ctx->priv; - int thread_ret; int ret; v4l_ctx->notifying = 0; - if ( (ret = pthread_join(v4l_ctx->notify_thread, (void *)&thread_ret)) ) + if ( (ret = vc_thread_join(&v4l_ctx->notify_thread)) ) { - log_error("failed pthread_join() notify thread %d\n", ret); + log_error("failed vc_thread_join() notify thread %d\n", ret); return -1; } - if ( thread_ret ) - log_warn("notify_thread_proc returned %d\n", thread_ret); - return 0; } @@ -992,10 +985,11 @@ v4l_ctx->notifying = 1; - if ( (ret = pthread_create(&v4l_ctx->notify_thread, 0, - notify_thread_proc, sapi_ctx)) ) + if ( (ret = vc_create_thread(&v4l_ctx->notify_thread, + notify_thread_proc, sapi_ctx, + &v4l_ctx->notify_thread_id)) ) { - log_error("failed pthread_create() for notify thread %d\n", + log_error("failed vc_create_thread() for notify thread %d\n", ret); return -1; } @@ -1009,7 +1003,7 @@ struct sapi_v4l_context * v4l_ctx = (struct sapi_v4l_context *)sapi_ctx->priv; - pthread_mutex_destroy(&v4l_ctx->mutex); + vc_mutex_destroy(&v4l_ctx->mutex); free(sapi_ctx->user_src_list.list); free(v4l_ctx); @@ -1028,9 +1022,9 @@ return -1; } - if ( pthread_mutex_init(&v4l_ctx->mutex, 0) ) + if ( vc_mutex_init(&v4l_ctx->mutex) ) { - log_error("failed pthread_mutex_init()\n"); + log_error("failed vc_mutex_init()\n"); 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-12-03 14:07:51
|
Revision: 71 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=71&view=rev Author: bcholew Date: 2007-12-03 06:07:46 -0800 (Mon, 03 Dec 2007) Log Message: ----------- Add return codes to abstracted thread and mutex functions. Modified Paths: -------------- trunk/src/os_funcs.h Modified: trunk/src/os_funcs.h =================================================================== --- trunk/src/os_funcs.h 2007-12-03 14:04:37 UTC (rev 70) +++ trunk/src/os_funcs.h 2007-12-03 14:07:46 UTC (rev 71) @@ -112,58 +112,65 @@ unsigned int (STDCALL * thread_func)(void *), void *args, unsigned int *thread_id) { + int ret = 0; #ifdef WIN32 *thread = (uintptr_t)_beginthreadex(NULL, 0, thread_func, (void *)args, 0, thread_id); /* FIXME: log the error */ if ( thread == 0 ) - return -1; + ret = errno; #else - int ret; void * (*func)(void *) = (void * (*)(void *))thread_func; ret = pthread_create(thread, NULL, func, args); - /* FIXME: log the error */ - if ( ret ) - return -1; + /* FIXME: log an error */ #endif - return 0; + return ret; } -static __inline void +static __inline int vc_thread_join(vc_thread *thread) { #ifdef WIN32 HANDLE _thread = (HANDLE)thread; - WaitForSingleObject(_thread, INFINITE); + DWORD ret = WaitForSingleObject(_thread, INFINITE); + + if ( ret == WAIT_FAILED ) + return GetLastError(); + + return 0; #else pthread_t *_thread = (pthread_t *)thread; - pthread_join(*_thread, 0); + return pthread_join(*_thread, 0); #endif } -static __inline void +static __inline int vc_mutex_init(vc_mutex *m) { #ifdef WIN32 InitializeCriticalSection(m); + + return 0; #else - pthread_mutex_init(m, NULL); + return pthread_mutex_init(m, NULL); #endif } -static __inline void +static __inline int vc_mutex_lock(vc_mutex *m) { #ifdef WIN32 EnterCriticalSection(m); + + return 0; #else - pthread_mutex_lock(m); + return pthread_mutex_lock(m); #endif } @@ -177,23 +184,27 @@ #endif } -static __inline void +static __inline int vc_mutex_unlock(vc_mutex *m) { #ifdef WIN32 LeaveCriticalSection(m); + + return 0; #else - pthread_mutex_unlock(m); + return pthread_mutex_unlock(m); #endif } -static __inline void +static __inline int vc_mutex_destroy(vc_mutex *m) { #ifdef WIN32 DeleteCriticalSection(m); + + return 0; #else - pthread_mutex_destroy(m); + return pthread_mutex_destroy(m); #endif } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. <lib...@li...> - 2007-12-03 14:04:42
|
Revision: 70 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=70&view=rev Author: bcholew Date: 2007-12-03 06:04:37 -0800 (Mon, 03 Dec 2007) Log Message: ----------- Screen out dataless capture callbacks. Adjust timer thread's sleep time to be more precise. Modified Paths: -------------- trunk/src/sapi.c Modified: trunk/src/sapi.c =================================================================== --- trunk/src/sapi.c 2007-11-26 19:32:59 UTC (rev 69) +++ trunk/src/sapi.c 2007-12-03 14:04:37 UTC (rev 70) @@ -219,6 +219,13 @@ if ( !frame ) return -1; + /* Screen-out useless callbacks */ + if ( video_data_size < 1 && !error_status ) + { + log_info("callback with no data?\n"); + return 0; + } + frame->video_data_size = video_data_size; frame->error_status = error_status; frame->stride = stride; @@ -398,8 +405,6 @@ { struct sapi_src_context * src_ctx = args; struct timeval tv_now; - - /* change to faster rate at capture time, and reduce when capture stopped */ const long idle_state_sleep_period_ms = 100; long sleep_ms = idle_state_sleep_period_ms; int first_time = 1; @@ -420,14 +425,13 @@ src_ctx->frame_time_next.tv_sec = tv_now.tv_sec; src_ctx->frame_time_next.tv_usec = tv_now.tv_usec; - log_info("capture timer thread now running\n"); src_ctx->capture_timer_thread_started = 1; while ( !src_ctx->kill_timer_thread ) { gettimeofday(&tv_now, 0); - /* time to attempt to read a frame? */ + /* sleep or read? */ if ( capture_error || src_ctx->src_state != src_capturing || !tv_greater_or_equal(&tv_now, &src_ctx->frame_time_next) ) { @@ -436,7 +440,17 @@ sleep_ms = idle_state_sleep_period_ms; first_time = 1; } + else if ( !capture_error ) + { + /* sleep just enough */ + sleep_ms = ((src_ctx->frame_time_next.tv_sec - tv_now.tv_sec) * + 1000000L + src_ctx->frame_time_next.tv_usec - + tv_now.tv_usec) / 1000L; + } + if ( sleep_ms < 0 ) + sleep_ms = 0; + vc_millisleep(sleep_ms); } else @@ -458,16 +472,11 @@ /* re-initialize when next to check for a frame */ src_ctx->frame_time_next.tv_sec = tv_now.tv_sec; src_ctx->frame_time_next.tv_usec = tv_now.tv_usec; - - sleep_ms = (1000 / sleeps_per_capture) * - src_ctx->fmt_nominal.fps_denominator / - src_ctx->fmt_nominal.fps_numerator; } if ( !first_time ) { /* update when next to check for a frame */ - /* FIXME: reduce round-off */ tv_add_usecs(&src_ctx->frame_time_next, &src_ctx->frame_time_next, 1000000 * src_ctx->fmt_nominal.fps_denominator / @@ -488,8 +497,6 @@ src_ctx->timer_thread_idle = 1; } - log_info("capture timer thread now exiting...\n"); - return 0; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. <lib...@li...> - 2007-11-26 19:33:09
|
Revision: 69 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=69&view=rev Author: bcholew Date: 2007-11-26 11:32:59 -0800 (Mon, 26 Nov 2007) Log Message: ----------- Keep public video data const, and the internal not. Modified Paths: -------------- trunk/include/vidcap/vidcap.h trunk/src/sapi.c trunk/src/sapi_context.h trunk/src/vidcap.c Modified: trunk/include/vidcap/vidcap.h =================================================================== --- trunk/include/vidcap/vidcap.h 2007-11-26 18:32:38 UTC (rev 68) +++ trunk/include/vidcap/vidcap.h 2007-11-26 19:32:59 UTC (rev 69) @@ -73,7 +73,7 @@ struct vidcap_capture_info { - char * video_data; + const char * video_data; int video_data_size; int error_status; }; Modified: trunk/src/sapi.c =================================================================== --- trunk/src/sapi.c 2007-11-26 18:32:38 UTC (rev 68) +++ trunk/src/sapi.c 2007-11-26 19:32:59 UTC (rev 69) @@ -219,15 +219,8 @@ if ( !frame ) return -1; - frame->cap_info = malloc(sizeof(struct vidcap_capture_info)); - if ( !frame->cap_info ) - { - free(frame); - return -1; - } - - frame->cap_info->video_data_size = video_data_size; - frame->cap_info->error_status = error_status; + frame->video_data_size = video_data_size; + frame->error_status = error_status; frame->stride = stride; if ( src_ctx->use_timer_thread ) @@ -235,15 +228,14 @@ /* Copy this buffer. It might not exist long enough for * read thread (capture timer thread) to copy it */ - frame->cap_info->video_data = malloc(video_data_size); - if ( !frame->cap_info->video_data ) + frame->video_data = malloc(video_data_size); + if ( !frame->video_data ) { - free(frame->cap_info); free(frame); return -1; } - memcpy(frame->cap_info->video_data, video_data, video_data_size); + memcpy(frame->video_data, video_data, video_data_size); /* buffer the frame - for processing by the timer thread */ double_buffer_insert(src_ctx->double_buff, frame); @@ -256,7 +248,7 @@ } else { - frame->cap_info->video_data = video_data; + frame->video_data = video_data; /* process the frame now */ src_ctx->no_timer_thread_frame = frame; @@ -303,10 +295,10 @@ frame = src_ctx->no_timer_thread_frame; } - video_data = frame->cap_info->video_data; - video_data_size = frame->cap_info->video_data_size; + video_data = frame->video_data; + video_data_size = frame->video_data_size; stride = frame->stride; - error_status = frame->cap_info->error_status; + error_status = frame->error_status; /* FIXME: right now enforce_framerate() and the capture timer * thread's main loop BOTH use the frame_time_next field @@ -381,8 +373,7 @@ if ( src_ctx->use_timer_thread ) { /* delete frame */ - free(frame->cap_info->video_data); - free(frame->cap_info); + free(frame->video_data); free(frame); if ( error_status ) Modified: trunk/src/sapi_context.h =================================================================== --- trunk/src/sapi_context.h 2007-11-26 18:32:38 UTC (rev 68) +++ trunk/src/sapi_context.h 2007-11-26 19:32:59 UTC (rev 69) @@ -36,7 +36,9 @@ struct frame_info { - struct vidcap_capture_info *cap_info; + char * video_data; + int video_data_size; + int error_status; int stride; }; Modified: trunk/src/vidcap.c =================================================================== --- trunk/src/vidcap.c 2007-11-26 18:32:38 UTC (rev 68) +++ trunk/src/vidcap.c 2007-11-26 19:32:59 UTC (rev 69) @@ -551,9 +551,7 @@ { struct frame_info *frame = (struct frame_info *)fr; - /* FIXME: unconstify video_data */ - free(frame->cap_info->video_data); - free(frame->cap_info); + free(frame->video_data); free(frame); } @@ -567,28 +565,19 @@ if ( !dup_frame ) return 0; - dup_frame->cap_info = calloc(1, sizeof(*dup_frame->cap_info)); - if ( !dup_frame->cap_info ) - { - free(dup_frame); - return 0; - } - dup_frame->stride = frame->stride; - dup_frame->cap_info->error_status = frame->cap_info->error_status; - dup_frame->cap_info->video_data_size = frame->cap_info->video_data_size; - dup_frame->cap_info->video_data = malloc(frame->cap_info->video_data_size); - if ( !dup_frame->cap_info->video_data ) + dup_frame->error_status = frame->error_status; + dup_frame->video_data_size = frame->video_data_size; + dup_frame->video_data = malloc(frame->video_data_size); + if ( !dup_frame->video_data ) { - free(dup_frame->cap_info); free(dup_frame); return 0; } - /* FIXME: unconstify cap_info->video_data */ - memcpy(dup_frame->cap_info->video_data, - frame->cap_info->video_data, - frame->cap_info->video_data_size); + memcpy(dup_frame->video_data, + frame->video_data, + frame->video_data_size); return dup_frame; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. <lib...@li...> - 2007-11-26 18:33:10
|
Revision: 68 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=68&view=rev Author: bcholew Date: 2007-11-26 10:32:38 -0800 (Mon, 26 Nov 2007) Log Message: ----------- De-constify the vidcap buffer - removing compile-time warnings. Modified Paths: -------------- trunk/include/vidcap/vidcap.h trunk/src/directshow/SourceStateMachine.cpp trunk/src/sapi.c trunk/src/sapi.h Modified: trunk/include/vidcap/vidcap.h =================================================================== --- trunk/include/vidcap/vidcap.h 2007-11-26 18:22:32 UTC (rev 67) +++ trunk/include/vidcap/vidcap.h 2007-11-26 18:32:38 UTC (rev 68) @@ -73,7 +73,7 @@ struct vidcap_capture_info { - const char * video_data; + char * video_data; int video_data_size; int error_status; }; Modified: trunk/src/directshow/SourceStateMachine.cpp =================================================================== --- trunk/src/directshow/SourceStateMachine.cpp 2007-11-26 18:22:32 UTC (rev 67) +++ trunk/src/directshow/SourceStateMachine.cpp 2007-11-26 18:32:38 UTC (rev 68) @@ -521,7 +521,7 @@ } int ret = sapi_src_capture_notify(instance->sourceContext_, - reinterpret_cast<const char *>(pBuff), + reinterpret_cast<char *>(pBuff), static_cast<int>(buffSize), 0, 0); instance->callbackInProgress_ = false; Modified: trunk/src/sapi.c =================================================================== --- trunk/src/sapi.c 2007-11-26 18:22:32 UTC (rev 67) +++ trunk/src/sapi.c 2007-11-26 18:32:38 UTC (rev 68) @@ -205,7 +205,7 @@ /* NOTE: stride-ignorant sapis should pass a stride of zero */ int sapi_src_capture_notify(struct sapi_src_context * src_ctx, - const char * video_data, int video_data_size, + char * video_data, int video_data_size, int stride, int error_status) { Modified: trunk/src/sapi.h =================================================================== --- trunk/src/sapi.h 2007-11-26 18:22:32 UTC (rev 67) +++ trunk/src/sapi.h 2007-11-26 18:32:38 UTC (rev 68) @@ -46,7 +46,7 @@ int sapi_src_capture_notify(struct sapi_src_context * src_ctx, - const char * video_data, int video_data_size, + char * video_data, int video_data_size, int stride, int error_status); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. <lib...@li...> - 2007-11-26 18:22:51
|
Revision: 67 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=67&view=rev Author: bcholew Date: 2007-11-26 10:22:32 -0800 (Mon, 26 Nov 2007) Log Message: ----------- Remove unused member variable. Modified Paths: -------------- trunk/src/directshow/DirectShowSource.h Modified: trunk/src/directshow/DirectShowSource.h =================================================================== --- trunk/src/directshow/DirectShowSource.h 2007-11-26 18:12:00 UTC (rev 66) +++ trunk/src/directshow/DirectShowSource.h 2007-11-26 18:22:32 UTC (rev 67) @@ -94,7 +94,6 @@ private: struct sapi_src_context * sourceContext_; - DShowSrcManager * dshowMgr_; bufferCallbackFunc bufferCB_; cancelCaptureFunc cancelCaptureCB_; void * parent_; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. <lib...@li...> - 2007-11-26 18:12:03
|
Revision: 66 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=66&view=rev Author: bcholew Date: 2007-11-26 10:12:00 -0800 (Mon, 26 Nov 2007) Log Message: ----------- Add windows solution file with vidcapTester - and dependency on libvidcap. Added Paths: ----------- trunk/contrib/win/vs2005/libvidcap.sln Added: trunk/contrib/win/vs2005/libvidcap.sln =================================================================== --- trunk/contrib/win/vs2005/libvidcap.sln (rev 0) +++ trunk/contrib/win/vs2005/libvidcap.sln 2007-11-26 18:12:00 UTC (rev 66) @@ -0,0 +1,29 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libvidcap", "libvidcap.vcproj", "{F5166D99-32BB-40D5-BE95-6F97F72C44CE}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vidcapTester", "..\..\..\examples\vidcapTester\vidcapTester.vcproj", "{BC64438B-D90D-3952-8ACE-7E3DBF22D068}" + ProjectSection(ProjectDependencies) = postProject + {F5166D99-32BB-40D5-BE95-6F97F72C44CE} = {F5166D99-32BB-40D5-BE95-6F97F72C44CE} + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {F5166D99-32BB-40D5-BE95-6F97F72C44CE}.Debug|Win32.ActiveCfg = Debug|Win32 + {F5166D99-32BB-40D5-BE95-6F97F72C44CE}.Debug|Win32.Build.0 = Debug|Win32 + {F5166D99-32BB-40D5-BE95-6F97F72C44CE}.Release|Win32.ActiveCfg = Release|Win32 + {F5166D99-32BB-40D5-BE95-6F97F72C44CE}.Release|Win32.Build.0 = Release|Win32 + {BC64438B-D90D-3952-8ACE-7E3DBF22D068}.Debug|Win32.ActiveCfg = Debug|Win32 + {BC64438B-D90D-3952-8ACE-7E3DBF22D068}.Debug|Win32.Build.0 = Debug|Win32 + {BC64438B-D90D-3952-8ACE-7E3DBF22D068}.Release|Win32.ActiveCfg = Release|Win32 + {BC64438B-D90D-3952-8ACE-7E3DBF22D068}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. <lib...@li...> - 2007-11-26 17:59:41
|
Revision: 65 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=65&view=rev Author: bcholew Date: 2007-11-26 09:59:33 -0800 (Mon, 26 Nov 2007) Log Message: ----------- Add a capture timer thread to strictly enforce framerate (but preserve code for use without this thread). Add a double buffer to pass frames between threads. Abstract threading and mutexes for linux, mac and windows. Add new double_buffer and os_funcs files to vcproj and Makefiles. Simplify and rearrange some includes. Modified Paths: -------------- trunk/contrib/win/vs2005/libvidcap.vcproj trunk/src/Makefile.am trunk/src/directshow/DShowSrcManager.cpp trunk/src/directshow/DevMonitor.cpp trunk/src/directshow/DevMonitor.h trunk/src/directshow/DirectShowSource.cpp trunk/src/directshow/SourceStateMachine.cpp trunk/src/sapi.c trunk/src/sapi_context.h trunk/src/sapi_dshow.cpp trunk/src/vidcap.c Added Paths: ----------- trunk/src/double_buffer.c trunk/src/double_buffer.h trunk/src/os_funcs.h Modified: trunk/contrib/win/vs2005/libvidcap.vcproj =================================================================== --- trunk/contrib/win/vs2005/libvidcap.vcproj 2007-11-20 17:51:57 UTC (rev 64) +++ trunk/contrib/win/vs2005/libvidcap.vcproj 2007-11-26 17:59:33 UTC (rev 65) @@ -228,6 +228,10 @@ </FileConfiguration> </File> <File + RelativePath="..\..\..\src\double_buffer.c" + > + </File> + <File RelativePath="..\..\..\src\directshow\DShowSrcManager.cpp" > <FileConfiguration @@ -372,6 +376,10 @@ > </File> <File + RelativePath="..\..\..\src\double_buffer.h" + > + </File> + <File RelativePath="..\..\..\src\directshow\DShowSrcManager.h" > </File> @@ -388,6 +396,10 @@ > </File> <File + RelativePath="..\..\..\src\os_funcs.h" + > + </File> + <File RelativePath="..\..\..\src\sapi.h" > </File> Modified: trunk/src/Makefile.am =================================================================== --- trunk/src/Makefile.am 2007-11-20 17:51:57 UTC (rev 64) +++ trunk/src/Makefile.am 2007-11-26 17:59:33 UTC (rev 65) @@ -19,10 +19,13 @@ conv_to_rgb.c \ conv_to_i420.c \ conv_to_yuy2.c \ + double_buffer.c \ + double_buffer.h \ hotlist.c \ hotlist.h \ logging.c \ logging.h \ + os_funcs.h \ sapi.c \ sapi.h \ sapi_context.h \ Modified: trunk/src/directshow/DShowSrcManager.cpp =================================================================== --- trunk/src/directshow/DShowSrcManager.cpp 2007-11-20 17:51:57 UTC (rev 64) +++ trunk/src/directshow/DShowSrcManager.cpp 2007-11-26 17:59:33 UTC (rev 65) @@ -22,7 +22,7 @@ // <http://www.gnu.org/licenses/>. // -#include <windows.h> +#include "os_funcs.h" #include <cstring> #include <cstdio> #include <cwchar> Modified: trunk/src/directshow/DevMonitor.cpp =================================================================== --- trunk/src/directshow/DevMonitor.cpp 2007-11-20 17:51:57 UTC (rev 64) +++ trunk/src/directshow/DevMonitor.cpp 2007-11-26 17:59:33 UTC (rev 65) @@ -22,11 +22,12 @@ // <http://www.gnu.org/licenses/>. // -#include "DevMonitor.h" +#include "os_funcs.h" #include <dbt.h> #include <process.h> #include <string> #include "sapi_context.h" +#include "DevMonitor.h" #include "logging.h" DevMonitor::DevMonitor() Modified: trunk/src/directshow/DevMonitor.h =================================================================== --- trunk/src/directshow/DevMonitor.h 2007-11-20 17:51:57 UTC (rev 64) +++ trunk/src/directshow/DevMonitor.h 2007-11-26 17:59:33 UTC (rev 65) @@ -25,21 +25,8 @@ #ifndef _DEVMONITOR_H_ #define _DEVMONITOR_H_ -#include <windows.h> #include <vidcap/vidcap.h> -// Allow use of features specific to Windows XP or later. -#ifndef _WIN32_WINNT - -// Change this to the appropriate value to target other versions of Windows. -// see: http://msdn2.microsoft.com/en-us/library/aa383745.aspx -#define _WIN32_WINNT 0x0501 - -#endif - -// Exclude rarely-used stuff from Windows headers -#define WIN32_LEAN_AND_MEAN - class DevMonitor { Modified: trunk/src/directshow/DirectShowSource.cpp =================================================================== --- trunk/src/directshow/DirectShowSource.cpp 2007-11-20 17:51:57 UTC (rev 64) +++ trunk/src/directshow/DirectShowSource.cpp 2007-11-26 17:59:33 UTC (rev 65) @@ -22,7 +22,7 @@ // <http://www.gnu.org/licenses/>. // -#include <windows.h> +#include "os_funcs.h" #include <cstring> #include <cstdio> #include <cwchar> @@ -686,6 +686,9 @@ static_cast<double>(fmtNominal->fps_denominator); // check framerate + // TODO: a timer thread could enforce this framerate, + // but would need to pass src_ctx->use_timer_thread here + // to know that if ( fps > fpsMax ) { freeMediaType(*pMediaType); Modified: trunk/src/directshow/SourceStateMachine.cpp =================================================================== --- trunk/src/directshow/SourceStateMachine.cpp 2007-11-20 17:51:57 UTC (rev 64) +++ trunk/src/directshow/SourceStateMachine.cpp 2007-11-26 17:59:33 UTC (rev 65) @@ -22,11 +22,9 @@ // <http://www.gnu.org/licenses/>. // -#include <windows.h> - +#include "sapi.h" #include "hotlist.h" #include "logging.h" -#include "sapi.h" #include "SourceStateMachine.h" SourceStateMachine::SourceStateMachine(struct sapi_src_context *src, Added: trunk/src/double_buffer.c =================================================================== --- trunk/src/double_buffer.c (rev 0) +++ trunk/src/double_buffer.c 2007-11-26 17:59:33 UTC (rev 65) @@ -0,0 +1,200 @@ +/* + * libvidcap - a cross-platform video capture library + * + * Copyright 2007 Wimba, Inc. + * + * Contributors: + * Peter Grayson <jpg...@gm...> + * Bill Cholewka <bc...@gm...> + * + * libvidcap is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * libvidcap is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#include <stdlib.h> +#include <string.h> + +#include "double_buffer.h" + +#include "logging.h" + +/* The write thread inserts (and frees) objects. + * The read thread reads (copies) objects + * + * It is the responsibility of the read thread's 'application' to + * free the copied objects. + * + * If the read thread 'application' blocks for too long (doesn't + * read often enough), the write thread will free a buffered object + * to make room for an incoming object + */ + +/* NOTE: This function is passed function pointers to call when + * necessary to free or copy an object + */ +struct double_buffer * +double_buffer_create( void (*free_me)(void *), void * (*copy_me)(void *) ) +{ + + struct double_buffer * db_buff; + + if ( !free_me || !copy_me ) + return 0; + + db_buff = calloc(1, sizeof(*db_buff)); + + if ( !db_buff ) + { + log_oom(__FILE__, __LINE__); + return 0; + } + + db_buff->read_count = 0; + db_buff->write_count = 0; + db_buff->count[0] = -1; + db_buff->count[1] = -1; + db_buff->objects[0] = 0; + db_buff->objects[1] = 0; + + db_buff->free_object = free_me; + db_buff->copy_object = copy_me; + + vc_mutex_init(&db_buff->locks[0]); + vc_mutex_init(&db_buff->locks[1]); + + /* TODO: remove this (debug) counter */ + db_buff->num_insert_too_far_failures = 0; + + return db_buff; +} + +void +double_buffer_destroy(struct double_buffer * db_buff) +{ + vc_mutex_destroy(&db_buff->locks[1]); + vc_mutex_destroy(&db_buff->locks[0]); + + if ( db_buff->write_count > 0 ) + db_buff->free_object(db_buff->objects[0]); + + if ( db_buff->write_count > 1 ) + db_buff->free_object(db_buff->objects[1]); + + free(db_buff); +} + +void +double_buffer_insert(struct double_buffer * db_buff, void * new_object) +{ + const int insertion_index = db_buff->write_count % 2; + + /* TODO: we could eliminate a copy by having the reader free + * all buffered objects. This would require that a failed + * check below result in the object being freed. This + * would ensure that the reader sees all BUFFERED objects. + * + * The reader would then need to take care to free objects + * as they become outdated. + * + * The tradeoff is the occasional dropped object when + * the writer gets ahead a little. The counter can help + * to evaluate the cost of this tradeoff + */ + /* don't get far ahead of the reader*/ + if ( db_buff->write_count > ( db_buff->read_count + 2 ) ) + { + db_buff->num_insert_too_far_failures++; + /* return; */ + } + + /* get exclusive access to the correct buffer */ + if ( vc_mutex_trylock(&db_buff->locks[insertion_index] )) + { + /* failed to obtain lock */ + /* drop incoming object */ + db_buff->free_object(new_object); + return; + } + + /* free the slot object if something is already there */ + if ( db_buff->write_count > 1 ) + db_buff->free_object(db_buff->objects[insertion_index]); + + /* insert object */ + db_buff->objects[insertion_index] = new_object; + + /* stamp the buffer with the write count */ + db_buff->count[insertion_index] = db_buff->write_count; + + /* advance the write count */ + ++db_buff->write_count; + + /* unlock the correct lock */ + vc_mutex_unlock(&db_buff->locks[insertion_index]); +} + +void * +double_buffer_read(struct double_buffer * db_buff) +{ + int copy_index = 1; + void * buff; + + if ( db_buff->write_count < 1 ) + return 0; + + /* NOTE: Try the newest buffer first + * IF that lock fails THEN try other + */ + if ( db_buff->count[0] > db_buff->count[1] ) + copy_index = 0; + + if ( vc_mutex_trylock(&db_buff->locks[copy_index] ) ) + { + /* failed to obtain lock */ + /* try the other (older) slot? */ + if ( db_buff->write_count < 2 ) + return 0; + + copy_index = 1 - copy_index; + + /* Failed to obtain other lock? */ + /* This should be pretty rare */ + if ( vc_mutex_trylock(&db_buff->locks[copy_index] ) ) + return 0; + } + + /* Is this buffer older than the last-read? + * TODO: could this happen? + */ + if ( db_buff->count[copy_index] < db_buff->read_count ) + { + vc_mutex_unlock(&db_buff->locks[copy_index]); + return 0; + } + + buff = db_buff->copy_object(db_buff->objects[copy_index]); + + db_buff->read_count = db_buff->count[copy_index]; + + vc_mutex_unlock(&db_buff->locks[copy_index]); + + return buff; +} + +int +double_buffer_count(struct double_buffer * db_buff) +{ + return db_buff->write_count; +} Property changes on: trunk/src/double_buffer.c ___________________________________________________________________ Name: svn:executable + * Added: trunk/src/double_buffer.h =================================================================== --- trunk/src/double_buffer.h (rev 0) +++ trunk/src/double_buffer.h 2007-11-26 17:59:33 UTC (rev 65) @@ -0,0 +1,65 @@ +/* + * libvidcap - a cross-platform video capture library + * + * Copyright 2007 Wimba, Inc. + * + * Contributors: + * Peter Grayson <jpg...@gm...> + * Bill Cholewka <bc...@gm...> + * + * libvidcap is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * libvidcap is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#ifndef _DOUBLE_BUFFER_H +#define _DOUBLE_BUFFER_H + +#include "os_funcs.h" + +#define _DOUBLE_MEANS_TWO_ 2 + +struct double_buffer +{ + int read_count; + int write_count; + void * objects[_DOUBLE_MEANS_TWO_]; + vc_mutex locks[_DOUBLE_MEANS_TWO_]; + + int count[_DOUBLE_MEANS_TWO_]; + + void * (*copy_object)(void *); + void (*free_object)(void *); + + /* TODO: remove */ + int num_insert_too_far_failures; +}; + +struct double_buffer * +double_buffer_create( void (*free_obj_func)(void *), + void * (*copy_object)(void *)); + +void +double_buffer_destroy(struct double_buffer * db_buff); + +void +double_buffer_insert(struct double_buffer * db_buff, void * object); + +void * +double_buffer_read(struct double_buffer * db_buff); + +int +double_buffer_count(struct double_buffer * db_buff); + +#endif Property changes on: trunk/src/double_buffer.h ___________________________________________________________________ Name: svn:executable + * Added: trunk/src/os_funcs.h =================================================================== --- trunk/src/os_funcs.h (rev 0) +++ trunk/src/os_funcs.h 2007-11-26 17:59:33 UTC (rev 65) @@ -0,0 +1,219 @@ +/* + * libvidcap - a cross-platform video capture library + * + * Copyright 2007 Wimba, Inc. + * + * Contributors: + * Peter Grayson <jpg...@gm...> + * Bill Cholewka <bc...@gm...> + * + * libvidcap is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * libvidcap is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/>. + * + */ + +#ifndef _OS_FUNCS_H +#define _OS_FUNCS_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#if defined(HAVE_NANOSLEEP) || defined(HAVE_GETTIMEOFDAY) +#include <sys/time.h> +#include <time.h> +#endif + +/* os-dependent macros */ +#if defined(WIN32) || defined(_WIN32_WCE) + +#ifndef _WIN32_WINNT +// Change this to the appropriate value to target other versions of Windows. +// see: http://msdn2.microsoft.com/en-us/library/aa383745.aspx +#define _WIN32_WINNT 0x0500 +#endif + +#include <windows.h> + +#if !defined(_WIN32_WCE) +#include <process.h> +#endif + +#define STDCALL __stdcall +typedef CRITICAL_SECTION vc_mutex; +typedef uintptr_t vc_thread; + +#else + +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <sys/time.h> +#include <pthread.h> + +#define STDCALL +typedef pthread_mutex_t vc_mutex; +typedef pthread_t vc_thread; + +#endif + +#ifdef MACOSX +#include <mach/mach_init.h> +#include <mach/thread_policy.h> +#include <sched.h> +#include <sys/sysctl.h> +#endif + +#ifndef HAVE_GETTIMEOFDAY +static __inline int +gettimeofday(struct timeval * tv, struct timezone * tz) +#ifdef WIN32 +{ + FILETIME ft; + LARGE_INTEGER li; + __int64 t; + static int tzflag; + const __int64 EPOCHFILETIME = 116444736000000000i64; + if ( tv ) + { + GetSystemTimeAsFileTime(&ft); + li.LowPart = ft.dwLowDateTime; + li.HighPart = ft.dwHighDateTime; + t = li.QuadPart; /* In 100-nanosecond intervals */ + t -= EPOCHFILETIME; /* Offset to the Epoch time */ + t /= 10; /* In microseconds */ + tv->tv_sec = (long)(t / 1000000); + tv->tv_usec = (long)(t % 1000000); + } + + return 0; + +#else /* !defined(_WINDOWS) */ + errno = ENOSYS; + return -1; +#endif +} +#endif /* !defined(HAVE_GETTIMEOFDAY) */ + + +static __inline int +vc_create_thread(vc_thread *thread, + unsigned int (STDCALL * thread_func)(void *), + void *args, unsigned int *thread_id) +{ +#ifdef WIN32 + *thread = (uintptr_t)_beginthreadex(NULL, 0, thread_func, + (void *)args, 0, thread_id); + + /* FIXME: log the error */ + if ( thread == 0 ) + return -1; +#else + int ret; + void * (*func)(void *) = (void * (*)(void *))thread_func; + + ret = pthread_create(thread, NULL, func, args); + + /* FIXME: log the error */ + if ( ret ) + return -1; +#endif + + return 0; +} + +static __inline void +vc_thread_join(vc_thread *thread) +{ +#ifdef WIN32 + HANDLE _thread = (HANDLE)thread; + + WaitForSingleObject(_thread, INFINITE); +#else + pthread_t *_thread = (pthread_t *)thread; + + pthread_join(*_thread, 0); +#endif +} + +static __inline void +vc_mutex_init(vc_mutex *m) +{ +#ifdef WIN32 + InitializeCriticalSection(m); +#else + pthread_mutex_init(m, NULL); +#endif +} + +static __inline void +vc_mutex_lock(vc_mutex *m) +{ +#ifdef WIN32 + EnterCriticalSection(m); +#else + pthread_mutex_lock(m); +#endif +} + +static __inline int +vc_mutex_trylock(vc_mutex *m) +{ +#ifdef WIN32 + return !TryEnterCriticalSection(m); +#else + return pthread_mutex_trylock(m); +#endif +} + +static __inline void +vc_mutex_unlock(vc_mutex *m) +{ +#ifdef WIN32 + LeaveCriticalSection(m); +#else + pthread_mutex_unlock(m); +#endif +} + +static __inline void +vc_mutex_destroy(vc_mutex *m) +{ +#ifdef WIN32 + DeleteCriticalSection(m); +#else + pthread_mutex_destroy(m); +#endif +} + +static __inline void +vc_millisleep(long ms) +{ +#ifdef WIN32 + + Sleep(ms); + +#else + + struct timespec req; + + req.tv_nsec = (ms % 1000) * 1000000; + req.tv_sec = ms / 1000; + + nanosleep(&req, NULL); + +#endif +} + +#endif Property changes on: trunk/src/os_funcs.h ___________________________________________________________________ Name: svn:executable + * Modified: trunk/src/sapi.c =================================================================== --- trunk/src/sapi.c 2007-11-20 17:51:57 UTC (rev 64) +++ trunk/src/sapi.c 2007-11-26 17:59:33 UTC (rev 65) @@ -30,36 +30,9 @@ #include "logging.h" #include "sapi.h" -#ifndef HAVE_GETTIMEOFDAY -static __inline int gettimeofday(struct timeval * tv, struct timezone * tz) -#ifdef WIN32 -{ - FILETIME ft; - LARGE_INTEGER li; - __int64 t; - static int tzflag; - const __int64 EPOCHFILETIME = 116444736000000000i64; - if ( tv ) - { - GetSystemTimeAsFileTime(&ft); - li.LowPart = ft.dwLowDateTime; - li.HighPart = ft.dwHighDateTime; - t = li.QuadPart; /* In 100-nanosecond intervals */ - t -= EPOCHFILETIME; /* Offset to the Epoch time */ - t /= 10; /* In microseconds */ - tv->tv_sec = (long)(t / 1000000); - tv->tv_usec = (long)(t % 1000000); - } +static int +deliver_frame(struct sapi_src_context * src_ctx); - return 0; - -#else /* !defined(_WINDOWS) */ - errno = ENOSYS; - return -1; -#endif -} -#endif - static __inline int tv_greater_or_equal(struct timeval * t1, struct timeval * t0) { @@ -76,7 +49,7 @@ } static __inline void -tv_add_usecs(struct timeval *t1, struct timeval *t0, int usecs) +tv_add_usecs(struct timeval *t1, struct timeval *t0, long usecs) { int secs_carried = 0; @@ -216,6 +189,19 @@ return 0; } +static void +wait_for_error_ack(struct sapi_src_context * src_ctx) +{ + while ( !src_ctx->capture_error_ack ) + vc_millisleep(10); +} + +static void +acknowledge_error(struct sapi_src_context * src_ctx) +{ + src_ctx->capture_error_ack = 1; +} + /* NOTE: stride-ignorant sapis should pass a stride of zero */ int sapi_src_capture_notify(struct sapi_src_context * src_ctx, @@ -223,25 +209,121 @@ int stride, int error_status) { - struct vidcap_capture_info cap_info; - /* NOTE: We may be called here by the capture thread while the * main thread is clearing capture_data and capture_callback * from within vidcap_src_capture_stop(). */ + + /* Package the video information */ + struct frame_info * frame = malloc(sizeof(*frame)); + if ( !frame ) + return -1; + + frame->cap_info = malloc(sizeof(struct vidcap_capture_info)); + if ( !frame->cap_info ) + { + free(frame); + return -1; + } + + frame->cap_info->video_data_size = video_data_size; + frame->cap_info->error_status = error_status; + frame->stride = stride; + + if ( src_ctx->use_timer_thread ) + { + /* Copy this buffer. It might not exist long enough for + * read thread (capture timer thread) to copy it + */ + frame->cap_info->video_data = malloc(video_data_size); + if ( !frame->cap_info->video_data ) + { + free(frame->cap_info); + free(frame); + return -1; + } + + memcpy(frame->cap_info->video_data, video_data, video_data_size); + + /* buffer the frame - for processing by the timer thread */ + double_buffer_insert(src_ctx->double_buff, frame); + + /* If there's an error, wait here until it's acknowledged + * by the timer thread (after having delivered it to the app). + */ + if ( error_status ) + wait_for_error_ack(src_ctx); + } + else + { + frame->cap_info->video_data = video_data; + + /* process the frame now */ + src_ctx->no_timer_thread_frame = frame; + deliver_frame(src_ctx); + } + + if ( error_status ) + { + src_ctx->src_state = src_bound; + src_ctx->capture_callback = 0; + src_ctx->capture_data = VIDCAP_INVALID_USER_DATA; + } + + return 0; +} + +static int +deliver_frame(struct sapi_src_context * src_ctx) +{ vidcap_src_capture_callback cap_callback = src_ctx->capture_callback; void * cap_data = src_ctx->capture_data; void * buf = 0; int buf_data_size = 0; - int send_frame = 0; - if ( !error_status ) - send_frame = enforce_framerate(src_ctx); + struct vidcap_capture_info cap_info; - if ( send_frame < 0 ) - error_status = -1000; + struct frame_info * frame; + const char * video_data; + int video_data_size; + int stride; + int error_status; + if ( src_ctx->use_timer_thread ) + { + frame = (struct frame_info *) + double_buffer_read(src_ctx->double_buff); + + if ( !frame ) + return -1; + } + else + { + frame = src_ctx->no_timer_thread_frame; + } + + video_data = frame->cap_info->video_data; + video_data_size = frame->cap_info->video_data_size; + stride = frame->stride; + error_status = frame->cap_info->error_status; + + /* FIXME: right now enforce_framerate() and the capture timer + * thread's main loop BOTH use the frame_time_next field + */ + if ( src_ctx->use_timer_thread ) + { + send_frame = 1; + } + else + { + if ( !error_status ) + send_frame = enforce_framerate(src_ctx); + + if ( send_frame < 0 ) + error_status = -1000; + } + cap_info.error_status = error_status; if ( !cap_info.error_status && stride && @@ -290,22 +372,143 @@ if ( ( send_frame || error_status ) && cap_callback && cap_data != VIDCAP_INVALID_USER_DATA ) { - /* FIXME: Need to check return code. - * Application may want capture to stop + /* FIXME: Need to check return code (and pass it back). + * Application may want capture to stop. + * Ensure we don't perform any more callbacks. */ cap_callback(src_ctx, cap_data, &cap_info); - if ( cap_info.error_status ) + if ( src_ctx->use_timer_thread ) { - src_ctx->src_state = src_bound; - src_ctx->capture_callback = 0; - src_ctx->capture_data = VIDCAP_INVALID_USER_DATA; + /* delete frame */ + free(frame->cap_info->video_data); + free(frame->cap_info); + free(frame); + + if ( error_status ) + { + /* Let capture thread know that the app + * Has received the error status. + * Ensure we don't deliver any more frames. + */ + acknowledge_error(src_ctx); + + /* inform calling function of error */ + return 1; + } } } return 0; } +unsigned int +STDCALL sapi_src_timer_thread_func(void *args) +{ + struct sapi_src_context * src_ctx = args; + struct timeval tv_now; + + /* change to faster rate at capture time, and reduce when capture stopped */ + const long idle_state_sleep_period_ms = 100; + long sleep_ms = idle_state_sleep_period_ms; + int first_time = 1; + const int sleeps_per_capture = 1; + int got_frame = 0; + int ret; + int capture_error = 0; /* FIXME: perhaps should exit on error */ + + src_ctx->timer_thread_idle = 1; + + if ( gettimeofday(&tv_now, 0) ) + { + src_ctx->capture_timer_thread_started = -1; + log_error("gettimeofday not supported\n"); + return -1; + } + + src_ctx->frame_time_next.tv_sec = tv_now.tv_sec; + src_ctx->frame_time_next.tv_usec = tv_now.tv_usec; + + log_info("capture timer thread now running\n"); + src_ctx->capture_timer_thread_started = 1; + + while ( !src_ctx->kill_timer_thread ) + { + gettimeofday(&tv_now, 0); + + /* time to attempt to read a frame? */ + if ( capture_error || src_ctx->src_state != src_capturing || + !tv_greater_or_equal(&tv_now, &src_ctx->frame_time_next) ) + { + if ( src_ctx->src_state != src_capturing ) + { + sleep_ms = idle_state_sleep_period_ms; + first_time = 1; + } + + vc_millisleep(sleep_ms); + } + else + { + src_ctx->timer_thread_idle = 0; + /* FIXME: memory barrier needed? */ + + /* attempt to read and deliver a frame */ + ret = deliver_frame(src_ctx); + + got_frame = !ret; + capture_error = ret > 0; + + /* Is this the first frame? */ + if ( got_frame && first_time ) + { + first_time = 0; + + /* re-initialize when next to check for a frame */ + src_ctx->frame_time_next.tv_sec = tv_now.tv_sec; + src_ctx->frame_time_next.tv_usec = tv_now.tv_usec; + + sleep_ms = (1000 / sleeps_per_capture) * + src_ctx->fmt_nominal.fps_denominator / + src_ctx->fmt_nominal.fps_numerator; + } + + if ( !first_time ) + { + /* update when next to check for a frame */ + /* FIXME: reduce round-off */ + tv_add_usecs(&src_ctx->frame_time_next, &src_ctx->frame_time_next, + 1000000 * + src_ctx->fmt_nominal.fps_denominator / + src_ctx->fmt_nominal.fps_numerator); + } + else + { + /* still no first frame */ + /* update when next to check for a frame */ + tv_add_usecs(&src_ctx->frame_time_next, &tv_now, + 1000000 * + src_ctx->fmt_nominal.fps_denominator / + src_ctx->fmt_nominal.fps_numerator); + } + } + + /* FIXME: memory barrier needed? */ + src_ctx->timer_thread_idle = 1; + } + + log_info("capture timer thread now exiting...\n"); + + return 0; +} + +void +sapi_src_timer_thread_idled(struct sapi_src_context * src_ctx) +{ + while ( !src_ctx->timer_thread_idle ) + vc_millisleep(10); +} + int sapi_can_convert_native_to_nominal(const struct vidcap_fmt_info * fmt_native, const struct vidcap_fmt_info * fmt_nominal) @@ -333,3 +536,4 @@ return 0; } + Modified: trunk/src/sapi_context.h =================================================================== --- trunk/src/sapi_context.h 2007-11-20 17:51:57 UTC (rev 64) +++ trunk/src/sapi_context.h 2007-11-26 17:59:33 UTC (rev 65) @@ -26,26 +26,20 @@ #ifndef _SAPI_CONTEXT_H #define _SAPI_CONTEXT_H -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef WIN32 -#include <windows.h> -#endif - -#if defined(HAVE_NANOSLEEP) || defined(HAVE_GETTIMEOFDAY) -#include <sys/time.h> -#include <time.h> -#endif - #include <vidcap/vidcap.h> +#include "double_buffer.h" #include "sliding_window.h" #include "conv.h" struct sapi_context; +struct frame_info +{ + struct vidcap_capture_info *cap_info; + int stride; +}; + struct sapi_src_context { int (*release)(struct sapi_src_context *); @@ -64,6 +58,7 @@ struct vidcap_src_info src_info; struct sliding_window * frame_times; struct timeval frame_time_next; + struct double_buffer * double_buff; struct vidcap_fmt_info fmt_nominal; struct vidcap_fmt_info fmt_native; @@ -82,6 +77,15 @@ vidcap_src_capture_callback capture_callback; void * capture_data; + int use_timer_thread; + struct frame_info * no_timer_thread_frame; + vc_thread capture_timer_thread; + unsigned int capture_timer_thread_id; + int capture_timer_thread_started; + int timer_thread_idle; + int kill_timer_thread; + int capture_error_ack; + void * priv; }; @@ -124,4 +128,10 @@ void sapi_src_fps_info_clean(struct sapi_src_context *); +void +sapi_src_timer_thread_idled(struct sapi_src_context * src_ctx); + +unsigned int +STDCALL sapi_src_timer_thread_func(void *); + #endif Modified: trunk/src/sapi_dshow.cpp =================================================================== --- trunk/src/sapi_dshow.cpp 2007-11-20 17:51:57 UTC (rev 64) +++ trunk/src/sapi_dshow.cpp 2007-11-26 17:59:33 UTC (rev 65) @@ -22,14 +22,12 @@ // <http://www.gnu.org/licenses/>. // -#include <windows.h> #include <stdio.h> +#include "sapi.h" #include "SourceStateMachine.h" #include "DShowSrcManager.h" - #include "logging.h" -#include "sapi.h" static const char * identifier = "DirectShow"; static const char * description = "DirectShow video capture API"; @@ -177,7 +175,7 @@ return -1; } - if ( src_ctx->priv == 0 ) + if ( src_ctx->priv == (void *)0 ) { log_warn("failed constructing source state machine for '%s'\n", src_info->identifier); Modified: trunk/src/vidcap.c =================================================================== --- trunk/src/vidcap.c 2007-11-20 17:51:57 UTC (rev 64) +++ trunk/src/vidcap.c 2007-11-26 17:59:33 UTC (rev 65) @@ -26,12 +26,6 @@ #include <stdlib.h> #include <string.h> -#include <vidcap/vidcap.h> - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - #include "logging.h" #include "sapi_context.h" #include "sapi.h" @@ -312,6 +306,41 @@ return 0; } + /* TODO: right now we always use the timer thread to enforce + * a very accurate framerate. Alternatively, we could + * allow an application to choose to forego this feature + * and the associated overhead + */ + src_ctx->use_timer_thread = 1; + + if ( src_ctx->use_timer_thread ) + { + src_ctx->kill_timer_thread = 0; + src_ctx->capture_timer_thread_started = 0; + src_ctx->capture_timer_thread = 0; + /* FIXME: memory barrier needed? */ + + if ( vc_create_thread(&src_ctx->capture_timer_thread, + sapi_src_timer_thread_func, src_ctx, + &src_ctx->capture_timer_thread_id) ) + { + src_ctx->capture_timer_thread = 0; + goto bail; + } + + /* ensure thread has started before proceeding */ + while ( !src_ctx->capture_timer_thread_started ) + vc_millisleep(10); + + if ( src_ctx->capture_timer_thread_started < 0 ) + { + log_error("source timer thread failed to start.\n"); + goto bail; + } + + log_info("using a capture timer thread for this source\n"); + } + if ( sapi_ctx->acquire_source(sapi_ctx, src_ctx, src_info) ) { log_error("failed to acquire %s\n", src_info ? @@ -330,6 +359,15 @@ return src_ctx; bail: + /* wait for it to exit (if it exists) */ + if ( src_ctx->use_timer_thread && src_ctx->capture_timer_thread ) + { + /* signal to timer thread to stop */ + src_ctx->kill_timer_thread = 1; + + vc_thread_join(&src_ctx->capture_timer_thread); + } + free(src_ctx); return 0; } @@ -352,6 +390,15 @@ if ( src_ctx->src_state == src_capturing ) return -1; + if ( src_ctx->use_timer_thread && src_ctx->capture_timer_thread ) + { + /* signal timer thread to exit */ + src_ctx->kill_timer_thread = 1; + + /* wait for it to exit */ + vc_thread_join(&src_ctx->capture_timer_thread); + } + ret = src_ctx->release(src_ctx); if ( src_ctx->fmt_list_len ) @@ -499,6 +546,53 @@ return 0; } +void +free_frame_info(void * fr) +{ + struct frame_info *frame = (struct frame_info *)fr; + + /* FIXME: unconstify video_data */ + free(frame->cap_info->video_data); + free(frame->cap_info); + free(frame); +} + +void * +copy_frame_info(void * fr) +{ + struct frame_info *frame = (struct frame_info *)fr; + + struct frame_info *dup_frame = malloc(sizeof(*dup_frame)); + + if ( !dup_frame ) + return 0; + + dup_frame->cap_info = calloc(1, sizeof(*dup_frame->cap_info)); + if ( !dup_frame->cap_info ) + { + free(dup_frame); + return 0; + } + + dup_frame->stride = frame->stride; + dup_frame->cap_info->error_status = frame->cap_info->error_status; + dup_frame->cap_info->video_data_size = frame->cap_info->video_data_size; + dup_frame->cap_info->video_data = malloc(frame->cap_info->video_data_size); + if ( !dup_frame->cap_info->video_data ) + { + free(dup_frame->cap_info); + free(dup_frame); + return 0; + } + + /* FIXME: unconstify cap_info->video_data */ + memcpy(dup_frame->cap_info->video_data, + frame->cap_info->video_data, + frame->cap_info->video_data_size); + + return dup_frame; +} + int vidcap_src_capture_start(vidcap_src * src, vidcap_src_capture_callback callback, @@ -524,6 +618,16 @@ if ( !src_ctx->frame_times ) return -2; + src_ctx->double_buff = double_buffer_create(&free_frame_info, + ©_frame_info); + + if ( !src_ctx->double_buff ) + { + sliding_window_destroy(src_ctx->frame_times); + src_ctx->frame_times = 0; + return -5; + } + src_ctx->capture_callback = callback; src_ctx->capture_data = user_data; @@ -531,6 +635,10 @@ { src_ctx->capture_callback = 0; src_ctx->capture_data = VIDCAP_INVALID_USER_DATA; + + double_buffer_destroy(src_ctx->double_buff); + src_ctx->double_buff = 0; + sliding_window_destroy(src_ctx->frame_times); src_ctx->frame_times = 0; return ret; @@ -551,12 +659,23 @@ ret = src_ctx->stop_capture(src_ctx); + /* signal to timer thread that capture has stopped */ + src_ctx->src_state = src_bound; + + if ( src_ctx->use_timer_thread ) + { + /* FIXME: memory barrier needed? */ + sapi_src_timer_thread_idled(src_ctx); + } + + double_buffer_destroy(src_ctx->double_buff); + src_ctx->double_buff = 0; + sliding_window_destroy(src_ctx->frame_times); + src_ctx->frame_times = 0; - 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. <lib...@li...> - 2007-11-20 17:53:38
|
Revision: 64 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=64&view=rev Author: bcholew Date: 2007-11-20 09:51:57 -0800 (Tue, 20 Nov 2007) Log Message: ----------- Delete sapi dshow's graph monitor thread when destroying the source. Modified Paths: -------------- trunk/src/directshow/DirectShowSource.cpp Modified: trunk/src/directshow/DirectShowSource.cpp =================================================================== --- trunk/src/directshow/DirectShowSource.cpp 2007-11-02 21:13:19 UTC (rev 63) +++ trunk/src/directshow/DirectShowSource.cpp 2007-11-20 17:51:57 UTC (rev 64) @@ -106,6 +106,8 @@ DirectShowSource::~DirectShowSource() { + delete graphMon_; + stop(); if ( nativeMediaType_ ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. <lib...@li...> - 2007-11-02 21:13:23
|
Revision: 63 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=63&view=rev Author: bcholew Date: 2007-11-02 14:13:19 -0700 (Fri, 02 Nov 2007) Log Message: ----------- Don't allow source release while capturing. Flag future fix. Modified Paths: -------------- trunk/src/sapi.c trunk/src/vidcap.c Modified: trunk/src/sapi.c =================================================================== --- trunk/src/sapi.c 2007-11-01 19:05:34 UTC (rev 62) +++ trunk/src/sapi.c 2007-11-02 21:13:19 UTC (rev 63) @@ -287,8 +287,12 @@ cap_info.video_data_size = buf_data_size; } - if ( ( send_frame || error_status ) && cap_callback && cap_data != VIDCAP_INVALID_USER_DATA ) + if ( ( send_frame || error_status ) && cap_callback && + cap_data != VIDCAP_INVALID_USER_DATA ) { + /* FIXME: Need to check return code. + * Application may want capture to stop + */ cap_callback(src_ctx, cap_data, &cap_info); if ( cap_info.error_status ) Modified: trunk/src/vidcap.c =================================================================== --- trunk/src/vidcap.c 2007-11-01 19:05:34 UTC (rev 62) +++ trunk/src/vidcap.c 2007-11-02 21:13:19 UTC (rev 63) @@ -349,6 +349,9 @@ struct sapi_src_context * src_ctx = (struct sapi_src_context *)src; int ret; + if ( src_ctx->src_state == src_capturing ) + return -1; + ret = src_ctx->release(src_ctx); if ( src_ctx->fmt_list_len ) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. <lib...@li...> - 2007-11-01 19:06:29
|
Revision: 62 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=62&view=rev Author: jpgrayson Date: 2007-11-01 12:05:34 -0700 (Thu, 01 Nov 2007) Log Message: ----------- Fix signed/unsigned type conversion warnings. Remove unneeded include. Modified Paths: -------------- trunk/src/conv_to_yuy2.c Modified: trunk/src/conv_to_yuy2.c =================================================================== --- trunk/src/conv_to_yuy2.c 2007-10-31 19:06:55 UTC (rev 61) +++ trunk/src/conv_to_yuy2.c 2007-11-01 19:05:34 UTC (rev 62) @@ -24,7 +24,6 @@ */ #include <vidcap/converters.h> -#include "logging.h" /* NOTE: size of dest buffer must be >= width * height * 2 */ @@ -32,17 +31,15 @@ int vidcap_rgb32_to_yuy2(int width, int height, const char * src, char * dest) { - unsigned char * dst_even, * dst_odd; - const unsigned char * src_even, * src_odd; - int i, j; + const unsigned char * src_even = (const unsigned char *)src; + const unsigned char * src_odd = src_even + width * 4; + unsigned char * dst_even = (unsigned char *)dest; + unsigned char * dst_odd = dst_even + width * 2; + int i; - 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 ) { + int j; for ( j = 0; j < width / 2; ++j ) { /* NOTE: u and v are taken from different src samples */ 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-31 19:07:02
|
Revision: 61 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=61&view=rev Author: bcholew Date: 2007-10-31 12:06:55 -0700 (Wed, 31 Oct 2007) Log Message: ----------- Return failure if a capture start is attempted while previous capture start attempt is still pending. Modified Paths: -------------- trunk/src/directshow/SourceStateMachine.cpp Modified: trunk/src/directshow/SourceStateMachine.cpp =================================================================== --- trunk/src/directshow/SourceStateMachine.cpp 2007-10-31 19:03:04 UTC (rev 60) +++ trunk/src/directshow/SourceStateMachine.cpp 2007-10-31 19:06:55 UTC (rev 61) @@ -291,6 +291,8 @@ break; } + pSrc->okToSendStart_ = true; + pSrc->doCancelCapture(); } else if ( index == startEventIndex ) @@ -340,7 +342,10 @@ SourceStateMachine::start() { if ( !okToSendStart_ ) + { + log_warn("ERROR: Source not ready for a start command\n"); return -1; + } okToSendStart_ = false; 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-31 19:03:11
|
Revision: 60 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=60&view=rev Author: bcholew Date: 2007-10-31 12:03:04 -0700 (Wed, 31 Oct 2007) Log Message: ----------- Return -1 when fail to scan for vidcap devices. Modified Paths: -------------- trunk/src/directshow/DShowSrcManager.cpp Modified: trunk/src/directshow/DShowSrcManager.cpp =================================================================== --- trunk/src/directshow/DShowSrcManager.cpp 2007-10-26 01:58:58 UTC (rev 59) +++ trunk/src/directshow/DShowSrcManager.cpp 2007-10-31 19:03:04 UTC (rev 60) @@ -100,7 +100,7 @@ if ( !pCreateDevEnum ) { log_error("failed creating device enumerator - to scan\n"); - return 0; + return -1; } // Enumerate video capture devices @@ -112,7 +112,7 @@ if ( !pEm ) { log_error("Failed creating enumerator moniker\n"); - return 0; + return -1; } pEm->Reset(); @@ -128,7 +128,7 @@ if ( FAILED(hr) ) { log_error("failed CreateBindCtx\n"); - return 0; + return -1; } IBaseFilter * pCaptureFilter = 0; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: libvidcap c. <lib...@li...> - 2007-10-26 01:58:59
|
Revision: 59 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=59&view=rev Author: jpgrayson Date: 2007-10-25 18:58:58 -0700 (Thu, 25 Oct 2007) Log Message: ----------- Fix a couple stray funny line endings (funny == CR/LF). Modified Paths: -------------- trunk/src/sapi_dshow.cpp Modified: trunk/src/sapi_dshow.cpp =================================================================== --- trunk/src/sapi_dshow.cpp 2007-10-26 01:50:54 UTC (rev 58) +++ trunk/src/sapi_dshow.cpp 2007-10-26 01:58:58 UTC (rev 59) @@ -214,11 +214,11 @@ return -1; } - if ( sapi_ctx->priv == 0 ) - { - log_error("failed constructing DShowSrcManager\n"); - return -1; - } + if ( sapi_ctx->priv == 0 ) + { + log_error("failed constructing DShowSrcManager\n"); + return -1; + } sapi_ctx->identifier = identifier; sapi_ctx->description = description; 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-26 01:50:57
|
Revision: 58 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=58&view=rev Author: jpgrayson Date: 2007-10-25 18:50:54 -0700 (Thu, 25 Oct 2007) Log Message: ----------- Correct the way sapi_v4l deals with source lists. Previously, acquired devices would not show up in the device list, this was bad. Also, acquiring two default devices would yield ill behavior. Added some beefy comments describing the new list management scheme. Modified Paths: -------------- trunk/src/sapi_v4l.c Modified: trunk/src/sapi_v4l.c =================================================================== --- trunk/src/sapi_v4l.c 2007-10-26 01:43:56 UTC (rev 57) +++ trunk/src/sapi_v4l.c 2007-10-26 01:50:54 UTC (rev 58) @@ -44,6 +44,7 @@ enum { device_path_max = 128, + device_num_max = 16, v4l_fps_mask = 0x003f0000, v4l_fps_shift = 16, }; @@ -53,10 +54,13 @@ pthread_mutex_t mutex; pthread_t notify_thread; int notifying; + struct sapi_src_list acquired_src_list; }; struct sapi_v4l_src_context { + struct sapi_v4l_context * v4l_ctx; + int fd; char device_path[device_path_max]; int channel; @@ -188,11 +192,150 @@ return 0; } +#if 0 static void -scan_device_for_sources(const char * device_path, - struct sapi_src_list * src_list, - int * new_list_len) +src_list_debug(const struct sapi_src_list * src_list, const char * name) { + int i; + for ( i = 0; i < src_list->len; ++i ) + log_debug("%10s: %2d: %s\n", name, i, + src_list->list[i].identifier); +} +#endif + +/* Searches src_list starting at index for a vidcap_src_info that + * matches device_path. The source identifier contains the device + * path and the channel. For sapi_v4l's purposes, we do _not_ match + * the channel -- just the device path. + */ +static const struct vidcap_src_info * +src_list_device_match_next(const struct sapi_src_list * src_list, + const char * device_path, int * index) +{ + int i; + + for ( i = *index; i < src_list->len; ++i ) + { + const struct vidcap_src_info * src_info = &src_list->list[i]; + char src_device_path[device_path_max]; + int src_device_channel; + + memset(src_device_path, 0, sizeof(src_device_path)); + + if ( parse_src_identifier(src_info->identifier, + src_device_path, + sizeof(src_device_path), + &src_device_channel) ) + { + log_warn("src_list_device_match_next: invalid src " + "identifier \"%s\"\n", + src_info->identifier); + return 0; + } + + if ( strncmp(src_device_path, device_path, + sizeof(src_device_path)) == 0 ) + { + *index = i + 1; + return src_info; + } + } + + *index = i; + + return 0; +} + +static const struct vidcap_src_info * +src_list_src_match_next(const struct sapi_src_list * src_list, + const struct vidcap_src_info * src_info, int * index) +{ + char device_path[device_path_max]; + int device_channel; + + if ( parse_src_identifier(src_info->identifier, device_path, + sizeof(device_path), &device_channel) ) + { + log_warn("src_list_src_match_next: invalid src " + "identifier \"%s\"\n", + src_info->identifier); + return 0; + } + + return src_list_device_match_next(src_list, device_path, index); +} + +/* The idea here is to find a vidcap_src_info in the src_list that + * matches the src_info parameter. We then remove the matched src_info + * with memmove(). + * + * 0 1 2 3 4 5 + * original list: p q r s t u len=6 + * remove 's': p q r t u u len=5 + */ +static int +src_list_src_remove(struct sapi_src_list * src_list, + const struct vidcap_src_info * src_info) +{ + int match_index = 0; + const struct vidcap_src_info * matched_src_info = + src_list_src_match_next(src_list, src_info, &match_index); + + if ( !matched_src_info ) + return -1; + + memmove(&src_list->list[match_index - 1], + &src_list->list[match_index], + sizeof(*matched_src_info) * + (src_list->len - match_index)); + + src_list->len--; + + return 0; +} + +static int +src_list_src_append(struct sapi_src_list * src_list, + const struct vidcap_src_info * src_info) +{ + src_list->len++; + src_list->list = realloc(src_list->list, + src_list->len * sizeof(*src_info)); + + if ( !src_list->list ) + { + log_oom(__FILE__, __LINE__); + return -1; + } + + memcpy(&src_list->list[src_list->len - 1], src_info, sizeof(*src_info)); + + return 0; +} + +static int +src_list_device_append(struct sapi_src_list * src_list, + const char * device_path, int channel, + const char * device_name, const char * channel_name) +{ + struct vidcap_src_info src_info; + + memset(&src_info, 0, sizeof(src_info)); + + snprintf(src_info.identifier, sizeof(src_info.identifier), + "%s,%d", device_path, channel); + + snprintf(src_info.description, sizeof(src_info.description), + "%s %s", device_name, channel_name); + + return src_list_src_append(src_list, &src_info); +} + +static int +src_list_device_scan(struct sapi_src_list * src_list, + const char * device_path) +{ + int ret = 0; int fd; int i; struct video_capability caps; @@ -200,7 +343,7 @@ fd = open(device_path, O_RDONLY); if ( fd == -1 ) - return; + return 1; /* Ensures file descriptor is closed on exec() */ fcntl(fd, F_SETFD, FD_CLOEXEC); @@ -210,15 +353,18 @@ if ( ioctl(fd, VIDIOCGCAP, &caps) == -1 ) { log_warn("failed to get capabilities for %s\n", device_path); + ret = -1; goto bail; } if ( caps.type != VID_TYPE_CAPTURE ) + { + ret = -1; goto bail; + } for ( i = 0; i < caps.channels; ++i ) { - struct vidcap_src_info * src_info; struct video_channel channel; memset(&channel, 0, sizeof(channel)); @@ -231,18 +377,13 @@ continue; } - *new_list_len += 1; - - if ( *new_list_len > src_list->len ) - src_list->list = realloc(src_list->list, *new_list_len * - sizeof(struct vidcap_src_info)); - - src_info = &src_list->list[*new_list_len - 1]; - - snprintf(src_info->identifier, sizeof(src_info->identifier), - "%s,%d", device_path, channel.channel); - snprintf(src_info->description, sizeof(src_info->description), - "%s %s", caps.name, channel.name); + if ( src_list_device_append(src_list, device_path, + channel.channel, caps.name, + channel.name) ) + { + ret = -1; + goto bail; + } } bail: @@ -250,37 +391,122 @@ if ( close(fd) == -1 ) log_warn("failed to close fd %d for %s (%s)\n", fd, device_path, strerror(errno)); + + return ret; } +/* Generate device path strings of the sequence: + * /dev/video + * /dev/video0 + * /dev/video/0 + * /dev/video1 + * /dev/video/1 + * ... + * /dev/video{device_num_max - 1} + * /dev/video/{device_num_max - 1} + */ static int +device_path_generate(char * device_path, int device_path_len, int * state) +{ + static const char device_prefix[] = "/dev/video"; + const int device_num = (*state - 1) / 2; + + memset(device_path, 0, device_path_len); + + if ( *state == 0 ) + snprintf(device_path, device_path_len, "%s", + device_prefix); + else if ( device_num >= device_num_max ) + return 0; + else if ( *state % 2 ) + snprintf(device_path, device_path_len, "%s%d", + device_prefix, device_num); + else + snprintf(device_path, device_path_len, "%s/%d", + device_prefix, device_num); + + *state += 1; + + return 1; +} + +/* The scanning semantics are a bit tricky. The src_list pointer parameter + * may or may not have anything in it. If we were so inclined, we could + * potentially reuse the memory in src_list->list; however we just free() + * the memory and start over. + * + * One of the tricky bits is that video devices are open()ed exclusively. + * This means that we cannot simply scan with open() and ioctl() calls to + * get the complete device list -- we must also include devices that have + * already been acquired. + * + * To this end, we keep an acquired device list as part of the + * sapi_v4l_context structure. This list must be taken into account and + * managed when we scan, acquire, and release sources. + * + * Complicating matters further is the fact that a single v4l device may + * have multiple "channels". We list each of these channels as a separate + * vidcap source, but we can only capture from a single v4l channel from + * any particular source. We enforce this exclusivity by matching sources + * using the device paths during aquired source list management. + * + * For example, consider this case: + * + * src0 --> /dev/video0 channel 0 + * src1 --> /dev/video0 channel 1 + * src2 --> /dev/video1 channel 0 + * + * If a user acquires src0, this implies that src1 is unavailable, so we + * put both src0 and src1 into the acquired list! Since src2 has a + * different device path, it remains available for acquisition. + */ +static int scan_sources(struct sapi_context * sapi_ctx, struct sapi_src_list * src_list) { - static const char * device_prefix = "/dev/video"; + struct sapi_v4l_context * v4l_ctx = + (struct sapi_v4l_context *)sapi_ctx->priv; char device_path[device_path_max]; - int list_len = 0; - int i; + int generate_index = 0; - snprintf(device_path, sizeof(device_path), "%s", device_prefix); +#if 0 + log_debug("scan_sources start\n"); + src_list_debug(&sapi_ctx->user_src_list, "usr"); + src_list_debug(&v4l_ctx->acquired_src_list, "acq"); +#endif - scan_device_for_sources(device_path, src_list, &list_len); + if ( sapi_ctx->user_src_list.list ) + { + free(sapi_ctx->user_src_list.list); + sapi_ctx->user_src_list.list = 0; + sapi_ctx->user_src_list.len = 0; + } - for ( i = 0; i < 16; ++i ) + while ( device_path_generate(device_path, sizeof(device_path), + &generate_index) ) { - snprintf(device_path, sizeof(device_path), "%s%d", - device_prefix, i); - scan_device_for_sources(device_path, src_list, &list_len); + const struct vidcap_src_info * acquired_src_info = 0; + int match_index = 0; - snprintf(device_path, sizeof(device_path), "%s/%d", - device_prefix, i); - scan_device_for_sources(device_path, src_list, &list_len); + while ( (acquired_src_info = src_list_device_match_next( + &v4l_ctx->acquired_src_list, + device_path, &match_index)) ) + { + if ( src_list_src_append(src_list, + acquired_src_info) ) + return -1; + } + + if ( !acquired_src_info ) + if ( src_list_device_scan(src_list, device_path) < 0 ) + return -1; } - if ( list_len > src_list->len ) - src_list->list = realloc(src_list->list, - list_len * sizeof(struct vidcap_src_info)); +#if 0 + log_debug("scan_sources finish\n"); + src_list_debug(&sapi_ctx->user_src_list, "usr"); + src_list_debug(&v4l_ctx->acquired_src_list, "acq"); +#endif - src_list->len = list_len; - return src_list->len; } @@ -502,7 +728,13 @@ if ( ioctl(v4l_src_ctx->fd, VIDIOCSWIN, &v4l_src_ctx->window) == -1 ) { - log_warn("failed to set v4l window parameters\n"); + log_warn("failed to set v4l window parameters x=%d y=%d " + "w=%d h=%d fl=0x%08x\n", + v4l_src_ctx->window.x, + v4l_src_ctx->window.y, + v4l_src_ctx->window.width, + v4l_src_ctx->window.height, + v4l_src_ctx->window.flags); return -1; } @@ -530,6 +762,11 @@ struct sapi_v4l_src_context * v4l_src_ctx = (struct sapi_v4l_src_context *)src_ctx->priv; + /* Remove all matching sources from the acquired src list */ + while ( !src_list_src_remove(&v4l_src_ctx->v4l_ctx->acquired_src_list, + &src_ctx->src_info) ) + ; + if ( v4l_src_ctx->fd < 0 ) { log_error("invalid fd (%d) for %s\n", v4l_src_ctx->fd, @@ -557,16 +794,58 @@ struct sapi_src_context * src_ctx, const struct vidcap_src_info * src_info) { + struct sapi_v4l_context * v4l_ctx = + (struct sapi_v4l_context *)sapi_ctx->priv; struct sapi_v4l_src_context * v4l_src_ctx = 0; + const struct vidcap_src_info * acquired_src_info; + int match_index; if ( !src_info ) { - if ( scan_sources(sapi_ctx, &sapi_ctx->user_src_list) > 0 ) - src_info = &sapi_ctx->user_src_list.list[0]; - else + int i; + + if ( scan_sources(sapi_ctx, &sapi_ctx->user_src_list) <= 0 ) return -1; + + /* Find the first src_info from user_src_list that is + * not in the acquired list. + */ + for ( i = 0; i < sapi_ctx->user_src_list.len; ++i ) + { + src_info = &sapi_ctx->user_src_list.list[i]; + match_index = 0; + + if ( !src_list_src_match_next( + &v4l_ctx->acquired_src_list, + src_info, &match_index) ) + { + break; + } + else + { + src_info = 0; + } + } + + if ( !src_info ) + { + log_error("failed finding default source to acquire\n"); + return -1; + } } + else + { + match_index = 0; + if ( src_list_src_match_next(&v4l_ctx->acquired_src_list, + src_info, &match_index) ) + { + log_error("source \"%s\" already acquired\n", + src_info->identifier); + return -1; + } + } + memcpy(&src_ctx->src_info, src_info, sizeof(src_ctx->src_info)); v4l_src_ctx = calloc(1, sizeof(*v4l_src_ctx)); @@ -577,6 +856,8 @@ return -1; } + v4l_src_ctx->v4l_ctx = v4l_ctx; + if ( parse_src_identifier(src_info->identifier, v4l_src_ctx->device_path, sizeof(v4l_src_ctx->device_path), @@ -618,6 +899,19 @@ goto bail; } + /* Add all sources with the same device path to the acquired + * source list. + */ + match_index = 0; + while ( (acquired_src_info = src_list_src_match_next( + &sapi_ctx->user_src_list, + src_info, &match_index)) ) + { + if ( src_list_src_append(&v4l_ctx->acquired_src_list, + acquired_src_info) ) + return -1; + } + v4l_src_ctx->capturing = 0; src_ctx->release = source_release; 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-26 01:43:57
|
Revision: 57 http://libvidcap.svn.sourceforge.net/libvidcap/?rev=57&view=rev Author: jpgrayson Date: 2007-10-25 18:43:56 -0700 (Thu, 25 Oct 2007) Log Message: ----------- Add new test to simplegrab that acquires two default sources. Modified Paths: -------------- trunk/examples/simplegrab.c Modified: trunk/examples/simplegrab.c =================================================================== --- trunk/examples/simplegrab.c 2007-10-25 21:25:46 UTC (rev 56) +++ trunk/examples/simplegrab.c 2007-10-26 01:43:56 UTC (rev 57) @@ -52,6 +52,7 @@ static int opt_quiet = 0; static int opt_do_enumeration = 0; static int opt_do_defaults = 0; +static int opt_do_double_default = 0; static int opt_do_captures = 0; static int opt_do_notifies = 0; @@ -221,6 +222,7 @@ { opt_do_enumeration = 1; opt_do_defaults = 1; + opt_do_double_default = 1; opt_do_captures = 1; opt_do_notifies = 1; } @@ -231,6 +233,8 @@ opt_do_enumeration = 1; else if ( !strcmp(argv[i], "-d") ) opt_do_defaults = 1; + else if ( !strcmp(argv[i], "-2") ) + opt_do_double_default = 1; else if ( !strcmp(argv[i], "-c") ) opt_do_captures = 1; else if ( !strcmp(argv[i], "-n") ) @@ -503,6 +507,133 @@ } static int +do_double_defaults() +{ + vidcap_state * vc; + vidcap_sapi * sapi; + vidcap_src * src; + vidcap_src * src2; + + struct vidcap_sapi_info sapi_info; + struct vidcap_src_info src_info; + struct vidcap_src_info src_info2; + struct vidcap_fmt_info fmt_info; + struct vidcap_fmt_info fmt_info2; + + char * fmt_str; + + log_info("Starting defaults\n"); + + if ( !(vc = vidcap_initialize()) ) + { + log_error("failed vidcap_initialize()\n"); + return -1; + } + + if ( !(sapi = vidcap_sapi_acquire(vc, 0)) ) + { + log_error("failed to acquire default sapi\n"); + return -1; + } + + if ( vidcap_sapi_info_get(sapi, &sapi_info) ) + { + log_error("failed to get default sapi info\n"); + return -1; + } + + log_info("sapi default: %s | %s\n", sapi_info.identifier, + sapi_info.description); + + if ( !(src = vidcap_src_acquire(sapi, 0)) ) + { + log_error("failed to acquire default src\n"); + return -1; + } + + if ( vidcap_src_info_get(src, &src_info) ) + { + log_error("failed to get default src info\n"); + return -1; + } + + log_info(" src default: %s | %s\n", src_info.identifier, + src_info.description); + + if ( vidcap_format_bind(src, 0) ) + { + log_error("failed to bind default format\n"); + return -1; + } + + if ( vidcap_format_info_get(src, &fmt_info) ) + { + log_error("failed to get default fmt info\n"); + return -1; + } + + fmt_str = my_fmt_info_str(&fmt_info); + log_info(" fmt default: %s\n", fmt_str); + free(fmt_str); + + /* Acquire a second default (with first still acquired) */ + if ( !(src2 = vidcap_src_acquire(sapi, 0)) ) + { + log_error("failed to acquire default src 2\n"); + return -1; + } + + if ( vidcap_src_info_get(src2, &src_info2) ) + { + log_error("failed to get default src info 2\n"); + return -1; + } + + log_info(" src default 2: %s | %s\n", src_info2.identifier, + src_info2.description); + + if ( vidcap_format_bind(src2, 0) ) + { + log_error("failed to bind default format 2\n"); + return -1; + } + + if ( vidcap_format_info_get(src2, &fmt_info2) ) + { + log_error("failed to get default fmt info 2\n"); + return -1; + } + + fmt_str = my_fmt_info_str(&fmt_info2); + log_info(" fmt default 2: %s\n", fmt_str); + free(fmt_str); + + if ( vidcap_src_release(src) ) + { + log_error("failed to release src\n"); + return -1; + } + + if ( vidcap_src_release(src2) ) + { + log_error("failed to release src 2\n"); + return -1; + } + + if ( vidcap_sapi_release(sapi) ) + { + log_error("failed to release sapi\n"); + return -1; + } + + vidcap_destroy(vc); + + log_info("Finished defaults\n\n"); + + return 0; +} + +static int do_captures() { const int sleep_ms = 10000; @@ -779,6 +910,9 @@ if ( opt_do_defaults && do_defaults() ) return 1; + if ( opt_do_double_default && do_double_defaults() ) + return 1; + if ( opt_do_captures && do_captures() ) return 1; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |