dvbsubdec.c 40 KB
Newer Older
1
/*
2
 * DVB subtitle decoding
3
 * Copyright (c) 2005 Ian Caulfield
4
 *
5
 * This file is part of Libav.
6
 *
7
 * Libav is free software; you can redistribute it and/or
8 9
 * modify it under the terms of the GNU Lesser General Public
 * 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
 * Libav is distributed in the hope that it will be useful,
13 14 15 16 17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with Libav; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 21 22
 */
#include "avcodec.h"
#include "dsputil.h"
23
#include "get_bits.h"
24
#include "bytestream.h"
25
#include "libavutil/colorspace.h"
26 27 28 29 30

#define DVBSUB_PAGE_SEGMENT     0x10
#define DVBSUB_REGION_SEGMENT   0x11
#define DVBSUB_CLUT_SEGMENT     0x12
#define DVBSUB_OBJECT_SEGMENT   0x13
31
#define DVBSUB_DISPLAYDEFINITION_SEGMENT 0x14
32 33
#define DVBSUB_DISPLAY_SEGMENT  0x80

34
#define cm (ff_cropTbl + MAX_NEG_CROP)
35

36
#ifdef DEBUG
37
#undef fprintf
38
#undef perror
39 40 41 42 43 44 45 46
#if 0
static void png_save(const char *filename, uint8_t *bitmap, int w, int h,
                     uint32_t *rgba_palette)
{
    int x, y, v;
    FILE *f;
    char fname[40], fname2[40];
    char command[1024];
47

48 49 50 51 52
    snprintf(fname, 40, "%s.ppm", filename);

    f = fopen(fname, "w");
    if (!f) {
        perror(fname);
53
        return;
54 55 56 57 58 59 60 61 62 63 64 65 66 67
    }
    fprintf(f, "P6\n"
            "%d %d\n"
            "%d\n",
            w, h, 255);
    for(y = 0; y < h; y++) {
        for(x = 0; x < w; x++) {
            v = rgba_palette[bitmap[y * w + x]];
            putc((v >> 16) & 0xff, f);
            putc((v >> 8) & 0xff, f);
            putc((v >> 0) & 0xff, f);
        }
    }
    fclose(f);
68 69


70 71 72 73 74
    snprintf(fname2, 40, "%s-a.pgm", filename);

    f = fopen(fname2, "w");
    if (!f) {
        perror(fname2);
75
        return;
76 77 78 79 80 81 82 83 84 85 86 87
    }
    fprintf(f, "P5\n"
            "%d %d\n"
            "%d\n",
            w, h, 255);
    for(y = 0; y < h; y++) {
        for(x = 0; x < w; x++) {
            v = rgba_palette[bitmap[y * w + x]];
            putc((v >> 24) & 0xff, f);
        }
    }
    fclose(f);
88

89 90
    snprintf(command, 1024, "pnmtopng -alpha %s %s > %s.png 2> /dev/null", fname2, fname, filename);
    system(command);
91

92 93 94 95 96 97 98 99 100 101 102
    snprintf(command, 1024, "rm %s %s", fname, fname2);
    system(command);
}
#endif

static void png_save2(const char *filename, uint32_t *bitmap, int w, int h)
{
    int x, y, v;
    FILE *f;
    char fname[40], fname2[40];
    char command[1024];
103

104
    snprintf(fname, sizeof(fname), "%s.ppm", filename);
105 106 107 108

    f = fopen(fname, "w");
    if (!f) {
        perror(fname);
109
        return;
110 111 112 113 114 115 116 117 118 119 120 121 122 123
    }
    fprintf(f, "P6\n"
            "%d %d\n"
            "%d\n",
            w, h, 255);
    for(y = 0; y < h; y++) {
        for(x = 0; x < w; x++) {
            v = bitmap[y * w + x];
            putc((v >> 16) & 0xff, f);
            putc((v >> 8) & 0xff, f);
            putc((v >> 0) & 0xff, f);
        }
    }
    fclose(f);
124 125


126
    snprintf(fname2, sizeof(fname2), "%s-a.pgm", filename);
127 128 129 130

    f = fopen(fname2, "w");
    if (!f) {
        perror(fname2);
131
        return;
132 133 134 135 136 137 138 139 140 141 142 143
    }
    fprintf(f, "P5\n"
            "%d %d\n"
            "%d\n",
            w, h, 255);
    for(y = 0; y < h; y++) {
        for(x = 0; x < w; x++) {
            v = bitmap[y * w + x];
            putc((v >> 24) & 0xff, f);
        }
    }
    fclose(f);
144

145
    snprintf(command, sizeof(command), "pnmtopng -alpha %s %s > %s.png 2> /dev/null", fname2, fname, filename);
146
    system(command);
147

148
    snprintf(command, sizeof(command), "rm %s %s", fname, fname2);
149 150 151 152
    system(command);
}
#endif

153
#define RGBA(r,g,b,a) (((unsigned)(a) << 24) | ((r) << 16) | ((g) << 8) | (b))
154 155 156 157 158 159 160

typedef struct DVBSubCLUT {
    int id;

    uint32_t clut4[4];
    uint32_t clut16[16];
    uint32_t clut256[256];
161

162 163 164 165 166 167 168 169 170 171 172 173
    struct DVBSubCLUT *next;
} DVBSubCLUT;

static DVBSubCLUT default_clut;

typedef struct DVBSubObjectDisplay {
    int object_id;
    int region_id;

    int x_pos;
    int y_pos;

174 175
    int fgcolor;
    int bgcolor;
176

177
    struct DVBSubObjectDisplay *region_list_next;
178
    struct DVBSubObjectDisplay *object_list_next;
179 180 181 182 183 184
} DVBSubObjectDisplay;

typedef struct DVBSubObject {
    int id;

    int type;
185 186 187

    DVBSubObjectDisplay *display_list;

188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
    struct DVBSubObject *next;
} DVBSubObject;

typedef struct DVBSubRegionDisplay {
    int region_id;

    int x_pos;
    int y_pos;

    struct DVBSubRegionDisplay *next;
} DVBSubRegionDisplay;

