59 { .section =
"Script Info",
60 .offset = offsetof(
ASS, script_info),
69 { .section =
"V4+ Styles",
70 .format_header =
"Format",
71 .fields_header =
"Style",
74 .offset_count = offsetof(
ASS, styles_count),
101 { .section =
"V4 Styles",
102 .format_header =
"Format",
103 .fields_header =
"Style",
106 .offset_count = offsetof(
ASS, styles_count),
128 { .section =
"Events",
129 .format_header =
"Format",
130 .fields_header =
"Dialogue",
133 .offset_count = offsetof(
ASS, dialogs_count),
156 memcpy(str, buf,
len);
160 *(
char **)dest = str;
166 return sscanf(buf,
"%d", (
int *)dest) == 1;
170 return sscanf(buf,
"%f", (
float *)dest) == 1;
174 return sscanf(buf,
"&H%8x", (
int *)dest) == 1 ||
175 sscanf(buf,
"%d", (
int *)dest) == 1;
180 if ((
c = sscanf(buf,
"%d:%02d:%02d.%02d", &
h, &m, &
s, &cs)) == 4)
181 *(
int *)dest = 360000*
h + 6000*m + 100*
s + cs;
187 if (sscanf(buf,
"%d", &
a) == 1) {
189 *(
int *)dest =
a + ((
a&4) >> 1) - 5*!!(
a&8);
217 void **section_ptr = (
void **)((uint8_t *)&
ctx->ass + section->
offset);
230 return buf ==
'\r' || buf ==
'\n' || buf == 0;
258 int *number = &
ctx->field_number[
ctx->current_section];
259 int *order =
ctx->field_order[
ctx->current_section];
262 while (buf && *buf) {
264 ctx->current_section = -1;
267 if (buf[0] ==
';' || (buf[0] ==
'!' && buf[1] ==
':'))
270 len = strcspn(buf,
":\r\n");
271 if (buf[
len] ==
':' &&
276 ctx->current_section =
i;
278 number = &
ctx->field_number[
ctx->current_section];
279 order =
ctx->field_order[
ctx->current_section];
290 len = strcspn(buf,
", \r\n");
303 ctx->field_order[
ctx->current_section] = order;
311 if (!struct_ptr)
return NULL;
318 ctx->field_order[
ctx->current_section] = order;
322 for (
i=0; !
is_eol(*buf) &&
i < *number;
i++) {
323 int last =
i == *number - 1;
325 len = strcspn(buf, last ?
"\r\n" :
",\r\n");
332 if (!last && *buf) buf++;
337 len = strcspn(buf,
":\r\n");
338 if (buf[
len] ==
':') {
342 uint8_t *ptr = (uint8_t *)&
ctx->ass + section->
offset;
351 buf += strcspn(buf,
"\n");
362 if (
ctx->current_section >= 0)
365 while (buf && *buf) {
366 if (sscanf(buf,
"[%15[0-9A-Za-z+ ]]%c", section, &
c) == 2) {
367 buf += strcspn(buf,
"\n");
371 ctx->current_section =
i;
375 buf += strcspn(buf,
"\n");
387 if (buf && !strncmp(buf,
"\xef\xbb\xbf", 3))
389 ctx->current_section = -1;
399 uint8_t *ptr = (uint8_t *)&
ctx->ass + section->
offset;
400 int i, j, *count,
c = 1;
409 for (
i=0;
i<*count;
i++, ptr += section->
size)
456 uint8_t *ptr = (uint8_t *)dialog + fields[
i].
offset;
458 len = last ? strlen(buf) : strcspn(buf,
",");
459 if (
len >= INT_MAX) {
486 const char *text =
NULL;
490 while (buf && *buf) {
491 if (text && callbacks->
text &&
492 (sscanf(buf,
"\\%1[nN]", new_line) == 1 ||
493 !strncmp(buf,
"{\\", 2))) {
494 callbacks->
text(priv, text, text_len);
497 if (sscanf(buf,
"\\%1[nN]", new_line) == 1) {
499 callbacks->
new_line(priv, new_line[0] ==
'N');
501 }
else if (!strncmp(buf,
"{\\", 2)) {
503 while (*buf ==
'\\') {
504 char style[2],
c[2], sep[2], c_num[2] =
"0",
tmp[128] = {0};
505 unsigned int color = 0xFFFFFFFF;
507 int x1, y1, x2, y2, t1 = -1, t2 = -1;
508 if (sscanf(buf,
"\\%1[bisu]%1[01\\}]%n", style,
c, &
len) > 1) {
509 int close =
c[0] ==
'0' ? 1 :
c[0] ==
'1' ? 0 : -1;
511 if (callbacks->
style)
513 }
else if (sscanf(buf,
"\\c%1[\\}]%n", sep, &
len) > 0 ||
514 sscanf(buf,
"\\c&H%X&%1[\\}]%n", &
color, sep, &
len) > 1 ||
515 sscanf(buf,
"\\%1[1234]c%1[\\}]%n", c_num, sep, &
len) > 1 ||
516 sscanf(buf,
"\\%1[1234]c&H%X&%1[\\}]%n", c_num, &
color, sep, &
len) > 2) {
517 if (callbacks->
color)
518 callbacks->
color(priv,
color, c_num[0] -
'0');
519 }
else if (sscanf(buf,
"\\alpha%1[\\}]%n", sep, &
len) > 0 ||
520 sscanf(buf,
"\\alpha&H%2X&%1[\\}]%n", &
alpha, sep, &
len) > 1 ||
521 sscanf(buf,
"\\%1[1234]a%1[\\}]%n", c_num, sep, &
len) > 1 ||
522 sscanf(buf,
"\\%1[1234]a&H%2X&%1[\\}]%n", c_num, &
alpha, sep, &
len) > 2) {
523 if (callbacks->
alpha)
524 callbacks->
alpha(priv,
alpha, c_num[0] -
'0');
525 }
else if (sscanf(buf,
"\\fn%1[\\}]%n", sep, &
len) > 0 ||
526 sscanf(buf,
"\\fn%127[^\\}]%1[\\}]%n",
tmp, sep, &
len) > 1) {
529 }
else if (sscanf(buf,
"\\fs%1[\\}]%n", sep, &
len) > 0 ||
530 sscanf(buf,
"\\fs%u%1[\\}]%n", &
size, sep, &
len) > 1) {
533 }
else if (sscanf(buf,
"\\a%1[\\}]%n", sep, &
len) > 0 ||
534 sscanf(buf,
"\\a%2u%1[\\}]%n", &an, sep, &
len) > 1 ||
535 sscanf(buf,
"\\an%1[\\}]%n", sep, &
len) > 0 ||
536 sscanf(buf,
"\\an%1u%1[\\}]%n", &an, sep, &
len) > 1) {
537 if (an != -1 && buf[2] !=
'n')
538 an = (an&3) + (an&4 ? 6 : an&8 ? 3 : 0);
541 }
else if (sscanf(buf,
"\\r%1[\\}]%n", sep, &
len) > 0 ||
542 sscanf(buf,
"\\r%127[^\\}]%1[\\}]%n",
tmp, sep, &
len) > 1) {
545 }
else if (sscanf(buf,
"\\move(%d,%d,%d,%d)%1[\\}]%n", &x1, &y1, &x2, &y2, sep, &
len) > 4 ||
546 sscanf(buf,
"\\move(%d,%d,%d,%d,%d,%d)%1[\\}]%n", &x1, &y1, &x2, &y2, &t1, &t2, sep, &
len) > 6) {
548 callbacks->
move(priv, x1, y1, x2, y2, t1, t2);
549 }
else if (sscanf(buf,
"\\pos(%d,%d)%1[\\}]%n", &x1, &y1, sep, &
len) > 2) {
551 callbacks->
move(priv, x1, y1, x1, y1, -1, -1);
552 }
else if (sscanf(buf,
"\\org(%d,%d)%1[\\}]%n", &x1, &y1, sep, &
len) > 2) {
554 callbacks->
origin(priv, x1, y1);
556 len = strcspn(buf+1,
"\\}") + 2;
571 if (text && callbacks->
text)
572 callbacks->
text(priv, text, text_len);
574 callbacks->
end(priv);
583 if (!style || !*style)
static AVFormatContext * ctx
static av_cold void close(AVCodecParserContext *s)
static int convert_color(void *dest, const char *buf, int len)
static void free_section(ASSSplitContext *ctx, const ASSSection *section)
static uint8_t * realloc_section_array(ASSSplitContext *ctx)
static const char * skip_space(const char *buf)
av_cold ASSSplitContext * ff_ass_split(const char *buf)
Split a full ASS file or a ASS header from a string buffer and store the split structure in a newly a...
static const char * ass_split_section(ASSSplitContext *ctx, const char *buf)
static const ASSConvertFunc convert_func[]
static int convert_str(void *dest, const char *buf, int len)
void ff_ass_free_dialog(ASSDialog **dialogp)
Free a dialogue obtained from ff_ass_split_dialog().
int ff_ass_split_override_codes(const ASSCodesCallbacks *callbacks, void *priv, const char *buf)
Split override codes out of a ASS "Dialogue" Text field.
static int convert_flt(void *dest, const char *buf, int len)
static int ass_split(ASSSplitContext *ctx, const char *buf)
static int convert_int(void *dest, const char *buf, int len)
ASSStyle * ff_ass_style_get(ASSSplitContext *ctx, const char *style)
Find an ASSStyle structure by its name.
static int is_eol(char buf)
static const ASSSection ass_sections[]
static int convert_alignment(void *dest, const char *buf, int len)
av_cold void ff_ass_split_free(ASSSplitContext *ctx)
Free all the memory allocated for an ASSSplitContext.
static int * get_default_field_orders(const ASSSection *section, int *number)
static int convert_timestamp(void *dest, const char *buf, int len)
int(* ASSConvertFunc)(void *dest, const char *buf, int len)
ASSDialog * ff_ass_split_dialog(ASSSplitContext *ctx, const char *buf)
Split one ASS Dialogue line from a string buffer.
#define i(width, name, range_min, range_max)
void(* move)(void *priv, int x1, int y1, int x2, int y2, int t1, int t2)
void(* origin)(void *priv, int x, int y)
void(* style)(void *priv, char style, int close)
void(* color)(void *priv, unsigned int, unsigned int color_id)
void(* font_size)(void *priv, int size)
void(* cancel_overrides)(void *priv, const char *style)
void(* alignment)(void *priv, int alignment)
void(* new_line)(void *priv, int forced)
void(* alpha)(void *priv, int alpha, int alpha_id)
void(* text)(void *priv, const char *text, int len)
void(* font_name)(void *priv, const char *name)
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
void * av_realloc_array(void *ptr, size_t nmemb, size_t size)
int av_reallocp_array(void *ptr, size_t nmemb, size_t size)
Allocate, reallocate an array through a pointer to a pointer.
static const int16_t alpha[]
Utility Preprocessor macros.
Memory handling functions.
#define FF_ARRAY_ELEMS(a)
Set of callback functions corresponding to each override codes that can be encountered in a "Dialogue...
fields extracted from the [Events] section
char * style
name of the ASSStyle to use with this dialog
char * text
actual text which will be displayed as a subtitle, can include style override control codes (see ff_a...
fields extracted from the [Script Info] section
const char * fields_header
const char * format_header
This struct can be casted to ASS to access to the split data.
int * field_order[FF_ARRAY_ELEMS(ass_sections)]
int field_number[FF_ARRAY_ELEMS(ass_sections)]
fields extracted from the [V4(+) Styles] section
char * name
name of the tyle (case sensitive)
structure containing the whole split ASS data
int styles_count
number of ASSStyle in the styles array
ASSStyle * styles
array of split out styles
#define av_malloc_array(a, b)