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 
200  int field_number[FF_ARRAY_ELEMS(ass_sections)];
201  int *field_order[FF_ARRAY_ELEMS(ass_sections)];
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 && !memcmp(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) {
383  ff_ass_split_free(ctx);
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")) {
421  free_section(ctx, &ass_sections[i]);
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++) {
486  free_section(ctx, &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 }
int(* ASSConvertFunc)(void *dest, const char *buf, int len)
Definition: ass_split.c:142
static const char * skip_space(const char *buf)
Definition: ass_split.c:225
char * style
name of the ASSStyle to use with this dialog
Definition: ass_split.h:76
#define NULL
Definition: coverity.c:32
#define AVERROR_INVALIDDATA
Invalid data found when processing input.
Definition: error.h:59
void(* new_line)(void *priv, int forced)
Definition: ass_split.h:160
fields extracted from the [Events] section
Definition: ass_split.h:71
int offset
Definition: ass_split.c:45
static int convert_alignment(void *dest, const char *buf, int len)
Definition: ass_split.c:176
void(* move)(void *priv, int x1, int y1, int x2, int y2, int t1, int t2)
Definition: ass_split.h:174
static int convert_str(void *dest, const char *buf, int len)
Definition: ass_split.c:144
ASSDialog * ff_ass_split_dialog2(ASSSplitContext *ctx, const char *buf)
Split one ASS Dialogue line from a string buffer.
Definition: ass_split.c:444
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
static const ASSSection ass_sections[]
Definition: ass_split.c:50
ASSDialog * dialogs
array of split out dialogs
Definition: ass_split.h:94
const char * format_header
Definition: ass_split.c:42
static int convert_color(void *dest, const char *buf, int len)
Definition: ass_split.c:164
structure containing the whole split ASS data
Definition: ass_split.h:90
void(* cancel_overrides)(void *priv, const char *style)
Definition: ass_split.h:167
static int * get_default_field_orders(const ASSSection *section, int *number)
Definition: ass_split.c:232
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:36
GLint GLenum type
Definition: opengl_enc.c:104
static int ass_split(ASSSplitContext *ctx, const char *buf)
Definition: ass_split.c:349
char * effect
Definition: ass_split.h:81
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
char * name
Definition: ass_split.h:77
static const char * ass_split_section(ASSSplitContext *ctx, const char *buf)
Definition: ass_split.c:247
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
ASSFields fields[24]
Definition: ass_split.c:47
const char * section
Definition: ass_split.c:41
This struct can be casted to ASS to access to the split data.
Definition: ass_split.c:197
uint8_t
#define av_malloc(s)
void ff_ass_free_dialog(ASSDialog **dialogp)
Free a dialogue obtained from ff_ass_split_dialog2().
Definition: ass_split.c:432
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
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:90
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
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
const char * fields_header
Definition: ass_split.c:43
static int is_eol(char buf)
Definition: ass_split.c:220
ptrdiff_t size
Definition: opengl_enc.c:100
void * av_realloc_array(void *ptr, size_t nmemb, size_t size)
Definition: mem.c:198
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
void(* color)(void *priv, unsigned int, unsigned int color_id)
Definition: ass_split.h:162
void(* font_name)(void *priv, const char *name)
Definition: ass_split.h:164
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
#define t1
Definition: regdef.h:29
int offset
Definition: ass_split.c:37
GLsizei count
Definition: opengl_enc.c:108
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
void(* font_size)(void *priv, int size)
Definition: ass_split.h:165
ASSFieldType
Definition: ass_split.c:25
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
AVFormatContext * ctx
Definition: movenc.c:48
int size
Definition: ass_split.c:44
#define s(width, name)
Definition: cbs_vp9.c:257
Set of callback functions corresponding to each override codes that can be encountered in a "Dialogue...
Definition: ass_split.h:154
#define FF_ARRAY_ELEMS(a)
if(ret)
static int convert_flt(void *dest, const char *buf, int len)
Definition: ass_split.c:160
Libavcodec external API header.
static const ASSConvertFunc convert_func[]
Definition: ass_split.c:187
void(* origin)(void *priv, int x, int y)
Definition: ass_split.h:175
static const int16_t alpha[]
Definition: ilbcdata.h:55
void(* alignment)(void *priv, int alignment)
Definition: ass_split.h:166
static void free_section(ASSSplitContext *ctx, const ASSSection *section)
Definition: ass_split.c:389
static uint8_t * realloc_section_array(ASSSplitContext *ctx)
Definition: ass_split.c:205
fields extracted from the [V4(+) Styles] section
Definition: ass_split.h:39
ASSStyle * ff_ass_style_get(ASSSplitContext *ctx, const char *style)
Find an ASSStyle structure by its name.
Definition: ass_split.c:589
static const OMX_CALLBACKTYPE callbacks
Definition: omx.c:332
void(* alpha)(void *priv, int alpha, int alpha_id)
Definition: ass_split.h:163
static int convert_timestamp(void *dest, const char *buf, int len)
Definition: ass_split.c:169
static int convert_int(void *dest, const char *buf, int len)
Definition: ass_split.c:156
int
int offset_count
Definition: ass_split.c:46
char * name
name of the tyle (case sensitive)
Definition: ass_split.h:40
void(* text)(void *priv, const char *text, int len)
Definition: ass_split.h:159
int dialogs_count
number of ASSDialog in the dialogs array
Definition: ass_split.h:95
int type
Definition: ass_split.c:36
#define av_free(p)
int len
int styles_count
number of ASSStyle in the styles array
Definition: ass_split.h:93
const char * name
Definition: ass_split.c:35
void ff_ass_split_free(ASSSplitContext *ctx)
Free all the memory allocated for an ASSSplitContext.
Definition: ass_split.c:481
#define av_freep(p)
void(* end)(void *priv)
Definition: ass_split.h:182
#define av_malloc_array(a, b)
fields extracted from the [Script Info] section
Definition: ass_split.h:28
void(* style)(void *priv, char style, int close)
Definition: ass_split.h:161
#define t2
Definition: regdef.h:30
int i
Definition: input.c:407
ASSStyle * styles
array of split out styles
Definition: ass_split.h:92
int * field_order[FF_ARRAY_ELEMS(ass_sections)]
Definition: ass_split.c:201
int field_number[FF_ARRAY_ELEMS(ass_sections)]
Definition: ass_split.c:200
const char * name
Definition: opengl_enc.c:102
static uint8_t tmp[11]
Definition: aes_ctr.c:26