未验证 提交 274bf52d 编写于 作者: J Jim 提交者: GitHub

Merge pull request #1452 from cg2121/slideshow-memory-usage

image-source: Decrease slideshow source memory usage
......@@ -57,6 +57,9 @@
/* ------------------------------------------------------------------------- */
#define MOD(a,b) ((((a)%(b))+(b))%(b))
#define MAX_LOADED 11 /* needs to be an odd number */
struct image_file_data {
char *path;
obs_source_t *source;
......@@ -75,7 +78,6 @@ struct slideshow {
bool loop;
bool restart_on_activate;
bool pause_on_deactivate;
bool restart;
bool manual;
bool hide;
bool use_cut;
......@@ -87,13 +89,14 @@ struct slideshow {
obs_source_t *transition;
float elapsed;
size_t cur_item;
int cur_item;
uint32_t cx;
uint32_t cy;
pthread_mutex_t mutex;
DARRAY(struct image_file_data) files;
DARRAY(char*) paths;
enum behavior behavior;
......@@ -164,7 +167,18 @@ static void free_files(struct darray *array)
static inline size_t random_file(struct slideshow *ss)
{
return (size_t)rand() % ss->files.num;
return (size_t)rand() % ss->paths.num;
}
static void free_paths(struct darray *array)
{
DARRAY(char*) paths;
paths.da = *array;
for (size_t i = 0; i < paths.num; i++)
bfree(paths.array[i]);
da_free(paths);
}
/* ------------------------------------------------------------------------- */
......@@ -176,7 +190,7 @@ static const char *ss_getname(void *unused)
}
static void add_file(struct slideshow *ss, struct darray *array,
const char *path, uint32_t *cx, uint32_t *cy)
const char *path, uint32_t *cx, uint32_t *cy, bool next)
{
DARRAY(struct image_file_data) new_files;
struct image_file_data data;
......@@ -199,7 +213,11 @@ static void add_file(struct slideshow *ss, struct darray *array,
data.path = bstrdup(path);
data.source = new_source;
da_push_back(new_files, &data);
if (next)
da_push_back(new_files, &data);
else
da_insert(new_files, 0, &data);
if (new_cx > *cx) *cx = new_cx;
if (new_cy > *cy) *cy = new_cy;
......@@ -208,6 +226,48 @@ static void add_file(struct slideshow *ss, struct darray *array,
*array = new_files.da;
}
static void clear_buffer(struct slideshow *ss, bool next)
{
if (ss->paths.num <= MAX_LOADED || !ss->paths.num || !ss->files.num)
return;
if (next) {
bfree(ss->files.array[0].path);
obs_source_release(ss->files.array[0].source);
da_erase(ss->files, 0);
} else {
bfree(ss->files.array[ss->files.num - 1].path);
obs_source_release(ss->files.array[ss->files.num - 1].source);
da_pop_back(ss->files);
}
size_t index = 0;
if (ss->randomize)
index = random_file(ss);
else if (!ss->randomize && next)
index = MOD((ss->cur_item + ((MAX_LOADED / 2) + 1)),
ss->paths.num);
else if (!ss->randomize && !next)
index = MOD((ss->cur_item - ((MAX_LOADED / 2) + 1)),
ss->paths.num);
uint32_t cx, cy;
add_file(ss, &ss->files.da, ss->paths.array[index], &cx, &cy,
next);
}
static void add_path(struct darray *array, const char *path)
{
DARRAY(char*) new_paths;
new_paths.da = *array;
const char *new_path = bstrdup(path);
da_push_back(new_paths, &new_path);
*array = new_paths.da;
}
static bool valid_extension(const char *ext)
{
if (!ext)
......@@ -222,35 +282,54 @@ static bool valid_extension(const char *ext)
static inline bool item_valid(struct slideshow *ss)
{
return ss->files.num && ss->cur_item < ss->files.num;
return ss->files.num && ss->paths.num &&
(size_t)ss->cur_item < ss->paths.num;
}
static void do_transition(void *data, bool to_null)
static void do_transition(void *data, bool to_null, bool next)
{
struct slideshow *ss = data;
bool valid = item_valid(ss);
if (valid && ss->use_cut)
obs_transition_set(ss->transition,
ss->files.array[ss->cur_item].source);
else if (valid && !to_null)
obs_transition_start(ss->transition,
OBS_TRANSITION_MODE_AUTO,
if (to_null) {
obs_transition_start(ss->transition, OBS_TRANSITION_MODE_AUTO,
ss->tr_speed,
ss->files.array[ss->cur_item].source);
NULL);
return;
}
else
if (!valid)
return;
clear_buffer(ss, next);
obs_source_t *source;
if (next && ss->paths.num > MAX_LOADED)
source = ss->files.array[(MAX_LOADED / 2) + 1].source;
else if (!next && ss->paths.num > MAX_LOADED)
source = ss->files.array[(MAX_LOADED / 2) - 1].source;
else if (ss->paths.num <= MAX_LOADED)
source = ss->files.array[(size_t)ss->cur_item].source;
if (!source)
return;
if (ss->use_cut)
obs_transition_set(ss->transition, source);
else if (!to_null)
obs_transition_start(ss->transition,
OBS_TRANSITION_MODE_AUTO,
ss->tr_speed,
NULL);
ss->tr_speed, source);
}
static void ss_update(void *data, obs_data_t *settings)
{
DARRAY(struct image_file_data) new_files;
DARRAY(struct image_file_data) old_files;
DARRAY(char*) new_paths;
DARRAY(char*) old_paths;
obs_source_t *new_tr = NULL;
obs_source_t *old_tr = NULL;
struct slideshow *ss = data;
......@@ -260,6 +339,8 @@ static void ss_update(void *data, obs_data_t *settings)
uint32_t new_speed;
uint32_t cx = 0;
uint32_t cy = 0;
uint32_t last_cx = 0;
uint32_t last_cy = 0;
size_t count;
const char *behavior;
const char *mode;
......@@ -268,6 +349,7 @@ static void ss_update(void *data, obs_data_t *settings)
/* get settings data */
da_init(new_files);
da_init(new_paths);
behavior = obs_data_get_string(settings, S_BEHAVIOR);
......@@ -333,14 +415,13 @@ static void ss_update(void *data, obs_data_t *settings)
dstr_copy(&dir_path, path);
dstr_cat_ch(&dir_path, '/');
dstr_cat(&dir_path, ent->d_name);
add_file(ss, &new_files.da, dir_path.array,
&cx, &cy);
add_path(&new_paths.da, dir_path.array);
}
dstr_free(&dir_path);
os_closedir(dir);
} else {
add_file(ss, &new_files.da, path, &cx, &cy);
add_path(&new_paths.da, path);
}
obs_data_release(item);
......@@ -353,6 +434,8 @@ static void ss_update(void *data, obs_data_t *settings)
old_files.da = ss->files.da;
ss->files.da = new_files.da;
old_paths.da = ss->paths.da;
ss->paths.da = new_paths.da;
if (new_tr) {
old_tr = ss->transition;
ss->transition = new_tr;
......@@ -369,12 +452,31 @@ static void ss_update(void *data, obs_data_t *settings)
pthread_mutex_unlock(&ss->mutex);
if (ss->paths.num > MAX_LOADED && !ss->randomize) {
for (int i = -(MAX_LOADED / 2); i <= (MAX_LOADED / 2); i++) {
size_t index = MOD(i, ss->paths.num);
add_file(ss, &ss->files.da, ss->paths.array[index],
&cx, &cy, true);
}
} else if (ss->paths.num > MAX_LOADED && ss->randomize) {
for (size_t i = 0; i < MAX_LOADED; i++) {
size_t index = random_file(ss);
add_file(ss, &ss->files.da, ss->paths.array[index],
&cx, &cy, true);
}
} else if (ss->paths.num <= MAX_LOADED) {
for (size_t i = 0; i < ss->paths.num; i++)
add_file(ss, &ss->files.da, ss->paths.array[i],
&cx, &cy, true);
}
/* ------------------------------------- */
/* clean up and restart transition */
if (old_tr)
obs_source_release(old_tr);
free_files(&old_files.da);
free_paths(&old_paths.da);
/* ------------------------- */
......@@ -418,21 +520,32 @@ static void ss_update(void *data, obs_data_t *settings)
/* ------------------------- */
obs_data_t *priv_settings = obs_source_get_private_settings(ss->source);
last_cx = (uint32_t)obs_data_get_int(priv_settings, "last_cx");
last_cy = (uint32_t)obs_data_get_int(priv_settings, "last_cy");
if (ss->randomize && last_cx > 0 && last_cy > 0) {
cx = last_cx;
cy = last_cy;
}
obs_data_set_int(priv_settings, "last_cx", cx);
obs_data_set_int(priv_settings, "last_cy", cy);
obs_data_release(priv_settings);
ss->cx = cx;
ss->cy = cy;
ss->cur_item = 0;
ss->elapsed = 0.0f;
ss->cur_item = 0;
obs_transition_set_size(ss->transition, cx, cy);
obs_transition_set_alignment(ss->transition, OBS_ALIGN_CENTER);
obs_transition_set_scale_type(ss->transition,
OBS_TRANSITION_SCALE_ASPECT);
if (ss->randomize && ss->files.num)
ss->cur_item = random_file(ss);
if (new_tr)
obs_source_add_active_child(ss->source, new_tr);
if (ss->files.num)
do_transition(ss, false);
do_transition(ss, false, true);
obs_data_array_release(array);
}
......@@ -449,14 +562,15 @@ static void ss_restart(void *data)
{
struct slideshow *ss = data;
ss->elapsed = 0.0f;
ss->cur_item = 0;
ss->stop = false;
ss->use_cut = true;
ss->restart_on_activate = false;
obs_transition_set(ss->transition,
ss->files.array[ss->cur_item].source);
obs_data_t *settings = obs_source_get_settings(ss->source);
ss_update(ss, settings);
obs_data_release(settings);
ss->stop = false;
ss->paused = false;
ss->use_cut = false;
}
static void ss_stop(void *data)
......@@ -466,7 +580,7 @@ static void ss_stop(void *data)
ss->elapsed = 0.0f;
ss->cur_item = 0;
do_transition(ss, true);
do_transition(ss, true, true);
ss->stop = true;
ss->paused = false;
}
......@@ -475,28 +589,26 @@ static void ss_next_slide(void *data)
{
struct slideshow *ss = data;
if (!ss->files.num)
if (!ss->paths.num)
return;
if (++ss->cur_item >= ss->files.num)
if (++ss->cur_item >= (int)ss->paths.num)
ss->cur_item = 0;
do_transition(ss, false);
do_transition(ss, false, true);
}
static void ss_previous_slide(void *data)
{
struct slideshow *ss = data;
if (!ss->files.num)
if (!ss->paths.num)
return;
if (ss->cur_item == 0)
ss->cur_item = ss->files.num - 1;
else
--ss->cur_item;
if (--ss->cur_item < 0)
ss->cur_item = (int)(ss->paths.num - 1);
do_transition(ss, false);
do_transition(ss, false, false);
}
static void play_pause_hotkey(void *data, obs_hotkey_id id,
......@@ -571,6 +683,7 @@ static void ss_destroy(void *data)
obs_source_release(ss->transition);
free_files(&ss->files.da);
free_paths(&ss->paths.da);
pthread_mutex_destroy(&ss->mutex);
bfree(ss);
}
......@@ -644,13 +757,8 @@ static void ss_video_tick(void *data, float seconds)
if (!ss->transition || !ss->slide_time)
return;
if (ss->restart_on_activate && !ss->randomize && ss->use_cut) {
ss->elapsed = 0.0f;
ss->cur_item = 0;
do_transition(ss, false);
ss->restart_on_activate = false;
ss->use_cut = false;
ss->stop = false;
if (ss->restart_on_activate && ss->use_cut) {
ss_restart(ss);
return;
}
......@@ -659,13 +767,13 @@ static void ss_video_tick(void *data, float seconds)
/* ----------------------------------------------------- */
/* fade to transparency when the file list becomes empty */
if (!ss->files.num) {
if (!ss->paths.num) {
obs_source_t* active_transition_source =
obs_transition_get_active_source(ss->transition);
if (active_transition_source) {
obs_source_release(active_transition_source);
do_transition(ss, true);
do_transition(ss, true, true);
}
}
......@@ -676,29 +784,17 @@ static void ss_video_tick(void *data, float seconds)
if (ss->elapsed > ss->slide_time) {
ss->elapsed -= ss->slide_time;
if (!ss->loop && ss->cur_item == ss->files.num - 1) {
if (!ss->loop && ss->cur_item == (int)ss->paths.num - 1 &&
!ss->randomize) {
if (ss->hide)
do_transition(ss, true);
do_transition(ss, true, true);
else
do_transition(ss, false);
do_transition(ss, false, true);
return;
}
if (ss->randomize) {
size_t next = ss->cur_item;
if (ss->files.num > 1) {
while (next == ss->cur_item)
next = random_file(ss);
}
ss->cur_item = next;
} else if (++ss->cur_item >= ss->files.num) {
ss->cur_item = 0;
}
if (ss->files.num)
do_transition(ss, false);
ss_next_slide(ss);
}
}
......@@ -861,11 +957,14 @@ static obs_properties_t *ss_properties(void *data)
if (ss) {
pthread_mutex_lock(&ss->mutex);
if (ss->files.num) {
struct image_file_data *last = da_end(ss->files);
if (ss->paths.num) {
char **p_last_path = da_end(ss->paths);
const char *last_path;
const char *slash;
dstr_copy(&path, last->path);
last_path = p_last_path ? *p_last_path : "";
dstr_copy(&path, last_path);
dstr_replace(&path, "\\", "/");
slash = strrchr(path.array, '/');
if (slash)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册