• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • Examples
  • File List
  • Globals

libavcodec/dvbsubdec.c

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

Generated on Wed Apr 11 2012 07:31:33 for FFmpeg by  doxygen 1.7.1