FFmpeg
ass_split.c
Go to the documentation of this file.
1 /*
2  * SSA/ASS spliting functions
3  * Copyright (c) 2010 Aurelien Jacobs <aurel@gnuage.org>
4  *
5  * This file is part of FFmpeg.
6  *
7  * FFmpeg is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * FFmpeg is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * License along with FFmpeg; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20  */
21 
22 #include "libavutil/common.h"
23 #include "libavutil/error.h"
24 #include "libavutil/mem.h"
25 #include "ass_split.h"
26 
27 typedef enum {
34 } ASSFieldType;
35 
36 typedef struct {
37  const char *name;
38  int type;
39  int offset;
40 } ASSFields;
41 
42 typedef struct {
43  const char *section;
44  const char *format_header;
45  const char *fields_header;
46  int size;
47  int offset;
50 } ASSSection;
51 
52 static const ASSSection ass_sections[] = {
53  { .section = "Script Info",
54  .offset = offsetof(ASS, script_info),
55  .fields = {{"ScriptType", ASS_STR, offsetof(ASSScriptInfo, script_type)},
56  {"Collisions", ASS_STR, offsetof(ASSScriptInfo, collisions) },
57  {"PlayResX", ASS_INT, offsetof(ASSScriptInfo, play_res_x) },
58  {"PlayResY", ASS_INT, offsetof(ASSScriptInfo, play_res_y) },
59  {"Timer", ASS_FLT, offsetof(ASSScriptInfo, timer) },
60  {0},
61  }
62  },
63  { .section = "V4+ Styles",
64  .format_header = "Format",
65  .fields_header = "Style",
66  .size = sizeof(ASSStyle),
67  .offset = offsetof(ASS, styles),
68  .offset_count = offsetof(ASS, styles_count),
69  .fields = {{"Name", ASS_STR, offsetof(ASSStyle, name) },
70  {"Fontname", ASS_STR, offsetof(ASSStyle, font_name) },
71  {"Fontsize", ASS_INT, offsetof(ASSStyle, font_size) },
72  {"PrimaryColour", ASS_COLOR, offsetof(ASSStyle, primary_color) },
73  {"SecondaryColour", ASS_COLOR, offsetof(ASSStyle, secondary_color)},
74  {"OutlineColour", ASS_COLOR, offsetof(ASSStyle, outline_color) },
75  {"BackColour", ASS_COLOR, offsetof(ASSStyle, back_color) },
76  {"Bold", ASS_INT, offsetof(ASSStyle, bold) },
77  {"Italic", ASS_INT, offsetof(ASSStyle, italic) },
78  {"Underline", ASS_INT, offsetof(ASSStyle, underline) },
79  {"StrikeOut", ASS_INT, offsetof(ASSStyle, strikeout) },
80  {"ScaleX", ASS_FLT, offsetof(ASSStyle, scalex) },
81  {"ScaleY", ASS_FLT, offsetof(ASSStyle, scaley) },
82  {"Spacing", ASS_FLT, offsetof(ASSStyle, spacing) },
83  {"Angle", ASS_FLT, offsetof(ASSStyle, angle) },
84  {"BorderStyle", ASS_INT, offsetof(ASSStyle, border_style) },
85  {"Outline", ASS_FLT, offsetof(ASSStyle, outline) },
86  {"Shadow", ASS_FLT, offsetof(ASSStyle, shadow) },
87  {"Alignment", ASS_INT, offsetof(ASSStyle, alignment) },
88  {"MarginL", ASS_INT, offsetof(ASSStyle, margin_l) },
89  {"MarginR", ASS_INT, offsetof(ASSStyle, margin_r) },
90  {"MarginV", ASS_INT, offsetof(ASSStyle, margin_v) },
91  {"Encoding", ASS_INT, offsetof(ASSStyle, encoding) },
92  {0},
93  }
94  },
95  { .section = "V4 Styles",
96  .format_header = "Format",
97  .fields_header = "Style",
98  .size = sizeof(ASSStyle),
99  .offset = offsetof(ASS, styles),
100  .offset_count = offsetof(ASS, styles_count),
101  .fields = {{"Name", ASS_STR, offsetof(ASSStyle, name) },
102  {"Fontname", ASS_STR, offsetof(ASSStyle, font_name) },
103  {"Fontsize", ASS_INT, offsetof(ASSStyle, font_size) },
104  {"PrimaryColour", ASS_COLOR, offsetof(ASSStyle, primary_color) },
105  {"SecondaryColour", ASS_COLOR, offsetof(ASSStyle, secondary_color)},
106  {"TertiaryColour", ASS_COLOR, offsetof(ASSStyle, outline_color) },
107  {"BackColour", ASS_COLOR, offsetof(ASSStyle, back_color) },
108  {"Bold", ASS_INT, offsetof(ASSStyle, bold) },
109  {"Italic", ASS_INT, offsetof(ASSStyle, italic) },
110  {"BorderStyle", ASS_INT, offsetof(ASSStyle, border_style) },
111  {"Outline", ASS_FLT, offsetof(ASSStyle, outline) },
112  {"Shadow", ASS_FLT, offsetof(ASSStyle, shadow) },
113  {"Alignment", ASS_ALGN, offsetof(ASSStyle, alignment) },
114  {"MarginL", ASS_INT, offsetof(ASSStyle, margin_l) },
115  {"MarginR", ASS_INT, offsetof(ASSStyle, margin_r) },
116  {"MarginV", ASS_INT, offsetof(ASSStyle, margin_v) },
117  {"AlphaLevel", ASS_INT, offsetof(ASSStyle, alpha_level) },
118  {"Encoding", ASS_INT, offsetof(ASSStyle, encoding) },
119  {0},
120  }
121  },
122  { .section = "Events",
123  .format_header = "Format",
124  .fields_header = "Dialogue",
125  .size = sizeof(ASSDialog),
126  .offset = offsetof(ASS, dialogs),
127  .offset_count = offsetof(ASS, dialogs_count),
128  .fields = {{"Layer", ASS_INT, offsetof(ASSDialog, layer) },
129  {"Start", ASS_TIMESTAMP, offsetof(ASSDialog, start) },
130  {"End", ASS_TIMESTAMP, offsetof(ASSDialog, end) },
131  {"Style", ASS_STR, offsetof(ASSDialog, style) },
132  {"Name", ASS_STR, offsetof(ASSDialog, name) },
133  {"MarginL", ASS_INT, offsetof(ASSDialog, margin_l)},
134  {"MarginR", ASS_INT, offsetof(ASSDialog, margin_r)},
135  {"MarginV", ASS_INT, offsetof(ASSDialog, margin_v)},
136  {"Effect", ASS_STR, offsetof(ASSDialog, effect) },
137  {"Text", ASS_STR, offsetof(ASSDialog, text) },
138  {0},
139  }
140  },
141 };
142 
143 
144 typedef int (*ASSConvertFunc)(void *dest, const char *buf, int len);
145 
146 static int convert_str(void *dest, const char *buf, int len)
147 {
148  char *str = av_malloc(len + 1);
149  if (str) {
150  memcpy(str, buf, len);
151  str[len] = 0;
152  if (*(void **)dest)
153  av_free(*(void **)dest);
154  *(char **)dest = str;
155  }
156  return !str;
157 }
158 static int convert_int(void *dest, const char *buf, int len)
159 {
160  return sscanf(buf, "%d", (int *)dest) == 1;
161 }
162 static int convert_flt(void *dest, const char *buf, int len)
163 {
164  return sscanf(buf, "%f", (float *)dest) == 1;
165 }
166 static int convert_color(void *dest, const char *buf, int len)
167 {
168  return sscanf(buf, "&H%8x", (int *)dest) == 1 ||
169  sscanf(buf, "%d", (int *)dest) == 1;
170 }
171 static int convert_timestamp(void *dest, const char *buf, int len)
172 {
173  int c, h, m, s, cs;
174  if ((c = sscanf(buf, "%d:%02d:%02d.%02d", &h, &m, &s, &cs)) == 4)
175  *(int *)dest = 360000*h + 6000*m + 100*s + cs;
176  return c == 4;
177 }
178 static int convert_alignment(void *dest, const char *buf, int len)
179 {
180  int a;
181  if (sscanf(buf, "%d", &a) == 1) {
182  /* convert V4 Style alignment to V4+ Style */
183  *(int *)dest = a + ((a&4) >> 1) - 5*!!(a&8);
184  return 1;
185  }
186  return 0;
187 }
188 
189 static const ASSConvertFunc convert_func[] = {
190  [ASS_STR] = convert_str,
191  [ASS_INT] = convert_int,
192  [ASS_FLT] = convert_flt,
196 };
197 
198 
204 };
205 
206 
208 {
209  const ASSSection *section = &ass_sections[ctx->current_section];
210  int *count = (int *)((uint8_t *)&ctx->ass + section->offset_count);
211  void **section_ptr = (void **)((uint8_t *)&ctx->ass + section->offset);
212  uint8_t *tmp = av_realloc_array(*section_ptr, (*count+1), section->size);
213  if (!tmp)
214  return NULL;
215  *section_ptr = tmp;
216  tmp += *count * section->size;
217  memset(tmp, 0, section->size);
218  (*count)++;
219  return tmp;
220 }
221 
222 static inline int is_eol(char buf)
223 {
224  return buf == '\r' || buf == '\n' || buf == 0;
225 }
226 
227 static inline const char *skip_space(const char *buf)
228 {
229  while (*buf == ' ')
230  buf++;
231  return buf;
232 }
233 
234 static int *get_default_field_orders(const ASSSection *section, int *number)
235 {
236  int i;
237  int *order = av_malloc_array(FF_ARRAY_ELEMS(section->fields), sizeof(*order));
238 
239  if (!order)
240  return NULL;
241  for (i = 0; section->fields[i].name; i++)
242  order[i] = i;
243  *number = i;
244  while (i < FF_ARRAY_ELEMS(section->fields))
245  order[i++] = -1;
246  return order;
247 }
248 
249 static const char *ass_split_section(ASSSplitContext *ctx, const char *buf)
250 {
251  const ASSSection *section = &ass_sections[ctx->current_section];
252  int *number = &ctx->field_number[ctx->current_section];
253  int *order = ctx->field_order[ctx->current_section];
254  int i, len;
255 
256  while (buf && *buf) {
257  if (buf[0] == '[') {
258  ctx->current_section = -1;
259  break;
260  }
261  if (buf[0] == ';' || (buf[0] == '!' && buf[1] == ':'))
262  goto next_line; // skip comments
263 
264  len = strcspn(buf, ":\r\n");
265  if (buf[len] == ':' &&
266  (!section->fields_header || strncmp(buf, section->fields_header, len))) {
267  for (i = 0; i < FF_ARRAY_ELEMS(ass_sections); i++) {
268  if (ass_sections[i].fields_header &&
269  !strncmp(buf, ass_sections[i].fields_header, len)) {
270  ctx->current_section = i;
271  section = &ass_sections[ctx->current_section];
272  number = &ctx->field_number[ctx->current_section];
273  order = ctx->field_order[ctx->current_section];
274  break;
275  }
276  }
277  }
278  if (section->format_header && !order) {
279  len = strlen(section->format_header);
280  if (!strncmp(buf, section->format_header, len) && buf[len] == ':') {
281  buf += len + 1;
282  while (!is_eol(*buf)) {
283  buf = skip_space(buf);
284  len = strcspn(buf, ", \r\n");
285  if (av_reallocp_array(&order, (*number + 1), sizeof(*order)) != 0)
286  return NULL;
287 
288  order[*number] = -1;
289  for (i=0; section->fields[i].name; i++)
290  if (!strncmp(buf, section->fields[i].name, len)) {
291  order[*number] = i;
292  break;
293  }
294  (*number)++;
295  buf = skip_space(buf + len + (buf[len] == ','));
296  }
297  ctx->field_order[ctx->current_section] = order;
298  goto next_line;
299  }
300  }
301  if (section->fields_header) {
302  len = strlen(section->fields_header);
303  if (!strncmp(buf, section->fields_header, len) && buf[len] == ':') {
304  uint8_t *ptr, *struct_ptr = realloc_section_array(ctx);
305  if (!struct_ptr) return NULL;
306 
307  /* No format header line found so far, assume default */
308  if (!order) {
309  order = get_default_field_orders(section, number);
310  if (!order)
311  return NULL;
312  ctx->field_order[ctx->current_section] = order;
313  }
314 
315  buf += len + 1;
316  for (i=0; !is_eol(*buf) && i < *number; i++) {
317  int last = i == *number - 1;
318  buf = skip_space(buf);
319  len = strcspn(buf, last ? "\r\n" : ",\r\n");
320  if (order[i] >= 0) {
321  ASSFieldType type = section->fields[order[i]].type;
322  ptr = struct_ptr + section->fields[order[i]].offset;
323  convert_func[type](ptr, buf, len);
324  }
325  buf += len;
326  if (!last && *buf) buf++;
327  buf = skip_space(buf);
328  }
329  }
330  } else {
331  len = strcspn(buf, ":\r\n");
332  if (buf[len] == ':') {
333  for (i=0; section->fields[i].name; i++)
334  if (!strncmp(buf, section->fields[i].name, len)) {
335  ASSFieldType type = section->fields[i].type;
336  uint8_t *ptr = (uint8_t *)&ctx->ass + section->offset;
337  ptr += section->fields[i].offset;
338  buf = skip_space(buf + len + 1);
339  convert_func[type](ptr, buf, strcspn(buf, "\r\n"));
340  break;
341  }
342  }
343  }
344 next_line:
345  buf += strcspn(buf, "\n");
346  buf += !!*buf;
347  }
348  return buf;
349 }
350 
351 static int ass_split(ASSSplitContext *ctx, const char *buf)
352 {
353  char c, section[16];
354  int i;
355 
356  if (ctx->current_section >= 0)
357  buf = ass_split_section(ctx, buf);
358 
359  while (buf && *buf) {
360  if (sscanf(buf, "[%15[0-9A-Za-z+ ]]%c", section, &c) == 2) {
361  buf += strcspn(buf, "\n");
362  buf += !!*buf;
363  for (i=0; i<FF_ARRAY_ELEMS(ass_sections); i++)
364  if (!strcmp(section, ass_sections[i].section)) {
365  ctx->current_section = i;
366  buf = ass_split_section(ctx, buf);
367  }
368  } else {
369  buf += strcspn(buf, "\n");
370  buf += !!*buf;
371  }
372  }
373  return buf ? 0 : AVERROR_INVALIDDATA;
374 }
375 
376 ASSSplitContext *ff_ass_split(const char *buf)
377 {
378  ASSSplitContext *ctx = av_mallocz(sizeof(*ctx));
379  if (!ctx)
380  return NULL;
381  if (buf && !strncmp(buf, "\xef\xbb\xbf", 3)) // Skip UTF-8 BOM header
382  buf += 3;
383  ctx->current_section = -1;
384  if (ass_split(ctx, buf) < 0) {
386  return NULL;
387  }
388  return ctx;
389 }
390 
392 {
393  uint8_t *ptr = (uint8_t *)&ctx->ass + section->offset;
394  int i, j, *count, c = 1;
395 
396  if (section->format_header) {
397  ptr = *(void **)ptr;
398  count = (int *)((uint8_t *)&ctx->ass + section->offset_count);
399  } else
400  count = &c;
401 
402  if (ptr)
403  for (i=0; i<*count; i++, ptr += section->size)
404  for (j=0; section->fields[j].name; j++) {
405  const ASSFields *field = &section->fields[j];
406  if (field->type == ASS_STR)
407  av_freep(ptr + field->offset);
408  }
409  *count = 0;
410 
411  if (section->format_header)
412  av_freep((uint8_t *)&ctx->ass + section->offset);
413 }
414 
416 {
417  ASSDialog *dialog = *dialogp;
418  if (!dialog)
419  return;
420  av_freep(&dialog->style);
421  av_freep(&dialog->name);
422  av_freep(&dialog->effect);
423  av_freep(&dialog->text);
424  av_freep(dialogp);
425 }
426 
428 {
429  int i;
430  static const ASSFields fields[] = {
431  {"ReadOrder", ASS_INT, offsetof(ASSDialog, readorder)},
432  {"Layer", ASS_INT, offsetof(ASSDialog, layer) },
433  {"Style", ASS_STR, offsetof(ASSDialog, style) },
434  {"Name", ASS_STR, offsetof(ASSDialog, name) },
435  {"MarginL", ASS_INT, offsetof(ASSDialog, margin_l) },
436  {"MarginR", ASS_INT, offsetof(ASSDialog, margin_r) },
437  {"MarginV", ASS_INT, offsetof(ASSDialog, margin_v) },
438  {"Effect", ASS_STR, offsetof(ASSDialog, effect) },
439  {"Text", ASS_STR, offsetof(ASSDialog, text) },
440  };
441 
442  ASSDialog *dialog = av_mallocz(sizeof(*dialog));
443  if (!dialog)
444  return NULL;
445 
446  for (i = 0; i < FF_ARRAY_ELEMS(fields); i++) {
447  size_t len;
448  const int last = i == FF_ARRAY_ELEMS(fields) - 1;
449  const ASSFieldType type = fields[i].type;
450  uint8_t *ptr = (uint8_t *)dialog + fields[i].offset;
451  buf = skip_space(buf);
452  len = last ? strlen(buf) : strcspn(buf, ",");
453  if (len >= INT_MAX) {
454  ff_ass_free_dialog(&dialog);
455  return NULL;
456  }
457  convert_func[type](ptr, buf, len);
458  buf += len;
459  if (*buf) buf++;
460  }
461  return dialog;
462 }
463 
465 {
466  if (ctx) {
467  int i;
468  for (i=0; i<FF_ARRAY_ELEMS(ass_sections); i++) {
470  av_freep(&(ctx->field_order[i]));
471  }
472  av_free(ctx);
473  }
474 }
475 
476 
478  const char *buf)
479 {
480  const char *text = NULL;
481  char new_line[2];
482  int text_len = 0;
483 
484  while (buf && *buf) {
485  if (text && callbacks->text &&
486  (sscanf(buf, "\\%1[nN]", new_line) == 1 ||
487  !strncmp(buf, "{\\", 2))) {
488  callbacks->text(priv, text, text_len);
489  text = NULL;
490  }
491  if (sscanf(buf, "\\%1[nN]", new_line) == 1) {
492  if (callbacks->new_line)
493  callbacks->new_line(priv, new_line[0] == 'N');
494  buf += 2;
495  } else if (!strncmp(buf, "{\\", 2)) {
496  buf++;
497  while (*buf == '\\') {
498  char style[2], c[2], sep[2], c_num[2] = "0", tmp[128] = {0};
499  unsigned int color = 0xFFFFFFFF;
500  int len, size = -1, an = -1, alpha = -1;
501  int x1, y1, x2, y2, t1 = -1, t2 = -1;
502  if (sscanf(buf, "\\%1[bisu]%1[01\\}]%n", style, c, &len) > 1) {
503  int close = c[0] == '0' ? 1 : c[0] == '1' ? 0 : -1;
504  len += close != -1;
505  if (callbacks->style)
506  callbacks->style(priv, style[0], close);
507  } else if (sscanf(buf, "\\c%1[\\}]%n", sep, &len) > 0 ||
508  sscanf(buf, "\\c&H%X&%1[\\}]%n", &color, sep, &len) > 1 ||
509  sscanf(buf, "\\%1[1234]c%1[\\}]%n", c_num, sep, &len) > 1 ||
510  sscanf(buf, "\\%1[1234]c&H%X&%1[\\}]%n", c_num, &color, sep, &len) > 2) {
511  if (callbacks->color)
512  callbacks->color(priv, color, c_num[0] - '0');
513  } else if (sscanf(buf, "\\alpha%1[\\}]%n", sep, &len) > 0 ||
514  sscanf(buf, "\\alpha&H%2X&%1[\\}]%n", &alpha, sep, &len) > 1 ||
515  sscanf(buf, "\\%1[1234]a%1[\\}]%n", c_num, sep, &len) > 1 ||
516  sscanf(buf, "\\%1[1234]a&H%2X&%1[\\}]%n", c_num, &alpha, sep, &len) > 2) {
517  if (callbacks->alpha)
518  callbacks->alpha(priv, alpha, c_num[0] - '0');
519  } else if (sscanf(buf, "\\fn%1[\\}]%n", sep, &len) > 0 ||
520  sscanf(buf, "\\fn%127[^\\}]%1[\\}]%n", tmp, sep, &len) > 1) {
521  if (callbacks->font_name)
522  callbacks->font_name(priv, tmp[0] ? tmp : NULL);
523  } else if (sscanf(buf, "\\fs%1[\\}]%n", sep, &len) > 0 ||
524  sscanf(buf, "\\fs%u%1[\\}]%n", &size, sep, &len) > 1) {
525  if (callbacks->font_size)
526  callbacks->font_size(priv, size);
527  } else if (sscanf(buf, "\\a%1[\\}]%n", sep, &len) > 0 ||
528  sscanf(buf, "\\a%2u%1[\\}]%n", &an, sep, &len) > 1 ||
529  sscanf(buf, "\\an%1[\\}]%n", sep, &len) > 0 ||
530  sscanf(buf, "\\an%1u%1[\\}]%n", &an, sep, &len) > 1) {
531  if (an != -1 && buf[2] != 'n')
532  an = (an&3) + (an&4 ? 6 : an&8 ? 3 : 0);
533  if (callbacks->alignment)
534  callbacks->alignment(priv, an);
535  } else if (sscanf(buf, "\\r%1[\\}]%n", sep, &len) > 0 ||
536  sscanf(buf, "\\r%127[^\\}]%1[\\}]%n", tmp, sep, &len) > 1) {
537  if (callbacks->cancel_overrides)
538  callbacks->cancel_overrides(priv, tmp);
539  } else if (sscanf(buf, "\\move(%d,%d,%d,%d)%1[\\}]%n", &x1, &y1, &x2, &y2, sep, &len) > 4 ||
540  sscanf(buf, "\\move(%d,%d,%d,%d,%d,%d)%1[\\}]%n", &x1, &y1, &x2, &y2, &t1, &t2, sep, &len) > 6) {
541  if (callbacks->move)
542  callbacks->move(priv, x1, y1, x2, y2, t1, t2);
543  } else if (sscanf(buf, "\\pos(%d,%d)%1[\\}]%n", &x1, &y1, sep, &len) > 2) {
544  if (callbacks->move)
545  callbacks->move(priv, x1, y1, x1, y1, -1, -1);
546  } else if (sscanf(buf, "\\org(%d,%d)%1[\\}]%n", &x1, &y1, sep, &len) > 2) {
547  if (callbacks->origin)
548  callbacks->origin(priv, x1, y1);
549  } else {
550  len = strcspn(buf+1, "\\}") + 2; /* skip unknown code */
551  }
552  buf += len - 1;
553  }
554  if (*buf++ != '}')
555  return AVERROR_INVALIDDATA;
556  } else {
557  if (!text) {
558  text = buf;
559  text_len = 1;
560  } else
561  text_len++;
562  buf++;
563  }
564  }
565  if (text && callbacks->text)
566  callbacks->text(priv, text, text_len);
567  if (callbacks->end)
568  callbacks->end(priv);
569  return 0;
570 }
571 
573 {
574  ASS *ass = &ctx->ass;
575  int i;
576 
577  if (!style || !*style)
578  style = "Default";
579  for (i=0; i<ass->styles_count; i++)
580  if (ass->styles[i].name && !strcmp(ass->styles[i].name, style))
581  return ass->styles + i;
582  return NULL;
583 }
ASS_TIMESTAMP
@ ASS_TIMESTAMP
Definition: ass_split.c:32
name
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default minimum maximum flags name is the option name
Definition: writing_filters.txt:88
ASSCodesCallbacks
Set of callback functions corresponding to each override codes that can be encountered in a "Dialogue...
Definition: ass_split.h:138
convert_str
static int convert_str(void *dest, const char *buf, int len)
Definition: ass_split.c:146
color
Definition: vf_paletteuse.c:599
is_eol
static int is_eol(char buf)
Definition: ass_split.c:222
ASSFieldType
ASSFieldType
Definition: ass_split.c:27
ASSFields
Definition: ass_split.c:36
convert_func
static const ASSConvertFunc convert_func[]
Definition: ass_split.c:189
callbacks
static const OMX_CALLBACKTYPE callbacks
Definition: omx.c:339
tmp
static uint8_t tmp[11]
Definition: aes_ctr.c:26
ff_ass_split_dialog
ASSDialog * ff_ass_split_dialog(ASSSplitContext *ctx, const char *buf)
Split one ASS Dialogue line from a string buffer.
Definition: ass_split.c:427
convert_flt
static int convert_flt(void *dest, const char *buf, int len)
Definition: ass_split.c:162
ASS::styles
ASSStyle * styles
array of split out styles
Definition: ass_split.h:92
t1
#define t1
Definition: regdef.h:29
ASS_ALGN
@ ASS_ALGN
Definition: ass_split.c:33
ASSDialog::style
char * style
name of the ASSStyle to use with this dialog
Definition: ass_split.h:76
ass_split_section
static const char * ass_split_section(ASSSplitContext *ctx, const char *buf)
Definition: ass_split.c:249
free_section
static void free_section(ASSSplitContext *ctx, const ASSSection *section)
Definition: ass_split.c:391
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:31
ass_split.h
type
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf type
Definition: writing_filters.txt:86
convert_color
static int convert_color(void *dest, const char *buf, int len)
Definition: ass_split.c:166
ff_ass_free_dialog
void ff_ass_free_dialog(ASSDialog **dialogp)
Free a dialogue obtained from ff_ass_split_dialog().
Definition: ass_split.c:415
ASSFields::type
int type
Definition: ass_split.c:38
ASSDialog::effect
char * effect
Definition: ass_split.h:81
ASS_STR
@ ASS_STR
Definition: ass_split.c:28
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
convert_alignment
static int convert_alignment(void *dest, const char *buf, int len)
Definition: ass_split.c:178
ASSSection::fields_header
const char * fields_header
Definition: ass_split.c:45
s
#define s(width, name)
Definition: cbs_vp9.c:257
av_realloc_array
void * av_realloc_array(void *ptr, size_t nmemb, size_t size)
Definition: mem.c:224
realloc_section_array
static uint8_t * realloc_section_array(ASSSplitContext *ctx)
Definition: ass_split.c:207
ASS_FLT
@ ASS_FLT
Definition: ass_split.c:30
ctx
AVFormatContext * ctx
Definition: movenc.c:48
ASSSection::section
const char * section
Definition: ass_split.c:43
ass_sections
static const ASSSection ass_sections[]
Definition: ass_split.c:52
field
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this field
Definition: writing_filters.txt:78
ASSSection::size
int size
Definition: ass_split.c:46
fields
the definition of that something depends on the semantic of the filter The callback must examine the status of the filter s links and proceed accordingly The status of output links is stored in the status_in and status_out fields and tested by the then the processing requires a frame on this link and the filter is expected to make efforts in that direction The status of input links is stored by the fifo and status_out fields
Definition: filter_design.txt:155
if
if(ret)
Definition: filter_design.txt:179
section::name
const char * name
Definition: ffprobe.c:149
ASS
structure containing the whole split ASS data
Definition: ass_split.h:90
ASSDialog::name
char * name
Definition: ass_split.h:77
NULL
#define NULL
Definition: coverity.c:32
ASSSplitContext::current_section
int current_section
Definition: ass_split.c:201
ASSScriptInfo
fields extracted from the [Script Info] section
Definition: ass_split.h:28
convert_timestamp
static int convert_timestamp(void *dest, const char *buf, int len)
Definition: ass_split.c:171
ASSSplitContext
This struct can be casted to ASS to access to the split data.
Definition: ass_split.c:199
ff_ass_split
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...
Definition: ass_split.c:376
ASSConvertFunc
int(* ASSConvertFunc)(void *dest, const char *buf, int len)
Definition: ass_split.c:144
c
Undefined Behavior In the C some operations are like signed integer dereferencing freed accessing outside allocated Undefined Behavior must not occur in a C it is not safe even if the output of undefined operations is unused The unsafety may seem nit picking but Optimizing compilers have in fact optimized code on the assumption that no undefined Behavior occurs Optimizing code based on wrong assumptions can and has in some cases lead to effects beyond the output of computations The signed integer overflow problem in speed critical code Code which is highly optimized and works with signed integers sometimes has the problem that often the output of the computation does not c
Definition: undefined.txt:32
ASSStyle
fields extracted from the [V4(+) Styles] section
Definition: ass_split.h:39
error.h
ASS_COLOR
@ ASS_COLOR
Definition: ass_split.c:31
ff_ass_split_free
void ff_ass_split_free(ASSSplitContext *ctx)
Free all the memory allocated for an ASSSplitContext.
Definition: ass_split.c:464
ASSDialog::text
char * text
actual text which will be displayed as a subtitle, can include style override control codes (see ff_a...
Definition: ass_split.h:82
ASSStyle::name
char * name
name of the tyle (case sensitive)
Definition: ass_split.h:40
size
int size
Definition: twinvq_data.h:10344
section
Definition: ffprobe.c:147
a
The reader does not expect b to be semantically here and if the code is changed by maybe adding a a division or other the signedness will almost certainly be mistaken To avoid this confusion a new type was SUINT is the C unsigned type but it holds a signed int to use the same example SUINT a
Definition: undefined.txt:41
av_reallocp_array
int av_reallocp_array(void *ptr, size_t nmemb, size_t size)
Allocate, reallocate, or free an array through a pointer to a pointer.
Definition: mem.c:232
offset
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf offset
Definition: writing_filters.txt:86
ff_ass_style_get
ASSStyle * ff_ass_style_get(ASSSplitContext *ctx, const char *style)
Find an ASSStyle structure by its name.
Definition: ass_split.c:572
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:271
av_malloc_array
#define av_malloc_array(a, b)
Definition: tableprint_vlc.h:32
common.h
ASSFields::offset
int offset
Definition: ass_split.c:39
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:263
ASS::styles_count
int styles_count
number of ASSStyle in the styles array
Definition: ass_split.h:93
len
int len
Definition: vorbis_enc_data.h:426
ASSFields::name
const char * name
Definition: ass_split.c:37
convert_int
static int convert_int(void *dest, const char *buf, int len)
Definition: ass_split.c:158
t2
#define t2
Definition: regdef.h:30
ASSSection
Definition: ass_split.c:42
ASS_INT
@ ASS_INT
Definition: ass_split.c:29
ASSDialog
fields extracted from the [Events] section
Definition: ass_split.h:71
mem.h
ass_split
static int ass_split(ASSSplitContext *ctx, const char *buf)
Definition: ass_split.c:351
ASSSection::offset
int offset
Definition: ass_split.c:47
av_free
#define av_free(p)
Definition: tableprint_vlc.h:34
alpha
static const int16_t alpha[]
Definition: ilbcdata.h:55
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
convert_header.str
string str
Definition: convert_header.py:20
ASSSplitContext::ass
ASS ass
Definition: ass_split.c:200
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:61
ff_ass_split_override_codes
int ff_ass_split_override_codes(const ASSCodesCallbacks *callbacks, void *priv, const char *buf)
Split override codes out of a ASS "Dialogue" Text field.
Definition: ass_split.c:477
ASSSection::format_header
const char * format_header
Definition: ass_split.c:44
h
h
Definition: vp9dsp_template.c:2038
ASSSection::offset_count
int offset_count
Definition: ass_split.c:48
skip_space
static const char * skip_space(const char *buf)
Definition: ass_split.c:227
ASSSplitContext::field_order
int * field_order[FF_ARRAY_ELEMS(ass_sections)]
Definition: ass_split.c:203
int
int
Definition: ffmpeg_filter.c:153
ASSSplitContext::field_number
int field_number[FF_ARRAY_ELEMS(ass_sections)]
Definition: ass_split.c:202
get_default_field_orders
static int * get_default_field_orders(const ASSSection *section, int *number)
Definition: ass_split.c:234