Skip to content

Commit

Permalink
Remove video capture device with replay buffer
Browse files Browse the repository at this point in the history
  • Loading branch information
exeldro committed Aug 3, 2024
1 parent d393b26 commit f6e2ec3
Show file tree
Hide file tree
Showing 9 changed files with 702 additions and 1,597 deletions.
2 changes: 2 additions & 0 deletions .clang-format
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
BasedOnStyle: InheritParentConfig
ColumnLimit: 132
29 changes: 1 addition & 28 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ else()
cmake_minimum_required(VERSION 3.18)
endif()

project(replay-source VERSION 1.7.0)
project(replay-source VERSION 1.8.0)
set(PROJECT_FULL_NAME "Replay Source")

# Set new UUIDs when you start to create a new plugin.
Expand Down Expand Up @@ -50,33 +50,6 @@ if(OS_WINDOWS)
)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/resource.rc.in ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.rc)
target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/${PROJECT_NAME}.rc)

find_package(FFmpeg REQUIRED COMPONENTS avcodec avutil)
include_directories(${FFMPEG_INCLUDE_DIRS})

find_package(libdshowcapture)
if(OBS_CMAKE_VERSION VERSION_LESS 3.0.0)
find_package(libdshowcapture-external)
endif()
target_sources(${PROJECT_NAME} PRIVATE
win-dshow-replay.cpp
../win-dshow/ffmpeg-decode.c
replay-source.rc
../win-dshow/ffmpeg-decode.h)

target_link_libraries(${PROJECT_NAME}
OBS::w32-pthreads
OBS::libdshowcapture
setupapi
strmiids
ksuser
winmm
wmcodecdspuuid
FFmpeg::avcodec
FFmpeg::avutil)
if(OBS_CMAKE_VERSION VERSION_LESS 3.0.0)
target_link_libraries(${PROJECT_NAME} OBS::libdshowcapture-external)
endif()
elseif(OS_MACOS)
set(MACOS_BUNDLEID "com.exeldro.${PROJECT_NAME}")
set(MACOSX_PLUGIN_GUI_IDENTIFIER "${MACOS_BUNDLEID}")
Expand Down
2 changes: 1 addition & 1 deletion buildspec.json
Original file line number Diff line number Diff line change
Expand Up @@ -80,5 +80,5 @@
}
},
"name": "replay-source",
"version": "1.7.0"
"version": "1.8.0"
}
95 changes: 29 additions & 66 deletions replay-filter-async.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,16 @@ static void replay_filter_update(void *data, obs_data_t *settings)
{
struct replay_filter *filter = data;

const uint64_t new_duration =
(uint64_t)obs_data_get_int(settings, SETTING_DURATION) *
MSEC_TO_NSEC;
const uint64_t new_duration = (uint64_t)obs_data_get_int(settings, SETTING_DURATION) * MSEC_TO_NSEC;

if (new_duration < filter->duration) {
pthread_mutex_lock(&filter->mutex);
free_video_data(filter);
pthread_mutex_unlock(&filter->mutex);
}
filter->duration = new_duration;
filter->internal_frames =
obs_data_get_bool(settings, SETTING_INTERNAL_FRAMES);
const double db =
obs_data_get_double(settings, SETTING_AUDIO_THRESHOLD);
filter->internal_frames = obs_data_get_bool(settings, SETTING_INTERNAL_FRAMES);
const double db = obs_data_get_double(settings, SETTING_AUDIO_THRESHOLD);
filter->threshold = db_to_mul((float)db);
}

Expand Down Expand Up @@ -77,90 +73,65 @@ struct async_frame {
bool used;
};

