Mercurial > libavcodec.hg
comparison dvbsub.c @ 2756:d8874c8749ec libavcodec
subtitle codec type support
author | bellard |
---|---|
date | Fri, 03 Jun 2005 13:59:38 +0000 |
parents | |
children | 95c35706acbb |
comparison
equal
deleted
inserted
replaced
2755:975074f04b95 | 2756:d8874c8749ec |
---|---|
1 /* | |
2 * DVB subtitle encoding for ffmpeg | |
3 * Copyright (c) 2005 Fabrice Bellard. | |
4 * | |
5 * This library is free software; you can redistribute it and/or | |
6 * modify it under the terms of the GNU Lesser General Public | |
7 * License as published by the Free Software Foundation; either | |
8 * version 2 of the License, or (at your option) any later version. | |
9 * | |
10 * This library is distributed in the hope that it will be useful, | |
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 * Lesser General Public License for more details. | |
14 * | |
15 * You should have received a copy of the GNU Lesser General Public | |
16 * License along with this library; if not, write to the Free Software | |
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
18 */ | |
19 #include "avcodec.h" | |
20 | |
21 typedef struct DVBSubtitleContext { | |
22 int hide_state; | |
23 int object_version; | |
24 } DVBSubtitleContext; | |
25 | |
26 #define PUTBITS2(val)\ | |
27 {\ | |
28 bitbuf |= (val) << bitcnt;\ | |
29 bitcnt -= 2;\ | |
30 if (bitcnt < 0) {\ | |
31 bitcnt = 6;\ | |
32 *q++ = bitbuf;\ | |
33 bitbuf = 0;\ | |
34 }\ | |
35 } | |
36 | |
37 static void dvb_encode_rle2(uint8_t **pq, | |
38 const uint8_t *bitmap, int linesize, | |
39 int w, int h) | |
40 { | |
41 uint8_t *q; | |
42 unsigned int bitbuf; | |
43 int bitcnt; | |
44 int x, y, len, x1, v, color; | |
45 | |
46 q = *pq; | |
47 | |
48 for(y = 0; y < h; y++) { | |
49 *q++ = 0x10; | |
50 bitbuf = 0; | |
51 bitcnt = 6; | |
52 | |
53 x = 0; | |
54 while (x < w) { | |
55 x1 = x; | |
56 color = bitmap[x1++]; | |
57 while (x1 < w && bitmap[x1] == color) | |
58 x1++; | |
59 len = x1 - x; | |
60 if (color == 0 && len == 2) { | |
61 PUTBITS2(0); | |
62 PUTBITS2(0); | |
63 PUTBITS2(1); | |
64 } else if (len >= 3 && len <= 10) { | |
65 v = len - 3; | |
66 PUTBITS2(0); | |
67 PUTBITS2((v >> 2) | 2); | |
68 PUTBITS2(v & 3); | |
69 PUTBITS2(color); | |
70 } else if (len >= 12 && len <= 27) { | |
71 v = len - 12; | |
72 PUTBITS2(0); | |
73 PUTBITS2(0); | |
74 PUTBITS2(2); | |
75 PUTBITS2(v >> 2); | |
76 PUTBITS2(v & 3); | |
77 PUTBITS2(color); | |
78 } else if (len >= 29) { | |
79 /* length = 29 ... 284 */ | |
80 if (len > 284) | |
81 len = 284; | |
82 v = len - 29; | |
83 PUTBITS2(0); | |
84 PUTBITS2(0); | |
85 PUTBITS2(3); | |
86 PUTBITS2((v >> 6)); | |
87 PUTBITS2((v >> 4) & 3); | |
88 PUTBITS2((v >> 2) & 3); | |
89 PUTBITS2(v & 3); | |
90 PUTBITS2(color); | |
91 } else { | |
92 PUTBITS2(color); | |
93 if (color == 0) { | |
94 PUTBITS2(1); | |
95 } | |
96 len = 1; | |
97 } | |
98 x += len; | |
99 } | |
100 /* end of line */ | |
101 PUTBITS2(0); | |
102 PUTBITS2(0); | |
103 PUTBITS2(0); | |
104 if (bitcnt != 6) { | |
105 *q++ = bitbuf; | |
106 } | |
107 *q++ = 0xf0; | |
108 bitmap += linesize; | |
109 } | |
110 *pq = q; | |
111 } | |
112 | |
113 #define PUTBITS4(val)\ | |
114 {\ | |
115 bitbuf |= (val) << bitcnt;\ | |
116 bitcnt -= 4;\ | |
117 if (bitcnt < 0) {\ | |
118 bitcnt = 4;\ | |
119 *q++ = bitbuf;\ | |
120 bitbuf = 0;\ | |
121 }\ | |
122 } | |
123 | |
124 /* some DVB decoders only implement 4 bits/pixel */ | |
125 static void dvb_encode_rle4(uint8_t **pq, | |
126 const uint8_t *bitmap, int linesize, | |
127 int w, int h) | |
128 { | |
129 uint8_t *q; | |
130 unsigned int bitbuf; | |
131 int bitcnt; | |
132 int x, y, len, x1, v, color; | |
133 | |
134 q = *pq; | |
135 | |
136 for(y = 0; y < h; y++) { | |
137 *q++ = 0x11; | |
138 bitbuf = 0; | |
139 bitcnt = 4; | |
140 | |
141 x = 0; | |
142 while (x < w) { | |
143 x1 = x; | |
144 color = bitmap[x1++]; | |
145 while (x1 < w && bitmap[x1] == color) | |
146 x1++; | |
147 len = x1 - x; | |
148 if (color == 0 && len == 2) { | |
149 PUTBITS4(0); | |
150 PUTBITS4(0xd); | |
151 } else if (color == 0 && (len >= 3 && len <= 9)) { | |
152 PUTBITS4(0); | |
153 PUTBITS4(len - 2); | |
154 } else if (len >= 4 && len <= 7) { | |
155 PUTBITS4(0); | |
156 PUTBITS4(8 + len - 4); | |
157 PUTBITS4(color); | |
158 } else if (len >= 9 && len <= 24) { | |
159 PUTBITS4(0); | |
160 PUTBITS4(0xe); | |
161 PUTBITS4(len - 9); | |
162 PUTBITS4(color); | |
163 } else if (len >= 25) { | |
164 if (len > 280) | |
165 len = 280; | |
166 v = len - 25; | |
167 PUTBITS4(0); | |
168 PUTBITS4(0xf); | |
169 PUTBITS4(v >> 4); | |
170 PUTBITS4(v & 0xf); | |
171 PUTBITS4(color); | |
172 } else { | |
173 PUTBITS4(color); | |
174 if (color == 0) { | |
175 PUTBITS4(0xc); | |
176 } | |
177 len = 1; | |
178 } | |
179 x += len; | |
180 } | |
181 /* end of line */ | |
182 PUTBITS4(0); | |
183 PUTBITS4(0); | |
184 if (bitcnt != 4) { | |
185 *q++ = bitbuf; | |
186 } | |
187 *q++ = 0xf0; | |
188 bitmap += linesize; | |
189 } | |
190 *pq = q; | |
191 } | |
192 | |
193 #define SCALEBITS 10 | |
194 #define ONE_HALF (1 << (SCALEBITS - 1)) | |
195 #define FIX(x) ((int) ((x) * (1<<SCALEBITS) + 0.5)) | |
196 | |
197 #define RGB_TO_Y_CCIR(r, g, b) \ | |
198 ((FIX(0.29900*219.0/255.0) * (r) + FIX(0.58700*219.0/255.0) * (g) + \ | |
199 FIX(0.11400*219.0/255.0) * (b) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS) | |
200 | |
201 #define RGB_TO_U_CCIR(r1, g1, b1, shift)\ | |
202 (((- FIX(0.16874*224.0/255.0) * r1 - FIX(0.33126*224.0/255.0) * g1 + \ | |
203 FIX(0.50000*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) | |
204 | |
205 #define RGB_TO_V_CCIR(r1, g1, b1, shift)\ | |
206 (((FIX(0.50000*224.0/255.0) * r1 - FIX(0.41869*224.0/255.0) * g1 - \ | |
207 FIX(0.08131*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) | |
208 | |
209 static inline void putbe16(uint8_t **pq, uint16_t v) | |
210 { | |
211 uint8_t *q; | |
212 q = *pq; | |
213 *q++ = v >> 8; | |
214 *q++ = v; | |
215 *pq = q; | |
216 } | |
217 | |
218 static int encode_dvb_subtitles(DVBSubtitleContext *s, | |
219 uint8_t *outbuf, AVSubtitle *h) | |
220 { | |
221 uint8_t *q, *pseg_len; | |
222 int page_id, region_id, clut_id, object_id, i, bpp_index, page_state; | |
223 | |
224 | |
225 q = outbuf; | |
226 | |
227 page_id = 1; | |
228 region_id = 0; | |
229 clut_id = 0; | |
230 object_id = 0; | |
231 if (h->nb_colors <= 4) { | |
232 /* 2 bpp, some decoders do not support it correctly */ | |
233 bpp_index = 0; | |
234 } else if (h->nb_colors <= 16) { | |
235 /* 4 bpp, standard encoding */ | |
236 bpp_index = 1; | |
237 } else { | |
238 return -1; | |
239 } | |
240 | |
241 *q++ = 0x00; /* subtitle_stream_id */ | |
242 | |
243 /* page composition segment */ | |
244 | |
245 *q++ = 0x0f; /* sync_byte */ | |
246 *q++ = 0x10; /* segment_type */ | |
247 putbe16(&q, page_id); | |
248 pseg_len = q; | |
249 q += 2; /* segment length */ | |
250 *q++ = 30; /* page_timeout (seconds) */ | |
251 if (s->hide_state) | |
252 page_state = 0; /* normal case */ | |
253 else | |
254 page_state = 2; /* mode change */ | |
255 /* page_version = 0 + page_state */ | |
256 *q++ = s->object_version | (page_state << 2) | 3; | |
257 *q++ = region_id; | |
258 *q++ = 0xff; /* reserved */ | |
259 putbe16(&q, 0); /* left pos */ | |
260 putbe16(&q, 0); /* top pos */ | |
261 | |
262 putbe16(&pseg_len, q - pseg_len - 2); | |
263 | |
264 if (!s->hide_state) { | |
265 /* CLUT segment */ | |
266 | |
267 *q++ = 0x0f; /* sync byte */ | |
268 *q++ = 0x12; /* CLUT definition segment */ | |
269 putbe16(&q, page_id); | |
270 pseg_len = q; | |
271 q += 2; /* segment length */ | |
272 *q++ = clut_id; | |
273 *q++ = (0 << 4) | 0xf; /* version = 0 */ | |
274 | |
275 for(i = 0; i < h->nb_colors; i++) { | |
276 *q++ = i; /* clut_entry_id */ | |
277 *q++ = (1 << (7 - bpp_index)) | (0xf << 1) | 1; /* 2 bits/pixel full range */ | |
278 { | |
279 int a, r, g, b; | |
280 a = (h->rgba_palette[i] >> 24) & 0xff; | |
281 r = (h->rgba_palette[i] >> 16) & 0xff; | |
282 g = (h->rgba_palette[i] >> 8) & 0xff; | |
283 b = (h->rgba_palette[i] >> 0) & 0xff; | |
284 | |
285 *q++ = RGB_TO_Y_CCIR(r, g, b); | |
286 *q++ = RGB_TO_V_CCIR(r, g, b, 0); | |
287 *q++ = RGB_TO_U_CCIR(r, g, b, 0); | |
288 *q++ = 255 - a; | |
289 } | |
290 } | |
291 | |
292 putbe16(&pseg_len, q - pseg_len - 2); | |
293 } | |
294 /* region composition segment */ | |
295 | |
296 *q++ = 0x0f; /* sync_byte */ | |
297 *q++ = 0x11; /* segment_type */ | |
298 putbe16(&q, page_id); | |
299 pseg_len = q; | |
300 q += 2; /* segment length */ | |
301 *q++ = region_id; | |
302 *q++ = (s->object_version << 4) | (0 << 3) | 0x07; /* version , no fill */ | |
303 putbe16(&q, 720); /* region width */ | |
304 putbe16(&q, 576); /* region height */ | |
305 *q++ = ((1 + bpp_index) << 5) | ((1 + bpp_index) << 2) | 0x03; | |
306 *q++ = clut_id; | |
307 *q++ = 0; /* 8 bit fill colors */ | |
308 *q++ = 0x03; /* 4 bit and 2 bit fill colors */ | |
309 | |
310 if (!s->hide_state) { | |
311 putbe16(&q, object_id); | |
312 *q++ = (0 << 6) | (0 << 4) | ((h->x >> 8) & 0xf); | |
313 *q++ = h->x; | |
314 *q++ = 0xf0 | ((h->y >> 8) & 0xf); | |
315 *q++ = h->y; | |
316 } | |
317 | |
318 putbe16(&pseg_len, q - pseg_len - 2); | |
319 | |
320 if (!s->hide_state) { | |
321 | |
322 /* Object Data segment */ | |
323 | |
324 *q++ = 0x0f; /* sync byte */ | |
325 *q++ = 0x13; | |
326 putbe16(&q, page_id); | |
327 pseg_len = q; | |
328 q += 2; /* segment length */ | |
329 | |
330 putbe16(&q, object_id); | |
331 *q++ = (s->object_version << 4) | (0 << 2) | (0 << 1) | 1; /* version = 0, | |
332 onject_coding_method, | |
333 non_modifying_color_flag */ | |
334 { | |
335 uint8_t *ptop_field_len, *pbottom_field_len, *top_ptr, *bottom_ptr; | |
336 void (*dvb_encode_rle)(uint8_t **pq, | |
337 const uint8_t *bitmap, int linesize, | |
338 int w, int h); | |
339 ptop_field_len = q; | |
340 q += 2; | |
341 pbottom_field_len = q; | |
342 q += 2; | |
343 | |
344 if (bpp_index == 0) | |
345 dvb_encode_rle = dvb_encode_rle2; | |
346 else | |
347 dvb_encode_rle = dvb_encode_rle4; | |
348 | |
349 top_ptr = q; | |
350 dvb_encode_rle(&q, h->bitmap, h->w * 2, h->w, h->h >> 1); | |
351 bottom_ptr = q; | |
352 dvb_encode_rle(&q, h->bitmap + h->w, h->w * 2, h->w, h->h >> 1); | |
353 | |
354 putbe16(&ptop_field_len, bottom_ptr - top_ptr); | |
355 putbe16(&pbottom_field_len, q - bottom_ptr); | |
356 } | |
357 | |
358 putbe16(&pseg_len, q - pseg_len - 2); | |
359 } | |
360 | |
361 /* end of display set segment */ | |
362 | |
363 *q++ = 0x0f; /* sync_byte */ | |
364 *q++ = 0x80; /* segment_type */ | |
365 putbe16(&q, page_id); | |
366 pseg_len = q; | |
367 q += 2; /* segment length */ | |
368 | |
369 putbe16(&pseg_len, q - pseg_len - 2); | |
370 | |
371 *q++ = 0xff; /* end of PES data */ | |
372 | |
373 s->object_version = (s->object_version + 1) & 0xf; | |
374 s->hide_state = !s->hide_state; | |
375 return q - outbuf; | |
376 } | |
377 | |
378 static int dvbsub_init_decoder(AVCodecContext *avctx) | |
379 { | |
380 return 0; | |
381 } | |
382 | |
383 static int dvbsub_close_decoder(AVCodecContext *avctx) | |
384 { | |
385 return 0; | |
386 } | |
387 | |
388 static int dvbsub_encode(AVCodecContext *avctx, | |
389 unsigned char *buf, int buf_size, void *data) | |
390 { | |
391 DVBSubtitleContext *s = avctx->priv_data; | |
392 AVSubtitle *sub = data; | |
393 int ret; | |
394 | |
395 ret = encode_dvb_subtitles(s, buf, sub); | |
396 return ret; | |
397 } | |
398 | |
399 AVCodec dvbsub_encoder = { | |
400 "dvbsub", | |
401 CODEC_TYPE_SUBTITLE, | |
402 CODEC_ID_DVB_SUBTITLE, | |
403 sizeof(DVBSubtitleContext), | |
404 dvbsub_init_decoder, | |
405 dvbsub_encode, | |
406 dvbsub_close_decoder, | |
407 }; |