Skip to content

Commit

Permalink
Add events garbage collection system and API.
Browse files Browse the repository at this point in the history
  • Loading branch information
cubicibo committed Oct 28, 2024
1 parent 6a75983 commit dcc9eb7
Show file tree
Hide file tree
Showing 5 changed files with 91 additions and 8 deletions.
6 changes: 3 additions & 3 deletions libass/Makefile_library.am
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
LIBASS_LT_CURRENT = 12
LIBASS_LT_REVISION = 1
LIBASS_LT_AGE = 3
LIBASS_LT_CURRENT = 13
LIBASS_LT_REVISION = 0
LIBASS_LT_AGE = 4

.asm.lo:
$(nasm_verbose)$(LIBTOOL) $(AM_V_lt) --tag=CC --mode=compile $(top_srcdir)/ltnasm.sh $(AS) $(ASFLAGS) -I$(top_srcdir)/libass/ -Dprivate_prefix=ass -o $@ $<
Expand Down
67 changes: 63 additions & 4 deletions libass/ass.c
Original file line number Diff line number Diff line change
Expand Up @@ -190,14 +190,29 @@ static int test_and_set_read_order_bit(ASS_Track *track, int id)
{
if (resize_read_order_bitmap(track, id) < 0)
return -1;
int index = id / 32;
uint32_t bit = 1u << (id % 32);
int index = id >> 5;
uint32_t bit = 1u << (id & 0x1F);
if (track->parser_priv->read_order_bitmap[index] & bit)
return 1;
track->parser_priv->read_order_bitmap[index] |= bit;
return 0;
}

static inline void clear_read_order_bit(ASS_Track *track, int id)
{
int index = id >> 5;
if (index < track->parser_priv->read_order_elems) {
uint32_t mask = ~(1u << (id & 0x1F));
track->parser_priv->read_order_bitmap[index] &= mask;
}
}

static inline void update_prune_ts(ASS_Track *track, const long long ts)
{
if (ts < track->parser_priv->prune_next_ts)
track->parser_priv->prune_next_ts = ts;
}

// ==============================================================================================

/**
Expand Down Expand Up @@ -1015,8 +1030,10 @@ static int process_events_line(ASS_Track *track, char *str)
event = track->events + eid;

int ret = process_event_tail(track, event, str, 0);
if (!ret)
if (!ret) {
update_prune_ts(track, event->Start + event->Duration);
return 0;
}
// If something went wrong, discard the useless Event
ass_free_event(track, eid);
track->n_events--;
Expand Down Expand Up @@ -1330,7 +1347,7 @@ void ass_process_chunk(ASS_Track *track, const char *data, int size,

event->Start = timecode;
event->Duration = duration;

update_prune_ts(track, event->Start + event->Duration);
goto cleanup;
// dump_events(tid);
} while (0);
Expand Down Expand Up @@ -1359,6 +1376,46 @@ void ass_flush_events(ASS_Track *track)
track->parser_priv->read_order_elems = 0;
}

void ass_configure_prune(ASS_Track *track, long long delay)
{
track->parser_priv->prune_delay = delay;
}

void ass_prune_events(ASS_Track *track, long long deadline)
{
if (deadline < track->parser_priv->prune_next_ts)
return;

const bool check_readorder = track->parser_priv->check_readorder;
const int old_n_events = track->n_events;

int n_kept = 0;
ASS_Event *events = track->events;

track->parser_priv->prune_next_ts = LLONG_MAX;
for (int k = 0; k < old_n_events;) {
// discardable sequence
for (; k < old_n_events && events[k].Start + events[k].Duration < deadline; k++) {
if (check_readorder)
clear_read_order_bit(track, events[k].ReadOrder);
ass_free_event(track, k);
}

// to-be-kept sequence
int move_from = k;
for (long long ts; k < old_n_events && (ts = events[k].Start + events[k].Duration) >= deadline; k++)
update_prune_ts(track, ts);

// Relocate kept events
if (move_from < k) {
int cnt = k - move_from;
memmove(events + n_kept, events + move_from, cnt * sizeof(*track->events));
n_kept += cnt;
}
}
track->n_events = n_kept;
}

#ifdef CONFIG_ICONV
/** \brief recode buffer to utf-8
* constraint: codepage != 0
Expand Down Expand Up @@ -1725,6 +1782,8 @@ ASS_Track *ass_new_track(ASS_Library *library)
if (!track->styles[def_sid].Name || !track->styles[def_sid].FontName)
goto fail;
track->parser_priv->check_readorder = 1;
track->parser_priv->prune_delay = -1;
track->parser_priv->prune_next_ts = LLONG_MAX;
return track;

fail:
Expand Down
20 changes: 19 additions & 1 deletion libass/ass.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
#include <stdarg.h>
#include "ass_types.h"

#define LIBASS_VERSION 0x01703000
#define LIBASS_VERSION 0x01703010

#ifdef __cplusplus
extern "C" {
Expand Down Expand Up @@ -734,6 +734,24 @@ void ass_process_chunk(ASS_Track *track, const char *data, int size,
*/
void ass_set_check_readorder(ASS_Track *track, int check_readorder);

/**
* \brief Prune events that preceed deadline.
* \param track track
* \param deadline cut-off timestamp in milliseconds.
*/
void ass_prune_events(ASS_Track *track, long long deadline);

/**
* \brief Configure automatic pruning of events.
* \param track track
* \param delay delay from "now" (ass_render_frame) in milliseconds.
* After every render, events whose undisplay timestamp predate
* "now - delay" will be deleted. A delay of 0 prunes aggressively.
* Negative delays disable automatic pruning.
* Disabled by default (no removal of events from memory).
*/
void ass_configure_prune(ASS_Track *track, long long delay);

/**
* \brief Flush buffered events.
* \param track track
Expand Down
3 changes: 3 additions & 0 deletions libass/ass_priv.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ struct parser_priv {
uint32_t header_flags;

uint32_t feature_flags;

long long prune_delay;
long long prune_next_ts;
};

#endif /* LIBASS_PRIV_H */
3 changes: 3 additions & 0 deletions libass/ass_render.c
Original file line number Diff line number Diff line change
Expand Up @@ -3428,6 +3428,9 @@ ASS_Image *ass_render_frame(ASS_Renderer *priv, ASS_Track *track,
ass_frame_unref(priv->prev_images_root);
priv->prev_images_root = NULL;

if (track->parser_priv->prune_delay >= 0)
ass_prune_events(track, now - track->parser_priv->prune_delay);

return priv->images_root;
}

Expand Down

0 comments on commit dcc9eb7

Please sign in to comment.