Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4349 | Serge | 1 | /* |
2 | * 3GPP TS 26.245 Timed Text encoder |
||
3 | * Copyright (c) 2012 Philip Langdale |
||
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 |
||
23 | #include "avcodec.h" |
||
24 | #include "libavutil/avassert.h" |
||
25 | #include "libavutil/avstring.h" |
||
26 | #include "libavutil/intreadwrite.h" |
||
27 | #include "ass_split.h" |
||
28 | #include "ass.h" |
||
29 | |||
30 | typedef struct { |
||
31 | ASSSplitContext *ass_ctx; |
||
32 | char buffer[2048]; |
||
33 | char *ptr; |
||
34 | char *end; |
||
35 | } MovTextContext; |
||
36 | |||
37 | |||
38 | static av_cold int mov_text_encode_init(AVCodecContext *avctx) |
||
39 | { |
||
40 | /* |
||
41 | * For now, we'll use a fixed default style. When we add styling |
||
42 | * support, this will be generated from the ASS style. |
||
43 | */ |
||
44 | static 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] |
||
49 | // BoxRecord { |
||
50 | 0x00, 0x00, // int16_t top |
||
51 | 0x00, 0x00, // int16_t left |
||
52 | 0x00, 0x00, // int16_t bottom |
||
53 | 0x00, 0x00, // int16_t right |
||
54 | // }; |
||
55 | // StyleRecord { |
||
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] |
||
62 | // }; |
||
63 | // FontTableBox { |
||
64 | 0x00, 0x00, 0x00, 0x12, // uint32_t size |
||
65 | 'f', 't', 'a', 'b', // uint8_t name[4] |
||
66 | 0x00, 0x01, // uint16_t entry-count |
||
67 | // FontRecord { |
||
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] |
||
71 | // }; |
||
72 | // }; |
||
73 | }; |
||
74 | |||
75 | MovTextContext *s = avctx->priv_data; |
||
76 | |||
77 | avctx->extradata_size = sizeof text_sample_entry; |
||
78 | avctx->extradata = av_mallocz(avctx->extradata_size); |
||
79 | if (!avctx->extradata) |
||
80 | return AVERROR(ENOMEM); |
||
81 | |||
82 | memcpy(avctx->extradata, text_sample_entry, avctx->extradata_size); |
||
83 | |||
84 | s->ass_ctx = ff_ass_split(avctx->subtitle_header); |
||
85 | return s->ass_ctx ? 0 : AVERROR_INVALIDDATA; |
||
86 | } |
||
87 | |||
88 | static void mov_text_text_cb(void *priv, const char *text, int len) |
||
89 | { |
||
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); |
||
94 | } |
||
95 | |||
96 | static void mov_text_new_line_cb(void *priv, int forced) |
||
97 | { |
||
98 | MovTextContext *s = priv; |
||
99 | av_assert0(s->end >= s->ptr); |
||
100 | av_strlcpy(s->ptr, "\n", FFMIN(s->end - s->ptr, 2)); |
||
101 | if (s->end > s->ptr) |
||
102 | s->ptr++; |
||
103 | } |
||
104 | |||
105 | static const ASSCodesCallbacks mov_text_callbacks = { |
||
106 | .text = mov_text_text_cb, |
||
107 | .new_line = mov_text_new_line_cb, |
||
108 | }; |
||
109 | |||
110 | static int mov_text_encode_frame(AVCodecContext *avctx, unsigned char *buf, |
||
111 | int bufsize, const AVSubtitle *sub) |
||
112 | { |
||
113 | MovTextContext *s = avctx->priv_data; |
||
114 | ASSDialog *dialog; |
||
115 | int i, len, num; |
||
116 | |||
117 | s->ptr = s->buffer; |
||
118 | s->end = s->ptr + sizeof(s->buffer); |
||
119 | |||
120 | for (i = 0; i < sub->num_rects; i++) { |
||
121 | |||
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); |
||
125 | } |
||
126 | |||
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); |
||
130 | } |
||
131 | } |
||
132 | |||
133 | if (s->ptr == s->buffer) |
||
134 | return 0; |
||
135 | |||
136 | AV_WB16(buf, strlen(s->buffer)); |
||
137 | buf += 2; |
||
138 | |||
139 | len = av_strlcpy(buf, s->buffer, bufsize - 2); |
||
140 | |||
141 | if (len > bufsize-3) { |
||
142 | av_log(avctx, AV_LOG_ERROR, "Buffer too small for ASS event.\n"); |
||
143 | return AVERROR(EINVAL); |
||
144 | } |
||
145 | |||
146 | return len + 2; |
||
147 | } |
||
148 | |||
149 | static int mov_text_encode_close(AVCodecContext *avctx) |
||
150 | { |
||
151 | MovTextContext *s = avctx->priv_data; |
||
152 | ff_ass_split_free(s->ass_ctx); |
||
153 | return 0; |
||
154 | } |
||
155 | |||
156 | AVCodec ff_movtext_encoder = { |
||
157 | .name = "mov_text", |
||
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, |
||
165 | };> |