2 * DVB subtitle encoding
3 * Copyright (c) 2005 Fabrice Bellard
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
22 #include "bytestream.h"
23 #include "libavutil/colorspace.h"
25 typedef struct DVBSubtitleContext
{
29 #define PUTBITS2(val)\
31 bitbuf |= (val) << bitcnt;\
40 static void dvb_encode_rle2(uint8_t **pq
,
41 const uint8_t *bitmap
, int linesize
,
47 int x
, y
, len
, x1
, v
, color
;
51 for(y
= 0; y
< h
; y
++) {
60 while (x1
< w
&& bitmap
[x1
] == color
)
63 if (color
== 0 && len
== 2) {
67 } else if (len
>= 3 && len
<= 10) {
70 PUTBITS2((v
>> 2) | 2);
73 } else if (len
>= 12 && len
<= 27) {
81 } else if (len
>= 29) {
82 /* length = 29 ... 284 */
90 PUTBITS2((v
>> 4) & 3);
91 PUTBITS2((v
>> 2) & 3);
116 #define PUTBITS4(val)\
118 bitbuf |= (val) << bitcnt;\
127 /* some DVB decoders only implement 4 bits/pixel */
128 static void dvb_encode_rle4(uint8_t **pq
,
129 const uint8_t *bitmap
, int linesize
,
135 int x
, y
, len
, x1
, v
, color
;
139 for(y
= 0; y
< h
; y
++) {
147 color
= bitmap
[x1
++];
148 while (x1
< w
&& bitmap
[x1
] == color
)
151 if (color
== 0 && len
== 2) {
154 } else if (color
== 0 && (len
>= 3 && len
<= 9)) {
157 } else if (len
>= 4 && len
<= 7) {
159 PUTBITS4(8 + len
- 4);
161 } else if (len
>= 9 && len
<= 24) {
166 } else if (len
>= 25) {
196 static void dvb_encode_rle8(uint8_t **pq
,
197 const uint8_t *bitmap
, int linesize
,
201 int x
, y
, len
, x1
, color
;
205 for (y
= 0; y
< h
; y
++) {
211 color
= bitmap
[x1
++];
212 while (x1
< w
&& bitmap
[x1
] == color
)
215 if (len
== 1 && color
) {
216 // 00000001 to 11111111 1 pixel in colour x
220 // 00000000 0LLLLLLL L pixels (1-127) in colour 0 (L > 0)
221 len
= FFMIN(len
, 127);
224 } else if (len
> 2) {
225 // 00000000 1LLLLLLL CCCCCCCC L pixels (3-127) in colour C (L > 2)
226 len
= FFMIN(len
, 127);
242 // 00000000 00000000 end of 8-bit/pixel_code_string
250 static int encode_dvb_subtitles(DVBSubtitleContext
*s
,
251 uint8_t *outbuf
, const AVSubtitle
*h
)
253 uint8_t *q
, *pseg_len
;
254 int page_id
, region_id
, clut_id
, object_id
, i
, bpp_index
, page_state
;
261 if (h
->num_rects
&& !h
->rects
)
264 /* page composition segment */
266 *q
++ = 0x0f; /* sync_byte */
267 *q
++ = 0x10; /* segment_type */
268 bytestream_put_be16(&q
, page_id
);
270 q
+= 2; /* segment length */
271 *q
++ = 30; /* page_timeout (seconds) */
272 page_state
= 2; /* mode change */
273 /* page_version = 0 + page_state */
274 *q
++ = (s
->object_version
<< 4) | (page_state
<< 2) | 3;
276 for (region_id
= 0; region_id
< h
->num_rects
; region_id
++) {
278 *q
++ = 0xff; /* reserved */
279 bytestream_put_be16(&q
, h
->rects
[region_id
]->x
); /* left pos */
280 bytestream_put_be16(&q
, h
->rects
[region_id
]->y
); /* top pos */
283 bytestream_put_be16(&pseg_len
, q
- pseg_len
- 2);
286 for (clut_id
= 0; clut_id
< h
->num_rects
; clut_id
++) {
290 if (h
->rects
[clut_id
]->nb_colors
<= 4) {
291 /* 2 bpp, some decoders do not support it correctly */
293 } else if (h
->rects
[clut_id
]->nb_colors
<= 16) {
294 /* 4 bpp, standard encoding */
296 } else if (h
->rects
[clut_id
]->nb_colors
<= 256) {
297 /* 8 bpp, standard encoding */
305 *q
++ = 0x0f; /* sync byte */
306 *q
++ = 0x12; /* CLUT definition segment */
307 bytestream_put_be16(&q
, page_id
);
309 q
+= 2; /* segment length */
311 *q
++ = (0 << 4) | 0xf; /* version = 0 */
313 for(i
= 0; i
< h
->rects
[clut_id
]->nb_colors
; i
++) {
314 *q
++ = i
; /* clut_entry_id */
315 *q
++ = (1 << (7 - bpp_index
)) | (0xf << 1) | 1; /* 2 bits/pixel full range */
318 uint32_t x
= ((uint32_t*)h
->rects
[clut_id
]->pict
.data
[1])[i
];
319 a
= (x
>> 24) & 0xff;
320 r
= (x
>> 16) & 0xff;
324 *q
++ = RGB_TO_Y_CCIR(r
, g
, b
);
325 *q
++ = RGB_TO_V_CCIR(r
, g
, b
, 0);
326 *q
++ = RGB_TO_U_CCIR(r
, g
, b
, 0);
331 bytestream_put_be16(&pseg_len
, q
- pseg_len
- 2);
335 for (region_id
= 0; region_id
< h
->num_rects
; region_id
++) {
337 /* region composition segment */
339 if (h
->rects
[region_id
]->nb_colors
<= 4) {
340 /* 2 bpp, some decoders do not support it correctly */
342 } else if (h
->rects
[region_id
]->nb_colors
<= 16) {
343 /* 4 bpp, standard encoding */
349 *q
++ = 0x0f; /* sync_byte */
350 *q
++ = 0x11; /* segment_type */
351 bytestream_put_be16(&q
, page_id
);
353 q
+= 2; /* segment length */
355 *q
++ = (s
->object_version
<< 4) | (0 << 3) | 0x07; /* version , no fill */
356 bytestream_put_be16(&q
, h
->rects
[region_id
]->w
); /* region width */
357 bytestream_put_be16(&q
, h
->rects
[region_id
]->h
); /* region height */
358 *q
++ = ((1 + bpp_index
) << 5) | ((1 + bpp_index
) << 2) | 0x03;
359 *q
++ = region_id
; /* clut_id == region_id */
360 *q
++ = 0; /* 8 bit fill colors */
361 *q
++ = 0x03; /* 4 bit and 2 bit fill colors */
363 bytestream_put_be16(&q
, region_id
); /* object_id == region_id */
364 *q
++ = (0 << 6) | (0 << 4);
369 bytestream_put_be16(&pseg_len
, q
- pseg_len
- 2);
374 for (object_id
= 0; object_id
< h
->num_rects
; object_id
++) {
375 void (*dvb_encode_rle
)(uint8_t **pq
,
376 const uint8_t *bitmap
, int linesize
,
379 /* bpp_index maths */
380 if (h
->rects
[object_id
]->nb_colors
<= 4) {
381 /* 2 bpp, some decoders do not support it correctly */
382 dvb_encode_rle
= dvb_encode_rle2
;
383 } else if (h
->rects
[object_id
]->nb_colors
<= 16) {
384 /* 4 bpp, standard encoding */
385 dvb_encode_rle
= dvb_encode_rle4
;
386 } else if (h
->rects
[object_id
]->nb_colors
<= 256) {
387 /* 8 bpp, standard encoding */
388 dvb_encode_rle
= dvb_encode_rle8
;
393 /* Object Data segment */
394 *q
++ = 0x0f; /* sync byte */
396 bytestream_put_be16(&q
, page_id
);
398 q
+= 2; /* segment length */
400 bytestream_put_be16(&q
, object_id
);
401 *q
++ = (s
->object_version
<< 4) | (0 << 2) | (0 << 1) | 1; /* version = 0,
402 onject_coding_method,
403 non_modifying_color_flag */
405 uint8_t *ptop_field_len
, *pbottom_field_len
, *top_ptr
, *bottom_ptr
;
409 pbottom_field_len
= q
;
413 dvb_encode_rle(&q
, h
->rects
[object_id
]->pict
.data
[0], h
->rects
[object_id
]->w
* 2,
414 h
->rects
[object_id
]->w
, h
->rects
[object_id
]->h
>> 1);
416 dvb_encode_rle(&q
, h
->rects
[object_id
]->pict
.data
[0] + h
->rects
[object_id
]->w
,
417 h
->rects
[object_id
]->w
* 2, h
->rects
[object_id
]->w
,
418 h
->rects
[object_id
]->h
>> 1);
420 bytestream_put_be16(&ptop_field_len
, bottom_ptr
- top_ptr
);
421 bytestream_put_be16(&pbottom_field_len
, q
- bottom_ptr
);
424 bytestream_put_be16(&pseg_len
, q
- pseg_len
- 2);
428 /* end of display set segment */
430 *q
++ = 0x0f; /* sync_byte */
431 *q
++ = 0x80; /* segment_type */
432 bytestream_put_be16(&q
, page_id
);
434 q
+= 2; /* segment length */
436 bytestream_put_be16(&pseg_len
, q
- pseg_len
- 2);
438 s
->object_version
= (s
->object_version
+ 1) & 0xf;
442 static int dvbsub_encode(AVCodecContext
*avctx
,
443 unsigned char *buf
, int buf_size
,
444 const AVSubtitle
*sub
)
446 DVBSubtitleContext
*s
= avctx
->priv_data
;
449 ret
= encode_dvb_subtitles(s
, buf
, sub
);
453 AVCodec ff_dvbsub_encoder
= {
455 .long_name
= NULL_IF_CONFIG_SMALL("DVB subtitles"),
456 .type
= AVMEDIA_TYPE_SUBTITLE
,
457 .id
= AV_CODEC_ID_DVB_SUBTITLE
,
458 .priv_data_size
= sizeof(DVBSubtitleContext
),
459 .encode_sub
= dvbsub_encode
,