typedef struct DVBSubRegion {
    int id;

    int width;
    int height;
    int depth;
206

207
    int clut;
208
    int bgcolor;
209

210 211 212 213
    uint8_t *pbuf;
    int buf_size;

    DVBSubObjectDisplay *display_list;
214

215 216 217
    struct DVBSubRegion *next;
} DVBSubRegion;

218 219 220 221 222 223 224 225 226
typedef struct DVBSubDisplayDefinition {
    int version;

    int x;
    int y;
    int width;
    int height;
} DVBSubDisplayDefinition;

227 228 229 230 231 232 233 234
typedef struct DVBSubContext {
    int composition_id;
    int ancillary_id;

    int time_out;
    DVBSubRegion *region_list;
    DVBSubCLUT   *clut_list;
    DVBSubObject *object_list;
235

236 237
    int display_list_size;
    DVBSubRegionDisplay *display_list;
238
    DVBSubDisplayDefinition *display_definition;
239 240 241 242 243 244 245
} DVBSubContext;


static DVBSubObject* get_object(DVBSubContext *ctx, int object_id)
{
    DVBSubObject *ptr = ctx->object_list;

246
    while (ptr && ptr->id != object_id) {
247 248
        ptr = ptr->next;
    }
249

250 251 252 253 254 255 256
    return ptr;
}

static DVBSubCLUT* get_clut(DVBSubContext *ctx, int clut_id)
{
    DVBSubCLUT *ptr = ctx->clut_list;

257
    while (ptr && ptr->id != clut_id) {
258 259
        ptr = ptr->next;
    }
260

261 262 263 264 265 266 267
    return ptr;
}

static DVBSubRegion* get_region(DVBSubContext *ctx, int region_id)
{
    DVBSubRegion *ptr = ctx->region_list;

268
    while (ptr && ptr->id != region_id) {
269 270
        ptr = ptr->next;
    }
271

272 273 274 275 276 277 278 279
    return ptr;
}

static void delete_region_display_list(DVBSubContext *ctx, DVBSubRegion *region)
{
    DVBSubObject *object, *obj2, **obj2_ptr;
    DVBSubObjectDisplay *display, *obj_disp, **obj_disp_ptr;

280
    while (region->display_list) {
281
        display = region->display_list;
282

283
        object = get_object(ctx, display->object_id);
284

285
        if (object) {
286
            obj_disp_ptr = &object->display_list;
287
            obj_disp = *obj_disp_ptr;
288

289
            while (obj_disp && obj_disp != display) {
290
                obj_disp_ptr = &obj_disp->object_list_next;
291
                obj_disp = *obj_disp_ptr;
292
            }
293

294 295
            if (obj_disp) {
                *obj_disp_ptr = obj_disp->object_list_next;
296

297
                if (!object->display_list) {
298
                    obj2_ptr = &ctx->object_list;
299
                    obj2 = *obj2_ptr;
300

Michael Niedermayer's avatar
Michael Niedermayer committed
301 302
                    while (obj2 != object) {
                        assert(obj2);
303
                        obj2_ptr = &obj2->next;
304
                        obj2 = *obj2_ptr;
305
                    }
306

307
                    *obj2_ptr = obj2->next;
308

309 310 311 312
                    av_free(obj2);
                }
            }
        }
313

314
        region->display_list = display->region_list_next;
315

316 317
        av_free(display);
    }
318

319 320 321 322 323 324
}

static void delete_state(DVBSubContext *ctx)
{
    DVBSubRegion *region;
    DVBSubCLUT *clut;
325

326
    while (ctx->region_list) {
327 328 329 330 331
        region = ctx->region_list;

        ctx->region_list = region->next;

        delete_region_display_list(ctx, region);
332
        av_free(region->pbuf);
333 334 335
        av_free(region);
    }

336
    while (ctx->clut_list) {
337 338 339 340 341 342 343
        clut = ctx->clut_list;

        ctx->clut_list = clut->next;

        av_free(clut);
    }

344 345
    av_freep(&ctx->display_definition);

346
    /* Should already be null */
347
    if (ctx->object_list)
348 349 350
        av_log(0, AV_LOG_ERROR, "Memory deallocation error!\n");
}

351
static av_cold int dvbsub_init_decoder(AVCodecContext *avctx)
352 353
{
    int i, r, g, b, a = 0;
354
    DVBSubContext *ctx = avctx->priv_data;
355

356 357 358 359 360 361 362 363
    if (!avctx->extradata || avctx->extradata_size != 4) {
        av_log(avctx, AV_LOG_WARNING, "Invalid extradata, subtitle streams may be combined!\n");
        ctx->composition_id = -1;
        ctx->ancillary_id   = -1;
    } else {
        ctx->composition_id = AV_RB16(avctx->extradata);
        ctx->ancillary_id   = AV_RB16(avctx->extradata + 2);
    }
364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382

    default_clut.id = -1;
    default_clut.next = NULL;

    default_clut.clut4[0] = RGBA(  0,   0,   0,   0);
    default_clut.clut4[1] = RGBA(255, 255, 255, 255);
    default_clut.clut4[2] = RGBA(  0,   0,   0, 255);
    default_clut.clut4[3] = RGBA(127, 127, 127, 255);

    default_clut.clut16[0] = RGBA(  0,   0,   0,   0);
    for (i = 1; i < 16; i++) {
        if (i < 8) {
            r = (i & 1) ? 255 : 0;
            g = (i & 2) ? 255 : 0;
            b = (i & 4) ? 255 : 0;
        } else {
            r = (i & 1) ? 127 : 0;
            g = (i & 2) ? 127 : 0;
            b = (i & 4) ? 127 : 0;
383
        }
384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420
        default_clut.clut16[i] = RGBA(r, g, b, 255);
    }

    default_clut.clut256[0] = RGBA(  0,   0,   0,   0);
    for (i = 1; i < 256; i++) {
        if (i < 8) {
            r = (i & 1) ? 255 : 0;
            g = (i & 2) ? 255 : 0;
            b = (i & 4) ? 255 : 0;
            a = 63;
        } else {
            switch (i & 0x88) {
            case 0x00:
                r = ((i & 1) ? 85 : 0) + ((i & 0x10) ? 170 : 0);
                g = ((i & 2) ? 85 : 0) + ((i & 0x20) ? 170 : 0);
                b = ((i & 4) ? 85 : 0) + ((i & 0x40) ? 170 : 0);
                a = 255;
                break;
            case 0x08:
                r = ((i & 1) ? 85 : 0) + ((i & 0x10) ? 170 : 0);
                g = ((i & 2) ? 85 : 0) + ((i & 0x20) ? 170 : 0);
                b = ((i & 4) ? 85 : 0) + ((i & 0x40) ? 170 : 0);
                a = 127;
                break;
            case 0x80:
                r = 127 + ((i & 1) ? 43 : 0) + ((i & 0x10) ? 85 : 0);
                g = 127 + ((i & 2) ? 43 : 0) + ((i & 0x20) ? 85 : 0);
                b = 127 + ((i & 4) ? 43 : 0) + ((i & 0x40) ? 85 : 0);
                a = 255;
                break;
            case 0x88:
                r = ((i & 1) ? 43 : 0) + ((i & 0x10) ? 85 : 0);
                g = ((i & 2) ? 43 : 0) + ((i & 0x20) ? 85 : 0);
                b = ((i & 4) ? 43 : 0) + ((i & 0x40) ? 85 : 0);
                a = 255;
                break;
            }
421
        }
422 423 424 425 426 427
        default_clut.clut256[i] = RGBA(r, g, b, a);
    }

    return 0;
}

