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 "avcodec.h"
23 #include "ass_split.h"
24 
25 typedef enum {
32 } ASSFieldType;
33 
34 typedef struct {
35  const char *name;
36  int type;
37  int offset;
38 } ASSFields;
39 
40 typedef struct {
41  const char *section;
42  const char *format_header;
43  const char *fields_header;
44  int size;
45  int offset;
48 } ASSSection;
49 
50 static const ASSSection ass_sections[] = {
51  { .section = "Script Info",
52  .offset = offsetof(ASS, script_info),
53  .fields = {{"ScriptType", ASS_STR, offsetof(ASSScriptInfo, script_type)},
54  {"Collisions", ASS_STR, offsetof(ASSScriptInfo, collisions) },
55  {"PlayResX", ASS_INT, offsetof(ASSScriptInfo, play_res_x) },
56  {"PlayResY", ASS_INT, offsetof(ASSScriptInfo, play_res_y) },
57  {"Timer", ASS_FLT, offsetof(ASSScriptInfo, timer) },
58  {0},
59  }
60  },
61  { .section = "V4+ Styles",
62  .format_header = "Format",
63  .fields_header = "Style",
64  .size = sizeof(ASSStyle),
65  .offset = offsetof(ASS, styles),
66  .offset_count = offsetof(ASS, styles_count),
67  .fields = {{"Name", ASS_STR, offsetof(ASSStyle, name) },
68  {"Fontname", ASS_STR, offsetof(ASSStyle, font_name) },
69  {"Fontsize", ASS_INT, offsetof(ASSStyle, font_size) },
70  {"PrimaryColour", ASS_COLOR, offsetof(ASSStyle, primary_color) },
71  {"SecondaryColour", ASS_COLOR, offsetof(ASSStyle, secondary_color)},
72  {"OutlineColour", ASS_COLOR, offsetof(ASSStyle, outline_color) },
73  {"BackColour", ASS_COLOR, offsetof(ASSStyle, back_color) },
74  {"Bold", ASS_INT, offsetof(ASSStyle, bold) },
75  {"Italic", ASS_INT, offsetof(ASSStyle, italic) },
76  {"Underline", ASS_INT, offsetof(ASSStyle, underline) },
77  {"StrikeOut", ASS_INT, offsetof(ASSStyle, strikeout) },
78  {"ScaleX", ASS_FLT, offsetof(ASSStyle, scalex) },
79  {"ScaleY", ASS_FLT, offsetof(ASSStyle, scaley) },
80  {"Spacing", ASS_FLT, offsetof(ASSStyle, spacing) },
81  {"Angle", ASS_FLT, offsetof(ASSStyle, angle) },
82  {"BorderStyle", ASS_INT, offsetof(ASSStyle, border_style) },
83  {"Outline", ASS_FLT, offsetof(ASSStyle, outline) },
84  {"Shadow", ASS_FLT, offsetof(ASSStyle, shadow) },
85  {"Alignment", ASS_INT, offsetof(ASSStyle, alignment) },
86  {"MarginL", ASS_INT, offsetof(ASSStyle, margin_l) },
87  {"MarginR", ASS_INT, offsetof(ASSStyle, margin_r) },
88  {"MarginV", ASS_INT, offsetof(ASSStyle, margin_v) },
89  {"Encoding", ASS_INT, offsetof(ASSStyle, encoding) },
90  {0},
91  }
92  },
93  { .section = "V4 Styles",
94  .format_header = "Format",
95  .fields_header = "Style",
96  .size = sizeof(ASSStyle),
97  .offset = offsetof(ASS, styles),
98  .offset_count = offsetof(ASS, styles_count),
99  .fields = {{"Name", ASS_STR, offsetof(ASSStyle, name) },
100  {"Fontname", ASS_STR, offsetof(ASSStyle, font_name) },
101  {"Fontsize", ASS_INT, offsetof(ASSStyle, font_size) },
102  {"PrimaryColour", ASS_COLOR, offsetof(ASSStyle, primary_color) },
103  {"SecondaryColour", ASS_COLOR, offsetof(ASSStyle, secondary_color)},
104  {"TertiaryColour", ASS_COLOR, offsetof(ASSStyle, outline_color) },
105  {"BackColour", ASS_COLOR, offsetof(ASSStyle, back_color) },
106  {"Bold", ASS_INT, offsetof(ASSStyle, bold) },
107  {"Italic", ASS_INT, offsetof(ASSStyle, italic) },
108  {"BorderStyle", ASS_INT, offsetof(ASSStyle, border_style) },
109  {"Outline", ASS_FLT, offsetof(ASSStyle, outline) },
110  {"Shadow", ASS_FLT, offsetof(ASSStyle, shadow) },
111  {"Alignment", ASS_ALGN, offsetof(ASSStyle, alignment) },
112  {"MarginL", ASS_INT, offsetof(ASSStyle, margin_l) },
113  {"MarginR", ASS_INT, offsetof(ASSStyle, margin_r) },
114  {"MarginV", ASS_INT, offsetof(ASSStyle, margin_v) },
115  {"AlphaLevel", ASS_INT, offsetof(ASSStyle, alpha_level) },
116  {"Encoding", ASS_INT, offsetof(ASSStyle, encoding) },
117  {0},
118  }
119  },
120  { .section = "Events",
121  .format_header = "Format",
122  .fields_header = "Dialogue",
123  .size = sizeof(ASSDialog),
124  .offset = offsetof(ASS, dialogs),
125  .offset_count = offsetof(ASS, dialogs_count),
126  .fields = {{"Layer", ASS_INT, offsetof(ASSDialog, layer) },
127  {"Start", ASS_TIMESTAMP, offsetof(ASSDialog, start) },
128  {"End", ASS_TIMESTAMP, offsetof(ASSDialog, end) },
129  {"Style", ASS_STR, offsetof(ASSDialog, style) },
130  {"Name", ASS_STR, offsetof(ASSDialog, name) },
131  {"MarginL", ASS_INT, offsetof(ASSDialog, margin_l)},
132  {"MarginR", ASS_INT, offsetof(ASSDialog, margin_r)},
133  {"MarginV", ASS_INT, offsetof(ASSDialog, margin_v)},
134  {"Effect", ASS_STR, offsetof(ASSDialog, effect) },
135  {"Text", ASS_STR, offsetof(ASSDialog, text) },
136  {0},
137  }
138  },
139 };
140 
141 
142 typedef int (*ASSConvertFunc)(void *dest, const char *buf, int len);
143 
144 static int convert_str(void *dest, const char *buf, int len)
145 {
146  char *str = av_malloc(len + 1);
147  if (str) {
148  memcpy(str, buf, len);
149  str[len] = 0;
150  if (*(void **)dest)
151  av_free(*(void **)dest);
152  *(char **)dest = str;
153  }
154  return !str;
155 }
156 static int convert_int(void *dest, const char *buf, int len)
157 {
158  return sscanf(buf, "%d", (int *)dest) == 1;
159 }
160 static int convert_flt(void *dest, const char *buf, int len)
161 {
162  return sscanf(buf, "%f", (float *)dest) == 1;
163 }
164 static int convert_color(void *dest, const char *buf, int len)
165 {
166  return sscanf(buf, "&H%8x", (int *)dest) == 1 ||
167  sscanf(buf, "%d", (int *)dest) == 1;
168 }
169 static int convert_timestamp(void *dest, const char *buf, int len)
170 {
171  int c, h, m, s, cs;
172  if ((c = sscanf(buf, "%d:%02d:%02d.%02d", &h, &m, &s, &cs)) == 4)
173  *(int *)dest = 360000*h + 6000*m + 100*s + cs;
174  return c == 4;
175 }
176 static int convert_alignment(void *dest, const char *buf, int len)
177 {
178  int a;
179  if (sscanf(buf, "%d", &a) == 1) {
180  /* convert V4 Style alignment to V4+ Style */
181  *(int *)dest = a + ((a&4) >> 1) - 5*!!(a&8);
182  return 1;
183  }
184  return 0;
185 }
186 
187 static const ASSConvertFunc convert_func[] = {
188  [ASS_STR] = convert_str,
189  [ASS_INT] = convert_int,
190  [ASS_FLT] = convert_flt,
194 };
195 
196 
202 };
203 
204 
206 {
207  const ASSSection *section = &ass_sections[ctx->current_section];
208  int *count = (int *)((uint8_t *)&ctx->ass + section->offset_count);
209  void **section_ptr = (void **)((uint8_t *)&ctx->ass + section->offset);
210  uint8_t *tmp = av_realloc_array(*section_ptr, (*count+1), section->size);
211  if (!tmp)
212  return NULL;
213  *section_ptr = tmp;
214  tmp += *count * section->size;
215  memset(tmp, 0, section->size);
216  (*count)++;
217  return tmp;
218 }
219 
220 static inline int is_eol(char buf)
221 {
222  return buf == '\r' || buf == '\n' || buf == 0;
223 }
224 
225 static inline const char *skip_space(const char *buf)
226 {
227  while (*buf == ' ')
228  buf++;
229  return buf;
230 }
231 
232 static int *get_default_field_orders(const ASSSection *section, int *number)
233 {
234  int i;
235  int *order = av_malloc_array(FF_ARRAY_ELEMS(section->fields), sizeof(*order));
236 
237  if (!order)
238  return NULL;
239  for (i = 0; section->fields[i].name; i++)
240  order[i] = i;
241  *number = i;
242  while (i < FF_ARRAY_ELEMS(section->fields))
243  order[i++] = -1;
244  return order;
245 }
246 
247 static const char *ass_split_section(ASSSplitContext *ctx, const char *buf)
248 {
249  const ASSSection *section = &ass_sections[ctx->current_section];
250  int *number = &ctx->field_number[ctx->current_section];
251  int *order = ctx->field_order[ctx->current_section];
252  int i, len;
253 
254  while (buf && *buf) {
255  if (buf[0] == '[') {
256  ctx->current_section = -1;
257  break;
258  }
259  if (buf[0] == ';' || (buf[0] == '!' && buf[1] == ':'))
260  goto next_line; // skip comments
261 
262  len = strcspn(buf, ":\r\n");
263  if (buf[len] == ':' &&
264  (!section->fields_header || strncmp(buf, section->fields_header, len))) {
265  for (i = 0; i < FF_ARRAY_ELEMS(ass_sections); i++) {
266  if (ass_sections[i].fields_header &&
267  !strncmp(buf, ass_sections[i].fields_header, len)) {
268  ctx->current_section = i;
269  section = &ass_sections[ctx->current_section];
270  number = &ctx->field_number[ctx->current_section];
271  order = ctx->field_order[ctx->current_section];
272  break;
273  }
274  }
275  }
276  if (section->format_header && !order) {
277  len = strlen(section->format_header);
278  if (!strncmp(buf, section->format_header, len) && buf[len] == ':') {
279  buf += len + 1;
280  while (!is_eol(*buf)) {
281  buf = skip_space(buf);
282  len = strcspn(buf, ", \r\n");
283  if (av_reallocp_array(&order, (*number + 1), sizeof(*order)) != 0)
284  return NULL;
285 
286  order[*number] = -1;
287  for (i=0; section->fields[i].name; i++)
288  if (!strncmp(buf, section->fields[i].name, len)) {
289  order[*number] = i;
290  break;
291  }
292  (*number)++;
293  buf = skip_space(buf + len + (buf[len] == ','));
294  }
295  ctx->field_order[ctx->current_section] = order;
296  goto next_line;
297  }
298  }
299  if (section->fields_header) {
300  len = strlen(section->fields_header);
301  if (!strncmp(buf, section->fields_header, len) && buf[len] == ':') {
302  uint8_t *ptr, *struct_ptr = realloc_section_array(ctx);
303  if (!struct_ptr) return NULL;
304 
305  /* No format header line found so far, assume default */
306  if (!order) {
307  order = get_default_field_orders(section, number);
308  if (!order)
309  return NULL;
310  ctx->field_order[ctx->current_section] = order;
311  }
312 
313  buf += len + 1;
314  for (i=0; !is_eol(*buf) && i < *number; i++) {
315  int last = i == *number - 1;
316  buf = skip_space(buf);
317  len = strcspn(buf, last ? "\r\n" : ",\r\n");
318  if (order[i] >= 0) {
319  ASSFieldType type = section->fields[order[i]].type;
320  ptr = struct_ptr + section->fields[order[i]].offset;
321  convert_func[type](ptr, buf, len);
322  }
323  buf += len;
324  if (!last && *buf) buf++;
325  buf = skip_space(buf);
326  }
327  }
328  } else {
329  len = strcspn(buf, ":\r\n");
330  if (buf[len] == ':') {
331  for (i=0; section->fields[i].name; i++)
332  if (!strncmp(buf, section->fields[i].name, len)) {
333  ASSFieldType type = section->fields[i].type;
334  uint8_t *ptr = (uint8_t *)&ctx->ass + section->offset;
335  ptr += section->fields[i].offset;
336  buf = skip_space(buf + len + 1);
337  convert_func[type](ptr, buf, strcspn(buf, "\r\n"));
338  break;
339  }
340  }
341  }
342 next_line:
343  buf += strcspn(buf, "\n");
344  buf += !!*buf;
345  }
346  return buf;
347 }
348 
349 static int ass_split(ASSSplitContext *ctx, const char *buf)
350 {
351  char c, section[16];
352  int i;
353 
354  if (ctx->current_section >= 0)
356 
357  while (buf && *buf) {
358  if (sscanf(buf, "[%15[0-9A-Za-z+ ]]%c", section, &c) == 2) {
359  buf += strcspn(buf, "\n");
360  buf += !!*buf;
361  for (i=0; i<FF_ARRAY_ELEMS(ass_sections); i++)
362  if (!strcmp(section, ass_sections[i].section)) {
363  ctx->current_section = i;
365  }
366  } else {
367  buf += strcspn(buf, "\n");
368  buf += !!*buf;
369  }
370  }
371  return buf ? 0 : AVERROR_INVALIDDATA;
372 }
373 
375 {
376  ASSSplitContext *ctx = av_mallocz(sizeof(*ctx));
377  if (!ctx)
378  return NULL;
379  ctx->current_section = -1;
380  if (ass_split(ctx, buf) < 0) {
382  return NULL;
383  }
384  return ctx;
385 }
386 
388 {
389  uint8_t *ptr = (uint8_t *)&ctx->ass + section->offset;
390  int i, j, *count, c = 1;
391 
392  if (section->format_header) {
393  ptr = *(void **)ptr;
394  count = (int *)((uint8_t *)&ctx->ass + section->offset_count);
395  } else
396  count = &c;
397 
398  if (ptr)
399  for (i=0; i<*count; i++, ptr += section->size)
400  for (j=0; section->fields[j].name; j++) {
401  const ASSFields *field = &section->fields[j];
402  if (field->type == ASS_STR)
403  av_freep(ptr + field->offset);
404  }
405  *count = 0;
406 
407  if (section->format_header)
408  av_freep((uint8_t *)&ctx->ass + section->offset);
409 }
410 
412  int cache, int *number)
413 {
414  ASSDialog *dialog = NULL;
415  int i, count;
416  if (!cache)
417  for (i=0; i<FF_ARRAY_ELEMS(ass_sections); i++)
418  if (!strcmp(ass_sections[i].section, "Events")) {
420  break;
421  }
422  count = ctx->ass.dialogs_count;
423  if (ass_split(ctx, buf) == 0)
424  dialog = ctx->ass.dialogs + count;
425  if (number)
426  *number = ctx->ass.dialogs_count - count;
427  return dialog;
428 }
429 
431 {
432  ASSDialog *dialog = *dialogp;
433  if (!dialog)
434  return;
435  av_freep(&dialog->style);
436  av_freep(&dialog->name);
437  av_freep(&dialog->effect);
438  av_freep(&dialog->text);
439  av_freep(dialogp);
440 }
441 
443 {
444  int i;
445  static const ASSFields fields[] = {
446  {"ReadOrder", ASS_INT, offsetof(ASSDialog, readorder)},
447  {"Layer", ASS_INT, offsetof(ASSDialog, layer) },
448  {"Style", ASS_STR, offsetof(ASSDialog, style) },
449  {"Name", ASS_STR, offsetof(ASSDialog, name) },
450  {"MarginL", ASS_INT, offsetof(ASSDialog, margin_l) },
451  {"MarginR", ASS_INT, offsetof(ASSDialog, margin_r) },
452  {"MarginV", ASS_INT, offsetof(ASSDialog, margin_v) },
453  {"Effect", ASS_STR, offsetof(ASSDialog, effect) },
454  {"Text", ASS_STR, offsetof(ASSDialog, text) },
455  };
456 
457  ASSDialog *dialog = av_mallocz(sizeof(*dialog));
458  if (!dialog)
459  return NULL;
460 
461  for (i = 0; i < FF_ARRAY_ELEMS(fields); i++) {
462  size_t len;
463  const int last = i == FF_ARRAY_ELEMS(fields) - 1;
464  const ASSFieldType type = fields[i].type;
465  uint8_t *ptr = (uint8_t *)dialog + fields[i].offset;
466  buf = skip_space(buf);
467  len = last ? strlen(buf) : strcspn(buf, ",");
468  if (len >= INT_MAX) {
469  ff_ass_free_dialog(&dialog);
470  return NULL;
471  }
472  convert_func[type](ptr, buf, len);
473  buf += len;
474  if (*buf) buf++;
475  }
476  return dialog;
477 }
478 
480 {
481  if (ctx) {
482  int i;
483  for (i=0; i<FF_ARRAY_ELEMS(ass_sections); i++) {
485  av_freep(&(ctx->field_order[i]));
486  }
487  av_free(ctx);
488  }
489 }
490 
491 
493  const char *buf)
494 {
495  const char *text = NULL;
496  char new_line[2];
497  int text_len = 0;
498 
499  while (buf && *buf) {
500  if (text && callbacks->text &&
501  (sscanf(buf, "\\%1[nN]", new_line) == 1 ||
502  !strncmp(buf, "{\\", 2))) {
503  callbacks->text(priv, text, text_len);
504  text = NULL;
505  }
506  if (sscanf(buf, "\\%1[nN]", new_line) == 1) {
507  if (callbacks->new_line)
508  callbacks->new_line(priv, new_line[0] == 'N');
509  buf += 2;
510  } else if (!strncmp(buf, "{\\", 2)) {
511  buf++;
512  while (*buf == '\\') {
513  char style[2], c[2], sep[2], c_num[2] = "0", tmp[128] = {0};
514  unsigned int color = 0xFFFFFFFF;
515  int len, size = -1, an = -1, alpha = -1;
516  int x1, y1, x2, y2, t1 = -1, t2 = -1;
517  if (sscanf(buf, "\\%1[bisu]%1[01\\}]%n", style, c, &len) > 1) {
518  int close = c[0] == '0' ? 1 : c[0] == '1' ? 0 : -1;
519  len += close != -1;
520  if (callbacks->style)
521  callbacks->style(priv, style[0], close);
522  } else if (sscanf(buf, "\\c%1[\\}]%n", sep, &len) > 0 ||
523  sscanf(buf, "\\c&H%X&%1[\\}]%n", &color, sep, &len) > 1 ||
524  sscanf(buf, "\\%1[1234]c%1[\\}]%n", c_num, sep, &len) > 1 ||
525  sscanf(buf, "\\%1[1234]c&H%X&%1[\\}]%n", c_num, &color, sep, &len) > 2) {
526  if (callbacks->color)
527  callbacks->color(priv, color, c_num[0] - '0');
528  } else if (sscanf(buf, "\\alpha%1[\\}]%n", sep, &len) > 0 ||
529  sscanf(buf, "\\alpha&H%2X&%1[\\}]%n", &alpha, sep, &len) > 1 ||
530  sscanf(buf, "\\%1[1234]a%1[\\}]%n", c_num, sep, &len) > 1 ||
531  sscanf(buf, "\\%1[1234]a&H%2X&%1[\\}]%n", c_num, &alpha, sep, &len) > 2) {
532  if (callbacks->alpha)
533  callbacks->alpha(priv, alpha, c_num[0] - '0');
534  } else if (sscanf(buf, "\\fn%1[\\}]%n", sep, &len) > 0 ||
535  sscanf(buf, "\\fn%127[^\\}]%1[\\}]%n", tmp, sep, &len) > 1) {
536  if (callbacks->font_name)
537  callbacks->font_name(priv, tmp[0] ? tmp : NULL);
538  } else if (sscanf(buf, "\\fs%1[\\}]%n", sep, &len) > 0 ||
539  sscanf(buf, "\\fs%u%1[\\}]%n", &size, sep, &len) > 1) {
540  if (callbacks->font_size)
541  callbacks->font_size(priv, size);
542  } else if (sscanf(buf, "\\a%1[\\}]%n", sep, &len) > 0 ||
543  sscanf(buf, "\\a%2u%1[\\}]%n", &an, sep, &len) > 1 ||
544  sscanf(buf, "\\an%1[\\}]%n", sep, &len) > 0 ||
545  sscanf(buf, "\\an%1u%1[\\}]%n", &an, sep, &len) > 1) {
546  if (an != -1 && buf[2] != 'n')
547  an = (an&3) + (an&4 ? 6 : an&8 ? 3 : 0);
548  if (callbacks->alignment)
549  callbacks->alignment(priv, an);
550  } else if (sscanf(buf, "\\r%1[\\}]%n", sep, &len) > 0 ||
551  sscanf(buf, "\\r%127[^\\}]%1[\\}]%n", tmp, sep, &len) > 1) {
552  if (callbacks->cancel_overrides)
553  callbacks->cancel_overrides(priv, tmp);
554  } else if (sscanf(buf, "\\move(%d,%d,%d,%d)%1[\\}]%n", &x1, &y1, &x2, &y2, sep, &len) > 4 ||
555  sscanf(buf, "\\move(%d,%d,%d,%d,%d,%d)%1[\\}]%n", &x1, &y1, &x2, &y2, &t1, &t2, sep, &len) > 6) {
556  if (callbacks->move)
557  callbacks->move(priv, x1, y1, x2, y2, t1, t2);
558  } else if (sscanf(buf, "\\pos(%d,%d)%1[\\}]%n", &x1, &y1, sep, &len) > 2) {
559  if (callbacks->move)
560  callbacks->move(priv, x1, y1, x1, y1, -1, -1);
561  } else if (sscanf(buf, "\\org(%d,%d)%1[\\}]%n", &x1, &y1, sep, &len) > 2) {
562  if (callbacks->origin)
563  callbacks->origin(priv, x1, y1);
564  } else {
565  len = strcspn(buf+1, "\\}") + 2; /* skip unknown code */
566  }
567  buf += len - 1;
568  }
569  if (*buf++ != '}')
570  return AVERROR_INVALIDDATA;
571  } else {
572  if (!text) {
573  text = buf;
574  text_len = 1;
575  } else
576  text_len++;
577  buf++;
578  }
579  }
580  if (text && callbacks->text)
581  callbacks->text(priv, text, text_len);
582  if (callbacks->end)
583  callbacks->end(priv);
584  return 0;
585 }
586 
588 {
589  ASS *ass = &ctx->ass;
590  int i;
591 
592  if (!style || !*style)
593  style = "Default";
594  for (i=0; i<ass->styles_count; i++)
595  if (ass->styles[i].name && !strcmp(ass->styles[i].name, style))
596  return ass->styles + i;
597  return NULL;
598 }
ASS_TIMESTAMP
@ ASS_TIMESTAMP
Definition: ass_split.c:30
ASSCodesCallbacks
Set of callback functions corresponding to each override codes that can be encountered in a "Dialogue...
Definition: ass_split.h:154
ff_ass_split_dialog
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 an already initializ...
Definition: ass_split.c:411
convert_str
static int convert_str(void *dest, const char *buf, int len)
Definition: ass_split.c:144
color
Definition: vf_paletteuse.c:588
is_eol
static int is_eol(char buf)
Definition: ass_split.c:220
ASSFieldType
ASSFieldType
Definition: ass_split.c:25
ASSFields
Definition: ass_split.c:34
convert_func
static const ASSConvertFunc convert_func[]
Definition: ass_split.c:187
count
void INT64 INT64 count
Definition: avisynth_c.h:767
end
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:90
callbacks
static const OMX_CALLBACKTYPE callbacks
Definition: omx.c:332
tmp
static uint8_t tmp[11]
Definition: aes_ctr.c:26
convert_flt
static int convert_flt(void *dest, const char *buf, int len)
Definition: ass_split.c:160
name
const char * name
Definition: avisynth_c.h:867
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:31
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:247
free_section
static void free_section(ASSSplitContext *ctx, const ASSSection *section)
Definition: ass_split.c:387
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:31
start
void INT64 start
Definition: avisynth_c.h:767
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:164
ff_ass_free_dialog
void ff_ass_free_dialog(ASSDialog **dialogp)
Free a dialogue obtained from ff_ass_split_dialog2().
Definition: ass_split.c:430
ASSFields::type
int type
Definition: ass_split.c:36
ASSDialog::effect
char * effect
Definition: ass_split.h:81
ASS_STR
@ ASS_STR
Definition: ass_split.c:26
buf
void * buf
Definition: avisynth_c.h:766
convert_alignment
static int convert_alignment(void *dest, const char *buf, int len)
Definition: ass_split.c:176
ASSSection::fields_header
const char * fields_header
Definition: ass_split.c:43
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:198
realloc_section_array
static uint8_t * realloc_section_array(ASSSplitContext *ctx)
Definition: ass_split.c:205
ASS_FLT
@ ASS_FLT
Definition: ass_split.c:28
ctx
AVFormatContext * ctx
Definition: movenc.c:48
ASSSection::section
const char * section
Definition: ass_split.c:41
ass_sections
static const ASSSection ass_sections[]
Definition: ass_split.c:50
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:44
ff_ass_split_dialog2
ASSDialog * ff_ass_split_dialog2(ASSSplitContext *ctx, const char *buf)
Split one ASS Dialogue line from a string buffer.
Definition: ass_split.c:442
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:141
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:199
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:169
ASSSplitContext
This struct can be casted to ASS to access to the split data.
Definition: ass_split.c:197
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:374
ASSConvertFunc
int(* ASSConvertFunc)(void *dest, const char *buf, int len)
Definition: ass_split.c:142
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
ASS_COLOR
@ ASS_COLOR
Definition: ass_split.c:29
ff_ass_split_free
void ff_ass_split_free(ASSSplitContext *ctx)
Free all the memory allocated for an ASSSplitContext.
Definition: ass_split.c:479
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:11134
section
Definition: ffprobe.c:139
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:205
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:587
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
av_malloc_array
#define av_malloc_array(a, b)
Definition: tableprint_vlc.h:32
ASSFields::offset
int offset
Definition: ass_split.c:37
uint8_t
uint8_t
Definition: audio_convert.c:194
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:236
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:452
ASSFields::name
const char * name
Definition: ass_split.c:35
avcodec.h
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen_template.c:38
convert_int
static int convert_int(void *dest, const char *buf, int len)
Definition: ass_split.c:156
t2
#define t2
Definition: regdef.h:30
ASSSection
Definition: ass_split.c:40
ASS_INT
@ ASS_INT
Definition: ass_split.c:27
ASSDialog
fields extracted from the [Events] section
Definition: ass_split.h:71
ass_split
static int ass_split(ASSSplitContext *ctx, const char *buf)
Definition: ass_split.c:349
ASSSection::offset
int offset
Definition: ass_split.c:45
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
ASSSplitContext::ass
ASS ass
Definition: ass_split.c:198
AVERROR_INVALIDDATA
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
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:492
ASSSection::format_header
const char * format_header
Definition: ass_split.c:42
h
h
Definition: vp9dsp_template.c:2038
ASSSection::offset_count
int offset_count
Definition: ass_split.c:46
skip_space
static const char * skip_space(const char *buf)
Definition: ass_split.c:225
ASSSplitContext::field_order
int * field_order[FF_ARRAY_ELEMS(ass_sections)]
Definition: ass_split.c:201
int
int
Definition: ffmpeg_filter.c:191
ASSSplitContext::field_number
int field_number[FF_ARRAY_ELEMS(ass_sections)]
Definition: ass_split.c:200
get_default_field_orders
static int * get_default_field_orders(const ASSSection *section, int *number)
Definition: ass_split.c:232