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