Libav 0.7.1
|
00001 /* 00002 * DVB subtitle encoding for ffmpeg 00003 * Copyright (c) 2005 Fabrice Bellard 00004 * 00005 * This file is part of Libav. 00006 * 00007 * Libav 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 * Libav 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 Libav; 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 int encode_dvb_subtitles(DVBSubtitleContext *s, 00198 uint8_t *outbuf, AVSubtitle *h) 00199 { 00200 uint8_t *q, *pseg_len; 00201 int page_id, region_id, clut_id, object_id, i, bpp_index, page_state; 00202 00203 00204 q = outbuf; 00205 00206 page_id = 1; 00207 00208 if (h->num_rects == 0 || h->rects == NULL) 00209 return -1; 00210 00211 *q++ = 0x00; /* subtitle_stream_id */ 00212 00213 /* page composition segment */ 00214 00215 *q++ = 0x0f; /* sync_byte */ 00216 *q++ = 0x10; /* segment_type */ 00217 bytestream_put_be16(&q, page_id); 00218 pseg_len = q; 00219 q += 2; /* segment length */ 00220 *q++ = 30; /* page_timeout (seconds) */ 00221 if (s->hide_state) 00222 page_state = 0; /* normal case */ 00223 else 00224 page_state = 2; /* mode change */ 00225 /* page_version = 0 + page_state */ 00226 *q++ = (s->object_version << 4) | (page_state << 2) | 3; 00227 00228 for (region_id = 0; region_id < h->num_rects; region_id++) { 00229 *q++ = region_id; 00230 *q++ = 0xff; /* reserved */ 00231 bytestream_put_be16(&q, h->rects[region_id]->x); /* left pos */ 00232 bytestream_put_be16(&q, h->rects[region_id]->y); /* top pos */ 00233 } 00234 00235 bytestream_put_be16(&pseg_len, q - pseg_len - 2); 00236 00237 if (!s->hide_state) { 00238 for (clut_id = 0; clut_id < h->num_rects; clut_id++) { 00239 00240 /* CLUT segment */ 00241 00242 if (h->rects[clut_id]->nb_colors <= 4) { 00243 /* 2 bpp, some decoders do not support it correctly */ 00244 bpp_index = 0; 00245 } else if (h->rects[clut_id]->nb_colors <= 16) { 00246 /* 4 bpp, standard encoding */ 00247 bpp_index = 1; 00248 } else { 00249 return -1; 00250 } 00251 00252 *q++ = 0x0f; /* sync byte */ 00253 *q++ = 0x12; /* CLUT definition segment */ 00254 bytestream_put_be16(&q, page_id); 00255 pseg_len = q; 00256 q += 2; /* segment length */ 00257 *q++ = clut_id; 00258 *q++ = (0 << 4) | 0xf; /* version = 0 */ 00259 00260 for(i = 0; i < h->rects[clut_id]->nb_colors; i++) { 00261 *q++ = i; /* clut_entry_id */ 00262 *q++ = (1 << (7 - bpp_index)) | (0xf << 1) | 1; /* 2 bits/pixel full range */ 00263 { 00264 int a, r, g, b; 00265 uint32_t x= ((uint32_t*)h->rects[clut_id]->pict.data[1])[i]; 00266 a = (x >> 24) & 0xff; 00267 r = (x >> 16) & 0xff; 00268 g = (x >> 8) & 0xff; 00269 b = (x >> 0) & 0xff; 00270 00271 *q++ = RGB_TO_Y_CCIR(r, g, b); 00272 *q++ = RGB_TO_V_CCIR(r, g, b, 0); 00273 *q++ = RGB_TO_U_CCIR(r, g, b, 0); 00274 *q++ = 255 - a; 00275 } 00276 } 00277 00278 bytestream_put_be16(&pseg_len, q - pseg_len - 2); 00279 } 00280 } 00281 00282 for (region_id = 0; region_id < h->num_rects; region_id++) { 00283 00284 /* region composition segment */ 00285 00286 if (h->rects[region_id]->nb_colors <= 4) { 00287 /* 2 bpp, some decoders do not support it correctly */ 00288 bpp_index = 0; 00289 } else if (h->rects[region_id]->nb_colors <= 16) { 00290 /* 4 bpp, standard encoding */ 00291 bpp_index = 1; 00292 } else { 00293 return -1; 00294 } 00295 00296 *q++ = 0x0f; /* sync_byte */ 00297 *q++ = 0x11; /* segment_type */ 00298 bytestream_put_be16(&q, page_id); 00299 pseg_len = q; 00300 q += 2; /* segment length */ 00301 *q++ = region_id; 00302 *q++ = (s->object_version << 4) | (0 << 3) | 0x07; /* version , no fill */ 00303 bytestream_put_be16(&q, h->rects[region_id]->w); /* region width */ 00304 bytestream_put_be16(&q, h->rects[region_id]->h); /* region height */ 00305 *q++ = ((1 + bpp_index) << 5) | ((1 + bpp_index) << 2) | 0x03; 00306 *q++ = region_id; /* clut_id == region_id */ 00307 *q++ = 0; /* 8 bit fill colors */ 00308 *q++ = 0x03; /* 4 bit and 2 bit fill colors */ 00309 00310 if (!s->hide_state) { 00311 bytestream_put_be16(&q, region_id); /* object_id == region_id */ 00312 *q++ = (0 << 6) | (0 << 4); 00313 *q++ = 0; 00314 *q++ = 0xf0; 00315 *q++ = 0; 00316 } 00317 00318 bytestream_put_be16(&pseg_len, q - pseg_len - 2); 00319 } 00320 00321 if (!s->hide_state) { 00322 00323 for (object_id = 0; object_id < h->num_rects; object_id++) { 00324 /* Object Data segment */ 00325 00326 if (h->rects[object_id]->nb_colors <= 4) { 00327 /* 2 bpp, some decoders do not support it correctly */ 00328 bpp_index = 0; 00329 } else if (h->rects[object_id]->nb_colors <= 16) { 00330 /* 4 bpp, standard encoding */ 00331 bpp_index = 1; 00332 } else { 00333 return -1; 00334 } 00335 00336 *q++ = 0x0f; /* sync byte */ 00337 *q++ = 0x13; 00338 bytestream_put_be16(&q, page_id); 00339 pseg_len = q; 00340 q += 2; /* segment length */ 00341 00342 bytestream_put_be16(&q, object_id); 00343 *q++ = (s->object_version << 4) | (0 << 2) | (0 << 1) | 1; /* version = 0, 00344 onject_coding_method, 00345 non_modifying_color_flag */ 00346 { 00347 uint8_t *ptop_field_len, *pbottom_field_len, *top_ptr, *bottom_ptr; 00348 void (*dvb_encode_rle)(uint8_t **pq, 00349 const uint8_t *bitmap, int linesize, 00350 int w, int h); 00351 ptop_field_len = q; 00352 q += 2; 00353 pbottom_field_len = q; 00354 q += 2; 00355 00356 if (bpp_index == 0) 00357 dvb_encode_rle = dvb_encode_rle2; 00358 else 00359 dvb_encode_rle = dvb_encode_rle4; 00360 00361 top_ptr = q; 00362 dvb_encode_rle(&q, h->rects[object_id]->pict.data[0], h->rects[object_id]->w * 2, 00363 h->rects[object_id]->w, h->rects[object_id]->h >> 1); 00364 bottom_ptr = q; 00365 dvb_encode_rle(&q, h->rects[object_id]->pict.data[0] + h->rects[object_id]->w, 00366 h->rects[object_id]->w * 2, h->rects[object_id]->w, 00367 h->rects[object_id]->h >> 1); 00368 00369 bytestream_put_be16(&ptop_field_len, bottom_ptr - top_ptr); 00370 bytestream_put_be16(&pbottom_field_len, q - bottom_ptr); 00371 } 00372 00373 bytestream_put_be16(&pseg_len, q - pseg_len - 2); 00374 } 00375 } 00376 00377 /* end of display set segment */ 00378 00379 *q++ = 0x0f; /* sync_byte */ 00380 *q++ = 0x80; /* segment_type */ 00381 bytestream_put_be16(&q, page_id); 00382 pseg_len = q; 00383 q += 2; /* segment length */ 00384 00385 bytestream_put_be16(&pseg_len, q - pseg_len - 2); 00386 00387 *q++ = 0xff; /* end of PES data */ 00388 00389 s->object_version = (s->object_version + 1) & 0xf; 00390 s->hide_state = !s->hide_state; 00391 return q - outbuf; 00392 } 00393 00394 static int dvbsub_encode(AVCodecContext *avctx, 00395 unsigned char *buf, int buf_size, void *data) 00396 { 00397 DVBSubtitleContext *s = avctx->priv_data; 00398 AVSubtitle *sub = data; 00399 int ret; 00400 00401 ret = encode_dvb_subtitles(s, buf, sub); 00402 return ret; 00403 } 00404 00405 AVCodec ff_dvbsub_encoder = { 00406 "dvbsub", 00407 AVMEDIA_TYPE_SUBTITLE, 00408 CODEC_ID_DVB_SUBTITLE, 00409 sizeof(DVBSubtitleContext), 00410 NULL, 00411 dvbsub_encode, 00412 .long_name = NULL_IF_CONFIG_SMALL("DVB subtitles"), 00413 };