From 75a3dbac9bd41842a4d00b0d42c9513e2c8aec67 Mon Sep 17 00:00:00 2001 From: Oneric Date: Tue, 4 Oct 2022 01:16:30 +0200 Subject: Parse ScriptType header VSFilter uses it for Dialogue lines and Style lines not preceeded by a styles section header. libass requires section headers to parse styles, but this still helps for files without a Styles section (placed before the Events section) and also makes our legacy-FFmpeg detection more accurate. In fact, VSFilter takes _only_ the ScriptType header into account for Dialogue lines and keeps a separate version for styles which is also affected by style section headers. This dual versioning is not implemented by this commit and the lack of any issue reports about it suggests such files may not exist in practice. If however it turned out they do, an additional version variable can be added to parser_priv and we need to decide which one to present to API users. --- libass/ass.c | 26 ++++++++++++++++++++++++-- libass/ass_priv.h | 3 ++- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/libass/ass.c b/libass/ass.c index e08a76a..ef3b471 100644 --- a/libass/ass.c +++ b/libass/ass.c @@ -681,6 +681,26 @@ static int process_styles_line(ASS_Track *track, char *str) return ret; } +static inline void parse_script_type(ASS_Track *track, const char *str) +{ + // VSF compat: don't check for leading 'v' and + // parse value from the last non-space backwards + const char *p = str + strlen(str); + rskip_spaces((char **) &p, (char *) str); + size_t len = p - str; + if (len < 4) // rskip_spaces stops _at_ last space + return; + + int ver = TRACK_TYPE_SSA; + if (*(p-1) == '+') { + ver = TRACK_TYPE_ASS; + --len; --p; + } + + if (len >= 4 && !strncmp(p-4, "4.00", 4)) + track->track_type = ver; +} + static inline void check_duplicate_info_line(const ASS_Track *const track, const ScriptInfo si, const char *const name) @@ -723,6 +743,9 @@ static int process_info_line(ASS_Track *track, char *str) while (*p && ass_isspace(*p)) p++; free(track->Language); track->Language = strndup(p, 2); + } else if (!strncmp(str, "ScriptType:", 11)) { + check_duplicate_info_line(track, SINFO_SCRIPTTYPE, "ScriptType"); + parse_script_type(track, str + 11); } else if (!strncmp(str, "; Script generated by ", 22)) { if (!strncmp(str + 22,"FFmpeg/Lavc", 11)) track->parser_priv->header_flags |= GENBY_FFMPEG; @@ -783,9 +806,8 @@ static bool detect_legacy_conv_subs(ASS_Track *track) */ // GENBY_FFMPEG and exact ffmpeg headers required - // Note: If there's SINFO_SCRIPTTYPE in the future this needs to be updated if (track->parser_priv->header_flags - ^ (SINFO_PLAYRESX | SINFO_PLAYRESY | GENBY_FFMPEG)) + != (SINFO_SCRIPTTYPE | SINFO_PLAYRESX | SINFO_PLAYRESY | GENBY_FFMPEG)) return false; // Legacy ffmpeg only ever has one style diff --git a/libass/ass_priv.h b/libass/ass_priv.h index 43a89c8..8c9d3cf 100644 --- a/libass/ass_priv.h +++ b/libass/ass_priv.h @@ -41,8 +41,9 @@ typedef enum { SINFO_SCALEDBORDER = 1 << 5, SINFO_COLOURMATRIX = 1 << 6, SINFO_KERNING = 1 << 7, + SINFO_SCRIPTTYPE = 1 << 8, // for legacy detection - GENBY_FFMPEG = 1 << 8 + GENBY_FFMPEG = 1 << 14 // max 32 enumerators } ScriptInfo; -- cgit v1.2.3