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