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)
355  buf = ass_split_section(ctx, buf);
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;
364  buf = ass_split_section(ctx, buf);
365  }
366  } else {
367  buf += strcspn(buf, "\n");
368  buf += !!*buf;
369  }
370  }
371  return buf ? 0 : AVERROR_INVALIDDATA;
372 }
373 
374 ASSSplitContext *ff_ass_split(const char *buf)
375 {
376  ASSSplitContext *ctx = av_mallocz(sizeof(*ctx));
377  if (!ctx)
378  return NULL;
379  if (buf && !strncmp(buf, "\xef\xbb\xbf", 3)) // Skip UTF-8 BOM header
380  buf += 3;
381  ctx->current_section = -1;
382  if (ass_split(ctx, buf) < 0) {
384  return NULL;
385  }
386  return ctx;
387 }
388 
390 {
391  uint8_t *ptr = (uint8_t *)&ctx->ass + section->offset;
392  int i, j, *count, c = 1;
393 
394  if (section->format_header) {
395  ptr = *(void **)ptr;
396  count = (int *)((uint8_t *)&ctx->ass + section->offset_count);
397  } else
398  count = &c;
399 
400  if (ptr)
401  for (i=0; i<*count; i++, ptr += section->size)
402  for (j=0; section->fields[j].name; j++) {
403  const ASSFields *field = &section->fields[j];
404  if (field->type == ASS_STR)
405  av_freep(ptr + field->offset);
406  }
407  *count = 0;
408 
409  if (section->format_header)
410  av_freep((uint8_t *)&ctx->ass + section->offset);
411 }
412 
414  int cache, int *number)
415 {
416  ASSDialog *dialog = NULL;
417  int i, count;
418  if (!cache)
419  for (i=0; i<FF_ARRAY_ELEMS(ass_sections); i++)
420  if (!strcmp(ass_sections[i].section, "Events")) {
422  break;
423  }
424  count = ctx->ass.dialogs_count;
425  if (ass_split(ctx, buf) == 0)
426  dialog = ctx->ass.dialogs + count;
427  if (number)
428  *number = ctx->ass.dialogs_count - count;
429  return dialog;
430 }
431 
433 {
434  ASSDialog *dialog = *dialogp;
435  if (!dialog)
436  return;
437  av_freep(&dialog->style);
438  av_freep(&dialog->name);
439  av_freep(&dialog->effect);
440  av_freep(&dialog->text);
441  av_freep(dialogp);
442 }
443 
445 {
446  int i;
447  static const ASSFields fields[] = {
448  {"ReadOrder", ASS_INT, offsetof(ASSDialog, readorder)},
449  {"Layer", ASS_INT, offsetof(ASSDialog, layer) },
450  {"Style", ASS_STR, offsetof(ASSDialog, style) },
451  {"Name", ASS_STR, offsetof(ASSDialog, name) },
452  {"MarginL", ASS_INT, offsetof(ASSDialog, margin_l) },
453  {"MarginR", ASS_INT, offsetof(ASSDialog, margin_r) },
454  {"MarginV", ASS_INT, offsetof(ASSDialog, margin_v) },
455  {"Effect", ASS_STR, offsetof(ASSDialog, effect) },
456  {"Text", ASS_STR, offsetof(ASSDialog, text) },
457  };
458 
459  ASSDialog *dialog = av_mallocz(sizeof(*dialog));
460  if (!dialog)
461  return NULL;
462 
463  for (i = 0; i < FF_ARRAY_ELEMS(fields); i++) {
464  size_t len;
465  const int last = i == FF_ARRAY_ELEMS(fields) - 1;
466  const ASSFieldType type = fields[i].type;
467  uint8_t *ptr = (uint8_t *)dialog + fields[i].offset;
468  buf = skip_space(buf);
469  len = last ? strlen(buf) : strcspn(buf, ",");
470  if (len >= INT_MAX) {
471  ff_ass_free_dialog(&dialog);
472  return NULL;
473  }
474  convert_func[type](ptr, buf, len);
475  buf += len;
476  if (*buf) buf++;
477  }
478  return dialog;
479 }
480 
482 {
483  if (ctx) {
484  int i;
485  for (i=0; i<FF_ARRAY_ELEMS(ass_sections); i++) {
487  av_freep(&(ctx->field_order[i]));
488  }
489  av_free(ctx);
490  }
491 }
492 
493 
495  const char *buf)
496 {
497  const char *text = NULL;
498  char new_line[2];
499  int text_len = 0;
500 
501  while (buf && *buf) {
502  if (text && callbacks->text &&
503  (sscanf(buf, "\\%1[nN]", new_line) == 1 ||
504  !strncmp(buf, "{\\", 2))) {
505  callbacks->text(priv, text, text_len);
506  text = NULL;
507  }
508  if (sscanf(buf, "\\%1[nN]", new_line) == 1) {
509  if (callbacks->new_line)
510  callbacks->new_line(priv, new_line[0] == 'N');
511  buf += 2;
512  } else if (!strncmp(buf, "{\\", 2)) {
513  buf++;
514  while (*buf == '\\') {
515  char style[2], c[2], sep[2], c_num[2] = "0", tmp[128] = {0};
516  unsigned int color = 0xFFFFFFFF;
517  int len, size = -1, an = -1, alpha = -1;
518  int x1, y1, x2, y2, t1 = -1, t2 = -1;
519  if (sscanf(buf, "\\%1[bisu]%1[01\\}]%n", style, c, &len) > 1) {
520  int close = c[0] == '0' ? 1 : c[0] == '1' ? 0 : -1;
521  len += close != -1;
522  if (callbacks->style)
523  callbacks->style(priv, style[0], close);
524  } else if (sscanf(buf, "\\c%1[\\}]%n", sep, &len) > 0 ||
525  sscanf(buf, "\\c&H%X&%1[\\}]%n", &color, sep, &len) > 1 ||
526  sscanf(buf, "\\%1[1234]c%1[\\}]%n", c_num, sep, &len) > 1 ||
527  sscanf(buf, "\\%1[1234]c&H%X&%1[\\}]%n", c_num, &color, sep, &len) > 2) {
528  if (callbacks->color)
529  callbacks->color(priv, color, c_num[0] - '0');
530  } else if (sscanf(buf, "\\alpha%1[\\}]%n", sep, &len) > 0 ||
531  sscanf(buf, "\\alpha&H%2X&%1[\\}]%n", &alpha, sep, &len) > 1 ||
532  sscanf(buf, "\\%1[1234]a%1[\\}]%n", c_num, sep, &len) > 1 ||
533  sscanf(buf, "\\%1[1234]a&H%2X&%1[\\}]%n", c_num, &alpha, sep, &len) > 2) {
534  if (callbacks->alpha)
535  callbacks->alpha(priv, alpha, c_num[0] - '0');
536  } else if (sscanf(buf, "\\fn%1[\\}]%n", sep, &len) > 0 ||
537  sscanf(buf, "\\fn%127[^\\}]%1[\\}]%n", tmp, sep, &len) > 1) {
538  if (callbacks->font_name)
539  callbacks->font_name(priv, tmp[0] ? tmp : NULL);
540  } else if (sscanf(buf, "\\fs%1[\\}]%n", sep, &len) > 0 ||
541  sscanf(buf, "\\fs%u%1[\\}]%n", &size, sep, &len) > 1) {
542  if (callbacks->font_size)
543  callbacks->font_size(priv, size);
544  } else if (sscanf(buf, "\\a%1[\\}]%n", sep, &len) > 0 ||
545  sscanf(buf, "\\a%2u%1[\\}]%n", &an, sep, &len) > 1 ||
546  sscanf(buf, "\\an%1[\\}]%n", sep, &len) > 0 ||
547  sscanf(buf, "\\an%1u%1[\\}]%n", &an, sep, &len) > 1) {
548  if (an != -1 && buf[2] != 'n')
549  an = (an&3) + (an&4 ? 6 : an&8 ? 3 : 0);
550  if (callbacks->alignment)
551  callbacks->alignment(priv, an);
552  } else if (sscanf(buf, "\\r%1[\\}]%n", sep, &len) > 0 ||
553  sscanf(buf, "\\r%127[^\\}]%1[\\}]%n", tmp, sep, &len) > 1) {
554  if (callbacks->cancel_overrides)
555  callbacks->cancel_overrides(priv, tmp);
556  } else if (sscanf(buf, "\\move(%d,%d,%d,%d)%1[\\}]%n", &x1, &y1, &x2, &y2, sep, &len) > 4 ||
557  sscanf(buf, "\\move(%d,%d,%d,%d,%d,%d)%1[\\}]%n", &x1, &y1, &x2, &y2, &t1, &t2, sep, &len) > 6) {
558  if (callbacks->move)
559  callbacks->move(priv, x1, y1, x2, y2, t1, t2);
560  } else if (sscanf(buf, "\\pos(%d,%d)%1[\\}]%n", &x1, &y1, sep, &len) > 2) {
561  if (callbacks->move)
562  callbacks->move(priv, x1, y1, x1, y1, -1, -1);
563  } else if (sscanf(buf, "\\org(%d,%d)%1[\\}]%n", &x1, &y1, sep, &len) > 2) {
564  if (callbacks->origin)
565  callbacks->origin(priv, x1, y1);
566  } else {
567  len = strcspn(buf+1, "\\}") + 2; /* skip unknown code */
568  }
569  buf += len - 1;
570  }
571  if (*buf++ != '}')
572  return AVERROR_INVALIDDATA;
573  } else {
574  if (!text) {
575  text = buf;
576  text_len = 1;
577  } else
578  text_len++;
579  buf++;
580  }
581  }
582  if (text && callbacks->text)
583  callbacks->text(priv, text, text_len);
584  if (callbacks->end)
585  callbacks->end(priv);
586  return 0;
587 }
588 
590 {
591  ASS *ass = &ctx->ass;
592  int i;
593 
594  if (!style || !*style)
595  style = "Default";
596  for (i=0; i<ass->styles_count; i++)
597  if (ass->styles[i].name && !strcmp(ass->styles[i].name, style))
598  return ass->styles + i;
599  return NULL;
600 }
ASS_TIMESTAMP
@ ASS_TIMESTAMP
Definition: ass_split.c:30
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: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:413
convert_str
static int convert_str(void *dest, const char *buf, int len)
Definition: ass_split.c:144
color
Definition: vf_paletteuse.c:583
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
callbacks
static const OMX_CALLBACKTYPE callbacks
Definition: omx.c:332
tmp
static uint8_t tmp[11]
Definition: aes_ctr.c:27
convert_flt
static int convert_flt(void *dest, const char *buf, int len)
Definition: ass_split.c:160
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:389
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: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:432
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
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: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:444
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:143
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:481
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:141
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:206
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:589
i
int i
Definition: input.c:407
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:237
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
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
convert_header.str
string str
Definition: convert_header.py:20
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:494
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:170
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