00001 /* 00002 * DVB subtitle encoding 00003 * Copyright (c) 2005 Fabrice Bellard 00004 * 00005 * This file is part of FFmpeg. 00006 * 00007 * FFmpeg is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * FFmpeg is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with FFmpeg; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 #include "avcodec.h" 00022 #include "bytestream.h" 00023 #include "libavutil/colorspace.h" 00024 00025 typedef struct DVBSubtitleContext { 00026 int hide_state; 00027 int object_version; 00028 } DVBSubtitleContext; 00029 00030 #define PUTBITS2(val)\ 00031 {\ 00032 bitbuf |= (val) << bitcnt;\ 00033 bitcnt -= 2;\ 00034 if (bitcnt < 0) {\ 00035 bitcnt = 6;\ 00036 *q++ = bitbuf;\ 00037 bitbuf = 0;\ 00038 }\ 00039 } 00040 00041 static void dvb_encode_rle2(uint8_t **pq, 00042 const uint8_t *bitmap, int linesize, 00043 int w, int h) 00044 { 00045 uint8_t *q; 00046 unsigned int bitbuf; 00047 int bitcnt; 00048 int x, y, len, x1, v, color; 00049 00050 q = *pq; 00051 00052 for(y = 0; y < h; y++) { 00053 *q++ = 0x10; 00054 bitbuf = 0; 00055 bitcnt = 6; 00056 00057 x = 0; 00058 while (x < w) { 00059 x1 = x; 00060 color = bitmap[x1++]; 00061 while (x1 < w && bitmap[x1] == color) 00062 x1++; 00063 len = x1 - x; 00064 if (color == 0 && len == 2) { 00065 PUTBITS2(0); 00066 PUTBITS2(0); 00067 PUTBITS2(1); 00068 } else if (len >= 3 && len <= 10) { 00069 v = len - 3; 00070 PUTBITS2(0); 00071 PUTBITS2((v >> 2) | 2); 00072 PUTBITS2(v & 3); 00073 PUTBITS2(color); 00074 } else if (len >= 12 && len <= 27) { 00075 v = len - 12; 00076 PUTBITS2(0); 00077 PUTBITS2(0); 00078 PUTBITS2(2); 00079 PUTBITS2(v >> 2); 00080 PUTBITS2(v & 3); 00081 PUTBITS2(color); 00082 } else if (len >= 29) { 00083 /* length = 29 ... 284 */ 00084 if (len > 284) 00085 len = 284; 00086 v = len - 29; 00087 PUTBITS2(0); 00088 PUTBITS2(0); 00089 PUTBITS2(3); 00090 PUTBITS2((v >> 6)); 00091 PUTBITS2((v >> 4) & 3); 00092 PUTBITS2((v >> 2) & 3); 00093 PUTBITS2(v & 3); 00094 PUTBITS2(color); 00095 } else { 00096 PUTBITS2(color); 00097 if (color == 0) { 00098 PUTBITS2(1); 00099 } 00100 len = 1; 00101 } 00102 x += len; 00103 } 00104 /* end of line */ 00105 PUTBITS2(0); 00106 PUTBITS2(0); 00107 PUTBITS2(0); 00108 if (bitcnt != 6) { 00109 *q++ = bitbuf; 00110 } 00111 *q++ = 0xf0; 00112 bitmap += linesize; 00113 } 00114 *pq = q; 00115 } 00116 00117 #define PUTBITS4(val)\ 00118 {\ 00119 bitbuf |= (val) << bitcnt;\ 00120 bitcnt -= 4;\ 00121 if (bitcnt < 0) {\ 00122 bitcnt = 4;\ 00123 *q++ = bitbuf;\ 00124 bitbuf = 0;\ 00125 }\ 00126 } 00127 00128 /* some DVB decoders only implement 4 bits/pixel */ 00129 static void dvb_encode_rle4(uint8_t **pq, 00130 const uint8_t *bitmap, int linesize, 00131 int w, int h) 00132 { 00133 uint8_t *q; 00134 unsigned int bitbuf; 00135 int bitcnt; 00136 int x, y, len, x1, v, color; 00137 00138 q = *pq; 00139 00140 for(y = 0; y < h; y++) { 00141 *q++ = 0x11; 00142 bitbuf = 0; 00143 bitcnt = 4; 00144 00145 x = 0; 00146 while (x < w) { 00147 x1 = x; 00148 color = bitmap[x1++]; 00149 while (x1 < w && bitmap[x1] == color) 00150 x1++; 00151 len = x1 - x; 00152 if (color == 0 && len == 2) { 00153 PUTBITS4(0); 00154 PUTBITS4(0xd); 00155 } else if (color == 0 && (len >= 3 && len <= 9)) { 00156 PUTBITS4(0); 00157 PUTBITS4(len - 2); 00158 } else if (len >= 4 && len <= 7) { 00159 PUTBITS4(0); 00160 PUTBITS4(8 + len - 4); 00161 PUTBITS4(color); 00162 } else if (len >= 9 && len <= 24) { 00163 PUTBITS4(0); 00164 PUTBITS4(0xe); 00165 PUTBITS4(len - 9); 00166 PUTBITS4(color); 00167 } else if (len >= 25) { 00168 if (len > 280) 00169 len = 280; 00170 v = len - 25; 00171 PUTBITS4(0); 00172 PUTBITS4(0xf); 00173 PUTBITS4(v >> 4); 00174 PUTBITS4(v & 0xf); 00175 PUTBITS4(color); 00176 } else { 00177 PUTBITS4(color); 00178 if (color == 0) { 00179 PUTBITS4(0xc); 00180 } 00181 len = 1; 00182 } 00183 x += len; 00184 } 00185 /* end of line */ 00186 PUTBITS4(0); 00187 PUTBITS4(0); 00188 if (bitcnt != 4) { 00189 *q++ = bitbuf; 00190 } 00191 *q++ = 0xf0; 00192 bitmap += linesize; 00193 } 00194 *pq = q; 00195 } 00196 00197 static void dvb_encode_rle8(uint8_t **pq, 00198 const uint8_t *bitmap, int linesize, 00199 int w, int h) 00200 { 00201 uint8_t *q; 00202 int x, y, len, x1, f, color; 00203 00204 q = *pq; 00205 00206 for (y = 0; y < h; y++) { 00207 *q++ = 0x12; 00208 00209 x = 0; 00210 f = 0; 00211 while (x < w) { 00212 x1 = x; 00213 color = bitmap[x1++]; 00214 while (x1 < w && bitmap[x1] == color) 00215 x1++; 00216 len = x1 - x; 00217 if (len == 1 && color) { 00218 // 00000001 to 11111111 1 pixel in colour x 00219 *q++ = color; 00220 } else { 00221 if (color == 0x00) { 00222 // 00000000 0LLLLLLL L pixels (1-127) in colour 0 (L > 0) 00223 len = FFMIN(len, 127); 00224 *q++ = 0x00; 00225 *q++ = len; 00226 } else if (len > 2) { 00227 // 00000000 1LLLLLLL CCCCCCCC L pixels (3-127) in colour C (L > 2) 00228 len = FFMIN(len, 127); 00229 *q++ = 0x00; 00230 *q++ = 0x80+len; 00231 *q++ = color; 00232 } 00233 else if (len == 2) { 00234 *q++ = color; 00235 *q++ = color; 00236 } else { 00237 *q++ = color; 00238 len = 1; 00239 } 00240 } 00241 x += len; 00242 } 00243 /* end of line */ 00244 // 00000000 00000000 end of 8-bit/pixel_code_string 00245 *q++ = 0x00; 00246 *q++ = 0x00; 00247 bitmap += linesize; 00248 } 00249 *pq = q; 00250 } 00251 00252 static int encode_dvb_subtitles(DVBSubtitleContext *s, 00253 uint8_t *outbuf, AVSubtitle *h) 00254 { 00255 uint8_t *q, *pseg_len; 00256 int page_id, region_id, clut_id, object_id, i, bpp_index, page_state; 00257 00258 00259 q = outbuf; 00260 00261 page_id = 1; 00262 00263 if (h->num_rects == 0 || h->rects == NULL) 00264 return -1; 00265 00266 *q++ = 0x00; /* subtitle_stream_id */ 00267 00268 /* page composition segment */ 00269 00270 *q++ = 0x0f; /* sync_byte */ 00271 *q++ = 0x10; /* segment_type */ 00272 bytestream_put_be16(&q, page_id); 00273 pseg_len = q; 00274 q += 2; /* segment length */ 00275 *q++ = 30; /* page_timeout (seconds) */ 00276 if (s->hide_state) 00277 page_state = 0; /* normal case */ 00278 else 00279 page_state = 2; /* mode change */ 00280 /* page_version = 0 + page_state */ 00281 *q++ = (s->object_version << 4) | (page_state << 2) | 3; 00282 00283 for (region_id = 0; region_id < h->num_rects; region_id++) { 00284 *q++ = region_id; 00285 *q++ = 0xff; /* reserved */ 00286 bytestream_put_be16(&q, h->rects[region_id]->x); /* left pos */ 00287 bytestream_put_be16(&q, h->rects[region_id]->y); /* top pos */ 00288 } 00289 00290 bytestream_put_be16(&pseg_len, q - pseg_len - 2); 00291 00292 if (!s->hide_state) { 00293 for (clut_id = 0; clut_id < h->num_rects; clut_id++) { 00294 00295 /* CLUT segment */ 00296 00297 if (h->rects[clut_id]->nb_colors <= 4) { 00298 /* 2 bpp, some decoders do not support it correctly */ 00299 bpp_index = 0; 00300 } else if (h->rects[clut_id]->nb_colors <= 16) { 00301 /* 4 bpp, standard encoding */ 00302 bpp_index = 1; 00303 } else if (h->rects[clut_id]->nb_colors <= 256) { 00304 /* 8 bpp, standard encoding */ 00305 bpp_index = 2; 00306 } else { 00307 return -1; 00308 } 00309 00310 00311 /* CLUT segment */ 00312 *q++ = 0x0f; /* sync byte */ 00313 *q++ = 0x12; /* CLUT definition segment */ 00314 bytestream_put_be16(&q, page_id); 00315 pseg_len = q; 00316 q += 2; /* segment length */ 00317 *q++ = clut_id; 00318 *q++ = (0 << 4) | 0xf; /* version = 0 */ 00319 00320 for(i = 0; i < h->rects[clut_id]->nb_colors; i++) { 00321 *q++ = i; /* clut_entry_id */ 00322 *q++ = (1 << (7 - bpp_index)) | (0xf << 1) | 1; /* 2 bits/pixel full range */ 00323 { 00324 int a, r, g, b; 00325 uint32_t x= ((uint32_t*)h->rects[clut_id]->pict.data[1])[i]; 00326 a = (x >> 24) & 0xff; 00327 r = (x >> 16) & 0xff; 00328 g = (x >> 8) & 0xff; 00329 b = (x >> 0) & 0xff; 00330 00331 *q++ = RGB_TO_Y_CCIR(r, g, b); 00332 *q++ = RGB_TO_V_CCIR(r, g, b, 0); 00333 *q++ = RGB_TO_U_CCIR(r, g, b, 0); 00334 *q++ = 255 - a; 00335 } 00336 } 00337 00338 bytestream_put_be16(&pseg_len, q - pseg_len - 2); 00339 } 00340 } 00341 00342 for (region_id = 0; region_id < h->num_rects; region_id++) { 00343 00344 /* region composition segment */ 00345 00346 if (h->rects[region_id]->nb_colors <= 4) { 00347 /* 2 bpp, some decoders do not support it correctly */ 00348 bpp_index = 0; 00349 } else if (h->rects[region_id]->nb_colors <= 16) { 00350 /* 4 bpp, standard encoding */ 00351 bpp_index = 1; 00352 } else { 00353 return -1; 00354 } 00355 00356 *q++ = 0x0f; /* sync_byte */ 00357 *q++ = 0x11; /* segment_type */ 00358 bytestream_put_be16(&q, page_id); 00359 pseg_len = q; 00360 q += 2; /* segment length */ 00361 *q++ = region_id; 00362 *q++ = (s->object_version << 4) | (0 << 3) | 0x07; /* version , no fill */ 00363 bytestream_put_be16(&q, h->rects[region_id]->w); /* region width */ 00364 bytestream_put_be16(&q, h->rects[region_id]->h); /* region height */ 00365 *q++ = ((1 + bpp_index) << 5) | ((1 + bpp_index) << 2) | 0x03; 00366 *q++ = region_id; /* clut_id == region_id */ 00367 *q++ = 0; /* 8 bit fill colors */ 00368 *q++ = 0x03; /* 4 bit and 2 bit fill colors */ 00369 00370 if (!s->hide_state) { 00371 bytestream_put_be16(&q, region_id); /* object_id == region_id */ 00372 *q++ = (0 << 6) | (0 << 4); 00373 *q++ = 0; 00374 *q++ = 0xf0; 00375 *q++ = 0; 00376 } 00377 00378 bytestream_put_be16(&pseg_len, q - pseg_len - 2); 00379 } 00380 00381 if (!s->hide_state) { 00382 00383 for (object_id = 0; object_id < h->num_rects; object_id++) { 00384 void (*dvb_encode_rle)(uint8_t **pq, 00385 const uint8_t *bitmap, int linesize, 00386 int w, int h); 00387 00388 /* bpp_index maths */ 00389 if (h->rects[object_id]->nb_colors <= 4) { 00390 /* 2 bpp, some decoders do not support it correctly */ 00391 dvb_encode_rle = dvb_encode_rle2; 00392 } else if (h->rects[object_id]->nb_colors <= 16) { 00393 /* 4 bpp, standard encoding */ 00394 dvb_encode_rle = dvb_encode_rle4; 00395 } else if (h->rects[object_id]->nb_colors <= 256) { 00396 /* 8 bpp, standard encoding */ 00397 dvb_encode_rle = dvb_encode_rle8; 00398 } else { 00399 return -1; 00400 } 00401 00402 /* Object Data segment */ 00403 *q++ = 0x0f; /* sync byte */ 00404 *q++ = 0x13; 00405 bytestream_put_be16(&q, page_id); 00406 pseg_len = q; 00407 q += 2; /* segment length */ 00408 00409 bytestream_put_be16(&q, object_id); 00410 *q++ = (s->object_version << 4) | (0 << 2) | (0 << 1) | 1; /* version = 0, 00411 onject_coding_method, 00412 non_modifying_color_flag */ 00413 { 00414 uint8_t *ptop_field_len, *pbottom_field_len, *top_ptr, *bottom_ptr; 00415 00416 ptop_field_len = q; 00417 q += 2; 00418 pbottom_field_len = q; 00419 q += 2; 00420 00421 top_ptr = q; 00422 dvb_encode_rle(&q, h->rects[object_id]->pict.data[0], h->rects[object_id]->w * 2, 00423 h->rects[object_id]->w, h->rects[object_id]->h >> 1); 00424 bottom_ptr = q; 00425 dvb_encode_rle(&q, h->rects[object_id]->pict.data[0] + h->rects[object_id]->w, 00426 h->rects[object_id]->w * 2, h->rects[object_id]->w, 00427 h->rects[object_id]->h >> 1); 00428 00429 bytestream_put_be16(&ptop_field_len, bottom_ptr - top_ptr); 00430 bytestream_put_be16(&pbottom_field_len, q - bottom_ptr); 00431 } 00432 00433 bytestream_put_be16(&pseg_len, q - pseg_len - 2); 00434 } 00435 } 00436 00437 /* end of display set segment */ 00438 00439 *q++ = 0x0f; /* sync_byte */ 00440 *q++ = 0x80; /* segment_type */ 00441 bytestream_put_be16(&q, page_id); 00442 pseg_len = q; 00443 q += 2; /* segment length */ 00444 00445 bytestream_put_be16(&pseg_len, q - pseg_len - 2); 00446 00447 *q++ = 0xff; /* end of PES data */ 00448 00449 s->object_version = (s->object_version + 1) & 0xf; 00450 s->hide_state = !s->hide_state; 00451 return q - outbuf; 00452 } 00453 00454 static int dvbsub_encode(AVCodecContext *avctx, 00455 unsigned char *buf, int buf_size, void *data) 00456 { 00457 DVBSubtitleContext *s = avctx->priv_data; 00458 AVSubtitle *sub = data; 00459 int ret; 00460 00461 ret = encode_dvb_subtitles(s, buf, sub); 00462 return ret; 00463 } 00464 00465 AVCodec ff_dvbsub_encoder = { 00466 .name = "dvbsub", 00467 .type = AVMEDIA_TYPE_SUBTITLE, 00468 .id = CODEC_ID_DVB_SUBTITLE, 00469 .priv_data_size = sizeof(DVBSubtitleContext), 00470 .encode = dvbsub_encode, 00471 .long_name = NULL_IF_CONFIG_SMALL("DVB subtitles"), 00472 };