libobs: Implement and use better scaling function for 64-bit integers

As os_gettime_ns() gets large the current scaling methods, mostly by casting
to uint64_t, may lead to numerical overflows. Sweep the code and use
util_mul_div64() where applicable.

Signed-off-by: Hans Petter Selasky <hps@selasky.org>
This commit is contained in:
Hans Petter Selasky
2020-04-05 20:27:28 +02:00
parent 47058d9b69
commit 0e4ea14ba1
22 changed files with 97 additions and 57 deletions
@@ -6,6 +6,7 @@
#include <util/platform.h>
#include <util/threading.h>
#include <util/util_uint64.h>
#include <sstream>
#include <algorithm>
@@ -90,8 +91,8 @@ void DeckLinkDeviceInstance::HandleAudioPacket(
if (decklink && !static_cast<DeckLinkInput *>(decklink)->buffering) {
currentPacket.timestamp = os_gettime_ns();
currentPacket.timestamp -=
(uint64_t)frameCount * 1000000000ULL /
(uint64_t)currentPacket.samples_per_sec;
util_mul_div64(frameCount, 1000000000ULL,
currentPacket.samples_per_sec);
}
int maxdevicechannel = device->GetMaxChannel();
@@ -113,7 +114,7 @@ void DeckLinkDeviceInstance::HandleAudioPacket(
}
nextAudioTS = timestamp +
((uint64_t)frameCount * 1000000000ULL / 48000ULL) + 1;
util_mul_div64(frameCount, 1000000000ULL, 48000ULL) + 1;
obs_source_output_audio(
static_cast<DeckLinkInput *>(decklink)->GetSource(),
+5 -3
View File
@@ -9,6 +9,7 @@
#include "decklink-devices.hpp"
#include "../../libobs/media-io/video-scaler.h"
#include "../../libobs/util/util_uint64.h"
static void decklink_output_destroy(void *data)
{
@@ -127,8 +128,8 @@ static bool prepare_audio(DeckLinkOutput *decklink,
*output = *frame;
if (frame->timestamp < decklink->start_timestamp) {
uint64_t duration = (uint64_t)frame->frames * 1000000000 /
(uint64_t)decklink->audio_samplerate;
uint64_t duration = util_mul_div64(frame->frames, 1000000000ULL,
decklink->audio_samplerate);
uint64_t end_ts = frame->timestamp + duration;
uint64_t cutoff;
@@ -138,7 +139,8 @@ static bool prepare_audio(DeckLinkOutput *decklink,
cutoff = decklink->start_timestamp - frame->timestamp;
output->timestamp += cutoff;
cutoff *= (uint64_t)decklink->audio_samplerate / 1000000000;
cutoff = util_mul_div64(cutoff, decklink->audio_samplerate,
1000000000ULL);
for (size_t i = 0; i < decklink->audio_planes; i++)
output->data[i] +=
+4 -2
View File
@@ -20,6 +20,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <util/bmem.h>
#include <util/platform.h>
#include <util/threading.h>
#include <util/util_uint64.h>
#include <obs-module.h>
#include <alsa/asoundlib.h>
@@ -562,8 +563,9 @@ void *_alsa_listen(void *attr)
}
out.frames = frames;
out.timestamp = os_gettime_ns() -
((frames * NSEC_PER_SEC) / data->rate);
out.timestamp =
os_gettime_ns() -
util_mul_div64(frames, NSEC_PER_SEC, data->rate);
if (!data->first_ts)
data->first_ts = out.timestamp + STARTUP_TIMEOUT_NS;
+2 -1
View File
@@ -17,6 +17,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
#include <util/platform.h>
#include <util/bmem.h>
#include <util/util_uint64.h>
#include <obs-module.h>
#include "pulse-wrapper.h"
@@ -161,7 +162,7 @@ static pa_channel_map pulse_channel_map(enum speaker_layout layout)
static inline uint64_t samples_to_ns(size_t frames, uint_fast32_t rate)
{
return frames * NSEC_PER_SEC / rate;
return util_mul_div64(frames, NSEC_PER_SEC, rate);
}
static inline uint64_t get_sample_time(size_t frames, uint_fast32_t rate)
+3 -1
View File
@@ -1,5 +1,6 @@
#include <obs-module.h>
#include <util/circlebuf.h>
#include <util/util_uint64.h>
#ifndef SEC_TO_NSEC
#define SEC_TO_NSEC 1000000000ULL
@@ -199,7 +200,8 @@ async_delay_filter_audio(void *data, struct obs_audio_data *audio)
filter->last_audio_ts = audio->timestamp;
duration = (uint64_t)audio->frames * SEC_TO_NSEC / filter->samplerate;
duration =
util_mul_div64(audio->frames, SEC_TO_NSEC, filter->samplerate);
end_ts = audio->timestamp + duration;
for (size_t i = 0; i < MAX_AV_PLANES; i++) {
+2 -2
View File
@@ -1,5 +1,6 @@
#include <obs-module.h>
#include <util/circlebuf.h>
#include <util/util_uint64.h>
#define S_DELAY_MS "delay_ms"
#define T_DELAY_MS obs_module_text("DelayMs")
@@ -90,8 +91,7 @@ static inline void check_interval(struct gpu_delay_filter_data *f)
obs_get_video_info(&ovi);
interval_ns =
(uint64_t)ovi.fps_den * 1000000000ULL / (uint64_t)ovi.fps_num;
interval_ns = util_mul_div64(ovi.fps_den, 1000000000ULL, ovi.fps_num);
if (interval_ns != f->interval_ns)
update_interval(f, interval_ns);
+3 -1
View File
@@ -6,6 +6,7 @@
#include <windows.h>
#include <dxgi.h>
#include <util/sse-intrin.h>
#include <util/util_uint64.h>
#include <ipc-util/pipe.h>
#include "obfuscate.h"
#include "inject-library.h"
@@ -729,7 +730,8 @@ static inline void reset_frame_interval(struct game_capture *gc)
uint64_t interval = 0;
if (obs_get_video_info(&ovi)) {
interval = ovi.fps_den * 1000000000ULL / ovi.fps_num;
interval =
util_mul_div64(ovi.fps_den, 1000000000ULL, ovi.fps_num);
/* Always limit capture framerate to some extent. If a game
* running at 900 FPS is being captured without some sort of
+3 -2
View File
@@ -8,6 +8,7 @@
#include <util/windows/WinHandle.hpp>
#include <util/windows/CoTaskMemPtr.hpp>
#include <util/threading.h>
#include <util/util_uint64.h>
using namespace std;
@@ -464,8 +465,8 @@ bool WASAPISource::ProcessCaptureData()
data.timestamp = useDeviceTiming ? ts * 100 : os_gettime_ns();
if (!useDeviceTiming)
data.timestamp -= (uint64_t)frames * 1000000000ULL /
(uint64_t)sampleRate;
data.timestamp -= util_mul_div64(frames, 1000000000ULL,
sampleRate);
obs_source_output_audio(source, &data);