⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dvbsub.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 5 页
字号:
    /* Check version number */    if( p_region && ( p_region->i_version == i_version ) )    {        bs_skip( s, 8 * (i_segment_length - 1) - 4 );        return;    }    if( !p_region )    {#ifdef DEBUG_DVBSUB        msg_Dbg( p_dec, "new region: %i", i_id );#endif        p_region = *pp_region = malloc( sizeof(dvbsub_region_t) );        if( p_region )        {            memset( p_region, 0, sizeof(dvbsub_region_t) );            p_region->p_object_defs = NULL;            p_region->p_pixbuf = NULL;            p_region->p_next = NULL;        }    }    /* Region attributes */    p_region->i_id = i_id;    p_region->i_version = i_version;    b_fill = bs_read( s, 1 );    bs_skip( s, 3 ); /* Reserved */    i_width = bs_read( s, 16 );    i_height = bs_read( s, 16 );#ifdef DEBUG_DVBSUB    msg_Dbg( p_dec, " width=%d height=%d", i_width, i_height );#endif    i_level_comp = bs_read( s, 3 );    i_depth = bs_read( s, 3 );    bs_skip( s, 2 ); /* Reserved */    i_clut = bs_read( s, 8 );    i_8_bg = bs_read( s, 8 );    i_4_bg = bs_read( s, 4 );    i_2_bg = bs_read( s, 2 );    bs_skip( s, 2 ); /* Reserved */    /* Free old object defs */    while( p_region->i_object_defs )        free( p_region->p_object_defs[--p_region->i_object_defs].psz_text );    free( p_region->p_object_defs );    p_region->p_object_defs = NULL;    /* Extra sanity checks */    if( ( p_region->i_width != i_width ) ||        ( p_region->i_height != i_height ) )    {        if( p_region->p_pixbuf )        {            msg_Dbg( p_dec, "region size changed (%dx%d->%dx%d)",                     p_region->i_width, p_region->i_height, i_width, i_height );            free( p_region->p_pixbuf );        }        p_region->p_pixbuf = malloc( i_height * i_width );        p_region->i_depth = 0;        b_fill = true;    }    if( p_region->i_depth &&        ( ( p_region->i_depth != i_depth ) ||          ( p_region->i_level_comp != i_level_comp ) ||          ( p_region->i_clut != i_clut) ) )    {        msg_Dbg( p_dec, "region parameters changed (not allowed)" );    }    /* Erase background of region */    if( b_fill )    {        int i_background = ( p_region->i_depth == 1 ) ? i_2_bg :            ( ( p_region->i_depth == 2 ) ? i_4_bg : i_8_bg );        memset( p_region->p_pixbuf, i_background, i_width * i_height );    }    p_region->i_width = i_width;    p_region->i_height = i_height;    p_region->i_level_comp = i_level_comp;    p_region->i_depth = i_depth;    p_region->i_clut = i_clut;    /* List of objects in the region */    i_processed_length = 10;    while( i_processed_length < i_segment_length )    {        dvbsub_objectdef_t *p_obj;        /* We create a new object */        p_region->i_object_defs++;        p_region->p_object_defs =            realloc( p_region->p_object_defs,                     sizeof(dvbsub_objectdef_t) * p_region->i_object_defs );        /* We parse object properties */        p_obj = &p_region->p_object_defs[p_region->i_object_defs - 1];        p_obj->i_id         = bs_read( s, 16 );        p_obj->i_type       = bs_read( s, 2 );        bs_skip( s, 2 ); /* Provider */        p_obj->i_x          = bs_read( s, 12 );        bs_skip( s, 4 ); /* Reserved */        p_obj->i_y          = bs_read( s, 12 );        p_obj->psz_text     = 0;        i_processed_length += 6;        if( ( p_obj->i_type == DVBSUB_OT_BASIC_CHAR ) ||            ( p_obj->i_type == DVBSUB_OT_COMPOSITE_STRING ) )        {            p_obj->i_fg_pc =  bs_read( s, 8 );            p_obj->i_bg_pc =  bs_read( s, 8 );            i_processed_length += 2;        }    }}/* ETSI 300 743 [7.2.1] */static void decode_display_definition( decoder_t *p_dec, bs_t *s ){    decoder_sys_t *p_sys = p_dec->p_sys;    uint16_t      i_segment_length;    uint16_t      i_processed_length = 40;    dvbsub_display_t *p_display;    dvbsub_display_t *p_old = p_sys->p_display;    int           i_version;    i_segment_length = bs_read( s, 16 );    i_version        = bs_read( s, 4 );    /* Check version number */    if( p_old && ( p_old->i_version == i_version ) )    {        /* The definition did not change */        bs_skip( s, 8*i_segment_length - 4 );        return;    }#ifdef DEBUG_DVBSUB    msg_Dbg( p_dec, "new display definition: %i", i_version );#endif    p_display = malloc( sizeof(dvbsub_display_t) );    if( p_display )    {        /* We don't have this version of the display definition: Parse it */        p_display->i_version = i_version;        p_display->b_windowed = bs_read( s, 1 );        bs_skip( s, 3 ); /* Reserved bits */        p_display->i_width = bs_read( s, 16 )+1;        p_display->i_height = bs_read( s, 16 )+1;        if( p_display->b_windowed )        {#ifdef DEBUG_DVBSUB            msg_Dbg( p_dec, "display definition with offsets (windowed)" );#endif            /* Coordinates are measured from the top left corner */            p_display->i_x     = bs_read( s, 16 );            p_display->i_max_x = bs_read( s, 16 );            p_display->i_y     = bs_read( s, 16 );            p_display->i_max_y = bs_read( s, 16 );            i_processed_length += 64;        }    }    p_sys->p_display = p_display;    free( p_old );    if( i_processed_length != i_segment_length*8 )    {        msg_Err( p_dec, "processed length %d != segment length %d",                 i_processed_length, i_segment_length );    }#ifdef DEBUG_DVBSUB    msg_Dbg( p_dec, "version: %d, width: %d, height: %d",             p_display->i_version, p_display->i_width, p_display->i_height );    if( p_display->b_windowed )        msg_Dbg( p_dec, "xmin: %d, xmax: %d, ymin: %d, ymax: %d",                 p_display->i_x, p_display->i_max_x, p_display->i_y, p_display->i_max_y );#endif}static void dvbsub_render_pdata( decoder_t *, dvbsub_region_t *, int, int,                                 uint8_t *, int );static void dvbsub_pdata2bpp( bs_t *, uint8_t *, int, int * );static void dvbsub_pdata4bpp( bs_t *, uint8_t *, int, int * );static void dvbsub_pdata8bpp( bs_t *, uint8_t *, int, int * );static void decode_object( decoder_t *p_dec, bs_t *s ){    decoder_sys_t *p_sys = p_dec->p_sys;    dvbsub_region_t *p_region;    int i_segment_length, i_coding_method, i_version, i_id, i;    bool b_non_modify_color;    /* ETSI 300-743 paragraph 7.2.4     * sync_byte, segment_type and page_id have already been processed.     */    i_segment_length = bs_read( s, 16 );    i_id             = bs_read( s, 16 );    i_version        = bs_read( s, 4 );    i_coding_method  = bs_read( s, 2 );    if( i_coding_method > 1 )    {        msg_Dbg( p_dec, "unknown DVB subtitling coding %d is not handled!", i_coding_method );        bs_skip( s, 8 * (i_segment_length - 2) - 6 );        return;    }    /* Check if the object needs to be rendered in at least one     * of the regions */    for( p_region = p_sys->p_regions; p_region != NULL;         p_region = p_region->p_next )    {        for( i = 0; i < p_region->i_object_defs; i++ )            if( p_region->p_object_defs[i].i_id == i_id ) break;        if( i != p_region->i_object_defs ) break;    }    if( !p_region )    {        bs_skip( s, 8 * (i_segment_length - 2) - 6 );        return;    }#ifdef DEBUG_DVBSUB    msg_Dbg( p_dec, "new object: %i", i_id );#endif    b_non_modify_color = bs_read( s, 1 );    bs_skip( s, 1 ); /* Reserved */    if( i_coding_method == 0x00 )    {        int i_topfield, i_bottomfield;        uint8_t *p_topfield, *p_bottomfield;        i_topfield    = bs_read( s, 16 );        i_bottomfield = bs_read( s, 16 );        p_topfield    = s->p_start + bs_pos( s ) / 8;        p_bottomfield = p_topfield + i_topfield;        bs_skip( s, 8 * (i_segment_length - 7) );        /* Sanity check */        if( ( i_segment_length < ( i_topfield + i_bottomfield + 7 ) ) ||            ( ( p_topfield + i_topfield + i_bottomfield ) > s->p_end ) )        {            msg_Dbg( p_dec, "corrupted object data" );            return;        }        for( p_region = p_sys->p_regions; p_region != NULL;             p_region = p_region->p_next )        {            for( i = 0; i < p_region->i_object_defs; i++ )            {                if( p_region->p_object_defs[i].i_id != i_id ) continue;                dvbsub_render_pdata( p_dec, p_region,                                     p_region->p_object_defs[i].i_x,                                     p_region->p_object_defs[i].i_y,                                     p_topfield, i_topfield );                if( i_bottomfield )                {                    dvbsub_render_pdata( p_dec, p_region,                                         p_region->p_object_defs[i].i_x,                                         p_region->p_object_defs[i].i_y + 1,                                         p_bottomfield, i_bottomfield );                }                else                {                    /* Duplicate the top field */                    dvbsub_render_pdata( p_dec, p_region,                                         p_region->p_object_defs[i].i_x,                                         p_region->p_object_defs[i].i_y + 1,                                         p_topfield, i_topfield );                }            }        }    }    else    {        /* DVB subtitling as characters */        int i_number_of_codes = bs_read( s, 8 );        uint8_t* p_start = s->p_start + bs_pos( s ) / 8;        /* Sanity check */        if( ( i_segment_length < ( i_number_of_codes*2 + 4 ) ) ||            ( ( p_start + i_number_of_codes*2 ) > s->p_end ) )        {            msg_Dbg( p_dec, "corrupted object data" );            return;        }        for( p_region = p_sys->p_regions; p_region != NULL;             p_region = p_region->p_next )        {            for( i = 0; i < p_region->i_object_defs; i++ )            {                int j;                if( p_region->p_object_defs[i].i_id != i_id ) continue;                p_region->p_object_defs[i].psz_text =                    realloc( p_region->p_object_defs[i].psz_text,                             i_number_of_codes + 1 );                /* FIXME 16bits -> char ??? See Preamble */                for( j = 0; j < i_number_of_codes; j++ )                {                    p_region->p_object_defs[i].psz_text[j] = (char)(bs_read( s, 16 ) & 0xFF);                }                /* Null terminate the string */                p_region->p_object_defs[i].psz_text[j] = 0;            }        }    }#ifdef DEBUG_DVBSUB    msg_Dbg( p_dec, "end object: %i", i_id );#endif}static void dvbsub_render_pdata( decoder_t *p_dec, dvbsub_region_t *p_region,                                 int i_x, int i_y,                                 uint8_t *p_field, int i_field ){    uint8_t *p_pixbuf;    int i_offset = 0;    bs_t bs;    /* Sanity check */    if( !p_region->p_pixbuf )    {        msg_Err( p_dec, "region %i has no pixel buffer!", p_region->i_id );        return;    }    if( i_y < 0 || i_x < 0 || i_y >= p_region->i_height ||        i_x >= p_region->i_width )    {        msg_Dbg( p_dec, "invalid offset (%i,%i)", i_x, i_y );        return;    }    p_pixbuf = p_region->p_pixbuf + i_y * p_region->i_width;    bs_init( &bs, p_field, i_field );    while( !bs_eof( &bs ) )    {        /* Sanity check */        if( i_y >= p_region->i_height ) return;        switch( bs_read( &bs, 8 ) )        {        case 0x10:            dvbsub_pdata2bpp( &bs, p_pixbuf + i_x, p_region->i_width - i_x,                              &i_offset );            break;        case 0x11:            dvbsub_pdata4bpp( &bs, p_pixbuf + i_x, p_region->i_width - i_x,                              &i_offset );            break;        case 0x12:            dvbsub_pdata8bpp( &bs, p_pixbuf + i_x, p_region->i_width - i_x,                              &i_offset );            break;        case 0x20:        case 0x21:        case 0x22:            /* We don't use map tables */            break;        case 0xf0: /* End of line code */            p_pixbuf += 2*p_region->i_width;            i_offset = 0; i_y += 2;            break;        }    }}static void dvbsub_pdata2bpp( bs_t *s, uint8_t *p, int i_width, int *pi_off ){    bool b_stop = false;    while( !b_stop && !bs_eof( s ) )    {        int i_count = 0, i_color = 0;        i_color = bs_read( s, 2 );        if( i_color != 0x00 )        {            i_count = 1;        }        else        {            if( bs_read( s, 1 ) == 0x01 )         // Switch1            {                i_count = 3 + bs_read( s, 3 );                i_color = bs_read( s, 2 );            }            else

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -