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