LCOV - code coverage report
Current view: top level - libavcodec - dvbsubdec.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 75 828 9.1 %
Date: 2017-12-18 20:14:19 Functions: 5 22 22.7 %

          Line data    Source code
       1             : /*
       2             :  * DVB subtitle decoding
       3             :  * Copyright (c) 2005 Ian Caulfield
       4             :  *
       5             :  * This file is part of FFmpeg.
       6             :  *
       7             :  * FFmpeg is free software; you can redistribute it and/or
       8             :  * modify it under the terms of the GNU Lesser General Public
       9             :  * License as published by the Free Software Foundation; either
      10             :  * version 2.1 of the License, or (at your option) any later version.
      11             :  *
      12             :  * FFmpeg is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :  * Lesser General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU Lesser General Public
      18             :  * License along with FFmpeg; if not, write to the Free Software
      19             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
      20             :  */
      21             : 
      22             : #include "avcodec.h"
      23             : #include "get_bits.h"
      24             : #include "bytestream.h"
      25             : #include "internal.h"
      26             : #include "libavutil/colorspace.h"
      27             : #include "libavutil/imgutils.h"
      28             : #include "libavutil/opt.h"
      29             : 
      30             : #define DVBSUB_PAGE_SEGMENT     0x10
      31             : #define DVBSUB_REGION_SEGMENT   0x11
      32             : #define DVBSUB_CLUT_SEGMENT     0x12
      33             : #define DVBSUB_OBJECT_SEGMENT   0x13
      34             : #define DVBSUB_DISPLAYDEFINITION_SEGMENT 0x14
      35             : #define DVBSUB_DISPLAY_SEGMENT  0x80
      36             : 
      37             : #define cm (ff_crop_tab + MAX_NEG_CROP)
      38             : 
      39             : #define RGBA(r,g,b,a) (((unsigned)(a) << 24) | ((r) << 16) | ((g) << 8) | (b))
      40             : 
      41             : typedef struct DVBSubCLUT {
      42             :     int id;
      43             :     int version;
      44             : 
      45             :     uint32_t clut4[4];
      46             :     uint32_t clut16[16];
      47             :     uint32_t clut256[256];
      48             : 
      49             :     struct DVBSubCLUT *next;
      50             : } DVBSubCLUT;
      51             : 
      52             : static DVBSubCLUT default_clut;
      53             : 
      54             : typedef struct DVBSubObjectDisplay {
      55             :     int object_id;
      56             :     int region_id;
      57             : 
      58             :     int x_pos;
      59             :     int y_pos;
      60             : 
      61             :     int fgcolor;
      62             :     int bgcolor;
      63             : 
      64             :     struct DVBSubObjectDisplay *region_list_next;
      65             :     struct DVBSubObjectDisplay *object_list_next;
      66             : } DVBSubObjectDisplay;
      67             : 
      68             : typedef struct DVBSubObject {
      69             :     int id;
      70             :     int version;
      71             : 
      72             :     int type;
      73             : 
      74             :     DVBSubObjectDisplay *display_list;
      75             : 
      76             :     struct DVBSubObject *next;
      77             : } DVBSubObject;
      78             : 
      79             : typedef struct DVBSubRegionDisplay {
      80             :     int region_id;
      81             : 
      82             :     int x_pos;
      83             :     int y_pos;
      84             : 
      85             :     struct DVBSubRegionDisplay *next;
      86             : } DVBSubRegionDisplay;
      87             : 
      88             : typedef struct DVBSubRegion {
      89             :     int id;
      90             :     int version;
      91             : 
      92             :     int width;
      93             :     int height;
      94             :     int depth;
      95             : 
      96             :     int clut;
      97             :     int bgcolor;
      98             : 
      99             :     uint8_t computed_clut[4*256];
     100             :     int has_computed_clut;
     101             : 
     102             :     uint8_t *pbuf;
     103             :     int buf_size;
     104             :     int dirty;
     105             : 
     106             :     DVBSubObjectDisplay *display_list;
     107             : 
     108             :     struct DVBSubRegion *next;
     109             : } DVBSubRegion;
     110             : 
     111             : typedef struct DVBSubDisplayDefinition {
     112             :     int version;
     113             : 
     114             :     int x;
     115             :     int y;
     116             :     int width;
     117             :     int height;
     118             : } DVBSubDisplayDefinition;
     119             : 
     120             : typedef struct DVBSubContext {
     121             :     AVClass *class;
     122             :     int composition_id;
     123             :     int ancillary_id;
     124             : 
     125             :     int version;
     126             :     int time_out;
     127             :     int compute_edt; /**< if 1 end display time calculated using pts
     128             :                           if 0 (Default) calculated using time out */
     129             :     int compute_clut;
     130             :     int substream;
     131             :     int64_t prev_start;
     132             :     DVBSubRegion *region_list;
     133             :     DVBSubCLUT   *clut_list;
     134             :     DVBSubObject *object_list;
     135             : 
     136             :     DVBSubRegionDisplay *display_list;
     137             :     DVBSubDisplayDefinition *display_definition;
     138             : } DVBSubContext;
     139             : 
     140             : 
     141           0 : static DVBSubObject* get_object(DVBSubContext *ctx, int object_id)
     142             : {
     143           0 :     DVBSubObject *ptr = ctx->object_list;
     144             : 
     145           0 :     while (ptr && ptr->id != object_id) {
     146           0 :         ptr = ptr->next;
     147             :     }
     148             : 
     149           0 :     return ptr;
     150             : }
     151             : 
     152           0 : static DVBSubCLUT* get_clut(DVBSubContext *ctx, int clut_id)
     153             : {
     154           0 :     DVBSubCLUT *ptr = ctx->clut_list;
     155             : 
     156           0 :     while (ptr && ptr->id != clut_id) {
     157           0 :         ptr = ptr->next;
     158             :     }
     159             : 
     160           0 :     return ptr;
     161             : }
     162             : 
     163           0 : static DVBSubRegion* get_region(DVBSubContext *ctx, int region_id)
     164             : {
     165           0 :     DVBSubRegion *ptr = ctx->region_list;
     166             : 
     167           0 :     while (ptr && ptr->id != region_id) {
     168           0 :         ptr = ptr->next;
     169             :     }
     170             : 
     171           0 :     return ptr;
     172             : }
     173             : 
     174           0 : static void delete_region_display_list(DVBSubContext *ctx, DVBSubRegion *region)
     175             : {
     176             :     DVBSubObject *object, *obj2, **obj2_ptr;
     177             :     DVBSubObjectDisplay *display, *obj_disp, **obj_disp_ptr;
     178             : 
     179           0 :     while (region->display_list) {
     180           0 :         display = region->display_list;
     181             : 
     182           0 :         object = get_object(ctx, display->object_id);
     183             : 
     184           0 :         if (object) {
     185           0 :             obj_disp_ptr = &object->display_list;
     186           0 :             obj_disp = *obj_disp_ptr;
     187             : 
     188           0 :             while (obj_disp && obj_disp != display) {
     189           0 :                 obj_disp_ptr = &obj_disp->object_list_next;
     190           0 :                 obj_disp = *obj_disp_ptr;
     191             :             }
     192             : 
     193           0 :             if (obj_disp) {
     194           0 :                 *obj_disp_ptr = obj_disp->object_list_next;
     195             : 
     196           0 :                 if (!object->display_list) {
     197           0 :                     obj2_ptr = &ctx->object_list;
     198           0 :                     obj2 = *obj2_ptr;
     199             : 
     200           0 :                     while (obj2 != object) {
     201           0 :                         av_assert0(obj2);
     202           0 :                         obj2_ptr = &obj2->next;
     203           0 :                         obj2 = *obj2_ptr;
     204             :                     }
     205             : 
     206           0 :                     *obj2_ptr = obj2->next;
     207             : 
     208           0 :                     av_freep(&obj2);
     209             :                 }
     210             :             }
     211             :         }
     212             : 
     213           0 :         region->display_list = display->region_list_next;
     214             : 
     215           0 :         av_freep(&display);
     216             :     }
     217             : 
     218           0 : }
     219             : 
     220           1 : static void delete_cluts(DVBSubContext *ctx)
     221             : {
     222           2 :     while (ctx->clut_list) {
     223           0 :         DVBSubCLUT *clut = ctx->clut_list;
     224             : 
     225           0 :         ctx->clut_list = clut->next;
     226             : 
     227           0 :         av_freep(&clut);
     228             :     }
     229           1 : }
     230             : 
     231           1 : static void delete_objects(DVBSubContext *ctx)
     232             : {
     233           2 :     while (ctx->object_list) {
     234           0 :         DVBSubObject *object = ctx->object_list;
     235             : 
     236           0 :         ctx->object_list = object->next;
     237             : 
     238           0 :         av_freep(&object);
     239             :     }
     240           1 : }
     241             : 
     242           1 : static void delete_regions(DVBSubContext *ctx)
     243             : {
     244           2 :     while (ctx->region_list) {
     245           0 :         DVBSubRegion *region = ctx->region_list;
     246             : 
     247           0 :         ctx->region_list = region->next;
     248             : 
     249           0 :         delete_region_display_list(ctx, region);
     250             : 
     251           0 :         av_freep(&region->pbuf);
     252           0 :         av_freep(&region);
     253             :     }
     254           1 : }
     255             : 
     256           1 : static av_cold int dvbsub_init_decoder(AVCodecContext *avctx)
     257             : {
     258           1 :     int i, r, g, b, a = 0;
     259           1 :     DVBSubContext *ctx = avctx->priv_data;
     260             : 
     261           1 :     if (ctx->substream < 0) {
     262           1 :         ctx->composition_id = -1;
     263           1 :         ctx->ancillary_id   = -1;
     264           0 :     } else if (!avctx->extradata || (avctx->extradata_size < 4) || ((avctx->extradata_size % 5 != 0) && (avctx->extradata_size != 4))) {
     265           0 :         av_log(avctx, AV_LOG_WARNING, "Invalid DVB subtitles stream extradata!\n");
     266           0 :         ctx->composition_id = -1;
     267           0 :         ctx->ancillary_id   = -1;
     268             :     } else {
     269           0 :         if (avctx->extradata_size > 5*ctx->substream + 2) {
     270           0 :             ctx->composition_id = AV_RB16(avctx->extradata + 5*ctx->substream);
     271           0 :             ctx->ancillary_id   = AV_RB16(avctx->extradata + 5*ctx->substream + 2);
     272             :         } else {
     273           0 :             av_log(avctx, AV_LOG_WARNING, "Selected DVB subtitles sub-stream %d is not available\n", ctx->substream);
     274           0 :             ctx->composition_id = AV_RB16(avctx->extradata);
     275           0 :             ctx->ancillary_id   = AV_RB16(avctx->extradata + 2);
     276             :         }
     277             :     }
     278             : 
     279           1 :     ctx->version = -1;
     280           1 :     ctx->prev_start = AV_NOPTS_VALUE;
     281             : 
     282           1 :     default_clut.id = -1;
     283           1 :     default_clut.next = NULL;
     284             : 
     285           1 :     default_clut.clut4[0] = RGBA(  0,   0,   0,   0);
     286           1 :     default_clut.clut4[1] = RGBA(255, 255, 255, 255);
     287           1 :     default_clut.clut4[2] = RGBA(  0,   0,   0, 255);
     288           1 :     default_clut.clut4[3] = RGBA(127, 127, 127, 255);
     289             : 
     290           1 :     default_clut.clut16[0] = RGBA(  0,   0,   0,   0);
     291          16 :     for (i = 1; i < 16; i++) {
     292          15 :         if (i < 8) {
     293           7 :             r = (i & 1) ? 255 : 0;
     294           7 :             g = (i & 2) ? 255 : 0;
     295           7 :             b = (i & 4) ? 255 : 0;
     296             :         } else {
     297           8 :             r = (i & 1) ? 127 : 0;
     298           8 :             g = (i & 2) ? 127 : 0;
     299           8 :             b = (i & 4) ? 127 : 0;
     300             :         }
     301          15 :         default_clut.clut16[i] = RGBA(r, g, b, 255);
     302             :     }
     303             : 
     304           1 :     default_clut.clut256[0] = RGBA(  0,   0,   0,   0);
     305         256 :     for (i = 1; i < 256; i++) {
     306         255 :         if (i < 8) {
     307           7 :             r = (i & 1) ? 255 : 0;
     308           7 :             g = (i & 2) ? 255 : 0;
     309           7 :             b = (i & 4) ? 255 : 0;
     310           7 :             a = 63;
     311             :         } else {
     312         248 :             switch (i & 0x88) {
     313          56 :             case 0x00:
     314          56 :                 r = ((i & 1) ? 85 : 0) + ((i & 0x10) ? 170 : 0);
     315          56 :                 g = ((i & 2) ? 85 : 0) + ((i & 0x20) ? 170 : 0);
     316          56 :                 b = ((i & 4) ? 85 : 0) + ((i & 0x40) ? 170 : 0);
     317          56 :                 a = 255;
     318          56 :                 break;
     319          64 :             case 0x08:
     320          64 :                 r = ((i & 1) ? 85 : 0) + ((i & 0x10) ? 170 : 0);
     321          64 :                 g = ((i & 2) ? 85 : 0) + ((i & 0x20) ? 170 : 0);
     322          64 :                 b = ((i & 4) ? 85 : 0) + ((i & 0x40) ? 170 : 0);
     323          64 :                 a = 127;
     324          64 :                 break;
     325          64 :             case 0x80:
     326          64 :                 r = 127 + ((i & 1) ? 43 : 0) + ((i & 0x10) ? 85 : 0);
     327          64 :                 g = 127 + ((i & 2) ? 43 : 0) + ((i & 0x20) ? 85 : 0);
     328          64 :                 b = 127 + ((i & 4) ? 43 : 0) + ((i & 0x40) ? 85 : 0);
     329          64 :                 a = 255;
     330          64 :                 break;
     331          64 :             case 0x88:
     332          64 :                 r = ((i & 1) ? 43 : 0) + ((i & 0x10) ? 85 : 0);
     333          64 :                 g = ((i & 2) ? 43 : 0) + ((i & 0x20) ? 85 : 0);
     334          64 :                 b = ((i & 4) ? 43 : 0) + ((i & 0x40) ? 85 : 0);
     335          64 :                 a = 255;
     336          64 :                 break;
     337             :             }
     338             :         }
     339         255 :         default_clut.clut256[i] = RGBA(r, g, b, a);
     340             :     }
     341             : 
     342           1 :     return 0;
     343             : }
     344             : 
     345           1 : static av_cold int dvbsub_close_decoder(AVCodecContext *avctx)
     346             : {
     347           1 :     DVBSubContext *ctx = avctx->priv_data;
     348             :     DVBSubRegionDisplay *display;
     349             : 
     350           1 :     delete_regions(ctx);
     351             : 
     352           1 :     delete_objects(ctx);
     353             : 
     354           1 :     delete_cluts(ctx);
     355             : 
     356           1 :     av_freep(&ctx->display_definition);
     357             : 
     358           2 :     while (ctx->display_list) {
     359           0 :         display = ctx->display_list;
     360           0 :         ctx->display_list = display->next;
     361             : 
     362           0 :         av_freep(&display);
     363             :     }
     364             : 
     365           1 :     return 0;
     366             : }
     367             : 
     368           0 : static int dvbsub_read_2bit_string(AVCodecContext *avctx,
     369             :                                    uint8_t *destbuf, int dbuf_len,
     370             :                                    const uint8_t **srcbuf, int buf_size,
     371             :                                    int non_mod, uint8_t *map_table, int x_pos)
     372             : {
     373             :     GetBitContext gb;
     374             : 
     375             :     int bits;
     376             :     int run_length;
     377           0 :     int pixels_read = x_pos;
     378             : 
     379           0 :     init_get_bits(&gb, *srcbuf, buf_size << 3);
     380             : 
     381           0 :     destbuf += x_pos;
     382             : 
     383           0 :     while (get_bits_count(&gb) < buf_size << 3 && pixels_read < dbuf_len) {
     384           0 :         bits = get_bits(&gb, 2);
     385             : 
     386           0 :         if (bits) {
     387           0 :             if (non_mod != 1 || bits != 1) {
     388           0 :                 if (map_table)
     389           0 :                     *destbuf++ = map_table[bits];
     390             :                 else
     391           0 :                     *destbuf++ = bits;
     392             :             }
     393           0 :             pixels_read++;
     394             :         } else {
     395           0 :             bits = get_bits1(&gb);
     396           0 :             if (bits == 1) {
     397           0 :                 run_length = get_bits(&gb, 3) + 3;
     398           0 :                 bits = get_bits(&gb, 2);
     399             : 
     400           0 :                 if (non_mod == 1 && bits == 1)
     401           0 :                     pixels_read += run_length;
     402             :                 else {
     403           0 :                     if (map_table)
     404           0 :                         bits = map_table[bits];
     405           0 :                     while (run_length-- > 0 && pixels_read < dbuf_len) {
     406           0 :                         *destbuf++ = bits;
     407           0 :                         pixels_read++;
     408             :                     }
     409             :                 }
     410             :             } else {
     411           0 :                 bits = get_bits1(&gb);
     412           0 :                 if (bits == 0) {
     413           0 :                     bits = get_bits(&gb, 2);
     414           0 :                     if (bits == 2) {
     415           0 :                         run_length = get_bits(&gb, 4) + 12;
     416           0 :                         bits = get_bits(&gb, 2);
     417             : 
     418           0 :                         if (non_mod == 1 && bits == 1)
     419           0 :                             pixels_read += run_length;
     420             :                         else {
     421           0 :                             if (map_table)
     422           0 :                                 bits = map_table[bits];
     423           0 :                             while (run_length-- > 0 && pixels_read < dbuf_len) {
     424           0 :                                 *destbuf++ = bits;
     425           0 :                                 pixels_read++;
     426             :                             }
     427             :                         }
     428           0 :                     } else if (bits == 3) {
     429           0 :                         run_length = get_bits(&gb, 8) + 29;
     430           0 :                         bits = get_bits(&gb, 2);
     431             : 
     432           0 :                         if (non_mod == 1 && bits == 1)
     433           0 :                             pixels_read += run_length;
     434             :                         else {
     435           0 :                             if (map_table)
     436           0 :                                 bits = map_table[bits];
     437           0 :                             while (run_length-- > 0 && pixels_read < dbuf_len) {
     438           0 :                                 *destbuf++ = bits;
     439           0 :                                 pixels_read++;
     440             :                             }
     441             :                         }
     442           0 :                     } else if (bits == 1) {
     443           0 :                         if (map_table)
     444           0 :                             bits = map_table[0];
     445             :                         else
     446           0 :                             bits = 0;
     447           0 :                         run_length = 2;
     448           0 :                         while (run_length-- > 0 && pixels_read < dbuf_len) {
     449           0 :                             *destbuf++ = bits;
     450           0 :                             pixels_read++;
     451             :                         }
     452             :                     } else {
     453           0 :                         (*srcbuf) += (get_bits_count(&gb) + 7) >> 3;
     454           0 :                         return pixels_read;
     455             :                     }
     456             :                 } else {
     457           0 :                     if (map_table)
     458           0 :                         bits = map_table[0];
     459             :                     else
     460           0 :                         bits = 0;
     461           0 :                     *destbuf++ = bits;
     462           0 :                     pixels_read++;
     463             :                 }
     464             :             }
     465             :         }
     466             :     }
     467             : 
     468           0 :     if (get_bits(&gb, 6))
     469           0 :         av_log(avctx, AV_LOG_ERROR, "line overflow\n");
     470             : 
     471           0 :     (*srcbuf) += (get_bits_count(&gb) + 7) >> 3;
     472             : 
     473           0 :     return pixels_read;
     474             : }
     475             : 
     476           0 : static int dvbsub_read_4bit_string(AVCodecContext *avctx, uint8_t *destbuf, int dbuf_len,
     477             :                                    const uint8_t **srcbuf, int buf_size,
     478             :                                    int non_mod, uint8_t *map_table, int x_pos)
     479             : {
     480             :     GetBitContext gb;
     481             : 
     482             :     int bits;
     483             :     int run_length;
     484           0 :     int pixels_read = x_pos;
     485             : 
     486           0 :     init_get_bits(&gb, *srcbuf, buf_size << 3);
     487             : 
     488           0 :     destbuf += x_pos;
     489             : 
     490           0 :     while (get_bits_count(&gb) < buf_size << 3 && pixels_read < dbuf_len) {
     491           0 :         bits = get_bits(&gb, 4);
     492             : 
     493           0 :         if (bits) {
     494           0 :             if (non_mod != 1 || bits != 1) {
     495           0 :                 if (map_table)
     496           0 :                     *destbuf++ = map_table[bits];
     497             :                 else
     498           0 :                     *destbuf++ = bits;
     499             :             }
     500           0 :             pixels_read++;
     501             :         } else {
     502           0 :             bits = get_bits1(&gb);
     503           0 :             if (bits == 0) {
     504           0 :                 run_length = get_bits(&gb, 3);
     505             : 
     506           0 :                 if (run_length == 0) {
     507           0 :                     (*srcbuf) += (get_bits_count(&gb) + 7) >> 3;
     508           0 :                     return pixels_read;
     509             :                 }
     510             : 
     511           0 :                 run_length += 2;
     512             : 
     513           0 :                 if (map_table)
     514           0 :                     bits = map_table[0];
     515             :                 else
     516           0 :                     bits = 0;
     517             : 
     518           0 :                 while (run_length-- > 0 && pixels_read < dbuf_len) {
     519           0 :                     *destbuf++ = bits;
     520           0 :                     pixels_read++;
     521             :                 }
     522             :             } else {
     523           0 :                 bits = get_bits1(&gb);
     524           0 :                 if (bits == 0) {
     525           0 :                     run_length = get_bits(&gb, 2) + 4;
     526           0 :                     bits = get_bits(&gb, 4);
     527             : 
     528           0 :                     if (non_mod == 1 && bits == 1)
     529           0 :                         pixels_read += run_length;
     530             :                     else {
     531           0 :                         if (map_table)
     532           0 :                             bits = map_table[bits];
     533           0 :                         while (run_length-- > 0 && pixels_read < dbuf_len) {
     534           0 :                             *destbuf++ = bits;
     535           0 :                             pixels_read++;
     536             :                         }
     537             :                     }
     538             :                 } else {
     539           0 :                     bits = get_bits(&gb, 2);
     540           0 :                     if (bits == 2) {
     541           0 :                         run_length = get_bits(&gb, 4) + 9;
     542           0 :                         bits = get_bits(&gb, 4);
     543             : 
     544           0 :                         if (non_mod == 1 && bits == 1)
     545           0 :                             pixels_read += run_length;
     546             :                         else {
     547           0 :                             if (map_table)
     548           0 :                                 bits = map_table[bits];
     549           0 :                             while (run_length-- > 0 && pixels_read < dbuf_len) {
     550           0 :                                 *destbuf++ = bits;
     551           0 :                                 pixels_read++;
     552             :                             }
     553             :                         }
     554           0 :                     } else if (bits == 3) {
     555           0 :                         run_length = get_bits(&gb, 8) + 25;
     556           0 :                         bits = get_bits(&gb, 4);
     557             : 
     558           0 :                         if (non_mod == 1 && bits == 1)
     559           0 :                             pixels_read += run_length;
     560             :                         else {
     561           0 :                             if (map_table)
     562           0 :                                 bits = map_table[bits];
     563           0 :                             while (run_length-- > 0 && pixels_read < dbuf_len) {
     564           0 :                                 *destbuf++ = bits;
     565           0 :                                 pixels_read++;
     566             :                             }
     567             :                         }
     568           0 :                     } else if (bits == 1) {
     569           0 :                         if (map_table)
     570           0 :                             bits = map_table[0];
     571             :                         else
     572           0 :                             bits = 0;
     573           0 :                         run_length = 2;
     574           0 :                         while (run_length-- > 0 && pixels_read < dbuf_len) {
     575           0 :                             *destbuf++ = bits;
     576           0 :                             pixels_read++;
     577             :                         }
     578             :                     } else {
     579           0 :                         if (map_table)
     580           0 :                             bits = map_table[0];
     581             :                         else
     582           0 :                             bits = 0;
     583           0 :                         *destbuf++ = bits;
     584           0 :                         pixels_read ++;
     585             :                     }
     586             :                 }
     587             :             }
     588             :         }
     589             :     }
     590             : 
     591           0 :     if (get_bits(&gb, 8))
     592           0 :         av_log(avctx, AV_LOG_ERROR, "line overflow\n");
     593             : 
     594           0 :     (*srcbuf) += (get_bits_count(&gb) + 7) >> 3;
     595             : 
     596           0 :     return pixels_read;
     597             : }
     598             : 
     599           0 : static int dvbsub_read_8bit_string(AVCodecContext *avctx,
     600             :                                    uint8_t *destbuf, int dbuf_len,
     601             :                                     const uint8_t **srcbuf, int buf_size,
     602             :                                     int non_mod, uint8_t *map_table, int x_pos)
     603             : {
     604           0 :     const uint8_t *sbuf_end = (*srcbuf) + buf_size;
     605             :     int bits;
     606             :     int run_length;
     607           0 :     int pixels_read = x_pos;
     608             : 
     609           0 :     destbuf += x_pos;
     610             : 
     611           0 :     while (*srcbuf < sbuf_end && pixels_read < dbuf_len) {
     612           0 :         bits = *(*srcbuf)++;
     613             : 
     614           0 :         if (bits) {
     615           0 :             if (non_mod != 1 || bits != 1) {
     616           0 :                 if (map_table)
     617           0 :                     *destbuf++ = map_table[bits];
     618             :                 else
     619           0 :                     *destbuf++ = bits;
     620             :             }
     621           0 :             pixels_read++;
     622             :         } else {
     623           0 :             bits = *(*srcbuf)++;
     624           0 :             run_length = bits & 0x7f;
     625           0 :             if ((bits & 0x80) == 0) {
     626           0 :                 if (run_length == 0) {
     627           0 :                     return pixels_read;
     628             :                 }
     629             : 
     630           0 :                 bits = 0;
     631             :             } else {
     632           0 :                 bits = *(*srcbuf)++;
     633             :             }
     634           0 :             if (non_mod == 1 && bits == 1)
     635           0 :                 pixels_read += run_length;
     636             :             else {
     637           0 :                 if (map_table)
     638           0 :                     bits = map_table[bits];
     639           0 :                 while (run_length-- > 0 && pixels_read < dbuf_len) {
     640           0 :                     *destbuf++ = bits;
     641           0 :                     pixels_read++;
     642             :                 }
     643             :             }
     644             :         }
     645             :     }
     646             : 
     647           0 :     if (*(*srcbuf)++)
     648           0 :         av_log(avctx, AV_LOG_ERROR, "line overflow\n");
     649             : 
     650           0 :     return pixels_read;
     651             : }
     652             : 
     653           0 : static void compute_default_clut(uint8_t *clut, AVSubtitleRect *rect, int w, int h)
     654             : {
     655           0 :     uint8_t list[256] = {0};
     656             :     uint8_t list_inv[256];
     657           0 :     int counttab[256] = {0};
     658             :     int count, i, x, y;
     659           0 :     ptrdiff_t stride = rect->linesize[0];
     660             : #define V(x,y) rect->data[0][(x) + (y)*stride]
     661           0 :     for (y = 0; y<h; y++) {
     662           0 :         for (x = 0; x<w; x++) {
     663           0 :             int v = V(x,y) + 1;
     664           0 :             int vl = x     ? V(x-1,y) + 1 : 0;
     665           0 :             int vr = x+1<w ? V(x+1,y) + 1 : 0;
     666           0 :             int vt = y     ? V(x,y-1) + 1 : 0;
     667           0 :             int vb = y+1<h ? V(x,y+1) + 1 : 0;
     668           0 :             counttab[v-1] += !!((v!=vl) + (v!=vr) + (v!=vt) + (v!=vb));
     669             :         }
     670             :     }
     671             : #define L(x,y) list[d[(x) + (y)*stride]]
     672             : 
     673           0 :     for (i = 0; i<256; i++) {
     674           0 :         int scoretab[256] = {0};
     675           0 :         int bestscore = 0;
     676           0 :         int bestv = 0;
     677           0 :         for (y = 0; y<h; y++) {
     678           0 :             for (x = 0; x<w; x++) {
     679           0 :                 uint8_t *d = &rect->data[0][x + y*stride];
     680           0 :                 int v = *d;
     681           0 :                 int l_m = list[v];
     682           0 :                 int l_l = x     ? L(-1, 0) : 1;
     683           0 :                 int l_r = x+1<w ? L( 1, 0) : 1;
     684           0 :                 int l_t = y     ? L( 0,-1) : 1;
     685           0 :                 int l_b = y+1<h ? L( 0, 1) : 1;
     686           0 :                 if (l_m)
     687           0 :                     continue;
     688           0 :                 scoretab[v] += l_l + l_r + l_t + l_b;
     689             :             }
     690             :         }
     691           0 :         for (x = 0; x < 256; x++) {
     692           0 :             if (scoretab[x]) {
     693           0 :                 int score = 1024LL*scoretab[x] / counttab[x];
     694           0 :                 if (score > bestscore) {
     695           0 :                     bestscore = score;
     696           0 :                     bestv = x;
     697             :                 }
     698             :             }
     699             :         }
     700           0 :         if (!bestscore)
     701           0 :             break;
     702           0 :         list    [ bestv ] = 1;
     703           0 :         list_inv[     i ] = bestv;
     704             :     }
     705             : 
     706           0 :     count = FFMAX(i - 1, 1);
     707           0 :     for (i--; i>=0; i--) {
     708           0 :         int v = i*255/count;
     709           0 :         AV_WN32(clut + 4*list_inv[i], RGBA(v/2,v,v/2,v));
     710             :     }
     711           0 : }
     712             : 
     713             : 
     714           0 : static int save_subtitle_set(AVCodecContext *avctx, AVSubtitle *sub, int *got_output)
     715             : {
     716           0 :     DVBSubContext *ctx = avctx->priv_data;
     717             :     DVBSubRegionDisplay *display;
     718           0 :     DVBSubDisplayDefinition *display_def = ctx->display_definition;
     719             :     DVBSubRegion *region;
     720             :     AVSubtitleRect *rect;
     721             :     DVBSubCLUT *clut;
     722             :     uint32_t *clut_table;
     723             :     int i;
     724           0 :     int offset_x=0, offset_y=0;
     725           0 :     int ret = 0;
     726             : 
     727             : 
     728           0 :     if (display_def) {
     729           0 :         offset_x = display_def->x;
     730           0 :         offset_y = display_def->y;
     731             :     }
     732             : 
     733             :     /* Not touching AVSubtitles again*/
     734           0 :     if(sub->num_rects) {
     735           0 :         avpriv_request_sample(ctx, "Different Version of Segment asked Twice");
     736           0 :         return AVERROR_PATCHWELCOME;
     737             :     }
     738           0 :     for (display = ctx->display_list; display; display = display->next) {
     739           0 :         region = get_region(ctx, display->region_id);
     740           0 :         if (region && region->dirty)
     741           0 :             sub->num_rects++;
     742             :     }
     743             : 
     744           0 :     if(ctx->compute_edt == 0) {
     745           0 :         sub->end_display_time = ctx->time_out * 1000;
     746           0 :         *got_output = 1;
     747           0 :     } else if (ctx->prev_start != AV_NOPTS_VALUE) {
     748           0 :         sub->end_display_time = av_rescale_q((sub->pts - ctx->prev_start ), AV_TIME_BASE_Q, (AVRational){ 1, 1000 }) - 1;
     749           0 :         *got_output = 1;
     750             :     }
     751           0 :     if (sub->num_rects > 0) {
     752             : 
     753           0 :         sub->rects = av_mallocz_array(sizeof(*sub->rects), sub->num_rects);
     754           0 :         if (!sub->rects) {
     755           0 :             ret = AVERROR(ENOMEM);
     756           0 :             goto fail;
     757             :         }
     758             : 
     759           0 :         for (i = 0; i < sub->num_rects; i++) {
     760           0 :             sub->rects[i] = av_mallocz(sizeof(*sub->rects[i]));
     761           0 :             if (!sub->rects[i]) {
     762           0 :                 ret = AVERROR(ENOMEM);
     763           0 :                 goto fail;
     764             :             }
     765             :         }
     766             : 
     767           0 :         i = 0;
     768             : 
     769           0 :         for (display = ctx->display_list; display; display = display->next) {
     770           0 :             region = get_region(ctx, display->region_id);
     771             : 
     772           0 :             if (!region)
     773           0 :                 continue;
     774             : 
     775           0 :             if (!region->dirty)
     776           0 :                 continue;
     777             : 
     778           0 :             rect = sub->rects[i];
     779           0 :             rect->x = display->x_pos + offset_x;
     780           0 :             rect->y = display->y_pos + offset_y;
     781           0 :             rect->w = region->width;
     782           0 :             rect->h = region->height;
     783           0 :             rect->nb_colors = (1 << region->depth);
     784           0 :             rect->type      = SUBTITLE_BITMAP;
     785           0 :             rect->linesize[0] = region->width;
     786             : 
     787           0 :             clut = get_clut(ctx, region->clut);
     788             : 
     789           0 :             if (!clut)
     790           0 :                 clut = &default_clut;
     791             : 
     792           0 :             switch (region->depth) {
     793           0 :             case 2:
     794           0 :                 clut_table = clut->clut4;
     795           0 :                 break;
     796           0 :             case 8:
     797           0 :                 clut_table = clut->clut256;
     798           0 :                 break;
     799           0 :             case 4:
     800             :             default:
     801           0 :                 clut_table = clut->clut16;
     802           0 :                 break;
     803             :             }
     804             : 
     805           0 :             rect->data[1] = av_mallocz(AVPALETTE_SIZE);
     806           0 :             if (!rect->data[1]) {
     807           0 :                 ret = AVERROR(ENOMEM);
     808           0 :                 goto fail;
     809             :             }
     810           0 :             memcpy(rect->data[1], clut_table, (1 << region->depth) * sizeof(uint32_t));
     811             : 
     812           0 :             rect->data[0] = av_malloc(region->buf_size);
     813           0 :             if (!rect->data[0]) {
     814           0 :                 ret = AVERROR(ENOMEM);
     815           0 :                 goto fail;
     816             :             }
     817             : 
     818           0 :             memcpy(rect->data[0], region->pbuf, region->buf_size);
     819             : 
     820           0 :             if ((clut == &default_clut && ctx->compute_clut == -1) || ctx->compute_clut == 1) {
     821           0 :                 if (!region->has_computed_clut) {
     822           0 :                     compute_default_clut(region->computed_clut, rect, rect->w, rect->h);
     823           0 :                     region->has_computed_clut = 1;
     824             :                 }
     825             : 
     826           0 :                 memcpy(rect->data[1], region->computed_clut, sizeof(region->computed_clut));
     827             :             }
     828             : 
     829             : #if FF_API_AVPICTURE
     830             : FF_DISABLE_DEPRECATION_WARNINGS
     831             : {
     832             :             int j;
     833           0 :             for (j = 0; j < 4; j++) {
     834           0 :                 rect->pict.data[j] = rect->data[j];
     835           0 :                 rect->pict.linesize[j] = rect->linesize[j];
     836             :             }
     837             : }
     838             : FF_ENABLE_DEPRECATION_WARNINGS
     839             : #endif
     840             : 
     841           0 :             i++;
     842             :         }
     843             :     }
     844             : 
     845           0 :     return 0;
     846           0 : fail:
     847           0 :     if (sub->rects) {
     848           0 :         for(i=0; i<sub->num_rects; i++) {
     849           0 :             rect = sub->rects[i];
     850           0 :             if (rect) {
     851           0 :                 av_freep(&rect->data[0]);
     852           0 :                 av_freep(&rect->data[1]);
     853             :             }
     854           0 :             av_freep(&sub->rects[i]);
     855             :         }
     856           0 :         av_freep(&sub->rects);
     857             :     }
     858           0 :     sub->num_rects = 0;
     859           0 :     return ret;
     860             : }
     861             : 
     862           0 : static void dvbsub_parse_pixel_data_block(AVCodecContext *avctx, DVBSubObjectDisplay *display,
     863             :                                           const uint8_t *buf, int buf_size, int top_bottom, int non_mod)
     864             : {
     865           0 :     DVBSubContext *ctx = avctx->priv_data;
     866             : 
     867           0 :     DVBSubRegion *region = get_region(ctx, display->region_id);
     868           0 :     const uint8_t *buf_end = buf + buf_size;
     869             :     uint8_t *pbuf;
     870             :     int x_pos, y_pos;
     871             :     int i;
     872             : 
     873           0 :     uint8_t map2to4[] = { 0x0,  0x7,  0x8,  0xf};
     874           0 :     uint8_t map2to8[] = {0x00, 0x77, 0x88, 0xff};
     875           0 :     uint8_t map4to8[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
     876             :                          0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff};
     877             :     uint8_t *map_table;
     878             : 
     879             : #if 0
     880             :     ff_dlog(avctx, "DVB pixel block size %d, %s field:\n", buf_size,
     881             :             top_bottom ? "bottom" : "top");
     882             : 
     883             :     for (i = 0; i < buf_size; i++) {
     884             :         if (i % 16 == 0)
     885             :             ff_dlog(avctx, "0x%8p: ", buf+i);
     886             : 
     887             :         ff_dlog(avctx, "%02x ", buf[i]);
     888             :         if (i % 16 == 15)
     889             :             ff_dlog(avctx, "\n");
     890             :     }
     891             : 
     892             :     if (i % 16)
     893             :         ff_dlog(avctx, "\n");
     894             : #endif
     895             : 
     896           0 :     if (!region)
     897           0 :         return;
     898             : 
     899           0 :     pbuf = region->pbuf;
     900           0 :     region->dirty = 1;
     901             : 
     902           0 :     x_pos = display->x_pos;
     903           0 :     y_pos = display->y_pos;
     904             : 
     905           0 :     y_pos += top_bottom;
     906             : 
     907           0 :     while (buf < buf_end) {
     908           0 :         if ((*buf!=0xf0 && x_pos >= region->width) || y_pos >= region->height) {
     909           0 :             av_log(avctx, AV_LOG_ERROR, "Invalid object location! %d-%d %d-%d %02x\n", x_pos, region->width, y_pos, region->height, *buf);
     910           0 :             return;
     911             :         }
     912             : 
     913           0 :         switch (*buf++) {
     914           0 :         case 0x10:
     915           0 :             if (region->depth == 8)
     916           0 :                 map_table = map2to8;
     917           0 :             else if (region->depth == 4)
     918           0 :                 map_table = map2to4;
     919             :             else
     920           0 :                 map_table = NULL;
     921             : 
     922           0 :             x_pos = dvbsub_read_2bit_string(avctx, pbuf + (y_pos * region->width),
     923           0 :                                             region->width, &buf, buf_end - buf,
     924             :                                             non_mod, map_table, x_pos);
     925           0 :             break;
     926           0 :         case 0x11:
     927           0 :             if (region->depth < 4) {
     928           0 :                 av_log(avctx, AV_LOG_ERROR, "4-bit pixel string in %d-bit region!\n", region->depth);
     929           0 :                 return;
     930             :             }
     931             : 
     932           0 :             if (region->depth == 8)
     933           0 :                 map_table = map4to8;
     934             :             else
     935           0 :                 map_table = NULL;
     936             : 
     937           0 :             x_pos = dvbsub_read_4bit_string(avctx, pbuf + (y_pos * region->width),
     938           0 :                                             region->width, &buf, buf_end - buf,
     939             :                                             non_mod, map_table, x_pos);
     940           0 :             break;
     941           0 :         case 0x12:
     942           0 :             if (region->depth < 8) {
     943           0 :                 av_log(avctx, AV_LOG_ERROR, "8-bit pixel string in %d-bit region!\n", region->depth);
     944           0 :                 return;
     945             :             }
     946             : 
     947           0 :             x_pos = dvbsub_read_8bit_string(avctx, pbuf + (y_pos * region->width),
     948           0 :                                             region->width, &buf, buf_end - buf,
     949             :                                             non_mod, NULL, x_pos);
     950           0 :             break;
     951             : 
     952           0 :         case 0x20:
     953           0 :             map2to4[0] = (*buf) >> 4;
     954           0 :             map2to4[1] = (*buf++) & 0xf;
     955           0 :             map2to4[2] = (*buf) >> 4;
     956           0 :             map2to4[3] = (*buf++) & 0xf;
     957           0 :             break;
     958           0 :         case 0x21:
     959           0 :             for (i = 0; i < 4; i++)
     960           0 :                 map2to8[i] = *buf++;
     961           0 :             break;
     962           0 :         case 0x22:
     963           0 :             for (i = 0; i < 16; i++)
     964           0 :                 map4to8[i] = *buf++;
     965           0 :             break;
     966             : 
     967           0 :         case 0xf0:
     968           0 :             x_pos = display->x_pos;
     969           0 :             y_pos += 2;
     970           0 :             break;
     971           0 :         default:
     972           0 :             av_log(avctx, AV_LOG_INFO, "Unknown/unsupported pixel block 0x%x\n", *(buf-1));
     973             :         }
     974             :     }
     975             : 
     976           0 :     region->has_computed_clut = 0;
     977             : }
     978             : 
     979           0 : static int dvbsub_parse_object_segment(AVCodecContext *avctx,
     980             :                                        const uint8_t *buf, int buf_size)
     981             : {
     982           0 :     DVBSubContext *ctx = avctx->priv_data;
     983             : 
     984           0 :     const uint8_t *buf_end = buf + buf_size;
     985             :     int object_id;
     986             :     DVBSubObject *object;
     987             :     DVBSubObjectDisplay *display;
     988             :     int top_field_len, bottom_field_len;
     989             : 
     990             :     int coding_method, non_modifying_color;
     991             : 
     992           0 :     object_id = AV_RB16(buf);
     993           0 :     buf += 2;
     994             : 
     995           0 :     object = get_object(ctx, object_id);
     996             : 
     997           0 :     if (!object)
     998           0 :         return AVERROR_INVALIDDATA;
     999             : 
    1000           0 :     coding_method = ((*buf) >> 2) & 3;
    1001           0 :     non_modifying_color = ((*buf++) >> 1) & 1;
    1002             : 
    1003           0 :     if (coding_method == 0) {
    1004           0 :         top_field_len = AV_RB16(buf);
    1005           0 :         buf += 2;
    1006           0 :         bottom_field_len = AV_RB16(buf);
    1007           0 :         buf += 2;
    1008             : 
    1009           0 :         if (buf + top_field_len + bottom_field_len > buf_end) {
    1010           0 :             av_log(avctx, AV_LOG_ERROR, "Field data size %d+%d too large\n", top_field_len, bottom_field_len);
    1011           0 :             return AVERROR_INVALIDDATA;
    1012             :         }
    1013             : 
    1014           0 :         for (display = object->display_list; display; display = display->object_list_next) {
    1015           0 :             const uint8_t *block = buf;
    1016           0 :             int bfl = bottom_field_len;
    1017             : 
    1018           0 :             dvbsub_parse_pixel_data_block(avctx, display, block, top_field_len, 0,
    1019             :                                             non_modifying_color);
    1020             : 
    1021           0 :             if (bottom_field_len > 0)
    1022           0 :                 block = buf + top_field_len;
    1023             :             else
    1024           0 :                 bfl = top_field_len;
    1025             : 
    1026           0 :             dvbsub_parse_pixel_data_block(avctx, display, block, bfl, 1,
    1027             :                                             non_modifying_color);
    1028             :         }
    1029             : 
    1030             : /*  } else if (coding_method == 1) {*/
    1031             : 
    1032             :     } else {
    1033           0 :         av_log(avctx, AV_LOG_ERROR, "Unknown object coding %d\n", coding_method);
    1034             :     }
    1035             : 
    1036           0 :     return 0;
    1037             : }
    1038             : 
    1039           0 : static int dvbsub_parse_clut_segment(AVCodecContext *avctx,
    1040             :                                      const uint8_t *buf, int buf_size)
    1041             : {
    1042           0 :     DVBSubContext *ctx = avctx->priv_data;
    1043             : 
    1044           0 :     const uint8_t *buf_end = buf + buf_size;
    1045             :     int i, clut_id;
    1046             :     int version;
    1047             :     DVBSubCLUT *clut;
    1048             :     int entry_id, depth , full_range;
    1049             :     int y, cr, cb, alpha;
    1050             :     int r, g, b, r_add, g_add, b_add;
    1051             : 
    1052             :     ff_dlog(avctx, "DVB clut packet:\n");
    1053             : 
    1054           0 :     for (i=0; i < buf_size; i++) {
    1055             :         ff_dlog(avctx, "%02x ", buf[i]);
    1056           0 :         if (i % 16 == 15)
    1057             :             ff_dlog(avctx, "\n");
    1058             :     }
    1059             : 
    1060           0 :     if (i % 16)
    1061             :         ff_dlog(avctx, "\n");
    1062             : 
    1063           0 :     clut_id = *buf++;
    1064           0 :     version = ((*buf)>>4)&15;
    1065           0 :     buf += 1;
    1066             : 
    1067           0 :     clut = get_clut(ctx, clut_id);
    1068             : 
    1069           0 :     if (!clut) {
    1070           0 :         clut = av_malloc(sizeof(DVBSubCLUT));
    1071           0 :         if (!clut)
    1072           0 :             return AVERROR(ENOMEM);
    1073             : 
    1074           0 :         memcpy(clut, &default_clut, sizeof(DVBSubCLUT));
    1075             : 
    1076           0 :         clut->id = clut_id;
    1077           0 :         clut->version = -1;
    1078             : 
    1079           0 :         clut->next = ctx->clut_list;
    1080           0 :         ctx->clut_list = clut;
    1081             :     }
    1082             : 
    1083           0 :     if (clut->version != version) {
    1084             : 
    1085           0 :     clut->version = version;
    1086             : 
    1087           0 :     while (buf + 4 < buf_end) {
    1088           0 :         entry_id = *buf++;
    1089             : 
    1090           0 :         depth = (*buf) & 0xe0;
    1091             : 
    1092           0 :         if (depth == 0) {
    1093           0 :             av_log(avctx, AV_LOG_ERROR, "Invalid clut depth 0x%x!\n", *buf);
    1094             :         }
    1095             : 
    1096           0 :         full_range = (*buf++) & 1;
    1097             : 
    1098           0 :         if (full_range) {
    1099           0 :             y = *buf++;
    1100           0 :             cr = *buf++;
    1101           0 :             cb = *buf++;
    1102           0 :             alpha = *buf++;
    1103             :         } else {
    1104           0 :             y = buf[0] & 0xfc;
    1105           0 :             cr = (((buf[0] & 3) << 2) | ((buf[1] >> 6) & 3)) << 4;
    1106           0 :             cb = (buf[1] << 2) & 0xf0;
    1107           0 :             alpha = (buf[1] << 6) & 0xc0;
    1108             : 
    1109           0 :             buf += 2;
    1110             :         }
    1111             : 
    1112           0 :         if (y == 0)
    1113           0 :             alpha = 0xff;
    1114             : 
    1115           0 :         YUV_TO_RGB1_CCIR(cb, cr);
    1116           0 :         YUV_TO_RGB2_CCIR(r, g, b, y);
    1117             : 
    1118             :         ff_dlog(avctx, "clut %d := (%d,%d,%d,%d)\n", entry_id, r, g, b, alpha);
    1119           0 :         if (!!(depth & 0x80) + !!(depth & 0x40) + !!(depth & 0x20) > 1) {
    1120             :             ff_dlog(avctx, "More than one bit level marked: %x\n", depth);
    1121           0 :             if (avctx->strict_std_compliance > FF_COMPLIANCE_NORMAL)
    1122           0 :                 return AVERROR_INVALIDDATA;
    1123             :         }
    1124             : 
    1125           0 :         if (depth & 0x80 && entry_id < 4)
    1126           0 :             clut->clut4[entry_id] = RGBA(r,g,b,255 - alpha);
    1127           0 :         else if (depth & 0x40 && entry_id < 16)
    1128           0 :             clut->clut16[entry_id] = RGBA(r,g,b,255 - alpha);
    1129           0 :         else if (depth & 0x20)
    1130           0 :             clut->clut256[entry_id] = RGBA(r,g,b,255 - alpha);
    1131             :     }
    1132             :     }
    1133             : 
    1134           0 :     return 0;
    1135             : }
    1136             : 
    1137             : 
    1138           0 : static int dvbsub_parse_region_segment(AVCodecContext *avctx,
    1139             :                                        const uint8_t *buf, int buf_size)
    1140             : {
    1141           0 :     DVBSubContext *ctx = avctx->priv_data;
    1142             : 
    1143           0 :     const uint8_t *buf_end = buf + buf_size;
    1144             :     int region_id, object_id;
    1145             :     int av_unused version;
    1146             :     DVBSubRegion *region;
    1147             :     DVBSubObject *object;
    1148             :     DVBSubObjectDisplay *display;
    1149             :     int fill;
    1150             :     int ret;
    1151             : 
    1152           0 :     if (buf_size < 10)
    1153           0 :         return AVERROR_INVALIDDATA;
    1154             : 
    1155           0 :     region_id = *buf++;
    1156             : 
    1157           0 :     region = get_region(ctx, region_id);
    1158             : 
    1159           0 :     if (!region) {
    1160           0 :         region = av_mallocz(sizeof(DVBSubRegion));
    1161           0 :         if (!region)
    1162           0 :             return AVERROR(ENOMEM);
    1163             : 
    1164           0 :         region->id = region_id;
    1165           0 :         region->version = -1;
    1166             : 
    1167           0 :         region->next = ctx->region_list;
    1168           0 :         ctx->region_list = region;
    1169             :     }
    1170             : 
    1171           0 :     version = ((*buf)>>4) & 15;
    1172           0 :     fill = ((*buf++) >> 3) & 1;
    1173             : 
    1174           0 :     region->width = AV_RB16(buf);
    1175           0 :     buf += 2;
    1176           0 :     region->height = AV_RB16(buf);
    1177           0 :     buf += 2;
    1178             : 
    1179           0 :     ret = av_image_check_size2(region->width, region->height, avctx->max_pixels, AV_PIX_FMT_PAL8, 0, avctx);
    1180           0 :     if (ret >= 0 && region->width * region->height * 2 > 320 * 1024 * 8) {
    1181           0 :         ret = AVERROR_INVALIDDATA;
    1182           0 :         av_log(avctx, AV_LOG_ERROR, "Pixel buffer memory constraint violated\n");
    1183             :     }
    1184           0 :     if (ret < 0) {
    1185           0 :         region->width= region->height= 0;
    1186           0 :         return ret;
    1187             :     }
    1188             : 
    1189           0 :     if (region->width * region->height != region->buf_size) {
    1190           0 :         av_free(region->pbuf);
    1191             : 
    1192           0 :         region->buf_size = region->width * region->height;
    1193             : 
    1194           0 :         region->pbuf = av_malloc(region->buf_size);
    1195           0 :         if (!region->pbuf) {
    1196           0 :             region->buf_size =
    1197           0 :             region->width =
    1198           0 :             region->height = 0;
    1199           0 :             return AVERROR(ENOMEM);
    1200             :         }
    1201             : 
    1202           0 :         fill = 1;
    1203           0 :         region->dirty = 0;
    1204             :     }
    1205             : 
    1206           0 :     region->depth = 1 << (((*buf++) >> 2) & 7);
    1207           0 :     if(region->depth<2 || region->depth>8){
    1208           0 :         av_log(avctx, AV_LOG_ERROR, "region depth %d is invalid\n", region->depth);
    1209           0 :         region->depth= 4;
    1210             :     }
    1211           0 :     region->clut = *buf++;
    1212             : 
    1213           0 :     if (region->depth == 8) {
    1214           0 :         region->bgcolor = *buf++;
    1215           0 :         buf += 1;
    1216             :     } else {
    1217           0 :         buf += 1;
    1218             : 
    1219           0 :         if (region->depth == 4)
    1220           0 :             region->bgcolor = (((*buf++) >> 4) & 15);
    1221             :         else
    1222           0 :             region->bgcolor = (((*buf++) >> 2) & 3);
    1223             :     }
    1224             : 
    1225             :     ff_dlog(avctx, "Region %d, (%dx%d)\n", region_id, region->width, region->height);
    1226             : 
    1227           0 :     if (fill) {
    1228           0 :         memset(region->pbuf, region->bgcolor, region->buf_size);
    1229             :         ff_dlog(avctx, "Fill region (%d)\n", region->bgcolor);
    1230             :     }
    1231             : 
    1232           0 :     delete_region_display_list(ctx, region);
    1233             : 
    1234           0 :     while (buf + 5 < buf_end) {
    1235           0 :         object_id = AV_RB16(buf);
    1236           0 :         buf += 2;
    1237             : 
    1238           0 :         object = get_object(ctx, object_id);
    1239             : 
    1240           0 :         if (!object) {
    1241           0 :             object = av_mallocz(sizeof(DVBSubObject));
    1242           0 :             if (!object)
    1243           0 :                 return AVERROR(ENOMEM);
    1244             : 
    1245           0 :             object->id = object_id;
    1246           0 :             object->next = ctx->object_list;
    1247           0 :             ctx->object_list = object;
    1248             :         }
    1249             : 
    1250           0 :         object->type = (*buf) >> 6;
    1251             : 
    1252           0 :         display = av_mallocz(sizeof(DVBSubObjectDisplay));
    1253           0 :         if (!display)
    1254           0 :             return AVERROR(ENOMEM);
    1255             : 
    1256           0 :         display->object_id = object_id;
    1257           0 :         display->region_id = region_id;
    1258             : 
    1259           0 :         display->x_pos = AV_RB16(buf) & 0xfff;
    1260           0 :         buf += 2;
    1261           0 :         display->y_pos = AV_RB16(buf) & 0xfff;
    1262           0 :         buf += 2;
    1263             : 
    1264           0 :         if ((object->type == 1 || object->type == 2) && buf+1 < buf_end) {
    1265           0 :             display->fgcolor = *buf++;
    1266           0 :             display->bgcolor = *buf++;
    1267             :         }
    1268             : 
    1269           0 :         display->region_list_next = region->display_list;
    1270           0 :         region->display_list = display;
    1271             : 
    1272           0 :         display->object_list_next = object->display_list;
    1273           0 :         object->display_list = display;
    1274             :     }
    1275             : 
    1276           0 :     return 0;
    1277             : }
    1278             : 
    1279           0 : static int dvbsub_parse_page_segment(AVCodecContext *avctx,
    1280             :                                      const uint8_t *buf, int buf_size, AVSubtitle *sub, int *got_output)
    1281             : {
    1282           0 :     DVBSubContext *ctx = avctx->priv_data;
    1283             :     DVBSubRegionDisplay *display;
    1284             :     DVBSubRegionDisplay *tmp_display_list, **tmp_ptr;
    1285             : 
    1286           0 :     const uint8_t *buf_end = buf + buf_size;
    1287             :     int region_id;
    1288             :     int page_state;
    1289             :     int timeout;
    1290             :     int version;
    1291             : 
    1292           0 :     if (buf_size < 1)
    1293           0 :         return AVERROR_INVALIDDATA;
    1294             : 
    1295           0 :     timeout = *buf++;
    1296           0 :     version = ((*buf)>>4) & 15;
    1297           0 :     page_state = ((*buf++) >> 2) & 3;
    1298             : 
    1299           0 :     if (ctx->version == version) {
    1300           0 :         return 0;
    1301             :     }
    1302             : 
    1303           0 :     ctx->time_out = timeout;
    1304           0 :     ctx->version = version;
    1305             : 
    1306             :     ff_dlog(avctx, "Page time out %ds, state %d\n", ctx->time_out, page_state);
    1307             : 
    1308           0 :     if(ctx->compute_edt == 1)
    1309           0 :         save_subtitle_set(avctx, sub, got_output);
    1310             : 
    1311           0 :     if (page_state == 1 || page_state == 2) {
    1312           0 :         delete_regions(ctx);
    1313           0 :         delete_objects(ctx);
    1314           0 :         delete_cluts(ctx);
    1315             :     }
    1316             : 
    1317           0 :     tmp_display_list = ctx->display_list;
    1318           0 :     ctx->display_list = NULL;
    1319             : 
    1320           0 :     while (buf + 5 < buf_end) {
    1321           0 :         region_id = *buf++;
    1322           0 :         buf += 1;
    1323             : 
    1324           0 :         display = ctx->display_list;
    1325           0 :         while (display && display->region_id != region_id) {
    1326           0 :             display = display->next;
    1327             :         }
    1328           0 :         if (display) {
    1329           0 :             av_log(avctx, AV_LOG_ERROR, "duplicate region\n");
    1330           0 :             break;
    1331             :         }
    1332             : 
    1333           0 :         display = tmp_display_list;
    1334           0 :         tmp_ptr = &tmp_display_list;
    1335             : 
    1336           0 :         while (display && display->region_id != region_id) {
    1337           0 :             tmp_ptr = &display->next;
    1338           0 :             display = display->next;
    1339             :         }
    1340             : 
    1341           0 :         if (!display) {
    1342           0 :             display = av_mallocz(sizeof(DVBSubRegionDisplay));
    1343           0 :             if (!display)
    1344           0 :                 return AVERROR(ENOMEM);
    1345             :         }
    1346             : 
    1347           0 :         display->region_id = region_id;
    1348             : 
    1349           0 :         display->x_pos = AV_RB16(buf);
    1350           0 :         buf += 2;
    1351           0 :         display->y_pos = AV_RB16(buf);
    1352           0 :         buf += 2;
    1353             : 
    1354           0 :         *tmp_ptr = display->next;
    1355             : 
    1356           0 :         display->next = ctx->display_list;
    1357           0 :         ctx->display_list = display;
    1358             : 
    1359             :         ff_dlog(avctx, "Region %d, (%d,%d)\n", region_id, display->x_pos, display->y_pos);
    1360             :     }
    1361             : 
    1362           0 :     while (tmp_display_list) {
    1363           0 :         display = tmp_display_list;
    1364             : 
    1365           0 :         tmp_display_list = display->next;
    1366             : 
    1367           0 :         av_freep(&display);
    1368             :     }
    1369             : 
    1370           0 :     return 0;
    1371             : }
    1372             : 
    1373             : 
    1374             : #ifdef DEBUG
    1375             : static void png_save(DVBSubContext *ctx, const char *filename, uint32_t *bitmap, int w, int h)
    1376             : {
    1377             :     int x, y, v;
    1378             :     FILE *f;
    1379             :     char fname[40], fname2[40];
    1380             :     char command[1024];
    1381             : 
    1382             :     snprintf(fname, sizeof(fname), "%s.ppm", filename);
    1383             : 
    1384             :     f = fopen(fname, "w");
    1385             :     if (!f) {
    1386             :         perror(fname);
    1387             :         return;
    1388             :     }
    1389             :     fprintf(f, "P6\n"
    1390             :             "%d %d\n"
    1391             :             "%d\n",
    1392             :             w, h, 255);
    1393             :     for(y = 0; y < h; y++) {
    1394             :         for(x = 0; x < w; x++) {
    1395             :             v = bitmap[y * w + x];
    1396             :             putc((v >> 16) & 0xff, f);
    1397             :             putc((v >> 8) & 0xff, f);
    1398             :             putc((v >> 0) & 0xff, f);
    1399             :         }
    1400             :     }
    1401             :     fclose(f);
    1402             : 
    1403             : 
    1404             :     snprintf(fname2, sizeof(fname2), "%s-a.pgm", filename);
    1405             : 
    1406             :     f = fopen(fname2, "w");
    1407             :     if (!f) {
    1408             :         perror(fname2);
    1409             :         return;
    1410             :     }
    1411             :     fprintf(f, "P5\n"
    1412             :             "%d %d\n"
    1413             :             "%d\n",
    1414             :             w, h, 255);
    1415             :     for(y = 0; y < h; y++) {
    1416             :         for(x = 0; x < w; x++) {
    1417             :             v = bitmap[y * w + x];
    1418             :             putc((v >> 24) & 0xff, f);
    1419             :         }
    1420             :     }
    1421             :     fclose(f);
    1422             : 
    1423             :     snprintf(command, sizeof(command), "pnmtopng -alpha %s %s > %s.png 2> /dev/null", fname2, fname, filename);
    1424             :     if (system(command) != 0) {
    1425             :         av_log(ctx, AV_LOG_ERROR, "Error running pnmtopng\n");
    1426             :         return;
    1427             :     }
    1428             : 
    1429             :     snprintf(command, sizeof(command), "rm %s %s", fname, fname2);
    1430             :     if (system(command) != 0) {
    1431             :         av_log(ctx, AV_LOG_ERROR, "Error removing %s and %s\n", fname, fname2);
    1432             :         return;
    1433             :     }
    1434             : }
    1435             : 
    1436             : static int save_display_set(DVBSubContext *ctx)
    1437             : {
    1438             :     DVBSubRegion *region;
    1439             :     DVBSubRegionDisplay *display;
    1440             :     DVBSubCLUT *clut;
    1441             :     uint32_t *clut_table;
    1442             :     int x_pos, y_pos, width, height;
    1443             :     int x, y, y_off, x_off;
    1444             :     uint32_t *pbuf;
    1445             :     char filename[32];
    1446             :     static int fileno_index = 0;
    1447             : 
    1448             :     x_pos = -1;
    1449             :     y_pos = -1;
    1450             :     width = 0;
    1451             :     height = 0;
    1452             : 
    1453             :     for (display = ctx->display_list; display; display = display->next) {
    1454             :         region = get_region(ctx, display->region_id);
    1455             : 
    1456             :         if (!region)
    1457             :             return -1;
    1458             : 
    1459             :         if (x_pos == -1) {
    1460             :             x_pos = display->x_pos;
    1461             :             y_pos = display->y_pos;
    1462             :             width = region->width;
    1463             :             height = region->height;
    1464             :         } else {
    1465             :             if (display->x_pos < x_pos) {
    1466             :                 width += (x_pos - display->x_pos);
    1467             :                 x_pos = display->x_pos;
    1468             :             }
    1469             : 
    1470             :             if (display->y_pos < y_pos) {
    1471             :                 height += (y_pos - display->y_pos);
    1472             :                 y_pos = display->y_pos;
    1473             :             }
    1474             : 
    1475             :             if (display->x_pos + region->width > x_pos + width) {
    1476             :                 width = display->x_pos + region->width - x_pos;
    1477             :             }
    1478             : 
    1479             :             if (display->y_pos + region->height > y_pos + height) {
    1480             :                 height = display->y_pos + region->height - y_pos;
    1481             :             }
    1482             :         }
    1483             :     }
    1484             : 
    1485             :     if (x_pos >= 0) {
    1486             : 
    1487             :         pbuf = av_malloc(width * height * 4);
    1488             :         if (!pbuf)
    1489             :             return -1;
    1490             : 
    1491             :         for (display = ctx->display_list; display; display = display->next) {
    1492             :             region = get_region(ctx, display->region_id);
    1493             : 
    1494             :             if (!region)
    1495             :                 return -1;
    1496             : 
    1497             :             x_off = display->x_pos - x_pos;
    1498             :             y_off = display->y_pos - y_pos;
    1499             : 
    1500             :             clut = get_clut(ctx, region->clut);
    1501             : 
    1502             :             if (!clut)
    1503             :                 clut = &default_clut;
    1504             : 
    1505             :             switch (region->depth) {
    1506             :             case 2:
    1507             :                 clut_table = clut->clut4;
    1508             :                 break;
    1509             :             case 8:
    1510             :                 clut_table = clut->clut256;
    1511             :                 break;
    1512             :             case 4:
    1513             :             default:
    1514             :                 clut_table = clut->clut16;
    1515             :                 break;
    1516             :             }
    1517             : 
    1518             :             for (y = 0; y < region->height; y++) {
    1519             :                 for (x = 0; x < region->width; x++) {
    1520             :                     pbuf[((y + y_off) * width) + x_off + x] =
    1521             :                         clut_table[region->pbuf[y * region->width + x]];
    1522             :                 }
    1523             :             }
    1524             : 
    1525             :         }
    1526             : 
    1527             :         snprintf(filename, sizeof(filename), "dvbs.%d", fileno_index);
    1528             : 
    1529             :         png_save(ctx, filename, pbuf, width, height);
    1530             : 
    1531             :         av_freep(&pbuf);
    1532             :     }
    1533             : 
    1534             :     fileno_index++;
    1535             :     return 0;
    1536             : }
    1537             : #endif /* DEBUG */
    1538             : 
    1539           0 : static int dvbsub_parse_display_definition_segment(AVCodecContext *avctx,
    1540             :                                                    const uint8_t *buf,
    1541             :                                                    int buf_size)
    1542             : {
    1543           0 :     DVBSubContext *ctx = avctx->priv_data;
    1544           0 :     DVBSubDisplayDefinition *display_def = ctx->display_definition;
    1545             :     int dds_version, info_byte;
    1546             : 
    1547           0 :     if (buf_size < 5)
    1548           0 :         return AVERROR_INVALIDDATA;
    1549             : 
    1550           0 :     info_byte   = bytestream_get_byte(&buf);
    1551           0 :     dds_version = info_byte >> 4;
    1552           0 :     if (display_def && display_def->version == dds_version)
    1553           0 :         return 0; // already have this display definition version
    1554             : 
    1555           0 :     if (!display_def) {
    1556           0 :         display_def             = av_mallocz(sizeof(*display_def));
    1557           0 :         if (!display_def)
    1558           0 :             return AVERROR(ENOMEM);
    1559           0 :         ctx->display_definition = display_def;
    1560             :     }
    1561             : 
    1562           0 :     display_def->version = dds_version;
    1563           0 :     display_def->x       = 0;
    1564           0 :     display_def->y       = 0;
    1565           0 :     display_def->width   = bytestream_get_be16(&buf) + 1;
    1566           0 :     display_def->height  = bytestream_get_be16(&buf) + 1;
    1567           0 :     if (!avctx->width || !avctx->height) {
    1568           0 :         avctx->width  = display_def->width;
    1569           0 :         avctx->height = display_def->height;
    1570             :     }
    1571             : 
    1572           0 :     if (info_byte & 1<<3) { // display_window_flag
    1573           0 :         if (buf_size < 13)
    1574           0 :             return AVERROR_INVALIDDATA;
    1575             : 
    1576           0 :         display_def->x = bytestream_get_be16(&buf);
    1577           0 :         display_def->width  = bytestream_get_be16(&buf) - display_def->x + 1;
    1578           0 :         display_def->y = bytestream_get_be16(&buf);
    1579           0 :         display_def->height = bytestream_get_be16(&buf) - display_def->y + 1;
    1580             :     }
    1581             : 
    1582           0 :     return 0;
    1583             : }
    1584             : 
    1585           0 : static int dvbsub_display_end_segment(AVCodecContext *avctx, const uint8_t *buf,
    1586             :                                       int buf_size, AVSubtitle *sub,int *got_output)
    1587             : {
    1588           0 :     DVBSubContext *ctx = avctx->priv_data;
    1589             : 
    1590           0 :     if(ctx->compute_edt == 0)
    1591           0 :         save_subtitle_set(avctx, sub, got_output);
    1592             : #ifdef DEBUG
    1593             :     save_display_set(ctx);
    1594             : #endif
    1595           0 :     return 0;
    1596             : }
    1597             : 
    1598           0 : static int dvbsub_decode(AVCodecContext *avctx,
    1599             :                          void *data, int *data_size,
    1600             :                          AVPacket *avpkt)
    1601             : {
    1602           0 :     const uint8_t *buf = avpkt->data;
    1603           0 :     int buf_size = avpkt->size;
    1604           0 :     DVBSubContext *ctx = avctx->priv_data;
    1605           0 :     AVSubtitle *sub = data;
    1606             :     const uint8_t *p, *p_end;
    1607             :     int segment_type;
    1608             :     int page_id;
    1609             :     int segment_length;
    1610             :     int i;
    1611           0 :     int ret = 0;
    1612           0 :     int got_segment = 0;
    1613           0 :     int got_dds = 0;
    1614             : 
    1615             :     ff_dlog(avctx, "DVB sub packet:\n");
    1616             : 
    1617           0 :     for (i=0; i < buf_size; i++) {
    1618             :         ff_dlog(avctx, "%02x ", buf[i]);
    1619           0 :         if (i % 16 == 15)
    1620             :             ff_dlog(avctx, "\n");
    1621             :     }
    1622             : 
    1623           0 :     if (i % 16)
    1624             :         ff_dlog(avctx, "\n");
    1625             : 
    1626           0 :     if (buf_size <= 6 || *buf != 0x0f) {
    1627             :         ff_dlog(avctx, "incomplete or broken packet");
    1628           0 :         return AVERROR_INVALIDDATA;
    1629             :     }
    1630             : 
    1631           0 :     p = buf;
    1632           0 :     p_end = buf + buf_size;
    1633             : 
    1634           0 :     while (p_end - p >= 6 && *p == 0x0f) {
    1635           0 :         p += 1;
    1636           0 :         segment_type = *p++;
    1637           0 :         page_id = AV_RB16(p);
    1638           0 :         p += 2;
    1639           0 :         segment_length = AV_RB16(p);
    1640           0 :         p += 2;
    1641             : 
    1642           0 :         if (avctx->debug & FF_DEBUG_STARTCODE) {
    1643           0 :             av_log(avctx, AV_LOG_DEBUG, "segment_type:%d page_id:%d segment_length:%d\n", segment_type, page_id, segment_length);
    1644             :         }
    1645             : 
    1646           0 :         if (p_end - p < segment_length) {
    1647             :             ff_dlog(avctx, "incomplete or broken packet");
    1648           0 :             ret = -1;
    1649           0 :             goto end;
    1650             :         }
    1651             : 
    1652           0 :         if (page_id == ctx->composition_id || page_id == ctx->ancillary_id ||
    1653           0 :             ctx->composition_id == -1 || ctx->ancillary_id == -1) {
    1654           0 :             int ret = 0;
    1655           0 :             switch (segment_type) {
    1656           0 :             case DVBSUB_PAGE_SEGMENT:
    1657           0 :                 ret = dvbsub_parse_page_segment(avctx, p, segment_length, sub, data_size);
    1658           0 :                 got_segment |= 1;
    1659           0 :                 break;
    1660           0 :             case DVBSUB_REGION_SEGMENT:
    1661           0 :                 ret = dvbsub_parse_region_segment(avctx, p, segment_length);
    1662           0 :                 got_segment |= 2;
    1663           0 :                 break;
    1664           0 :             case DVBSUB_CLUT_SEGMENT:
    1665           0 :                 ret = dvbsub_parse_clut_segment(avctx, p, segment_length);
    1666           0 :                 if (ret < 0) goto end;
    1667           0 :                 got_segment |= 4;
    1668           0 :                 break;
    1669           0 :             case DVBSUB_OBJECT_SEGMENT:
    1670           0 :                 ret = dvbsub_parse_object_segment(avctx, p, segment_length);
    1671           0 :                 got_segment |= 8;
    1672           0 :                 break;
    1673           0 :             case DVBSUB_DISPLAYDEFINITION_SEGMENT:
    1674           0 :                 ret = dvbsub_parse_display_definition_segment(avctx, p,
    1675             :                                                               segment_length);
    1676           0 :                 got_dds = 1;
    1677           0 :                 break;
    1678           0 :             case DVBSUB_DISPLAY_SEGMENT:
    1679           0 :                 ret = dvbsub_display_end_segment(avctx, p, segment_length, sub, data_size);
    1680           0 :                 if (got_segment == 15 && !got_dds && !avctx->width && !avctx->height) {
    1681             :                     // Default from ETSI EN 300 743 V1.3.1 (7.2.1)
    1682           0 :                     avctx->width  = 720;
    1683           0 :                     avctx->height = 576;
    1684             :                 }
    1685           0 :                 got_segment |= 16;
    1686           0 :                 break;
    1687           0 :             default:
    1688             :                 ff_dlog(avctx, "Subtitling segment type 0x%x, page id %d, length %d\n",
    1689             :                         segment_type, page_id, segment_length);
    1690           0 :                 break;
    1691             :             }
    1692           0 :             if (ret < 0)
    1693           0 :                 goto end;
    1694             :         }
    1695             : 
    1696           0 :         p += segment_length;
    1697             :     }
    1698             :     // Some streams do not send a display segment but if we have all the other
    1699             :     // segments then we need no further data.
    1700           0 :     if (got_segment == 15) {
    1701           0 :         av_log(avctx, AV_LOG_DEBUG, "Missing display_end_segment, emulating\n");
    1702           0 :         dvbsub_display_end_segment(avctx, p, 0, sub, data_size);
    1703             :     }
    1704             : 
    1705           0 : end:
    1706           0 :     if(ret < 0) {
    1707           0 :         *data_size = 0;
    1708           0 :         avsubtitle_free(sub);
    1709           0 :         return ret;
    1710             :     } else {
    1711           0 :         if(ctx->compute_edt == 1 )
    1712           0 :             FFSWAP(int64_t, ctx->prev_start, sub->pts);
    1713             :     }
    1714             : 
    1715           0 :     return p - buf;
    1716             : }
    1717             : 
    1718             : #define DS AV_OPT_FLAG_DECODING_PARAM | AV_OPT_FLAG_SUBTITLE_PARAM
    1719             : static const AVOption options[] = {
    1720             :     {"compute_edt", "compute end of time using pts or timeout", offsetof(DVBSubContext, compute_edt), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, DS},
    1721             :     {"compute_clut", "compute clut when not available(-1) or always(1) or never(0)", offsetof(DVBSubContext, compute_clut), AV_OPT_TYPE_BOOL, {.i64 = -1}, -1, 1, DS},
    1722             :     {"dvb_substream", "", offsetof(DVBSubContext, substream), AV_OPT_TYPE_INT, {.i64 = -1}, -1, 63, DS},
    1723             :     {NULL}
    1724             : };
    1725             : static const AVClass dvbsubdec_class = {
    1726             :     .class_name = "DVB Sub Decoder",
    1727             :     .item_name  = av_default_item_name,
    1728             :     .option     = options,
    1729             :     .version    = LIBAVUTIL_VERSION_INT,
    1730             : };
    1731             : 
    1732             : AVCodec ff_dvbsub_decoder = {
    1733             :     .name           = "dvbsub",
    1734             :     .long_name      = NULL_IF_CONFIG_SMALL("DVB subtitles"),
    1735             :     .type           = AVMEDIA_TYPE_SUBTITLE,
    1736             :     .id             = AV_CODEC_ID_DVB_SUBTITLE,
    1737             :     .priv_data_size = sizeof(DVBSubContext),
    1738             :     .init           = dvbsub_init_decoder,
    1739             :     .close          = dvbsub_close_decoder,
    1740             :     .decode         = dvbsub_decode,
    1741             :     .priv_class     = &dvbsubdec_class,
    1742             : };

Generated by: LCOV version 1.13