FFmpeg  4.3
movtextenc.c
Go to the documentation of this file.
1 /*
2  * 3GPP TS 26.245 Timed Text encoder
3  * Copyright (c) 2012 Philip Langdale <philipl@overt.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 <stdarg.h>
23 #include "avcodec.h"
24 #include "libavutil/opt.h"
25 #include "libavutil/avassert.h"
26 #include "libavutil/avstring.h"
27 #include "libavutil/intreadwrite.h"
28 #include "libavutil/mem.h"
29 #include "libavutil/common.h"
30 #include "ass_split.h"
31 #include "ass.h"
32 
33 #define STYLE_FLAG_BOLD (1<<0)
34 #define STYLE_FLAG_ITALIC (1<<1)
35 #define STYLE_FLAG_UNDERLINE (1<<2)
36 #define STYLE_RECORD_SIZE 12
37 #define SIZE_ADD 10
38 
39 #define STYL_BOX (1<<0)
40 #define HLIT_BOX (1<<1)
41 #define HCLR_BOX (1<<2)
42 
43 #define DEFAULT_STYLE_FONT_ID 0x01
44 #define DEFAULT_STYLE_FONTSIZE 0x12
45 #define DEFAULT_STYLE_COLOR 0xffffffff
46 #define DEFAULT_STYLE_FLAG 0x00
47 
48 #define BGR_TO_RGB(c) (((c) & 0xff) << 16 | ((c) & 0xff00) | (((c) >> 16) & 0xff))
49 #define FONTSIZE_SCALE(s,fs) ((fs) * (s)->font_scale_factor + 0.5)
50 #define av_bprint_append_any(buf, data, size) av_bprint_append_data(buf, ((const char*)data), size)
51 
52 typedef struct {
53  uint16_t style_start;
54  uint16_t style_end;
55  uint8_t style_flag;
56  uint16_t style_fontID;
58  uint32_t style_color;
59 } StyleBox;
60 
61 typedef struct {
62  uint16_t start;
63  uint16_t end;
64 } HighlightBox;
65 
66 typedef struct {
67  uint32_t color;
69 
70 typedef struct {
71  AVClass *class;
73 
76  AVBPrint buffer;
81  int count;
82  uint8_t box_flags;
84  uint16_t text_pos;
85  uint16_t byte_count;
86  char ** fonts;
89  int frame_height;
91 
92 typedef struct {
93  uint32_t type;
94  void (*encode)(MovTextContext *s, uint32_t tsmb_type);
95 } Box;
96 
98 {
99  int j;
100  if (s->box_flags & STYL_BOX) {
101  for (j = 0; j < s->count; j++) {
102  av_freep(&s->style_attributes[j]);
103  }
104  av_freep(&s->style_attributes);
105  }
106  if (s->style_attributes_temp) {
107  *s->style_attributes_temp = s->d;
108  }
109 }
110 
111 static void encode_styl(MovTextContext *s, uint32_t tsmb_type)
112 {
113  int j;
114  uint32_t tsmb_size;
115  uint16_t style_entries;
116  if ((s->box_flags & STYL_BOX) && s->count) {
117  tsmb_size = s->count * STYLE_RECORD_SIZE + SIZE_ADD;
118  tsmb_size = AV_RB32(&tsmb_size);
119  style_entries = AV_RB16(&s->count);
120  /*The above three attributes are hard coded for now
121  but will come from ASS style in the future*/
122  av_bprint_append_any(&s->buffer, &tsmb_size, 4);
123  av_bprint_append_any(&s->buffer, &tsmb_type, 4);
124  av_bprint_append_any(&s->buffer, &style_entries, 2);
125  for (j = 0; j < s->count; j++) {
126  uint16_t style_start, style_end, style_fontID;
127  uint32_t style_color;
128 
129  style_start = AV_RB16(&s->style_attributes[j]->style_start);
130  style_end = AV_RB16(&s->style_attributes[j]->style_end);
131  style_color = AV_RB32(&s->style_attributes[j]->style_color);
132  style_fontID = AV_RB16(&s->style_attributes[j]->style_fontID);
133 
134  av_bprint_append_any(&s->buffer, &style_start, 2);
135  av_bprint_append_any(&s->buffer, &style_end, 2);
136  av_bprint_append_any(&s->buffer, &style_fontID, 2);
137  av_bprint_append_any(&s->buffer, &s->style_attributes[j]->style_flag, 1);
138  av_bprint_append_any(&s->buffer, &s->style_attributes[j]->style_fontsize, 1);
139  av_bprint_append_any(&s->buffer, &style_color, 4);
140  }
141  }
143 }
144 
145 static void encode_hlit(MovTextContext *s, uint32_t tsmb_type)
146 {
147  uint32_t tsmb_size;
148  uint16_t start, end;
149  if (s->box_flags & HLIT_BOX) {
150  tsmb_size = 12;
151  tsmb_size = AV_RB32(&tsmb_size);
152  start = AV_RB16(&s->hlit.start);
153  end = AV_RB16(&s->hlit.end);
154  av_bprint_append_any(&s->buffer, &tsmb_size, 4);
155  av_bprint_append_any(&s->buffer, &tsmb_type, 4);
156  av_bprint_append_any(&s->buffer, &start, 2);
157  av_bprint_append_any(&s->buffer, &end, 2);
158  }
159 }
160 
161 static void encode_hclr(MovTextContext *s, uint32_t tsmb_type)
162 {
163  uint32_t tsmb_size, color;
164  if (s->box_flags & HCLR_BOX) {
165  tsmb_size = 12;
166  tsmb_size = AV_RB32(&tsmb_size);
167  color = AV_RB32(&s->hclr.color);
168  av_bprint_append_any(&s->buffer, &tsmb_size, 4);
169  av_bprint_append_any(&s->buffer, &tsmb_type, 4);
170  av_bprint_append_any(&s->buffer, &color, 4);
171  }
172 }
173 
174 static const Box box_types[] = {
175  { MKTAG('s','t','y','l'), encode_styl },
176  { MKTAG('h','l','i','t'), encode_hlit },
177  { MKTAG('h','c','l','r'), encode_hclr },
178 };
179 
180 const static size_t box_count = FF_ARRAY_ELEMS(box_types);
181 
183 {
184  MovTextContext *s = avctx->priv_data;
185  int i;
186 
187  ff_ass_split_free(s->ass_ctx);
188  if (s->style_attributes) {
189  for (i = 0; i < s->count; i++) {
190  av_freep(&s->style_attributes[i]);
191  }
192  av_freep(&s->style_attributes);
193  }
194  av_freep(&s->fonts);
195  av_freep(&s->style_attributes_temp);
196  av_bprint_finalize(&s->buffer, NULL);
197  return 0;
198 }
199 
201 {
202  ASS * ass;
203  ASSStyle * style;
204  int i, j;
205  uint32_t tsmb_size, tsmb_type, back_color, style_color;
206  uint16_t style_start, style_end, fontID, count;
207  int font_names_total_len = 0;
208  MovTextContext *s = avctx->priv_data;
209 
210  static const uint8_t display_and_justification[] = {
211  0x00, 0x00, 0x00, 0x00, // uint32_t displayFlags
212  0x01, // int8_t horizontal-justification
213  0xFF, // int8_t vertical-justification
214  };
215  // 0x00, 0x00, 0x00, 0x00, // uint8_t background-color-rgba[4]
216  static const uint8_t box_record[] = {
217  // BoxRecord {
218  0x00, 0x00, // int16_t top
219  0x00, 0x00, // int16_t left
220  0x00, 0x00, // int16_t bottom
221  0x00, 0x00, // int16_t right
222  // };
223  };
224  // StyleRecord {
225  // 0x00, 0x00, // uint16_t startChar
226  // 0x00, 0x00, // uint16_t endChar
227  // 0x00, 0x01, // uint16_t font-ID
228  // 0x00, // uint8_t face-style-flags
229  // 0x12, // uint8_t font-size
230  // 0xFF, 0xFF, 0xFF, 0xFF, // uint8_t text-color-rgba[4]
231  // };
232  // FontTableBox {
233  // 0x00, 0x00, 0x00, 0x12, // uint32_t size
234  // 'f', 't', 'a', 'b', // uint8_t name[4]
235  // 0x00, 0x01, // uint16_t entry-count
236  // FontRecord {
237  // 0x00, 0x01, // uint16_t font-ID
238  // 0x05, // uint8_t font-name-length
239  // 'S', 'e', 'r', 'i', 'f',// uint8_t font[font-name-length]
240  // };
241  // };
242 
243  // Populate sample description from ASS header
244  ass = (ASS*)s->ass_ctx;
245  // Compute font scaling factor based on (optionally) provided
246  // output video height and ASS script play_res_y
247  if (s->frame_height && ass->script_info.play_res_y)
248  s->font_scale_factor = (double)s->frame_height / ass->script_info.play_res_y;
249  else
250  s->font_scale_factor = 1;
251 
252  style = ff_ass_style_get(s->ass_ctx, "Default");
253  if (!style && ass->styles_count) {
254  style = &ass->styles[0];
255  }
256  s->d.style_fontID = DEFAULT_STYLE_FONT_ID;
257  s->d.style_fontsize = DEFAULT_STYLE_FONTSIZE;
258  s->d.style_color = DEFAULT_STYLE_COLOR;
259  s->d.style_flag = DEFAULT_STYLE_FLAG;
260  if (style) {
261  s->d.style_fontsize = FONTSIZE_SCALE(s, style->font_size);
262  s->d.style_color = BGR_TO_RGB(style->primary_color & 0xffffff) << 8 |
263  255 - ((uint32_t)style->primary_color >> 24);
264  s->d.style_flag = (!!style->bold * STYLE_FLAG_BOLD) |
265  (!!style->italic * STYLE_FLAG_ITALIC) |
266  (!!style->underline * STYLE_FLAG_UNDERLINE);
267  back_color = (BGR_TO_RGB(style->back_color & 0xffffff) << 8) |
268  (255 - ((uint32_t)style->back_color >> 24));
269  }
270 
271  av_bprint_append_any(&s->buffer, display_and_justification,
272  sizeof(display_and_justification));
273  back_color = AV_RB32(&back_color);
274  av_bprint_append_any(&s->buffer, &back_color, 4);
275  // BoxRecord {
276  av_bprint_append_any(&s->buffer, box_record, sizeof(box_record));
277  // };
278  // StyleRecord {
279  style_start = AV_RB16(&s->d.style_start);
280  style_end = AV_RB16(&s->d.style_end);
281  fontID = AV_RB16(&s->d.style_fontID);
282  style_color = AV_RB32(&s->d.style_color);
283  av_bprint_append_any(&s->buffer, &style_start, 2);
284  av_bprint_append_any(&s->buffer, &style_end, 2);
285  av_bprint_append_any(&s->buffer, &fontID, 2);
286  av_bprint_append_any(&s->buffer, &s->d.style_flag, 1);
287  av_bprint_append_any(&s->buffer, &s->d.style_fontsize, 1);
288  av_bprint_append_any(&s->buffer, &style_color, 4);
289  // };
290 
291  // Build font table
292  // We can't build a complete font table since that would require
293  // scanning all dialogs first. But we can at least fill in what
294  // is avaiable in the ASS header
295  if (style && ass->styles_count) {
296  // Find unique font names
297  av_dynarray_add(&s->fonts, &s->font_count, style->font_name);
298  font_names_total_len += strlen(style->font_name);
299  for (i = 0; i < ass->styles_count; i++) {
300  int found = 0;
301  for (j = 0; j < s->font_count; j++) {
302  if (!strcmp(s->fonts[j], ass->styles[i].font_name)) {
303  found = 1;
304  break;
305  }
306  }
307  if (!found) {
308  av_dynarray_add(&s->fonts, &s->font_count,
309  ass->styles[i].font_name);
310  font_names_total_len += strlen(ass->styles[i].font_name);
311  }
312  }
313  } else
314  av_dynarray_add(&s->fonts, &s->font_count, (char*)"Serif");
315 
316  // FontTableBox {
317  tsmb_size = SIZE_ADD + 3 * s->font_count + font_names_total_len;
318  tsmb_size = AV_RB32(&tsmb_size);
319  tsmb_type = MKTAG('f','t','a','b');
320  count = AV_RB16(&s->font_count);
321  av_bprint_append_any(&s->buffer, &tsmb_size, 4);
322  av_bprint_append_any(&s->buffer, &tsmb_type, 4);
323  av_bprint_append_any(&s->buffer, &count, 2);
324  // FontRecord {
325  for (i = 0; i < s->font_count; i++) {
326  int len;
327  fontID = i + 1;
328  fontID = AV_RB16(&fontID);
329  av_bprint_append_any(&s->buffer, &fontID, 2);
330  len = strlen(s->fonts[i]);
331  av_bprint_append_any(&s->buffer, &len, 1);
332  av_bprint_append_any(&s->buffer, s->fonts[i], len);
333  }
334  // };
335  // };
336 
337  if (!av_bprint_is_complete(&s->buffer)) {
338  return AVERROR(ENOMEM);
339  }
340 
341  avctx->extradata_size = s->buffer.len;
343  if (!avctx->extradata) {
344  return AVERROR(ENOMEM);
345  }
346 
347  memcpy(avctx->extradata, s->buffer.str, avctx->extradata_size);
348  av_bprint_clear(&s->buffer);
349 
350  return 0;
351 }
352 
354 {
355  int ret;
356  MovTextContext *s = avctx->priv_data;
357  s->avctx = avctx;
358 
360 
361  s->style_attributes_temp = av_mallocz(sizeof(*s->style_attributes_temp));
362  if (!s->style_attributes_temp) {
363  ret = AVERROR(ENOMEM);
364  goto fail;
365  }
366 
367  s->ass_ctx = ff_ass_split(avctx->subtitle_header);
368  if (!s->ass_ctx) {
370  goto fail;
371  }
373  if (ret < 0)
374  goto fail;
375 
376  return 0;
377 
378 fail:
379  mov_text_encode_close(avctx);
380  return ret;
381 }
382 
383 // Start a new style box if needed
385 {
386  // there's an existing style entry
387  if (s->style_attributes_temp->style_start == s->text_pos)
388  // Still at same text pos, use same entry
389  return 1;
390  if (s->style_attributes_temp->style_flag != s->d.style_flag ||
391  s->style_attributes_temp->style_color != s->d.style_color ||
392  s->style_attributes_temp->style_fontID != s->d.style_fontID ||
393  s->style_attributes_temp->style_fontsize != s->d.style_fontsize) {
394  // last style != defaults, end the style entry and start a new one
395  s->box_flags |= STYL_BOX;
396  s->style_attributes_temp->style_end = s->text_pos;
397  av_dynarray_add(&s->style_attributes, &s->count, s->style_attributes_temp);
398  s->style_attributes_temp = av_malloc(sizeof(*s->style_attributes_temp));
399  if (!s->style_attributes_temp) {
401  av_bprint_clear(&s->buffer);
402  s->box_flags &= ~STYL_BOX;
403  return 0;
404  }
405 
406  *s->style_attributes_temp = s->d;
407  s->style_attributes_temp->style_start = s->text_pos;
408  } else { // style entry matches defaults, drop entry
409  *s->style_attributes_temp = s->d;
410  s->style_attributes_temp->style_start = s->text_pos;
411  }
412  return 1;
413 }
414 
415 static uint8_t mov_text_style_to_flag(const char style)
416 {
417  uint8_t style_flag = 0;
418 
419  switch (style){
420  case 'b':
421  style_flag = STYLE_FLAG_BOLD;
422  break;
423  case 'i':
424  style_flag = STYLE_FLAG_ITALIC;
425  break;
426  case 'u':
427  style_flag = STYLE_FLAG_UNDERLINE;
428  break;
429  }
430  return style_flag;
431 }
432 
433 static void mov_text_style_set(MovTextContext *s, uint8_t style_flags)
434 {
435  if (!s->style_attributes_temp ||
436  !((s->style_attributes_temp->style_flag & style_flags) ^ style_flags)) {
437  // setting flags that that are already set
438  return;
439  }
440  if (mov_text_style_start(s))
441  s->style_attributes_temp->style_flag |= style_flags;
442 }
443 
444 static void mov_text_style_cb(void *priv, const char style, int close)
445 {
446  MovTextContext *s = priv;
447  uint8_t style_flag = mov_text_style_to_flag(style);
448 
449  if (!s->style_attributes_temp ||
450  !!(s->style_attributes_temp->style_flag & style_flag) != close) {
451  // setting flag that is already set
452  return;
453  }
454  if (mov_text_style_start(s)) {
455  if (!close)
456  s->style_attributes_temp->style_flag |= style_flag;
457  else
458  s->style_attributes_temp->style_flag &= ~style_flag;
459  }
460 }
461 
462 static void mov_text_color_set(MovTextContext *s, uint32_t color)
463 {
464  if (!s->style_attributes_temp ||
465  (s->style_attributes_temp->style_color & 0xffffff00) == color) {
466  // color hasn't changed
467  return;
468  }
469  if (mov_text_style_start(s))
470  s->style_attributes_temp->style_color = (color & 0xffffff00) |
471  (s->style_attributes_temp->style_color & 0xff);
472 }
473 
474 static void mov_text_color_cb(void *priv, unsigned int color, unsigned int color_id)
475 {
476  MovTextContext *s = priv;
477 
478  color = BGR_TO_RGB(color) << 8;
479  if (color_id == 1) { //primary color changes
481  } else if (color_id == 2) { //secondary color changes
482  if (!(s->box_flags & HCLR_BOX))
483  // Highlight alpha not set yet, use current primary alpha
484  s->hclr.color = s->style_attributes_temp->style_color;
485  if (!(s->box_flags & HLIT_BOX) || s->hlit.start == s->text_pos) {
486  s->box_flags |= HCLR_BOX;
487  s->box_flags |= HLIT_BOX;
488  s->hlit.start = s->text_pos;
489  s->hclr.color = color | (s->hclr.color & 0xFF);
490  }
491  else //close tag
492  s->hlit.end = s->text_pos;
493  /* If there are more than one secondary color changes in ASS,
494  take start of first section and end of last section. Movtext
495  allows only one highlight box per sample.
496  */
497  }
498  // Movtext does not support changes to other color_id (outline, background)
499 }
500 
502 {
503  if (!s->style_attributes_temp ||
504  (s->style_attributes_temp->style_color & 0xff) == alpha) {
505  // color hasn't changed
506  return;
507  }
508  if (mov_text_style_start(s))
509  s->style_attributes_temp->style_color =
510  (s->style_attributes_temp->style_color & 0xffffff00) | alpha;
511 }
512 
513 static void mov_text_alpha_cb(void *priv, int alpha, int alpha_id)
514 {
515  MovTextContext *s = priv;
516 
517  alpha = 255 - alpha;
518  if (alpha_id == 1) // primary alpha changes
520  else if (alpha_id == 2) { //secondary alpha changes
521  if (!(s->box_flags & HCLR_BOX))
522  // Highlight color not set yet, use current primary color
523  s->hclr.color = s->style_attributes_temp->style_color;
524  if (!(s->box_flags & HLIT_BOX) || s->hlit.start == s->text_pos) {
525  s->box_flags |= HCLR_BOX;
526  s->box_flags |= HLIT_BOX;
527  s->hlit.start = s->text_pos;
528  s->hclr.color = (s->hclr.color & 0xffffff00) | alpha;
529  }
530  else //close tag
531  s->hlit.end = s->text_pos;
532  }
533  // Movtext does not support changes to other alpha_id (outline, background)
534 }
535 
536 static uint16_t find_font_id(MovTextContext * s, const char * name)
537 {
538  int i;
539  for (i = 0; i < s->font_count; i++) {
540  if (!strcmp(name, s->fonts[i]))
541  return i + 1;
542  }
543  return 1;
544 }
545 
546 static void mov_text_font_name_set(MovTextContext *s, const char *name)
547 {
548  int fontID = find_font_id(s, name);
549  if (!s->style_attributes_temp ||
550  s->style_attributes_temp->style_fontID == fontID) {
551  // color hasn't changed
552  return;
553  }
554  if (mov_text_style_start(s))
555  s->style_attributes_temp->style_fontID = fontID;
556 }
557 
558 static void mov_text_font_name_cb(void *priv, const char *name)
559 {
561 }
562 
564 {
566  if (!s->style_attributes_temp ||
567  s->style_attributes_temp->style_fontsize == size) {
568  // color hasn't changed
569  return;
570  }
571  if (mov_text_style_start(s))
572  s->style_attributes_temp->style_fontsize = size;
573 }
574 
575 static void mov_text_font_size_cb(void *priv, int size)
576 {
578 }
579 
580 static void mov_text_end_cb(void *priv)
581 {
582  // End of text, close any open style record
584 }
585 
587 {
588  uint8_t style_flags, alpha;
589  uint32_t color;
590 
591  if (style) {
592  style_flags = (!!style->bold * STYLE_FLAG_BOLD) |
593  (!!style->italic * STYLE_FLAG_ITALIC) |
594  (!!style->underline * STYLE_FLAG_UNDERLINE);
595  mov_text_style_set(s, style_flags);
596  color = BGR_TO_RGB(style->primary_color & 0xffffff) << 8;
598  alpha = 255 - ((uint32_t)style->primary_color >> 24);
602  } else {
603  // End current style record, go back to defaults
605  }
606 }
607 
609 {
610  ASSStyle * style = ff_ass_style_get(s->ass_ctx, dialog->style);
611 
612  s->ass_dialog_style = style;
613  mov_text_ass_style_set(s, style);
614 }
615 
616 static void mov_text_cancel_overrides_cb(void *priv, const char * style_name)
617 {
618  MovTextContext *s = priv;
619  ASSStyle * style;
620 
621  if (!style_name || !*style_name)
622  style = s->ass_dialog_style;
623  else
624  style= ff_ass_style_get(s->ass_ctx, style_name);
625 
626  mov_text_ass_style_set(s, style);
627 }
628 
629 static uint16_t utf8_strlen(const char *text, int len)
630 {
631  uint16_t i = 0, ret = 0;
632  while (i < len) {
633  char c = text[i];
634  if ((c & 0x80) == 0)
635  i += 1;
636  else if ((c & 0xE0) == 0xC0)
637  i += 2;
638  else if ((c & 0xF0) == 0xE0)
639  i += 3;
640  else if ((c & 0xF8) == 0xF0)
641  i += 4;
642  else
643  return 0;
644  ret++;
645  }
646  return ret;
647 }
648 
649 static void mov_text_text_cb(void *priv, const char *text, int len)
650 {
651  uint16_t utf8_len = utf8_strlen(text, len);
652  MovTextContext *s = priv;
653  av_bprint_append_data(&s->buffer, text, len);
654  // If it's not utf-8, just use the byte length
655  s->text_pos += utf8_len ? utf8_len : len;
656  s->byte_count += len;
657 }
658 
659 static void mov_text_new_line_cb(void *priv, int forced)
660 {
661  MovTextContext *s = priv;
662  av_bprint_append_data(&s->buffer, "\n", 1);
663  s->text_pos += 1;
664  s->byte_count += 1;
665 }
666 
669  .new_line = mov_text_new_line_cb,
670  .style = mov_text_style_cb,
671  .color = mov_text_color_cb,
672  .alpha = mov_text_alpha_cb,
673  .font_name = mov_text_font_name_cb,
674  .font_size = mov_text_font_size_cb,
675  .cancel_overrides = mov_text_cancel_overrides_cb,
676  .end = mov_text_end_cb,
677 };
678 
679 static int mov_text_encode_frame(AVCodecContext *avctx, unsigned char *buf,
680  int bufsize, const AVSubtitle *sub)
681 {
682  MovTextContext *s = avctx->priv_data;
683  ASSDialog *dialog;
684  int i, length;
685  size_t j;
686 
687  s->byte_count = 0;
688  s->text_pos = 0;
689  s->count = 0;
690  s->box_flags = 0;
691  for (i = 0; i < sub->num_rects; i++) {
692  const char *ass = sub->rects[i]->ass;
693 
694  if (sub->rects[i]->type != SUBTITLE_ASS) {
695  av_log(avctx, AV_LOG_ERROR, "Only SUBTITLE_ASS type supported.\n");
696  return AVERROR(EINVAL);
697  }
698 
699 #if FF_API_ASS_TIMING
700  if (!strncmp(ass, "Dialogue: ", 10)) {
701  int num;
702  dialog = ff_ass_split_dialog(s->ass_ctx, ass, 0, &num);
703  for (; dialog && num--; dialog++) {
704  mov_text_dialog(s, dialog);
706  }
707  } else {
708 #endif
709  dialog = ff_ass_split_dialog2(s->ass_ctx, ass);
710  if (!dialog)
711  return AVERROR(ENOMEM);
712  mov_text_dialog(s, dialog);
714  ff_ass_free_dialog(&dialog);
715 #if FF_API_ASS_TIMING
716  }
717 #endif
718 
719  for (j = 0; j < box_count; j++) {
720  box_types[j].encode(s, box_types[j].type);
721  }
722  }
723 
724  AV_WB16(buf, s->byte_count);
725  buf += 2;
726 
727  if (!av_bprint_is_complete(&s->buffer)) {
728  length = AVERROR(ENOMEM);
729  goto exit;
730  }
731 
732  if (!s->buffer.len) {
733  length = 0;
734  goto exit;
735  }
736 
737  if (s->buffer.len > bufsize - 3) {
738  av_log(avctx, AV_LOG_ERROR, "Buffer too small for ASS event.\n");
739  length = AVERROR_BUFFER_TOO_SMALL;
740  goto exit;
741  }
742 
743  memcpy(buf, s->buffer.str, s->buffer.len);
744  length = s->buffer.len + 2;
745 
746 exit:
747  av_bprint_clear(&s->buffer);
748  return length;
749 }
750 
751 #define OFFSET(x) offsetof(MovTextContext, x)
752 #define FLAGS AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_SUBTITLE_PARAM
753 static const AVOption options[] = {
754  { "height", "Frame height, usually video height", OFFSET(frame_height), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS },
755  { NULL },
756 };
757 
759  .class_name = "MOV text enoder",
760  .item_name = av_default_item_name,
761  .option = options,
762  .version = LIBAVUTIL_VERSION_INT,
763 };
764 
766  .name = "mov_text",
767  .long_name = NULL_IF_CONFIG_SMALL("3GPP Timed Text subtitle"),
768  .type = AVMEDIA_TYPE_SUBTITLE,
769  .id = AV_CODEC_ID_MOV_TEXT,
770  .priv_data_size = sizeof(MovTextContext),
771  .priv_class = &mov_text_encoder_class,
773  .encode_sub = mov_text_encode_frame,
774  .close = mov_text_encode_close,
775 };
AVSubtitle
Definition: avcodec.h:2694
AVCodec
AVCodec.
Definition: codec.h:190
AVMEDIA_TYPE_SUBTITLE
@ AVMEDIA_TYPE_SUBTITLE
Definition: avutil.h:204
AV_BPRINT_SIZE_UNLIMITED
#define AV_BPRINT_SIZE_UNLIMITED
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
MovTextContext::avctx
AVCodecContext * avctx
Definition: movtextenc.c:72
init
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
ASSCodesCallbacks
Set of callback functions corresponding to each override codes that can be encountered in a "Dialogue...
Definition: ass_split.h:154
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
AVSubtitle::rects
AVSubtitleRect ** rects
Definition: avcodec.h:2699
opt.h
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
av_bprint_finalize
int av_bprint_finalize(AVBPrint *buf, char **ret_str)
Finalize a print buffer.
Definition: bprint.c:235
mov_text_dialog
static void mov_text_dialog(MovTextContext *s, ASSDialog *dialog)
Definition: movtextenc.c:608
color
Definition: vf_paletteuse.c:588
av_bprint_init
void av_bprint_init(AVBPrint *buf, unsigned size_init, unsigned size_max)
Definition: bprint.c:69
MovTextContext::d
StyleBox d
Definition: movtextenc.c:83
MKTAG
#define MKTAG(a, b, c, d)
Definition: common.h:406
mov_text_cancel_overrides_cb
static void mov_text_cancel_overrides_cb(void *priv, const char *style_name)
Definition: movtextenc.c:616
AVSubtitle::num_rects
unsigned num_rects
Definition: avcodec.h:2698
end
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:90
AVOption
AVOption.
Definition: opt.h:246
mov_text_font_name_set
static void mov_text_font_name_set(MovTextContext *s, const char *name)
Definition: movtextenc.c:546
options
static const AVOption options[]
Definition: movtextenc.c:753
ASS::styles
ASSStyle * styles
array of split out styles
Definition: ass_split.h:92
AV_RB16
#define AV_RB16
Definition: intreadwrite.h:53
ASSStyle::font_size
int font_size
font height
Definition: ass_split.h:42
AVCodecContext::subtitle_header
uint8_t * subtitle_header
Header containing style information for text subtitles.
Definition: avcodec.h:2014
mov_text_encode_init
static av_cold int mov_text_encode_init(AVCodecContext *avctx)
Definition: movtextenc.c:353
HighlightBox
Definition: movtextdec.c:86
MovTextContext::font_scale_factor
double font_scale_factor
Definition: movtextenc.c:88
MovTextContext::style_attributes_temp
StyleBox * style_attributes_temp
Definition: movtextenc.c:78
av_bprint_append_data
void av_bprint_append_data(AVBPrint *buf, const char *data, unsigned size)
Append data to a print buffer.
Definition: bprint.c:158
box_count
const static size_t box_count
Definition: movtextenc.c:180
ASSDialog::style
char * style
name of the ASSStyle to use with this dialog
Definition: ass_split.h:76
OFFSET
#define OFFSET(x)
Definition: movtextenc.c:751
mov_text_color_set
static void mov_text_color_set(MovTextContext *s, uint32_t color)
Definition: movtextenc.c:462
DEFAULT_STYLE_FONT_ID
#define DEFAULT_STYLE_FONT_ID
Definition: movtextenc.c:43
mov_text_encoder_class
static const AVClass mov_text_encoder_class
Definition: movtextenc.c:758
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:31
SUBTITLE_ASS
@ SUBTITLE_ASS
Formatted text, the ass field must be set by the decoder and is authoritative.
Definition: avcodec.h:2654
ASSStyle::font_name
char * font_name
font face (case sensitive)
Definition: ass_split.h:41
mov_text_font_size_set
static void mov_text_font_size_set(MovTextContext *s, int size)
Definition: movtextenc.c:563
Box
Definition: movtextdec.c:119
mov_text_alpha_set
static void mov_text_alpha_set(MovTextContext *s, uint8_t alpha)
Definition: movtextenc.c:501
fail
#define fail()
Definition: checkasm.h:123
StyleBox
Definition: movtextdec.c:73
MovTextContext::style_attributes
StyleBox ** style_attributes
Definition: movtextenc.c:77
ass_split.h
mov_text_color_cb
static void mov_text_color_cb(void *priv, unsigned int color, unsigned int color_id)
Definition: movtextenc.c:474
AVERROR_BUFFER_TOO_SMALL
#define AVERROR_BUFFER_TOO_SMALL
Buffer too small.
Definition: error.h:51
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
FONTSIZE_SCALE
#define FONTSIZE_SCALE(s, fs)
Definition: movtextenc.c:49
HilightcolorBox::color
uint32_t color
Definition: movtextenc.c:67
STYL_BOX
#define STYL_BOX
Definition: movtextenc.c:39
AVSubtitleRect::ass
char * ass
0 terminated ASS/SSA compatible event line.
Definition: avcodec.h:2689
ass.h
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
avassert.h
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
av_cold
#define av_cold
Definition: attributes.h:90
mov_text_text_cb
static void mov_text_text_cb(void *priv, const char *text, int len)
Definition: movtextenc.c:649
mov_text_style_start
static int mov_text_style_start(MovTextContext *s)
Definition: movtextenc.c:384
AVCodecContext::extradata_size
int extradata_size
Definition: avcodec.h:628
box_types
static const Box box_types[]
Definition: movtextenc.c:174
intreadwrite.h
s
#define s(width, name)
Definition: cbs_vp9.c:257
mov_text_cleanup
static void mov_text_cleanup(MovTextContext *s)
Definition: movtextenc.c:97
STYLE_FLAG_UNDERLINE
#define STYLE_FLAG_UNDERLINE
Definition: movtextenc.c:35
MovTextContext::fonts
char ** fonts
Definition: movtextenc.c:86
FLAGS
#define FLAGS
Definition: movtextenc.c:752
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
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
MovTextContext::font_count
int font_count
Definition: movtextenc.c:87
if
if(ret)
Definition: filter_design.txt:179
ASSScriptInfo::play_res_y
int play_res_y
video height that ASS coords are referring to
Definition: ass_split.h:32
STYLE_FLAG_ITALIC
#define STYLE_FLAG_ITALIC
Definition: movtextenc.c:34
HLIT_BOX
#define HLIT_BOX
Definition: movtextenc.c:40
ASS
structure containing the whole split ASS data
Definition: ass_split.h:90
LIBAVUTIL_VERSION_INT
#define LIBAVUTIL_VERSION_INT
Definition: version.h:85
AVClass
Describe the class of an AVClass context structure.
Definition: log.h:67
NULL
#define NULL
Definition: coverity.c:32
AV_WB16
#define AV_WB16(p, v)
Definition: intreadwrite.h:405
AV_CODEC_ID_MOV_TEXT
@ AV_CODEC_ID_MOV_TEXT
Definition: codec_id.h:513
ASSStyle::primary_color
int primary_color
color that a subtitle will normally appear in
Definition: ass_split.h:43
av_default_item_name
const char * av_default_item_name(void *ptr)
Return the context name.
Definition: log.c:235
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
utf8_strlen
static uint16_t utf8_strlen(const char *text, int len)
Definition: movtextenc.c:629
AV_RB32
#define AV_RB32
Definition: intreadwrite.h:130
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
mov_text_style_to_flag
static uint8_t mov_text_style_to_flag(const char style)
Definition: movtextenc.c:415
av_bprint_is_complete
static int av_bprint_is_complete(const AVBPrint *buf)
Test if the print buffer is complete (not truncated).
Definition: bprint.h:185
ASSStyle::underline
int underline
whether text is underlined (1) or not (0)
Definition: ass_split.h:49
ff_ass_split_free
void ff_ass_split_free(ASSSplitContext *ctx)
Free all the memory allocated for an ASSSplitContext.
Definition: ass_split.c:481
DEFAULT_STYLE_COLOR
#define DEFAULT_STYLE_COLOR
Definition: movtextenc.c:45
NULL_IF_CONFIG_SMALL
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:186
av_dynarray_add
void av_dynarray_add(void *tab_ptr, int *nb_ptr, void *elem)
Add the pointer to an element to a dynamic array.
Definition: mem.c:310
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
HighlightBox::end
uint16_t end
Definition: movtextenc.c:63
size
int size
Definition: twinvq_data.h:11134
mov_text_style_set
static void mov_text_style_set(MovTextContext *s, uint8_t style_flags)
Definition: movtextenc.c:433
color
static const uint32_t color[16+AV_CLASS_CATEGORY_NB]
Definition: log.c:92
ASSStyle::italic
int italic
whether text is italic (1) or not (0)
Definition: ass_split.h:48
MovTextContext::ass_dialog_style
ASSStyle * ass_dialog_style
Definition: movtextenc.c:75
AVSubtitleRect::type
enum AVSubtitleType type
Definition: avcodec.h:2680
encode
static void encode(AVCodecContext *ctx, AVFrame *frame, AVPacket *pkt, FILE *output)
Definition: encode_audio.c:95
DEFAULT_STYLE_FONTSIZE
#define DEFAULT_STYLE_FONTSIZE
Definition: movtextenc.c:44
mov_text_encode_close
static int mov_text_encode_close(AVCodecContext *avctx)
Definition: movtextenc.c:182
find_font_id
static uint16_t find_font_id(MovTextContext *s, const char *name)
Definition: movtextenc.c:536
mov_text_font_name_cb
static void mov_text_font_name_cb(void *priv, const char *name)
Definition: movtextenc.c:558
ASSStyle::back_color
int back_color
color of the subtitle outline or shadow
Definition: ass_split.h:46
SIZE_ADD
#define SIZE_ADD
Definition: movtextenc.c:37
mov_text_callbacks
static const ASSCodesCallbacks mov_text_callbacks
Definition: movtextenc.c:667
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
encode_sample_description
static int encode_sample_description(AVCodecContext *avctx)
Definition: movtextenc.c:200
STYLE_RECORD_SIZE
#define STYLE_RECORD_SIZE
Definition: movtextenc.c:36
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
ff_movtext_encoder
AVCodec ff_movtext_encoder
Definition: movtextenc.c:765
AVCodecContext::extradata
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
Definition: avcodec.h:627
STYLE_FLAG_BOLD
#define STYLE_FLAG_BOLD
Definition: movtextenc.c:33
common.h
MovTextContext::byte_count
uint16_t byte_count
Definition: movtextenc.c:85
StyleBox::style_color
uint32_t style_color
Definition: movtextenc.c:58
MovTextContext::hlit
HighlightBox hlit
Definition: movtextenc.c:79
mov_text_encode_frame
static int mov_text_encode_frame(AVCodecContext *avctx, unsigned char *buf, int bufsize, const AVSubtitle *sub)
Definition: movtextenc.c:679
uint8_t
uint8_t
Definition: audio_convert.c:194
AVCodec::name
const char * name
Name of the codec implementation.
Definition: codec.h:197
mov_text_new_line_cb
static void mov_text_new_line_cb(void *priv, int forced)
Definition: movtextenc.c:659
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
MovTextContext::count
int count
Definition: movtextenc.c:81
mov_text_end_cb
static void mov_text_end_cb(void *priv)
Definition: movtextenc.c:580
avcodec.h
encode_hclr
static void encode_hclr(MovTextContext *s, uint32_t tsmb_type)
Definition: movtextenc.c:161
ret
ret
Definition: filter_design.txt:187
BGR_TO_RGB
#define BGR_TO_RGB(c)
Definition: movtextenc.c:48
AVClass::class_name
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:72
AV_INPUT_BUFFER_PADDING_SIZE
#define AV_INPUT_BUFFER_PADDING_SIZE
Definition: avcodec.h:215
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen_template.c:38
AVCodecContext
main external API structure.
Definition: avcodec.h:526
void
typedef void(RENAME(mix_any_func_type))
Definition: rematrix_template.c:52
av_bprint_clear
void av_bprint_clear(AVBPrint *buf)
Reset the string to "" but keep internal allocated data.
Definition: bprint.c:227
AV_OPT_TYPE_INT
@ AV_OPT_TYPE_INT
Definition: opt.h:223
mov_text_font_size_cb
static void mov_text_font_size_cb(void *priv, int size)
Definition: movtextenc.c:575
ASSDialog
fields extracted from the [Events] section
Definition: ass_split.h:71
encode_styl
static void encode_styl(MovTextContext *s, uint32_t tsmb_type)
Definition: movtextenc.c:111
StyleBox::style_fontsize
uint8_t style_fontsize
Definition: movtextenc.c:57
av_bprint_append_any
#define av_bprint_append_any(buf, data, size)
Definition: movtextenc.c:50
MovTextContext::text_pos
uint16_t text_pos
Definition: movtextenc.c:84
HilightcolorBox
Definition: movtextdec.c:91
mem.h
mov_text_style_cb
static void mov_text_style_cb(void *priv, const char style, int close)
Definition: movtextenc.c:444
alpha
static const int16_t alpha[]
Definition: ilbcdata.h:55
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:553
mov_text_ass_style_set
static void mov_text_ass_style_set(MovTextContext *s, ASSStyle *style)
Definition: movtextenc.c:586
MovTextContext::hclr
HilightcolorBox hclr
Definition: movtextenc.c:80
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
encode_hlit
static void encode_hlit(MovTextContext *s, uint32_t tsmb_type)
Definition: movtextenc.c:145
DEFAULT_STYLE_FLAG
#define DEFAULT_STYLE_FLAG
Definition: movtextenc.c:46
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
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
HighlightBox::start
uint16_t start
Definition: movtextenc.c:62
avstring.h
Box::encode
void(* encode)(MovTextContext *s, uint32_t tsmb_type)
Definition: movtextenc.c:94
MovTextContext::ass_ctx
ASSSplitContext * ass_ctx
Definition: movtextenc.c:74
mov_text_alpha_cb
static void mov_text_alpha_cb(void *priv, int alpha, int alpha_id)
Definition: movtextenc.c:513
MovTextContext::buffer
AVBPrint buffer
Definition: movtextenc.c:76
MovTextContext
Definition: movtextdec.c:99
ASSStyle::bold
int bold
whether text is bold (1) or not (0)
Definition: ass_split.h:47
ASSCodesCallbacks::text
void(* text)(void *priv, const char *text, int len)
Definition: ass_split.h:159
HCLR_BOX
#define HCLR_BOX
Definition: movtextenc.c:41
ASS::script_info
ASSScriptInfo script_info
general information about the SSA script
Definition: ass_split.h:91