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

📄 parse.c

📁 video linux conference
💻 C
📖 第 1 页 / 共 2 页
字号:
    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,                     subpicture_data_t *p_spu_data ){    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_data->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;    /* Cropping */    vlc_bool_t b_empty_top = VLC_TRUE;    unsigned int i_skipped_top = 0, i_skipped_bottom = 0;    unsigned int i_transparent_code = 0;     /* Colormap statistics */    int i_border = -1;    int stats[4]; stats[0] = stats[1] = stats[2] = stats[3] = 0;    pi_table[ 0 ] = p_spu_data->pi_offset[ 0 ] << 1;    pi_table[ 1 ] = p_spu_data->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_data->pi_alpha[ i_code & 0x3 ] != 0x00 )            {                i_border = i_code & 0x3;                stats[i_border] += i_code >> 2;            }            /* Auto crop subtitles (a lot more optimized) */            if( p_spu_data->b_auto_crop )            {                if( !i_y )                {                    /* We assume that if the first line is transparent, then                     * it is using the palette index for the                     * (background) transparent color */                    if( (i_code >> 2) == i_width &&                        p_spu_data->pi_alpha[ i_code & 0x3 ] == 0x00 )                    {                        i_transparent_code = i_code;                    }                    else                    {                        p_spu_data->b_auto_crop = VLC_FALSE;                    }                }                if( i_code == i_transparent_code )                {                    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;                      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;                    i_skipped_bottom = 0;                }            }            else            {                *p_dest++ = i_code;            }        }        /* 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 );    /* Crop if necessary */    if( i_skipped_top || i_skipped_bottom )    {        int i_y = p_spu->i_y + i_skipped_top;        int i_height = p_spu->i_height - (i_skipped_top + i_skipped_bottom);        p_spu_data->i_y_top_offset = i_skipped_top;        p_spu_data->i_y_bottom_offset = i_skipped_bottom;        msg_Dbg( p_dec, "cropped to: %ix%i, position: %i,%i",                 p_spu->i_width, i_height, p_spu->i_x, i_y );    }     /* Handle color if no palette was found */    if( !p_spu_data->b_palette )    {        int i, i_inner = -1, i_shade = -1;        /* Set the border color */        p_spu_data->pi_yuv[i_border][0] = 0x00;        p_spu_data->pi_yuv[i_border][1] = 0x80;        p_spu_data->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_data->pi_yuv[i_inner][0] = 0xff;            p_spu_data->pi_yuv[i_inner][1] = 0x80;            p_spu_data->pi_yuv[i_inner][2] = 0x80;        }        /* Set the anti-aliasing color */        if( i_shade != -1 )        {            p_spu_data->pi_yuv[i_shade][0] = 0x80;            p_spu_data->pi_yuv[i_shade][1] = 0x80;            p_spu_data->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;}static void Render( decoder_t *p_dec, subpicture_t *p_spu,                    subpicture_data_t *p_spu_data ){    uint8_t *p_p;    int i_x, i_y, i_len, i_color, i_pitch;    uint16_t *p_source = (uint16_t *)p_spu_data->p_data;    video_format_t fmt;    /* Create a new subpicture region */    memset( &fmt, 0, sizeof(video_format_t) );    fmt.i_chroma = VLC_FOURCC('Y','U','V','P');    fmt.i_aspect = 0; /* 0 means use aspect ratio of background video */    fmt.i_width = fmt.i_visible_width = p_spu->i_width;    fmt.i_height = fmt.i_visible_height = p_spu->i_height -        p_spu_data->i_y_top_offset - p_spu_data->i_y_bottom_offset;    fmt.i_x_offset = fmt.i_y_offset = 0;    p_spu->p_region = p_spu->pf_create_region( VLC_OBJECT(p_dec), &fmt );    if( !p_spu->p_region )    {        msg_Err( p_dec, "cannot allocate SPU region" );        return;    }    p_spu->p_region->i_x = 0;    p_spu->p_region->i_y = p_spu_data->i_y_top_offset;    p_p = p_spu->p_region->picture.p->p_pixels;    i_pitch = p_spu->p_region->picture.p->i_pitch;    /* Build palette */    fmt.p_palette->i_entries = 4;    for( i_x = 0; i_x < fmt.p_palette->i_entries; i_x++ )    {        fmt.p_palette->palette[i_x][0] = p_spu_data->pi_yuv[i_x][0];        fmt.p_palette->palette[i_x][1] = p_spu_data->pi_yuv[i_x][1];        fmt.p_palette->palette[i_x][2] = p_spu_data->pi_yuv[i_x][2];        fmt.p_palette->palette[i_x][3] =            p_spu_data->pi_alpha[i_x] == 0xf ? 0xff :            p_spu_data->pi_alpha[i_x] << 4;    }    /* Draw until we reach the bottom of the subtitle */    for( i_y = 0; i_y < (int)fmt.i_height * i_pitch; i_y += i_pitch )    {        /* Draw until we reach the end of the line */        for( i_x = 0 ; i_x < (int)fmt.i_width; i_x += i_len )        {            /* Get the RLE part, then draw the line */            i_color = *p_source & 0x3;            i_len = *p_source++ >> 2;            memset( p_p + i_x + i_y, i_color, i_len );        }    }}

⌨️ 快捷键说明

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