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/avassert.h"
25 #include "libavutil/avstring.h"
26 #include "libavutil/intreadwrite.h"
27 #include "ass_split.h"
31 ASSSplitContext
*ass_ctx
;
38 static av_cold
int mov_text_encode_init(AVCodecContext
*avctx
)
41 * For now, we'll use a fixed default style. When we add styling
42 * support, this will be generated from the ASS style.
44 static const uint8_t text_sample_entry
[] = {
45 0x00, 0x00, 0x00, 0x00, // uint32_t displayFlags
46 0x01, // int8_t horizontal-justification
47 0xFF, // int8_t vertical-justification
48 0x00, 0x00, 0x00, 0x00, // uint8_t background-color-rgba[4]
50 0x00, 0x00, // int16_t top
51 0x00, 0x00, // int16_t left
52 0x00, 0x00, // int16_t bottom
53 0x00, 0x00, // int16_t right
56 0x00, 0x00, // uint16_t startChar
57 0x00, 0x00, // uint16_t endChar
58 0x00, 0x01, // uint16_t font-ID
59 0x00, // uint8_t face-style-flags
60 0x12, // uint8_t font-size
61 0xFF, 0xFF, 0xFF, 0xFF, // uint8_t text-color-rgba[4]
64 0x00, 0x00, 0x00, 0x12, // uint32_t size
65 'f', 't', 'a', 'b', // uint8_t name[4]
66 0x00, 0x01, // uint16_t entry-count
68 0x00, 0x01, // uint16_t font-ID
69 0x05, // uint8_t font-name-length
70 'S', 'e', 'r', 'i', 'f',// uint8_t font[font-name-length]
75 MovTextContext
*s
= avctx
->priv_data
;
77 avctx
->extradata_size
= sizeof text_sample_entry
;
78 avctx
->extradata
= av_mallocz(avctx
->extradata_size
+ FF_INPUT_BUFFER_PADDING_SIZE
);
79 if (!avctx
->extradata
)
80 return AVERROR(ENOMEM
);
82 memcpy(avctx
->extradata
, text_sample_entry
, avctx
->extradata_size
);
84 s
->ass_ctx
= ff_ass_split(avctx
->subtitle_header
);
85 return s
->ass_ctx
? 0 : AVERROR_INVALIDDATA
;
88 static void mov_text_text_cb(void *priv
, const char *text
, int len
)
90 MovTextContext
*s
= priv
;
91 av_assert0(s
->end
>= s
->ptr
);
92 av_strlcpy(s
->ptr
, text
, FFMIN(s
->end
- s
->ptr
, len
+ 1));
93 s
->ptr
+= FFMIN(s
->end
- s
->ptr
, len
);
96 static void mov_text_new_line_cb(void *priv
, int forced
)
98 MovTextContext
*s
= priv
;
99 av_assert0(s
->end
>= s
->ptr
);
100 av_strlcpy(s
->ptr
, "\n", FFMIN(s
->end
- s
->ptr
, 2));
105 static const ASSCodesCallbacks mov_text_callbacks
= {
106 .text
= mov_text_text_cb
,
107 .new_line
= mov_text_new_line_cb
,
110 static int mov_text_encode_frame(AVCodecContext
*avctx
, unsigned char *buf
,
111 int bufsize
, const AVSubtitle
*sub
)
113 MovTextContext
*s
= avctx
->priv_data
;
118 s
->end
= s
->ptr
+ sizeof(s
->buffer
);
120 for (i
= 0; i
< sub
->num_rects
; i
++) {
122 if (sub
->rects
[i
]->type
!= SUBTITLE_ASS
) {
123 av_log(avctx
, AV_LOG_ERROR
, "Only SUBTITLE_ASS type supported.\n");
124 return AVERROR(ENOSYS
);
127 dialog
= ff_ass_split_dialog(s
->ass_ctx
, sub
->rects
[i
]->ass
, 0, &num
);
128 for (; dialog
&& num
--; dialog
++) {
129 ff_ass_split_override_codes(&mov_text_callbacks
, s
, dialog
->text
);
133 if (s
->ptr
== s
->buffer
)
136 AV_WB16(buf
, strlen(s
->buffer
));
139 len
= av_strlcpy(buf
, s
->buffer
, bufsize
- 2);
141 if (len
> bufsize
-3) {
142 av_log(avctx
, AV_LOG_ERROR
, "Buffer too small for ASS event.\n");
143 return AVERROR(EINVAL
);
149 static int mov_text_encode_close(AVCodecContext
*avctx
)
151 MovTextContext
*s
= avctx
->priv_data
;
152 ff_ass_split_free(s
->ass_ctx
);
156 AVCodec ff_movtext_encoder
= {
158 .long_name
= NULL_IF_CONFIG_SMALL("3GPP Timed Text subtitle"),
159 .type
= AVMEDIA_TYPE_SUBTITLE
,
160 .id
= AV_CODEC_ID_MOV_TEXT
,
161 .priv_data_size
= sizeof(MovTextContext
),
162 .init
= mov_text_encode_init
,
163 .encode_sub
= mov_text_encode_frame
,
164 .close
= mov_text_encode_close
,