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 
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) {
381  ff_ass_split_free(ctx);
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")) {
419  free_section(ctx, &ass_sections[i]);
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++) {
484  free_section(ctx, &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 }
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:442
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:236
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:430
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:492
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:411
void(* color)(void *priv, unsigned int, unsigned int color_id)
Definition: ass_split.h:162
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
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:205
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 * buf
Definition: avisynth_c.h:766
void(* alignment)(void *priv, int alignment)
Definition: ass_split.h:166
static void free_section(ASSSplitContext *ctx, const ASSSection *section)
Definition: ass_split.c:387
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:587
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:479
#define av_freep(p)
void INT64 start
Definition: avisynth_c.h:766
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
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