428
static av_cold int dvbsub_close_decoder(AVCodecContext *avctx)
429
{
430
    DVBSubContext *ctx = avctx->priv_data;
431 432 433
    DVBSubRegionDisplay *display;

    delete_state(ctx);
434

435
    while (ctx->display_list) {
436 437
        display = ctx->display_list;
        ctx->display_list = display->next;
438

439 440 441 442 443 444
        av_free(display);
    }

    return 0;
}

445
static int dvbsub_read_2bit_string(uint8_t *destbuf, int dbuf_len,
Michael Niedermayer's avatar
Michael Niedermayer committed
446
                                   const uint8_t **srcbuf, int buf_size,
447 448 449
                                   int non_mod, uint8_t *map_table)
{
    GetBitContext gb;
450

451 452 453
    int bits;
    int run_length;
    int pixels_read = 0;
454

455
    init_get_bits(&gb, *srcbuf, buf_size << 3);
456

457
    while (get_bits_count(&gb) < buf_size << 3 && pixels_read < dbuf_len) {
458 459
        bits = get_bits(&gb, 2);

460
        if (bits) {
461
            if (non_mod != 1 || bits != 1) {
462
                if (map_table)
463 464 465 466 467 468
                    *destbuf++ = map_table[bits];
                else
                    *destbuf++ = bits;
            }
            pixels_read++;
        } else {
469
            bits = get_bits1(&gb);
470 471 472
            if (bits == 1) {
                run_length = get_bits(&gb, 3) + 3;
                bits = get_bits(&gb, 2);
473

474 475 476
                if (non_mod == 1 && bits == 1)
                    pixels_read += run_length;
                else {
477
                    if (map_table)
478 479 480 481 482 483 484
                        bits = map_table[bits];
                    while (run_length-- > 0 && pixels_read < dbuf_len) {
                        *destbuf++ = bits;
                        pixels_read++;
                    }
                }
            } else {
485
                bits = get_bits1(&gb);
486 487 488 489 490 491 492 493 494
                if (bits == 0) {
                    bits = get_bits(&gb, 2);
                    if (bits == 2) {
                        run_length = get_bits(&gb, 4) + 12;
                        bits = get_bits(&gb, 2);

                        if (non_mod == 1 && bits == 1)
                            pixels_read += run_length;
                        else {
495
                            if (map_table)
496 497 498 499 500 501 502 503 504 505 506 507 508
                                bits = map_table[bits];
                            while (run_length-- > 0 && pixels_read < dbuf_len) {
                                *destbuf++ = bits;
                                pixels_read++;
                            }
                        }
                    } else if (bits == 3) {
                        run_length = get_bits(&gb, 8) + 29;
                        bits = get_bits(&gb, 2);

                        if (non_mod == 1 && bits == 1)
                            pixels_read += run_length;
                        else {
509
                            if (map_table)
510 511 512 513 514 515 516 517
                                bits = map_table[bits];
                            while (run_length-- > 0 && pixels_read < dbuf_len) {
                                *destbuf++ = bits;
                                pixels_read++;
                            }
                        }
                    } else if (bits == 1) {
                        pixels_read += 2;
518
                        if (map_table)
519 520 521 522 523 524 525 526 527 528 529 530
                            bits = map_table[0];
                        else
                            bits = 0;
                        if (pixels_read <= dbuf_len) {
                            *destbuf++ = bits;
                            *destbuf++ = bits;
                        }
                    } else {
                        (*srcbuf) += (get_bits_count(&gb) + 7) >> 3;
                        return pixels_read;
                    }
                } else {
531
                    if (map_table)
532 533 534 535 536 537 538 539 540
                        bits = map_table[0];
                    else
                        bits = 0;
                    *destbuf++ = bits;
                    pixels_read++;
                }
            }
        }
    }
541

542
    if (get_bits(&gb, 6))
543 544 545 546 547 548
        av_log(0, AV_LOG_ERROR, "DVBSub error: line overflow\n");

    (*srcbuf) += (get_bits_count(&gb) + 7) >> 3;

    return pixels_read;
}
549 550

