Mercurial > libavcodec.hg
annotate dvbsub.c @ 6017:e1404acccac3 libavcodec
Actually return with an error condition if we're being asked to deal with too
many reference frames. Also check max num ref frames against our internal
ref buffer sizes.
Part of fix for roundup issue 281
author | heydowns |
---|---|
date | Fri, 14 Dec 2007 05:48:27 +0000 |
parents | d030978bcd93 |
children | 5b3acf9fd50a |
rev | line source |
---|---|
2756 | 1 /* |
2 * DVB subtitle encoding for ffmpeg | |
3 * Copyright (c) 2005 Fabrice Bellard. | |
4 * | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3036
diff
changeset
|
5 * This file is part of FFmpeg. |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3036
diff
changeset
|
6 * |
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3036
diff
changeset
|
7 * FFmpeg is free software; you can redistribute it and/or |
2756 | 8 * modify it under the terms of the GNU Lesser General Public |
9 * License as published by the Free Software Foundation; either | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3036
diff
changeset
|
10 * version 2.1 of the License, or (at your option) any later version. |
2756 | 11 * |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3036
diff
changeset
|
12 * FFmpeg is distributed in the hope that it will be useful, |
2756 | 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 | |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3036
diff
changeset
|
18 * License along with FFmpeg; if not, write to the Free Software |
3036
0b546eab515d
Update licensing information: The FSF changed postal address.
diego
parents:
2979
diff
changeset
|
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
2756 | 20 */ |
21 #include "avcodec.h" | |
5067 | 22 #include "bytestream.h" |
5354 | 23 #include "colorspace.h" |
2756 | 24 |
25 typedef struct DVBSubtitleContext { | |
26 int hide_state; | |
27 int object_version; | |
28 } DVBSubtitleContext; | |
29 | |
30 #define PUTBITS2(val)\ | |
31 {\ | |
32 bitbuf |= (val) << bitcnt;\ | |
33 bitcnt -= 2;\ | |
34 if (bitcnt < 0) {\ | |
35 bitcnt = 6;\ | |
36 *q++ = bitbuf;\ | |
37 bitbuf = 0;\ | |
38 }\ | |
39 } | |
40 | |
41 static void dvb_encode_rle2(uint8_t **pq, | |
42 const uint8_t *bitmap, int linesize, | |
43 int w, int h) | |
44 { | |
45 uint8_t *q; | |
46 unsigned int bitbuf; | |
47 int bitcnt; | |
48 int x, y, len, x1, v, color; | |
49 | |
50 q = *pq; | |
2967 | 51 |
2756 | 52 for(y = 0; y < h; y++) { |
53 *q++ = 0x10; | |
54 bitbuf = 0; | |
55 bitcnt = 6; | |
2967 | 56 |
2756 | 57 x = 0; |
58 while (x < w) { | |
59 x1 = x; | |
60 color = bitmap[x1++]; | |
61 while (x1 < w && bitmap[x1] == color) | |
62 x1++; | |
63 len = x1 - x; | |
64 if (color == 0 && len == 2) { | |
65 PUTBITS2(0); | |
66 PUTBITS2(0); | |
67 PUTBITS2(1); | |
68 } else if (len >= 3 && len <= 10) { | |
69 v = len - 3; | |
70 PUTBITS2(0); | |
71 PUTBITS2((v >> 2) | 2); | |
72 PUTBITS2(v & 3); | |
73 PUTBITS2(color); | |
74 } else if (len >= 12 && len <= 27) { | |
75 v = len - 12; | |
76 PUTBITS2(0); | |
77 PUTBITS2(0); | |
78 PUTBITS2(2); | |
79 PUTBITS2(v >> 2); | |
80 PUTBITS2(v & 3); | |
81 PUTBITS2(color); | |
82 } else if (len >= 29) { | |
83 /* length = 29 ... 284 */ | |
84 if (len > 284) | |
85 len = 284; | |
86 v = len - 29; | |
87 PUTBITS2(0); | |
88 PUTBITS2(0); | |
89 PUTBITS2(3); | |
90 PUTBITS2((v >> 6)); | |
91 PUTBITS2((v >> 4) & 3); | |
92 PUTBITS2((v >> 2) & 3); | |
93 PUTBITS2(v & 3); | |
94 PUTBITS2(color); | |
95 } else { | |
96 PUTBITS2(color); | |
97 if (color == 0) { | |
98 PUTBITS2(1); | |
99 } | |
100 len = 1; | |
101 } | |
102 x += len; | |
103 } | |
104 /* end of line */ | |
105 PUTBITS2(0); | |
106 PUTBITS2(0); | |
107 PUTBITS2(0); | |
108 if (bitcnt != 6) { | |
109 *q++ = bitbuf; | |
110 } | |
111 *q++ = 0xf0; | |
112 bitmap += linesize; | |
113 } | |
114 *pq = q; | |
115 } | |
116 | |
117 #define PUTBITS4(val)\ | |
118 {\ | |
119 bitbuf |= (val) << bitcnt;\ | |
120 bitcnt -= 4;\ | |
121 if (bitcnt < 0) {\ | |
122 bitcnt = 4;\ | |
123 *q++ = bitbuf;\ | |
124 bitbuf = 0;\ | |
125 }\ | |
126 } | |
127 | |
128 /* some DVB decoders only implement 4 bits/pixel */ | |
129 static void dvb_encode_rle4(uint8_t **pq, | |
130 const uint8_t *bitmap, int linesize, | |
131 int w, int h) | |
132 { | |
133 uint8_t *q; | |
134 unsigned int bitbuf; | |
135 int bitcnt; | |
136 int x, y, len, x1, v, color; | |
137 | |
138 q = *pq; | |
2967 | 139 |
2756 | 140 for(y = 0; y < h; y++) { |
141 *q++ = 0x11; | |
142 bitbuf = 0; | |
143 bitcnt = 4; | |
2967 | 144 |
2756 | 145 x = 0; |
146 while (x < w) { | |
147 x1 = x; | |
148 color = bitmap[x1++]; | |
149 while (x1 < w && bitmap[x1] == color) | |
150 x1++; | |
151 len = x1 - x; | |
152 if (color == 0 && len == 2) { | |
153 PUTBITS4(0); | |
154 PUTBITS4(0xd); | |
155 } else if (color == 0 && (len >= 3 && len <= 9)) { | |
156 PUTBITS4(0); | |
157 PUTBITS4(len - 2); | |
158 } else if (len >= 4 && len <= 7) { | |
159 PUTBITS4(0); | |
160 PUTBITS4(8 + len - 4); | |
161 PUTBITS4(color); | |
162 } else if (len >= 9 && len <= 24) { | |
163 PUTBITS4(0); | |
164 PUTBITS4(0xe); | |
165 PUTBITS4(len - 9); | |
166 PUTBITS4(color); | |
167 } else if (len >= 25) { | |
168 if (len > 280) | |
169 len = 280; | |
170 v = len - 25; | |
171 PUTBITS4(0); | |
172 PUTBITS4(0xf); | |
173 PUTBITS4(v >> 4); | |
174 PUTBITS4(v & 0xf); | |
175 PUTBITS4(color); | |
176 } else { | |
177 PUTBITS4(color); | |
178 if (color == 0) { | |
179 PUTBITS4(0xc); | |
180 } | |
181 len = 1; | |
182 } | |
183 x += len; | |
184 } | |
185 /* end of line */ | |
186 PUTBITS4(0); | |
187 PUTBITS4(0); | |
188 if (bitcnt != 4) { | |
189 *q++ = bitbuf; | |
190 } | |
191 *q++ = 0xf0; | |
192 bitmap += linesize; | |
193 } | |
194 *pq = q; | |
195 } | |
196 | |
2967 | 197 static int encode_dvb_subtitles(DVBSubtitleContext *s, |
2756 | 198 uint8_t *outbuf, AVSubtitle *h) |
199 { | |
200 uint8_t *q, *pseg_len; | |
201 int page_id, region_id, clut_id, object_id, i, bpp_index, page_state; | |
202 | |
203 | |
204 q = outbuf; | |
205 | |
206 page_id = 1; | |
2796
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
207 |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
208 if (h->num_rects == 0 || h->rects == NULL) |
2756 | 209 return -1; |
210 | |
211 *q++ = 0x00; /* subtitle_stream_id */ | |
212 | |
213 /* page composition segment */ | |
214 | |
215 *q++ = 0x0f; /* sync_byte */ | |
216 *q++ = 0x10; /* segment_type */ | |
5067 | 217 bytestream_put_be16(&q, page_id); |
2756 | 218 pseg_len = q; |
219 q += 2; /* segment length */ | |
220 *q++ = 30; /* page_timeout (seconds) */ | |
221 if (s->hide_state) | |
222 page_state = 0; /* normal case */ | |
223 else | |
224 page_state = 2; /* mode change */ | |
225 /* page_version = 0 + page_state */ | |
2967 | 226 *q++ = s->object_version | (page_state << 2) | 3; |
2796
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
227 |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
228 for (region_id = 0; region_id < h->num_rects; region_id++) { |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
229 *q++ = region_id; |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
230 *q++ = 0xff; /* reserved */ |
5067 | 231 bytestream_put_be16(&q, h->rects[region_id].x); /* left pos */ |
232 bytestream_put_be16(&q, h->rects[region_id].y); /* top pos */ | |
2796
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
233 } |
2756 | 234 |
5067 | 235 bytestream_put_be16(&pseg_len, q - pseg_len - 2); |
2756 | 236 |
237 if (!s->hide_state) { | |
2796
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
238 for (clut_id = 0; clut_id < h->num_rects; clut_id++) { |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
239 |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
240 /* CLUT segment */ |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
241 |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
242 if (h->rects[clut_id].nb_colors <= 4) { |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
243 /* 2 bpp, some decoders do not support it correctly */ |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
244 bpp_index = 0; |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
245 } else if (h->rects[clut_id].nb_colors <= 16) { |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
246 /* 4 bpp, standard encoding */ |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
247 bpp_index = 1; |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
248 } else { |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
249 return -1; |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
250 } |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
251 |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
252 *q++ = 0x0f; /* sync byte */ |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
253 *q++ = 0x12; /* CLUT definition segment */ |
5067 | 254 bytestream_put_be16(&q, page_id); |
2796
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
255 pseg_len = q; |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
256 q += 2; /* segment length */ |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
257 *q++ = clut_id; |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
258 *q++ = (0 << 4) | 0xf; /* version = 0 */ |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
259 |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
260 for(i = 0; i < h->rects[clut_id].nb_colors; i++) { |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
261 *q++ = i; /* clut_entry_id */ |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
262 *q++ = (1 << (7 - bpp_index)) | (0xf << 1) | 1; /* 2 bits/pixel full range */ |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
263 { |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
264 int a, r, g, b; |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
265 a = (h->rects[clut_id].rgba_palette[i] >> 24) & 0xff; |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
266 r = (h->rects[clut_id].rgba_palette[i] >> 16) & 0xff; |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
267 g = (h->rects[clut_id].rgba_palette[i] >> 8) & 0xff; |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
268 b = (h->rects[clut_id].rgba_palette[i] >> 0) & 0xff; |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
269 |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
270 *q++ = RGB_TO_Y_CCIR(r, g, b); |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
271 *q++ = RGB_TO_V_CCIR(r, g, b, 0); |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
272 *q++ = RGB_TO_U_CCIR(r, g, b, 0); |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
273 *q++ = 255 - a; |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
274 } |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
275 } |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
276 |
5067 | 277 bytestream_put_be16(&pseg_len, q - pseg_len - 2); |
2796
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
278 } |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
279 } |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
280 |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
281 for (region_id = 0; region_id < h->num_rects; region_id++) { |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
282 |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
283 /* region composition segment */ |
2967 | 284 |
2796
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
285 if (h->rects[region_id].nb_colors <= 4) { |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
286 /* 2 bpp, some decoders do not support it correctly */ |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
287 bpp_index = 0; |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
288 } else if (h->rects[region_id].nb_colors <= 16) { |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
289 /* 4 bpp, standard encoding */ |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
290 bpp_index = 1; |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
291 } else { |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
292 return -1; |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
293 } |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
294 |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
295 *q++ = 0x0f; /* sync_byte */ |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
296 *q++ = 0x11; /* segment_type */ |
5067 | 297 bytestream_put_be16(&q, page_id); |
2756 | 298 pseg_len = q; |
299 q += 2; /* segment length */ | |
2796
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
300 *q++ = region_id; |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
301 *q++ = (s->object_version << 4) | (0 << 3) | 0x07; /* version , no fill */ |
5067 | 302 bytestream_put_be16(&q, h->rects[region_id].w); /* region width */ |
303 bytestream_put_be16(&q, h->rects[region_id].h); /* region height */ | |
2796
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
304 *q++ = ((1 + bpp_index) << 5) | ((1 + bpp_index) << 2) | 0x03; |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
305 *q++ = region_id; /* clut_id == region_id */ |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
306 *q++ = 0; /* 8 bit fill colors */ |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
307 *q++ = 0x03; /* 4 bit and 2 bit fill colors */ |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
308 |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
309 if (!s->hide_state) { |
5067 | 310 bytestream_put_be16(&q, region_id); /* object_id == region_id */ |
2796
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
311 *q++ = (0 << 6) | (0 << 4); |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
312 *q++ = 0; |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
313 *q++ = 0xf0; |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
314 *q++ = 0; |
2756 | 315 } |
316 | |
5067 | 317 bytestream_put_be16(&pseg_len, q - pseg_len - 2); |
2756 | 318 } |
319 | |
320 if (!s->hide_state) { | |
2967 | 321 |
2796
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
322 for (object_id = 0; object_id < h->num_rects; object_id++) { |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
323 /* Object Data segment */ |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
324 |
2946
ac94d509884e
dvbsub encoder, patch by Wolfram Gloger < wmglo AH dent POIS med POIS uni-muenchen POIS de >
gpoirier
parents:
2796
diff
changeset
|
325 if (h->rects[object_id].nb_colors <= 4) { |
2796
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
326 /* 2 bpp, some decoders do not support it correctly */ |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
327 bpp_index = 0; |
2946
ac94d509884e
dvbsub encoder, patch by Wolfram Gloger < wmglo AH dent POIS med POIS uni-muenchen POIS de >
gpoirier
parents:
2796
diff
changeset
|
328 } else if (h->rects[object_id].nb_colors <= 16) { |
2796
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
329 /* 4 bpp, standard encoding */ |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
330 bpp_index = 1; |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
331 } else { |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
332 return -1; |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
333 } |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
334 |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
335 *q++ = 0x0f; /* sync byte */ |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
336 *q++ = 0x13; |
5067 | 337 bytestream_put_be16(&q, page_id); |
2796
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
338 pseg_len = q; |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
339 q += 2; /* segment length */ |
2756 | 340 |
5067 | 341 bytestream_put_be16(&q, object_id); |
2796
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
342 *q++ = (s->object_version << 4) | (0 << 2) | (0 << 1) | 1; /* version = 0, |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
343 onject_coding_method, |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
344 non_modifying_color_flag */ |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
345 { |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
346 uint8_t *ptop_field_len, *pbottom_field_len, *top_ptr, *bottom_ptr; |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
347 void (*dvb_encode_rle)(uint8_t **pq, |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
348 const uint8_t *bitmap, int linesize, |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
349 int w, int h); |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
350 ptop_field_len = q; |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
351 q += 2; |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
352 pbottom_field_len = q; |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
353 q += 2; |
2756 | 354 |
2796
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
355 if (bpp_index == 0) |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
356 dvb_encode_rle = dvb_encode_rle2; |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
357 else |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
358 dvb_encode_rle = dvb_encode_rle4; |
2756 | 359 |
2796
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
360 top_ptr = q; |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
361 dvb_encode_rle(&q, h->rects[object_id].bitmap, h->rects[object_id].w * 2, |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
362 h->rects[object_id].w, h->rects[object_id].h >> 1); |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
363 bottom_ptr = q; |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
364 dvb_encode_rle(&q, h->rects[object_id].bitmap + h->rects[object_id].w, |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
365 h->rects[object_id].w * 2, h->rects[object_id].w, |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
366 h->rects[object_id].h >> 1); |
2756 | 367 |
5067 | 368 bytestream_put_be16(&ptop_field_len, bottom_ptr - top_ptr); |
369 bytestream_put_be16(&pbottom_field_len, q - bottom_ptr); | |
2796
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
370 } |
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
371 |
5067 | 372 bytestream_put_be16(&pseg_len, q - pseg_len - 2); |
2796
95c35706acbb
DVB subtitle decoder by (Ian Caulfield: imc25, cam ac uk)
michael
parents:
2756
diff
changeset
|
373 } |
2756 | 374 } |
375 | |
376 /* end of display set segment */ | |
377 | |
378 *q++ = 0x0f; /* sync_byte */ | |
379 *q++ = 0x80; /* segment_type */ | |
5067 | 380 bytestream_put_be16(&q, page_id); |
2756 | 381 pseg_len = q; |
382 q += 2; /* segment length */ | |
383 | |
5067 | 384 bytestream_put_be16(&pseg_len, q - pseg_len - 2); |
2756 | 385 |
386 *q++ = 0xff; /* end of PES data */ | |
387 | |
388 s->object_version = (s->object_version + 1) & 0xf; | |
389 s->hide_state = !s->hide_state; | |
390 return q - outbuf; | |
391 } | |
392 | |
393 static int dvbsub_encode(AVCodecContext *avctx, | |
394 unsigned char *buf, int buf_size, void *data) | |
395 { | |
396 DVBSubtitleContext *s = avctx->priv_data; | |
397 AVSubtitle *sub = data; | |
398 int ret; | |
399 | |
400 ret = encode_dvb_subtitles(s, buf, sub); | |
401 return ret; | |
402 } | |
403 | |
404 AVCodec dvbsub_encoder = { | |
405 "dvbsub", | |
406 CODEC_TYPE_SUBTITLE, | |
407 CODEC_ID_DVB_SUBTITLE, | |
408 sizeof(DVBSubtitleContext), | |
5941 | 409 NULL, |
2756 | 410 dvbsub_encode, |
411 }; |