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

📄 flac.c

📁 VLC Player Source Code
💻 C
📖 第 1 页 / 共 2 页
字号:
    else if( i_query == DEMUX_GET_LENGTH )    {        int64_t *pi64 = (int64_t*)va_arg( args, int64_t * );        *pi64 = ControlGetLength( p_demux );        return VLC_SUCCESS;    }    else if( i_query == DEMUX_SET_TIME )    {        int64_t i_time = (int64_t)va_arg( args, int64_t );        return ControlSetTime( p_demux, i_time );    }    else if( i_query == DEMUX_SET_POSITION )    {        const double f = (double)va_arg( args, double );        int64_t i_time = f * ControlGetLength( p_demux );        return ControlSetTime( p_demux, i_time );    }    else if( i_query == DEMUX_GET_TIME )    {        int64_t *pi64 = (int64_t*)va_arg( args, int64_t * );        *pi64 = ControlGetTime( p_demux );        return VLC_SUCCESS;    }    else if( i_query == DEMUX_GET_POSITION )    {        double *pf = (double*)va_arg( args, double * );        const int64_t i_length = ControlGetLength(p_demux);        if( i_length > 0 )            *pf = (double)ControlGetTime(p_demux) / (double)i_length;        else            *pf= 0.0;        return VLC_SUCCESS;    }    else if( i_query == DEMUX_GET_ATTACHMENTS )    {        input_attachment_t ***ppp_attach =            (input_attachment_t***)va_arg( args, input_attachment_t*** );        int *pi_int = (int*)va_arg( args, int * );        int i;        if( p_sys->i_attachments <= 0 )            return VLC_EGENERIC;        *pi_int = p_sys->i_attachments;;        *ppp_attach = malloc( sizeof(input_attachment_t**) * p_sys->i_attachments );        for( i = 0; i < p_sys->i_attachments; i++ )            (*ppp_attach)[i] = vlc_input_attachment_Duplicate( p_sys->attachments[i] );        return VLC_SUCCESS;    }    return demux_vaControlHelper( p_demux->s, p_sys->i_data_pos, -1,                                   8*0, 1, i_query, args );}enum{    META_STREAMINFO = 0,    META_SEEKTABLE = 3,    META_COMMENT = 4,    META_PICTURE = 6,};static inline int Get24bBE( const uint8_t *p ){    return (p[0] << 16)|(p[1] << 8)|(p[2]);}static void ParseStreamInfo( int *pi_rate, int64_t *pi_count, uint8_t *p_data );static void ParseSeekTable( demux_t *p_demux, const uint8_t *p_data, int i_data,                            int i_sample_rate );static void ParseComment( demux_t *, const uint8_t *p_data, int i_data );static void ParsePicture( demux_t *, const uint8_t *p_data, int i_data );static int  ReadMeta( demux_t *p_demux, uint8_t **pp_streaminfo, int *pi_streaminfo ){    demux_sys_t *p_sys = p_demux->p_sys;    int     i_peek;    const uint8_t *p_peek;    bool b_last;    int i_sample_rate;    int64_t i_sample_count;    seekpoint_t *s;    /* Read STREAMINFO */    i_peek = stream_Peek( p_demux->s, &p_peek, 8 );    if( (p_peek[4] & 0x7F) != META_STREAMINFO )    {        msg_Err( p_demux, "this isn't a STREAMINFO metadata block" );        return VLC_EGENERIC;    }    if( Get24bBE(&p_peek[5]) != (STREAMINFO_SIZE - 4) )    {        msg_Err( p_demux, "invalid size for a STREAMINFO metadata block" );        return VLC_EGENERIC;    }    *pi_streaminfo = 4 + STREAMINFO_SIZE;    *pp_streaminfo = malloc( 4 + STREAMINFO_SIZE );    if( *pp_streaminfo == NULL )        return VLC_EGENERIC;    if( stream_Read( p_demux->s, *pp_streaminfo, 4+STREAMINFO_SIZE ) != 4+STREAMINFO_SIZE )    {        msg_Err( p_demux, "failed to read STREAMINFO metadata block" );        free( *pp_streaminfo );        return VLC_EGENERIC;    }    /* */    ParseStreamInfo( &i_sample_rate, &i_sample_count, *pp_streaminfo );    if( i_sample_rate > 0 )        p_sys->i_length = i_sample_count * INT64_C(1000000)/i_sample_rate;    /* Be sure we have seekpoint 0 */    s = vlc_seekpoint_New();    s->i_time_offset = 0;    s->i_byte_offset = 0;    TAB_APPEND( p_sys->i_seekpoint, p_sys->seekpoint, s );    b_last = (*pp_streaminfo)[4]&0x80;    while( !b_last )    {        int i_len;        int i_type;        i_peek = stream_Peek( p_demux->s, &p_peek, 4 );        if( i_peek < 4 )            break;        b_last = p_peek[0]&0x80;        i_type = p_peek[0]&0x7f;        i_len  = Get24bBE( &p_peek[1] );        if( i_type == META_SEEKTABLE )        {            i_peek = stream_Peek( p_demux->s, &p_peek, 4+i_len );            if( i_peek == 4+i_len )                ParseSeekTable( p_demux, p_peek, i_peek, i_sample_rate );        }        else if( i_type == META_COMMENT )        {            i_peek = stream_Peek( p_demux->s, &p_peek, 4+i_len );            if( i_peek == 4+i_len )                ParseComment( p_demux, p_peek, i_peek );        }        else if( i_type == META_PICTURE )        {            i_peek = stream_Peek( p_demux->s, &p_peek, 4+i_len );            if( i_peek == 4+i_len )                ParsePicture( p_demux, p_peek, i_peek );        }        if( stream_Read( p_demux->s, NULL, 4+i_len ) < 4+i_len )            break;    }    /* */    p_sys->i_data_pos = stream_Tell( p_demux->s );    return VLC_SUCCESS;}static void ParseStreamInfo( int *pi_rate, int64_t *pi_count, uint8_t *p_data ){    const int i_skip = 4+4;    *pi_rate = GetDWBE(&p_data[i_skip+4+6]) >> 12;    *pi_count = GetQWBE(&p_data[i_skip+4+6]) &  ((INT64_C(1)<<36)-1);}static void ParseSeekTable( demux_t *p_demux, const uint8_t *p_data, int i_data,                            int i_sample_rate ){    demux_sys_t *p_sys = p_demux->p_sys;    seekpoint_t *s;    int i;    if( i_sample_rate <= 0 )        return;    /* */    for( i = 0; i < (i_data-4)/18; i++ )    {        const int64_t i_sample = GetQWBE( &p_data[4+18*i+0] );        int j;        if( i_sample < 0 || i_sample >= INT64_MAX )            continue;        s = vlc_seekpoint_New();        s->i_time_offset = i_sample * INT64_C(1000000)/i_sample_rate;        s->i_byte_offset = GetQWBE( &p_data[4+18*i+8] );        /* Check for duplicate entry */        for( j = 0; j < p_sys->i_seekpoint; j++ )        {            if( p_sys->seekpoint[j]->i_time_offset == s->i_time_offset ||                p_sys->seekpoint[j]->i_byte_offset == s->i_byte_offset )            {                vlc_seekpoint_Delete( s );                s = NULL;                break;            }        }        if( s )        {            TAB_APPEND( p_sys->i_seekpoint, p_sys->seekpoint, s );        }    }    /* TODO sort it by size and remove wrong seek entry (time not increasing) */}#define RM(x) do { i_data -= (x); p_data += (x); } while(0)static void ParseComment( demux_t *p_demux, const uint8_t *p_data, int i_data ){    demux_sys_t *p_sys = p_demux->p_sys;    int n;    int i_comment;    if( i_data < 8 )        return;    RM(4);    n = GetDWLE(p_data); RM(4);    if( n < 0 || n > i_data )        return;#if 0    if( n > 0 )    {        /* TODO report vendor string ? */        char *psz_vendor = psz_vendor = strndup( p_data, n );        msg_Dbg( p_demux, "FLAC: COMMENT vendor length=%d vendor=%s\n", n, psz_vendor );        free( psz_vendor );    }#endif    RM(n);    if( i_data < 4 )        return;    i_comment = GetDWLE(p_data); RM(4);    if( i_comment <= 0 )        return;    p_sys->p_meta = vlc_meta_New();    for( ; i_comment > 0; i_comment-- )    {        char *psz;        if( i_data < 4 )            break;        n = GetDWLE(p_data); RM(4);        if( n > i_data )            break;        if( n <= 0 )            continue;        psz = strndup( (const char*)p_data, n );        RM(n);        EnsureUTF8( psz );#define IF_EXTRACT(txt,var) \    if( !strncasecmp(psz, txt, strlen(txt)) ) \    { \        const char *oldval = vlc_meta_Get( p_sys->p_meta, vlc_meta_ ## var ); \        if( oldval ) \        { \            char * newval; \            if( asprintf( &newval, "%s,%s", oldval, &psz[strlen(txt)] ) == -1 ) \                newval = NULL; \            vlc_meta_Set( p_sys->p_meta, vlc_meta_ ## var, newval ); \            free( newval ); \        } \        else \            vlc_meta_Set( p_sys->p_meta, vlc_meta_ ## var, &psz[strlen(txt)] ); \    }        IF_EXTRACT("TITLE=", Title )        else IF_EXTRACT("ALBUM=", Album )        else IF_EXTRACT("TRACKNUMBER=", TrackNumber )        else IF_EXTRACT("ARTIST=", Artist )        else IF_EXTRACT("COPYRIGHT=", Copyright )        else IF_EXTRACT("DESCRIPTION=", Description )        else IF_EXTRACT("GENRE=", Genre )        else IF_EXTRACT("DATE=", Date )        else if( strchr( psz, '=' ) )        {            /* generic (PERFORMER/LICENSE/ORGANIZATION/LOCATION/CONTACT/ISRC,             * undocumented tags and replay gain ) */            char *p = strchr( psz, '=' );            *p++ = '\0';            vlc_meta_AddExtra( p_sys->p_meta, psz, p );        }#undef IF_EXTRACT        free( psz );    }#undef RM}static void ParsePicture( demux_t *p_demux, const uint8_t *p_data, int i_data ){    static const int pi_cover_score[] = {        0,      /* other */        2, 1,   /* icons */        10,     /* front cover */        9,      /* back cover */        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,        6,      /* movie/video screen capture */        0,        7,      /* Illustration */        8,      /* Band/Artist logotype */        0,      /* Publisher/Studio */    };    demux_sys_t *p_sys = p_demux->p_sys;    int i_type;    int i_len;    char *psz_mime = NULL;    char *psz_description = NULL;    input_attachment_t *p_attachment;    char psz_name[128];    if( i_data < 4 + 3*4 )        return;#define RM(x) do { i_data -= (x); p_data += (x); } while(0)    RM(4);    i_type = GetDWBE( p_data ); RM(4);    i_len = GetDWBE( p_data ); RM(4);    if( i_len < 0 || i_data < i_len + 4 )        goto error;    psz_mime = strndup( (const char*)p_data, i_len ); RM(i_len);    i_len = GetDWBE( p_data ); RM(4);    if( i_len < 0 || i_data < i_len + 4*4 + 4)        goto error;    psz_description = strndup( (const char*)p_data, i_len ); RM(i_len);    EnsureUTF8( psz_description );    RM(4*4);    i_len = GetDWBE( p_data ); RM(4);    if( i_len < 0 || i_len > i_data )        goto error;    msg_Dbg( p_demux, "FLAC: Picture type=%d mime=%s description='%s' file length=%d",             i_type, psz_mime, psz_description, i_len );    snprintf( psz_name, sizeof(psz_name), "picture%d", p_sys->i_attachments );    if( !strcasecmp( psz_mime, "image/jpeg" ) )        strcat( psz_name, ".jpg" );    else if( !strcasecmp( psz_mime, "image/png" ) )        strcat( psz_name, ".png" );    p_attachment = vlc_input_attachment_New( psz_name, psz_mime, psz_description,                                             p_data, i_data );    TAB_APPEND( p_sys->i_attachments, p_sys->attachments, p_attachment );    if( i_type >= 0 && (unsigned int)i_type < sizeof(pi_cover_score)/sizeof(pi_cover_score[0]) &&        p_sys->i_cover_score < pi_cover_score[i_type] )    {        p_sys->i_cover_idx = p_sys->i_attachments-1;        p_sys->i_cover_score = pi_cover_score[i_type];    }error:    free( psz_mime );    free( psz_description );}#undef RM

⌨️ 快捷键说明

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