libavcodec/dvbsubdec.c
Go to the documentation of this file.
00001 /*
00002  * DVB subtitle decoding
00003  * Copyright (c) 2005 Ian Caulfield
00004  *
00005  * This file is part of FFmpeg.
00006  *
00007  * FFmpeg is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * FFmpeg is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with FFmpeg; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
00020  */
00021 #include "avcodec.h"
00022 #include "dsputil.h"
00023 #include "get_bits.h"
00024 #include "bytestream.h"
00025 #include "libavutil/colorspace.h"
00026 
00027 #define DVBSUB_PAGE_SEGMENT     0x10
00028 #define DVBSUB_REGION_SEGMENT   0x11
00029 #define DVBSUB_CLUT_SEGMENT     0x12
00030 #define DVBSUB_OBJECT_SEGMENT   0x13
00031 #define DVBSUB_DISPLAYDEFINITION_SEGMENT 0x14
00032 #define DVBSUB_DISPLAY_SEGMENT  0x80
00033 
00034 #define cm (ff_cropTbl + MAX_NEG_CROP)
00035 
00036 #ifdef DEBUG
00037 #undef fprintf
00038 #undef perror
00039 #if 0
00040 static void png_save(const char *filename, uint8_t *bitmap, int w, int h,
00041                      uint32_t *rgba_palette)
00042 {
00043     int x, y, v;
00044     FILE *f;
00045     char fname[40], fname2[40];
00046     char command[1024];
00047 
00048     snprintf(fname, 40, "%s.ppm", filename);
00049 
00050     f = fopen(fname, "w");
00051     if (!f) {
00052         perror(fname);
00053         return;
00054     }
00055     fprintf(f, "P6\n"
00056             "%d %d\n"
00057             "%d\n",
00058             w, h, 255);
00059     for(y = 0; y < h; y++) {
00060         for(x = 0; x < w; x++) {
00061             v = rgba_palette[bitmap[y * w + x]];
00062             putc((v >> 16) & 0xff, f);
00063             putc((v >> 8) & 0xff, f);
00064             putc((v >> 0) & 0xff, f);
00065         }
00066     }
00067     fclose(f);
00068 
00069 
00070     snprintf(fname2, 40, "%s-a.pgm", filename);
00071 
00072     f = fopen(fname2, "w");
00073     if (!f) {
00074         perror(fname2);
00075         return;
00076     }
00077     fprintf(f, "P5\n"
00078             "%d %d\n"
00079             "%d\n",
00080             w, h, 255);
00081     for(y = 0; y < h; y++) {
00082         for(x = 0; x < w; x++) {
00083             v = rgba_palette[bitmap[y * w + x]];
00084             putc((v >> 24) & 0xff, f);
00085         }
00086     }
00087     fclose(f);
00088 
00089     snprintf(command, 1024, "pnmtopng -alpha %s %s > %s.png 2> /dev/null", fname2, fname, filename);
00090     system(command);
00091 
00092     snprintf(command, 1024, "rm %s %s", fname, fname2);
00093     system(command);
00094 }
00095 #endif
00096 
00097 static void png_save2(const char *filename, uint32_t *bitmap, int w, int h)
00098 {
00099     int x, y, v;
00100     FILE *f;
00101     char fname[40], fname2[40];
00102     char command[1024];
00103 
00104     snprintf(fname, sizeof(fname), "%s.ppm", filename);
00105 
00106     f = fopen(fname, "w");
00107     if (!f) {
00108         perror(fname);
00109         return;
00110     }
00111     fprintf(f, "P6\n"
00112             "%d %d\n"
00113             "%d\n",
00114             w, h, 255);
00115     for(y = 0; y < h; y++) {
00116         for(x = 0; x < w; x++) {
00117             v = bitmap[y * w + x];
00118             putc((v >> 16) & 0xff, f);
00119             putc((v >> 8) & 0xff, f);
00120             putc((v >> 0) & 0xff, f);
00121         }
00122     }
00123     fclose(f);
00124 
00125 
00126     snprintf(fname2, sizeof(fname2), "%s-a.pgm", filename);
00127 
00128     f = fopen(fname2, "w");
00129     if (!f) {
00130         perror(fname2);
00131         return;
00132     }
00133     fprintf(f, "P5\n"
00134             "%d %d\n"
00135             "%d\n",
00136             w, h, 255);
00137     for(y = 0; y < h; y++) {
00138         for(x = 0; x < w; x++) {
00139             v = bitmap[y * w + x];
00140             putc((v >> 24) & 0xff, f);
00141         }
00142     }
00143     fclose(f);
00144 
00145     snprintf(command, sizeof(command), "pnmtopng -alpha %s %s > %s.png 2> /dev/null", fname2, fname, filename);
00146     system(command);
00147 
00148     snprintf(command, sizeof(command), "rm %s %s", fname, fname2);
00149     system(command);
00150 }
00151 #endif
00152 
00153 #define RGBA(r,g,b,a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
00154 
00155 typedef struct DVBSubCLUT {
00156     int id;
00157     int version;
00158 
00159     uint32_t clut4[4];
00160     uint32_t clut16[16];
00161     uint32_t clut256[256];
00162 
00163     struct DVBSubCLUT *next;
00164 } DVBSubCLUT;
00165 
00166 static DVBSubCLUT default_clut;
00167 
00168 typedef struct DVBSubObjectDisplay {
00169     int object_id;
00170     int region_id;
00171 
00172     int x_pos;
00173     int y_pos;
00174 
00175     int fgcolor;
00176     int bgcolor;
00177 
00178     struct DVBSubObjectDisplay *region_list_next;
00179     struct DVBSubObjectDisplay *object_list_next;
00180 } DVBSubObjectDisplay;
00181 
00182 typedef struct DVBSubObject {
00183     int id;
00184     int version;
00185 
00186     int type;
00187 
00188     DVBSubObjectDisplay *display_list;
00189 
00190     struct DVBSubObject *next;
00191 } DVBSubObject;
00192 
00193 typedef struct DVBSubRegionDisplay {
00194     int region_id;
00195 
00196     int x_pos;
00197     int y_pos;
00198 
00199     struct DVBSubRegionDisplay *next;
00200 } DVBSubRegionDisplay;
00201 
00202 typedef struct DVBSubRegion {
00203     int id;
00204     int version;
00205 
00206     int width;
00207     int height;
00208     int depth;
00209 
00210     int clut;
00211     int bgcolor;
00212 
00213     uint8_t *pbuf;
00214     int buf_size;
00215     int dirty;
00216 
00217     DVBSubObjectDisplay *display_list;
00218 
00219     struct DVBSubRegion *next;
00220 } DVBSubRegion;
00221 
00222 typedef struct DVBSubDisplayDefinition {
00223     int version;
00224 
00225     int x;
00226     int y;
00227     int width;
00228     int height;
00229 } DVBSubDisplayDefinition;
00230 
00231 typedef struct DVBSubContext {
00232     int composition_id;
00233     int ancillary_id;
00234 
00235     int version;
00236     int time_out;
00237     DVBSubRegion *region_list;
00238     DVBSubCLUT   *clut_list;
00239     DVBSubObject *object_list;
00240 
00241     int display_list_size;
00242     DVBSubRegionDisplay *display_list;
00243     DVBSubDisplayDefinition *display_definition;
00244 } DVBSubContext;
00245 
00246 
00247 static DVBSubObject* get_object(DVBSubContext *ctx, int object_id)
00248 {
00249     DVBSubObject *ptr = ctx->object_list;
00250 
00251     while (ptr && ptr->id != object_id) {
00252         ptr = ptr->next;
00253     }
00254 
00255     return ptr;
00256 }
00257 
00258 static DVBSubCLUT* get_clut(DVBSubContext *ctx, int clut_id)
00259 {
00260     DVBSubCLUT *ptr = ctx->clut_list;
00261 
00262     while (ptr && ptr->id != clut_id) {
00263         ptr = ptr->next;
00264     }
00265 
00266     return ptr;
00267 }
00268 
00269 static DVBSubRegion* get_region(DVBSubContext *ctx, int region_id)
00270 {
00271     DVBSubRegion *ptr = ctx->region_list;
00272 
00273     while (ptr && ptr->id != region_id) {
00274         ptr = ptr->next;
00275     }
00276 
00277     return ptr;
00278 }
00279 
00280 static void delete_region_display_list(DVBSubContext *ctx, DVBSubRegion *region)
00281 {
00282     DVBSubObject *object, *obj2, **obj2_ptr;
00283     DVBSubObjectDisplay *display, *obj_disp, **obj_disp_ptr;
00284 
00285     while (region->display_list) {
00286         display = region->display_list;
00287 
00288         object = get_object(ctx, display->object_id);
00289 
00290         if (object) {
00291             obj_disp_ptr = &object->display_list;
00292             obj_disp = *obj_disp_ptr;
00293 
00294             while (obj_disp && obj_disp != display) {
00295                 obj_disp_ptr = &obj_disp->object_list_next;
00296                 obj_disp = *obj_disp_ptr;
00297             }
00298 
00299             if (obj_disp) {
00300                 *obj_disp_ptr = obj_disp->object_list_next;
00301 
00302                 if (!object->display_list) {
00303                     obj2_ptr = &ctx->object_list;
00304                     obj2 = *obj2_ptr;
00305 
00306                     while (obj2 != object) {
00307                         assert(obj2);
00308                         obj2_ptr = &obj2->next;
00309                         obj2 = *obj2_ptr;
00310                     }
00311 
00312                     *obj2_ptr = obj2->next;
00313 
00314                     av_free(obj2);
00315                 }
00316             }
00317         }
00318 
00319         region->display_list = display->region_list_next;
00320 
00321         av_free(display);
00322     }
00323 
00324 }
00325 
00326 static void delete_cluts(DVBSubContext *ctx)
00327 {
00328     DVBSubCLUT *clut;
00329 
00330     while (ctx->clut_list) {
00331         clut = ctx->clut_list;
00332 
00333         ctx->clut_list = clut->next;
00334 
00335         av_free(clut);
00336     }
00337 }
00338 
00339 static void delete_objects(DVBSubContext *ctx)
00340 {
00341     DVBSubObject *object;
00342 
00343     while (ctx->object_list) {
00344         object = ctx->object_list;
00345 
00346         ctx->object_list = object->next;
00347 
00348         av_free(object);
00349     }
00350 }
00351 
00352 static void delete_regions(DVBSubContext *ctx)
00353 {
00354     DVBSubRegion *region;
00355 
00356     while (ctx->region_list) {
00357         region = ctx->region_list;
00358 
00359         ctx->region_list = region->next;
00360 
00361         delete_region_display_list(ctx, region);
00362 
00363         av_free(region->pbuf);
00364         av_free(region);
00365     }
00366 }
00367 
00368 static av_cold int dvbsub_init_decoder(AVCodecContext *avctx)
00369 {
00370     int i, r, g, b, a = 0;
00371     DVBSubContext *ctx = avctx->priv_data;
00372 
00373     if (!avctx->extradata || avctx->extradata_size != 4) {
00374         av_log(avctx, AV_LOG_WARNING, "Invalid extradata, subtitle streams may be combined!\n");
00375         ctx->composition_id = -1;
00376         ctx->ancillary_id   = -1;
00377     } else {
00378         ctx->composition_id = AV_RB16(avctx->extradata);
00379         ctx->ancillary_id   = AV_RB16(avctx->extradata + 2);
00380     }
00381 
00382     ctx->version = -1;
00383 
00384     default_clut.id = -1;
00385     default_clut.next = NULL;
00386 
00387     default_clut.clut4[0] = RGBA(  0,   0,   0,   0);
00388     default_clut.clut4[1] = RGBA(255, 255, 255, 255);
00389     default_clut.clut4[2] = RGBA(  0,   0,   0, 255);
00390     default_clut.clut4[3] = RGBA(127, 127, 127, 255);
00391 
00392     default_clut.clut16[0] = RGBA(  0,   0,   0,   0);
00393     for (i = 1; i < 16; i++) {
00394         if (i < 8) {
00395             r = (i & 1) ? 255 : 0;
00396             g = (i & 2) ? 255 : 0;
00397             b = (i & 4) ? 255 : 0;
00398         } else {
00399             r = (i & 1) ? 127 : 0;
00400             g = (i & 2) ? 127 : 0;
00401             b = (i & 4) ? 127 : 0;
00402         }
00403         default_clut.clut16[i] = RGBA(r, g, b, 255);
00404     }
00405 
00406     default_clut.clut256[0] = RGBA(  0,   0,   0,   0);
00407     for (i = 1; i < 256; i++) {
00408         if (i < 8) {
00409             r = (i & 1) ? 255 : 0;
00410             g = (i & 2) ? 255 : 0;
00411             b = (i & 4) ? 255 : 0;
00412             a = 63;
00413         } else {
00414             switch (i & 0x88) {
00415             case 0x00:
00416                 r = ((i & 1) ? 85 : 0) + ((i & 0x10) ? 170 : 0);
00417                 g = ((i & 2) ? 85 : 0) + ((i & 0x20) ? 170 : 0);
00418                 b = ((i & 4) ? 85 : 0) + ((i & 0x40) ? 170 : 0);
00419                 a = 255;
00420                 break;
00421             case 0x08:
00422                 r = ((i & 1) ? 85 : 0) + ((i & 0x10) ? 170 : 0);
00423                 g = ((i & 2) ? 85 : 0) + ((i & 0x20) ? 170 : 0);
00424                 b = ((i & 4) ? 85 : 0) + ((i & 0x40) ? 170 : 0);
00425                 a = 127;
00426                 break;
00427             case 0x80:
00428                 r = 127 + ((i & 1) ? 43 : 0) + ((i & 0x10) ? 85 : 0);
00429                 g = 127 + ((i & 2) ? 43 : 0) + ((i & 0x20) ? 85 : 0);
00430                 b = 127 + ((i & 4) ? 43 : 0) + ((i & 0x40) ? 85 : 0);
00431                 a = 255;
00432                 break;
00433             case 0x88:
00434                 r = ((i & 1) ? 43 : 0) + ((i & 0x10) ? 85 : 0);
00435                 g = ((i & 2) ? 43 : 0) + ((i & 0x20) ? 85 : 0);
00436                 b = ((i & 4) ? 43 : 0) + ((i & 0x40) ? 85 : 0);
00437                 a = 255;
00438                 break;
00439             }
00440         }
00441         default_clut.clut256[i] = RGBA(r, g, b, a);
00442     }
00443 
00444     return 0;
00445 }
00446 
00447 static av_cold int dvbsub_close_decoder(AVCodecContext *avctx)
00448 {
00449     DVBSubContext *ctx = avctx->priv_data;
00450     DVBSubRegionDisplay *display;
00451 
00452     delete_regions(ctx);
00453 
00454     delete_objects(ctx);
00455 
00456     delete_cluts(ctx);
00457 
00458     av_freep(&ctx->display_definition);
00459 
00460     while (ctx->display_list) {
00461         display = ctx->display_list;
00462         ctx->display_list = display->next;
00463 
00464         av_free(display);
00465     }
00466 
00467     return 0;
00468 }
00469 
00470 static int dvbsub_read_2bit_string(uint8_t *destbuf, int dbuf_len,
00471                                    const uint8_t **srcbuf, int buf_size,
00472                                    int non_mod, uint8_t *map_table, int x_pos)
00473 {
00474     GetBitContext gb;
00475 
00476     int bits;
00477     int run_length;
00478     int pixels_read = x_pos;
00479 
00480     init_get_bits(&gb, *srcbuf, buf_size << 3);
00481 
00482     destbuf += x_pos;
00483 
00484     while (get_bits_count(&gb) < buf_size << 3 && pixels_read < dbuf_len) {
00485         bits = get_bits(&gb, 2);
00486 
00487         if (bits) {
00488             if (non_mod != 1 || bits != 1) {
00489                 if (map_table)
00490                     *destbuf++ = map_table[bits];
00491                 else
00492                     *destbuf++ = bits;
00493             }
00494             pixels_read++;
00495         } else {
00496             bits = get_bits1(&gb);
00497             if (bits == 1) {
00498                 run_length = get_bits(&gb, 3) + 3;
00499                 bits = get_bits(&gb, 2);
00500 
00501                 if (non_mod == 1 && bits == 1)
00502                     pixels_read += run_length;
00503                 else {
00504                     if (map_table)
00505                         bits = map_table[bits];
00506                     while (run_length-- > 0 && pixels_read < dbuf_len) {
00507                         *destbuf++ = bits;
00508                         pixels_read++;
00509                     }
00510                 }
00511             } else {
00512                 bits = get_bits1(&gb);
00513                 if (bits == 0) {
00514                     bits = get_bits(&gb, 2);
00515                     if (bits == 2) {
00516                         run_length = get_bits(&gb, 4) + 12;
00517                         bits = get_bits(&gb, 2);
00518 
00519                         if (non_mod == 1 && bits == 1)
00520                             pixels_read += run_length;
00521                         else {
00522                             if (map_table)
00523                                 bits = map_table[bits];
00524                             while (run_length-- > 0 && pixels_read < dbuf_len) {
00525                                 *destbuf++ = bits;
00526                                 pixels_read++;
00527                             }
00528                         }
00529                     } else if (bits == 3) {
00530                         run_length = get_bits(&gb, 8) + 29;
00531                         bits = get_bits(&gb, 2);
00532 
00533                         if (non_mod == 1 && bits == 1)
00534                             pixels_read += run_length;
00535                         else {
00536                             if (map_table)
00537                                 bits = map_table[bits];
00538                             while (run_length-- > 0 && pixels_read < dbuf_len) {
00539                                 *destbuf++ = bits;
00540                                 pixels_read++;
00541                             }
00542                         }
00543                     } else if (bits == 1) {
00544                         if (map_table)
00545                             bits = map_table[0];
00546                         else
00547                             bits = 0;
00548                         run_length = 2;
00549                         while (run_length-- > 0 && pixels_read < dbuf_len) {
00550                             *destbuf++ = bits;
00551                             pixels_read++;
00552                         }
00553                     } else {
00554                         (*srcbuf) += (get_bits_count(&gb) + 7) >> 3;
00555                         return pixels_read;
00556                     }
00557                 } else {
00558                     if (map_table)
00559                         bits = map_table[0];
00560                     else
00561                         bits = 0;
00562                     *destbuf++ = bits;
00563                     pixels_read++;
00564                 }
00565             }
00566         }
00567     }
00568 
00569     if (get_bits(&gb, 6))
00570         av_log(0, AV_LOG_ERROR, "DVBSub error: line overflow\n");
00571 
00572     (*srcbuf) += (get_bits_count(&gb) + 7) >> 3;
00573 
00574     return pixels_read;
00575 }
00576 
00577 static int dvbsub_read_4bit_string(uint8_t *destbuf, int dbuf_len,
00578                                    const uint8_t **srcbuf, int buf_size,
00579                                    int non_mod, uint8_t *map_table, int x_pos)
00580 {
00581     GetBitContext gb;
00582 
00583     int bits;
00584     int run_length;
00585     int pixels_read = x_pos;
00586 
00587     init_get_bits(&gb, *srcbuf, buf_size << 3);
00588 
00589     destbuf += x_pos;
00590 
00591     while (get_bits_count(&gb) < buf_size << 3 && pixels_read < dbuf_len) {
00592         bits = get_bits(&gb, 4);
00593 
00594         if (bits) {
00595             if (non_mod != 1 || bits != 1) {
00596                 if (map_table)
00597                     *destbuf++ = map_table[bits];
00598                 else
00599                     *destbuf++ = bits;
00600             }
00601             pixels_read++;
00602         } else {
00603             bits = get_bits1(&gb);
00604             if (bits == 0) {
00605                 run_length = get_bits(&gb, 3);
00606 
00607                 if (run_length == 0) {
00608                     (*srcbuf) += (get_bits_count(&gb) + 7) >> 3;
00609                     return pixels_read;
00610                 }
00611 
00612                 run_length += 2;
00613 
00614                 if (map_table)
00615                     bits = map_table[0];
00616                 else
00617                     bits = 0;
00618 
00619                 while (run_length-- > 0 && pixels_read < dbuf_len) {
00620                     *destbuf++ = bits;
00621                     pixels_read++;
00622                 }
00623             } else {
00624                 bits = get_bits1(&gb);
00625                 if (bits == 0) {
00626                     run_length = get_bits(&gb, 2) + 4;
00627                     bits = get_bits(&gb, 4);
00628 
00629                     if (non_mod == 1 && bits == 1)
00630                         pixels_read += run_length;
00631                     else {
00632                         if (map_table)
00633                             bits = map_table[bits];
00634                         while (run_length-- > 0 && pixels_read < dbuf_len) {
00635                             *destbuf++ = bits;
00636                             pixels_read++;
00637                         }
00638                     }
00639                 } else {
00640                     bits = get_bits(&gb, 2);
00641                     if (bits == 2) {
00642                         run_length = get_bits(&gb, 4) + 9;
00643                         bits = get_bits(&gb, 4);
00644 
00645                         if (non_mod == 1 && bits == 1)
00646                             pixels_read += run_length;
00647                         else {
00648                             if (map_table)
00649                                 bits = map_table[bits];
00650                             while (run_length-- > 0 && pixels_read < dbuf_len) {
00651                                 *destbuf++ = bits;
00652                                 pixels_read++;
00653                             }
00654                         }
00655                     } else if (bits == 3) {
00656                         run_length = get_bits(&gb, 8) + 25;
00657                         bits = get_bits(&gb, 4);
00658 
00659                         if (non_mod == 1 && bits == 1)
00660                             pixels_read += run_length;
00661                         else {
00662                             if (map_table)
00663                                 bits = map_table[bits];
00664                             while (run_length-- > 0 && pixels_read < dbuf_len) {
00665                                 *destbuf++ = bits;
00666                                 pixels_read++;
00667                             }
00668                         }
00669                     } else if (bits == 1) {
00670                         if (map_table)
00671                             bits = map_table[0];
00672                         else
00673                             bits = 0;
00674                         run_length = 2;
00675                         while (run_length-- > 0 && pixels_read < dbuf_len) {
00676                             *destbuf++ = bits;
00677                             pixels_read++;
00678                         }
00679                     } else {
00680                         if (map_table)
00681                             bits = map_table[0];
00682                         else
00683                             bits = 0;
00684                         *destbuf++ = bits;
00685                         pixels_read ++;
00686                     }
00687                 }
00688             }
00689         }
00690     }
00691 
00692     if (get_bits(&gb, 8))
00693         av_log(0, AV_LOG_ERROR, "DVBSub error: line overflow\n");
00694 
00695     (*srcbuf) += (get_bits_count(&gb) + 7) >> 3;
00696 
00697     return pixels_read;
00698 }
00699 
00700 static int dvbsub_read_8bit_string(uint8_t *destbuf, int dbuf_len,
00701                                     const uint8_t **srcbuf, int buf_size,
00702                                     int non_mod, uint8_t *map_table, int x_pos)
00703 {
00704     const uint8_t *sbuf_end = (*srcbuf) + buf_size;
00705     int bits;
00706     int run_length;
00707     int pixels_read = x_pos;
00708 
00709     destbuf += x_pos;
00710 
00711     while (*srcbuf < sbuf_end && pixels_read < dbuf_len) {
00712         bits = *(*srcbuf)++;
00713 
00714         if (bits) {
00715             if (non_mod != 1 || bits != 1) {
00716                 if (map_table)
00717                     *destbuf++ = map_table[bits];
00718                 else
00719                     *destbuf++ = bits;
00720             }
00721             pixels_read++;
00722         } else {
00723             bits = *(*srcbuf)++;
00724             run_length = bits & 0x7f;
00725             if ((bits & 0x80) == 0) {
00726                 if (run_length == 0) {
00727                     return pixels_read;
00728                 }
00729 
00730                 if (map_table)
00731                     bits = map_table[0];
00732                 else
00733                     bits = 0;
00734                 while (run_length-- > 0 && pixels_read < dbuf_len) {
00735                     *destbuf++ = bits;
00736                     pixels_read++;
00737                 }
00738             } else {
00739                 bits = *(*srcbuf)++;
00740 
00741                 if (non_mod == 1 && bits == 1)
00742                     pixels_read += run_length;
00743                 if (map_table)
00744                     bits = map_table[bits];
00745                 else while (run_length-- > 0 && pixels_read < dbuf_len) {
00746                     *destbuf++ = bits;
00747                     pixels_read++;
00748                 }
00749             }
00750         }
00751     }
00752 
00753     if (*(*srcbuf)++)
00754         av_log(0, AV_LOG_ERROR, "DVBSub error: line overflow\n");
00755 
00756     return pixels_read;
00757 }
00758 
00759 
00760 
00761 static void dvbsub_parse_pixel_data_block(AVCodecContext *avctx, DVBSubObjectDisplay *display,
00762                                           const uint8_t *buf, int buf_size, int top_bottom, int non_mod)
00763 {
00764     DVBSubContext *ctx = avctx->priv_data;
00765 
00766     DVBSubRegion *region = get_region(ctx, display->region_id);
00767     const uint8_t *buf_end = buf + buf_size;
00768     uint8_t *pbuf;
00769     int x_pos, y_pos;
00770     int i;
00771 
00772     uint8_t map2to4[] = { 0x0,  0x7,  0x8,  0xf};
00773     uint8_t map2to8[] = {0x00, 0x77, 0x88, 0xff};
00774     uint8_t map4to8[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
00775                          0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
00776     uint8_t *map_table;
00777 
00778 #if 0
00779     av_dlog(avctx, "DVB pixel block size %d, %s field:\n", buf_size,
00780             top_bottom ? "bottom" : "top");
00781 
00782     for (i = 0; i < buf_size; i++) {
00783         if (i % 16 == 0)
00784             av_dlog(avctx, "0x%8p: ", buf+i);
00785 
00786         av_dlog(avctx, "%02x ", buf[i]);
00787         if (i % 16 == 15)
00788             av_dlog(avctx, "\n");
00789     }
00790 
00791     if (i % 16)
00792         av_dlog(avctx, "\n");
00793 #endif
00794 
00795     if (region == 0)
00796         return;
00797 
00798     pbuf = region->pbuf;
00799     region->dirty = 1;
00800 
00801     x_pos = display->x_pos;
00802     y_pos = display->y_pos;
00803 
00804     y_pos += top_bottom;
00805 
00806     while (buf < buf_end) {
00807         if ((*buf!=0xf0 && x_pos >= region->width) || y_pos >= region->height) {
00808             av_log(avctx, AV_LOG_ERROR, "Invalid object location! %d-%d %d-%d %02x\n", x_pos, region->width, y_pos, region->height, *buf);
00809             return;
00810         }
00811 
00812         switch (*buf++) {
00813         case 0x10:
00814             if (region->depth == 8)
00815                 map_table = map2to8;
00816             else if (region->depth == 4)
00817                 map_table = map2to4;
00818             else
00819                 map_table = NULL;
00820 
00821             x_pos = dvbsub_read_2bit_string(pbuf + (y_pos * region->width),
00822                                             region->width, &buf, buf_end - buf,
00823                                             non_mod, map_table, x_pos);
00824             break;
00825         case 0x11:
00826             if (region->depth < 4) {
00827                 av_log(avctx, AV_LOG_ERROR, "4-bit pixel string in %d-bit region!\n", region->depth);
00828                 return;
00829             }
00830 
00831             if (region->depth == 8)
00832                 map_table = map4to8;
00833             else
00834                 map_table = NULL;
00835 
00836             x_pos = dvbsub_read_4bit_string(pbuf + (y_pos * region->width),
00837                                             region->width, &buf, buf_end - buf,
00838                                             non_mod, map_table, x_pos);
00839             break;
00840         case 0x12:
00841             if (region->depth < 8) {
00842                 av_log(avctx, AV_LOG_ERROR, "8-bit pixel string in %d-bit region!\n", region->depth);
00843                 return;
00844             }
00845 
00846             x_pos = dvbsub_read_8bit_string(pbuf + (y_pos * region->width),
00847                                             region->width, &buf, buf_end - buf,
00848                                             non_mod, NULL, x_pos);
00849             break;
00850 
00851         case 0x20:
00852             map2to4[0] = (*buf) >> 4;
00853             map2to4[1] = (*buf++) & 0xf;
00854             map2to4[2] = (*buf) >> 4;
00855             map2to4[3] = (*buf++) & 0xf;
00856             break;
00857         case 0x21:
00858             for (i = 0; i < 4; i++)
00859                 map2to8[i] = *buf++;
00860             break;
00861         case 0x22:
00862             for (i = 0; i < 16; i++)
00863                 map4to8[i] = *buf++;
00864             break;
00865 
00866         case 0xf0:
00867             x_pos = display->x_pos;
00868             y_pos += 2;
00869             break;
00870         default:
00871             av_log(avctx, AV_LOG_INFO, "Unknown/unsupported pixel block 0x%x\n", *(buf-1));
00872         }
00873     }
00874 
00875 }
00876 
00877 static void dvbsub_parse_object_segment(AVCodecContext *avctx,
00878                                         const uint8_t *buf, int buf_size)
00879 {
00880     DVBSubContext *ctx = avctx->priv_data;
00881 
00882     const uint8_t *buf_end = buf + buf_size;
00883     int object_id;
00884     DVBSubObject *object;
00885     DVBSubObjectDisplay *display;
00886     int top_field_len, bottom_field_len;
00887 
00888     int coding_method, non_modifying_color;
00889 
00890     object_id = AV_RB16(buf);
00891     buf += 2;
00892 
00893     object = get_object(ctx, object_id);
00894 
00895     if (!object)
00896         return;
00897 
00898     coding_method = ((*buf) >> 2) & 3;
00899     non_modifying_color = ((*buf++) >> 1) & 1;
00900 
00901     if (coding_method == 0) {
00902         top_field_len = AV_RB16(buf);
00903         buf += 2;
00904         bottom_field_len = AV_RB16(buf);
00905         buf += 2;
00906 
00907         if (buf + top_field_len + bottom_field_len > buf_end) {
00908             av_log(avctx, AV_LOG_ERROR, "Field data size too large\n");
00909             return;
00910         }
00911 
00912         for (display = object->display_list; display; display = display->object_list_next) {
00913             const uint8_t *block = buf;
00914             int bfl = bottom_field_len;
00915 
00916             dvbsub_parse_pixel_data_block(avctx, display, block, top_field_len, 0,
00917                                             non_modifying_color);
00918 
00919             if (bottom_field_len > 0)
00920                 block = buf + top_field_len;
00921             else
00922                 bfl = top_field_len;
00923 
00924             dvbsub_parse_pixel_data_block(avctx, display, block, bfl, 1,
00925                                             non_modifying_color);
00926         }
00927 
00928 /*  } else if (coding_method == 1) {*/
00929 
00930     } else {
00931         av_log(avctx, AV_LOG_ERROR, "Unknown object coding %d\n", coding_method);
00932     }
00933 
00934 }
00935 
00936 static void dvbsub_parse_clut_segment(AVCodecContext *avctx,
00937                                         const uint8_t *buf, int buf_size)
00938 {
00939     DVBSubContext *ctx = avctx->priv_data;
00940 
00941     const uint8_t *buf_end = buf + buf_size;
00942     int i, clut_id;
00943     int version;
00944     DVBSubCLUT *clut;
00945     int entry_id, depth , full_range;
00946     int y, cr, cb, alpha;
00947     int r, g, b, r_add, g_add, b_add;
00948 
00949     av_dlog(avctx, "DVB clut packet:\n");
00950 
00951     for (i=0; i < buf_size; i++) {
00952         av_dlog(avctx, "%02x ", buf[i]);
00953         if (i % 16 == 15)
00954             av_dlog(avctx, "\n");
00955     }
00956 
00957     if (i % 16)
00958         av_dlog(avctx, "\n");
00959 
00960     clut_id = *buf++;
00961     version = ((*buf)>>4)&15;
00962     buf += 1;
00963 
00964     clut = get_clut(ctx, clut_id);
00965 
00966     if (!clut) {
00967         clut = av_malloc(sizeof(DVBSubCLUT));
00968 
00969         memcpy(clut, &default_clut, sizeof(DVBSubCLUT));
00970 
00971         clut->id = clut_id;
00972         clut->version = -1;
00973 
00974         clut->next = ctx->clut_list;
00975         ctx->clut_list = clut;
00976     }
00977 
00978     if (clut->version != version) {
00979 
00980     clut->version = version;
00981 
00982     while (buf + 4 < buf_end) {
00983         entry_id = *buf++;
00984 
00985         depth = (*buf) & 0xe0;
00986 
00987         if (depth == 0) {
00988             av_log(avctx, AV_LOG_ERROR, "Invalid clut depth 0x%x!\n", *buf);
00989             return;
00990         }
00991 
00992         full_range = (*buf++) & 1;
00993 
00994         if (full_range) {
00995             y = *buf++;
00996             cr = *buf++;
00997             cb = *buf++;
00998             alpha = *buf++;
00999         } else {
01000             y = buf[0] & 0xfc;
01001             cr = (((buf[0] & 3) << 2) | ((buf[1] >> 6) & 3)) << 4;
01002             cb = (buf[1] << 2) & 0xf0;
01003             alpha = (buf[1] << 6) & 0xc0;
01004 
01005             buf += 2;
01006         }
01007 
01008         if (y == 0)
01009             alpha = 0xff;
01010 
01011         YUV_TO_RGB1_CCIR(cb, cr);
01012         YUV_TO_RGB2_CCIR(r, g, b, y);
01013 
01014         av_dlog(avctx, "clut %d := (%d,%d,%d,%d)\n", entry_id, r, g, b, alpha);
01015 
01016         if (depth & 0x80)
01017             clut->clut4[entry_id] = RGBA(r,g,b,255 - alpha);
01018         if (depth & 0x40)
01019             clut->clut16[entry_id] = RGBA(r,g,b,255 - alpha);
01020         if (depth & 0x20)
01021             clut->clut256[entry_id] = RGBA(r,g,b,255 - alpha);
01022     }
01023     }
01024 }
01025 
01026 
01027 static void dvbsub_parse_region_segment(AVCodecContext *avctx,
01028                                         const uint8_t *buf, int buf_size)
01029 {
01030     DVBSubContext *ctx = avctx->priv_data;
01031 
01032     const uint8_t *buf_end = buf + buf_size;
01033     int region_id, object_id;
01034     int version;
01035     DVBSubRegion *region;
01036     DVBSubObject *object;
01037     DVBSubObjectDisplay *display;
01038     int fill;
01039 
01040     if (buf_size < 10)
01041         return;
01042 
01043     region_id = *buf++;
01044 
01045     region = get_region(ctx, region_id);
01046 
01047     if (!region) {
01048         region = av_mallocz(sizeof(DVBSubRegion));
01049 
01050         region->id = region_id;
01051         region->version = -1;
01052 
01053         region->next = ctx->region_list;
01054         ctx->region_list = region;
01055     }
01056 
01057     version = ((*buf)>>4) & 15;
01058     fill = ((*buf++) >> 3) & 1;
01059 
01060     region->width = AV_RB16(buf);
01061     buf += 2;
01062     region->height = AV_RB16(buf);
01063     buf += 2;
01064 
01065     if (region->width * region->height != region->buf_size) {
01066         av_free(region->pbuf);
01067 
01068         region->buf_size = region->width * region->height;
01069 
01070         region->pbuf = av_malloc(region->buf_size);
01071 
01072         fill = 1;
01073         region->dirty = 0;
01074     }
01075 
01076     region->depth = 1 << (((*buf++) >> 2) & 7);
01077     if(region->depth<2 || region->depth>8){
01078         av_log(avctx, AV_LOG_ERROR, "region depth %d is invalid\n", region->depth);
01079         region->depth= 4;
01080     }
01081     region->clut = *buf++;
01082 
01083     if (region->depth == 8) {
01084         region->bgcolor = *buf++;
01085         buf += 1;
01086     } else {
01087         buf += 1;
01088 
01089         if (region->depth == 4)
01090             region->bgcolor = (((*buf++) >> 4) & 15);
01091         else
01092             region->bgcolor = (((*buf++) >> 2) & 3);
01093     }
01094 
01095     av_dlog(avctx, "Region %d, (%dx%d)\n", region_id, region->width, region->height);
01096 
01097     if (fill) {
01098         memset(region->pbuf, region->bgcolor, region->buf_size);
01099         av_dlog(avctx, "Fill region (%d)\n", region->bgcolor);
01100     }
01101 
01102     delete_region_display_list(ctx, region);
01103 
01104     while (buf + 5 < buf_end) {
01105         object_id = AV_RB16(buf);
01106         buf += 2;
01107 
01108         object = get_object(ctx, object_id);
01109 
01110         if (!object) {
01111             object = av_mallocz(sizeof(DVBSubObject));
01112 
01113             object->id = object_id;
01114             object->next = ctx->object_list;
01115             ctx->object_list = object;
01116         }
01117 
01118         object->type = (*buf) >> 6;
01119 
01120         display = av_mallocz(sizeof(DVBSubObjectDisplay));
01121 
01122         display->object_id = object_id;
01123         display->region_id = region_id;
01124 
01125         display->x_pos = AV_RB16(buf) & 0xfff;
01126         buf += 2;
01127         display->y_pos = AV_RB16(buf) & 0xfff;
01128         buf += 2;
01129 
01130         if ((object->type == 1 || object->type == 2) && buf+1 < buf_end) {
01131             display->fgcolor = *buf++;
01132             display->bgcolor = *buf++;
01133         }
01134 
01135         display->region_list_next = region->display_list;
01136         region->display_list = display;
01137 
01138         display->object_list_next = object->display_list;
01139         object->display_list = display;
01140     }
01141 }
01142 
01143 static void dvbsub_parse_page_segment(AVCodecContext *avctx,
01144                                         const uint8_t *buf, int buf_size)
01145 {
01146     DVBSubContext *ctx = avctx->priv_data;
01147     DVBSubRegionDisplay *display;
01148     DVBSubRegionDisplay *tmp_display_list, **tmp_ptr;
01149 
01150     const uint8_t *buf_end = buf + buf_size;
01151     int region_id;
01152     int page_state;
01153     int timeout;
01154     int version;
01155 
01156     if (buf_size < 1)
01157         return;
01158 
01159     timeout = *buf++;
01160     version = ((*buf)>>4) & 15;
01161     page_state = ((*buf++) >> 2) & 3;
01162 
01163     if (ctx->version != version) {
01164 
01165     ctx->time_out = timeout;
01166     ctx->version = version;
01167 
01168     av_dlog(avctx, "Page time out %ds, state %d\n", ctx->time_out, page_state);
01169 
01170     if (page_state == 1 || page_state == 2) {
01171         delete_regions(ctx);
01172         delete_objects(ctx);
01173         delete_cluts(ctx);
01174     }
01175 
01176     tmp_display_list = ctx->display_list;
01177     ctx->display_list = NULL;
01178     ctx->display_list_size = 0;
01179 
01180     while (buf + 5 < buf_end) {
01181         region_id = *buf++;
01182         buf += 1;
01183 
01184         display = tmp_display_list;
01185         tmp_ptr = &tmp_display_list;
01186 
01187         while (display && display->region_id != region_id) {
01188             tmp_ptr = &display->next;
01189             display = display->next;
01190         }
01191 
01192         if (!display)
01193             display = av_mallocz(sizeof(DVBSubRegionDisplay));
01194 
01195         display->region_id = region_id;
01196 
01197         display->x_pos = AV_RB16(buf);
01198         buf += 2;
01199         display->y_pos = AV_RB16(buf);
01200         buf += 2;
01201 
01202         *tmp_ptr = display->next;
01203 
01204         display->next = ctx->display_list;
01205         ctx->display_list = display;
01206         ctx->display_list_size++;
01207 
01208         av_dlog(avctx, "Region %d, (%d,%d)\n", region_id, display->x_pos, display->y_pos);
01209     }
01210 
01211     while (tmp_display_list) {
01212         display = tmp_display_list;
01213 
01214         tmp_display_list = display->next;
01215 
01216         av_free(display);
01217     }
01218     }
01219 
01220 }
01221 
01222 
01223 #ifdef DEBUG
01224 static void save_display_set(DVBSubContext *ctx)
01225 {
01226     DVBSubRegion *region;
01227     DVBSubRegionDisplay *display;
01228     DVBSubCLUT *clut;
01229     uint32_t *clut_table;
01230     int x_pos, y_pos, width, height;
01231     int x, y, y_off, x_off;
01232     uint32_t *pbuf;
01233     char filename[32];
01234     static int fileno_index = 0;
01235 
01236     x_pos = -1;
01237     y_pos = -1;
01238     width = 0;
01239     height = 0;
01240 
01241     for (display = ctx->display_list; display; display = display->next) {
01242         region = get_region(ctx, display->region_id);
01243 
01244         if (x_pos == -1) {
01245             x_pos = display->x_pos;
01246             y_pos = display->y_pos;
01247             width = region->width;
01248             height = region->height;
01249         } else {
01250             if (display->x_pos < x_pos) {
01251                 width += (x_pos - display->x_pos);
01252                 x_pos = display->x_pos;
01253             }
01254 
01255             if (display->y_pos < y_pos) {
01256                 height += (y_pos - display->y_pos);
01257                 y_pos = display->y_pos;
01258             }
01259 
01260             if (display->x_pos + region->width > x_pos + width) {
01261                 width = display->x_pos + region->width - x_pos;
01262             }
01263 
01264             if (display->y_pos + region->height > y_pos + height) {
01265                 height = display->y_pos + region->height - y_pos;
01266             }
01267         }
01268     }
01269 
01270     if (x_pos >= 0) {
01271 
01272         pbuf = av_malloc(width * height * 4);
01273 
01274         for (display = ctx->display_list; display; display = display->next) {
01275             region = get_region(ctx, display->region_id);
01276 
01277             x_off = display->x_pos - x_pos;
01278             y_off = display->y_pos - y_pos;
01279 
01280             clut = get_clut(ctx, region->clut);
01281 
01282             if (clut == 0)
01283                 clut = &default_clut;
01284 
01285             switch (region->depth) {
01286             case 2:
01287                 clut_table = clut->clut4;
01288                 break;
01289             case 8:
01290                 clut_table = clut->clut256;
01291                 break;
01292             case 4:
01293             default:
01294                 clut_table = clut->clut16;
01295                 break;
01296             }
01297 
01298             for (y = 0; y < region->height; y++) {
01299                 for (x = 0; x < region->width; x++) {
01300                     pbuf[((y + y_off) * width) + x_off + x] =
01301                         clut_table[region->pbuf[y * region->width + x]];
01302                 }
01303             }
01304 
01305         }
01306 
01307         snprintf(filename, sizeof(filename), "dvbs.%d", fileno_index);
01308 
01309         png_save2(filename, pbuf, width, height);
01310 
01311         av_free(pbuf);
01312     }
01313 
01314     fileno_index++;
01315 }
01316 #endif
01317 
01318 static void dvbsub_parse_display_definition_segment(AVCodecContext *avctx,
01319                                                     const uint8_t *buf,
01320                                                     int buf_size)
01321 {
01322     DVBSubContext *ctx = avctx->priv_data;
01323     DVBSubDisplayDefinition *display_def = ctx->display_definition;
01324     int dds_version, info_byte;
01325 
01326     if (buf_size < 5)
01327         return;
01328 
01329     info_byte   = bytestream_get_byte(&buf);
01330     dds_version = info_byte >> 4;
01331     if (display_def && display_def->version == dds_version)
01332         return; // already have this display definition version
01333 
01334     if (!display_def) {
01335         display_def             = av_mallocz(sizeof(*display_def));
01336         ctx->display_definition = display_def;
01337     }
01338     if (!display_def)
01339         return;
01340 
01341     display_def->version = dds_version;
01342     display_def->x       = 0;
01343     display_def->y       = 0;
01344     display_def->width   = bytestream_get_be16(&buf) + 1;
01345     display_def->height  = bytestream_get_be16(&buf) + 1;
01346 
01347     if (buf_size < 13)
01348         return;
01349 
01350     if (info_byte & 1<<3) { // display_window_flag
01351         display_def->x = bytestream_get_be16(&buf);
01352         display_def->y = bytestream_get_be16(&buf);
01353         display_def->width  = bytestream_get_be16(&buf) - display_def->x + 1;
01354         display_def->height = bytestream_get_be16(&buf) - display_def->y + 1;
01355     }
01356 }
01357 
01358 static int dvbsub_display_end_segment(AVCodecContext *avctx, const uint8_t *buf,
01359                                         int buf_size, AVSubtitle *sub)
01360 {
01361     DVBSubContext *ctx = avctx->priv_data;
01362     DVBSubDisplayDefinition *display_def = ctx->display_definition;
01363 
01364     DVBSubRegion *region;
01365     DVBSubRegionDisplay *display;
01366     AVSubtitleRect *rect;
01367     DVBSubCLUT *clut;
01368     uint32_t *clut_table;
01369     int i;
01370     int offset_x=0, offset_y=0;
01371 
01372     sub->end_display_time = ctx->time_out * 1000;
01373 
01374     if (display_def) {
01375         offset_x = display_def->x;
01376         offset_y = display_def->y;
01377     }
01378 
01379     sub->num_rects = ctx->display_list_size;
01380 
01381     if (sub->num_rects > 0){
01382         sub->rects = av_mallocz(sizeof(*sub->rects) * sub->num_rects);
01383         for(i=0; i<sub->num_rects; i++)
01384             sub->rects[i] = av_mallocz(sizeof(*sub->rects[i]));
01385 
01386     i = 0;
01387 
01388     for (display = ctx->display_list; display; display = display->next) {
01389         region = get_region(ctx, display->region_id);
01390 
01391         if (!region)
01392             continue;
01393 
01394         if (!region->dirty)
01395             continue;
01396 
01397         rect = sub->rects[i];
01398         rect->x = display->x_pos + offset_x;
01399         rect->y = display->y_pos + offset_y;
01400         rect->w = region->width;
01401         rect->h = region->height;
01402         rect->nb_colors = (1 << region->depth);
01403         rect->type      = SUBTITLE_BITMAP;
01404         rect->pict.linesize[0] = region->width;
01405 
01406         clut = get_clut(ctx, region->clut);
01407 
01408         if (!clut)
01409             clut = &default_clut;
01410 
01411         switch (region->depth) {
01412         case 2:
01413             clut_table = clut->clut4;
01414             break;
01415         case 8:
01416             clut_table = clut->clut256;
01417             break;
01418         case 4:
01419         default:
01420             clut_table = clut->clut16;
01421             break;
01422         }
01423 
01424         rect->pict.data[1] = av_mallocz(AVPALETTE_SIZE);
01425         memcpy(rect->pict.data[1], clut_table, (1 << region->depth) * sizeof(uint32_t));
01426 
01427         rect->pict.data[0] = av_malloc(region->buf_size);
01428         memcpy(rect->pict.data[0], region->pbuf, region->buf_size);
01429 
01430         i++;
01431     }
01432 
01433     sub->num_rects = i;
01434     }
01435 #ifdef DEBUG
01436     save_display_set(ctx);
01437 #endif
01438 
01439     return 1;
01440 }
01441 
01442 static int dvbsub_decode(AVCodecContext *avctx,
01443                          void *data, int *data_size,
01444                          AVPacket *avpkt)
01445 {
01446     const uint8_t *buf = avpkt->data;
01447     int buf_size = avpkt->size;
01448     DVBSubContext *ctx = avctx->priv_data;
01449     AVSubtitle *sub = data;
01450     const uint8_t *p, *p_end;
01451     int segment_type;
01452     int page_id;
01453     int segment_length;
01454     int i;
01455 
01456     av_dlog(avctx, "DVB sub packet:\n");
01457 
01458     for (i=0; i < buf_size; i++) {
01459         av_dlog(avctx, "%02x ", buf[i]);
01460         if (i % 16 == 15)
01461             av_dlog(avctx, "\n");
01462     }
01463 
01464     if (i % 16)
01465         av_dlog(avctx, "\n");
01466 
01467     if (buf_size <= 6 || *buf != 0x0f) {
01468         av_dlog(avctx, "incomplete or broken packet");
01469         return -1;
01470     }
01471 
01472     p = buf;
01473     p_end = buf + buf_size;
01474 
01475     while (p_end - p >= 6 && *p == 0x0f) {
01476         p += 1;
01477         segment_type = *p++;
01478         page_id = AV_RB16(p);
01479         p += 2;
01480         segment_length = AV_RB16(p);
01481         p += 2;
01482 
01483         if (p_end - p < segment_length) {
01484             av_dlog(avctx, "incomplete or broken packet");
01485             return -1;
01486         }
01487 
01488         if (page_id == ctx->composition_id || page_id == ctx->ancillary_id ||
01489             ctx->composition_id == -1 || ctx->ancillary_id == -1) {
01490             switch (segment_type) {
01491             case DVBSUB_PAGE_SEGMENT:
01492                 dvbsub_parse_page_segment(avctx, p, segment_length);
01493                 break;
01494             case DVBSUB_REGION_SEGMENT:
01495                 dvbsub_parse_region_segment(avctx, p, segment_length);
01496                 break;
01497             case DVBSUB_CLUT_SEGMENT:
01498                 dvbsub_parse_clut_segment(avctx, p, segment_length);
01499                 break;
01500             case DVBSUB_OBJECT_SEGMENT:
01501                 dvbsub_parse_object_segment(avctx, p, segment_length);
01502                 break;
01503             case DVBSUB_DISPLAYDEFINITION_SEGMENT:
01504                 dvbsub_parse_display_definition_segment(avctx, p, segment_length);
01505                 break;
01506             case DVBSUB_DISPLAY_SEGMENT:
01507                 *data_size = dvbsub_display_end_segment(avctx, p, segment_length, sub);
01508                 break;
01509             default:
01510                 av_dlog(avctx, "Subtitling segment type 0x%x, page id %d, length %d\n",
01511                         segment_type, page_id, segment_length);
01512                 break;
01513             }
01514         }
01515 
01516         p += segment_length;
01517     }
01518 
01519     return p - buf;
01520 }
01521 
01522 
01523 AVCodec ff_dvbsub_decoder = {
01524     .name           = "dvbsub",
01525     .type           = AVMEDIA_TYPE_SUBTITLE,
01526     .id             = CODEC_ID_DVB_SUBTITLE,
01527     .priv_data_size = sizeof(DVBSubContext),
01528     .init           = dvbsub_init_decoder,
01529     .close          = dvbsub_close_decoder,
01530     .decode         = dvbsub_decode,
01531     .long_name = NULL_IF_CONFIG_SMALL("DVB subtitles"),
01532 };