2 * 3GPP TS 26.245 Timed Text encoder
3 * Copyright (c) 2012 Philip Langdale <philipl@overt.org>
5 * This file is part of FFmpeg.
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.
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.
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
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"
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
39 #define STYL_BOX (1<<0)
40 #define HLIT_BOX (1<<1)
41 #define HCLR_BOX (1<<2)
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
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)
56 uint16_t style_fontID;
57 uint8_t style_fontsize;
72 AVCodecContext *avctx;
74 ASSSplitContext *ass_ctx;
75 ASSStyle *ass_dialog_style;
77 StyleBox **style_attributes;
78 StyleBox *style_attributes_temp;
88 double font_scale_factor;
94 void (*encode)(MovTextContext *s, uint32_t tsmb_type);
97 static void mov_text_cleanup(MovTextContext *s)
100 if (s->box_flags & STYL_BOX) {
101 for (j = 0; j < s->count; j++) {
102 av_freep(&s->style_attributes[j]);
104 av_freep(&s->style_attributes);
107 if (s->style_attributes_temp) {
108 *s->style_attributes_temp = s->d;
112 static void encode_styl(MovTextContext *s, uint32_t tsmb_type)
116 uint16_t style_entries;
117 if ((s->box_flags & STYL_BOX) && s->count) {
118 tsmb_size = s->count * STYLE_RECORD_SIZE + SIZE_ADD;
119 tsmb_size = AV_RB32(&tsmb_size);
120 tsmb_type = AV_RB32(&tsmb_type);
121 style_entries = AV_RB16(&s->count);
122 /*The above three attributes are hard coded for now
123 but will come from ASS style in the future*/
124 av_bprint_append_any(&s->buffer, &tsmb_size, 4);
125 av_bprint_append_any(&s->buffer, &tsmb_type, 4);
126 av_bprint_append_any(&s->buffer, &style_entries, 2);
127 for (j = 0; j < s->count; j++) {
128 uint16_t style_start, style_end, style_fontID;
129 uint32_t style_color;
131 style_start = AV_RB16(&s->style_attributes[j]->style_start);
132 style_end = AV_RB16(&s->style_attributes[j]->style_end);
133 style_color = AV_RB32(&s->style_attributes[j]->style_color);
134 style_fontID = AV_RB16(&s->style_attributes[j]->style_fontID);
136 av_bprint_append_any(&s->buffer, &style_start, 2);
137 av_bprint_append_any(&s->buffer, &style_end, 2);
138 av_bprint_append_any(&s->buffer, &style_fontID, 2);
139 av_bprint_append_any(&s->buffer, &s->style_attributes[j]->style_flag, 1);
140 av_bprint_append_any(&s->buffer, &s->style_attributes[j]->style_fontsize, 1);
141 av_bprint_append_any(&s->buffer, &style_color, 4);
147 static void encode_hlit(MovTextContext *s, uint32_t tsmb_type)
151 if (s->box_flags & HLIT_BOX) {
153 tsmb_size = AV_RB32(&tsmb_size);
154 tsmb_type = AV_RB32(&tsmb_type);
155 start = AV_RB16(&s->hlit.start);
156 end = AV_RB16(&s->hlit.end);
157 av_bprint_append_any(&s->buffer, &tsmb_size, 4);
158 av_bprint_append_any(&s->buffer, &tsmb_type, 4);
159 av_bprint_append_any(&s->buffer, &start, 2);
160 av_bprint_append_any(&s->buffer, &end, 2);
164 static void encode_hclr(MovTextContext *s, uint32_t tsmb_type)
166 uint32_t tsmb_size, color;
167 if (s->box_flags & HCLR_BOX) {
169 tsmb_size = AV_RB32(&tsmb_size);
170 tsmb_type = AV_RB32(&tsmb_type);
171 color = AV_RB32(&s->hclr.color);
172 av_bprint_append_any(&s->buffer, &tsmb_size, 4);
173 av_bprint_append_any(&s->buffer, &tsmb_type, 4);
174 av_bprint_append_any(&s->buffer, &color, 4);
178 static const Box box_types[] = {
179 { MKBETAG('s','t','y','l'), encode_styl },
180 { MKBETAG('h','l','i','t'), encode_hlit },
181 { MKBETAG('h','c','l','r'), encode_hclr },
184 const static size_t box_count = FF_ARRAY_ELEMS(box_types);
186 static int mov_text_encode_close(AVCodecContext *avctx)
188 MovTextContext *s = avctx->priv_data;
191 ff_ass_split_free(s->ass_ctx);
192 if (s->style_attributes) {
193 for (i = 0; i < s->count; i++) {
194 av_freep(&s->style_attributes[i]);
196 av_freep(&s->style_attributes);
199 av_freep(&s->style_attributes_temp);
200 av_bprint_finalize(&s->buffer, NULL);
204 static int encode_sample_description(AVCodecContext *avctx)
209 uint32_t tsmb_size, tsmb_type, back_color = 0, style_color;
210 uint16_t style_start, style_end, fontID, count;
211 int font_names_total_len = 0;
212 MovTextContext *s = avctx->priv_data;
214 static const uint8_t display_and_justification[] = {
215 0x00, 0x00, 0x00, 0x00, // uint32_t displayFlags
216 0x01, // int8_t horizontal-justification
217 0xFF, // int8_t vertical-justification
219 // 0x00, 0x00, 0x00, 0x00, // uint8_t background-color-rgba[4]
220 static const uint8_t box_record[] = {
222 0x00, 0x00, // int16_t top
223 0x00, 0x00, // int16_t left
224 0x00, 0x00, // int16_t bottom
225 0x00, 0x00, // int16_t right
229 // 0x00, 0x00, // uint16_t startChar
230 // 0x00, 0x00, // uint16_t endChar
231 // 0x00, 0x01, // uint16_t font-ID
232 // 0x00, // uint8_t face-style-flags
233 // 0x12, // uint8_t font-size
234 // 0xFF, 0xFF, 0xFF, 0xFF, // uint8_t text-color-rgba[4]
237 // 0x00, 0x00, 0x00, 0x12, // uint32_t size
238 // 'f', 't', 'a', 'b', // uint8_t name[4]
239 // 0x00, 0x01, // uint16_t entry-count
241 // 0x00, 0x01, // uint16_t font-ID
242 // 0x05, // uint8_t font-name-length
243 // 'S', 'e', 'r', 'i', 'f',// uint8_t font[font-name-length]
247 // Populate sample description from ASS header
248 ass = (ASS*)s->ass_ctx;
249 // Compute font scaling factor based on (optionally) provided
250 // output video height and ASS script play_res_y
251 if (s->frame_height && ass->script_info.play_res_y)
252 s->font_scale_factor = (double)s->frame_height / ass->script_info.play_res_y;
254 s->font_scale_factor = 1;
256 style = ff_ass_style_get(s->ass_ctx, "Default");
257 if (!style && ass->styles_count) {
258 style = &ass->styles[0];
260 s->d.style_fontID = DEFAULT_STYLE_FONT_ID;
261 s->d.style_fontsize = DEFAULT_STYLE_FONTSIZE;
262 s->d.style_color = DEFAULT_STYLE_COLOR;
263 s->d.style_flag = DEFAULT_STYLE_FLAG;
265 s->d.style_fontsize = FONTSIZE_SCALE(s, style->font_size);
266 s->d.style_color = BGR_TO_RGB(style->primary_color & 0xffffff) << 8 |
267 255 - ((uint32_t)style->primary_color >> 24);
268 s->d.style_flag = (!!style->bold * STYLE_FLAG_BOLD) |
269 (!!style->italic * STYLE_FLAG_ITALIC) |
270 (!!style->underline * STYLE_FLAG_UNDERLINE);
271 back_color = (BGR_TO_RGB(style->back_color & 0xffffff) << 8) |
272 (255 - ((uint32_t)style->back_color >> 24));
275 av_bprint_append_any(&s->buffer, display_and_justification,
276 sizeof(display_and_justification));
277 back_color = AV_RB32(&back_color);
278 av_bprint_append_any(&s->buffer, &back_color, 4);
280 av_bprint_append_any(&s->buffer, box_record, sizeof(box_record));
283 style_start = AV_RB16(&s->d.style_start);
284 style_end = AV_RB16(&s->d.style_end);
285 fontID = AV_RB16(&s->d.style_fontID);
286 style_color = AV_RB32(&s->d.style_color);
287 av_bprint_append_any(&s->buffer, &style_start, 2);
288 av_bprint_append_any(&s->buffer, &style_end, 2);
289 av_bprint_append_any(&s->buffer, &fontID, 2);
290 av_bprint_append_any(&s->buffer, &s->d.style_flag, 1);
291 av_bprint_append_any(&s->buffer, &s->d.style_fontsize, 1);
292 av_bprint_append_any(&s->buffer, &style_color, 4);
296 // We can't build a complete font table since that would require
297 // scanning all dialogs first. But we can at least fill in what
298 // is avaiable in the ASS header
299 if (style && ass->styles_count) {
300 // Find unique font names
301 av_dynarray_add(&s->fonts, &s->font_count, style->font_name);
302 font_names_total_len += strlen(style->font_name);
303 for (i = 0; i < ass->styles_count; i++) {
305 for (j = 0; j < s->font_count; j++) {
306 if (!strcmp(s->fonts[j], ass->styles[i].font_name)) {
312 av_dynarray_add(&s->fonts, &s->font_count,
313 ass->styles[i].font_name);
314 font_names_total_len += strlen(ass->styles[i].font_name);
318 av_dynarray_add(&s->fonts, &s->font_count, (char*)"Serif");
321 tsmb_size = SIZE_ADD + 3 * s->font_count + font_names_total_len;
322 tsmb_size = AV_RB32(&tsmb_size);
323 tsmb_type = MKBETAG('f','t','a','b');
324 tsmb_type = AV_RB32(&tsmb_type);
325 count = s->font_count;
326 count = AV_RB16(&count);
327 av_bprint_append_any(&s->buffer, &tsmb_size, 4);
328 av_bprint_append_any(&s->buffer, &tsmb_type, 4);
329 av_bprint_append_any(&s->buffer, &count, 2);
331 for (i = 0; i < s->font_count; i++) {
334 fontID = AV_RB16(&fontID);
335 av_bprint_append_any(&s->buffer, &fontID, 2);
336 len = strlen(s->fonts[i]);
337 av_bprint_append_any(&s->buffer, &len, 1);
338 av_bprint_append_any(&s->buffer, s->fonts[i], len);
343 if (!av_bprint_is_complete(&s->buffer)) {
344 return AVERROR(ENOMEM);
347 avctx->extradata_size = s->buffer.len;
348 avctx->extradata = av_mallocz(avctx->extradata_size + AV_INPUT_BUFFER_PADDING_SIZE);
349 if (!avctx->extradata) {
350 return AVERROR(ENOMEM);
353 memcpy(avctx->extradata, s->buffer.str, avctx->extradata_size);
354 av_bprint_clear(&s->buffer);
359 static av_cold int mov_text_encode_init(AVCodecContext *avctx)
362 MovTextContext *s = avctx->priv_data;
365 av_bprint_init(&s->buffer, 0, AV_BPRINT_SIZE_UNLIMITED);
367 s->style_attributes_temp = av_mallocz(sizeof(*s->style_attributes_temp));
368 if (!s->style_attributes_temp) {
369 ret = AVERROR(ENOMEM);
373 s->ass_ctx = ff_ass_split(avctx->subtitle_header);
375 ret = AVERROR_INVALIDDATA;
378 ret = encode_sample_description(avctx);
385 mov_text_encode_close(avctx);
389 // Start a new style box if needed
390 static int mov_text_style_start(MovTextContext *s)
392 // there's an existing style entry
393 if (s->style_attributes_temp->style_start == s->text_pos)
394 // Still at same text pos, use same entry
396 if (s->style_attributes_temp->style_flag != s->d.style_flag ||
397 s->style_attributes_temp->style_color != s->d.style_color ||
398 s->style_attributes_temp->style_fontID != s->d.style_fontID ||
399 s->style_attributes_temp->style_fontsize != s->d.style_fontsize) {
400 // last style != defaults, end the style entry and start a new one
401 s->box_flags |= STYL_BOX;
402 s->style_attributes_temp->style_end = s->text_pos;
403 av_dynarray_add(&s->style_attributes, &s->count, s->style_attributes_temp);
404 s->style_attributes_temp = av_malloc(sizeof(*s->style_attributes_temp));
405 if (!s->style_attributes_temp) {
407 av_bprint_clear(&s->buffer);
408 s->box_flags &= ~STYL_BOX;
412 *s->style_attributes_temp = s->d;
413 s->style_attributes_temp->style_start = s->text_pos;
414 } else { // style entry matches defaults, drop entry
415 *s->style_attributes_temp = s->d;
416 s->style_attributes_temp->style_start = s->text_pos;
421 static uint8_t mov_text_style_to_flag(const char style)
423 uint8_t style_flag = 0;
427 style_flag = STYLE_FLAG_BOLD;
430 style_flag = STYLE_FLAG_ITALIC;
433 style_flag = STYLE_FLAG_UNDERLINE;
439 static void mov_text_style_set(MovTextContext *s, uint8_t style_flags)
441 if (!s->style_attributes_temp ||
442 !((s->style_attributes_temp->style_flag & style_flags) ^ style_flags)) {
443 // setting flags that that are already set
446 if (mov_text_style_start(s))
447 s->style_attributes_temp->style_flag |= style_flags;
450 static void mov_text_style_cb(void *priv, const char style, int close)
452 MovTextContext *s = priv;
453 uint8_t style_flag = mov_text_style_to_flag(style);
455 if (!s->style_attributes_temp ||
456 !!(s->style_attributes_temp->style_flag & style_flag) != close) {
457 // setting flag that is already set
460 if (mov_text_style_start(s)) {
462 s->style_attributes_temp->style_flag |= style_flag;
464 s->style_attributes_temp->style_flag &= ~style_flag;
468 static void mov_text_color_set(MovTextContext *s, uint32_t color)
470 if (!s->style_attributes_temp ||
471 (s->style_attributes_temp->style_color & 0xffffff00) == color) {
472 // color hasn't changed
475 if (mov_text_style_start(s))
476 s->style_attributes_temp->style_color = (color & 0xffffff00) |
477 (s->style_attributes_temp->style_color & 0xff);
480 static void mov_text_color_cb(void *priv, unsigned int color, unsigned int color_id)
482 MovTextContext *s = priv;
484 color = BGR_TO_RGB(color) << 8;
485 if (color_id == 1) { //primary color changes
486 mov_text_color_set(s, color);
487 } else if (color_id == 2) { //secondary color changes
488 if (!(s->box_flags & HCLR_BOX))
489 // Highlight alpha not set yet, use current primary alpha
490 s->hclr.color = s->style_attributes_temp->style_color;
491 if (!(s->box_flags & HLIT_BOX) || s->hlit.start == s->text_pos) {
492 s->box_flags |= HCLR_BOX;
493 s->box_flags |= HLIT_BOX;
494 s->hlit.start = s->text_pos;
495 s->hclr.color = color | (s->hclr.color & 0xFF);
498 s->hlit.end = s->text_pos;
499 /* If there are more than one secondary color changes in ASS,
500 take start of first section and end of last section. Movtext
501 allows only one highlight box per sample.
504 // Movtext does not support changes to other color_id (outline, background)
507 static void mov_text_alpha_set(MovTextContext *s, uint8_t alpha)
509 if (!s->style_attributes_temp ||
510 (s->style_attributes_temp->style_color & 0xff) == alpha) {
511 // color hasn't changed
514 if (mov_text_style_start(s))
515 s->style_attributes_temp->style_color =
516 (s->style_attributes_temp->style_color & 0xffffff00) | alpha;
519 static void mov_text_alpha_cb(void *priv, int alpha, int alpha_id)
521 MovTextContext *s = priv;
524 if (alpha_id == 1) // primary alpha changes
525 mov_text_alpha_set(s, alpha);
526 else if (alpha_id == 2) { //secondary alpha changes
527 if (!(s->box_flags & HCLR_BOX))
528 // Highlight color not set yet, use current primary color
529 s->hclr.color = s->style_attributes_temp->style_color;
530 if (!(s->box_flags & HLIT_BOX) || s->hlit.start == s->text_pos) {
531 s->box_flags |= HCLR_BOX;
532 s->box_flags |= HLIT_BOX;
533 s->hlit.start = s->text_pos;
534 s->hclr.color = (s->hclr.color & 0xffffff00) | alpha;
537 s->hlit.end = s->text_pos;
539 // Movtext does not support changes to other alpha_id (outline, background)
542 static uint16_t find_font_id(MovTextContext *s, const char *name)
545 for (i = 0; i < s->font_count; i++) {
546 if (!strcmp(name, s->fonts[i]))
552 static void mov_text_font_name_set(MovTextContext *s, const char *name)
554 int fontID = find_font_id(s, name);
555 if (!s->style_attributes_temp ||
556 s->style_attributes_temp->style_fontID == fontID) {
557 // color hasn't changed
560 if (mov_text_style_start(s))
561 s->style_attributes_temp->style_fontID = fontID;
564 static void mov_text_font_name_cb(void *priv, const char *name)
566 mov_text_font_name_set((MovTextContext*)priv, name);
569 static void mov_text_font_size_set(MovTextContext *s, int size)
571 size = FONTSIZE_SCALE(s, size);
572 if (!s->style_attributes_temp ||
573 s->style_attributes_temp->style_fontsize == size) {
574 // color hasn't changed
577 if (mov_text_style_start(s))
578 s->style_attributes_temp->style_fontsize = size;
581 static void mov_text_font_size_cb(void *priv, int size)
583 mov_text_font_size_set((MovTextContext*)priv, size);
586 static void mov_text_end_cb(void *priv)
588 // End of text, close any open style record
589 mov_text_style_start((MovTextContext*)priv);
592 static void mov_text_ass_style_set(MovTextContext *s, ASSStyle *style)
594 uint8_t style_flags, alpha;
598 style_flags = (!!style->bold * STYLE_FLAG_BOLD) |
599 (!!style->italic * STYLE_FLAG_ITALIC) |
600 (!!style->underline * STYLE_FLAG_UNDERLINE);
601 mov_text_style_set(s, style_flags);
602 color = BGR_TO_RGB(style->primary_color & 0xffffff) << 8;
603 mov_text_color_set(s, color);
604 alpha = 255 - ((uint32_t)style->primary_color >> 24);
605 mov_text_alpha_set(s, alpha);
606 mov_text_font_size_set(s, style->font_size);
607 mov_text_font_name_set(s, style->font_name);
609 // End current style record, go back to defaults
610 mov_text_style_start(s);
614 static void mov_text_dialog(MovTextContext *s, ASSDialog *dialog)
616 ASSStyle *style = ff_ass_style_get(s->ass_ctx, dialog->style);
618 s->ass_dialog_style = style;
619 mov_text_ass_style_set(s, style);
622 static void mov_text_cancel_overrides_cb(void *priv, const char *style_name)
624 MovTextContext *s = priv;
627 if (!style_name || !*style_name)
628 style = s->ass_dialog_style;
630 style= ff_ass_style_get(s->ass_ctx, style_name);
632 mov_text_ass_style_set(s, style);
635 static uint16_t utf8_strlen(const char *text, int len)
637 uint16_t i = 0, ret = 0;
642 else if ((c & 0xE0) == 0xC0)
644 else if ((c & 0xF0) == 0xE0)
646 else if ((c & 0xF8) == 0xF0)
655 static void mov_text_text_cb(void *priv, const char *text, int len)
657 uint16_t utf8_len = utf8_strlen(text, len);
658 MovTextContext *s = priv;
659 av_bprint_append_data(&s->buffer, text, len);
660 // If it's not utf-8, just use the byte length
661 s->text_pos += utf8_len ? utf8_len : len;
662 s->byte_count += len;
665 static void mov_text_new_line_cb(void *priv, int forced)
667 MovTextContext *s = priv;
668 av_bprint_append_data(&s->buffer, "\n", 1);
673 static const ASSCodesCallbacks mov_text_callbacks = {
674 .text = mov_text_text_cb,
675 .new_line = mov_text_new_line_cb,
676 .style = mov_text_style_cb,
677 .color = mov_text_color_cb,
678 .alpha = mov_text_alpha_cb,
679 .font_name = mov_text_font_name_cb,
680 .font_size = mov_text_font_size_cb,
681 .cancel_overrides = mov_text_cancel_overrides_cb,
682 .end = mov_text_end_cb,
685 static int mov_text_encode_frame(AVCodecContext *avctx, unsigned char *buf,
686 int bufsize, const AVSubtitle *sub)
688 MovTextContext *s = avctx->priv_data;
697 for (i = 0; i < sub->num_rects; i++) {
698 const char *ass = sub->rects[i]->ass;
700 if (sub->rects[i]->type != SUBTITLE_ASS) {
701 av_log(avctx, AV_LOG_ERROR, "Only SUBTITLE_ASS type supported.\n");
702 return AVERROR(EINVAL);
705 #if FF_API_ASS_TIMING
706 if (!strncmp(ass, "Dialogue: ", 10)) {
708 dialog = ff_ass_split_dialog(s->ass_ctx, ass, 0, &num);
709 for (; dialog && num--; dialog++) {
710 mov_text_dialog(s, dialog);
711 ff_ass_split_override_codes(&mov_text_callbacks, s, dialog->text);
715 dialog = ff_ass_split_dialog2(s->ass_ctx, ass);
717 return AVERROR(ENOMEM);
718 mov_text_dialog(s, dialog);
719 ff_ass_split_override_codes(&mov_text_callbacks, s, dialog->text);
720 ff_ass_free_dialog(&dialog);
721 #if FF_API_ASS_TIMING
725 for (j = 0; j < box_count; j++) {
726 box_types[j].encode(s, box_types[j].type);
730 AV_WB16(buf, s->byte_count);
733 if (!av_bprint_is_complete(&s->buffer)) {
734 length = AVERROR(ENOMEM);
738 if (!s->buffer.len) {
743 if (s->buffer.len > bufsize - 3) {
744 av_log(avctx, AV_LOG_ERROR, "Buffer too small for ASS event.\n");
745 length = AVERROR_BUFFER_TOO_SMALL;
749 memcpy(buf, s->buffer.str, s->buffer.len);
750 length = s->buffer.len + 2;
753 av_bprint_clear(&s->buffer);
757 #define OFFSET(x) offsetof(MovTextContext, x)
758 #define FLAGS AV_OPT_FLAG_ENCODING_PARAM | AV_OPT_FLAG_SUBTITLE_PARAM
759 static const AVOption options[] = {
760 { "height", "Frame height, usually video height", OFFSET(frame_height), AV_OPT_TYPE_INT, {.i64=0}, 0, INT_MAX, FLAGS },
764 static const AVClass mov_text_encoder_class = {
765 .class_name = "MOV text enoder",
766 .item_name = av_default_item_name,
768 .version = LIBAVUTIL_VERSION_INT,
771 AVCodec ff_movtext_encoder = {
773 .long_name = NULL_IF_CONFIG_SMALL("3GPP Timed Text subtitle"),
774 .type = AVMEDIA_TYPE_SUBTITLE,
775 .id = AV_CODEC_ID_MOV_TEXT,
776 .priv_data_size = sizeof(MovTextContext),
777 .priv_class = &mov_text_encoder_class,
778 .init = mov_text_encode_init,
779 .encode_sub = mov_text_encode_frame,
780 .close = mov_text_encode_close,