Example #1
0
File: vcd.c Project: Ackhuman/vlc
/*****************************************************************************
 * EntryPoints: Reads the information about the entry points on the disc.
 *****************************************************************************/
static int EntryPoints( access_t *p_access )
{
    access_sys_t *p_sys = p_access->p_sys;
    uint8_t      sector[VCD_DATA_SIZE];

    entries_sect_t entries;
    int i_nb;

    /* Read the entry point sector */
    if( ioctl_ReadSectors( VLC_OBJECT(p_access), p_sys->vcddev,
        VCD_ENTRIES_SECTOR, sector, 1, VCD_TYPE ) < 0 )
    {
        msg_Err( p_access, "could not read entry points sector" );
        return VLC_EGENERIC;
    }
    memcpy( &entries, sector, CD_SECTOR_SIZE );

    i_nb = GetWBE( &entries.i_entries_nb );
    if( i_nb > 500 )
    {
        msg_Err( p_access, "invalid entry points number" );
        return VLC_EGENERIC;
    }

    if( strncmp( entries.psz_id, "ENTRYVCD", sizeof( entries.psz_id ) ) &&
        strncmp( entries.psz_id, "ENTRYSVD", sizeof( entries.psz_id ) ) )
    {
        msg_Err( p_access, "unrecognized entry points format" );
        return VLC_EGENERIC;
    }

    for( int i = 0; i < i_nb; i++ )
    {
        const int i_title = BCD_TO_BIN(entries.entry[i].i_track) - 2;
        const int i_sector =
            (MSF_TO_LBA2( BCD_TO_BIN( entries.entry[i].msf.minute ),
                          BCD_TO_BIN( entries.entry[i].msf.second ),
                          BCD_TO_BIN( entries.entry[i].msf.frame  ) ));
        seekpoint_t *s;

        if( i_title < 0 ) continue;   /* Should not occur */
        if( i_title >= p_sys->i_titles ) continue;

        msg_Dbg( p_access, "Entry[%d] title=%d sector=%d",
                 i, i_title, i_sector );

        s = vlc_seekpoint_New();
        s->i_byte_offset = (i_sector - p_sys->p_sectors[i_title+1]) *
            VCD_DATA_SIZE;

        TAB_APPEND( p_sys->title[i_title]->i_seekpoint,
                    p_sys->title[i_title]->seekpoint, s );
    }

    return VLC_SUCCESS;
}
/*****************************************************************************
 * Block: read data (CDDA_DATA_ONCE)
 *****************************************************************************/
static block_t *Block( access_t *p_access )
{
    access_sys_t *p_sys = p_access->p_sys;
    int i_blocks = CDDA_BLOCKS_ONCE;
    block_t *p_block;

    if( p_sys->i_track < 0 ) p_access->info.b_eof = true;

    /* Check end of file */
    if( p_access->info.b_eof ) return NULL;

    if( !p_sys->b_header )
    {
        /* Return only the header */
        p_block = block_Alloc( sizeof( WAVEHEADER ) );
        memcpy( p_block->p_buffer, &p_sys->waveheader, sizeof(WAVEHEADER) );
        p_sys->b_header = true;
        return p_block;
    }

    if( p_sys->i_sector >= p_sys->i_last_sector )
    {
        p_access->info.b_eof = true;
        return NULL;
    }

    /* Don't read too far */
    if( p_sys->i_sector + i_blocks >= p_sys->i_last_sector )
        i_blocks = p_sys->i_last_sector - p_sys->i_sector;

    /* Do the actual reading */
    if( !( p_block = block_Alloc( i_blocks * CDDA_DATA_SIZE ) ) )
    {
        msg_Err( p_access, "cannot get a new block of size: %i",
                 i_blocks * CDDA_DATA_SIZE );
        return NULL;
    }

    if( ioctl_ReadSectors( VLC_OBJECT(p_access), p_sys->vcddev,
            p_sys->i_sector, p_block->p_buffer, i_blocks, CDDA_TYPE ) < 0 )
    {
        msg_Err( p_access, "cannot read sector %i", p_sys->i_sector );
        block_Release( p_block );

        /* Try to skip one sector (in case of bad sectors) */
        p_sys->i_sector++;
        p_access->info.i_pos += CDDA_DATA_SIZE;
        return NULL;
    }

    /* Update a few values */
    p_sys->i_sector += i_blocks;
    p_access->info.i_pos += p_block->i_buffer;

    return p_block;
}
Example #3
0
File: vcd.c Project: Ackhuman/vlc
/*****************************************************************************
 * Block:
 *****************************************************************************/
static block_t *Block( access_t *p_access )
{
    access_sys_t *p_sys = p_access->p_sys;
    int i_blocks = VCD_BLOCKS_ONCE;
    block_t *p_block;

    /* Check end of file */
    if( p_access->info.b_eof ) return NULL;

    /* Check end of title */
    while( p_sys->i_sector >= p_sys->p_sectors[p_access->info.i_title + 2] )
    {
        if( p_access->info.i_title + 2 >= p_sys->i_titles )
        {
            p_access->info.b_eof = true;
            return NULL;
        }

        p_access->info.i_update |=
            INPUT_UPDATE_TITLE | INPUT_UPDATE_SEEKPOINT | INPUT_UPDATE_SIZE;
        p_access->info.i_title++;
        p_access->info.i_seekpoint = 0;
        p_access->info.i_size = p_sys->title[p_access->info.i_title]->i_size;
        p_access->info.i_pos = 0;
    }

    /* Don't read after the end of a title */
    if( p_sys->i_sector + i_blocks >=
        p_sys->p_sectors[p_access->info.i_title + 2] )
    {
        i_blocks = p_sys->p_sectors[p_access->info.i_title + 2 ] - p_sys->i_sector;
    }

    /* Do the actual reading */
    if( i_blocks < 0 || !( p_block = block_Alloc( i_blocks * VCD_DATA_SIZE ) ) )
    {
        msg_Err( p_access, "cannot get a new block of size: %i",
                 i_blocks * VCD_DATA_SIZE );
        return NULL;
    }

    if( ioctl_ReadSectors( VLC_OBJECT(p_access), p_sys->vcddev,
            p_sys->i_sector, p_block->p_buffer, i_blocks, VCD_TYPE ) < 0 )
    {
        msg_Err( p_access, "cannot read sector %i", p_sys->i_sector );
        block_Release( p_block );

        /* Try to skip one sector (in case of bad sectors) */
        p_sys->i_sector++;
        p_access->info.i_pos += VCD_DATA_SIZE;
        return NULL;
    }

    /* Update seekpoints */
    for( int i_read = 0; i_read < i_blocks; i_read++ )
    {
        input_title_t *t = p_sys->title[p_access->info.i_title];

        if( t->i_seekpoint > 0 &&
            p_access->info.i_seekpoint + 1 < t->i_seekpoint &&
            (int64_t) /* Unlikely to go over 8192 PetaB */
                (p_access->info.i_pos + i_read * VCD_DATA_SIZE) >=
            t->seekpoint[p_access->info.i_seekpoint+1]->i_byte_offset )
        {
            msg_Dbg( p_access, "seekpoint change" );
            p_access->info.i_update |= INPUT_UPDATE_SEEKPOINT;
            p_access->info.i_seekpoint++;
        }
    }

    /* Update a few values */
    p_sys->i_sector += i_blocks;
    p_access->info.i_pos += p_block->i_buffer;

    return p_block;
}