52 .offset = offsetof(
ASS, script_info),
61 { .section =
"V4+ Styles",
62 .format_header =
"Format",
63 .fields_header =
"Style",
66 .offset_count = offsetof(
ASS, styles_count),
93 { .section =
"V4 Styles",
94 .format_header =
"Format",
95 .fields_header =
"Style",
98 .offset_count = offsetof(
ASS, styles_count),
120 { .section =
"Events",
121 .format_header =
"Format",
122 .fields_header =
"Dialogue",
125 .offset_count = offsetof(
ASS, dialogs_count),
148 memcpy(str, buf, len);
152 *(
char **)dest = str;
158 return sscanf(buf,
"%d", (
int *)dest) == 1;
162 return sscanf(buf,
"%f", (
float *)dest) == 1;
166 return sscanf(buf,
"&H%8x", (
int *)dest) == 1 ||
167 sscanf(buf,
"%d", (
int *)dest) == 1;
172 if ((c = sscanf(buf,
"%d:%02d:%02d.%02d", &h, &m, &s, &cs)) == 4)
173 *(
int *)dest = 360000*h + 6000*m + 100*s + cs;
179 if (sscanf(buf,
"%d", &a) == 1) {
181 *(
int *)dest = a + ((a&4) >> 1) - 5*!!(a&8);
214 tmp += *count * section->
size;
215 memset(tmp, 0, section->
size);
222 return buf ==
'\r' || buf ==
'\n' || buf == 0;
253 while (buf && *buf) {
258 if (buf[0] ==
';' || (buf[0] ==
'!' && buf[1] ==
':')) {
262 if (strncmp(buf, section->
format_header, len) || buf[len] !=
':')
267 len = strcspn(buf,
", \r\n");
273 if (!strncmp(buf, section->
fields[i].
name, len)) {
278 buf =
skip_space(buf + len + (buf[len] ==
','));
283 if (!strncmp(buf, section->
fields_header, len) && buf[len] ==
':') {
285 if (!struct_ptr)
return NULL;
296 for (i=0; !
is_eol(*buf) && i < *number; i++) {
297 int last = i == *number - 1;
299 len = strcspn(buf, last ?
"\r\n" :
",\r\n");
306 if (!last && *buf) buf++;
311 len = strcspn(buf,
":\r\n");
312 if (buf[len] ==
':') {
314 if (!strncmp(buf, section->
fields[i].
name, len)) {
325 buf += strcspn(buf,
"\n");
339 while (buf && *buf) {
340 if (sscanf(buf,
"[%15[0-9A-Za-z+ ]]%c", section, &c) == 2) {
341 buf += strcspn(buf,
"\n");
344 if (!strcmp(section, ass_sections[i].section)) {
349 buf += strcspn(buf,
"\n");
381 for (i=0; i<*
count; i++, ptr += section->
size)
394 int cache,
int *number)
400 if (!strcmp(ass_sections[i].
section,
"Events")) {
428 const char *text =
NULL;
432 while (buf && *buf) {
433 if (text && callbacks->
text &&
434 (sscanf(buf,
"\\%1[nN]", new_line) == 1 ||
435 !strncmp(buf,
"{\\", 2))) {
436 callbacks->
text(priv, text, text_len);
439 if (sscanf(buf,
"\\%1[nN]", new_line) == 1) {
441 callbacks->
new_line(priv, new_line[0] ==
'N');
443 }
else if (!strncmp(buf,
"{\\", 2)) {
445 while (*buf ==
'\\') {
446 char style[2],
c[2], sep[2], c_num[2] =
"0", tmp[128] = {0};
447 unsigned int color = 0xFFFFFFFF;
449 int x1, y1, x2, y2,
t1 = -1,
t2 = -1;
450 if (sscanf(buf,
"\\%1[bisu]%1[01\\}]%n", style, c, &len) > 1) {
451 int close = c[0] ==
'0' ? 1 : c[0] ==
'1' ? 0 : -1;
453 if (callbacks->
style)
454 callbacks->
style(priv, style[0], close);
455 }
else if (sscanf(buf,
"\\c%1[\\}]%n", sep, &len) > 0 ||
456 sscanf(buf,
"\\c&H%X&%1[\\}]%n", &color, sep, &len) > 1 ||
457 sscanf(buf,
"\\%1[1234]c%1[\\}]%n", c_num, sep, &len) > 1 ||
458 sscanf(buf,
"\\%1[1234]c&H%X&%1[\\}]%n", c_num, &color, sep, &len) > 2) {
459 if (callbacks->
color)
460 callbacks->
color(priv, color, c_num[0] -
'0');
461 }
else if (sscanf(buf,
"\\alpha%1[\\}]%n", sep, &len) > 0 ||
462 sscanf(buf,
"\\alpha&H%2X&%1[\\}]%n", &
alpha, sep, &len) > 1 ||
463 sscanf(buf,
"\\%1[1234]a%1[\\}]%n", c_num, sep, &len) > 1 ||
464 sscanf(buf,
"\\%1[1234]a&H%2X&%1[\\}]%n", c_num, &
alpha, sep, &len) > 2) {
465 if (callbacks->
alpha)
466 callbacks->
alpha(priv,
alpha, c_num[0] -
'0');
467 }
else if (sscanf(buf,
"\\fn%1[\\}]%n", sep, &len) > 0 ||
468 sscanf(buf,
"\\fn%127[^\\}]%1[\\}]%n", tmp, sep, &len) > 1) {
471 }
else if (sscanf(buf,
"\\fs%1[\\}]%n", sep, &len) > 0 ||
472 sscanf(buf,
"\\fs%u%1[\\}]%n", &size, sep, &len) > 1) {
475 }
else if (sscanf(buf,
"\\a%1[\\}]%n", sep, &len) > 0 ||
476 sscanf(buf,
"\\a%2u%1[\\}]%n", &an, sep, &len) > 1 ||
477 sscanf(buf,
"\\an%1[\\}]%n", sep, &len) > 0 ||
478 sscanf(buf,
"\\an%1u%1[\\}]%n", &an, sep, &len) > 1) {
479 if (an != -1 && buf[2] !=
'n')
480 an = (an&3) + (an&4 ? 6 : an&8 ? 3 : 0);
483 }
else if (sscanf(buf,
"\\r%1[\\}]%n", sep, &len) > 0 ||
484 sscanf(buf,
"\\r%127[^\\}]%1[\\}]%n", tmp, sep, &len) > 1) {
487 }
else if (sscanf(buf,
"\\move(%d,%d,%d,%d)%1[\\}]%n", &x1, &y1, &x2, &y2, sep, &len) > 4 ||
488 sscanf(buf,
"\\move(%d,%d,%d,%d,%d,%d)%1[\\}]%n", &x1, &y1, &x2, &y2, &t1, &
t2, sep, &len) > 6) {
490 callbacks->
move(priv, x1, y1, x2, y2, t1,
t2);
491 }
else if (sscanf(buf,
"\\pos(%d,%d)%1[\\}]%n", &x1, &y1, sep, &len) > 2) {
493 callbacks->
move(priv, x1, y1, x1, y1, -1, -1);
494 }
else if (sscanf(buf,
"\\org(%d,%d)%1[\\}]%n", &x1, &y1, sep, &len) > 2) {
496 callbacks->
origin(priv, x1, y1);
498 len = strcspn(buf+1,
"\\}") + 2;
513 if (text && callbacks->
text)
514 callbacks->
text(priv, text, text_len);
516 callbacks->
end(priv);
525 if (!style || !*style)
static const char * skip_space(const char *buf)
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
fields extracted from the [Events] section
static int convert_alignment(void *dest, const char *buf, int len)
static int convert_str(void *dest, const char *buf, int len)
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 ASSSection ass_sections[]
ASSDialog * dialogs
array of split out dialogs
const char * format_header
static int convert_color(void *dest, const char *buf, int len)
structure containing the whole split ASS data
void(* cancel_overrides)(void *priv, const char *style)
int(* ASSConvertFunc)(void *dest, const char *buf, int len)
static int ass_split(ASSSplitContext *ctx, const char *buf)
static const char * ass_split_section(ASSSplitContext *ctx, const char *buf)
void(* origin)(void *priv, int x, int y)
This struct can be casted to ASS to access to the split data.
static av_cold int end(AVCodecContext *avctx)
int ff_ass_split_override_codes(const ASSCodesCallbacks *callbacks, void *priv, const char *buf)
Split override codes out of a ASS "Dialogue" Text field.
const char * fields_header
static int is_eol(char buf)
ASSDialog * ff_ass_split_dialog(ASSSplitContext *ctx, const char *buf, int cache, int *number)
Split one or several ASS "Dialogue" lines from a string buffer and store them in a already initialize...
static double alpha(void *priv, double x, double y)
static int * get_default_field_orders(const ASSSection *section)
void(* move)(void *priv, int x1, int y1, int x2, int y2, int t1, int t2)
static const uint8_t offset[127][2]
void(* text)(void *priv, const char *text, int len)
Set of callback functions corresponding to each override codes that can be encountered in a "Dialogue...
void(* alpha)(void *priv, int alpha, int alpha_id)
#define FF_ARRAY_ELEMS(a)
void(* font_size)(void *priv, int size)
static int convert_flt(void *dest, const char *buf, int len)
Libavcodec external API header.
static const ASSConvertFunc convert_func[]
void(* alignment)(void *priv, int alignment)
static void free_section(ASSSplitContext *ctx, const ASSSection *section)
static uint8_t * realloc_section_array(ASSSplitContext *ctx)
fields extracted from the [V4(+) Styles] section
void(* new_line)(void *priv, int forced)
ASSStyle * ff_ass_style_get(ASSSplitContext *ctx, const char *style)
Find an ASSStyle structure by its name.
static int convert_timestamp(void *dest, const char *buf, int len)
static int convert_int(void *dest, const char *buf, int len)
void(* style)(void *priv, char style, int close)
char * name
name of the tyle (case sensitive)
int dialogs_count
number of ASSDialog in the dialogs array
void(* color)(void *priv, unsigned int, unsigned int color_id)
void * av_realloc_array(void *ptr, size_t nmemb, size_t size)
int styles_count
number of ASSStyle in the styles array
void ff_ass_split_free(ASSSplitContext *ctx)
Free all the memory allocated for an ASSSplitContext.
#define av_malloc_array(a, b)
fields extracted from the [Script Info] section
void(* font_name)(void *priv, const char *name)
void * av_mallocz(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
ASSStyle * styles
array of split out styles
int * field_order[FF_ARRAY_ELEMS(ass_sections)]
int field_number[FF_ARRAY_ELEMS(ass_sections)]