static int dvbsub_read_4bit_string(uint8_t *destbuf, int dbuf_len,
Michael Niedermayer's avatar
Michael Niedermayer committed
551
                                   const uint8_t **srcbuf, int buf_size,
552 553 554
                                   int non_mod, uint8_t *map_table)
{
    GetBitContext gb;
555

556 557 558
    int bits;
    int run_length;
    int pixels_read = 0;
559

560
    init_get_bits(&gb, *srcbuf, buf_size << 3);
561

562
    while (get_bits_count(&gb) < buf_size << 3 && pixels_read < dbuf_len) {
563 564
        bits = get_bits(&gb, 4);

565
        if (bits) {
566
            if (non_mod != 1 || bits != 1) {
567
                if (map_table)
568 569 570 571 572 573
                    *destbuf++ = map_table[bits];
                else
                    *destbuf++ = bits;
            }
            pixels_read++;
        } else {
574
            bits = get_bits1(&gb);
575 576
            if (bits == 0) {
                run_length = get_bits(&gb, 3);
577

578 579 580 581
                if (run_length == 0) {
                    (*srcbuf) += (get_bits_count(&gb) + 7) >> 3;
                    return pixels_read;
                }
582

583
                run_length += 2;
584

585
                if (map_table)
586 587 588
                    bits = map_table[0];
                else
                    bits = 0;
589

590 591 592 593 594
                while (run_length-- > 0 && pixels_read < dbuf_len) {
                    *destbuf++ = bits;
                    pixels_read++;
                }
            } else {
595
                bits = get_bits1(&gb);
596 597 598 599 600 601 602
                if (bits == 0) {
                    run_length = get_bits(&gb, 2) + 4;
                    bits = get_bits(&gb, 4);

                    if (non_mod == 1 && bits == 1)
                        pixels_read += run_length;
                    else {
603
                        if (map_table)
604 605 606 607 608 609 610 611 612 613 614
                            bits = map_table[bits];
                        while (run_length-- > 0 && pixels_read < dbuf_len) {
                            *destbuf++ = bits;
                            pixels_read++;
                        }
                    }
                } else {
                    bits = get_bits(&gb, 2);
                    if (bits == 2) {
                        run_length = get_bits(&gb, 4) + 9;
                        bits = get_bits(&gb, 4);
615

616 617 618
                        if (non_mod == 1 && bits == 1)
                            pixels_read += run_length;
                        else {
619
                            if (map_table)
620 621 622 623 624 625 626 627 628 629 630 631 632
                                bits = map_table[bits];
                            while (run_length-- > 0 && pixels_read < dbuf_len) {
                                *destbuf++ = bits;
                                pixels_read++;
                            }
                        }
                    } else if (bits == 3) {
                        run_length = get_bits(&gb, 8) + 25;
                        bits = get_bits(&gb, 4);

                        if (non_mod == 1 && bits == 1)
                            pixels_read += run_length;
                        else {
633
                            if (map_table)
634 635 636 637 638 639 640 641
                                bits = map_table[bits];
                            while (run_length-- > 0 && pixels_read < dbuf_len) {
                                *destbuf++ = bits;
                                pixels_read++;
                            }
                        }
                    } else if (bits == 1) {
                        pixels_read += 2;
642
                        if (map_table)
643 644 645 646 647 648 649 650
                            bits = map_table[0];
                        else
                            bits = 0;
                        if (pixels_read <= dbuf_len) {
                            *destbuf++ = bits;
                            *destbuf++ = bits;
                        }
                    } else {
651
                        if (map_table)
652 653 654 655 656 657 658 659 660 661
                            bits = map_table[0];
                        else
                            bits = 0;
                        *destbuf++ = bits;
                        pixels_read ++;
                    }
                }
            }
        }
    }
662

663
    if (get_bits(&gb, 8))
664
        av_log(0, AV_LOG_ERROR, "DVBSub error: line overflow\n");
665

666 667 668 669
    (*srcbuf) += (get_bits_count(&gb) + 7) >> 3;

    return pixels_read;
}
670 671

static int dvbsub_read_8bit_string(uint8_t *destbuf, int dbuf_len,
Michael Niedermayer's avatar
Michael Niedermayer committed
672
                                    const uint8_t **srcbuf, int buf_size,
673 674
                                    int non_mod, uint8_t *map_table)
{
Michael Niedermayer's avatar
Michael Niedermayer committed
675
    const uint8_t *sbuf_end = (*srcbuf) + buf_size;
676 677 678
    int bits;
    int run_length;
    int pixels_read = 0;
679

680 681
    while (*srcbuf < sbuf_end && pixels_read < dbuf_len) {
        bits = *(*srcbuf)++;
682

683
        if (bits) {
684
            if (non_mod != 1 || bits != 1) {
685
                if (map_table)
686 687 688 689 690 691 692 693 694 695 696 697
                    *destbuf++ = map_table[bits];
                else
                    *destbuf++ = bits;
            }
            pixels_read++;
        } else {
            bits = *(*srcbuf)++;
            run_length = bits & 0x7f;
            if ((bits & 0x80) == 0) {
                if (run_length == 0) {
                    return pixels_read;
                }
698

699
                if (map_table)
700 701 702 703 704 705 706 707 708 709 710 711
                    bits = map_table[0];
                else
                    bits = 0;
                while (run_length-- > 0 && pixels_read < dbuf_len) {
                    *destbuf++ = bits;
                    pixels_read++;
                }
            } else {
                bits = *(*srcbuf)++;

                if (non_mod == 1 && bits == 1)
                    pixels_read += run_length;
712
                if (map_table)
713 714 715 716 717 718 719 720
                    bits = map_table[bits];
                else while (run_length-- > 0 && pixels_read < dbuf_len) {
                    *destbuf++ = bits;
                    pixels_read++;
                }
            }
        }
    }
721

722
    if (*(*srcbuf)++)
723
        av_log(0, AV_LOG_ERROR, "DVBSub error: line overflow\n");
724

725 726
    return pixels_read;
}
727

728 729 730


static void dvbsub_parse_pixel_data_block(AVCodecContext *avctx, DVBSubObjectDisplay *display,
Michael Niedermayer's avatar
Michael Niedermayer committed
731
                                          const uint8_t *buf, int buf_size, int top_bottom, int non_mod)
