Index: multimedia/obs-studio/Makefile =================================================================== --- multimedia/obs-studio/Makefile +++ multimedia/obs-studio/Makefile @@ -2,6 +2,7 @@ PORTNAME= obs-studio DISTVERSION= 25.0.8 +PORTREVISION= 1 CATEGORIES= multimedia MAINTAINER= yuri@FreeBSD.org @@ -23,7 +24,6 @@ libjack.so:audio/jack \ libjansson.so:devel/jansson \ libmbedtls.so:security/mbedtls \ - libpulse.so:audio/pulseaudio \ libspeexdsp.so:audio/speexdsp \ libsysinfo.so:devel/libsysinfo \ libudev.so:devel/libudev-devd \ @@ -44,6 +44,11 @@ USE_XORG= ice sm x11 xcb xcomposite xext xfixes xinerama xrandr USE_LDCONFIG= yes +OPTIONS_DEFINE= PULSE +OPTIONS_SUB= yes +PULSE_DESC= Build with pulseaudio dependency +PULSE_LIB_DEPENDS= libpulse.so:audio/pulseaudio + CMAKE_ON= UNIX_STRUCTURE CMAKE_ARGS= -DOBS_VERSION_OVERRIDE:STRING="${PORTVERSION}" CFLAGS+= -D_WITH_GETLINE Index: multimedia/obs-studio/files/patch-UI_window-basic-auto-config-test.cpp =================================================================== --- /dev/null +++ multimedia/obs-studio/files/patch-UI_window-basic-auto-config-test.cpp @@ -0,0 +1,28 @@ +--- UI/window-basic-auto-config-test.cpp.orig 2020-04-26 23:47:36 UTC ++++ UI/window-basic-auto-config-test.cpp +@@ -4,6 +4,7 @@ + + #include + #include ++#include + #include + #include + #include +@@ -413,12 +414,14 @@ void AutoConfigTestPage::TestBandwidthThread() + cv.wait(ul); + + uint64_t total_time = os_gettime_ns() - t_start; ++ if (total_time == 0) ++ total_time = 1; + + int total_bytes = + (int)obs_output_get_total_bytes(output) - start_bytes; +- uint64_t bitrate = (uint64_t)total_bytes * 8 * 1000000000 / +- total_time / 1000; +- ++ uint64_t bitrate = util_mul_div64( ++ total_bytes, 8ULL * 1000000000ULL / 1000ULL, ++ total_time); + if (obs_output_get_frames_dropped(output) || + (int)bitrate < (wiz->startingBitrate * 75 / 100)) { + server.bitrate = (int)bitrate * 70 / 100; Index: multimedia/obs-studio/files/patch-UI_window-basic-main.cpp =================================================================== --- multimedia/obs-studio/files/patch-UI_window-basic-main.cpp +++ multimedia/obs-studio/files/patch-UI_window-basic-main.cpp @@ -1,6 +1,6 @@ ---- UI/window-basic-main.cpp.orig 2020-03-19 16:51:06 UTC +--- UI/window-basic-main.cpp.orig 2020-04-26 23:47:36 UTC +++ UI/window-basic-main.cpp -@@ -3207,6 +3207,10 @@ void OBSBasic::TimedCheckForUpdates() +@@ -3214,6 +3214,10 @@ void OBSBasic::TimedCheckForUpdates() void OBSBasic::CheckForUpdates(bool manualUpdate) { Index: multimedia/obs-studio/files/patch-UI_window-basic-preview.cpp =================================================================== --- multimedia/obs-studio/files/patch-UI_window-basic-preview.cpp +++ multimedia/obs-studio/files/patch-UI_window-basic-preview.cpp @@ -1,4 +1,4 @@ ---- UI/window-basic-preview.cpp.orig 2019-09-17 21:29:34 UTC +--- UI/window-basic-preview.cpp.orig 2020-04-26 23:47:36 UTC +++ UI/window-basic-preview.cpp @@ -572,8 +572,8 @@ void OBSBasicPreview::mousePressEvent(QMouseEvent *eve GetStretchHandleData(startPos); @@ -11,7 +11,7 @@ mouseOverItems = SelectedAtPos(startPos); vec2_zero(&lastMoveOffset); -@@ -1159,8 +1159,8 @@ void OBSBasicPreview::ClampAspect(vec3 &tl, vec3 &br, +@@ -1161,8 +1161,8 @@ void OBSBasicPreview::ClampAspect(vec3 &tl, vec3 &br, size.y = size.x / baseAspect * -1.0f; } @@ -22,7 +22,7 @@ if (stretchFlags & ITEM_LEFT) tl.x = br.x - size.x; -@@ -1401,7 +1401,7 @@ void OBSBasicPreview::StretchItem(const vec2 &pos) +@@ -1403,7 +1403,7 @@ void OBSBasicPreview::StretchItem(const vec2 &pos) vec3_transform(&pos3, &pos3, &itemToScreen); vec2 newPos; @@ -31,7 +31,7 @@ obs_sceneitem_set_pos(stretchItem, &newPos); } -@@ -1428,8 +1428,8 @@ void OBSBasicPreview::mouseMoveEvent(QMouseEvent *even +@@ -1430,8 +1430,8 @@ void OBSBasicPreview::mouseMoveEvent(QMouseEvent *even mouseOverItems = SelectedAtPos(startPos); } Index: multimedia/obs-studio/files/patch-cmake_Modules_FindOSS.cmake =================================================================== --- /dev/null +++ multimedia/obs-studio/files/patch-cmake_Modules_FindOSS.cmake @@ -0,0 +1,36 @@ +--- cmake/Modules/FindOSS.cmake.orig 2020-06-01 19:59:40 UTC ++++ cmake/Modules/FindOSS.cmake +@@ -0,0 +1,33 @@ ++# Try to find OSS on a *nix system ++# ++# OSS_FOUND - True if OSS is available ++# OSS_INCLUDE_DIR - Include directory of OSS header ++# OSS_HEADER_NAME - OSS header file name ++# ++ ++IF (CMAKE_SYSTEM_NAME MATCHES "FreeBSD") ++ set(OSS_HEADER_NAME "sys/soundcard.h") ++ELSEIF (CMAKE_SYSTEM_NAME MATCHES "DragonFly") ++ set(OSS_HEADER_NAME "sys/soundcard.h") ++ENDIF() ++ ++find_path(OSS_INCLUDE_DIR "${OSS_HEADER_NAME}" ++ "/usr/include" ++ "/usr/local/include" ++) ++ ++if (OSS_INCLUDE_DIR) ++ set(OSS_FOUND True) ++else (OSS_INCLUDE_DIR) ++ set(OSS_FOUND) ++endif (OSS_INCLUDE_DIR) ++ ++if (OSS_FOUND) ++ message(STATUS "Found OSS header: ${OSS_INCLUDE_DIR}/${OSS_HEADER_NAME}") ++else (OSS_FOUND) ++ if (OSS_FIND_REQUIRED) ++ message(FATAL_ERROR "Could not find OSS header file") ++ endif (OSS_FIND_REQUIRED) ++endif (OSS_FOUND) ++ ++mark_as_advanced(OSS_FOUND OSS_INCLUDE_DIR OSS_HEADER_NAME) Index: multimedia/obs-studio/files/patch-libobs_CMakeLists.txt =================================================================== --- /dev/null +++ multimedia/obs-studio/files/patch-libobs_CMakeLists.txt @@ -0,0 +1,10 @@ +--- libobs/CMakeLists.txt.orig 2020-04-26 23:47:36 UTC ++++ libobs/CMakeLists.txt +@@ -370,6 +370,7 @@ set(libobs_util_HEADERS + util/text-lookup.h + util/bmem.h + util/c99defs.h ++ util/util_uint64.h + util/util_uint128.h + util/cf-parser.h + util/threading.h Index: multimedia/obs-studio/files/patch-libobs_audio-monitoring_win32_wasapi-output.c =================================================================== --- /dev/null +++ multimedia/obs-studio/files/patch-libobs_audio-monitoring_win32_wasapi-output.c @@ -0,0 +1,32 @@ +--- libobs/audio-monitoring/win32/wasapi-output.c.orig 2020-04-26 23:47:36 UTC ++++ libobs/audio-monitoring/win32/wasapi-output.c +@@ -2,6 +2,7 @@ + #include "../../util/circlebuf.h" + #include "../../util/platform.h" + #include "../../util/darray.h" ++#include "../../util/util_uint64.h" + #include "../../obs-internal.h" + + #include "wasapi-output.h" +@@ -78,8 +79,8 @@ static bool process_audio_delay(struct audio_monitor * + monitor->prev_video_ts = last_frame_ts; + + } else if (monitor->prev_video_ts == last_frame_ts) { +- monitor->time_since_prev += (uint64_t)*frames * 1000000000ULL / +- (uint64_t)monitor->sample_rate; ++ monitor->time_since_prev += util_mul_div64( ++ *frames, 1000000000ULL, monitor->sample_rate); + } else { + monitor->time_since_prev = 0; + } +@@ -90,8 +91,8 @@ static bool process_audio_delay(struct audio_monitor * + + circlebuf_peek_front(&monitor->delay_buffer, &cur_ts, + sizeof(ts)); +- front_ts = cur_ts - ((uint64_t)pad * 1000000000ULL / +- (uint64_t)monitor->sample_rate); ++ front_ts = cur_ts - util_mul_div64(pad, 1000000000ULL, ++ monitor->sample_rate); + diff = (int64_t)front_ts - (int64_t)last_frame_ts; + bad_diff = !last_frame_ts || llabs(diff) > 5000000000 || + monitor->time_since_prev > 100000000ULL; Index: multimedia/obs-studio/files/patch-libobs_media-io_audio-io.h =================================================================== --- /dev/null +++ multimedia/obs-studio/files/patch-libobs_media-io_audio-io.h @@ -0,0 +1,32 @@ +--- libobs/media-io/audio-io.h.orig 2020-04-26 23:47:36 UTC ++++ libobs/media-io/audio-io.h +@@ -19,7 +19,7 @@ + + #include "media-io-defs.h" + #include "../util/c99defs.h" +-#include "../util/util_uint128.h" ++#include "../util/util_uint64.h" + + #ifdef __cplusplus + extern "C" { +@@ -195,18 +195,12 @@ static inline size_t get_audio_size(enum audio_format + + static inline uint64_t audio_frames_to_ns(size_t sample_rate, uint64_t frames) + { +- util_uint128_t val; +- val = util_mul64_64(frames, 1000000000ULL); +- val = util_div128_32(val, (uint32_t)sample_rate); +- return val.low; ++ return util_mul_div64(frames, 1000000000ULL, sample_rate); + } + + static inline uint64_t ns_to_audio_frames(size_t sample_rate, uint64_t frames) + { +- util_uint128_t val; +- val = util_mul64_64(frames, sample_rate); +- val = util_div128_32(val, 1000000000); +- return val.low; ++ return util_mul_div64(frames, sample_rate, 1000000000ULL); + } + + #define AUDIO_OUTPUT_SUCCESS 0 Index: multimedia/obs-studio/files/patch-libobs_media-io_audio-io.c =================================================================== --- /dev/null +++ multimedia/obs-studio/files/patch-libobs_media-io_audio-io.c @@ -0,0 +1,23 @@ +--- libobs/media-io/audio-io.c.orig 2020-04-26 23:47:36 UTC ++++ libobs/media-io/audio-io.c +@@ -23,6 +23,7 @@ + #include "../util/circlebuf.h" + #include "../util/platform.h" + #include "../util/profiler.h" ++#include "../util/util_uint64.h" + + #include "audio-io.h" + #include "audio-resampler.h" +@@ -78,11 +79,7 @@ struct audio_output { + + static inline double ts_to_frames(const audio_t *audio, uint64_t ts) + { +- double audio_offset_d = (double)ts; +- audio_offset_d /= 1000000000.0; +- audio_offset_d *= (double)audio->info.samples_per_sec; +- +- return audio_offset_d; ++ return util_mul_div64(ts, audio->info.samples_per_sec, 1000000000ULL); + } + + static inline double positive_round(double val) Index: multimedia/obs-studio/files/patch-libobs_media-io_video-io.c =================================================================== --- /dev/null +++ multimedia/obs-studio/files/patch-libobs_media-io_video-io.c @@ -0,0 +1,21 @@ +--- libobs/media-io/video-io.c.orig 2020-04-26 23:47:36 UTC ++++ libobs/media-io/video-io.c +@@ -22,6 +22,7 @@ + #include "../util/profiler.h" + #include "../util/threading.h" + #include "../util/darray.h" ++#include "../util/util_uint64.h" + + #include "format-conversion.h" + #include "video-io.h" +@@ -234,8 +235,8 @@ int video_output_open(video_t **video, struct video_ou + goto fail; + + memcpy(&out->info, info, sizeof(struct video_output_info)); +- out->frame_time = (uint64_t)(1000000000.0 * (double)info->fps_den / +- (double)info->fps_num); ++ out->frame_time = ++ util_mul_div64(1000000000ULL, info->fps_den, info->fps_num); + out->initialized = false; + + if (pthread_mutexattr_init(&attr) != 0) Index: multimedia/obs-studio/files/patch-libobs_obs-audio.c =================================================================== --- /dev/null +++ multimedia/obs-studio/files/patch-libobs_obs-audio.c @@ -0,0 +1,30 @@ +--- libobs/obs-audio.c.orig 2020-04-26 23:47:36 UTC ++++ libobs/obs-audio.c +@@ -17,6 +17,7 @@ + + #include + #include "obs-internal.h" ++#include "util/util_uint64.h" + + struct ts_info { + uint64_t start; +@@ -41,7 +42,7 @@ static void push_audio_tree(obs_source_t *parent, obs_ + + static inline size_t convert_time_to_frames(size_t sample_rate, uint64_t t) + { +- return (size_t)(t * (uint64_t)sample_rate / 1000000000ULL); ++ return util_mul_div64(t, sample_rate, 1000000000ULL); + } + + static inline void mix_audio(struct audio_output_data *mixes, +@@ -90,8 +91,8 @@ static void ignore_audio(obs_source_t *source, size_t + source->audio_input_buf[ch].size); + + source->last_audio_input_buf_size = 0; +- source->audio_ts += (uint64_t)num_floats * 1000000000ULL / +- (uint64_t)sample_rate; ++ source->audio_ts += ++ util_mul_div64(num_floats, 1000000000ULL, sample_rate); + } + } + Index: multimedia/obs-studio/files/patch-libobs_obs-encoder.c =================================================================== --- /dev/null +++ multimedia/obs-studio/files/patch-libobs_obs-encoder.c @@ -0,0 +1,31 @@ +--- libobs/obs-encoder.c.orig 2020-04-26 23:47:36 UTC ++++ libobs/obs-encoder.c +@@ -17,6 +17,7 @@ + + #include "obs.h" + #include "obs-internal.h" ++#include "util/util_uint64.h" + + #define encoder_active(encoder) os_atomic_load_bool(&encoder->active) + #define set_encoder_active(encoder, val) \ +@@ -1076,8 +1077,7 @@ static inline size_t calc_offset_size(struct obs_encod + uint64_t v_start_ts, uint64_t a_start_ts) + { + uint64_t offset = v_start_ts - a_start_ts; +- offset = (uint64_t)offset * (uint64_t)encoder->samplerate / +- 1000000000ULL; ++ offset = util_mul_div64(offset, encoder->samplerate, 1000000000ULL); + return (size_t)offset * encoder->blocksize; + } + +@@ -1124,8 +1124,8 @@ static bool buffer_audio(struct obs_encoder *encoder, + + /* audio starting point still not synced with video starting + * point, so don't start audio */ +- end_ts += (uint64_t)data->frames * 1000000000ULL / +- (uint64_t)encoder->samplerate; ++ end_ts += util_mul_div64(data->frames, 1000000000ULL, ++ encoder->samplerate); + if (end_ts <= v_start_ts) { + success = false; + goto fail; Index: multimedia/obs-studio/files/patch-libobs_obs-output.c =================================================================== --- /dev/null +++ multimedia/obs-studio/files/patch-libobs_obs-output.c @@ -0,0 +1,31 @@ +--- libobs/obs-output.c.orig 2020-04-26 23:47:36 UTC ++++ libobs/obs-output.c +@@ -17,6 +17,7 @@ + + #include + #include "util/platform.h" ++#include "util/util_uint64.h" + #include "obs.h" + #include "obs-internal.h" + +@@ -1731,8 +1732,8 @@ static bool prepare_audio(struct obs_output *output, + *new = *old; + + if (old->timestamp < output->video_start_ts) { +- uint64_t duration = (uint64_t)old->frames * 1000000000 / +- (uint64_t)output->sample_rate; ++ uint64_t duration = util_mul_div64(old->frames, 1000000000ULL, ++ output->sample_rate); + uint64_t end_ts = (old->timestamp + duration); + uint64_t cutoff; + +@@ -1742,7 +1743,8 @@ static bool prepare_audio(struct obs_output *output, + cutoff = output->video_start_ts - old->timestamp; + new->timestamp += cutoff; + +- cutoff = cutoff * (uint64_t)output->sample_rate / 1000000000; ++ cutoff = util_mul_div64(cutoff, output->sample_rate, ++ 1000000000ULL); + + for (size_t i = 0; i < output->planes; i++) + new->data[i] += output->audio_size *(uint32_t)cutoff; Index: multimedia/obs-studio/files/patch-libobs_obs-scene.c =================================================================== --- /dev/null +++ multimedia/obs-studio/files/patch-libobs_obs-scene.c @@ -0,0 +1,32 @@ +--- libobs/obs-scene.c.orig 2020-04-26 23:47:36 UTC ++++ libobs/obs-scene.c +@@ -17,6 +17,7 @@ + ******************************************************************************/ + + #include "util/threading.h" ++#include "util/util_uint64.h" + #include "graphics/math-defs.h" + #include "obs-scene.h" + +@@ -974,8 +975,8 @@ static void apply_scene_item_audio_actions(struct obs_ + if (timestamp < ts) + timestamp = ts; + +- new_frame_num = (timestamp - ts) * (uint64_t)sample_rate / +- 1000000000ULL; ++ new_frame_num = util_mul_div64(timestamp - ts, sample_rate, ++ 1000000000ULL); + + if (ts && new_frame_num >= AUDIO_OUTPUT_FRAMES) + break; +@@ -1024,8 +1025,8 @@ static bool apply_scene_item_volume(struct obs_scene_i + pthread_mutex_unlock(&item->actions_mutex); + + if (actions_pending) { +- uint64_t duration = (uint64_t)AUDIO_OUTPUT_FRAMES * +- 1000000000ULL / (uint64_t)sample_rate; ++ uint64_t duration = util_mul_div64(AUDIO_OUTPUT_FRAMES, ++ 1000000000ULL, sample_rate); + + if (!ts || action.timestamp < (ts + duration)) { + apply_scene_item_audio_actions(item, buf, ts, Index: multimedia/obs-studio/files/patch-libobs_obs-source-transition.c =================================================================== --- /dev/null +++ multimedia/obs-studio/files/patch-libobs_obs-source-transition.c @@ -0,0 +1,19 @@ +--- libobs/obs-source-transition.c.orig 2020-04-26 23:47:36 UTC ++++ libobs/obs-source-transition.c +@@ -16,6 +16,7 @@ + ******************************************************************************/ + + #include "obs-internal.h" ++#include "util/util_uint64.h" + #include "graphics/math-extra.h" + + #define lock_transition(transition) \ +@@ -866,7 +867,7 @@ static inline float get_sample_time(obs_source_t *tran + uint64_t ts) + { + uint64_t sample_ts_offset = +- (uint64_t)sample * 1000000000ULL / (uint64_t)sample_rate; ++ util_mul_div64(sample, 1000000000ULL, sample_rate); + uint64_t i_ts = ts + sample_ts_offset; + return calc_time(transition, i_ts); + } Index: multimedia/obs-studio/files/patch-libobs_obs-source.c =================================================================== --- /dev/null +++ multimedia/obs-studio/files/patch-libobs_obs-source.c @@ -0,0 +1,35 @@ +--- libobs/obs-source.c.orig 2020-04-26 23:47:36 UTC ++++ libobs/obs-source.c +@@ -23,6 +23,7 @@ + #include "media-io/audio-io.h" + #include "util/threading.h" + #include "util/platform.h" ++#include "util/util_uint64.h" + #include "callback/calldata.h" + #include "graphics/matrix3.h" + #include "graphics/vec3.h" +@@ -1165,13 +1166,13 @@ static inline uint64_t conv_frames_to_time(const size_ + if (!sample_rate) + return 0; + +- return (uint64_t)frames * 1000000000ULL / (uint64_t)sample_rate; ++ return util_mul_div64(frames, 1000000000ULL, sample_rate); + } + + static inline size_t conv_time_to_frames(const size_t sample_rate, + const uint64_t duration) + { +- return (size_t)(duration * (uint64_t)sample_rate / 1000000000ULL); ++ return (size_t)util_mul_div64(duration, sample_rate, 1000000000ULL); + } + + /* maximum buffer size */ +@@ -1235,7 +1236,7 @@ static inline uint64_t uint64_diff(uint64_t ts1, uint6 + static inline size_t get_buf_placement(audio_t *audio, uint64_t offset) + { + uint32_t sample_rate = audio_output_get_sample_rate(audio); +- return (size_t)(offset * (uint64_t)sample_rate / 1000000000ULL); ++ return (size_t)util_mul_div64(offset, sample_rate, 1000000000ULL); + } + + static void source_output_audio_place(obs_source_t *source, Index: multimedia/obs-studio/files/patch-libobs_util_util__uint64.h =================================================================== --- /dev/null +++ multimedia/obs-studio/files/patch-libobs_util_util__uint64.h @@ -0,0 +1,27 @@ +--- libobs/util/util_uint64.h.orig 2020-06-01 20:04:24 UTC ++++ libobs/util/util_uint64.h +@@ -0,0 +1,24 @@ ++/* ++ * Copyright (c) 2020 Hans Petter Selasky ++ * ++ * Permission to use, copy, modify, and distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++#pragma once ++ ++static inline uint64_t util_mul_div64(uint64_t num, uint64_t mul, uint64_t div) ++{ ++ const uint64_t rem = num % div; ++ ++ return (num / div) * mul + (rem * mul) / div; ++} Index: multimedia/obs-studio/files/patch-plugins_decklink_decklink-device-instance.cpp =================================================================== --- /dev/null +++ multimedia/obs-studio/files/patch-plugins_decklink_decklink-device-instance.cpp @@ -0,0 +1,30 @@ +--- plugins/decklink/decklink-device-instance.cpp.orig 2020-04-26 23:47:36 UTC ++++ plugins/decklink/decklink-device-instance.cpp +@@ -6,6 +6,7 @@ + + #include + #include ++#include + + #include + #include +@@ -90,8 +91,8 @@ void DeckLinkDeviceInstance::HandleAudioPacket( + if (decklink && !static_cast(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(decklink)->GetSource(), Index: multimedia/obs-studio/files/patch-plugins_decklink_decklink-output.cpp =================================================================== --- /dev/null +++ multimedia/obs-studio/files/patch-plugins_decklink_decklink-output.cpp @@ -0,0 +1,31 @@ +--- plugins/decklink/decklink-output.cpp.orig 2020-04-26 23:47:36 UTC ++++ plugins/decklink/decklink-output.cpp +@@ -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] += Index: multimedia/obs-studio/files/patch-plugins_linux-alsa_alsa-input.c =================================================================== --- /dev/null +++ multimedia/obs-studio/files/patch-plugins_linux-alsa_alsa-input.c @@ -0,0 +1,22 @@ +--- plugins/linux-alsa/alsa-input.c.orig 2020-04-26 23:47:36 UTC ++++ plugins/linux-alsa/alsa-input.c +@@ -20,6 +20,7 @@ along with this program. If not, see + #include + #include ++#include + #include + + #include +@@ -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; Index: multimedia/obs-studio/files/patch-plugins_linux-pulseaudio_pulse-input.c =================================================================== --- /dev/null +++ multimedia/obs-studio/files/patch-plugins_linux-pulseaudio_pulse-input.c @@ -0,0 +1,19 @@ +--- plugins/linux-pulseaudio/pulse-input.c.orig 2020-04-26 23:47:36 UTC ++++ plugins/linux-pulseaudio/pulse-input.c +@@ -17,6 +17,7 @@ along with this program. If not, see + #include ++#include + #include + + #include "pulse-wrapper.h" +@@ -161,7 +162,7 @@ static pa_channel_map pulse_channel_map(enum speaker_l + + 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) Index: multimedia/obs-studio/files/patch-plugins_obs-filters_async-delay-filter.c =================================================================== --- /dev/null +++ multimedia/obs-studio/files/patch-plugins_obs-filters_async-delay-filter.c @@ -0,0 +1,19 @@ +--- plugins/obs-filters/async-delay-filter.c.orig 2020-04-26 23:47:36 UTC ++++ plugins/obs-filters/async-delay-filter.c +@@ -1,5 +1,6 @@ + #include + #include ++#include + + #ifndef SEC_TO_NSEC + #define SEC_TO_NSEC 1000000000ULL +@@ -199,7 +200,8 @@ async_delay_filter_audio(void *data, struct obs_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++) { Index: multimedia/obs-studio/files/patch-plugins_obs-filters_gpu-delay.c =================================================================== --- /dev/null +++ multimedia/obs-studio/files/patch-plugins_obs-filters_gpu-delay.c @@ -0,0 +1,19 @@ +--- plugins/obs-filters/gpu-delay.c.orig 2020-04-26 23:47:36 UTC ++++ plugins/obs-filters/gpu-delay.c +@@ -1,5 +1,6 @@ + #include + #include ++#include + + #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_fil + + 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); Index: multimedia/obs-studio/files/patch-plugins_oss-audio_CMakeLists.txt =================================================================== --- /dev/null +++ multimedia/obs-studio/files/patch-plugins_oss-audio_CMakeLists.txt @@ -0,0 +1,39 @@ +--- plugins/oss-audio/CMakeLists.txt.orig 2020-06-01 19:59:40 UTC ++++ plugins/oss-audio/CMakeLists.txt +@@ -0,0 +1,36 @@ ++project(oss-audio) ++ ++if(DISABLE_OSS) ++ message(STATUS "OSS support disabled") ++ return() ++endif() ++ ++find_package(OSS) ++if(NOT OSS_FOUND AND ENABLE_OSS) ++ message(FATAL_ERROR "OSS not found but set as enabled") ++elseif(NOT OSS_FOUND) ++ message(STATUS "OSS not found, disabling OSS plugin") ++ return() ++endif() ++ ++configure_file(oss-platform.h.in oss-platform.h) ++ ++include_directories( ++ SYSTEM "${CMAKE_SOURCE_DIR}/libobs" ++ "${OSS_INCLUDE_DIR}" ++ "${CMAKE_CURRENT_BINARY_DIR}" ++) ++ ++set(oss-audio_SOURCES ++ oss-audio.c ++ oss-input.c ++) ++ ++add_library(oss-audio MODULE ++ ${oss-audio_SOURCES} ++) ++target_link_libraries(oss-audio ++ libobs ++) ++ ++install_obs_plugin(oss-audio) Index: multimedia/obs-studio/files/patch-plugins_oss-audio_oss-audio.c =================================================================== --- /dev/null +++ multimedia/obs-studio/files/patch-plugins_oss-audio_oss-audio.c @@ -0,0 +1,36 @@ +--- plugins/oss-audio/oss-audio.c.orig 2020-06-01 19:59:40 UTC ++++ plugins/oss-audio/oss-audio.c +@@ -0,0 +1,33 @@ ++/* ++Copyright (C) 2020. Ka Ho Ng ++ ++This program is free software: you can redistribute it and/or modify ++it under the terms of the GNU General Public License as published by ++the Free Software Foundation, either version 2 of the License, or ++(at your option) any later version. ++ ++This program 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 General Public License for more details. ++ ++You should have received a copy of the GNU General Public License ++along with this program. If not, see . ++*/ ++#include ++ ++OBS_DECLARE_MODULE() ++OBS_MODULE_USE_DEFAULT_LOCALE("oss-audio", "en-US") ++ ++MODULE_EXPORT const char *obs_module_description(void) ++{ ++ return "OSS audio input capture"; ++} ++ ++extern struct obs_source_info oss_input_capture; ++ ++bool obs_module_load(void) ++{ ++ obs_register_source(&oss_input_capture); ++ return true; ++} Index: multimedia/obs-studio/files/patch-plugins_oss-audio_oss-input.c =================================================================== --- /dev/null +++ multimedia/obs-studio/files/patch-plugins_oss-audio_oss-input.c @@ -0,0 +1,679 @@ +--- plugins/oss-audio/oss-input.c.orig 2020-06-01 19:59:40 UTC ++++ plugins/oss-audio/oss-input.c +@@ -0,0 +1,676 @@ ++/* ++Copyright (C) 2020. Ka Ho Ng ++Copyright (C) 2020. Ed Maste ++ ++This program is free software: you can redistribute it and/or modify ++it under the terms of the GNU General Public License as published by ++the Free Software Foundation, either version 2 of the License, or ++(at your option) any later version. ++ ++This program 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 General Public License for more details. ++ ++You should have received a copy of the GNU General Public License ++along with this program. If not, see . ++*/ ++ ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++#include "oss-platform.h" ++ ++#define blog(level, msg, ...) blog(level, "oss-audio: " msg, ##__VA_ARGS__) ++ ++#define NSEC_PER_SEC 1000000000LL ++ ++#define OSS_MAX_CHANNELS 8 ++ ++#define OSS_DSP_DEFAULT "/dev/dsp" ++#define OSS_SNDSTAT_PATH "/dev/sndstat" ++#define OSS_RATE_DEFAULT 48000 ++#define OSS_CHANNELS_DEFAULT 2 ++ ++/** ++ * Control block of plugin instance ++ */ ++struct oss_input_data { ++ obs_source_t *source; ++ ++ char *device; ++ int channels; ++ int rate; ++ int sample_fmt; ++ ++ pthread_t reader_thr; ++ int notify_pipe[2]; ++ ++ int dsp_fd; ++ void *dsp_buf; ++ size_t dsp_fragsize; ++}; ++#define OBS_PROPS_DSP "dsp" ++#define OBS_PROPS_CUSTOM_DSP "custom_dsp" ++#define OBS_PATH_DSP_CUSTOM "/" ++#define OBS_PROPS_CHANNELS "channels" ++#define OBS_PROPS_RATE "rate" ++#define OBS_PROPS_SAMPLE_FMT "sample_fmt" ++ ++/** ++ * Common sampling rate table ++ */ ++struct rate_option { ++ int rate; ++ char *desc; ++} rate_table[] = { ++ {8000, "8000 Hz"}, {11025, "11025 Hz"}, {16000, "16000 Hz"}, ++ {22050, "22050 Hz"}, {32000, "32000 Hz"}, {44100, "44100 Hz"}, ++ {48000, "48000 Hz"}, {96000, "96000 Hz"}, {192000, "192000 Hz"}, ++ {384000, "384000 Hz"}, ++}; ++ ++static unsigned int oss_sample_size(unsigned int sample_fmt) ++{ ++ switch (sample_fmt) { ++ case AFMT_U8: ++ case AFMT_S8: ++ return 8; ++ case AFMT_S16_LE: ++ case AFMT_S16_BE: ++ case AFMT_U16_LE: ++ case AFMT_U16_BE: ++ return 16; ++ case AFMT_S32_LE: ++ case AFMT_S32_BE: ++ case AFMT_U32_LE: ++ case AFMT_U32_BE: ++ case AFMT_S24_LE: ++ case AFMT_S24_BE: ++ case AFMT_U24_LE: ++ case AFMT_U24_BE: ++ return 32; ++ } ++ return 0; ++} ++ ++static size_t oss_calc_framesize(unsigned int channels, unsigned int sample_fmt) ++{ ++ return oss_sample_size(sample_fmt) * channels / 8; ++} ++ ++static enum audio_format oss_fmt_to_obs_audio_format(int fmt) ++{ ++ switch (fmt) { ++ case AFMT_U8: ++ return AUDIO_FORMAT_U8BIT; ++ case AFMT_S16_LE: ++ return AUDIO_FORMAT_16BIT; ++ case AFMT_S32_LE: ++ return AUDIO_FORMAT_32BIT; ++ } ++ ++ return AUDIO_FORMAT_UNKNOWN; ++} ++ ++static enum speaker_layout oss_channels_to_obs_speakers(unsigned int channels) ++{ ++ switch (channels) { ++ case 1: ++ return SPEAKERS_MONO; ++ case 2: ++ return SPEAKERS_STEREO; ++ case 3: ++ return SPEAKERS_2POINT1; ++ case 4: ++ return SPEAKERS_4POINT0; ++ case 5: ++ return SPEAKERS_4POINT1; ++ case 6: ++ return SPEAKERS_5POINT1; ++ case 8: ++ return SPEAKERS_7POINT1; ++ } ++ ++ return SPEAKERS_UNKNOWN; ++} ++ ++static int oss_setup_device(struct oss_input_data *handle) ++{ ++ size_t dsp_fragsize; ++ void *dsp_buf = NULL; ++ int fd = -1, err; ++ audio_buf_info bi; ++ ++ fd = open(handle->device, O_RDONLY); ++ if (fd < 0) { ++ blog(LOG_ERROR, "Failed to open device '%s'.", handle->device); ++ return -1; ++ } ++ int val = handle->channels; ++ err = ioctl(fd, SNDCTL_DSP_CHANNELS, &val); ++ if (err) { ++ blog(LOG_ERROR, "Failed to set number of channels on DSP '%s'.", ++ handle->device); ++ goto failed_state; ++ } ++ val = handle->sample_fmt; ++ err = ioctl(fd, SNDCTL_DSP_SETFMT, &val); ++ if (err) { ++ blog(LOG_ERROR, "Failed to set format on DSP '%s'.", ++ handle->device); ++ goto failed_state; ++ } ++ val = handle->rate; ++ err = ioctl(fd, SNDCTL_DSP_SPEED, &val); ++ if (err) { ++ blog(LOG_ERROR, "Failed to set sample rate on DSP '%s'.", ++ handle->device); ++ goto failed_state; ++ } ++ err = ioctl(fd, SNDCTL_DSP_GETISPACE, &bi); ++ if (err) { ++ blog(LOG_ERROR, "Failed to get fragment size on DSP '%s'.", ++ handle->device); ++ goto failed_state; ++ } ++ ++ dsp_fragsize = bi.fragsize; ++ dsp_buf = bmalloc(dsp_fragsize); ++ if (dsp_buf == NULL) ++ goto failed_state; ++ ++ handle->dsp_buf = dsp_buf; ++ handle->dsp_fragsize = dsp_fragsize; ++ handle->dsp_fd = fd; ++ return 0; ++ ++failed_state: ++ if (fd != -1) ++ close(fd); ++ bfree(dsp_buf); ++ return -1; ++} ++ ++static void oss_close_device(struct oss_input_data *handle) ++{ ++ if (handle->dsp_fd != -1) ++ close(handle->dsp_fd); ++ bfree(handle->dsp_buf); ++ handle->dsp_fd = -1; ++ handle->dsp_buf = NULL; ++ handle->dsp_fragsize = 0; ++} ++ ++static void *oss_reader_thr(void *vptr) ++{ ++ struct oss_input_data *handle = vptr; ++ struct pollfd fds[2] = {0}; ++ size_t framesize; ++ ++ framesize = oss_calc_framesize(handle->channels, handle->sample_fmt); ++ fds[0].fd = handle->dsp_fd; ++ fds[0].events = POLLIN; ++ fds[1].fd = handle->notify_pipe[0]; ++ fds[1].events = POLLIN; ++ ++ assert(handle->dsp_buf); ++ ++ while (poll(fds, 2, INFTIM) >= 0) { ++ if (fds[0].revents & POLLIN) { ++ /* ++ * Incoming audio frames ++ */ ++ ++ struct obs_source_audio out; ++ ssize_t nbytes; ++ ++ do { ++ nbytes = read(handle->dsp_fd, handle->dsp_buf, ++ handle->dsp_fragsize); ++ } while (nbytes < 0 && errno == EINTR); ++ ++ if (nbytes < 0) { ++ blog(LOG_ERROR, ++ "%s: Failed to read buffer on DSP '%s'. Errno %d", ++ __func__, handle->device, errno); ++ break; ++ } else if (!nbytes) { ++ blog(LOG_ERROR, ++ "%s: Unexpected EOF on DSP '%s'.", ++ __func__, handle->device); ++ break; ++ } ++ ++ out.data[0] = handle->dsp_buf; ++ out.format = ++ oss_fmt_to_obs_audio_format(handle->sample_fmt); ++ out.speakers = ++ oss_channels_to_obs_speakers(handle->channels); ++ out.samples_per_sec = handle->rate; ++ out.frames = nbytes / framesize; ++ out.timestamp = ++ os_gettime_ns() - ++ ((out.frames * NSEC_PER_SEC) / handle->rate); ++ obs_source_output_audio(handle->source, &out); ++ } ++ if (fds[1].revents & POLLIN) { ++ char buf; ++ ssize_t nbytes; ++ ++ do { ++ nbytes = read(handle->notify_pipe[0], &buf, 1); ++ assert(nbytes != 0); ++ } while (nbytes < 0 && errno == EINTR); ++ ++ break; ++ } ++ } ++ ++ return NULL; ++} ++ ++static int oss_start_reader(struct oss_input_data *handle) ++{ ++ int pfd[2]; ++ int err; ++ pthread_t thr; ++ ++ err = pipe(pfd); ++ if (err) ++ return -1; ++ ++ err = pthread_create(&thr, NULL, oss_reader_thr, handle); ++ if (err) { ++ close(pfd[0]); ++ close(pfd[1]); ++ return -1; ++ } ++ ++ handle->notify_pipe[0] = pfd[0]; ++ handle->notify_pipe[1] = pfd[1]; ++ handle->reader_thr = thr; ++ return 0; ++} ++ ++static void oss_stop_reader(struct oss_input_data *handle) ++{ ++ if (handle->reader_thr) { ++ char buf = 0x0; ++ ++ write(handle->notify_pipe[1], &buf, 1); ++ pthread_join(handle->reader_thr, NULL); ++ } ++ if (handle->notify_pipe[0] != -1) { ++ close(handle->notify_pipe[0]); ++ close(handle->notify_pipe[1]); ++ } ++ handle->notify_pipe[0] = -1; ++ handle->notify_pipe[1] = -1; ++ handle->reader_thr = NULL; ++} ++ ++/** ++ * Returns the name of the plugin ++ */ ++static const char *oss_getname(void *unused) ++{ ++ UNUSED_PARAMETER(unused); ++ return obs_module_text("OSS Input"); ++} ++ ++/** ++ * Create the plugin object ++ */ ++static void *oss_create(obs_data_t *settings, obs_source_t *source) ++{ ++ const char *dsp; ++ const char *custom_dsp; ++ struct oss_input_data *handle; ++ ++ dsp = obs_data_get_string(settings, OBS_PROPS_DSP); ++ custom_dsp = obs_data_get_string(settings, OBS_PROPS_CUSTOM_DSP); ++ handle = bmalloc(sizeof(struct oss_input_data)); ++ if (handle == NULL) ++ return NULL; ++ ++ handle->source = source; ++ handle->device = NULL; ++ handle->channels = 0; ++ handle->rate = 0; ++ handle->sample_fmt = 0; ++ ++ handle->dsp_buf = NULL; ++ handle->dsp_fragsize = 0; ++ handle->dsp_fd = -1; ++ ++ handle->notify_pipe[0] = -1; ++ handle->notify_pipe[1] = -1; ++ handle->reader_thr = NULL; ++ ++ if (dsp == NULL) ++ return handle; ++ if (!strcmp(dsp, OBS_PATH_DSP_CUSTOM)) { ++ if (custom_dsp == NULL) ++ return handle; ++ ++ handle->device = bstrdup(custom_dsp); ++ } else ++ handle->device = bstrdup(dsp); ++ if (handle->device == NULL) ++ goto failed_state; ++ ++ handle->channels = obs_data_get_int(settings, OBS_PROPS_CHANNELS); ++ handle->rate = obs_data_get_int(settings, OBS_PROPS_RATE); ++ handle->sample_fmt = obs_data_get_int(settings, OBS_PROPS_SAMPLE_FMT); ++ ++ int err = oss_setup_device(handle); ++ if (err) ++ goto failed_state; ++ err = oss_start_reader(handle); ++ if (err) { ++ oss_close_device(handle); ++ goto failed_state; ++ } ++ ++ return handle; ++ ++failed_state: ++ bfree(handle); ++ return NULL; ++} ++ ++/** ++ * Destroy the plugin object and free all memory ++ */ ++static void oss_destroy(void *vptr) ++{ ++ struct oss_input_data *handle = vptr; ++ ++ oss_stop_reader(handle); ++ oss_close_device(handle); ++ bfree(handle->device); ++ bfree(handle); ++} ++ ++/** ++ * Update the input settings ++ */ ++static void oss_update(void *vptr, obs_data_t *settings) ++{ ++ struct oss_input_data *handle = vptr; ++ ++ oss_stop_reader(handle); ++ oss_close_device(handle); ++ ++ const char *dsp = obs_data_get_string(settings, OBS_PROPS_DSP); ++ const char *custom_dsp = ++ obs_data_get_string(settings, OBS_PROPS_CUSTOM_DSP); ++ if (dsp == NULL) { ++ bfree(handle->device); ++ handle->device = NULL; ++ return; ++ } ++ ++ bfree(handle->device); ++ handle->device = NULL; ++ if (!strcmp(dsp, OBS_PATH_DSP_CUSTOM)) { ++ if (custom_dsp == NULL) ++ return; ++ handle->device = bstrdup(custom_dsp); ++ } else ++ handle->device = bstrdup(dsp); ++ if (handle->device == NULL) ++ return; ++ ++ handle->channels = obs_data_get_int(settings, OBS_PROPS_CHANNELS); ++ handle->rate = obs_data_get_int(settings, OBS_PROPS_RATE); ++ handle->sample_fmt = obs_data_get_int(settings, OBS_PROPS_SAMPLE_FMT); ++ ++ int err = oss_setup_device(handle); ++ if (err) { ++ goto failed_state; ++ return; ++ } ++ err = oss_start_reader(handle); ++ if (err) { ++ oss_close_device(handle); ++ goto failed_state; ++ } ++ ++ return; ++ ++failed_state: ++ bfree(handle->device); ++ handle->device = NULL; ++} ++ ++/** ++ * Add audio devices to property ++ */ ++static void oss_prop_add_devices(obs_property_t *p) ++{ ++#if defined(__FreeBSD__) || defined(__DragonFly__) ++ char *line = NULL; ++ size_t linecap = 0; ++ FILE *fp; ++ ++ fp = fopen(OSS_SNDSTAT_PATH, "r"); ++ if (fp == NULL) { ++ blog(LOG_ERROR, "Failed to open sndstat at '%s'.", ++ OSS_SNDSTAT_PATH); ++ return; ++ } ++ ++ while (getline(&line, &linecap, fp) > 0) { ++ int pcm; ++ char *ptr, *pdesc, *descr, *devname, *pmode; ++ ++ if (sscanf(line, "pcm%i: ", &pcm) != 1) ++ continue; ++ if ((ptr = strchr(line, '<')) == NULL) ++ continue; ++ pdesc = ptr + 1; ++ if ((ptr = strrchr(pdesc, '>')) == NULL) ++ continue; ++ *ptr++ = '\0'; ++ if (*ptr++ != ' ' || *ptr++ != '(') ++ continue; ++ pmode = ptr; ++ if ((ptr = strrchr(pmode, ')')) == NULL) ++ continue; ++ *ptr++ = '\0'; ++ if (strcmp(pmode, "rec") != 0 && strcmp(pmode, "play/rec") != 0) ++ continue; ++ if (asprintf(&descr, "pcm%i: %s", pcm, pdesc) == -1) ++ continue; ++ if (asprintf(&devname, "/dev/dsp%i", pcm) == -1) { ++ free(descr); ++ continue; ++ } ++ ++ obs_property_list_add_string(p, descr, devname); ++ ++ free(descr); ++ free(devname); ++ } ++ free(line); ++ ++ fclose(fp); ++#endif /* defined(__FreeBSD__) || defined(__DragonFly__) */ ++} ++ ++/** ++ * Get plugin defaults ++ */ ++static void oss_defaults(obs_data_t *settings) ++{ ++ obs_data_set_default_int(settings, OBS_PROPS_CHANNELS, ++ OSS_CHANNELS_DEFAULT); ++ obs_data_set_default_int(settings, OBS_PROPS_RATE, OSS_RATE_DEFAULT); ++ obs_data_set_default_int(settings, OBS_PROPS_SAMPLE_FMT, AFMT_S16_LE); ++ obs_data_set_default_string(settings, OBS_PROPS_DSP, OSS_DSP_DEFAULT); ++} ++ ++/** ++ * Get plugin properties: ++ * ++ * Fetch the engine information of the corresponding DSP ++ */ ++static bool oss_fill_device_info(obs_property_t *rate, obs_property_t *channels, ++ const char *device) ++{ ++ oss_audioinfo ai; ++ int fd = -1; ++ int err; ++ ++ obs_property_list_clear(rate); ++ obs_property_list_clear(channels); ++ ++ if (!strcmp(device, OBS_PATH_DSP_CUSTOM)) ++ goto cleanup; ++ ++ fd = open(device, O_RDONLY); ++ if (fd < 0) { ++ blog(LOG_ERROR, "Failed to open device '%s'.", device); ++ goto cleanup; ++ } ++ ++ ai.dev = -1; ++ err = ioctl(fd, SNDCTL_ENGINEINFO, &ai); ++ if (err) { ++ blog(LOG_ERROR, ++ "Failed to issue ioctl(SNDCTL_ENGINEINFO) on device '%s'. Errno: %d", ++ device, errno); ++ goto cleanup; ++ } ++ ++ for (int i = ai.min_channels; ++ i <= ai.max_channels && i <= OSS_MAX_CHANNELS; i++) { ++ enum speaker_layout layout = oss_channels_to_obs_speakers(i); ++ ++ if (layout != SPEAKERS_UNKNOWN) { ++ char name[] = "xxx"; ++ snprintf(name, sizeof(name), "%d", i); ++ obs_property_list_add_int(channels, name, i); ++ } ++ } ++ ++ for (size_t i = 0; i < sizeof(rate_table) / sizeof(rate_table[0]); ++ i++) { ++ if (ai.min_rate <= rate_table[i].rate && ++ ai.max_rate >= rate_table[i].rate) ++ obs_property_list_add_int(rate, rate_table[i].desc, ++ rate_table[i].rate); ++ } ++ ++cleanup: ++ if (!obs_property_list_item_count(rate)) ++ obs_property_list_add_int(rate, "48000 Hz", OSS_RATE_DEFAULT); ++ if (!obs_property_list_item_count(channels)) ++ obs_property_list_add_int(channels, "2", OSS_CHANNELS_DEFAULT); ++ if (fd != -1) ++ close(fd); ++ return true; ++} ++ ++/** ++ * Get plugin properties ++ */ ++static bool oss_on_devices_changed(obs_properties_t *props, obs_property_t *p, ++ obs_data_t *settings) ++{ ++ obs_property_t *rate, *channels; ++ obs_property_t *custom_dsp; ++ const char *device; ++ ++ UNUSED_PARAMETER(p); ++ ++ device = obs_data_get_string(settings, OBS_PROPS_DSP); ++ custom_dsp = obs_properties_get(props, OBS_PROPS_CUSTOM_DSP); ++ rate = obs_properties_get(props, OBS_PROPS_RATE); ++ channels = obs_properties_get(props, OBS_PROPS_CHANNELS); ++ ++ if (!strcmp(device, OBS_PATH_DSP_CUSTOM)) ++ obs_property_set_visible(custom_dsp, true); ++ else ++ obs_property_set_visible(custom_dsp, false); ++ oss_fill_device_info(rate, channels, device); ++ obs_property_modified(rate, settings); ++ obs_property_modified(channels, settings); ++ ++ obs_property_modified(custom_dsp, settings); ++ ++ return true; ++} ++ ++/** ++ * Get plugin properties ++ */ ++static obs_properties_t *oss_properties(void *unused) ++{ ++ obs_properties_t *props; ++ obs_property_t *devices; ++ obs_property_t *rate; ++ obs_property_t *sample_fmt; ++ obs_property_t *channels; ++ ++ UNUSED_PARAMETER(unused); ++ ++ props = obs_properties_create(); ++ ++ devices = obs_properties_add_list(props, OBS_PROPS_DSP, ++ obs_module_text("DSP"), ++ OBS_COMBO_TYPE_LIST, ++ OBS_COMBO_FORMAT_STRING); ++ ++ obs_property_list_add_string(devices, "Default", OSS_DSP_DEFAULT); ++ obs_property_list_add_string(devices, "Custom", OBS_PATH_DSP_CUSTOM); ++ obs_property_set_modified_callback(devices, oss_on_devices_changed); ++ ++ obs_properties_add_text(props, OBS_PROPS_CUSTOM_DSP, ++ obs_module_text("Custom DSP Path"), ++ OBS_TEXT_DEFAULT); ++ ++ rate = obs_properties_add_list(props, OBS_PROPS_RATE, ++ obs_module_text("Sample rate"), ++ OBS_COMBO_TYPE_LIST, ++ OBS_COMBO_FORMAT_INT); ++ channels = obs_properties_add_list(props, OBS_PROPS_CHANNELS, ++ obs_module_text("Channels"), ++ OBS_COMBO_TYPE_LIST, ++ OBS_COMBO_FORMAT_INT); ++ oss_fill_device_info(rate, channels, OSS_DSP_DEFAULT); ++ ++ sample_fmt = obs_properties_add_list(props, OBS_PROPS_SAMPLE_FMT, ++ obs_module_text("Sample format"), ++ OBS_COMBO_TYPE_LIST, ++ OBS_COMBO_FORMAT_INT); ++ ++ obs_property_list_add_int(sample_fmt, "pcm8", AFMT_U8); ++ obs_property_list_add_int(sample_fmt, "pcm16le", AFMT_S16_LE); ++ obs_property_list_add_int(sample_fmt, "pcm32le", AFMT_S32_LE); ++ ++ oss_prop_add_devices(devices); ++ ++ return props; ++} ++ ++struct obs_source_info oss_input_capture = { ++ .id = "oss_input_capture", ++ .type = OBS_SOURCE_TYPE_INPUT, ++ .output_flags = OBS_SOURCE_AUDIO, ++ .get_name = oss_getname, ++ .create = oss_create, ++ .destroy = oss_destroy, ++ .update = oss_update, ++ .get_defaults = oss_defaults, ++ .get_properties = oss_properties, ++ .icon_type = OBS_ICON_TYPE_AUDIO_INPUT, ++}; Index: multimedia/obs-studio/files/patch-plugins_oss-audio_oss-platform.h.in =================================================================== --- /dev/null +++ multimedia/obs-studio/files/patch-plugins_oss-audio_oss-platform.h.in @@ -0,0 +1,6 @@ +--- plugins/oss-audio/oss-platform.h.in.orig 2020-06-01 19:59:40 UTC ++++ plugins/oss-audio/oss-platform.h.in +@@ -0,0 +1,3 @@ ++#pragma once ++ ++#include <@OSS_HEADER_NAME@> Index: multimedia/obs-studio/files/patch-plugins_win-capture_game-capture.c =================================================================== --- /dev/null +++ multimedia/obs-studio/files/patch-plugins_win-capture_game-capture.c @@ -0,0 +1,20 @@ +--- plugins/win-capture/game-capture.c.orig 2020-04-26 23:47:36 UTC ++++ plugins/win-capture/game-capture.c +@@ -6,6 +6,7 @@ + #include + #include + #include ++#include + #include + #include "obfuscate.h" + #include "inject-library.h" +@@ -729,7 +730,8 @@ static inline void reset_frame_interval(struct game_ca + 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 Index: multimedia/obs-studio/files/patch-plugins_win-wasapi_win-wasapi.cpp =================================================================== --- /dev/null +++ multimedia/obs-studio/files/patch-plugins_win-wasapi_win-wasapi.cpp @@ -0,0 +1,21 @@ +--- plugins/win-wasapi/win-wasapi.cpp.orig 2020-04-26 23:47:36 UTC ++++ plugins/win-wasapi/win-wasapi.cpp +@@ -8,6 +8,7 @@ + #include + #include + #include ++#include + + 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); + Index: multimedia/obs-studio/files/patch-test_test-input_sync-pair-aud.c =================================================================== --- /dev/null +++ multimedia/obs-studio/files/patch-test_test-input_sync-pair-aud.c @@ -0,0 +1,20 @@ +--- test/test-input/sync-pair-aud.c.orig 2020-04-26 23:47:36 UTC ++++ test/test-input/sync-pair-aud.c +@@ -2,6 +2,7 @@ + #include + #include + #include ++#include + #include + + struct sync_pair_aud { +@@ -54,7 +55,8 @@ static void *sync_pair_aud_thread(void *pdata) + + for (uint64_t i = 0; i < frames; i++) { + uint64_t ts = +- last_time + i * 1000000000ULL / sample_rate; ++ last_time + ++ util_mul_div64(i, 1000000000ULL, sample_rate); + + if (whitelist_time(ts, interval, fps_num, fps_den)) { + cos_val += rate * M_PI_X2; Index: multimedia/obs-studio/pkg-plist =================================================================== --- multimedia/obs-studio/pkg-plist +++ multimedia/obs-studio/pkg-plist @@ -1,6 +1,6 @@ bin/obs bin/obs-ffmpeg-mux -include/obs/audio-monitoring/pulse/pulseaudio-wrapper.h +%%PULSE%%include/obs/audio-monitoring/pulse/pulseaudio-wrapper.h include/obs/callback/calldata.h include/obs/callback/decl.h include/obs/callback/proc.h @@ -105,7 +105,7 @@ lib/obs-plugins/image-source.so lib/obs-plugins/linux-capture.so lib/obs-plugins/linux-jack.so -lib/obs-plugins/linux-pulseaudio.so +%%PULSE%%lib/obs-plugins/linux-pulseaudio.so lib/obs-plugins/linux-v4l2.so lib/obs-plugins/obs-ffmpeg.so lib/obs-plugins/obs-filters.so @@ -336,50 +336,50 @@ share/obs/obs-plugins/linux-jack/locale/vi-VN.ini share/obs/obs-plugins/linux-jack/locale/zh-CN.ini share/obs/obs-plugins/linux-jack/locale/zh-TW.ini -share/obs/obs-plugins/linux-pulseaudio/locale/ar-SA.ini -share/obs/obs-plugins/linux-pulseaudio/locale/bg-BG.ini -share/obs/obs-plugins/linux-pulseaudio/locale/bn-BD.ini -share/obs/obs-plugins/linux-pulseaudio/locale/ca-ES.ini -share/obs/obs-plugins/linux-pulseaudio/locale/cs-CZ.ini -share/obs/obs-plugins/linux-pulseaudio/locale/da-DK.ini -share/obs/obs-plugins/linux-pulseaudio/locale/de-DE.ini -share/obs/obs-plugins/linux-pulseaudio/locale/el-GR.ini -share/obs/obs-plugins/linux-pulseaudio/locale/en-US.ini -share/obs/obs-plugins/linux-pulseaudio/locale/es-ES.ini -share/obs/obs-plugins/linux-pulseaudio/locale/et-EE.ini -share/obs/obs-plugins/linux-pulseaudio/locale/eu-ES.ini -share/obs/obs-plugins/linux-pulseaudio/locale/fa-IR.ini -share/obs/obs-plugins/linux-pulseaudio/locale/fi-FI.ini -share/obs/obs-plugins/linux-pulseaudio/locale/fil-PH.ini -share/obs/obs-plugins/linux-pulseaudio/locale/fr-FR.ini -share/obs/obs-plugins/linux-pulseaudio/locale/gd-GB.ini -share/obs/obs-plugins/linux-pulseaudio/locale/gl-ES.ini -share/obs/obs-plugins/linux-pulseaudio/locale/he-IL.ini -share/obs/obs-plugins/linux-pulseaudio/locale/hi-IN.ini -share/obs/obs-plugins/linux-pulseaudio/locale/hr-HR.ini -share/obs/obs-plugins/linux-pulseaudio/locale/hu-HU.ini -share/obs/obs-plugins/linux-pulseaudio/locale/it-IT.ini -share/obs/obs-plugins/linux-pulseaudio/locale/ja-JP.ini -share/obs/obs-plugins/linux-pulseaudio/locale/ka-GE.ini -share/obs/obs-plugins/linux-pulseaudio/locale/ko-KR.ini -share/obs/obs-plugins/linux-pulseaudio/locale/nb-NO.ini -share/obs/obs-plugins/linux-pulseaudio/locale/nl-NL.ini -share/obs/obs-plugins/linux-pulseaudio/locale/pl-PL.ini -share/obs/obs-plugins/linux-pulseaudio/locale/pt-BR.ini -share/obs/obs-plugins/linux-pulseaudio/locale/pt-PT.ini -share/obs/obs-plugins/linux-pulseaudio/locale/ro-RO.ini -share/obs/obs-plugins/linux-pulseaudio/locale/ru-RU.ini -share/obs/obs-plugins/linux-pulseaudio/locale/sk-SK.ini -share/obs/obs-plugins/linux-pulseaudio/locale/sl-SI.ini -share/obs/obs-plugins/linux-pulseaudio/locale/sr-CS.ini -share/obs/obs-plugins/linux-pulseaudio/locale/sr-SP.ini -share/obs/obs-plugins/linux-pulseaudio/locale/sv-SE.ini -share/obs/obs-plugins/linux-pulseaudio/locale/th-TH.ini -share/obs/obs-plugins/linux-pulseaudio/locale/tr-TR.ini -share/obs/obs-plugins/linux-pulseaudio/locale/uk-UA.ini -share/obs/obs-plugins/linux-pulseaudio/locale/vi-VN.ini -share/obs/obs-plugins/linux-pulseaudio/locale/zh-CN.ini -share/obs/obs-plugins/linux-pulseaudio/locale/zh-TW.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/ar-SA.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/bg-BG.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/bn-BD.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/ca-ES.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/cs-CZ.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/da-DK.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/de-DE.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/el-GR.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/en-US.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/es-ES.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/et-EE.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/eu-ES.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/fa-IR.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/fi-FI.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/fil-PH.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/fr-FR.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/gd-GB.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/gl-ES.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/he-IL.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/hi-IN.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/hr-HR.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/hu-HU.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/it-IT.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/ja-JP.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/ka-GE.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/ko-KR.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/nb-NO.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/nl-NL.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/pl-PL.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/pt-BR.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/pt-PT.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/ro-RO.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/ru-RU.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/sk-SK.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/sl-SI.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/sr-CS.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/sr-SP.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/sv-SE.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/th-TH.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/tr-TR.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/uk-UA.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/vi-VN.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/zh-CN.ini +%%PULSE%%share/obs/obs-plugins/linux-pulseaudio/locale/zh-TW.ini share/obs/obs-plugins/linux-v4l2/locale/ar-SA.ini share/obs/obs-plugins/linux-v4l2/locale/bg-BG.ini share/obs/obs-plugins/linux-v4l2/locale/bn-BD.ini