From d77b0558a274e6b06ea700693b5c0468fd1bc799 Mon Sep 17 00:00:00 2001 From: Catxfish Date: Mon, 30 Sep 2019 11:35:00 +0800 Subject: [PATCH] Change virtual source timestamp count behavior --- src/queue/share_queue_read.cpp | 4 ++-- src/virtual-source/clock.cpp | 10 +++++----- src/virtual-source/clock.h | 4 ++-- src/virtual-source/virtual-audio.cpp | 14 +++++++------- src/virtual-source/virtual-audio.h | 4 +--- src/virtual-source/virtual-cam.cpp | 22 +++++++++++++++------- src/virtual-source/virtual-cam.h | 4 +++- 7 files changed, 35 insertions(+), 27 deletions(-) diff --git a/src/queue/share_queue_read.cpp b/src/queue/share_queue_read.cpp index 47a304c..8b84752 100644 --- a/src/queue/share_queue_read.cpp +++ b/src/queue/share_queue_read.cpp @@ -54,10 +54,10 @@ bool share_queue_init_index(share_queue* q) } else if (q->mode == ModeAudio) { int write_index = q->header->write_index; - int delay_frame = q->header->delay_frame; + int delay_frame = max(q->header->delay_frame, 3); int64_t frame_time = q->header->frame_time; int64_t last_ts = q->header->last_ts; - uint64_t start_ts = last_ts - delay_frame*frame_time; + uint64_t start_ts = last_ts - frame_time * delay_frame; int index = write_index; uint64_t frame_ts = 0; diff --git a/src/virtual-source/clock.cpp b/src/virtual-source/clock.cpp index 838dd4c..8089938 100644 --- a/src/virtual-source/clock.cpp +++ b/src/virtual-source/clock.cpp @@ -5,7 +5,7 @@ static LARGE_INTEGER clock_freq; //directshow use 100ns as time unit -uint64_t get_current_time(void) +uint64_t get_current_time(uint64_t start_time) { LARGE_INTEGER current_time; double time_val; @@ -20,18 +20,18 @@ uint64_t get_current_time(void) time_val *= 10000000.0; time_val /= (double)clock_freq.QuadPart; - return (uint64_t)time_val; + return (uint64_t)time_val - start_time; } -bool sleepto(uint64_t time_target) +bool sleepto(uint64_t time_target, uint64_t start_time) { - uint64_t t = get_current_time(); + uint64_t t = get_current_time(start_time); uint32_t milliseconds; if (t >= time_target) return false; milliseconds = (uint32_t)((time_target - t) / 10000); - if (milliseconds > 1) + if (milliseconds > 10) Sleep(milliseconds - 1); } \ No newline at end of file diff --git a/src/virtual-source/clock.h b/src/virtual-source/clock.h index ff97384..0832e03 100644 --- a/src/virtual-source/clock.h +++ b/src/virtual-source/clock.h @@ -1,5 +1,5 @@ #include #include -uint64_t get_current_time(void); -bool sleepto(uint64_t time_target); \ No newline at end of file +uint64_t get_current_time(uint64_t start_time = 0); +bool sleepto(uint64_t time_target, uint64_t start_time); \ No newline at end of file diff --git a/src/virtual-source/virtual-audio.cpp b/src/virtual-source/virtual-audio.cpp index 056487c..e647cfc 100644 --- a/src/virtual-source/virtual-audio.cpp +++ b/src/virtual-source/virtual-audio.cpp @@ -87,17 +87,20 @@ HRESULT CVAudioStream::FillBuffer(IMediaSample *pms) uint32_t size = 0; uint32_t get_times = 0; uint64_t current_time = 0; - uint64_t timestamp = 0; + uint64_t timestamp = 0; REFERENCE_TIME start_time = 0; REFERENCE_TIME end_time = 0; + long a = 0; hr = pms->GetPointer((BYTE**)&dst); - if (system_start_time <= 0) + if (system_start_time <= 0) { system_start_time = get_current_time(); + a = pms->GetActualDataLength(); + } else - current_time = get_current_time() - system_start_time; + current_time = get_current_time(system_start_time); if (!queue.hwnd) shared_queue_open(&queue, ModeAudio); @@ -105,9 +108,6 @@ HRESULT CVAudioStream::FillBuffer(IMediaSample *pms) if (sync_timeout <= 0) { SetTimeout(); } - else if (prev_end_ts >current_time) { - sleepto(prev_end_ts); - } else if (current_time - prev_end_ts > sync_timeout) { if (queue.header) share_queue_init_index(&queue); @@ -149,7 +149,7 @@ HRESULT CVAudioStream::FillBuffer(IMediaSample *pms) dshow_start_ts = 0; } - REFERENCE_TIME duration = (REFERENCE_TIME)10000000 * size / + REFERENCE_TIME duration = (REFERENCE_TIME)UNITS * size / (REFERENCE_TIME)SAMPLE_SIZE; end_time = start_time + duration; prev_end_ts = end_time; diff --git a/src/virtual-source/virtual-audio.h b/src/virtual-source/virtual-audio.h index 8518cd2..364f80a 100644 --- a/src/virtual-source/virtual-audio.h +++ b/src/virtual-source/virtual-audio.h @@ -4,14 +4,12 @@ #define DECLARE_PTR(type, ptr, expr) type* ptr = (type*)(expr); -#define AUDIO_BUFFER_SIZE 5880 +#define AUDIO_BUFFER_SIZE 4096 #define SAMPLE_RATE 44100 #define SAMPLE_SIZE 176400 EXTERN_C const GUID CLSID_OBS_VirtualA; -static void Log(char* msg); - class CVAudioStream; class CVAudio : public CSource, public IAMFilterMiscFlags { diff --git a/src/virtual-source/virtual-cam.cpp b/src/virtual-source/virtual-cam.cpp index 2fcc351..b44e071 100644 --- a/src/virtual-source/virtual-cam.cpp +++ b/src/virtual-source/virtual-cam.cpp @@ -12,6 +12,7 @@ #define MAX_HEIGHT 3072 #define MAX_FRAMETIME 1000000 #define MIN_FRAMETIME 166666 +#define SLEEP_DURATION 5 CUnknown * WINAPI CreateInstance(LPUNKNOWN lpunk, HRESULT *phr) @@ -113,15 +114,21 @@ void CVCamStream::SetConvertContext() scale_info.dst_linesize[0] = pvi->bmiHeader.biWidth * 2; } -void CVCamStream::SetTimeout() +void CVCamStream::SetSyncTimeout() { if (queue.header) { - sync_timeout = queue.header->queue_length * + sync_timeout = queue.header->queue_length * queue.header->frame_time / 100; } else { sync_timeout = 10 * ((VIDEOINFOHEADER*)m_mt.pbFormat)->AvgTimePerFrame; } + +} + +void CVCamStream::SetGetTimeout() +{ + get_timeout = ((VIDEOINFOHEADER*)m_mt.pbFormat)->AvgTimePerFrame * 3 / (SLEEP_DURATION * 10000); } HRESULT CVCamStream::QueryInterface(REFIID riid, void **ppv) @@ -153,7 +160,7 @@ HRESULT CVCamStream::FillBuffer(IMediaSample *pms) if (system_start_time <= 0) system_start_time = get_current_time(); else - current_time = get_current_time() - system_start_time; + current_time = get_current_time(system_start_time); if (!queue.hwnd) { @@ -161,15 +168,16 @@ HRESULT CVCamStream::FillBuffer(IMediaSample *pms) shared_queue_get_video_format(queue_mode, &format, &frame_width, &frame_height, &time_perframe); SetConvertContext(); + SetGetTimeout(); sync_timeout = 0; } } if (sync_timeout <= 0) { - SetTimeout(); + SetSyncTimeout(); } else if (prev_end_ts >current_time) { - sleepto(prev_end_ts); + sleepto(prev_end_ts, system_start_time); } else if (current_time - prev_end_ts > sync_timeout) { if(queue.header) @@ -180,14 +188,14 @@ HRESULT CVCamStream::FillBuffer(IMediaSample *pms) while (queue.header && !get_sample) { - if (get_times > 20 || queue.header->state != OutputReady) + if (get_times >= get_timeout || queue.header->state != OutputReady) break; get_sample = shared_queue_get_video(&queue, &scale_info, dst, ×tamp); if (!get_sample) { - Sleep(5); + Sleep(SLEEP_DURATION); get_times++; } } diff --git a/src/virtual-source/virtual-cam.h b/src/virtual-source/virtual-cam.h index e683c42..bf477d5 100644 --- a/src/virtual-source/virtual-cam.h +++ b/src/virtual-source/virtual-cam.h @@ -108,7 +108,8 @@ class CVCamStream : public CSourceStream, public IAMStreamConfig, public IKsProp bool ListSupportFormat(void); bool CheckObsSetting(void); bool ValidateResolution(long width, long height); - void SetTimeout(); + void SetSyncTimeout(); + void SetGetTimeout(); void SetConvertContext(void); CVCam *parent; @@ -119,6 +120,7 @@ class CVCamStream : public CSourceStream, public IAMStreamConfig, public IKsProp bool reset_mode = false; int queue_mode = 0; int format = 0; + int get_timeout = 20; uint8_t* dst; uint32_t frame_width = 0; uint32_t frame_height = 0;