00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "avcodec.h"
00020
00021 typedef struct DVBSubtitleContext {
00022 int hide_state;
00023 int object_version;
00024 } DVBSubtitleContext;
00025
00026 #define PUTBITS2(val)\
00027 {\
00028 bitbuf |= (val) << bitcnt;\
00029 bitcnt -= 2;\
00030 if (bitcnt < 0) {\
00031 bitcnt = 6;\
00032 *q++ = bitbuf;\
00033 bitbuf = 0;\
00034 }\
00035 }
00036
00037 static void dvb_encode_rle2(uint8_t **pq,
00038 const uint8_t *bitmap, int linesize,
00039 int w, int h)
00040 {
00041 uint8_t *q;
00042 unsigned int bitbuf;
00043 int bitcnt;
00044 int x, y, len, x1, v, color;
00045
00046 q = *pq;
00047
00048 for(y = 0; y < h; y++) {
00049 *q++ = 0x10;
00050 bitbuf = 0;
00051 bitcnt = 6;
00052
00053 x = 0;
00054 while (x < w) {
00055 x1 = x;
00056 color = bitmap[x1++];
00057 while (x1 < w && bitmap[x1] == color)
00058 x1++;
00059 len = x1 - x;
00060 if (color == 0 && len == 2) {
00061 PUTBITS2(0);
00062 PUTBITS2(0);
00063 PUTBITS2(1);
00064 } else if (len >= 3 && len <= 10) {
00065 v = len - 3;
00066 PUTBITS2(0);
00067 PUTBITS2((v >> 2) | 2);
00068 PUTBITS2(v & 3);
00069 PUTBITS2(color);
00070 } else if (len >= 12 && len <= 27) {
00071 v = len - 12;
00072 PUTBITS2(0);
00073 PUTBITS2(0);
00074 PUTBITS2(2);
00075 PUTBITS2(v >> 2);
00076 PUTBITS2(v & 3);
00077 PUTBITS2(color);
00078 } else if (len >= 29) {
00079
00080 if (len > 284)
00081 len = 284;
00082 v = len - 29;
00083 PUTBITS2(0);
00084 PUTBITS2(0);
00085 PUTBITS2(3);
00086 PUTBITS2((v >> 6));
00087 PUTBITS2((v >> 4) & 3);
00088 PUTBITS2((v >> 2) & 3);
00089 PUTBITS2(v & 3);
00090 PUTBITS2(color);
00091 } else {
00092 PUTBITS2(color);
00093 if (color == 0) {
00094 PUTBITS2(1);
00095 }
00096 len = 1;
00097 }
00098 x += len;
00099 }
00100
00101 PUTBITS2(0);
00102 PUTBITS2(0);
00103 PUTBITS2(0);
00104 if (bitcnt != 6) {
00105 *q++ = bitbuf;
00106 }
00107 *q++ = 0xf0;
00108 bitmap += linesize;
00109 }
00110 *pq = q;
00111 }
00112
00113 #define PUTBITS4(val)\
00114 {\
00115 bitbuf |= (val) << bitcnt;\
00116 bitcnt -= 4;\
00117 if (bitcnt < 0) {\
00118 bitcnt = 4;\
00119 *q++ = bitbuf;\
00120 bitbuf = 0;\
00121 }\
00122 }
00123
00124
00125 static void dvb_encode_rle4(uint8_t **pq,
00126 const uint8_t *bitmap, int linesize,
00127 int w, int h)
00128 {
00129 uint8_t *q;
00130 unsigned int bitbuf;
00131 int bitcnt;
00132 int x, y, len, x1, v, color;
00133
00134 q = *pq;
00135
00136 for(y = 0; y < h; y++) {
00137 *q++ = 0x11;
00138 bitbuf = 0;
00139 bitcnt = 4;
00140
00141 x = 0;
00142 while (x < w) {
00143 x1 = x;
00144 color = bitmap[x1++];
00145 while (x1 < w && bitmap[x1] == color)
00146 x1++;
00147 len = x1 - x;
00148 if (color == 0 && len == 2) {
00149 PUTBITS4(0);
00150 PUTBITS4(0xd);
00151 } else if (color == 0 && (len >= 3 && len <= 9)) {
00152 PUTBITS4(0);
00153 PUTBITS4(len - 2);
00154 } else if (len >= 4 && len <= 7) {
00155 PUTBITS4(0);
00156 PUTBITS4(8 + len - 4);
00157 PUTBITS4(color);
00158 } else if (len >= 9 && len <= 24) {
00159 PUTBITS4(0);
00160 PUTBITS4(0xe);
00161 PUTBITS4(len - 9);
00162 PUTBITS4(color);
00163 } else if (len >= 25) {
00164 if (len > 280)
00165 len = 280;
00166 v = len - 25;
00167 PUTBITS4(0);
00168 PUTBITS4(0xf);
00169 PUTBITS4(v >> 4);
00170 PUTBITS4(v & 0xf);
00171 PUTBITS4(color);
00172 } else {
00173 PUTBITS4(color);
00174 if (color == 0) {
00175 PUTBITS4(0xc);
00176 }
00177 len = 1;
00178 }
00179 x += len;
00180 }
00181
00182 PUTBITS4(0);
00183 PUTBITS4(0);
00184 if (bitcnt != 4) {
00185 *q++ = bitbuf;
00186 }
00187 *q++ = 0xf0;
00188 bitmap += linesize;
00189 }
00190 *pq = q;
00191 }
00192
00193 #define SCALEBITS 10
00194 #define ONE_HALF (1 << (SCALEBITS - 1))
00195 #define FIX(x) ((int) ((x) * (1<<SCALEBITS) + 0.5))
00196
00197 #define RGB_TO_Y_CCIR(r, g, b) \
00198 ((FIX(0.29900*219.0/255.0) * (r) + FIX(0.58700*219.0/255.0) * (g) + \
00199 FIX(0.11400*219.0/255.0) * (b) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS)
00200
00201 #define RGB_TO_U_CCIR(r1, g1, b1, shift)\
00202 (((- FIX(0.16874*224.0/255.0) * r1 - FIX(0.33126*224.0/255.0) * g1 + \
00203 FIX(0.50000*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
00204
00205 #define RGB_TO_V_CCIR(r1, g1, b1, shift)\
00206 (((FIX(0.50000*224.0/255.0) * r1 - FIX(0.41869*224.0/255.0) * g1 - \
00207 FIX(0.08131*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128)
00208
00209 static inline void putbe16(uint8_t **pq, uint16_t v)
00210 {
00211 uint8_t *q;
00212 q = *pq;
00213 *q++ = v >> 8;
00214 *q++ = v;
00215 *pq = q;
00216 }
00217
00218 static int encode_dvb_subtitles(DVBSubtitleContext *s,
00219 uint8_t *outbuf, AVSubtitle *h)
00220 {
00221 uint8_t *q, *pseg_len;
00222 int page_id, region_id, clut_id, object_id, i, bpp_index, page_state;
00223
00224
00225 q = outbuf;
00226
00227 page_id = 1;
00228
00229 if (h->num_rects == 0 || h->rects == NULL)
00230 return -1;
00231
00232 *q++ = 0x00;
00233
00234
00235
00236 *q++ = 0x0f;
00237 *q++ = 0x10;
00238 putbe16(&q, page_id);
00239 pseg_len = q;
00240 q += 2;
00241 *q++ = 30;
00242 if (s->hide_state)
00243 page_state = 0;
00244 else
00245 page_state = 2;
00246
00247 *q++ = s->object_version | (page_state << 2) | 3;
00248
00249 for (region_id = 0; region_id < h->num_rects; region_id++) {
00250 *q++ = region_id;
00251 *q++ = 0xff;
00252 putbe16(&q, h->rects[region_id].x);
00253 putbe16(&q, h->rects[region_id].y);
00254 }
00255
00256 putbe16(&pseg_len, q - pseg_len - 2);
00257
00258 if (!s->hide_state) {
00259 for (clut_id = 0; clut_id < h->num_rects; clut_id++) {
00260
00261
00262
00263 if (h->rects[clut_id].nb_colors <= 4) {
00264
00265 bpp_index = 0;
00266 } else if (h->rects[clut_id].nb_colors <= 16) {
00267
00268 bpp_index = 1;
00269 } else {
00270 return -1;
00271 }
00272
00273 *q++ = 0x0f;
00274 *q++ = 0x12;
00275 putbe16(&q, page_id);
00276 pseg_len = q;
00277 q += 2;
00278 *q++ = clut_id;
00279 *q++ = (0 << 4) | 0xf;
00280
00281 for(i = 0; i < h->rects[clut_id].nb_colors; i++) {
00282 *q++ = i;
00283 *q++ = (1 << (7 - bpp_index)) | (0xf << 1) | 1;
00284 {
00285 int a, r, g, b;
00286 a = (h->rects[clut_id].rgba_palette[i] >> 24) & 0xff;
00287 r = (h->rects[clut_id].rgba_palette[i] >> 16) & 0xff;
00288 g = (h->rects[clut_id].rgba_palette[i] >> 8) & 0xff;
00289 b = (h->rects[clut_id].rgba_palette[i] >> 0) & 0xff;
00290
00291 *q++ = RGB_TO_Y_CCIR(r, g, b);
00292 *q++ = RGB_TO_V_CCIR(r, g, b, 0);
00293 *q++ = RGB_TO_U_CCIR(r, g, b, 0);
00294 *q++ = 255 - a;
00295 }
00296 }
00297
00298 putbe16(&pseg_len, q - pseg_len - 2);
00299 }
00300 }
00301
00302 for (region_id = 0; region_id < h->num_rects; region_id++) {
00303
00304
00305
00306 if (h->rects[region_id].nb_colors <= 4) {
00307
00308 bpp_index = 0;
00309 } else if (h->rects[region_id].nb_colors <= 16) {
00310
00311 bpp_index = 1;
00312 } else {
00313 return -1;
00314 }
00315
00316 *q++ = 0x0f;
00317 *q++ = 0x11;
00318 putbe16(&q, page_id);
00319 pseg_len = q;
00320 q += 2;
00321 *q++ = region_id;
00322 *q++ = (s->object_version << 4) | (0 << 3) | 0x07;
00323 putbe16(&q, h->rects[region_id].w);
00324 putbe16(&q, h->rects[region_id].h);
00325 *q++ = ((1 + bpp_index) << 5) | ((1 + bpp_index) << 2) | 0x03;
00326 *q++ = region_id;
00327 *q++ = 0;
00328 *q++ = 0x03;
00329
00330 if (!s->hide_state) {
00331 putbe16(&q, region_id);
00332 *q++ = (0 << 6) | (0 << 4);
00333 *q++ = 0;
00334 *q++ = 0xf0;
00335 *q++ = 0;
00336 }
00337
00338 putbe16(&pseg_len, q - pseg_len - 2);
00339 }
00340
00341 if (!s->hide_state) {
00342
00343 for (object_id = 0; object_id < h->num_rects; object_id++) {
00344
00345
00346 if (h->rects[region_id].nb_colors <= 4) {
00347
00348 bpp_index = 0;
00349 } else if (h->rects[region_id].nb_colors <= 16) {
00350
00351 bpp_index = 1;
00352 } else {
00353 return -1;
00354 }
00355
00356 *q++ = 0x0f;
00357 *q++ = 0x13;
00358 putbe16(&q, page_id);
00359 pseg_len = q;
00360 q += 2;
00361
00362 putbe16(&q, object_id);
00363 *q++ = (s->object_version << 4) | (0 << 2) | (0 << 1) | 1;
00364
00365
00366 {
00367 uint8_t *ptop_field_len, *pbottom_field_len, *top_ptr, *bottom_ptr;
00368 void (*dvb_encode_rle)(uint8_t **pq,
00369 const uint8_t *bitmap, int linesize,
00370 int w, int h);
00371 ptop_field_len = q;
00372 q += 2;
00373 pbottom_field_len = q;
00374 q += 2;
00375
00376 if (bpp_index == 0)
00377 dvb_encode_rle = dvb_encode_rle2;
00378 else
00379 dvb_encode_rle = dvb_encode_rle4;
00380
00381 top_ptr = q;
00382 dvb_encode_rle(&q, h->rects[object_id].bitmap, h->rects[object_id].w * 2,
00383 h->rects[object_id].w, h->rects[object_id].h >> 1);
00384 bottom_ptr = q;
00385 dvb_encode_rle(&q, h->rects[object_id].bitmap + h->rects[object_id].w,
00386 h->rects[object_id].w * 2, h->rects[object_id].w,
00387 h->rects[object_id].h >> 1);
00388
00389 putbe16(&ptop_field_len, bottom_ptr - top_ptr);
00390 putbe16(&pbottom_field_len, q - bottom_ptr);
00391 }
00392
00393 putbe16(&pseg_len, q - pseg_len - 2);
00394 }
00395 }
00396
00397
00398
00399 *q++ = 0x0f;
00400 *q++ = 0x80;
00401 putbe16(&q, page_id);
00402 pseg_len = q;
00403 q += 2;
00404
00405 putbe16(&pseg_len, q - pseg_len - 2);
00406
00407 *q++ = 0xff;
00408
00409 s->object_version = (s->object_version + 1) & 0xf;
00410 s->hide_state = !s->hide_state;
00411 return q - outbuf;
00412 }
00413
00414 static int dvbsub_init_decoder(AVCodecContext *avctx)
00415 {
00416 return 0;
00417 }
00418
00419 static int dvbsub_close_decoder(AVCodecContext *avctx)
00420 {
00421 return 0;
00422 }
00423
00424 static int dvbsub_encode(AVCodecContext *avctx,
00425 unsigned char *buf, int buf_size, void *data)
00426 {
00427 DVBSubtitleContext *s = avctx->priv_data;
00428 AVSubtitle *sub = data;
00429 int ret;
00430
00431 ret = encode_dvb_subtitles(s, buf, sub);
00432 return ret;
00433 }
00434
00435 AVCodec dvbsub_encoder = {
00436 "dvbsub",
00437 CODEC_TYPE_SUBTITLE,
00438 CODEC_ID_DVB_SUBTITLE,
00439 sizeof(DVBSubtitleContext),
00440 dvbsub_init_decoder,
00441 dvbsub_encode,
00442 dvbsub_close_decoder,
00443 };