parse.c

来自「VLC媒体播放程序」· C语言 代码 · 共 673 行 · 第 1/2 页

C
673
字号
        */        p_spu->b_ephemer = VLC_TRUE;    }    /* Get rid of padding bytes */    if( p_sys->i_spu_size > (int)i_index + 1 )    {        /* Zero or one padding byte, are quite usual         * More than one padding byte - this is very strange, but         * we can deal with it */        msg_Warn( p_dec, "%i padding bytes, we usually get 0 or 1 of them",                  p_sys->i_spu_size - i_index );    }    /* Successfully parsed ! */    return VLC_SUCCESS;}/***************************************************************************** * ParseRLE: parse the RLE part of the subtitle ***************************************************************************** * This part parses the subtitle graphical data and stores it in a more * convenient structure for later decoding. For more information on the * subtitles format, see http://sam.zoy.org/doc/dvd/subtitles/index.html *****************************************************************************/static int ParseRLE( decoder_t *p_dec, subpicture_t * p_spu ){    decoder_sys_t *p_sys = p_dec->p_sys;    uint8_t       *p_src = &p_sys->buffer[4];    unsigned int i_code;    unsigned int i_width = p_spu->i_width;    unsigned int i_height = p_spu->i_height;    unsigned int i_x, i_y;    uint16_t *p_dest = (uint16_t *)p_spu->p_sys->p_data;    /* The subtitles are interlaced, we need two offsets */    unsigned int  i_id = 0;                   /* Start on the even SPU layer */    unsigned int  pi_table[ 2 ];    unsigned int *pi_offset;#if 0 /* cropping */    vlc_bool_t b_empty_top = VLC_TRUE,               b_empty_bottom = VLC_FALSE;    unsigned int i_skipped_top = 0,                 i_skipped_bottom = 0;#endif    /* Colormap statistics */    int i_border = -1;    int stats[4]; stats[0] = stats[1] = stats[2] = stats[3] = 0;    pi_table[ 0 ] = p_spu->p_sys->pi_offset[ 0 ] << 1;    pi_table[ 1 ] = p_spu->p_sys->pi_offset[ 1 ] << 1;    for( i_y = 0 ; i_y < i_height ; i_y++ )    {        pi_offset = pi_table + i_id;        for( i_x = 0 ; i_x < i_width ; i_x += i_code >> 2 )        {            i_code = AddNibble( 0, p_src, pi_offset );            if( i_code < 0x04 )            {                i_code = AddNibble( i_code, p_src, pi_offset );                if( i_code < 0x10 )                {                    i_code = AddNibble( i_code, p_src, pi_offset );                    if( i_code < 0x040 )                    {                        i_code = AddNibble( i_code, p_src, pi_offset );                        if( i_code < 0x0100 )                        {                            /* If the 14 first bits are set to 0, then it's a                             * new line. We emulate it. */                            if( i_code < 0x0004 )                            {                                i_code |= ( i_width - i_x ) << 2;                            }                            else                            {                                /* We have a boo boo ! */                                msg_Err( p_dec, "unknown RLE code "                                         "0x%.4x", i_code );                                return VLC_EGENERIC;                            }                        }                    }                }            }            if( ( (i_code >> 2) + i_x + i_y * i_width ) > i_height * i_width )            {                msg_Err( p_dec,                         "out of bounds, %i at (%i,%i) is out of %ix%i",                         i_code >> 2, i_x, i_y, i_width, i_height );                return VLC_EGENERIC;            }            /* Try to find the border color */            if( p_spu->p_sys->pi_alpha[ i_code & 0x3 ] != 0x00 )            {                i_border = i_code & 0x3;                stats[i_border] += i_code >> 2;            }#if 0 /* cropping */            if( (i_code >> 2) == i_width                 && p_spu->p_sys->pi_alpha[ i_code & 0x3 ] == 0x00 )            {                if( b_empty_top )                {                    /* This is a blank top line, we skip it */                    i_skipped_top++;                }                else                {                    /* We can't be sure the current lines will be skipped,                     * so we store the code just in case. */                    *p_dest++ = i_code;                    b_empty_bottom = VLC_TRUE;                    i_skipped_bottom++;                }            }            else            {                /* We got a valid code, store it */                *p_dest++ = i_code;                /* Valid code means no blank line */                b_empty_top = VLC_FALSE;                b_empty_bottom = VLC_FALSE;                i_skipped_bottom = 0;            }#else            *p_dest++ = i_code;#endif        }        /* Check that we didn't go too far */        if( i_x > i_width )        {            msg_Err( p_dec, "i_x overflowed, %i > %i",                     i_x, i_width );            return VLC_EGENERIC;        }        /* Byte-align the stream */        if( *pi_offset & 0x1 )        {            (*pi_offset)++;        }        /* Swap fields */        i_id = ~i_id & 0x1;    }    /* We shouldn't get any padding bytes */    if( i_y < i_height )    {        msg_Err( p_dec, "padding bytes found in RLE sequence" );        msg_Err( p_dec, "send mail to <sam@zoy.org> if you "                        "want to help debugging this" );        /* Skip them just in case */        while( i_y < i_height )        {            *p_dest++ = i_width << 2;            i_y++;        }        return VLC_EGENERIC;    }    msg_Dbg( p_dec, "valid subtitle, size: %ix%i, position: %i,%i",             p_spu->i_width, p_spu->i_height, p_spu->i_x, p_spu->i_y );#if 0 /* cropping */    /* Crop if necessary */    if( i_skipped_top || i_skipped_bottom )    {        p_spu->i_y += i_skipped_top;        p_spu->i_height -= i_skipped_top + i_skipped_bottom;        msg_Dbg( p_spudec->p_fifo, "cropped to: %ix%i, position: %i,%i",                 p_spu->i_width, p_spu->i_height, p_spu->i_x, p_spu->i_y );    }#endif    /* Handle color if no palette was found */    if( !p_spu->p_sys->b_palette )    {        int i, i_inner = -1, i_shade = -1;        /* Set the border color */        p_spu->p_sys->pi_yuv[i_border][0] = 0x00;        p_spu->p_sys->pi_yuv[i_border][1] = 0x80;        p_spu->p_sys->pi_yuv[i_border][2] = 0x80;        stats[i_border] = 0;        /* Find the inner colors */        for( i = 0 ; i < 4 && i_inner == -1 ; i++ )        {            if( stats[i] )            {                i_inner = i;            }        }        for(       ; i < 4 && i_shade == -1 ; i++ )        {            if( stats[i] )            {                if( stats[i] > stats[i_inner] )                {                    i_shade = i_inner;                    i_inner = i;                }                else                {                    i_shade = i;                }            }        }        /* Set the inner color */        if( i_inner != -1 )        {            p_spu->p_sys->pi_yuv[i_inner][0] = 0xff;            p_spu->p_sys->pi_yuv[i_inner][1] = 0x80;            p_spu->p_sys->pi_yuv[i_inner][2] = 0x80;        }        /* Set the anti-aliasing color */        if( i_shade != -1 )        {            p_spu->p_sys->pi_yuv[i_shade][0] = 0x80;            p_spu->p_sys->pi_yuv[i_shade][1] = 0x80;            p_spu->p_sys->pi_yuv[i_shade][2] = 0x80;        }        msg_Dbg( p_dec,                 "using custom palette (border %i, inner %i, shade %i)",                 i_border, i_inner, i_shade );    }    return VLC_SUCCESS;}/***************************************************************************** * DestroySPU: subpicture destructor *****************************************************************************/static void DestroySPU( subpicture_t *p_spu ){    if( p_spu->p_sys->p_input )    {        /* Detach from our input thread */        var_DelCallback( p_spu->p_sys->p_input, "highlight",                         CropCallback, p_spu );        vlc_object_release( p_spu->p_sys->p_input );    }    vlc_mutex_destroy( &p_spu->p_sys->lock );    free( p_spu->p_sys );}/***************************************************************************** * UpdateSPU: update subpicture settings ***************************************************************************** * This function is called from CropCallback and at initialization time, to * retrieve crop information from the input. *****************************************************************************/static void UpdateSPU( subpicture_t *p_spu, vlc_object_t *p_object ){    vlc_value_t val;    if( var_Get( p_object, "highlight", &val ) )    {        return;    }    p_spu->p_sys->b_crop = val.b_bool;    if( !p_spu->p_sys->b_crop )    {        return;    }    var_Get( p_object, "x-start", &val );    p_spu->p_sys->i_x_start = val.i_int;    var_Get( p_object, "y-start", &val );    p_spu->p_sys->i_y_start = val.i_int;    var_Get( p_object, "x-end", &val );    p_spu->p_sys->i_x_end = val.i_int;    var_Get( p_object, "y-end", &val );    p_spu->p_sys->i_y_end = val.i_int;#if 0    if( var_Get( p_object, "color", &val ) == VLC_SUCCESS )    {        p_spu->p_sys->pi_color[0] = ((uint8_t *)val.p_address)[0];        p_spu->p_sys->pi_color[1] = ((uint8_t *)val.p_address)[1];        p_spu->p_sys->pi_color[2] = ((uint8_t *)val.p_address)[2];        p_spu->p_sys->pi_color[3] = ((uint8_t *)val.p_address)[3];    }#endif    if( var_Get( p_object, "contrast", &val ) == VLC_SUCCESS )    {        p_spu->p_sys->pi_alpha[0] = ((uint8_t *)val.p_address)[0];        p_spu->p_sys->pi_alpha[1] = ((uint8_t *)val.p_address)[1];        p_spu->p_sys->pi_alpha[2] = ((uint8_t *)val.p_address)[2];        p_spu->p_sys->pi_alpha[3] = ((uint8_t *)val.p_address)[3];    }}/***************************************************************************** * CropCallback: called when the highlight properties are changed ***************************************************************************** * This callback is called from the input thread when we need cropping *****************************************************************************/static int CropCallback( vlc_object_t *p_object, char const *psz_var,                         vlc_value_t oldval, vlc_value_t newval, void *p_data ){    UpdateSPU( (subpicture_t *)p_data, p_object );    return VLC_SUCCESS;}

⌨️ 快捷键说明

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