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