1 /*
2 * DivX (XSUB) subtitle encoder
3 * Copyright (c) 2005 DivX, Inc.
4 * Copyright (c) 2009 Bjorn Axelsson
5 *
6 * This file is part of FFmpeg.
7 *
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22
27
28 /**
29 * Number of pixels to pad left and right.
30 *
31 * The official encoder pads the subtitles with two pixels on either side,
32 * but until we find out why, we won't do it (we will pad to have width
33 * divisible by 2 though).
34 */
36 #define PADDING_COLOR 0
37
38 /**
39 * Encode a single color run. At most 16 bits will be used.
40 * @param len length of the run, values > 255 mean "until end of line", may not be < 0.
41 * @param color color to encode, only the lowest two bits are used and all others must be 0.
42 */
44 {
47 else
50 }
51
52 /**
53 * Encode a 4-color bitmap with XSUB rle.
54 *
55 * The encoded bitmap may be wider than the source bitmap due to padding.
56 */
58 int linesize,
int w,
int h)
59 {
61
62 for (y = 0; y <
h; y++) {
63 x0 = 0;
65 // Make sure we have enough room for at least one run and padding
68
69 x1 = x0;
70 color = bitmap[x1++] & 3;
71 while (x1 <
w && (bitmap[x1] & 3) ==
color)
72 x1++;
78 } else
80 }
81
82 // Run can't be longer than 255, unless it is the rest of a row
85 } else
88
90 }
93
95
96 bitmap += linesize;
97 }
98
99 return 0;
100 }
101
103 {
104 static const int tc_divs[3] = { 1000, 60, 60 };
106 for (
i=0;
i<3;
i++) {
107 tc[
i] = ms % tc_divs[
i];
109 }
111 return ms > 99;
112 }
113
116 {
117 uint64_t startTime =
h->pts / 1000;
// FIXME: need better solution...
118 uint64_t endTime = startTime +
h->end_display_time -
h->start_display_time;
119 int start_tc[4], end_tc[4];
120 uint8_t *hdr = buf + 27; // Point behind the timestamp
121 uint8_t *rlelenptr;
125
126 if (bufsize < 27 + 7*2 + 4*3) {
129 }
130
131 // TODO: support multiple rects
132 if (
h->num_rects != 1)
134
135 // TODO: render text-based subtitles into bitmaps
136 if (!
h->rects[0]->data[0] || !
h->rects[0]->data[1]) {
139 }
140
141 // TODO: color reduction, similar to dvdsub encoder
142 if (
h->rects[0]->nb_colors > 4)
143 av_log(avctx,
AV_LOG_WARNING,
"No more than 4 subtitle colors supported (%d found.)\n",
h->rects[0]->nb_colors);
144
145 // TODO: Palette swapping if color zero is not transparent
146 if (((uint32_t *)
h->rects[0]->data[1])[0] & 0xff000000)
147 av_log(avctx,
AV_LOG_WARNING,
"Color index 0 is not transparent. Transparency will be messed up.\n");
148
152 }
153
155 "[%02d:%02d:%02d.%03d-%02d:%02d:%02d.%03d]",
156 start_tc[3], start_tc[2], start_tc[1], start_tc[0],
157 end_tc[3], end_tc[2], end_tc[1], end_tc[0]);
158
159 // Width and height must probably be multiples of 2.
160 // 2 pixels required on either side of subtitle.
161 // Possibly due to limitations of hardware renderers.
162 // TODO: check if the bitmap is already padded
165
166 bytestream_put_le16(&hdr,
width);
167 bytestream_put_le16(&hdr,
height);
168 bytestream_put_le16(&hdr,
h->rects[0]->x);
169 bytestream_put_le16(&hdr,
h->rects[0]->y);
170 bytestream_put_le16(&hdr,
h->rects[0]->x +
width -1);
171 bytestream_put_le16(&hdr,
h->rects[0]->y +
height -1);
172
173 rlelenptr = hdr; // Will store length of first field here later.
174 hdr+=2;
175
176 // Palette
178 bytestream_put_be24(&hdr, ((uint32_t *)
h->rects[0]->data[1])[
i]);
179
180 // Bitmap
181 // RLE buffer. Reserve 2 bytes for possible padding after the last row.
184 h->rects[0]->linesize[0] * 2,
185 h->rects[0]->w, (
h->rects[0]->h + 1) >> 1))
187 bytestream_put_le16(&rlelenptr,
put_bytes_count(&pb, 0));
// Length of first field
188
190 h->rects[0]->linesize[0] * 2,
191 h->rects[0]->w,
h->rects[0]->h >> 1))
193
194 // Enforce total height to be a multiple of 2
195 if (
h->rects[0]->h & 1) {
197 }
198
200
202 }
203
205 {
208
210
211 return 0;
212 }
213
222 };