123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227 |
- #include "precompile.h"
- #include "videoclock.h"
- #define TIMER_RESOLUTION 1
- struct videoclock
- {
- get_frame_cb get_frame;
- put_frame_cb put_frame;
- clockdbg_cb dbglog;
- int fps_num;
- int fps_den;
- void *put_user_data;
- void *get_user_data;
- int frame_width;
- int frame_height;
- int frame_format;
- HANDLE exit_evt;
- HANDLE thread_run;
- volatile int *nVideoSendFreq;
- };
- static void clockDbg(videoclock_t clock, const char* fmt, ...)
- {
-
- va_list arg;
- va_start(arg, fmt);
- if (clock->dbglog) {
- (clock->dbglog)(clock, fmt, arg);
- }
- else {
- int n = _vscprintf(fmt, arg);
- if (n > 0) {
- char* buf = (char*)malloc((size_t)(n + 3));
- vsprintf(buf, fmt, arg);
- strcat(buf, "\r\n");
- printf(buf);
- free(buf);
- }
- }
- va_end(arg);
- }
- static __inline void GetTick(LARGE_INTEGER *last, LARGE_INTEGER *lt)
- {
- DWORD dwNow = GetTickCount();
- if (last->LowPart > dwNow) {
- lt->LowPart = dwNow;
- lt->HighPart = last->HighPart + 1;
- } else {
- lt->LowPart = dwNow;
- lt->HighPart = last->HighPart;
- }
- }
- static unsigned int __stdcall worker_thread_proc(void* param)
- {
- struct videoclock *clock = (struct videoclock*)param;
- video_frame frame;
- LARGE_INTEGER start_tick;
- DWORD dwTimeout = 0;
- LARGE_INTEGER seq = {0};
- LARGE_INTEGER tick = {0};
- SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
-
- if (video_frame_alloc(clock->frame_width, clock->frame_height, clock->frame_format, &frame) != 0)
- goto on_error;
- start_tick.LowPart = GetTickCount();
- start_tick.HighPart = 0;
- seq.LowPart = 1;
- for (;;) {
- DWORD dwRet = WaitForSingleObject(clock->exit_evt, dwTimeout);
- if (dwRet == WAIT_TIMEOUT) {
- clock->get_frame(clock->get_user_data, &frame);
- clock->put_frame(clock->put_user_data, &frame);
- seq.LowPart++;
- if (seq.LowPart == 0) {
- seq.HighPart ++;
- }
- GetTick(&tick, &tick);
- //no support VideoSendFreq(req dynamics fps)
- #if 1
- if (seq.QuadPart * clock->fps_den * 1000 / clock->fps_num < tick.QuadPart - start_tick.QuadPart) {
- dwTimeout = 0;
- } else {
- dwTimeout = (DWORD)(seq.QuadPart * clock->fps_den * 1000 / clock->fps_num - (tick.QuadPart - start_tick.QuadPart));
- }
- #else
- if (*clock->nVideoSendFreq!= 0)
- {
- if (seq.QuadPart * clock->fps_den * 1000 / (*clock->nVideoSendFreq)< tick.QuadPart - start_tick.QuadPart) {
- dwTimeout = 0;
- } else {
- dwTimeout = (DWORD)(seq.QuadPart * clock->fps_den * 1000 / (*clock->nVideoSendFreq)- (tick.QuadPart - start_tick.QuadPart));
- }
- }
- else if(*clock->nVideoSendFreq== -1)
- {
- //暂停发送视频
- dwTimeout = 200000;
- }
- else if(*clock->nVideoSendFreq== 0)
- {
- if (seq.QuadPart * clock->fps_den * 1000 / clock->fps_num < tick.QuadPart - start_tick.QuadPart) {
- dwTimeout = 0;
- } else {
- dwTimeout = (DWORD)(seq.QuadPart * clock->fps_den * 1000 / clock->fps_num - (tick.QuadPart - start_tick.QuadPart));
- }
- }
- #endif
- } else {
- break;
- }
- }
- video_frame_free(&frame);
- on_error:
- _endthreadex(0);
- return 0;
- }
- int videoclock_create(int fps_num,
- int fps_den,
- int video_width,
- int video_height,
- int frame_format,
- put_frame_cb put,
- void *put_user_data,
- get_frame_cb get,
- void *get_user_data,
- videoclock_t *p_clock,
- volatile int*nFps,
- clockdbg_cb dbgfunc)
- {
- struct videoclock *clock;
- /* check ... */
- if (!p_clock)
- return -1;
- if (!put || !get)
- return -1;
- if (frame_format != VIDEO_FORMAT_I420 &&
- frame_format != VIDEO_FORMAT_RGB24)
- return -1;
- if (NULL == dbgfunc) {
- return -1;
- }
- clock = malloc(sizeof(struct videoclock));
- if (!clock)
- return -1;
- memset(clock, 0, sizeof(struct videoclock));
- clock->exit_evt = CreateEvent(NULL, FALSE, FALSE, NULL);
- if (!clock->exit_evt)
- goto on_error;
- clock->fps_num = fps_num;
- clock->nVideoSendFreq = fps_num;
- clock->fps_den = fps_den;
- clock->frame_format = frame_format;
- clock->frame_width = video_width;
- clock->frame_height = video_height;
- clock->get_frame = get;
- clock->get_user_data = get_user_data;
- clock->put_frame = put;
- clock->put_user_data = put_user_data;
- clock->nVideoSendFreq = nFps;
- clock->dbglog = dbgfunc;
- *p_clock = clock;
-
- return 0;
- on_error:
- clockDbg(clock,"videoclock_create failed for %s.", strerror(errno));
- CloseHandle(clock->exit_evt);
- free(clock);
- return -1;
- }
- void videoclock_destroy(videoclock_t vc)
- {
- if (vc) {
- CloseHandle(vc->exit_evt);
- free(vc);
- }
- }
- int videoclock_start(videoclock_t vc)
- {
- if (!vc)
- return -1;
- ResetEvent(vc->exit_evt);
- vc->thread_run = (HANDLE)_beginthreadex(NULL, 0, &worker_thread_proc, vc, 0, NULL);
- if (!vc->thread_run)
- return -1;
-
- return 0;
- }
- int videoclock_stop(videoclock_t vc)
- {
- if (!vc)
- return -1;
- if (vc->exit_evt) {
- SetEvent(vc->exit_evt);
- }
- if (vc->thread_run) {
- WaitForSingleObject(vc->thread_run, INFINITE);
- CloseHandle(vc->thread_run);
- vc->thread_run = NULL;
- }
- return 0;
- }
|