annotate ffmpeg/libavcodec/dvbsubdec.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents 6840f77b83aa
children
rev   line source
yading@10 1 /*
yading@10 2 * DVB subtitle decoding
yading@10 3 * Copyright (c) 2005 Ian Caulfield
yading@10 4 *
yading@10 5 * This file is part of FFmpeg.
yading@10 6 *
yading@10 7 * FFmpeg is free software; you can redistribute it and/or
yading@10 8 * modify it under the terms of the GNU Lesser General Public
yading@10 9 * License as published by the Free Software Foundation; either
yading@10 10 * version 2.1 of the License, or (at your option) any later version.
yading@10 11 *
yading@10 12 * FFmpeg is distributed in the hope that it will be useful,
yading@10 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@10 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@10 15 * Lesser General Public License for more details.
yading@10 16 *
yading@10 17 * You should have received a copy of the GNU Lesser General Public
yading@10 18 * License along with FFmpeg; if not, write to the Free Software
yading@10 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@10 20 */
yading@10 21 #include "avcodec.h"
yading@10 22 #include "dsputil.h"
yading@10 23 #include "get_bits.h"
yading@10 24 #include "bytestream.h"
yading@10 25 #include "libavutil/colorspace.h"
yading@10 26
yading@10 27 #define DVBSUB_PAGE_SEGMENT 0x10
yading@10 28 #define DVBSUB_REGION_SEGMENT 0x11
yading@10 29 #define DVBSUB_CLUT_SEGMENT 0x12
yading@10 30 #define DVBSUB_OBJECT_SEGMENT 0x13
yading@10 31 #define DVBSUB_DISPLAYDEFINITION_SEGMENT 0x14
yading@10 32 #define DVBSUB_DISPLAY_SEGMENT 0x80
yading@10 33
yading@10 34 #define cm (ff_cropTbl + MAX_NEG_CROP)
yading@10 35
yading@10 36 #ifdef DEBUG
yading@10 37 #undef fprintf
yading@10 38 #undef perror
yading@10 39 #if 0
yading@10 40 static void png_save(const char *filename, uint8_t *bitmap, int w, int h,
yading@10 41 uint32_t *rgba_palette)
yading@10 42 {
yading@10 43 int x, y, v;
yading@10 44 FILE *f;
yading@10 45 char fname[40], fname2[40];
yading@10 46 char command[1024];
yading@10 47
yading@10 48 snprintf(fname, 40, "%s.ppm", filename);
yading@10 49
yading@10 50 f = fopen(fname, "w");
yading@10 51 if (!f) {
yading@10 52 perror(fname);
yading@10 53 return;
yading@10 54 }
yading@10 55 fprintf(f, "P6\n"
yading@10 56 "%d %d\n"
yading@10 57 "%d\n",
yading@10 58 w, h, 255);
yading@10 59 for(y = 0; y < h; y++) {
yading@10 60 for(x = 0; x < w; x++) {
yading@10 61 v = rgba_palette[bitmap[y * w + x]];
yading@10 62 putc((v >> 16) & 0xff, f);
yading@10 63 putc((v >> 8) & 0xff, f);
yading@10 64 putc((v >> 0) & 0xff, f);
yading@10 65 }
yading@10 66 }
yading@10 67 fclose(f);
yading@10 68
yading@10 69
yading@10 70 snprintf(fname2, 40, "%s-a.pgm", filename);
yading@10 71
yading@10 72 f = fopen(fname2, "w");
yading@10 73 if (!f) {
yading@10 74 perror(fname2);
yading@10 75 return;
yading@10 76 }
yading@10 77 fprintf(f, "P5\n"
yading@10 78 "%d %d\n"
yading@10 79 "%d\n",
yading@10 80 w, h, 255);
yading@10 81 for(y = 0; y < h; y++) {
yading@10 82 for(x = 0; x < w; x++) {
yading@10 83 v = rgba_palette[bitmap[y * w + x]];
yading@10 84 putc((v >> 24) & 0xff, f);
yading@10 85 }
yading@10 86 }
yading@10 87 fclose(f);
yading@10 88
yading@10 89 snprintf(command, 1024, "pnmtopng -alpha %s %s > %s.png 2> /dev/null", fname2, fname, filename);
yading@10 90 system(command);
yading@10 91
yading@10 92 snprintf(command, 1024, "rm %s %s", fname, fname2);
yading@10 93 system(command);
yading@10 94 }
yading@10 95 #endif
yading@10 96
yading@10 97 static void png_save2(const char *filename, uint32_t *bitmap, int w, int h)
yading@10 98 {
yading@10 99 int x, y, v;
yading@10 100 FILE *f;
yading@10 101 char fname[40], fname2[40];
yading@10 102 char command[1024];
yading@10 103
yading@10 104 snprintf(fname, sizeof(fname), "%s.ppm", filename);
yading@10 105
yading@10 106 f = fopen(fname, "w");
yading@10 107 if (!f) {
yading@10 108 perror(fname);
yading@10 109 return;
yading@10 110 }
yading@10 111 fprintf(f, "P6\n"
yading@10 112 "%d %d\n"
yading@10 113 "%d\n",
yading@10 114 w, h, 255);
yading@10 115 for(y = 0; y < h; y++) {
yading@10 116 for(x = 0; x < w; x++) {
yading@10 117 v = bitmap[y * w + x];
yading@10 118 putc((v >> 16) & 0xff, f);
yading@10 119 putc((v >> 8) & 0xff, f);
yading@10 120 putc((v >> 0) & 0xff, f);
yading@10 121 }
yading@10 122 }
yading@10 123 fclose(f);
yading@10 124
yading@10 125
yading@10 126 snprintf(fname2, sizeof(fname2), "%s-a.pgm", filename);
yading@10 127
yading@10 128 f = fopen(fname2, "w");
yading@10 129 if (!f) {
yading@10 130 perror(fname2);
yading@10 131 return;
yading@10 132 }
yading@10 133 fprintf(f, "P5\n"
yading@10 134 "%d %d\n"
yading@10 135 "%d\n",
yading@10 136 w, h, 255);
yading@10 137 for(y = 0; y < h; y++) {
yading@10 138 for(x = 0; x < w; x++) {
yading@10 139 v = bitmap[y * w + x];
yading@10 140 putc((v >> 24) & 0xff, f);
yading@10 141 }
yading@10 142 }
yading@10 143 fclose(f);
yading@10 144
yading@10 145 snprintf(command, sizeof(command), "pnmtopng -alpha %s %s > %s.png 2> /dev/null", fname2, fname, filename);
yading@10 146 system(command);
yading@10 147
yading@10 148 snprintf(command, sizeof(command), "rm %s %s", fname, fname2);
yading@10 149 system(command);
yading@10 150 }
yading@10 151 #endif
yading@10 152
yading@10 153 #define RGBA(r,g,b,a) (((unsigned)(a) << 24) | ((r) << 16) | ((g) << 8) | (b))
yading@10 154
yading@10 155 typedef struct DVBSubCLUT {
yading@10 156 int id;
yading@10 157 int version;
yading@10 158
yading@10 159 uint32_t clut4[4];
yading@10 160 uint32_t clut16[16];
yading@10 161 uint32_t clut256[256];
yading@10 162
yading@10 163 struct DVBSubCLUT *next;
yading@10 164 } DVBSubCLUT;
yading@10 165
yading@10 166 static DVBSubCLUT default_clut;
yading@10 167
yading@10 168 typedef struct DVBSubObjectDisplay {
yading@10 169 int object_id;
yading@10 170 int region_id;
yading@10 171
yading@10 172 int x_pos;
yading@10 173 int y_pos;
yading@10 174
yading@10 175 int fgcolor;
yading@10 176 int bgcolor;
yading@10 177
yading@10 178 struct DVBSubObjectDisplay *region_list_next;
yading@10 179 struct DVBSubObjectDisplay *object_list_next;
yading@10 180 } DVBSubObjectDisplay;
yading@10 181
yading@10 182 typedef struct DVBSubObject {
yading@10 183 int id;
yading@10 184 int version;
yading@10 185
yading@10 186 int type;
yading@10 187
yading@10 188 DVBSubObjectDisplay *display_list;
yading@10 189
yading@10 190 struct DVBSubObject *next;
yading@10 191 } DVBSubObject;
yading@10 192
yading@10 193 typedef struct DVBSubRegionDisplay {
yading@10 194 int region_id;
yading@10 195
yading@10 196 int x_pos;
yading@10 197 int y_pos;
yading@10 198
yading@10 199 struct DVBSubRegionDisplay *next;
yading@10 200 } DVBSubRegionDisplay;
yading@10 201
yading@10 202 typedef struct DVBSubRegion {
yading@10 203 int id;
yading@10 204 int version;
yading@10 205
yading@10 206 int width;
yading@10 207 int height;
yading@10 208 int depth;
yading@10 209
yading@10 210 int clut;
yading@10 211 int bgcolor;
yading@10 212
yading@10 213 uint8_t *pbuf;
yading@10 214 int buf_size;
yading@10 215 int dirty;
yading@10 216
yading@10 217 DVBSubObjectDisplay *display_list;
yading@10 218
yading@10 219 struct DVBSubRegion *next;
yading@10 220 } DVBSubRegion;
yading@10 221
yading@10 222 typedef struct DVBSubDisplayDefinition {
yading@10 223 int version;
yading@10 224
yading@10 225 int x;
yading@10 226 int y;
yading@10 227 int width;
yading@10 228 int height;
yading@10 229 } DVBSubDisplayDefinition;
yading@10 230
yading@10 231 typedef struct DVBSubContext {
yading@10 232 int composition_id;
yading@10 233 int ancillary_id;
yading@10 234
yading@10 235 int version;
yading@10 236 int time_out;
yading@10 237 DVBSubRegion *region_list;
yading@10 238 DVBSubCLUT *clut_list;
yading@10 239 DVBSubObject *object_list;
yading@10 240
yading@10 241 int display_list_size;
yading@10 242 DVBSubRegionDisplay *display_list;
yading@10 243 DVBSubDisplayDefinition *display_definition;
yading@10 244 } DVBSubContext;
yading@10 245
yading@10 246
yading@10 247 static DVBSubObject* get_object(DVBSubContext *ctx, int object_id)
yading@10 248 {
yading@10 249 DVBSubObject *ptr = ctx->object_list;
yading@10 250
yading@10 251 while (ptr && ptr->id != object_id) {
yading@10 252 ptr = ptr->next;
yading@10 253 }
yading@10 254
yading@10 255 return ptr;
yading@10 256 }
yading@10 257
yading@10 258 static DVBSubCLUT* get_clut(DVBSubContext *ctx, int clut_id)
yading@10 259 {
yading@10 260 DVBSubCLUT *ptr = ctx->clut_list;
yading@10 261
yading@10 262 while (ptr && ptr->id != clut_id) {
yading@10 263 ptr = ptr->next;
yading@10 264 }
yading@10 265
yading@10 266 return ptr;
yading@10 267 }
yading@10 268
yading@10 269 static DVBSubRegion* get_region(DVBSubContext *ctx, int region_id)
yading@10 270 {
yading@10 271 DVBSubRegion *ptr = ctx->region_list;
yading@10 272
yading@10 273 while (ptr && ptr->id != region_id) {
yading@10 274 ptr = ptr->next;
yading@10 275 }
yading@10 276
yading@10 277 return ptr;
yading@10 278 }
yading@10 279
yading@10 280 static void delete_region_display_list(DVBSubContext *ctx, DVBSubRegion *region)
yading@10 281 {
yading@10 282 DVBSubObject *object, *obj2, **obj2_ptr;
yading@10 283 DVBSubObjectDisplay *display, *obj_disp, **obj_disp_ptr;
yading@10 284
yading@10 285 while (region->display_list) {
yading@10 286 display = region->display_list;
yading@10 287
yading@10 288 object = get_object(ctx, display->object_id);
yading@10 289
yading@10 290 if (object) {
yading@10 291 obj_disp_ptr = &object->display_list;
yading@10 292 obj_disp = *obj_disp_ptr;
yading@10 293
yading@10 294 while (obj_disp && obj_disp != display) {
yading@10 295 obj_disp_ptr = &obj_disp->object_list_next;
yading@10 296 obj_disp = *obj_disp_ptr;
yading@10 297 }
yading@10 298
yading@10 299 if (obj_disp) {
yading@10 300 *obj_disp_ptr = obj_disp->object_list_next;
yading@10 301
yading@10 302 if (!object->display_list) {
yading@10 303 obj2_ptr = &ctx->object_list;
yading@10 304 obj2 = *obj2_ptr;
yading@10 305
yading@10 306 while (obj2 != object) {
yading@10 307 assert(obj2);
yading@10 308 obj2_ptr = &obj2->next;
yading@10 309 obj2 = *obj2_ptr;
yading@10 310 }
yading@10 311
yading@10 312 *obj2_ptr = obj2->next;
yading@10 313
yading@10 314 av_free(obj2);
yading@10 315 }
yading@10 316 }
yading@10 317 }
yading@10 318
yading@10 319 region->display_list = display->region_list_next;
yading@10 320
yading@10 321 av_free(display);
yading@10 322 }
yading@10 323
yading@10 324 }
yading@10 325
yading@10 326 static void delete_cluts(DVBSubContext *ctx)
yading@10 327 {
yading@10 328 DVBSubCLUT *clut;
yading@10 329
yading@10 330 while (ctx->clut_list) {
yading@10 331 clut = ctx->clut_list;
yading@10 332
yading@10 333 ctx->clut_list = clut->next;
yading@10 334
yading@10 335 av_free(clut);
yading@10 336 }
yading@10 337 }
yading@10 338
yading@10 339 static void delete_objects(DVBSubContext *ctx)
yading@10 340 {
yading@10 341 DVBSubObject *object;
yading@10 342
yading@10 343 while (ctx->object_list) {
yading@10 344 object = ctx->object_list;
yading@10 345
yading@10 346 ctx->object_list = object->next;
yading@10 347
yading@10 348 av_free(object);
yading@10 349 }
yading@10 350 }
yading@10 351
yading@10 352 static void delete_regions(DVBSubContext *ctx)
yading@10 353 {
yading@10 354 DVBSubRegion *region;
yading@10 355
yading@10 356 while (ctx->region_list) {
yading@10 357 region = ctx->region_list;
yading@10 358
yading@10 359 ctx->region_list = region->next;
yading@10 360
yading@10 361 delete_region_display_list(ctx, region);
yading@10 362
yading@10 363 av_free(region->pbuf);
yading@10 364 av_free(region);
yading@10 365 }
yading@10 366 }
yading@10 367
yading@10 368 static av_cold int dvbsub_init_decoder(AVCodecContext *avctx)
yading@10 369 {
yading@10 370 int i, r, g, b, a = 0;
yading@10 371 DVBSubContext *ctx = avctx->priv_data;
yading@10 372
yading@10 373 if (!avctx->extradata || avctx->extradata_size != 4) {
yading@10 374 av_log(avctx, AV_LOG_WARNING, "Invalid extradata, subtitle streams may be combined!\n");
yading@10 375 ctx->composition_id = -1;
yading@10 376 ctx->ancillary_id = -1;
yading@10 377 } else {
yading@10 378 ctx->composition_id = AV_RB16(avctx->extradata);
yading@10 379 ctx->ancillary_id = AV_RB16(avctx->extradata + 2);
yading@10 380 }
yading@10 381
yading@10 382 ctx->version = -1;
yading@10 383
yading@10 384 default_clut.id = -1;
yading@10 385 default_clut.next = NULL;
yading@10 386
yading@10 387 default_clut.clut4[0] = RGBA( 0, 0, 0, 0);
yading@10 388 default_clut.clut4[1] = RGBA(255, 255, 255, 255);
yading@10 389 default_clut.clut4[2] = RGBA( 0, 0, 0, 255);
yading@10 390 default_clut.clut4[3] = RGBA(127, 127, 127, 255);
yading@10 391
yading@10 392 default_clut.clut16[0] = RGBA( 0, 0, 0, 0);
yading@10 393 for (i = 1; i < 16; i++) {
yading@10 394 if (i < 8) {
yading@10 395 r = (i & 1) ? 255 : 0;
yading@10 396 g = (i & 2) ? 255 : 0;
yading@10 397 b = (i & 4) ? 255 : 0;
yading@10 398 } else {
yading@10 399 r = (i & 1) ? 127 : 0;
yading@10 400 g = (i & 2) ? 127 : 0;
yading@10 401 b = (i & 4) ? 127 : 0;
yading@10 402 }
yading@10 403 default_clut.clut16[i] = RGBA(r, g, b, 255);
yading@10 404 }
yading@10 405
yading@10 406 default_clut.clut256[0] = RGBA( 0, 0, 0, 0);
yading@10 407 for (i = 1; i < 256; i++) {
yading@10 408 if (i < 8) {
yading@10 409 r = (i & 1) ? 255 : 0;
yading@10 410 g = (i & 2) ? 255 : 0;
yading@10 411 b = (i & 4) ? 255 : 0;
yading@10 412 a = 63;
yading@10 413 } else {
yading@10 414 switch (i & 0x88) {
yading@10 415 case 0x00:
yading@10 416 r = ((i & 1) ? 85 : 0) + ((i & 0x10) ? 170 : 0);
yading@10 417 g = ((i & 2) ? 85 : 0) + ((i & 0x20) ? 170 : 0);
yading@10 418 b = ((i & 4) ? 85 : 0) + ((i & 0x40) ? 170 : 0);
yading@10 419 a = 255;
yading@10 420 break;
yading@10 421 case 0x08:
yading@10 422 r = ((i & 1) ? 85 : 0) + ((i & 0x10) ? 170 : 0);
yading@10 423 g = ((i & 2) ? 85 : 0) + ((i & 0x20) ? 170 : 0);
yading@10 424 b = ((i & 4) ? 85 : 0) + ((i & 0x40) ? 170 : 0);
yading@10 425 a = 127;
yading@10 426 break;
yading@10 427 case 0x80:
yading@10 428 r = 127 + ((i & 1) ? 43 : 0) + ((i & 0x10) ? 85 : 0);
yading@10 429 g = 127 + ((i & 2) ? 43 : 0) + ((i & 0x20) ? 85 : 0);
yading@10 430 b = 127 + ((i & 4) ? 43 : 0) + ((i & 0x40) ? 85 : 0);
yading@10 431 a = 255;
yading@10 432 break;
yading@10 433 case 0x88:
yading@10 434 r = ((i & 1) ? 43 : 0) + ((i & 0x10) ? 85 : 0);
yading@10 435 g = ((i & 2) ? 43 : 0) + ((i & 0x20) ? 85 : 0);
yading@10 436 b = ((i & 4) ? 43 : 0) + ((i & 0x40) ? 85 : 0);
yading@10 437 a = 255;
yading@10 438 break;
yading@10 439 }
yading@10 440 }
yading@10 441 default_clut.clut256[i] = RGBA(r, g, b, a);
yading@10 442 }
yading@10 443
yading@10 444 return 0;
yading@10 445 }
yading@10 446
yading@10 447 static av_cold int dvbsub_close_decoder(AVCodecContext *avctx)
yading@10 448 {
yading@10 449 DVBSubContext *ctx = avctx->priv_data;
yading@10 450 DVBSubRegionDisplay *display;
yading@10 451
yading@10 452 delete_regions(ctx);
yading@10 453
yading@10 454 delete_objects(ctx);
yading@10 455
yading@10 456 delete_cluts(ctx);
yading@10 457
yading@10 458 av_freep(&ctx->display_definition);
yading@10 459
yading@10 460 while (ctx->display_list) {
yading@10 461 display = ctx->display_list;
yading@10 462 ctx->display_list = display->next;
yading@10 463
yading@10 464 av_free(display);
yading@10 465 }
yading@10 466
yading@10 467 return 0;
yading@10 468 }
yading@10 469
yading@10 470 static int dvbsub_read_2bit_string(uint8_t *destbuf, int dbuf_len,
yading@10 471 const uint8_t **srcbuf, int buf_size,
yading@10 472 int non_mod, uint8_t *map_table, int x_pos)
yading@10 473 {
yading@10 474 GetBitContext gb;
yading@10 475
yading@10 476 int bits;
yading@10 477 int run_length;
yading@10 478 int pixels_read = x_pos;
yading@10 479
yading@10 480 init_get_bits(&gb, *srcbuf, buf_size << 3);
yading@10 481
yading@10 482 destbuf += x_pos;
yading@10 483
yading@10 484 while (get_bits_count(&gb) < buf_size << 3 && pixels_read < dbuf_len) {
yading@10 485 bits = get_bits(&gb, 2);
yading@10 486
yading@10 487 if (bits) {
yading@10 488 if (non_mod != 1 || bits != 1) {
yading@10 489 if (map_table)
yading@10 490 *destbuf++ = map_table[bits];
yading@10 491 else
yading@10 492 *destbuf++ = bits;
yading@10 493 }
yading@10 494 pixels_read++;
yading@10 495 } else {
yading@10 496 bits = get_bits1(&gb);
yading@10 497 if (bits == 1) {
yading@10 498 run_length = get_bits(&gb, 3) + 3;
yading@10 499 bits = get_bits(&gb, 2);
yading@10 500
yading@10 501 if (non_mod == 1 && bits == 1)
yading@10 502 pixels_read += run_length;
yading@10 503 else {
yading@10 504 if (map_table)
yading@10 505 bits = map_table[bits];
yading@10 506 while (run_length-- > 0 && pixels_read < dbuf_len) {
yading@10 507 *destbuf++ = bits;
yading@10 508 pixels_read++;
yading@10 509 }
yading@10 510 }
yading@10 511 } else {
yading@10 512 bits = get_bits1(&gb);
yading@10 513 if (bits == 0) {
yading@10 514 bits = get_bits(&gb, 2);
yading@10 515 if (bits == 2) {
yading@10 516 run_length = get_bits(&gb, 4) + 12;
yading@10 517 bits = get_bits(&gb, 2);
yading@10 518
yading@10 519 if (non_mod == 1 && bits == 1)
yading@10 520 pixels_read += run_length;
yading@10 521 else {
yading@10 522 if (map_table)
yading@10 523 bits = map_table[bits];
yading@10 524 while (run_length-- > 0 && pixels_read < dbuf_len) {
yading@10 525 *destbuf++ = bits;
yading@10 526 pixels_read++;
yading@10 527 }
yading@10 528 }
yading@10 529 } else if (bits == 3) {
yading@10 530 run_length = get_bits(&gb, 8) + 29;
yading@10 531 bits = get_bits(&gb, 2);
yading@10 532
yading@10 533 if (non_mod == 1 && bits == 1)
yading@10 534 pixels_read += run_length;
yading@10 535 else {
yading@10 536 if (map_table)
yading@10 537 bits = map_table[bits];
yading@10 538 while (run_length-- > 0 && pixels_read < dbuf_len) {
yading@10 539 *destbuf++ = bits;
yading@10 540 pixels_read++;
yading@10 541 }
yading@10 542 }
yading@10 543 } else if (bits == 1) {
yading@10 544 if (map_table)
yading@10 545 bits = map_table[0];
yading@10 546 else
yading@10 547 bits = 0;
yading@10 548 run_length = 2;
yading@10 549 while (run_length-- > 0 && pixels_read < dbuf_len) {
yading@10 550 *destbuf++ = bits;
yading@10 551 pixels_read++;
yading@10 552 }
yading@10 553 } else {
yading@10 554 (*srcbuf) += (get_bits_count(&gb) + 7) >> 3;
yading@10 555 return pixels_read;
yading@10 556 }
yading@10 557 } else {
yading@10 558 if (map_table)
yading@10 559 bits = map_table[0];
yading@10 560 else
yading@10 561 bits = 0;
yading@10 562 *destbuf++ = bits;
yading@10 563 pixels_read++;
yading@10 564 }
yading@10 565 }
yading@10 566 }
yading@10 567 }
yading@10 568
yading@10 569 if (get_bits(&gb, 6))
yading@10 570 av_log(0, AV_LOG_ERROR, "DVBSub error: line overflow\n");
yading@10 571
yading@10 572 (*srcbuf) += (get_bits_count(&gb) + 7) >> 3;
yading@10 573
yading@10 574 return pixels_read;
yading@10 575 }
yading@10 576
yading@10 577 static int dvbsub_read_4bit_string(uint8_t *destbuf, int dbuf_len,
yading@10 578 const uint8_t **srcbuf, int buf_size,
yading@10 579 int non_mod, uint8_t *map_table, int x_pos)
yading@10 580 {
yading@10 581 GetBitContext gb;
yading@10 582
yading@10 583 int bits;
yading@10 584 int run_length;
yading@10 585 int pixels_read = x_pos;
yading@10 586
yading@10 587 init_get_bits(&gb, *srcbuf, buf_size << 3);
yading@10 588
yading@10 589 destbuf += x_pos;
yading@10 590
yading@10 591 while (get_bits_count(&gb) < buf_size << 3 && pixels_read < dbuf_len) {
yading@10 592 bits = get_bits(&gb, 4);
yading@10 593
yading@10 594 if (bits) {
yading@10 595 if (non_mod != 1 || bits != 1) {
yading@10 596 if (map_table)
yading@10 597 *destbuf++ = map_table[bits];
yading@10 598 else
yading@10 599 *destbuf++ = bits;
yading@10 600 }
yading@10 601 pixels_read++;
yading@10 602 } else {
yading@10 603 bits = get_bits1(&gb);
yading@10 604 if (bits == 0) {
yading@10 605 run_length = get_bits(&gb, 3);
yading@10 606
yading@10 607 if (run_length == 0) {
yading@10 608 (*srcbuf) += (get_bits_count(&gb) + 7) >> 3;
yading@10 609 return pixels_read;
yading@10 610 }
yading@10 611
yading@10 612 run_length += 2;
yading@10 613
yading@10 614 if (map_table)
yading@10 615 bits = map_table[0];
yading@10 616 else
yading@10 617 bits = 0;
yading@10 618
yading@10 619 while (run_length-- > 0 && pixels_read < dbuf_len) {
yading@10 620 *destbuf++ = bits;
yading@10 621 pixels_read++;
yading@10 622 }
yading@10 623 } else {
yading@10 624 bits = get_bits1(&gb);
yading@10 625 if (bits == 0) {
yading@10 626 run_length = get_bits(&gb, 2) + 4;
yading@10 627 bits = get_bits(&gb, 4);
yading@10 628
yading@10 629 if (non_mod == 1 && bits == 1)
yading@10 630 pixels_read += run_length;
yading@10 631 else {
yading@10 632 if (map_table)
yading@10 633 bits = map_table[bits];
yading@10 634 while (run_length-- > 0 && pixels_read < dbuf_len) {
yading@10 635 *destbuf++ = bits;
yading@10 636 pixels_read++;
yading@10 637 }
yading@10 638 }
yading@10 639 } else {
yading@10 640 bits = get_bits(&gb, 2);
yading@10 641 if (bits == 2) {
yading@10 642 run_length = get_bits(&gb, 4) + 9;
yading@10 643 bits = get_bits(&gb, 4);
yading@10 644
yading@10 645 if (non_mod == 1 && bits == 1)
yading@10 646 pixels_read += run_length;
yading@10 647 else {
yading@10 648 if (map_table)
yading@10 649 bits = map_table[bits];
yading@10 650 while (run_length-- > 0 && pixels_read < dbuf_len) {
yading@10 651 *destbuf++ = bits;
yading@10 652 pixels_read++;
yading@10 653 }
yading@10 654 }
yading@10 655 } else if (bits == 3) {
yading@10 656 run_length = get_bits(&gb, 8) + 25;
yading@10 657 bits = get_bits(&gb, 4);
yading@10 658
yading@10 659 if (non_mod == 1 && bits == 1)
yading@10 660 pixels_read += run_length;
yading@10 661 else {
yading@10 662 if (map_table)
yading@10 663 bits = map_table[bits];
yading@10 664 while (run_length-- > 0 && pixels_read < dbuf_len) {
yading@10 665 *destbuf++ = bits;
yading@10 666 pixels_read++;
yading@10 667 }
yading@10 668 }
yading@10 669 } else if (bits == 1) {
yading@10 670 if (map_table)
yading@10 671 bits = map_table[0];
yading@10 672 else
yading@10 673 bits = 0;
yading@10 674 run_length = 2;
yading@10 675 while (run_length-- > 0 && pixels_read < dbuf_len) {
yading@10 676 *destbuf++ = bits;
yading@10 677 pixels_read++;
yading@10 678 }
yading@10 679 } else {
yading@10 680 if (map_table)
yading@10 681 bits = map_table[0];
yading@10 682 else
yading@10 683 bits = 0;
yading@10 684 *destbuf++ = bits;
yading@10 685 pixels_read ++;
yading@10 686 }
yading@10 687 }
yading@10 688 }
yading@10 689 }
yading@10 690 }
yading@10 691
yading@10 692 if (get_bits(&gb, 8))
yading@10 693 av_log(0, AV_LOG_ERROR, "DVBSub error: line overflow\n");
yading@10 694
yading@10 695 (*srcbuf) += (get_bits_count(&gb) + 7) >> 3;
yading@10 696
yading@10 697 return pixels_read;
yading@10 698 }
yading@10 699
yading@10 700 static int dvbsub_read_8bit_string(uint8_t *destbuf, int dbuf_len,
yading@10 701 const uint8_t **srcbuf, int buf_size,
yading@10 702 int non_mod, uint8_t *map_table, int x_pos)
yading@10 703 {
yading@10 704 const uint8_t *sbuf_end = (*srcbuf) + buf_size;
yading@10 705 int bits;
yading@10 706 int run_length;
yading@10 707 int pixels_read = x_pos;
yading@10 708
yading@10 709 destbuf += x_pos;
yading@10 710
yading@10 711 while (*srcbuf < sbuf_end && pixels_read < dbuf_len) {
yading@10 712 bits = *(*srcbuf)++;
yading@10 713
yading@10 714 if (bits) {
yading@10 715 if (non_mod != 1 || bits != 1) {
yading@10 716 if (map_table)
yading@10 717 *destbuf++ = map_table[bits];
yading@10 718 else
yading@10 719 *destbuf++ = bits;
yading@10 720 }
yading@10 721 pixels_read++;
yading@10 722 } else {
yading@10 723 bits = *(*srcbuf)++;
yading@10 724 run_length = bits & 0x7f;
yading@10 725 if ((bits & 0x80) == 0) {
yading@10 726 if (run_length == 0) {
yading@10 727 return pixels_read;
yading@10 728 }
yading@10 729
yading@10 730 if (map_table)
yading@10 731 bits = map_table[0];
yading@10 732 else
yading@10 733 bits = 0;
yading@10 734 while (run_length-- > 0 && pixels_read < dbuf_len) {
yading@10 735 *destbuf++ = bits;
yading@10 736 pixels_read++;
yading@10 737 }
yading@10 738 } else {
yading@10 739 bits = *(*srcbuf)++;
yading@10 740
yading@10 741 if (non_mod == 1 && bits == 1)
yading@10 742 pixels_read += run_length;
yading@10 743 if (map_table)
yading@10 744 bits = map_table[bits];
yading@10 745 else while (run_length-- > 0 && pixels_read < dbuf_len) {
yading@10 746 *destbuf++ = bits;
yading@10 747 pixels_read++;
yading@10 748 }
yading@10 749 }
yading@10 750 }
yading@10 751 }
yading@10 752
yading@10 753 if (*(*srcbuf)++)
yading@10 754 av_log(0, AV_LOG_ERROR, "DVBSub error: line overflow\n");
yading@10 755
yading@10 756 return pixels_read;
yading@10 757 }
yading@10 758
yading@10 759
yading@10 760
yading@10 761 static void dvbsub_parse_pixel_data_block(AVCodecContext *avctx, DVBSubObjectDisplay *display,
yading@10 762 const uint8_t *buf, int buf_size, int top_bottom, int non_mod)
yading@10 763 {
yading@10 764 DVBSubContext *ctx = avctx->priv_data;
yading@10 765
yading@10 766 DVBSubRegion *region = get_region(ctx, display->region_id);
yading@10 767 const uint8_t *buf_end = buf + buf_size;
yading@10 768 uint8_t *pbuf;
yading@10 769 int x_pos, y_pos;
yading@10 770 int i;
yading@10 771
yading@10 772 uint8_t map2to4[] = { 0x0, 0x7, 0x8, 0xf};
yading@10 773 uint8_t map2to8[] = {0x00, 0x77, 0x88, 0xff};
yading@10 774 uint8_t map4to8[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
yading@10 775 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
yading@10 776 uint8_t *map_table;
yading@10 777
yading@10 778 #if 0
yading@10 779 av_dlog(avctx, "DVB pixel block size %d, %s field:\n", buf_size,
yading@10 780 top_bottom ? "bottom" : "top");
yading@10 781
yading@10 782 for (i = 0; i < buf_size; i++) {
yading@10 783 if (i % 16 == 0)
yading@10 784 av_dlog(avctx, "0x%8p: ", buf+i);
yading@10 785
yading@10 786 av_dlog(avctx, "%02x ", buf[i]);
yading@10 787 if (i % 16 == 15)
yading@10 788 av_dlog(avctx, "\n");
yading@10 789 }
yading@10 790
yading@10 791 if (i % 16)
yading@10 792 av_dlog(avctx, "\n");
yading@10 793 #endif
yading@10 794
yading@10 795 if (region == 0)
yading@10 796 return;
yading@10 797
yading@10 798 pbuf = region->pbuf;
yading@10 799 region->dirty = 1;
yading@10 800
yading@10 801 x_pos = display->x_pos;
yading@10 802 y_pos = display->y_pos;
yading@10 803
yading@10 804 y_pos += top_bottom;
yading@10 805
yading@10 806 while (buf < buf_end) {
yading@10 807 if ((*buf!=0xf0 && x_pos >= region->width) || y_pos >= region->height) {
yading@10 808 av_log(avctx, AV_LOG_ERROR, "Invalid object location! %d-%d %d-%d %02x\n", x_pos, region->width, y_pos, region->height, *buf);
yading@10 809 return;
yading@10 810 }
yading@10 811
yading@10 812 switch (*buf++) {
yading@10 813 case 0x10:
yading@10 814 if (region->depth == 8)
yading@10 815 map_table = map2to8;
yading@10 816 else if (region->depth == 4)
yading@10 817 map_table = map2to4;
yading@10 818 else
yading@10 819 map_table = NULL;
yading@10 820
yading@10 821 x_pos = dvbsub_read_2bit_string(pbuf + (y_pos * region->width),
yading@10 822 region->width, &buf, buf_end - buf,
yading@10 823 non_mod, map_table, x_pos);
yading@10 824 break;
yading@10 825 case 0x11:
yading@10 826 if (region->depth < 4) {
yading@10 827 av_log(avctx, AV_LOG_ERROR, "4-bit pixel string in %d-bit region!\n", region->depth);
yading@10 828 return;
yading@10 829 }
yading@10 830
yading@10 831 if (region->depth == 8)
yading@10 832 map_table = map4to8;
yading@10 833 else
yading@10 834 map_table = NULL;
yading@10 835
yading@10 836 x_pos = dvbsub_read_4bit_string(pbuf + (y_pos * region->width),
yading@10 837 region->width, &buf, buf_end - buf,
yading@10 838 non_mod, map_table, x_pos);
yading@10 839 break;
yading@10 840 case 0x12:
yading@10 841 if (region->depth < 8) {
yading@10 842 av_log(avctx, AV_LOG_ERROR, "8-bit pixel string in %d-bit region!\n", region->depth);
yading@10 843 return;
yading@10 844 }
yading@10 845
yading@10 846 x_pos = dvbsub_read_8bit_string(pbuf + (y_pos * region->width),
yading@10 847 region->width, &buf, buf_end - buf,
yading@10 848 non_mod, NULL, x_pos);
yading@10 849 break;
yading@10 850
yading@10 851 case 0x20:
yading@10 852 map2to4[0] = (*buf) >> 4;
yading@10 853 map2to4[1] = (*buf++) & 0xf;
yading@10 854 map2to4[2] = (*buf) >> 4;
yading@10 855 map2to4[3] = (*buf++) & 0xf;
yading@10 856 break;
yading@10 857 case 0x21:
yading@10 858 for (i = 0; i < 4; i++)
yading@10 859 map2to8[i] = *buf++;
yading@10 860 break;
yading@10 861 case 0x22:
yading@10 862 for (i = 0; i < 16; i++)
yading@10 863 map4to8[i] = *buf++;
yading@10 864 break;
yading@10 865
yading@10 866 case 0xf0:
yading@10 867 x_pos = display->x_pos;
yading@10 868 y_pos += 2;
yading@10 869 break;
yading@10 870 default:
yading@10 871 av_log(avctx, AV_LOG_INFO, "Unknown/unsupported pixel block 0x%x\n", *(buf-1));
yading@10 872 }
yading@10 873 }
yading@10 874
yading@10 875 }
yading@10 876
yading@10 877 static void dvbsub_parse_object_segment(AVCodecContext *avctx,
yading@10 878 const uint8_t *buf, int buf_size)
yading@10 879 {
yading@10 880 DVBSubContext *ctx = avctx->priv_data;
yading@10 881
yading@10 882 const uint8_t *buf_end = buf + buf_size;
yading@10 883 int object_id;
yading@10 884 DVBSubObject *object;
yading@10 885 DVBSubObjectDisplay *display;
yading@10 886 int top_field_len, bottom_field_len;
yading@10 887
yading@10 888 int coding_method, non_modifying_color;
yading@10 889
yading@10 890 object_id = AV_RB16(buf);
yading@10 891 buf += 2;
yading@10 892
yading@10 893 object = get_object(ctx, object_id);
yading@10 894
yading@10 895 if (!object)
yading@10 896 return;
yading@10 897
yading@10 898 coding_method = ((*buf) >> 2) & 3;
yading@10 899 non_modifying_color = ((*buf++) >> 1) & 1;
yading@10 900
yading@10 901 if (coding_method == 0) {
yading@10 902 top_field_len = AV_RB16(buf);
yading@10 903 buf += 2;
yading@10 904 bottom_field_len = AV_RB16(buf);
yading@10 905 buf += 2;
yading@10 906
yading@10 907 if (buf + top_field_len + bottom_field_len > buf_end) {
yading@10 908 av_log(avctx, AV_LOG_ERROR, "Field data size too large\n");
yading@10 909 return;
yading@10 910 }
yading@10 911
yading@10 912 for (display = object->display_list; display; display = display->object_list_next) {
yading@10 913 const uint8_t *block = buf;
yading@10 914 int bfl = bottom_field_len;
yading@10 915
yading@10 916 dvbsub_parse_pixel_data_block(avctx, display, block, top_field_len, 0,
yading@10 917 non_modifying_color);
yading@10 918
yading@10 919 if (bottom_field_len > 0)
yading@10 920 block = buf + top_field_len;
yading@10 921 else
yading@10 922 bfl = top_field_len;
yading@10 923
yading@10 924 dvbsub_parse_pixel_data_block(avctx, display, block, bfl, 1,
yading@10 925 non_modifying_color);
yading@10 926 }
yading@10 927
yading@10 928 /* } else if (coding_method == 1) {*/
yading@10 929
yading@10 930 } else {
yading@10 931 av_log(avctx, AV_LOG_ERROR, "Unknown object coding %d\n", coding_method);
yading@10 932 }
yading@10 933
yading@10 934 }
yading@10 935
yading@10 936 static void dvbsub_parse_clut_segment(AVCodecContext *avctx,
yading@10 937 const uint8_t *buf, int buf_size)
yading@10 938 {
yading@10 939 DVBSubContext *ctx = avctx->priv_data;
yading@10 940
yading@10 941 const uint8_t *buf_end = buf + buf_size;
yading@10 942 int i, clut_id;
yading@10 943 int version;
yading@10 944 DVBSubCLUT *clut;
yading@10 945 int entry_id, depth , full_range;
yading@10 946 int y, cr, cb, alpha;
yading@10 947 int r, g, b, r_add, g_add, b_add;
yading@10 948
yading@10 949 av_dlog(avctx, "DVB clut packet:\n");
yading@10 950
yading@10 951 for (i=0; i < buf_size; i++) {
yading@10 952 av_dlog(avctx, "%02x ", buf[i]);
yading@10 953 if (i % 16 == 15)
yading@10 954 av_dlog(avctx, "\n");
yading@10 955 }
yading@10 956
yading@10 957 if (i % 16)
yading@10 958 av_dlog(avctx, "\n");
yading@10 959
yading@10 960 clut_id = *buf++;
yading@10 961 version = ((*buf)>>4)&15;
yading@10 962 buf += 1;
yading@10 963
yading@10 964 clut = get_clut(ctx, clut_id);
yading@10 965
yading@10 966 if (!clut) {
yading@10 967 clut = av_malloc(sizeof(DVBSubCLUT));
yading@10 968
yading@10 969 memcpy(clut, &default_clut, sizeof(DVBSubCLUT));
yading@10 970
yading@10 971 clut->id = clut_id;
yading@10 972 clut->version = -1;
yading@10 973
yading@10 974 clut->next = ctx->clut_list;
yading@10 975 ctx->clut_list = clut;
yading@10 976 }
yading@10 977
yading@10 978 if (clut->version != version) {
yading@10 979
yading@10 980 clut->version = version;
yading@10 981
yading@10 982 while (buf + 4 < buf_end) {
yading@10 983 entry_id = *buf++;
yading@10 984
yading@10 985 depth = (*buf) & 0xe0;
yading@10 986
yading@10 987 if (depth == 0) {
yading@10 988 av_log(avctx, AV_LOG_ERROR, "Invalid clut depth 0x%x!\n", *buf);
yading@10 989 return;
yading@10 990 }
yading@10 991
yading@10 992 full_range = (*buf++) & 1;
yading@10 993
yading@10 994 if (full_range) {
yading@10 995 y = *buf++;
yading@10 996 cr = *buf++;
yading@10 997 cb = *buf++;
yading@10 998 alpha = *buf++;
yading@10 999 } else {
yading@10 1000 y = buf[0] & 0xfc;
yading@10 1001 cr = (((buf[0] & 3) << 2) | ((buf[1] >> 6) & 3)) << 4;
yading@10 1002 cb = (buf[1] << 2) & 0xf0;
yading@10 1003 alpha = (buf[1] << 6) & 0xc0;
yading@10 1004
yading@10 1005 buf += 2;
yading@10 1006 }
yading@10 1007
yading@10 1008 if (y == 0)
yading@10 1009 alpha = 0xff;
yading@10 1010
yading@10 1011 YUV_TO_RGB1_CCIR(cb, cr);
yading@10 1012 YUV_TO_RGB2_CCIR(r, g, b, y);
yading@10 1013
yading@10 1014 av_dlog(avctx, "clut %d := (%d,%d,%d,%d)\n", entry_id, r, g, b, alpha);
yading@10 1015
yading@10 1016 if (depth & 0x80)
yading@10 1017 clut->clut4[entry_id] = RGBA(r,g,b,255 - alpha);
yading@10 1018 if (depth & 0x40)
yading@10 1019 clut->clut16[entry_id] = RGBA(r,g,b,255 - alpha);
yading@10 1020 if (depth & 0x20)
yading@10 1021 clut->clut256[entry_id] = RGBA(r,g,b,255 - alpha);
yading@10 1022 }
yading@10 1023 }
yading@10 1024 }
yading@10 1025
yading@10 1026
yading@10 1027 static void dvbsub_parse_region_segment(AVCodecContext *avctx,
yading@10 1028 const uint8_t *buf, int buf_size)
yading@10 1029 {
yading@10 1030 DVBSubContext *ctx = avctx->priv_data;
yading@10 1031
yading@10 1032 const uint8_t *buf_end = buf + buf_size;
yading@10 1033 int region_id, object_id;
yading@10 1034 int av_unused version;
yading@10 1035 DVBSubRegion *region;
yading@10 1036 DVBSubObject *object;
yading@10 1037 DVBSubObjectDisplay *display;
yading@10 1038 int fill;
yading@10 1039
yading@10 1040 if (buf_size < 10)
yading@10 1041 return;
yading@10 1042
yading@10 1043 region_id = *buf++;
yading@10 1044
yading@10 1045 region = get_region(ctx, region_id);
yading@10 1046
yading@10 1047 if (!region) {
yading@10 1048 region = av_mallocz(sizeof(DVBSubRegion));
yading@10 1049
yading@10 1050 region->id = region_id;
yading@10 1051 region->version = -1;
yading@10 1052
yading@10 1053 region->next = ctx->region_list;
yading@10 1054 ctx->region_list = region;
yading@10 1055 }
yading@10 1056
yading@10 1057 version = ((*buf)>>4) & 15;
yading@10 1058 fill = ((*buf++) >> 3) & 1;
yading@10 1059
yading@10 1060 region->width = AV_RB16(buf);
yading@10 1061 buf += 2;
yading@10 1062 region->height = AV_RB16(buf);
yading@10 1063 buf += 2;
yading@10 1064
yading@10 1065 if (region->width * region->height != region->buf_size) {
yading@10 1066 av_free(region->pbuf);
yading@10 1067
yading@10 1068 region->buf_size = region->width * region->height;
yading@10 1069
yading@10 1070 region->pbuf = av_malloc(region->buf_size);
yading@10 1071
yading@10 1072 fill = 1;
yading@10 1073 region->dirty = 0;
yading@10 1074 }
yading@10 1075
yading@10 1076 region->depth = 1 << (((*buf++) >> 2) & 7);
yading@10 1077 if(region->depth<2 || region->depth>8){
yading@10 1078 av_log(avctx, AV_LOG_ERROR, "region depth %d is invalid\n", region->depth);
yading@10 1079 region->depth= 4;
yading@10 1080 }
yading@10 1081 region->clut = *buf++;
yading@10 1082
yading@10 1083 if (region->depth == 8) {
yading@10 1084 region->bgcolor = *buf++;
yading@10 1085 buf += 1;
yading@10 1086 } else {
yading@10 1087 buf += 1;
yading@10 1088
yading@10 1089 if (region->depth == 4)
yading@10 1090 region->bgcolor = (((*buf++) >> 4) & 15);
yading@10 1091 else
yading@10 1092 region->bgcolor = (((*buf++) >> 2) & 3);
yading@10 1093 }
yading@10 1094
yading@10 1095 av_dlog(avctx, "Region %d, (%dx%d)\n", region_id, region->width, region->height);
yading@10 1096
yading@10 1097 if (fill) {
yading@10 1098 memset(region->pbuf, region->bgcolor, region->buf_size);
yading@10 1099 av_dlog(avctx, "Fill region (%d)\n", region->bgcolor);
yading@10 1100 }
yading@10 1101
yading@10 1102 delete_region_display_list(ctx, region);
yading@10 1103
yading@10 1104 while (buf + 5 < buf_end) {
yading@10 1105 object_id = AV_RB16(buf);
yading@10 1106 buf += 2;
yading@10 1107
yading@10 1108 object = get_object(ctx, object_id);
yading@10 1109
yading@10 1110 if (!object) {
yading@10 1111 object = av_mallocz(sizeof(DVBSubObject));
yading@10 1112
yading@10 1113 object->id = object_id;
yading@10 1114 object->next = ctx->object_list;
yading@10 1115 ctx->object_list = object;
yading@10 1116 }
yading@10 1117
yading@10 1118 object->type = (*buf) >> 6;
yading@10 1119
yading@10 1120 display = av_mallocz(sizeof(DVBSubObjectDisplay));
yading@10 1121
yading@10 1122 display->object_id = object_id;
yading@10 1123 display->region_id = region_id;
yading@10 1124
yading@10 1125 display->x_pos = AV_RB16(buf) & 0xfff;
yading@10 1126 buf += 2;
yading@10 1127 display->y_pos = AV_RB16(buf) & 0xfff;
yading@10 1128 buf += 2;
yading@10 1129
yading@10 1130 if ((object->type == 1 || object->type == 2) && buf+1 < buf_end) {
yading@10 1131 display->fgcolor = *buf++;
yading@10 1132 display->bgcolor = *buf++;
yading@10 1133 }
yading@10 1134
yading@10 1135 display->region_list_next = region->display_list;
yading@10 1136 region->display_list = display;
yading@10 1137
yading@10 1138 display->object_list_next = object->display_list;
yading@10 1139 object->display_list = display;
yading@10 1140 }
yading@10 1141 }
yading@10 1142
yading@10 1143 static void dvbsub_parse_page_segment(AVCodecContext *avctx,
yading@10 1144 const uint8_t *buf, int buf_size)
yading@10 1145 {
yading@10 1146 DVBSubContext *ctx = avctx->priv_data;
yading@10 1147 DVBSubRegionDisplay *display;
yading@10 1148 DVBSubRegionDisplay *tmp_display_list, **tmp_ptr;
yading@10 1149
yading@10 1150 const uint8_t *buf_end = buf + buf_size;
yading@10 1151 int region_id;
yading@10 1152 int page_state;
yading@10 1153 int timeout;
yading@10 1154 int version;
yading@10 1155
yading@10 1156 if (buf_size < 1)
yading@10 1157 return;
yading@10 1158
yading@10 1159 timeout = *buf++;
yading@10 1160 version = ((*buf)>>4) & 15;
yading@10 1161 page_state = ((*buf++) >> 2) & 3;
yading@10 1162
yading@10 1163 if (ctx->version != version) {
yading@10 1164
yading@10 1165 ctx->time_out = timeout;
yading@10 1166 ctx->version = version;
yading@10 1167
yading@10 1168 av_dlog(avctx, "Page time out %ds, state %d\n", ctx->time_out, page_state);
yading@10 1169
yading@10 1170 if (page_state == 1 || page_state == 2) {
yading@10 1171 delete_regions(ctx);
yading@10 1172 delete_objects(ctx);
yading@10 1173 delete_cluts(ctx);
yading@10 1174 }
yading@10 1175
yading@10 1176 tmp_display_list = ctx->display_list;
yading@10 1177 ctx->display_list = NULL;
yading@10 1178 ctx->display_list_size = 0;
yading@10 1179
yading@10 1180 while (buf + 5 < buf_end) {
yading@10 1181 region_id = *buf++;
yading@10 1182 buf += 1;
yading@10 1183
yading@10 1184 display = tmp_display_list;
yading@10 1185 tmp_ptr = &tmp_display_list;
yading@10 1186
yading@10 1187 while (display && display->region_id != region_id) {
yading@10 1188 tmp_ptr = &display->next;
yading@10 1189 display = display->next;
yading@10 1190 }
yading@10 1191
yading@10 1192 if (!display)
yading@10 1193 display = av_mallocz(sizeof(DVBSubRegionDisplay));
yading@10 1194
yading@10 1195 display->region_id = region_id;
yading@10 1196
yading@10 1197 display->x_pos = AV_RB16(buf);
yading@10 1198 buf += 2;
yading@10 1199 display->y_pos = AV_RB16(buf);
yading@10 1200 buf += 2;
yading@10 1201
yading@10 1202 *tmp_ptr = display->next;
yading@10 1203
yading@10 1204 display->next = ctx->display_list;
yading@10 1205 ctx->display_list = display;
yading@10 1206 ctx->display_list_size++;
yading@10 1207
yading@10 1208 av_dlog(avctx, "Region %d, (%d,%d)\n", region_id, display->x_pos, display->y_pos);
yading@10 1209 }
yading@10 1210
yading@10 1211 while (tmp_display_list) {
yading@10 1212 display = tmp_display_list;
yading@10 1213
yading@10 1214 tmp_display_list = display->next;
yading@10 1215
yading@10 1216 av_free(display);
yading@10 1217 }
yading@10 1218 }
yading@10 1219
yading@10 1220 }
yading@10 1221
yading@10 1222
yading@10 1223 #ifdef DEBUG
yading@10 1224 static void save_display_set(DVBSubContext *ctx)
yading@10 1225 {
yading@10 1226 DVBSubRegion *region;
yading@10 1227 DVBSubRegionDisplay *display;
yading@10 1228 DVBSubCLUT *clut;
yading@10 1229 uint32_t *clut_table;
yading@10 1230 int x_pos, y_pos, width, height;
yading@10 1231 int x, y, y_off, x_off;
yading@10 1232 uint32_t *pbuf;
yading@10 1233 char filename[32];
yading@10 1234 static int fileno_index = 0;
yading@10 1235
yading@10 1236 x_pos = -1;
yading@10 1237 y_pos = -1;
yading@10 1238 width = 0;
yading@10 1239 height = 0;
yading@10 1240
yading@10 1241 for (display = ctx->display_list; display; display = display->next) {
yading@10 1242 region = get_region(ctx, display->region_id);
yading@10 1243
yading@10 1244 if (x_pos == -1) {
yading@10 1245 x_pos = display->x_pos;
yading@10 1246 y_pos = display->y_pos;
yading@10 1247 width = region->width;
yading@10 1248 height = region->height;
yading@10 1249 } else {
yading@10 1250 if (display->x_pos < x_pos) {
yading@10 1251 width += (x_pos - display->x_pos);
yading@10 1252 x_pos = display->x_pos;
yading@10 1253 }
yading@10 1254
yading@10 1255 if (display->y_pos < y_pos) {
yading@10 1256 height += (y_pos - display->y_pos);
yading@10 1257 y_pos = display->y_pos;
yading@10 1258 }
yading@10 1259
yading@10 1260 if (display->x_pos + region->width > x_pos + width) {
yading@10 1261 width = display->x_pos + region->width - x_pos;
yading@10 1262 }
yading@10 1263
yading@10 1264 if (display->y_pos + region->height > y_pos + height) {
yading@10 1265 height = display->y_pos + region->height - y_pos;
yading@10 1266 }
yading@10 1267 }
yading@10 1268 }
yading@10 1269
yading@10 1270 if (x_pos >= 0) {
yading@10 1271
yading@10 1272 pbuf = av_malloc(width * height * 4);
yading@10 1273
yading@10 1274 for (display = ctx->display_list; display; display = display->next) {
yading@10 1275 region = get_region(ctx, display->region_id);
yading@10 1276
yading@10 1277 x_off = display->x_pos - x_pos;
yading@10 1278 y_off = display->y_pos - y_pos;
yading@10 1279
yading@10 1280 clut = get_clut(ctx, region->clut);
yading@10 1281
yading@10 1282 if (clut == 0)
yading@10 1283 clut = &default_clut;
yading@10 1284
yading@10 1285 switch (region->depth) {
yading@10 1286 case 2:
yading@10 1287 clut_table = clut->clut4;
yading@10 1288 break;
yading@10 1289 case 8:
yading@10 1290 clut_table = clut->clut256;
yading@10 1291 break;
yading@10 1292 case 4:
yading@10 1293 default:
yading@10 1294 clut_table = clut->clut16;
yading@10 1295 break;
yading@10 1296 }
yading@10 1297
yading@10 1298 for (y = 0; y < region->height; y++) {
yading@10 1299 for (x = 0; x < region->width; x++) {
yading@10 1300 pbuf[((y + y_off) * width) + x_off + x] =
yading@10 1301 clut_table[region->pbuf[y * region->width + x]];
yading@10 1302 }
yading@10 1303 }
yading@10 1304
yading@10 1305 }
yading@10 1306
yading@10 1307 snprintf(filename, sizeof(filename), "dvbs.%d", fileno_index);
yading@10 1308
yading@10 1309 png_save2(filename, pbuf, width, height);
yading@10 1310
yading@10 1311 av_free(pbuf);
yading@10 1312 }
yading@10 1313
yading@10 1314 fileno_index++;
yading@10 1315 }
yading@10 1316 #endif
yading@10 1317
yading@10 1318 static void dvbsub_parse_display_definition_segment(AVCodecContext *avctx,
yading@10 1319 const uint8_t *buf,
yading@10 1320 int buf_size)
yading@10 1321 {
yading@10 1322 DVBSubContext *ctx = avctx->priv_data;
yading@10 1323 DVBSubDisplayDefinition *display_def = ctx->display_definition;
yading@10 1324 int dds_version, info_byte;
yading@10 1325
yading@10 1326 if (buf_size < 5)
yading@10 1327 return;
yading@10 1328
yading@10 1329 info_byte = bytestream_get_byte(&buf);
yading@10 1330 dds_version = info_byte >> 4;
yading@10 1331 if (display_def && display_def->version == dds_version)
yading@10 1332 return; // already have this display definition version
yading@10 1333
yading@10 1334 if (!display_def) {
yading@10 1335 display_def = av_mallocz(sizeof(*display_def));
yading@10 1336 ctx->display_definition = display_def;
yading@10 1337 }
yading@10 1338 if (!display_def)
yading@10 1339 return;
yading@10 1340
yading@10 1341 display_def->version = dds_version;
yading@10 1342 display_def->x = 0;
yading@10 1343 display_def->y = 0;
yading@10 1344 display_def->width = bytestream_get_be16(&buf) + 1;
yading@10 1345 display_def->height = bytestream_get_be16(&buf) + 1;
yading@10 1346 if (!avctx->width || !avctx->height) {
yading@10 1347 avctx->width = display_def->width;
yading@10 1348 avctx->height = display_def->height;
yading@10 1349 }
yading@10 1350
yading@10 1351 if (buf_size < 13)
yading@10 1352 return;
yading@10 1353
yading@10 1354 if (info_byte & 1<<3) { // display_window_flag
yading@10 1355 display_def->x = bytestream_get_be16(&buf);
yading@10 1356 display_def->y = bytestream_get_be16(&buf);
yading@10 1357 display_def->width = bytestream_get_be16(&buf) - display_def->x + 1;
yading@10 1358 display_def->height = bytestream_get_be16(&buf) - display_def->y + 1;
yading@10 1359 }
yading@10 1360 }
yading@10 1361
yading@10 1362 static int dvbsub_display_end_segment(AVCodecContext *avctx, const uint8_t *buf,
yading@10 1363 int buf_size, AVSubtitle *sub)
yading@10 1364 {
yading@10 1365 DVBSubContext *ctx = avctx->priv_data;
yading@10 1366 DVBSubDisplayDefinition *display_def = ctx->display_definition;
yading@10 1367
yading@10 1368 DVBSubRegion *region;
yading@10 1369 DVBSubRegionDisplay *display;
yading@10 1370 AVSubtitleRect *rect;
yading@10 1371 DVBSubCLUT *clut;
yading@10 1372 uint32_t *clut_table;
yading@10 1373 int i;
yading@10 1374 int offset_x=0, offset_y=0;
yading@10 1375
yading@10 1376 sub->end_display_time = ctx->time_out * 1000;
yading@10 1377
yading@10 1378 if (display_def) {
yading@10 1379 offset_x = display_def->x;
yading@10 1380 offset_y = display_def->y;
yading@10 1381 }
yading@10 1382
yading@10 1383 sub->num_rects = ctx->display_list_size;
yading@10 1384
yading@10 1385 if (sub->num_rects > 0){
yading@10 1386 sub->rects = av_mallocz(sizeof(*sub->rects) * sub->num_rects);
yading@10 1387 for(i=0; i<sub->num_rects; i++)
yading@10 1388 sub->rects[i] = av_mallocz(sizeof(*sub->rects[i]));
yading@10 1389
yading@10 1390 i = 0;
yading@10 1391
yading@10 1392 for (display = ctx->display_list; display; display = display->next) {
yading@10 1393 region = get_region(ctx, display->region_id);
yading@10 1394
yading@10 1395 if (!region)
yading@10 1396 continue;
yading@10 1397
yading@10 1398 if (!region->dirty)
yading@10 1399 continue;
yading@10 1400
yading@10 1401 rect = sub->rects[i];
yading@10 1402 rect->x = display->x_pos + offset_x;
yading@10 1403 rect->y = display->y_pos + offset_y;
yading@10 1404 rect->w = region->width;
yading@10 1405 rect->h = region->height;
yading@10 1406 rect->nb_colors = (1 << region->depth);
yading@10 1407 rect->type = SUBTITLE_BITMAP;
yading@10 1408 rect->pict.linesize[0] = region->width;
yading@10 1409
yading@10 1410 clut = get_clut(ctx, region->clut);
yading@10 1411
yading@10 1412 if (!clut)
yading@10 1413 clut = &default_clut;
yading@10 1414
yading@10 1415 switch (region->depth) {
yading@10 1416 case 2:
yading@10 1417 clut_table = clut->clut4;
yading@10 1418 break;
yading@10 1419 case 8:
yading@10 1420 clut_table = clut->clut256;
yading@10 1421 break;
yading@10 1422 case 4:
yading@10 1423 default:
yading@10 1424 clut_table = clut->clut16;
yading@10 1425 break;
yading@10 1426 }
yading@10 1427
yading@10 1428 rect->pict.data[1] = av_mallocz(AVPALETTE_SIZE);
yading@10 1429 memcpy(rect->pict.data[1], clut_table, (1 << region->depth) * sizeof(uint32_t));
yading@10 1430
yading@10 1431 rect->pict.data[0] = av_malloc(region->buf_size);
yading@10 1432 memcpy(rect->pict.data[0], region->pbuf, region->buf_size);
yading@10 1433
yading@10 1434 i++;
yading@10 1435 }
yading@10 1436
yading@10 1437 sub->num_rects = i;
yading@10 1438 }
yading@10 1439 #ifdef DEBUG
yading@10 1440 save_display_set(ctx);
yading@10 1441 #endif
yading@10 1442
yading@10 1443 return 1;
yading@10 1444 }
yading@10 1445
yading@10 1446 static int dvbsub_decode(AVCodecContext *avctx,
yading@10 1447 void *data, int *data_size,
yading@10 1448 AVPacket *avpkt)
yading@10 1449 {
yading@10 1450 const uint8_t *buf = avpkt->data;
yading@10 1451 int buf_size = avpkt->size;
yading@10 1452 DVBSubContext *ctx = avctx->priv_data;
yading@10 1453 AVSubtitle *sub = data;
yading@10 1454 const uint8_t *p, *p_end;
yading@10 1455 int segment_type;
yading@10 1456 int page_id;
yading@10 1457 int segment_length;
yading@10 1458 int i;
yading@10 1459 int got_segment = 0;
yading@10 1460
yading@10 1461 av_dlog(avctx, "DVB sub packet:\n");
yading@10 1462
yading@10 1463 for (i=0; i < buf_size; i++) {
yading@10 1464 av_dlog(avctx, "%02x ", buf[i]);
yading@10 1465 if (i % 16 == 15)
yading@10 1466 av_dlog(avctx, "\n");
yading@10 1467 }
yading@10 1468
yading@10 1469 if (i % 16)
yading@10 1470 av_dlog(avctx, "\n");
yading@10 1471
yading@10 1472 if (buf_size <= 6 || *buf != 0x0f) {
yading@10 1473 av_dlog(avctx, "incomplete or broken packet");
yading@10 1474 return -1;
yading@10 1475 }
yading@10 1476
yading@10 1477 p = buf;
yading@10 1478 p_end = buf + buf_size;
yading@10 1479
yading@10 1480 while (p_end - p >= 6 && *p == 0x0f) {
yading@10 1481 p += 1;
yading@10 1482 segment_type = *p++;
yading@10 1483 page_id = AV_RB16(p);
yading@10 1484 p += 2;
yading@10 1485 segment_length = AV_RB16(p);
yading@10 1486 p += 2;
yading@10 1487
yading@10 1488 if (p_end - p < segment_length) {
yading@10 1489 av_dlog(avctx, "incomplete or broken packet");
yading@10 1490 return -1;
yading@10 1491 }
yading@10 1492
yading@10 1493 if (page_id == ctx->composition_id || page_id == ctx->ancillary_id ||
yading@10 1494 ctx->composition_id == -1 || ctx->ancillary_id == -1) {
yading@10 1495 switch (segment_type) {
yading@10 1496 case DVBSUB_PAGE_SEGMENT:
yading@10 1497 dvbsub_parse_page_segment(avctx, p, segment_length);
yading@10 1498 got_segment |= 1;
yading@10 1499 break;
yading@10 1500 case DVBSUB_REGION_SEGMENT:
yading@10 1501 dvbsub_parse_region_segment(avctx, p, segment_length);
yading@10 1502 got_segment |= 2;
yading@10 1503 break;
yading@10 1504 case DVBSUB_CLUT_SEGMENT:
yading@10 1505 dvbsub_parse_clut_segment(avctx, p, segment_length);
yading@10 1506 got_segment |= 4;
yading@10 1507 break;
yading@10 1508 case DVBSUB_OBJECT_SEGMENT:
yading@10 1509 dvbsub_parse_object_segment(avctx, p, segment_length);
yading@10 1510 got_segment |= 8;
yading@10 1511 break;
yading@10 1512 case DVBSUB_DISPLAYDEFINITION_SEGMENT:
yading@10 1513 dvbsub_parse_display_definition_segment(avctx, p, segment_length);
yading@10 1514 break;
yading@10 1515 case DVBSUB_DISPLAY_SEGMENT:
yading@10 1516 *data_size = dvbsub_display_end_segment(avctx, p, segment_length, sub);
yading@10 1517 got_segment |= 16;
yading@10 1518 break;
yading@10 1519 default:
yading@10 1520 av_dlog(avctx, "Subtitling segment type 0x%x, page id %d, length %d\n",
yading@10 1521 segment_type, page_id, segment_length);
yading@10 1522 break;
yading@10 1523 }
yading@10 1524 }
yading@10 1525
yading@10 1526 p += segment_length;
yading@10 1527 }
yading@10 1528 // Some streams do not send a display segment but if we have all the other
yading@10 1529 // segments then we need no further data.
yading@10 1530 if (got_segment == 15 && sub)
yading@10 1531 *data_size = dvbsub_display_end_segment(avctx, p, 0, sub);
yading@10 1532
yading@10 1533 return p - buf;
yading@10 1534 }
yading@10 1535
yading@10 1536
yading@10 1537 AVCodec ff_dvbsub_decoder = {
yading@10 1538 .name = "dvbsub",
yading@10 1539 .type = AVMEDIA_TYPE_SUBTITLE,
yading@10 1540 .id = AV_CODEC_ID_DVB_SUBTITLE,
yading@10 1541 .priv_data_size = sizeof(DVBSubContext),
yading@10 1542 .init = dvbsub_init_decoder,
yading@10 1543 .close = dvbsub_close_decoder,
yading@10 1544 .decode = dvbsub_decode,
yading@10 1545 .long_name = NULL_IF_CONFIG_SMALL("DVB subtitles"),
yading@10 1546 };