732
{
733
    DVBSubContext *ctx = avctx->priv_data;
734 735

    DVBSubRegion *region = get_region(ctx, display->region_id);
Michael Niedermayer's avatar
Michael Niedermayer committed
736
    const uint8_t *buf_end = buf + buf_size;
737 738 739
    uint8_t *pbuf;
    int x_pos, y_pos;
    int i;
740

741 742
    uint8_t map2to4[] = { 0x0,  0x7,  0x8,  0xf};
    uint8_t map2to8[] = {0x00, 0x77, 0x88, 0xff};
743
    uint8_t map4to8[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
744 745
                         0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
    uint8_t *map_table;
746

747
    av_dlog(avctx, "DVB pixel block size %d, %s field:\n", buf_size,
748
            top_bottom ? "bottom" : "top");
749

750
    for (i = 0; i < buf_size; i++) {
751
        if (i % 16 == 0)
752
            av_dlog(avctx, "0x%8p: ", buf+i);
753

754
        av_dlog(avctx, "%02x ", buf[i]);
755
        if (i % 16 == 15)
756
            av_dlog(avctx, "\n");
757
    }
758

759
    if (i % 16)
760
        av_dlog(avctx, "\n");
761 762 763

    if (region == 0)
        return;
764

765
    pbuf = region->pbuf;
766

767 768
    x_pos = display->x_pos;
    y_pos = display->y_pos;
769

770 771 772 773 774 775 776 777
    if ((y_pos & 1) != top_bottom)
        y_pos++;

    while (buf < buf_end) {
        if (x_pos > region->width || y_pos > region->height) {
            av_log(avctx, AV_LOG_ERROR, "Invalid object location!\n");
            return;
        }
778

779 780 781 782 783 784 785 786
        switch (*buf++) {
        case 0x10:
            if (region->depth == 8)
                map_table = map2to8;
            else if (region->depth == 4)
                map_table = map2to4;
            else
                map_table = NULL;
787 788

            x_pos += dvbsub_read_2bit_string(pbuf + (y_pos * region->width) + x_pos,
789
                                                region->width - x_pos, &buf, buf_end - buf,
790 791 792 793 794 795 796
                                                non_mod, map_table);
            break;
        case 0x11:
            if (region->depth < 4) {
                av_log(avctx, AV_LOG_ERROR, "4-bit pixel string in %d-bit region!\n", region->depth);
                return;
            }
797

798 799 800 801
            if (region->depth == 8)
                map_table = map4to8;
            else
                map_table = NULL;
802 803

            x_pos += dvbsub_read_4bit_string(pbuf + (y_pos * region->width) + x_pos,
804
                                                region->width - x_pos, &buf, buf_end - buf,
805 806 807 808 809 810 811
                                                non_mod, map_table);
            break;
        case 0x12:
            if (region->depth < 8) {
                av_log(avctx, AV_LOG_ERROR, "8-bit pixel string in %d-bit region!\n", region->depth);
                return;
            }
812 813

            x_pos += dvbsub_read_8bit_string(pbuf + (y_pos * region->width) + x_pos,
814
                                                region->width - x_pos, &buf, buf_end - buf,
815 816
                                                non_mod, NULL);
            break;
817

818 819 820 821 822 823 824 825 826 827 828 829 830 831
        case 0x20:
            map2to4[0] = (*buf) >> 4;
            map2to4[1] = (*buf++) & 0xf;
            map2to4[2] = (*buf) >> 4;
            map2to4[3] = (*buf++) & 0xf;
            break;
        case 0x21:
            for (i = 0; i < 4; i++)
                map2to8[i] = *buf++;
            break;
        case 0x22:
            for (i = 0; i < 16; i++)
                map4to8[i] = *buf++;
            break;
832

833 834 835 836 837 838 839 840
        case 0xf0:
            x_pos = display->x_pos;
            y_pos += 2;
            break;
        default:
            av_log(avctx, AV_LOG_INFO, "Unknown/unsupported pixel block 0x%x\n", *(buf-1));
        }
    }
841

842 843 844
}

static void dvbsub_parse_object_segment(AVCodecContext *avctx,
Michael Niedermayer's avatar
Michael Niedermayer committed
845
                                        const uint8_t *buf, int buf_size)
846
{
847
    DVBSubContext *ctx = avctx->priv_data;
848

Michael Niedermayer's avatar
Michael Niedermayer committed
849 850
    const uint8_t *buf_end = buf + buf_size;
    const uint8_t *block;
851 852 853 854
    int object_id;
    DVBSubObject *object;
    DVBSubObjectDisplay *display;
    int top_field_len, bottom_field_len;
855

856
    int coding_method, non_modifying_color;
857

858
    object_id = AV_RB16(buf);
859
    buf += 2;
860

861 862
    object = get_object(ctx, object_id);

863 864 865
    if (!object)
        return;

866
    coding_method = ((*buf) >> 2) & 3;
867
    non_modifying_color = ((*buf++) >> 1) & 1;
868

869
    if (coding_method == 0) {
870
        top_field_len = AV_RB16(buf);
871
        buf += 2;
872
        bottom_field_len = AV_RB16(buf);
873
        buf += 2;
874

875 876 877
        if (buf + top_field_len + bottom_field_len > buf_end) {
            av_log(avctx, AV_LOG_ERROR, "Field data size too large\n");
            return;
878 879
        }

880
        for (display = object->display_list; display; display = display->object_list_next) {
881 882 883
            block = buf;

            dvbsub_parse_pixel_data_block(avctx, display, block, top_field_len, 0,
884
                                            non_modifying_color);
885 886 887 888 889 890 891

            if (bottom_field_len > 0)
                block = buf + top_field_len;
            else
                bottom_field_len = top_field_len;

            dvbsub_parse_pixel_data_block(avctx, display, block, bottom_field_len, 1,
892
                                            non_modifying_color);
893
        }
894

895
/*  } else if (coding_method == 1) {*/
896

897 898 899
    } else {
        av_log(avctx, AV_LOG_ERROR, "Unknown object coding %d\n", coding_method);
    }
900

901 902 903
}

static void dvbsub_parse_clut_segment(AVCodecContext *avctx,
Michael Niedermayer's avatar
Michael Niedermayer committed
904
                                        const uint8_t *buf, int buf_size)
905
{
906
    DVBSubContext *ctx = avctx->priv_data;
907

Michael Niedermayer's avatar
Michael Niedermayer committed
908
    const uint8_t *buf_end = buf + buf_size;
909
    int i, clut_id;
910 911 912 913 914
    DVBSubCLUT *clut;
    int entry_id, depth , full_range;
    int y, cr, cb, alpha;
    int r, g, b, r_add, g_add, b_add;

915
    av_dlog(avctx, "DVB clut packet:\n");
916

917
    for (i=0; i < buf_size; i++) {
918
        av_dlog(avctx, "%02x ", buf[i]);
919
        if (i % 16 == 15)
920
            av_dlog(avctx, "\n");
921
    }
922

923
    if (i % 16)
924
        av_dlog(avctx, "\n");
925 926 927

    clut_id = *buf++;
    buf += 1;
928

929
    clut = get_clut(ctx, clut_id);
930

931
    if (!clut) {
932
        clut = av_malloc(sizeof(DVBSubCLUT));
933

934 935 936
        memcpy(clut, &default_clut, sizeof(DVBSubCLUT));

        clut->id = clut_id;
937 938

        clut->next = ctx->clut_list;
939 940
        ctx->clut_list = clut;
    }
941

942
    while (buf + 4 < buf_end) {
943
        entry_id = *buf++;
944

945
        depth = (*buf) & 0xe0;
946

947 948 949 950
        if (depth == 0) {
            av_log(avctx, AV_LOG_ERROR, "Invalid clut depth 0x%x!\n", *buf);
            return;
        }
951

952
        full_range = (*buf++) & 1;
953

954 955 956 957 958 959 960 961 962 963
        if (full_range) {
            y = *buf++;
            cr = *buf++;
            cb = *buf++;
            alpha = *buf++;
        } else {
            y = buf[0] & 0xfc;
            cr = (((buf[0] & 3) << 2) | ((buf[1] >> 6) & 3)) << 4;
            cb = (buf[1] << 2) & 0xf0;
            alpha = (buf[1] << 6) & 0xc0;
964

965 966
            buf += 2;
        }
967

968 969
        if (y == 0)
            alpha = 0xff;
970

971 972
        YUV_TO_RGB1_CCIR(cb, cr);
        YUV_TO_RGB2_CCIR(r, g, b, y);
973

974
        av_dlog(avctx, "clut %d := (%d,%d,%d,%d)\n", entry_id, r, g, b, alpha);
975

976 977 978 979 980 981 982 983 984 985 986
        if (depth & 0x80)
            clut->clut4[entry_id] = RGBA(r,g,b,255 - alpha);
        if (depth & 0x40)
            clut->clut16[entry_id] = RGBA(r,g,b,255 - alpha);
        if (depth & 0x20)
            clut->clut256[entry_id] = RGBA(r,g,b,255 - alpha);
    }
}


static void dvbsub_parse_region_segment(AVCodecContext *avctx,
Michael Niedermayer's avatar
Michael Niedermayer committed
987
                                        const uint8_t *buf, int buf_size)
988
{
989
    DVBSubContext *ctx = avctx->priv_data;
990

Michael Niedermayer's avatar
Michael Niedermayer committed
991
    const uint8_t *buf_end = buf + buf_size;
992 993 994 995 996
    int region_id, object_id;
    DVBSubRegion *region;
    DVBSubObject *object;
    DVBSubObjectDisplay *display;
    int fill;
997

998 999
    if (buf_size < 10)
        return;
1000

1001
    region_id = *buf++;
1002

1003
    region = get_region(ctx, region_id);
1004

1005
    if (!region) {
1006
        region = av_mallocz(sizeof(DVBSubRegion));
1007

1008
        region->id = region_id;
1009

1010 1011 1012
        region->next = ctx->region_list;
        ctx->region_list = region;
    }
1013

1014
    fill = ((*buf++) >> 3) & 1;
1015

1016
    region->width = AV_RB16(buf);
1017
    buf += 2;
1018
    region->height = AV_RB16(buf);
1019
    buf += 2;
1020

1021
    if (region->width * region->height != region->buf_size) {
1022
        av_free(region->pbuf);
1023

1024
        region->buf_size = region->width * region->height;
1025

1026
        region->pbuf = av_malloc(region->buf_size);
1027

1028 1029
        fill = 1;
    }
1030

1031
    region->depth = 1 << (((*buf++) >> 2) & 7);
1032 1033 1034 1035
    if(region->depth<2 || region->depth>8){
        av_log(avctx, AV_LOG_ERROR, "region depth %d is invalid\n", region->depth);
        region->depth= 4;
    }
1036
    region->clut = *buf++;
1037

1038
    if (region->depth == 8)
1039
        region->bgcolor = *buf++;
1040 1041
    else {
        buf += 1;
1042

1043
        if (region->depth == 4)
1044
            region->bgcolor = (((*buf++) >> 4) & 15);
1045
        else
1046
            region->bgcolor = (((*buf++) >> 2) & 3);
1047 1048
    }

1049
    av_dlog(avctx, "Region %d, (%dx%d)\n", region_id, region->width, region->height);
1050 1051

    if (fill) {
1052
        memset(region->pbuf, region->bgcolor, region->buf_size);
1053
        av_dlog(avctx, "Fill region (%d)\n", region->bgcolor);
1054 1055 1056 1057 1058
    }

    delete_region_display_list(ctx, region);

    while (buf + 5 < buf_end) {
1059
        object_id = AV_RB16(buf);
1060
        buf += 2;
1061

1062 1063
        object = get_object(ctx, object_id);

1064
        if (!object) {
1065
            object = av_mallocz(sizeof(DVBSubObject));
1066

1067 1068 1069 1070
            object->id = object_id;
            object->next = ctx->object_list;
            ctx->object_list = object;
        }
1071

1072
        object->type = (*buf) >> 6;
1073

1074
        display = av_mallocz(sizeof(DVBSubObjectDisplay));
1075

1076 1077
        display->object_id = object_id;
        display->region_id = region_id;
1078

1079
        display->x_pos = AV_RB16(buf) & 0xfff;
1080
        buf += 2;
1081
        display->y_pos = AV_RB16(buf) & 0xfff;
1082
        buf += 2;
1083

1084
        if ((object->type == 1 || object->type == 2) && buf+1 < buf_end) {
1085 1086
            display->fgcolor = *buf++;
            display->bgcolor = *buf++;
1087
        }
1088

1089 1090
        display->region_list_next = region->display_list;
        region->display_list = display;
1091

1092 1093 1094 1095 1096 1097
        display->object_list_next = object->display_list;
        object->display_list = display;
    }
}

static void dvbsub_parse_page_segment(AVCodecContext *avctx,
Michael Niedermayer's avatar
Michael Niedermayer committed
1098
                                        const uint8_t *buf, int buf_size)
1099
{
1100
    DVBSubContext *ctx = avctx->priv_data;
1101 1102
    DVBSubRegionDisplay *display;
    DVBSubRegionDisplay *tmp_display_list, **tmp_ptr;
1103

Michael Niedermayer's avatar
Michael Niedermayer committed
1104
    const uint8_t *buf_end = buf + buf_size;
1105 1106
    int region_id;
    int page_state;
1107

1108 1109
    if (buf_size < 1)
        return;
1110

1111 1112
    ctx->time_out = *buf++;
    page_state = ((*buf++) >> 2) & 3;
1113

1114
    av_dlog(avctx, "Page time out %ds, state %d\n", ctx->time_out, page_state);
1115

1116
    if (page_state == 2) {
1117 1118
        delete_state(ctx);
    }
1119

1120 1121 1122
    tmp_display_list = ctx->display_list;
    ctx->display_list = NULL;
    ctx->display_list_size = 0;
1123

1124 1125 1126
    while (buf + 5 < buf_end) {
        region_id = *buf++;
        buf += 1;
1127

1128 1129
        display = tmp_display_list;
        tmp_ptr = &tmp_display_list;
1130

1131
        while (display && display->region_id != region_id) {
1132 1133 1134
            tmp_ptr = &display->next;
            display = display->next;
        }
1135

1136
        if (!display)
1137
            display = av_mallocz(sizeof(DVBSubRegionDisplay));
1138

1139
        display->region_id = region_id;
1140

1141
        display->x_pos = AV_RB16(buf);
1142
        buf += 2;
1143
        display->y_pos = AV_RB16(buf);
1144
        buf += 2;
1145

1146
        *tmp_ptr = display->next;
1147

1148 1149 1150
        display->next = ctx->display_list;
        ctx->display_list = display;
        ctx->display_list_size++;
1151

1152
        av_dlog(avctx, "Region %d, (%d,%d)\n", region_id, display->x_pos, display->y_pos);
1153
    }
1154

1155
    while (tmp_display_list) {
1156
        display = tmp_display_list;
1157

1158
        tmp_display_list = display->next;
1159

1160 1161
        av_free(display);
    }
1162

1163 1164 1165
}


1166
#ifdef DEBUG
1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182
static void save_display_set(DVBSubContext *ctx)
{
    DVBSubRegion *region;
    DVBSubRegionDisplay *display;
    DVBSubCLUT *clut;
    uint32_t *clut_table;
    int x_pos, y_pos, width, height;
    int x, y, y_off, x_off;
    uint32_t *pbuf;
    char filename[32];
    static int fileno_index = 0;

    x_pos = -1;
    y_pos = -1;
    width = 0;
    height = 0;
1183

1184
    for (display = ctx->display_list; display; display = display->next) {
1185
        region = get_region(ctx, display->region_id);
1186

1187 1188 1189 1190 1191 1192 1193 1194 1195 1196
        if (x_pos == -1) {
            x_pos = display->x_pos;
            y_pos = display->y_pos;
            width = region->width;
            height = region->height;
        } else {
            if (display->x_pos < x_pos) {
                width += (x_pos - display->x_pos);
                x_pos = display->x_pos;
            }
1197

1198 1199 1200 1201
            if (display->y_pos < y_pos) {
                height += (y_pos - display->y_pos);
                y_pos = display->y_pos;
            }
1202

1203 1204 1205
            if (display->x_pos + region->width > x_pos + width) {
                width = display->x_pos + region->width - x_pos;
            }
1206

1207 1208 1209 1210 1211
            if (display->y_pos + region->height > y_pos + height) {
                height = display->y_pos + region->height - y_pos;
            }
        }
    }
1212

1213
    if (x_pos >= 0) {
1214

1215 1216
        pbuf = av_malloc(width * height * 4);

1217
        for (display = ctx->display_list; display; display = display->next) {
1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239
            region = get_region(ctx, display->region_id);

            x_off = display->x_pos - x_pos;
            y_off = display->y_pos - y_pos;

            clut = get_clut(ctx, region->clut);

            if (clut == 0)
                clut = &default_clut;

            switch (region->depth) {
            case 2:
                clut_table = clut->clut4;
                break;
            case 8:
                clut_table = clut->clut256;
                break;
            case 4:
            default:
                clut_table = clut->clut16;
                break;
            }
1240

1241 1242
            for (y = 0; y < region->height; y++) {
                for (x = 0; x < region->width; x++) {
1243
                    pbuf[((y + y_off) * width) + x_off + x] =
1244 1245 1246 1247
                        clut_table[region->pbuf[y * region->width + x]];
                }
            }

1248
        }
1249

1250
        snprintf(filename, sizeof(filename), "dvbs.%d", fileno_index);
1251 1252 1253 1254 1255

        png_save2(filename, pbuf, width, height);

        av_free(pbuf);
    }
1256

1257 1258 1259 1260
    fileno_index++;
}
#endif

1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300
static void dvbsub_parse_display_definition_segment(AVCodecContext *avctx,
                                                    const uint8_t *buf,
                                                    int buf_size)
{
    DVBSubContext *ctx = avctx->priv_data;
    DVBSubDisplayDefinition *display_def = ctx->display_definition;
    int dds_version, info_byte;

    if (buf_size < 5)
        return;

    info_byte   = bytestream_get_byte(&buf);
    dds_version = info_byte >> 4;
    if (display_def && display_def->version == dds_version)
        return; // already have this display definition version

    if (!display_def) {
        display_def             = av_mallocz(sizeof(*display_def));
        ctx->display_definition = display_def;
    }
    if (!display_def)
        return;

    display_def->version = dds_version;
    display_def->x       = 0;
    display_def->y       = 0;
    display_def->width   = bytestream_get_be16(&buf) + 1;
    display_def->height  = bytestream_get_be16(&buf) + 1;

    if (buf_size < 13)
        return;

    if (info_byte & 1<<3) { // display_window_flag
        display_def->x = bytestream_get_be16(&buf);
        display_def->y = bytestream_get_be16(&buf);
        display_def->width  = bytestream_get_be16(&buf) - display_def->x + 1;
        display_def->height = bytestream_get_be16(&buf) - display_def->y + 1;
    }
}

Michael Niedermayer's avatar
Michael Niedermayer committed
1301
static int dvbsub_display_end_segment(AVCodecContext *avctx, const uint8_t *buf,
1302 1303
                                        int buf_size, AVSubtitle *sub)
{
1304
    DVBSubContext *ctx = avctx->priv_data;
1305
    DVBSubDisplayDefinition *display_def = ctx->display_definition;
1306 1307 1308 1309 1310 1311 1312

    DVBSubRegion *region;
    DVBSubRegionDisplay *display;
    AVSubtitleRect *rect;
    DVBSubCLUT *clut;
    uint32_t *clut_table;
    int i;
1313
    int offset_x=0, offset_y=0;
1314

1315 1316 1317 1318 1319
    sub->rects = NULL;
    sub->start_display_time = 0;
    sub->end_display_time = ctx->time_out * 1000;
    sub->format = 0;

1320 1321 1322 1323 1324
    if (display_def) {
        offset_x = display_def->x;
        offset_y = display_def->y;
    }

1325
    sub->num_rects = ctx->display_list_size;
1326

1327 1328 1329 1330 1331
    if (sub->num_rects > 0){
        sub->rects = av_mallocz(sizeof(*sub->rects) * sub->num_rects);
        for(i=0; i<sub->num_rects; i++)
            sub->rects[i] = av_mallocz(sizeof(*sub->rects[i]));
    }
1332 1333 1334

    i = 0;

1335
    for (display = ctx->display_list; display; display = display->next) {
1336
        region = get_region(ctx, display->region_id);
1337
        rect = sub->rects[i];
1338

1339
        if (!region)
1340
            continue;
1341

1342 1343
        rect->x = display->x_pos + offset_x;
        rect->y = display->y_pos + offset_y;
1344 1345 1346
        rect->w = region->width;
        rect->h = region->height;
        rect->nb_colors = 16;
1347
        rect->type      = SUBTITLE_BITMAP;
1348
        rect->pict.linesize[0] = region->width;
1349 1350

        clut = get_clut(ctx, region->clut);
1351

1352
        if (!clut)
1353
            clut = &default_clut;
1354

1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366
        switch (region->depth) {
        case 2:
            clut_table = clut->clut4;
            break;
        case 8:
            clut_table = clut->clut256;
            break;
        case 4:
        default:
            clut_table = clut->clut16;
            break;
        }
1367

1368
        rect->pict.data[1] = av_mallocz(AVPALETTE_SIZE);
1369
        memcpy(rect->pict.data[1], clut_table, (1 << region->depth) * sizeof(uint32_t));
1370

1371 1372
        rect->pict.data[0] = av_malloc(region->buf_size);
        memcpy(rect->pict.data[0], region->pbuf, region->buf_size);
1373

1374 1375
        i++;
    }
1376

1377
    sub->num_rects = i;
1378

1379
#ifdef DEBUG
1380 1381
    save_display_set(ctx);
#endif
1382

1383 1384 1385 1386 1387
    return 1;
}

static int dvbsub_decode(AVCodecContext *avctx,
                         void *data, int *data_size,
1388
                         AVPacket *avpkt)
1389
{
1390 1391
    const uint8_t *buf = avpkt->data;
    int buf_size = avpkt->size;
1392 1393
    DVBSubContext *ctx = avctx->priv_data;
    AVSubtitle *sub = data;
Michael Niedermayer's avatar
Michael Niedermayer committed
1394
    const uint8_t *p, *p_end;
1395 1396 1397 1398 1399
    int segment_type;
    int page_id;
    int segment_length;
    int i;

1400
    av_dlog(avctx, "DVB sub packet:\n");
1401

1402
    for (i=0; i < buf_size; i++) {
1403
        av_dlog(avctx, "%02x ", buf[i]);
1404
        if (i % 16 == 15)
1405
            av_dlog(avctx, "\n");
1406
    }
1407

1408
    if (i % 16)
1409
        av_dlog(avctx, "\n");
1410

1411 1412
    if (buf_size <= 6 || *buf != 0x0f) {
        av_dlog(avctx, "incomplete or broken packet");
1413
        return -1;
1414
    }
1415

1416 1417
    p = buf;
    p_end = buf + buf_size;
1418

1419
    while (p_end - p >= 6 && *p == 0x0f) {
1420 1421
        p += 1;
        segment_type = *p++;
1422
        page_id = AV_RB16(p);
1423
        p += 2;
1424
        segment_length = AV_RB16(p);
1425
        p += 2;
1426

1427 1428 1429 1430 1431
        if (p_end - p < segment_length) {
            av_dlog(avctx, "incomplete or broken packet");
            return -1;
        }

1432 1433
        if (page_id == ctx->composition_id || page_id == ctx->ancillary_id ||
            ctx->composition_id == -1 || ctx->ancillary_id == -1) {
1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446
            switch (segment_type) {
            case DVBSUB_PAGE_SEGMENT:
                dvbsub_parse_page_segment(avctx, p, segment_length);
                break;
            case DVBSUB_REGION_SEGMENT:
                dvbsub_parse_region_segment(avctx, p, segment_length);
                break;
            case DVBSUB_CLUT_SEGMENT:
                dvbsub_parse_clut_segment(avctx, p, segment_length);
                break;
            case DVBSUB_OBJECT_SEGMENT:
                dvbsub_parse_object_segment(avctx, p, segment_length);
                break;
1447 1448
            case DVBSUB_DISPLAYDEFINITION_SEGMENT:
                dvbsub_parse_display_definition_segment(avctx, p, segment_length);
1449 1450 1451 1452
            case DVBSUB_DISPLAY_SEGMENT:
                *data_size = dvbsub_display_end_segment(avctx, p, segment_length, sub);
                break;
            default:
1453
                av_dlog(avctx, "Subtitling segment type 0x%x, page id %d, length %d\n",
1454 1455 1456 1457 1458 1459 1460
                        segment_type, page_id, segment_length);
                break;
            }
        }

        p += segment_length;
    }
1461

1462
    return p - buf;
1463 1464 1465
}


1466
AVCodec ff_dvbsub_decoder = {
1467 1468
    .name           = "dvbsub",
    .type           = AVMEDIA_TYPE_SUBTITLE,
1469
    .id             = AV_CODEC_ID_DVB_SUBTITLE,
1470 1471 1472 1473
    .priv_data_size = sizeof(DVBSubContext),
    .init           = dvbsub_init_decoder,
    .close          = dvbsub_close_decoder,
    .decode         = dvbsub_decode,
1474
    .long_name      = NULL_IF_CONFIG_SMALL("DVB subtitles"),
1475
};