static struct obs_source_frame *
replay_filter_video(void *data, struct obs_source_frame *frame)
static struct obs_source_frame *replay_filter_video(void *data, struct obs_source_frame *frame)
{
struct replay_filter *filter = data;
struct obs_source_frame *output;

uint64_t last_timestamp = 0;

obs_source_t *target = filter->internal_frames
? obs_filter_get_parent(filter->src)
: NULL;
obs_source_t *target = filter->internal_frames ? obs_filter_get_parent(filter->src) : NULL;
const uint64_t os_time = obs_get_video_frame_time();
struct obs_source_frame *new_frame = NULL;

pthread_mutex_lock(&filter->mutex);
if (filter->video_frames.size) {
circlebuf_peek_back(&filter->video_frames, &output,
sizeof(struct obs_source_frame *));
circlebuf_peek_back(&filter->video_frames, &output, sizeof(struct obs_source_frame *));
last_timestamp = output->timestamp;
}
if (target) {
if (filter->target_offset == 0) {
if (obs_get_version() <
MAKE_SEMANTIC_VERSION(30, 0, 0)) {
if (obs_get_version() < MAKE_SEMANTIC_VERSION(30, 0, 0)) {
filter->target_offset = 2000;
} else if (obs_get_version() <
MAKE_SEMANTIC_VERSION(30, 2, 0)) {
} else if (obs_get_version() < MAKE_SEMANTIC_VERSION(30, 2, 0)) {
filter->target_offset = 2008;
} else {
filter->target_offset = 2000;
}
}
struct darray *async_cache =
(struct darray *)((uint8_t *)target +
filter->target_offset);
struct darray *async_cache = (struct darray *)((uint8_t *)target + filter->target_offset);
pthread_mutex_t *async_mutex =
(pthread_mutex_t *)((uint8_t *)target +
filter->target_offset +
sizeof(struct darray) * 2);
(pthread_mutex_t *)((uint8_t *)target + filter->target_offset + sizeof(struct darray) * 2);
pthread_mutex_lock(async_mutex);
for (size_t i = 0; i < async_cache->num; i++) {
struct obs_source_frame *extra_frame =
((struct async_frame *)async_cache->array)[i]
.frame;
if (extra_frame->timestamp + filter->timing_adjust >
last_timestamp) {
new_frame = obs_source_frame_create(
extra_frame->format, extra_frame->width,
extra_frame->height);
struct obs_source_frame *extra_frame = ((struct async_frame *)async_cache->array)[i].frame;
if (extra_frame->timestamp + filter->timing_adjust > last_timestamp) {
new_frame = obs_source_frame_create(extra_frame->format, extra_frame->width, extra_frame->height);
new_frame->refs = 1;
obs_source_frame_copy(new_frame, extra_frame);
const uint64_t timestamp =
extra_frame->timestamp;
uint64_t adjusted_time =
timestamp + filter->timing_adjust;
if (filter->timing_adjust &&
uint64_diff(os_time, timestamp) <
MAX_TS_VAR) {
const uint64_t timestamp = extra_frame->timestamp;
uint64_t adjusted_time = timestamp + filter->timing_adjust;
if (filter->timing_adjust && uint64_diff(os_time, timestamp) < MAX_TS_VAR) {
adjusted_time = timestamp;
filter->timing_adjust = 0;
} else if (uint64_diff(os_time, adjusted_time) >
MAX_TS_VAR) {
filter->timing_adjust =
os_time - timestamp;
} else if (uint64_diff(os_time, adjusted_time) > MAX_TS_VAR) {
filter->timing_adjust = os_time - timestamp;
adjusted_time = os_time;
}
new_frame->timestamp = adjusted_time;
last_timestamp = adjusted_time;
circlebuf_push_back(
&filter->video_frames, &new_frame,
sizeof(struct obs_source_frame *));
circlebuf_push_back(&filter->video_frames, &new_frame, sizeof(struct obs_source_frame *));
}
}
pthread_mutex_unlock(async_mutex);
}
if (frame->timestamp + filter->timing_adjust > last_timestamp) {
new_frame = obs_source_frame_create(frame->format, frame->width,
frame->height);
new_frame = obs_source_frame_create(frame->format, frame->width, frame->height);
new_frame->refs = 1;
obs_source_frame_copy(new_frame, frame);
const uint64_t timestamp = frame->timestamp;
uint64_t adjusted_time = timestamp + filter->timing_adjust;
if (filter->timing_adjust &&
uint64_diff(os_time, timestamp) < MAX_TS_VAR) {
if (filter->timing_adjust && uint64_diff(os_time, timestamp) < MAX_TS_VAR) {
adjusted_time = timestamp;
filter->timing_adjust = 0;
} else if (uint64_diff(os_time, adjusted_time) > MAX_TS_VAR) {
Expand All @@ -169,29 +140,25 @@ replay_filter_video(void *data, struct obs_source_frame *frame)
}
new_frame->timestamp = adjusted_time;
last_timestamp = adjusted_time;
circlebuf_push_back(&filter->video_frames, &new_frame,
sizeof(struct obs_source_frame *));
circlebuf_push_back(&filter->video_frames, &new_frame, sizeof(struct obs_source_frame *));
}
if (!last_timestamp) {
pthread_mutex_unlock(&filter->mutex);
return frame;
}
circlebuf_peek_front(&filter->video_frames, &output,
sizeof(struct obs_source_frame *));
circlebuf_peek_front(&filter->video_frames, &output, sizeof(struct obs_source_frame *));

uint64_t cur_duration = last_timestamp - output->timestamp;
while (cur_duration > 0 && cur_duration > filter->duration) {

circlebuf_pop_front(&filter->video_frames, NULL,
sizeof(struct obs_source_frame *));
circlebuf_pop_front(&filter->video_frames, NULL, sizeof(struct obs_source_frame *));

if (os_atomic_dec_long(&output->refs) <= 0) {
obs_source_frame_destroy(output);
output = NULL;
}
if (filter->video_frames.size) {
circlebuf_peek_front(&filter->video_frames, &output,
sizeof(struct obs_source_frame *));
circlebuf_peek_front(&filter->video_frames, &output, sizeof(struct obs_source_frame *));
cur_duration = last_timestamp - output->timestamp;
} else {
cur_duration = 0;
Expand All @@ -207,15 +174,11 @@ static obs_properties_t *replay_filter_properties(void *unused)

obs_properties_t *props = obs_properties_create();

obs_property_t *prop = obs_properties_add_int(
props, SETTING_DURATION, obs_module_text("Duration"),
SETTING_DURATION_MIN, SETTING_DURATION_MAX, 1000);
obs_property_t *prop = obs_properties_add_int(props, SETTING_DURATION, obs_module_text("Duration"), SETTING_DURATION_MIN,
SETTING_DURATION_MAX, 1000);
obs_property_int_set_suffix(prop, "ms");
obs_properties_add_bool(props, SETTING_INTERNAL_FRAMES,
obs_module_text("CaptureInternalFrames"));
obs_properties_add_float_slider(props, SETTING_AUDIO_THRESHOLD,
obs_module_text("ThresholdDb"),
SETTING_AUDIO_THRESHOLD_MIN,
obs_properties_add_bool(props, SETTING_INTERNAL_FRAMES, obs_module_text("CaptureInternalFrames"));
obs_properties_add_float_slider(props, SETTING_AUDIO_THRESHOLD, obs_module_text("ThresholdDb"), SETTING_AUDIO_THRESHOLD_MIN,
SETTING_AUDIO_THRESHOLD_MAX, 0.1);

return props;
Expand Down
16 changes: 5 additions & 11 deletions replay-filter-audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,13 @@ static void replay_filter_update(void *data, obs_data_t *settings)
{
struct replay_filter *filter = data;

const uint64_t new_duration =
(uint64_t)obs_data_get_int(settings, SETTING_DURATION) *
MSEC_TO_NSEC;
const uint64_t new_duration = (uint64_t)obs_data_get_int(settings, SETTING_DURATION) * MSEC_TO_NSEC;

if (new_duration < filter->duration)
free_video_data(filter);

filter->duration = new_duration;
const double db =
obs_data_get_double(settings, SETTING_AUDIO_THRESHOLD);
const double db = obs_data_get_double(settings, SETTING_AUDIO_THRESHOLD);
filter->threshold = db_to_mul((float)db);
}

Expand Down Expand Up @@ -72,13 +69,10 @@ static obs_properties_t *replay_filter_properties(void *unused)

obs_properties_t *props = obs_properties_create();

obs_property_t *prop = obs_properties_add_int(
props, SETTING_DURATION, obs_module_text("Duration"),
SETTING_DURATION_MIN, SETTING_DURATION_MAX, 1000);
obs_property_t *prop = obs_properties_add_int(props, SETTING_DURATION, obs_module_text("Duration"), SETTING_DURATION_MIN,
SETTING_DURATION_MAX, 1000);
obs_property_int_set_suffix(prop, "ms");
obs_properties_add_float_slider(props, SETTING_AUDIO_THRESHOLD,
obs_module_text("ThresholdDb"),
SETTING_AUDIO_THRESHOLD_MIN,
obs_properties_add_float_slider(props, SETTING_AUDIO_THRESHOLD, obs_module_text("ThresholdDb"), SETTING_AUDIO_THRESHOLD_MIN,
SETTING_AUDIO_THRESHOLD_MAX, 0.1);

return props;
Expand Down
Loading

0 comments on commit f6e2ec3

Please sign in to comment.