浏览代码

libobs: Deallocate lingering unused cache frames

This fixes an issue where cache frames would not free at all after
having been allocated with no upper limit on the cached frame size.  If
cached frames go unused for a specific period of time, they are
deallocated and removed from the cache.

This is preferable to having an upper cache limit due to the potential
for async delay filtering.
jp9000 10 年之前
父节点
当前提交
3a90be39dd
共有 2 个文件被更改,包括 22 次插入0 次删除
  1. 1 0
      libobs/obs-internal.h
  2. 21 0
      libobs/obs-source.c

+ 1 - 0
libobs/obs-internal.h

@@ -277,6 +277,7 @@ extern void obs_context_data_setname(struct obs_context_data *context,
 
 struct async_frame {
 	struct obs_source_frame *frame;
+	long unused_count;
 	bool used;
 };
 

+ 21 - 0
libobs/obs-source.c

@@ -1629,6 +1629,23 @@ static inline void free_async_cache(struct obs_source *source)
 	da_resize(source->async_frames, 0);
 }
 
+#define MAX_UNUSED_FRAME_DURATION 5
+
+/* frees frame allocations if they haven't been used for a specific period
+ * of time */
+static void clean_cache(obs_source_t *source)
+{
+	for (size_t i = source->async_cache.num; i > 0; i--) {
+		struct async_frame *af = &source->async_cache.array[i - 1];
+		if (!af->used) {
+			if (++af->unused_count == MAX_UNUSED_FRAME_DURATION) {
+				obs_source_frame_destroy(af->frame);
+				da_erase(source->async_cache, i - 1);
+			}
+		}
+	}
+}
+
 static inline struct obs_source_frame *cache_video(struct obs_source *source,
 		const struct obs_source_frame *frame)
 {
@@ -1652,10 +1669,13 @@ static inline struct obs_source_frame *cache_video(struct obs_source *source,
 		if (!af->used) {
 			new_frame = af->frame;
 			af->used = true;
+			af->unused_count = 0;
 			break;
 		}
 	}
 
+	clean_cache(source);
+
 	if (!new_frame) {
 		struct async_frame new_af;
 
@@ -1663,6 +1683,7 @@ static inline struct obs_source_frame *cache_video(struct obs_source *source,
 				frame->width, frame->height);
 		new_af.frame = new_frame;
 		new_af.used = true;
+		new_af.unused_count = 0;
 		new_frame->refs = 1;
 
 		da_push_back(source->async_cache, &new_af);