1/* 2 * DVB subtitle encoding 3 * Copyright (c) 2005 Fabrice Bellard 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#include "avcodec.h" 22#include "bytestream.h" 23#include "libavutil/colorspace.h" 24 25typedef struct DVBSubtitleContext { 26 int object_version; 27} DVBSubtitleContext; 28 29#define PUTBITS2(val)\ 30{\ 31 bitbuf |= (val) << bitcnt;\ 32 bitcnt -= 2;\ 33 if (bitcnt < 0) {\ 34 bitcnt = 6;\ 35 *q++ = bitbuf;\ 36 bitbuf = 0;\ 37 }\ 38} 39 40static void dvb_encode_rle2(uint8_t **pq, 41 const uint8_t *bitmap, int linesize, 42 int w, int h) 43{ 44 uint8_t *q; 45 unsigned int bitbuf; 46 int bitcnt; 47 int x, y, len, x1, v, color; 48 49 q = *pq; 50 51 for(y = 0; y < h; y++) { 52 *q++ = 0x10; 53 bitbuf = 0; 54 bitcnt = 6; 55 56 x = 0; 57 while (x < w) { 58 x1 = x; 59 color = bitmap[x1++]; 60 while (x1 < w && bitmap[x1] == color) 61 x1++; 62 len = x1 - x; 63 if (color == 0 && len == 2) { 64 PUTBITS2(0); 65 PUTBITS2(0); 66 PUTBITS2(1); 67 } else if (len >= 3 && len <= 10) { 68 v = len - 3; 69 PUTBITS2(0); 70 PUTBITS2((v >> 2) | 2); 71 PUTBITS2(v & 3); 72 PUTBITS2(color); 73 } else if (len >= 12 && len <= 27) { 74 v = len - 12; 75 PUTBITS2(0); 76 PUTBITS2(0); 77 PUTBITS2(2); 78 PUTBITS2(v >> 2); 79 PUTBITS2(v & 3); 80 PUTBITS2(color); 81 } else if (len >= 29) { 82 /* length = 29 ... 284 */ 83 if (len > 284) 84 len = 284; 85 v = len - 29; 86 PUTBITS2(0); 87 PUTBITS2(0); 88 PUTBITS2(3); 89 PUTBITS2((v >> 6)); 90 PUTBITS2((v >> 4) & 3); 91 PUTBITS2((v >> 2) & 3); 92 PUTBITS2(v & 3); 93 PUTBITS2(color); 94 } else { 95 PUTBITS2(color); 96 if (color == 0) { 97 PUTBITS2(1); 98 } 99 len = 1; 100 } 101 x += len; 102 } 103 /* end of line */ 104 PUTBITS2(0); 105 PUTBITS2(0); 106 PUTBITS2(0); 107 if (bitcnt != 6) { 108 *q++ = bitbuf; 109 } 110 *q++ = 0xf0; 111 bitmap += linesize; 112 } 113 *pq = q; 114} 115 116#define PUTBITS4(val)\ 117{\ 118 bitbuf |= (val) << bitcnt;\ 119 bitcnt -= 4;\ 120 if (bitcnt < 0) {\ 121 bitcnt = 4;\ 122 *q++ = bitbuf;\ 123 bitbuf = 0;\ 124 }\ 125} 126 127/* some DVB decoders only implement 4 bits/pixel */ 128static void dvb_encode_rle4(uint8_t **pq, 129 const uint8_t *bitmap, int linesize, 130 int w, int h) 131{ 132 uint8_t *q; 133 unsigned int bitbuf; 134 int bitcnt; 135 int x, y, len, x1, v, color; 136 137 q = *pq; 138 139 for(y = 0; y < h; y++) { 140 *q++ = 0x11; 141 bitbuf = 0; 142 bitcnt = 4; 143 144 x = 0; 145 while (x < w) { 146 x1 = x; 147 color = bitmap[x1++]; 148 while (x1 < w && bitmap[x1] == color) 149 x1++; 150 len = x1 - x; 151 if (color == 0 && len == 2) { 152 PUTBITS4(0); 153 PUTBITS4(0xd); 154 } else if (color == 0 && (len >= 3 && len <= 9)) { 155 PUTBITS4(0); 156 PUTBITS4(len - 2); 157 } else if (len >= 4 && len <= 7) { 158 PUTBITS4(0); 159 PUTBITS4(8 + len - 4); 160 PUTBITS4(color); 161 } else if (len >= 9 && len <= 24) { 162 PUTBITS4(0); 163 PUTBITS4(0xe); 164 PUTBITS4(len - 9); 165 PUTBITS4(color); 166 } else if (len >= 25) { 167 if (len > 280) 168 len = 280; 169 v = len - 25; 170 PUTBITS4(0); 171 PUTBITS4(0xf); 172 PUTBITS4(v >> 4); 173 PUTBITS4(v & 0xf); 174 PUTBITS4(color); 175 } else { 176 PUTBITS4(color); 177 if (color == 0) { 178 PUTBITS4(0xc); 179 } 180 len = 1; 181 } 182 x += len; 183 } 184 /* end of line */ 185 PUTBITS4(0); 186 PUTBITS4(0); 187 if (bitcnt != 4) { 188 *q++ = bitbuf; 189 } 190 *q++ = 0xf0; 191 bitmap += linesize; 192 } 193 *pq = q; 194} 195 196static void dvb_encode_rle8(uint8_t **pq, 197 const uint8_t *bitmap, int linesize, 198 int w, int h) 199{ 200 uint8_t *q; 201 int x, y, len, x1, color; 202 203 q = *pq; 204 205 for (y = 0; y < h; y++) { 206 *q++ = 0x12; 207 208 x = 0; 209 while (x < w) { 210 x1 = x; 211 color = bitmap[x1++]; 212 while (x1 < w && bitmap[x1] == color) 213 x1++; 214 len = x1 - x; 215 if (len == 1 && color) { 216 // 00000001 to 11111111 1 pixel in colour x 217 *q++ = color; 218 } else { 219 if (color == 0x00) { 220 // 00000000 0LLLLLLL L pixels (1-127) in colour 0 (L > 0) 221 len = FFMIN(len, 127); 222 *q++ = 0x00; 223 *q++ = len; 224 } else if (len > 2) { 225 // 00000000 1LLLLLLL CCCCCCCC L pixels (3-127) in colour C (L > 2) 226 len = FFMIN(len, 127); 227 *q++ = 0x00; 228 *q++ = 0x80+len; 229 *q++ = color; 230 } 231 else if (len == 2) { 232 *q++ = color; 233 *q++ = color; 234 } else { 235 *q++ = color; 236 len = 1; 237 } 238 } 239 x += len; 240 } 241 /* end of line */ 242 // 00000000 00000000 end of 8-bit/pixel_code_string 243 *q++ = 0x00; 244 *q++ = 0x00; 245 bitmap += linesize; 246 } 247 *pq = q; 248} 249 250static int encode_dvb_subtitles(DVBSubtitleContext *s, 251 uint8_t *outbuf, const AVSubtitle *h) 252{ 253 uint8_t *q, *pseg_len; 254 int page_id, region_id, clut_id, object_id, i, bpp_index, page_state; 255 256 257 q = outbuf; 258 259 page_id = 1; 260 261 if (h->num_rects && h->rects == NULL) 262 return -1; 263 264 /* page composition segment */ 265 266 *q++ = 0x0f; /* sync_byte */ 267 *q++ = 0x10; /* segment_type */ 268 bytestream_put_be16(&q, page_id); 269 pseg_len = q; 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; 275 276 for (region_id = 0; region_id < h->num_rects; region_id++) { 277 *q++ = 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 */ 281 } 282 283 bytestream_put_be16(&pseg_len, q - pseg_len - 2); 284 285 if (h->num_rects) { 286 for (clut_id = 0; clut_id < h->num_rects; clut_id++) { 287 288 /* CLUT segment */ 289 290 if (h->rects[clut_id]->nb_colors <= 4) { 291 /* 2 bpp, some decoders do not support it correctly */ 292 bpp_index = 0; 293 } else if (h->rects[clut_id]->nb_colors <= 16) { 294 /* 4 bpp, standard encoding */ 295 bpp_index = 1; 296 } else if (h->rects[clut_id]->nb_colors <= 256) { 297 /* 8 bpp, standard encoding */ 298 bpp_index = 2; 299 } else { 300 return -1; 301 } 302 303 304 /* CLUT segment */ 305 *q++ = 0x0f; /* sync byte */ 306 *q++ = 0x12; /* CLUT definition segment */ 307 bytestream_put_be16(&q, page_id); 308 pseg_len = q; 309 q += 2; /* segment length */ 310 *q++ = clut_id; 311 *q++ = (0 << 4) | 0xf; /* version = 0 */ 312 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 */ 316 { 317 int a, r, g, b; 318 uint32_t x= ((uint32_t*)h->rects[clut_id]->pict.data[1])[i]; 319 a = (x >> 24) & 0xff; 320 r = (x >> 16) & 0xff; 321 g = (x >> 8) & 0xff; 322 b = (x >> 0) & 0xff; 323 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); 327 *q++ = 255 - a; 328 } 329 } 330 331 bytestream_put_be16(&pseg_len, q - pseg_len - 2); 332 } 333 } 334 335 for (region_id = 0; region_id < h->num_rects; region_id++) { 336 337 /* region composition segment */ 338 339 if (h->rects[region_id]->nb_colors <= 4) { 340 /* 2 bpp, some decoders do not support it correctly */ 341 bpp_index = 0; 342 } else if (h->rects[region_id]->nb_colors <= 16) { 343 /* 4 bpp, standard encoding */ 344 bpp_index = 1; 345 } else { 346 return -1; 347 } 348 349 *q++ = 0x0f; /* sync_byte */ 350 *q++ = 0x11; /* segment_type */ 351 bytestream_put_be16(&q, page_id); 352 pseg_len = q; 353 q += 2; /* segment length */ 354 *q++ = region_id; 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 */ 362 363 bytestream_put_be16(&q, region_id); /* object_id == region_id */ 364 *q++ = (0 << 6) | (0 << 4); 365 *q++ = 0; 366 *q++ = 0xf0; 367 *q++ = 0; 368 369 bytestream_put_be16(&pseg_len, q - pseg_len - 2); 370 } 371 372 if (h->num_rects) { 373 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, 377 int w, int h); 378 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; 389 } else { 390 return -1; 391 } 392 393 /* Object Data segment */ 394 *q++ = 0x0f; /* sync byte */ 395 *q++ = 0x13; 396 bytestream_put_be16(&q, page_id); 397 pseg_len = q; 398 q += 2; /* segment length */ 399 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 */ 404 { 405 uint8_t *ptop_field_len, *pbottom_field_len, *top_ptr, *bottom_ptr; 406 407 ptop_field_len = q; 408 q += 2; 409 pbottom_field_len = q; 410 q += 2; 411 412 top_ptr = 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); 415 bottom_ptr = q; 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); 419 420 bytestream_put_be16(&ptop_field_len, bottom_ptr - top_ptr); 421 bytestream_put_be16(&pbottom_field_len, q - bottom_ptr); 422 } 423 424 bytestream_put_be16(&pseg_len, q - pseg_len - 2); 425 } 426 } 427 428 /* end of display set segment */ 429 430 *q++ = 0x0f; /* sync_byte */ 431 *q++ = 0x80; /* segment_type */ 432 bytestream_put_be16(&q, page_id); 433 pseg_len = q; 434 q += 2; /* segment length */ 435 436 bytestream_put_be16(&pseg_len, q - pseg_len - 2); 437 438 s->object_version = (s->object_version + 1) & 0xf; 439 return q - outbuf; 440} 441 442static int dvbsub_encode(AVCodecContext *avctx, 443 unsigned char *buf, int buf_size, 444 const AVSubtitle *sub) 445{ 446 DVBSubtitleContext *s = avctx->priv_data; 447 int ret; 448 449 ret = encode_dvb_subtitles(s, buf, sub); 450 return ret; 451} 452 453AVCodec ff_dvbsub_encoder = { 454 .name = "dvbsub", 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, 460}; 461