예제 #1
0
void vlc_stream_io_callback::setFilePointer(int64_t i_offset, seek_mode mode )
{
    int64_t i_pos, i_size;

    switch( mode )
    {
        case seek_beginning:
            i_pos = i_offset;
            break;
        case seek_end:
            i_pos = stream_Size( s ) - i_offset;
            break;
        default:
            i_pos= stream_Tell( s ) + i_offset;
            break;
    }

    if( i_pos < 0 || ( ( i_size = stream_Size( s ) ) != 0 && i_pos >= i_size ) )
    {
        mb_eof = true;
        return;
    }

    mb_eof = false;
    if( stream_Seek( s, i_pos ) )
    {
        mb_eof = true;
    }
    return;
}
예제 #2
0
파일: access.c 프로젝트: 9034725985/vlc
static ssize_t SeekCallback(struct archive *p_archive, void *p_object, ssize_t i_offset, int i_whence)
{
    VLC_UNUSED(p_archive);
    callback_data_t *p_data = (callback_data_t *) p_object;
    access_sys_t *p_sys = p_data->p_access->p_sys;

    ssize_t i_pos;

    switch(i_whence)
    {
    case SEEK_CUR:
        i_pos = stream_Tell(p_sys->p_stream);
        break;
    case SEEK_SET:
        i_pos = 0;
        break;
    case SEEK_END:
        i_pos = stream_Size(p_sys->p_stream) - 1;
        break;
    default:
        return -1;
    }

    if (i_pos < 0)
        return -1;

    stream_Seek(p_sys->p_stream, i_pos + i_offset); /* We don't care about return val */
    return stream_Tell(p_sys->p_stream);
}
예제 #3
0
파일: flac.c 프로젝트: chouquette/vlc
/*****************************************************************************
 * Control:
 *****************************************************************************/
static int64_t ControlGetLength( demux_t *p_demux )
{
    demux_sys_t *p_sys = p_demux->p_sys;
    const uint64_t i_size = stream_Size(p_demux->s) - p_sys->i_data_pos;
    int64_t i_length = p_sys->i_length;
    int i;

    /* Try to fix length using seekpoint and current size for truncated file */
    for( i = p_sys->i_seekpoint-1; i >= 0; i-- )
    {
        flac_seekpoint_t *s = p_sys->seekpoint[i];
        if( s->i_byte_offset <= i_size )
        {
            if( i+1 < p_sys->i_seekpoint )
            {
                /* Broken file */
                flac_seekpoint_t *n = p_sys->seekpoint[i+1];
                assert( n->i_byte_offset != s->i_byte_offset); /* Should be ensured by ParseSeekTable */
                i_length = s->i_time_offset + (n->i_time_offset-s->i_time_offset) * (i_size-s->i_byte_offset) / (n->i_byte_offset-s->i_byte_offset);
            }
            break;
        }
    }
    return i_length;
}
예제 #4
0
파일: vlc.c 프로젝트: banketree/faplayer
/** Replacement for luaL_dofile, using VLC's input capabilities */
int vlclua_dofile( vlc_object_t *p_this, lua_State *L, const char *uri )
{
    if( !strstr( uri, "://" ) )
        return luaL_dofile( L, uri );
    if( !strncasecmp( uri, "file://", 7 ) )
        return luaL_dofile( L, uri + 7 );
    stream_t *s = stream_UrlNew( p_this, uri );
    if( !s )
    {
        return 1;
    }
    int64_t i_size = stream_Size( s );
    char *p_buffer = ( i_size > 0 ) ? malloc( i_size ) : NULL;
    if( !p_buffer )
    {
        // FIXME: read the whole stream until we reach the end (if no size)
        stream_Delete( s );
        return 1;
    }
    int64_t i_read = stream_Read( s, p_buffer, (int) i_size );
    int i_ret = ( i_read == i_size ) ? 0 : 1;
    if( !i_ret )
        i_ret = luaL_loadbuffer( L, p_buffer, (size_t) i_size, uri );
    if( !i_ret )
        i_ret = lua_pcall( L, 0, LUA_MULTRET, 0 );
    stream_Delete( s );
    free( p_buffer );
    return i_ret;
}
예제 #5
0
uint64 vlc_stream_io_callback::toRead( void )
{
    uint64_t i_size;

    if( s == NULL)
        return 0;

    i_size = stream_Size( s );

    if( i_size <= 0 )
        return UINT64_MAX;

    return static_cast<uint64>( i_size - stream_Tell( s ) );
}
예제 #6
0
int AVI_ChunkReadRoot( stream_t *s, avi_chunk_t *p_root )
{
    avi_chunk_list_t *p_list = (avi_chunk_list_t*)p_root;
    avi_chunk_t      *p_chk;
    bool b_seekable;

    stream_Control( s, STREAM_CAN_FASTSEEK, &b_seekable );

    p_list->i_chunk_pos  = 0;
    p_list->i_chunk_size = stream_Size( s );
    p_list->i_chunk_fourcc = AVIFOURCC_LIST;
    p_list->p_father = NULL;
    p_list->p_next  = NULL;
    p_list->p_first = NULL;
    p_list->p_last  = NULL;

    p_list->i_type = VLC_FOURCC( 'r', 'o', 'o', 't' );

    for( ; ; )
    {
        p_chk = malloc( sizeof( avi_chunk_t ) );
        memset( p_chk, 0, sizeof( avi_chunk_t ) );
        if( !p_root->common.p_first )
        {
            p_root->common.p_first = p_chk;
        }
        else
        {
            p_root->common.p_last->common.p_next = p_chk;
        }
        p_root->common.p_last = p_chk;

        if( AVI_ChunkRead( s, p_chk, p_root ) ||
           ( stream_Tell( s ) >=
              (off_t)p_chk->common.p_father->common.i_chunk_pos +
               (off_t)__EVEN( p_chk->common.p_father->common.i_chunk_size ) ) )
        {
            break;
        }
        /* If we can't seek then stop when we 've found first RIFF-AVI */
        if( p_chk->common.i_chunk_fourcc == AVIFOURCC_RIFF &&
            p_chk->list.i_type == AVIFOURCC_AVI && !b_seekable )
        {
            break;
        }
    }

    AVI_ChunkDumpDebug_level( (vlc_object_t*)s, p_root, 0 );
    return VLC_SUCCESS;
}
uint64 vlc_stream_io_callback::toRead( void )
{
    uint64_t i_size;

    if( s == NULL)
        return 0;

    i_size = stream_Size( s );

    if( i_size == 0 )
        return UINT64_MAX;

    return (uint64) i_size - stream_Tell( s );
}
예제 #8
0
파일: demux.c 프로젝트: mstorsjo/vlc
static int64_t IOSeek( void *opaque, int64_t offset, int whence )
{
    demux_t *p_demux = opaque;
    int64_t i_absolute;
    int64_t i_size = stream_Size( p_demux->s );

#ifdef AVFORMAT_DEBUG
    msg_Warn( p_demux, "IOSeek offset: %"PRId64", whence: %i", offset, whence );
#endif

    switch( whence )
    {
#ifdef AVSEEK_SIZE
        case AVSEEK_SIZE:
            return i_size;
#endif
        case SEEK_SET:
            i_absolute = (int64_t)offset;
            break;
        case SEEK_CUR:
            i_absolute = vlc_stream_Tell( p_demux->s ) + (int64_t)offset;
            break;
        case SEEK_END:
            i_absolute = i_size + (int64_t)offset;
            break;
        default:
            return -1;

    }

    if( i_absolute < 0 )
    {
        msg_Dbg( p_demux, "Trying to seek before the beginning" );
        return -1;
    }

    if( i_size > 0 && i_absolute >= i_size )
    {
        msg_Dbg( p_demux, "Trying to seek too far : EOF?" );
        return -1;
    }

    if( vlc_stream_Seek( p_demux->s, i_absolute ) )
    {
        msg_Warn( p_demux, "we were not allowed to seek, or EOF " );
        return -1;
    }

    return vlc_stream_Tell( p_demux->s );
}
예제 #9
0
파일: image.c 프로젝트: jomanmuk/vlc-2.2
static block_t *Load(demux_t *demux)
{
    const int     max_size = 4096 * 4096 * 8;
    const int64_t size = stream_Size(demux->s);
    if (size < 0 || size > max_size) {
        msg_Err(demux, "Rejecting image based on its size (%"PRId64" > %d)", size, max_size);
        return NULL;
    }

    if (size > 0)
        return stream_Block(demux->s, size);
    /* TODO */
    return NULL;
}
예제 #10
0
파일: ps.c 프로젝트: mstorsjo/vlc
static bool FindLength( demux_t *p_demux )
{
    demux_sys_t *p_sys = p_demux->p_sys;
    int64_t i_current_pos = -1, i_size = 0, i_end = 0;

    if( !var_CreateGetBool( p_demux, "ps-trust-timestamps" ) )
        return true;

    if( p_sys->i_length == VLC_TICK_INVALID ) /* First time */
    {
        p_sys->i_length = VLC_TICK_0;
        /* Check beginning */
        int i = 0;
        i_current_pos = vlc_stream_Tell( p_demux->s );
        while( i < 40 && Probe( p_demux, false ) > 0 ) i++;

        /* Check end */
        i_size = stream_Size( p_demux->s );
        i_end = VLC_CLIP( i_size, 0, 200000 );
        if( vlc_stream_Seek( p_demux->s, i_size - i_end ) == VLC_SUCCESS )
        {
            i = 0;
            while( i < 400 && Probe( p_demux, true ) > 0 ) i++;
            if( i_current_pos >= 0 &&
                vlc_stream_Seek( p_demux->s, i_current_pos ) != VLC_SUCCESS )
                    return false;
        }
        else return false;
    }

    /* Find the longest track */
    for( int i = 0; i < PS_TK_COUNT; i++ )
    {
        ps_track_t *tk = &p_sys->tk[i];
        if( tk->i_first_pts != VLC_TICK_INVALID &&
            tk->i_last_pts > tk->i_first_pts )
        {
            vlc_tick_t i_length = tk->i_last_pts - tk->i_first_pts;
            if( i_length > p_sys->i_length )
            {
                p_sys->i_length = i_length;
                p_sys->i_time_track_index = i;
                msg_Dbg( p_demux, "we found a length of: %"PRId64 "s", SEC_FROM_VLC_TICK(p_sys->i_length) );
            }
        }
    }
    return true;
}
예제 #11
0
파일: image.c 프로젝트: Flameeyes/vlc
static picture_t *ImageReadUrl( image_handler_t *p_image, const char *psz_url,
                                video_format_t *p_fmt_in,
                                video_format_t *p_fmt_out )
{
    block_t *p_block;
    picture_t *p_pic;
    stream_t *p_stream = NULL;
    int i_size;

    p_stream = stream_UrlNew( p_image->p_parent, psz_url );

    if( !p_stream )
    {
        msg_Dbg( p_image->p_parent, "could not open %s for reading",
                 psz_url );
        return NULL;
    }

    i_size = stream_Size( p_stream );

    p_block = block_New( p_image->p_parent, i_size );

    stream_Read( p_stream, p_block->p_buffer, i_size );

    if( !p_fmt_in->i_chroma )
    {
        char *psz_mime = NULL;
        stream_Control( p_stream, STREAM_GET_CONTENT_TYPE, &psz_mime );
        if( psz_mime )
            p_fmt_in->i_chroma = image_Mime2Fourcc( psz_mime );
        free( psz_mime );
    }
    stream_Delete( p_stream );

    if( !p_fmt_in->i_chroma )
    {
        /* Try to guess format from file name */
        p_fmt_in->i_chroma = image_Ext2Fourcc( psz_url );
    }

    p_pic = ImageRead( p_image, p_block, p_fmt_in, p_fmt_out );

    return p_pic;
}
예제 #12
0
파일: image.c 프로젝트: jomanmuk/vlc-2.2
static bool IsTarga(stream_t *s)
{
    /* The header is not enough to ensure proper detection, we need
     * to have a look at the footer. But doing so can be slow. So
     * try to avoid it when possible */
    const uint8_t *header;
    if (stream_Peek(s, &header, 18) < 18)   /* Targa fixed header */
        return false;
    if (header[1] > 1)                      /* Color Map Type */
        return false;
    if ((header[1] != 0 || header[3 + 4] != 0) &&
        header[3 + 4] != 8  &&
        header[3 + 4] != 15 && header[3 + 4] != 16 &&
        header[3 + 4] != 24 && header[3 + 4] != 32)
        return false;
    if ((header[2] > 3 && header[2] < 9) || header[2] > 11) /* Image Type */
        return false;
    if (GetWLE(&header[8 + 4]) <= 0 ||      /* Width */
        GetWLE(&header[8 + 6]) <= 0)        /* Height */
        return false;
    if (header[8 + 8] != 8  &&
        header[8 + 8] != 15 && header[8 + 8] != 16 &&
        header[8 + 8] != 24 && header[8 + 8] != 32)
        return false;
    if (header[8 + 9] & 0xc0)               /* Reserved bits */
        return false;

    const int64_t size = stream_Size(s);
    if (size <= 18 + 26)
        return false;
    bool can_seek;
    if (stream_Control(s, STREAM_CAN_SEEK, &can_seek) || !can_seek)
        return false;

    const int64_t position = stream_Tell(s);
    if (stream_Seek(s, size - 26))
        return false;

    const uint8_t *footer;
    bool is_targa = stream_Peek(s, &footer, 26) >= 26 &&
                    !memcmp(&footer[8], "TRUEVISION-XFILE.\x00", 18);
    stream_Seek(s, position);
    return is_targa;
}
예제 #13
0
파일: archive.c 프로젝트: mstorsjo/vlc
static la_int64_t libarchive_seek_cb( libarchive_t* p_arc, void* p_obj,
  la_int64_t offset, int whence )
{
    VLC_UNUSED( p_arc );

    libarchive_callback_t* p_cb = (libarchive_callback_t*)p_obj;
    stream_t* p_source = p_cb->p_source;

    ssize_t whence_pos;

    switch( whence )
    {
        case SEEK_SET: whence_pos = 0;                           break;
        case SEEK_CUR: whence_pos = vlc_stream_Tell( p_source ); break;
        case SEEK_END: whence_pos = stream_Size( p_source ); break;
              default: vlc_assert_unreachable();

    }

    if( whence_pos < 0 || vlc_stream_Seek( p_source, whence_pos + offset ) )
        return ARCHIVE_FATAL;

    return vlc_stream_Tell( p_source );
}
예제 #14
0
파일: mod.c 프로젝트: mstorsjo/vlc
/*****************************************************************************
 * Open
 *****************************************************************************/
static int Open( vlc_object_t *p_this )
{
    demux_t     *p_demux = (demux_t*)p_this;
    demux_sys_t *p_sys;
    ModPlug_Settings settings;

    /* We accept file based on extension match */
    if( !p_demux->obj.force )
    {
        const char *psz_ext = p_demux->psz_filepath ? strrchr( p_demux->psz_filepath, '.' )
                                                : NULL;
        if( psz_ext )
            psz_ext++;

        if( Validate( p_demux, psz_ext ) )
        {
            msg_Dbg( p_demux, "MOD validation failed (ext=%s)", psz_ext ? psz_ext : "");
            return VLC_EGENERIC;
        }
    }

    const int64_t i_size = stream_Size( p_demux->s );
    if( i_size <= 0 || i_size >= MOD_MAX_FILE_SIZE )
        return VLC_EGENERIC;

    p_sys = vlc_obj_malloc( p_this, sizeof (*p_sys) );
    if( !p_sys )
        return VLC_ENOMEM;

    msg_Dbg( p_demux, "loading complete file (could be long)" );
    p_sys->i_data = i_size;
    p_sys->p_data = vlc_obj_malloc( p_this, p_sys->i_data );
    if( unlikely(p_sys->p_data == NULL) )
        return VLC_ENOMEM;

    p_sys->i_data = vlc_stream_Read( p_demux->s, p_sys->p_data,
                                     p_sys->i_data );
    if( p_sys->i_data <= 0 )
    {
        msg_Err( p_demux, "failed to read the complete file" );
        return VLC_EGENERIC;
    }

    /* Configure modplug before loading the file */
    vlc_mutex_lock( &libmodplug_lock );
    ModPlug_GetSettings( &settings );
    settings.mFlags = MODPLUG_ENABLE_OVERSAMPLING;
    settings.mChannels = 2;
    settings.mBits = 16;
    settings.mFrequency = 44100;
    settings.mResamplingMode = MODPLUG_RESAMPLE_FIR;

    if( var_InheritBool( p_demux, "mod-noisereduction" ) )
        settings.mFlags |= MODPLUG_ENABLE_NOISE_REDUCTION;

    if( var_InheritBool( p_demux, "mod-reverb" ) )
        settings.mFlags |= MODPLUG_ENABLE_REVERB;
    settings.mReverbDepth = var_InheritInteger( p_demux, "mod-reverb-level" );
    settings.mReverbDelay = var_InheritInteger( p_demux, "mod-reverb-delay" );

    if( var_InheritBool( p_demux, "mod-megabass" ) )
        settings.mFlags |= MODPLUG_ENABLE_MEGABASS;
    settings.mBassAmount = var_InheritInteger( p_demux, "mod-megabass-level" );
    settings.mBassRange = var_InheritInteger( p_demux, "mod-megabass-range" );

    if( var_InheritBool( p_demux, "mod-surround" ) )
        settings.mFlags |= MODPLUG_ENABLE_SURROUND;
    settings.mSurroundDepth = var_InheritInteger( p_demux, "mod-surround-level" );
    settings.mSurroundDelay = var_InheritInteger( p_demux, "mod-surround-delay" );

    ModPlug_SetSettings( &settings );

    p_sys->f = ModPlug_Load( p_sys->p_data, p_sys->i_data );
    vlc_mutex_unlock( &libmodplug_lock );

    if( !p_sys->f )
    {
        msg_Err( p_demux, "failed to understand the file" );
        return VLC_EGENERIC;
    }

    /* init time */
    date_Init( &p_sys->pts, settings.mFrequency, 1 );
    date_Set( &p_sys->pts, VLC_TICK_0 );
    p_sys->i_length = VLC_TICK_FROM_MS( ModPlug_GetLength( p_sys->f ) );

    msg_Dbg( p_demux, "MOD loaded name=%s length=%"PRId64"ms",
             ModPlug_GetName( p_sys->f ),
             MS_FROM_VLC_TICK( p_sys->i_length ) );

#ifdef WORDS_BIGENDIAN
    es_format_Init( &p_sys->fmt, AUDIO_ES, VLC_FOURCC( 't', 'w', 'o', 's' ) );
#else
    es_format_Init( &p_sys->fmt, AUDIO_ES, VLC_FOURCC( 'a', 'r', 'a', 'w' ) );
#endif
    p_sys->fmt.audio.i_rate = settings.mFrequency;
    p_sys->fmt.audio.i_channels = settings.mChannels;
    p_sys->fmt.audio.i_bitspersample = settings.mBits;
    p_sys->es = es_out_Add( p_demux->out, &p_sys->fmt );
    if( unlikely(p_sys->es == NULL) )
        return VLC_ENOMEM;

    /* Fill p_demux field */
    p_demux->pf_demux = Demux;
    p_demux->pf_control = Control;
    p_demux->p_sys = p_sys;
    return VLC_SUCCESS;
}
예제 #15
0
파일: sid.cpp 프로젝트: chouquette/vlc
static int Open (vlc_object_t *obj)
{
    demux_t *demux = (demux_t *)obj;
    demux_sys_t *sys = NULL;
    es_format_t fmt;
    bool result = false;
    SidTune *tune = NULL;
    sidplay2 *player = NULL;
    ReSIDBuilder *builder = NULL;

    int64_t size = stream_Size (demux->s);
    if (size < 4 || size > LONG_MAX) /* We need to load the whole file for sidplay */
        return VLC_EGENERIC;

    const uint8_t *peek;
    if (vlc_stream_Peek (demux->s, &peek, 4) < 4)
        return VLC_EGENERIC;

    /* sidplay2 can read PSID and the newer RSID formats */
    if(memcmp(peek,"PSID",4)!=0 && memcmp(peek,"RSID",4)!=0)
        return VLC_EGENERIC;

    uint8_t *data = (uint8_t*) malloc(size);
    if (unlikely (data==NULL))
        goto error;

    if (vlc_stream_Read (demux->s,data,size) < size) {
        free (data);
        goto error;
    }

    tune = new (std::nothrow) SidTune(0);
    if (unlikely (tune==NULL)) {
        free (data);
        goto error;
    }

    result = tune->read (data, size);
    free (data);
    if (!result)
        goto error;

    player = new (std::nothrow) sidplay2();
    if (unlikely(player==NULL))
        goto error;

    sys = (demux_sys_t*) calloc (1, sizeof(demux_sys_t));
    if (unlikely(sys==NULL))
        goto error;

    sys->player = player;
    sys->tune = tune;

    tune->getInfo (sys->tuneInfo);

    sys->info = player->info();
    sys->config = player->config();

    builder = new (std::nothrow) ReSIDBuilder ("ReSID");
    if (unlikely(builder==NULL))
        goto error;

    builder->create (sys->info.maxsids);
    builder->sampling (sys->config.frequency);

    sys->config.sidEmulation = builder;
    sys->config.precision    = 16;
    sys->config.playback     = (sys->info.channels == 2 ? sid2_stereo : sid2_mono);

    player->config (sys->config);

    sys->bytes_per_frame = sys->info.channels * sys->config.precision / 8;
    sys->block_size = sys->config.frequency / 10 * sys->bytes_per_frame;

    es_format_Init (&fmt, AUDIO_ES, VLC_CODEC_S16N);

    fmt.audio.i_channels        = sys->info.channels;
    fmt.audio.i_bitspersample   = sys->config.precision;
    fmt.audio.i_rate            = sys->config.frequency;
    fmt.audio.i_bytes_per_frame = sys->bytes_per_frame;
    fmt.audio.i_frame_length    = fmt.audio.i_bytes_per_frame;
    fmt.audio.i_blockalign      = fmt.audio.i_bytes_per_frame;

    fmt.i_bitrate = fmt.audio.i_rate * fmt.audio.i_bytes_per_frame;

    sys->es = es_out_Add (demux->out, &fmt);

    date_Init (&sys->pts, fmt.audio.i_rate, 1);
    date_Set (&sys->pts, 0);

    sys->tune->selectSong (0);
    result = (sys->player->load (sys->tune) >=0 );
    sys->player->fastForward (100);
    if (!result)
        goto error;

    /* Callbacks */
    demux->pf_demux = Demux;
    demux->pf_control = Control;
    demux->p_sys = sys;

    return VLC_SUCCESS;

error:
    msg_Err (demux, "An error occurred during sid demuxing" );
    delete player;
    delete builder;
    delete tune;
    free (sys);
    return VLC_EGENERIC;
}
예제 #16
0
파일: demux.c 프로젝트: mstorsjo/vlc
/*****************************************************************************
 * Control:
 *****************************************************************************/
static int Control( demux_t *p_demux, int i_query, va_list args )
{
    demux_sys_t *p_sys = p_demux->p_sys;
    const int64_t i_start_time = p_sys->ic->start_time != AV_NOPTS_VALUE ? p_sys->ic->start_time : 0;
    double f, *pf;
    int64_t i64;

    switch( i_query )
    {
        case DEMUX_CAN_SEEK:
            *va_arg( args, bool * ) = true;
            return VLC_SUCCESS;

        case DEMUX_GET_POSITION:
            pf = va_arg( args, double * ); *pf = 0.0;
            i64 = stream_Size( p_demux->s );
            if( i64 > 0 )
            {
                double current = vlc_stream_Tell( p_demux->s );
                *pf = current / (double)i64;
            }

            if( (p_sys->ic->duration != (int64_t)AV_NOPTS_VALUE) && (p_sys->i_pcr > 0) )
            {
                *pf = (double)p_sys->i_pcr / (double)p_sys->ic->duration;
            }

            return VLC_SUCCESS;

        case DEMUX_SET_POSITION:
        {
            f = va_arg( args, double );
            bool precise = va_arg( args, int );
            i64 = p_sys->ic->duration * f + i_start_time;

            msg_Warn( p_demux, "DEMUX_SET_POSITION: %"PRId64, i64 );

            /* If we have a duration, we prefer to seek by time
               but if we don't, or if the seek fails, try BYTE seeking */
            if( p_sys->ic->duration == (int64_t)AV_NOPTS_VALUE ||
                (av_seek_frame( p_sys->ic, -1, i64, AVSEEK_FLAG_BACKWARD ) < 0) )
            {
                int64_t i_size = stream_Size( p_demux->s );
                i64 = (i_size * f);

                msg_Warn( p_demux, "DEMUX_SET_BYTE_POSITION: %"PRId64, i64 );
                if( av_seek_frame( p_sys->ic, -1, i64, AVSEEK_FLAG_BYTE ) < 0 )
                    return VLC_EGENERIC;

                ResetTime( p_demux, -1 );
            }
            else
            {
                if( precise )
                    ResetTime( p_demux, i64 - i_start_time );
                else
                    ResetTime( p_demux, -1 );
            }
            return VLC_SUCCESS;
        }

        case DEMUX_GET_LENGTH:
            if( p_sys->ic->duration != (int64_t)AV_NOPTS_VALUE )
                *va_arg( args, vlc_tick_t * ) = FROM_AV_TS(p_sys->ic->duration);
            else
                *va_arg( args, vlc_tick_t * ) = 0;
            return VLC_SUCCESS;

        case DEMUX_GET_TIME:
            *va_arg( args, vlc_tick_t * ) = p_sys->i_pcr;
            return VLC_SUCCESS;

        case DEMUX_SET_TIME:
        {
            i64 = TO_AV_TS(va_arg( args, vlc_tick_t ));
            bool precise = va_arg( args, int );

            msg_Warn( p_demux, "DEMUX_SET_TIME: %"PRId64, i64 );

            if( av_seek_frame( p_sys->ic, -1, i64 + i_start_time, AVSEEK_FLAG_BACKWARD ) < 0 )
            {
                return VLC_EGENERIC;
            }
            if( precise )
                ResetTime( p_demux, i64 - i_start_time );
            else
                ResetTime( p_demux, -1 );
            return VLC_SUCCESS;
        }

        case DEMUX_HAS_UNSUPPORTED_META:
        {
            bool *pb_bool = va_arg( args, bool* );
            *pb_bool = true;
            return VLC_SUCCESS;
        }


        case DEMUX_GET_META:
        {
            static const char names[][10] = {
                [vlc_meta_Title] = "title",
                [vlc_meta_Artist] = "artist",
                [vlc_meta_Genre] = "genre",
                [vlc_meta_Copyright] = "copyright",
                [vlc_meta_Album] = "album",
                //[vlc_meta_TrackNumber] -- TODO: parse number/total value
                [vlc_meta_Description] = "comment",
                //[vlc_meta_Rating]
                [vlc_meta_Date] = "date",
                [vlc_meta_Setting] = "encoder",
                //[vlc_meta_URL]
                [vlc_meta_Language] = "language",
                //[vlc_meta_NowPlaying]
                [vlc_meta_Publisher] = "publisher",
                [vlc_meta_EncodedBy] = "encoded_by",
                //[vlc_meta_ArtworkURL]
                //[vlc_meta_TrackID]
                //[vlc_meta_TrackTotal]
            };
            vlc_meta_t *p_meta = va_arg( args, vlc_meta_t * );
            AVDictionary *dict = p_sys->ic->metadata;

            for( unsigned i = 0; i < sizeof(names) / sizeof(*names); i++)
            {
                if( !names[i][0] )
                    continue;

                AVDictionaryEntry *e = av_dict_get( dict, names[i], NULL, 0 );
                if( e != NULL && e->value != NULL && IsUTF8(e->value) )
                    vlc_meta_Set( p_meta, i, e->value );
            }
            return VLC_SUCCESS;
        }

        case DEMUX_GET_ATTACHMENTS:
        {
            input_attachment_t ***ppp_attach =
                va_arg( args, input_attachment_t*** );
            int *pi_int = va_arg( args, int * );
            int i;

            if( p_sys->i_attachments <= 0 )
                return VLC_EGENERIC;

            *ppp_attach = vlc_alloc( p_sys->i_attachments, sizeof(input_attachment_t*) );
            if( *ppp_attach == NULL )
                return VLC_EGENERIC;

            for( i = 0; i < p_sys->i_attachments; i++ )
            {
                (*ppp_attach)[i] = vlc_input_attachment_Duplicate( p_sys->attachments[i] );
                if((*ppp_attach)[i] == NULL)
                    break;
            }
            *pi_int = i;
            return VLC_SUCCESS;
        }

        case DEMUX_GET_TITLE_INFO:
        {
            input_title_t ***ppp_title = va_arg( args, input_title_t *** );
            int *pi_int = va_arg( args, int * );
            int *pi_title_offset = va_arg( args, int * );
            int *pi_seekpoint_offset = va_arg( args, int * );

            if( !p_sys->p_title )
                return VLC_EGENERIC;

            *ppp_title = malloc( sizeof( input_title_t*) );
            if( *ppp_title == NULL )
                return VLC_EGENERIC;
            (*ppp_title)[0] = vlc_input_title_Duplicate( p_sys->p_title );
            *pi_int = (*ppp_title)[0] ? 1 : 0;
            *pi_title_offset = 0;
            *pi_seekpoint_offset = 0;
            return VLC_SUCCESS;
        }
        case DEMUX_SET_TITLE:
        {
            const int i_title = va_arg( args, int );
            if( !p_sys->p_title || i_title != 0 )
                return VLC_EGENERIC;
            return VLC_SUCCESS;
        }
        case DEMUX_SET_SEEKPOINT:
        {
            const int i_seekpoint = va_arg( args, int );
            if( !p_sys->p_title )
                return VLC_EGENERIC;

            i64 = TO_AV_TS(p_sys->p_title->seekpoint[i_seekpoint]->i_time_offset) +
                  i_start_time;

            msg_Warn( p_demux, "DEMUX_SET_SEEKPOINT: %"PRId64, i64 );

            if( av_seek_frame( p_sys->ic, -1, i64, AVSEEK_FLAG_BACKWARD ) < 0 )
            {
                return VLC_EGENERIC;
            }
            ResetTime( p_demux, i64 - i_start_time );
            return VLC_SUCCESS;
        }
        case DEMUX_TEST_AND_CLEAR_FLAGS:
        {
            unsigned *restrict flags = va_arg(args, unsigned *);
            *flags &= p_sys->i_update;
            p_sys->i_update &= ~*flags;
            return VLC_SUCCESS;
        }
        case DEMUX_GET_TITLE:
            if( p_sys->p_title == NULL )
                return VLC_EGENERIC;
            *va_arg( args, int * ) = 0;
            return VLC_SUCCESS;
        case DEMUX_GET_SEEKPOINT:
            if( p_sys->p_title == NULL )
                return VLC_EGENERIC;
            *va_arg( args, int * ) = p_sys->i_seekpoint;
            return VLC_SUCCESS;
        case DEMUX_CAN_PAUSE:
        case DEMUX_SET_PAUSE_STATE:
        case DEMUX_CAN_CONTROL_PACE:
        case DEMUX_GET_PTS_DELAY:
            return demux_vaControlHelper( p_demux->s, 0, -1, 0, 1, i_query, args );
        default:
            return VLC_EGENERIC;
    }
}
예제 #17
0
/**
 * Get the update file and parse it
 * p_update has to be locked when calling this function
 *
 * \param p_update pointer to update struct
 * \return true if the update is valid and authenticated
 */
static bool GetUpdateFile( update_t *p_update )
{
    stream_t *p_stream = NULL;
    int i_major = 0;
    int i_minor = 0;
    int i_revision = 0;
    unsigned char extra;
    char *psz_version_line = NULL;
    char *psz_update_data = NULL;

    p_stream = stream_UrlNew( p_update->p_libvlc, UPDATE_VLC_STATUS_URL );
    if( !p_stream )
    {
        msg_Err( p_update->p_libvlc, "Failed to open %s for reading",
                 UPDATE_VLC_STATUS_URL );
        goto error;
    }

    const int64_t i_read = stream_Size( p_stream );
    psz_update_data = malloc( i_read + 1 ); /* terminating '\0' */
    if( !psz_update_data )
        goto error;

    if( stream_Read( p_stream, psz_update_data, i_read ) != i_read )
    {
        msg_Err( p_update->p_libvlc, "Couldn't download update file %s",
                UPDATE_VLC_STATUS_URL );
        goto error;
    }
    psz_update_data[i_read] = '\0';

    stream_Delete( p_stream );
    p_stream = NULL;

    /* first line : version number */
    char *psz_update_data_parser = psz_update_data;
    size_t i_len = strcspn( psz_update_data, "\r\n" );
    psz_update_data_parser += i_len;
    while( *psz_update_data_parser == '\r' || *psz_update_data_parser == '\n' )
        psz_update_data_parser++;

    if( !(psz_version_line = malloc( i_len + 1)) )
        goto error;
    strncpy( psz_version_line, psz_update_data, i_len );
    psz_version_line[i_len] = '\0';

    p_update->release.extra = 0;
    switch( sscanf( psz_version_line, "%i.%i.%i%c",
                    &i_major, &i_minor, &i_revision, &extra ) )
    {
        case 4:
            p_update->release.extra = extra;
        case 3:
            p_update->release.i_major = i_major;
            p_update->release.i_minor = i_minor;
            p_update->release.i_revision = i_revision;
            break;
        default:
            msg_Err( p_update->p_libvlc, "Update version false formated" );
            goto error;
    }

    /* second line : URL */
    i_len = strcspn( psz_update_data_parser, "\r\n" );
    if( i_len == 0 )
    {
        msg_Err( p_update->p_libvlc, "Update file %s is corrupted: URL missing",
                 UPDATE_VLC_STATUS_URL );

        goto error;
    }

    if( !(p_update->release.psz_url = malloc( i_len + 1)) )
        goto error;
    strncpy( p_update->release.psz_url, psz_update_data_parser, i_len );
    p_update->release.psz_url[i_len] = '\0';

    psz_update_data_parser += i_len;
    while( *psz_update_data_parser == '\r' || *psz_update_data_parser == '\n' )
        psz_update_data_parser++;

    /* Remaining data : description */
    i_len = strlen( psz_update_data_parser );
    if( i_len == 0 )
    {
        msg_Err( p_update->p_libvlc,
                "Update file %s is corrupted: description missing",
                UPDATE_VLC_STATUS_URL );
        goto error;
    }

    if( !(p_update->release.psz_desc = malloc( i_len + 1)) )
        goto error;
    strncpy( p_update->release.psz_desc, psz_update_data_parser, i_len );
    p_update->release.psz_desc[i_len] = '\0';

    /* Now that we know the status is valid, we must download its signature
     * to authenticate it */
    signature_packet_t sign;
    if( download_signature( VLC_OBJECT( p_update->p_libvlc ), &sign,
            UPDATE_VLC_STATUS_URL ) != VLC_SUCCESS )
    {
        msg_Err( p_update->p_libvlc, "Couldn't download signature of status file" );
        goto error;
    }

    if( sign.type != BINARY_SIGNATURE && sign.type != TEXT_SIGNATURE )
    {
        msg_Err( p_update->p_libvlc, "Invalid signature type" );
        goto error;
    }

    p_update->p_pkey = (public_key_t*)malloc( sizeof( public_key_t ) );
    if( !p_update->p_pkey )
        goto error;

    if( parse_public_key( videolan_public_key, sizeof( videolan_public_key ),
                        p_update->p_pkey, NULL ) != VLC_SUCCESS )
    {
        msg_Err( p_update->p_libvlc, "Couldn't parse embedded public key, something went really wrong..." );
        FREENULL( p_update->p_pkey );
        goto error;
    }

    memcpy( p_update->p_pkey->longid, videolan_public_key_longid, 8 );

    if( memcmp( sign.issuer_longid, p_update->p_pkey->longid , 8 ) != 0 )
    {
        msg_Dbg( p_update->p_libvlc, "Need to download the GPG key" );
        public_key_t *p_new_pkey = download_key(
                VLC_OBJECT(p_update->p_libvlc),
                sign.issuer_longid, videolan_public_key_longid );
        if( !p_new_pkey )
        {
            msg_Err( p_update->p_libvlc, "Couldn't download GPG key" );
            FREENULL( p_update->p_pkey );
            goto error;
        }

        uint8_t *p_hash = hash_sha1_from_public_key( p_new_pkey );
        if( !p_hash )
        {
            msg_Err( p_update->p_libvlc, "Failed to hash signature" );
            free( p_new_pkey );
            FREENULL( p_update->p_pkey );
            goto error;
        }

        if( verify_signature( p_new_pkey->sig.r, p_new_pkey->sig.s,
                    &p_update->p_pkey->key, p_hash ) == VLC_SUCCESS )
        {
            free( p_hash );
            msg_Info( p_update->p_libvlc, "Key authenticated" );
            free( p_update->p_pkey );
            p_update->p_pkey = p_new_pkey;
        }
        else
        {
            free( p_hash );
            msg_Err( p_update->p_libvlc, "Key signature invalid !\n" );
            goto error;
        }
    }

    uint8_t *p_hash = hash_sha1_from_text( psz_update_data, &sign );
    if( !p_hash )
    {
        msg_Warn( p_update->p_libvlc, "Can't compute SHA1 hash for status file" );
        goto error;
    }

    else if( p_hash[0] != sign.hash_verification[0] ||
        p_hash[1] != sign.hash_verification[1] )
    {
        msg_Warn( p_update->p_libvlc, "Bad SHA1 hash for status file" );
        goto error;
    }

    else if( verify_signature( sign.r, sign.s, &p_update->p_pkey->key, p_hash )
            != VLC_SUCCESS )
    {
        msg_Err( p_update->p_libvlc, "BAD SIGNATURE for status file" );
        goto error;
    }

    else
    {
        msg_Info( p_update->p_libvlc, "Status file authenticated" );
        return true;
    }

error:
    if( p_stream )
        stream_Delete( p_stream );
    free( psz_version_line );
    free( psz_update_data );
    return false;
}
예제 #18
0
파일: ps.c 프로젝트: mstorsjo/vlc
/*****************************************************************************
 * Control:
 *****************************************************************************/
static int Control( demux_t *p_demux, int i_query, va_list args )
{
    demux_sys_t *p_sys = p_demux->p_sys;
    double f, *pf;
    int64_t i64;
    int i_ret;

    switch( i_query )
    {
        case DEMUX_CAN_SEEK:
            *va_arg( args, bool * ) = p_sys->b_seekable;
            return VLC_SUCCESS;

        case DEMUX_GET_TITLE:
            *va_arg( args, int * ) = p_sys->current_title;
            return VLC_SUCCESS;

        case DEMUX_GET_SEEKPOINT:
            *va_arg( args, int * ) = p_sys->current_seekpoint;
            return VLC_SUCCESS;

        case DEMUX_GET_POSITION:
            pf = va_arg( args, double * );
            i64 = stream_Size( p_demux->s ) - p_sys->i_start_byte;
            if( i64 > 0 )
            {
                double current = vlc_stream_Tell( p_demux->s ) - p_sys->i_start_byte;
                *pf = current / (double)i64;
            }
            else
            {
                *pf = 0.0;
            }
            return VLC_SUCCESS;

        case DEMUX_SET_POSITION:
            f = va_arg( args, double );
            i64 = stream_Size( p_demux->s ) - p_sys->i_start_byte;
            p_sys->i_current_pts = VLC_TICK_INVALID;
            p_sys->i_scr = VLC_TICK_INVALID;

            if( p_sys->format == CDXA_PS )
            {
                i64 = (int64_t)(i64  * f); /* Align to sector payload */
                i64 = p_sys->i_start_byte + i64 - (i64 % CDXA_SECTOR_SIZE) + CDXA_SECTOR_HEADER_SIZE;
            }
            else
            {
                i64 = p_sys->i_start_byte + (int64_t)(i64 * f);
            }

            i_ret = vlc_stream_Seek( p_demux->s, i64 );
            if( i_ret == VLC_SUCCESS )
            {
                NotifyDiscontinuity( p_sys->tk, p_demux->out );
                return i_ret;
            }
            break;

        case DEMUX_GET_TIME:
            if( p_sys->i_time_track_index >= 0 && p_sys->i_current_pts != VLC_TICK_INVALID )
            {
                *va_arg( args, vlc_tick_t * ) = p_sys->i_current_pts - p_sys->tk[p_sys->i_time_track_index].i_first_pts;
                return VLC_SUCCESS;
            }
            if( p_sys->i_first_scr != VLC_TICK_INVALID && p_sys->i_scr != VLC_TICK_INVALID )
            {
                vlc_tick_t i_time = p_sys->i_scr - p_sys->i_first_scr;
                /* H.222 2.5.2.2 */
                if( p_sys->i_mux_rate > 0 && p_sys->b_have_pack )
                {
                    uint64_t i_offset = vlc_stream_Tell( p_demux->s ) - p_sys->i_lastpack_byte;
                    i_time += vlc_tick_from_samples(i_offset, p_sys->i_mux_rate * 50);
                }
                *va_arg( args, vlc_tick_t * ) = i_time;
                return VLC_SUCCESS;
            }
            *va_arg( args, vlc_tick_t * ) = 0;
            break;

        case DEMUX_GET_LENGTH:
            if( p_sys->i_length > VLC_TICK_0 )
            {
                *va_arg( args, vlc_tick_t * ) = p_sys->i_length;
                return VLC_SUCCESS;
            }
            else if( p_sys->i_mux_rate > 0 )
            {
                *va_arg( args, vlc_tick_t * ) = vlc_tick_from_samples( stream_Size( p_demux->s ) - p_sys->i_start_byte / 50,
                    p_sys->i_mux_rate );
                return VLC_SUCCESS;
            }
            *va_arg( args, vlc_tick_t * ) = 0;
            break;

        case DEMUX_SET_TIME:
        {
            if( p_sys->i_time_track_index >= 0 && p_sys->i_current_pts != VLC_TICK_INVALID &&
                p_sys->i_length > VLC_TICK_0)
            {
                vlc_tick_t i_time = va_arg( args, vlc_tick_t );
                i_time -= p_sys->tk[p_sys->i_time_track_index].i_first_pts;
                return demux_Control( p_demux, DEMUX_SET_POSITION, (double) i_time / p_sys->i_length );
            }
            break;
        }

        case DEMUX_GET_TITLE_INFO:
        {
            struct input_title_t ***v = va_arg( args, struct input_title_t*** );
            int *c = va_arg( args, int * );

            *va_arg( args, int* ) = 0; /* Title offset */
            *va_arg( args, int* ) = 0; /* Chapter offset */
            return vlc_stream_Control( p_demux->s, STREAM_GET_TITLE_INFO, v,
                                       c );
        }

        case DEMUX_SET_TITLE:
            return vlc_stream_vaControl( p_demux->s, STREAM_SET_TITLE, args );

        case DEMUX_SET_SEEKPOINT:
            return vlc_stream_vaControl( p_demux->s, STREAM_SET_SEEKPOINT,
                                         args );

        case DEMUX_TEST_AND_CLEAR_FLAGS:
        {
            unsigned *restrict flags = va_arg(args, unsigned *);
            *flags &= p_sys->updates;
            p_sys->updates &= ~*flags;
            return VLC_SUCCESS;
        }

        case DEMUX_GET_META:
            return vlc_stream_vaControl( p_demux->s, STREAM_GET_META, args );

        case DEMUX_GET_FPS:
            break;

        case DEMUX_CAN_PAUSE:
        case DEMUX_SET_PAUSE_STATE:
        case DEMUX_CAN_CONTROL_PACE:
        case DEMUX_GET_PTS_DELAY:
            return demux_vaControlHelper( p_demux->s, 0, -1, 0, 1, i_query, args );

        default:
            break;

    }
    return VLC_EGENERIC;
}
예제 #19
0
파일: aribcam.c 프로젝트: mstorsjo/vlc
static int Open( vlc_object_t *p_object )
{
    stream_t *p_stream = (stream_t *) p_object;

    int64_t i_stream_size = stream_Size( p_stream->s );
    if ( i_stream_size > 0 && i_stream_size < ARIB_STD_B25_TS_PROBING_MIN_DATA )
        return VLC_EGENERIC;

    stream_sys_t *p_sys = p_stream->p_sys = calloc( 1, sizeof(*p_sys) );
    if (p_sys == NULL)
        return VLC_ENOMEM;

    p_sys->p_b25 = create_arib_std_b25();
    if ( p_sys->p_b25 )
    {
        if ( p_sys->p_b25->set_multi2_round( p_sys->p_b25, 4 ) < 0 )
            msg_Warn( p_stream, "cannot set B25 round number" );

        if ( p_sys->p_b25->set_strip( p_sys->p_b25, 0 ) < 0 )
            msg_Warn( p_stream, "cannot set B25 strip option" );

        if ( p_sys->p_b25->set_emm_proc( p_sys->p_b25, 0 ) < 0 )
            msg_Warn( p_stream, "cannot set B25 emm_proc" );

        /* ARIB STD-B25 scrambled TS's packet size is always 188 bytes */
        if ( p_sys->p_b25->set_unit_size( p_sys->p_b25, 188 ) < 0)
            msg_Warn( p_stream, "cannot set B25 TS packet size" );

        p_sys->p_bcas = create_b_cas_card();
        if ( p_sys->p_bcas )
        {
            int i_code = p_sys->p_bcas->init( p_sys->p_bcas );
            if ( i_code < 0 )
            {
                /* Card could be just missing */
                msg_Warn( p_stream, "cannot initialize BCAS card (missing ?): %s",
                          GetErrorMessage( i_code, bcas_errors ) );
                goto error;
            }

            B_CAS_ID bcasid;
            if ( p_sys->p_bcas->get_id( p_sys->p_bcas, &bcasid ) == 0 )
            {
                for ( int32_t i=0; i<bcasid.count; i++)
                {
                    msg_Dbg( p_stream, "BCAS card id 0x%"PRId64" initialized",
                             bcasid.data[i] );
                }
            }

            B_CAS_INIT_STATUS bcas_status;
            if ( p_sys->p_bcas->get_init_status( p_sys->p_bcas, &bcas_status ) == 0 )
            {
                msg_Dbg( p_stream, "BCAS card system id 0x%"PRIx32,
                         bcas_status.ca_system_id );
            }

            i_code = p_sys->p_b25->set_b_cas_card( p_sys->p_b25, p_sys->p_bcas );
            if ( i_code < 0 )
            {
                msg_Err( p_stream, "cannot attach BCAS card to decoder: %s",
                         GetErrorMessage( i_code, bcas_errors ) );
                goto error;
            }
        }
        else
            msg_Err( p_stream, "cannot create BCAS card" );
    }
    else
    {
        msg_Err( p_stream, "cannot create B25 instance" );
        goto error;
    }

    p_stream->pf_read = Read;
    p_stream->pf_seek = Seek;
    p_stream->pf_control = Control;

    return VLC_SUCCESS;

error:
    Close( VLC_OBJECT(p_stream) );
    return VLC_EGENERIC;
}
예제 #20
0
파일: flac.c 프로젝트: chouquette/vlc
static int ControlSetTime( demux_t *p_demux, int64_t i_time )
{
    demux_sys_t *p_sys = p_demux->p_sys;
    bool b_seekable;
    int i;

    /* */
    vlc_stream_Control( p_demux->s, STREAM_CAN_SEEK, &b_seekable );
    if( !b_seekable )
        return VLC_EGENERIC;

    const mtime_t i_length = ControlGetLength( p_demux );
    if( i_length <= 0 )
        return VLC_EGENERIC;

    const uint64_t i_stream_size = stream_Size( p_demux->s );
    if( i_stream_size <= p_sys->i_data_pos )
        return VLC_EGENERIC;

    const double i_bytemicrorate = (double) i_length / (i_stream_size - p_sys->i_data_pos);
    if( i_bytemicrorate == 0 )
        return VLC_EGENERIC;

    uint64_t i_lower = p_sys->i_data_pos;
    uint64_t i_upper = i_stream_size;
    uint64_t i_start_pos;

    assert( p_sys->i_seekpoint > 0 );   /* ReadMeta ensure at least (0,0) */
    if( p_sys->i_seekpoint > 1 )
    {
        /* lookup base offset */
        for( i = p_sys->i_seekpoint-1; i >= 0; i-- )
        {
            if( p_sys->seekpoint[i]->i_time_offset <= i_time )
                break;
        }

        i_lower = p_sys->seekpoint[0]->i_byte_offset + p_sys->i_data_pos;
        if( i+1 < p_sys->i_seekpoint )
            i_upper = p_sys->seekpoint[i+1]->i_byte_offset + p_sys->i_data_pos;

        i_start_pos = i_lower;
    }
    else
    {
        i_start_pos = i_time / i_bytemicrorate;
    }

    if( VLC_SUCCESS != vlc_stream_Seek( p_demux->s, i_start_pos ) )
        return VLC_EGENERIC;

    int i_ret = RefineSeek( p_demux, i_time, i_bytemicrorate, i_lower, i_upper );
    if( i_ret == VLC_SUCCESS )
    {
        p_sys->i_next_block_flags |= BLOCK_FLAG_DISCONTINUITY;
        Reset( p_sys );
        es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME, i_time );
    }

    return i_ret;
}
예제 #21
0
파일: flac.c 프로젝트: RodrigoNieves/vlc
static int ControlSetTime( demux_t *p_demux, int64_t i_time )
{
    demux_sys_t *p_sys = p_demux->p_sys;
    int64_t i_delta_time;
    bool b_seekable;
    int i;

    /* */
    stream_Control( p_demux->s, STREAM_CAN_SEEK, &b_seekable );
    if( !b_seekable )
        return VLC_EGENERIC;

    /* */
    assert( p_sys->i_seekpoint > 0 );   /* ReadMeta ensure at least (0,0) */
    for( i = p_sys->i_seekpoint-1; i >= 0; i-- )
    {
        if( p_sys->seekpoint[i]->i_time_offset <= i_time )
            break;
    }
    i_delta_time = i_time - p_sys->seekpoint[i]->i_time_offset;

    /* XXX We do exact seek if it's not too far away(45s) */
    if( i_delta_time < 45*INT64_C(1000000) )
    {
        if( stream_Seek( p_demux->s, p_sys->seekpoint[i]->i_byte_offset+p_sys->i_data_pos ) )
            return VLC_EGENERIC;

        p_sys->i_time_offset = p_sys->seekpoint[i]->i_time_offset - p_sys->i_pts;
        p_sys->i_pts_start = p_sys->i_pts+i_delta_time;
        es_out_Control( p_demux->out, ES_OUT_SET_NEXT_DISPLAY_TIME, p_sys->i_pts_start + p_sys->i_time_offset );
    }
    else
    {
        int64_t i_delta_offset;
        int64_t i_next_time;
        int64_t i_next_offset;

        if( i+1 < p_sys->i_seekpoint )
        {
            i_next_time   = p_sys->seekpoint[i+1]->i_time_offset;
            i_next_offset = p_sys->seekpoint[i+1]->i_byte_offset;
        }
        else
        {
            i_next_time   = p_sys->i_length;
            i_next_offset = stream_Size(p_demux->s)-p_sys->i_data_pos;
        }

        i_delta_offset = 0;
        if( i_next_time-p_sys->seekpoint[i]->i_time_offset > 0 )
            i_delta_offset = (i_next_offset - p_sys->seekpoint[i]->i_byte_offset) * i_delta_time /
                             (i_next_time-p_sys->seekpoint[i]->i_time_offset);

        if( stream_Seek( p_demux->s, p_sys->seekpoint[i]->i_byte_offset+p_sys->i_data_pos + i_delta_offset ) )
            return VLC_EGENERIC;

        p_sys->i_pts_start = p_sys->i_pts;
        p_sys->i_time_offset = (p_sys->seekpoint[i]->i_time_offset+i_delta_time) - p_sys->i_pts;
    }
    return VLC_SUCCESS;
}
예제 #22
0
파일: zipstream.c 프로젝트: qdk0901/vlc
/** **************************************************************************
 * \brief tell size of stream
 * \param opaque should be the stream
 * \param stream stream created by ZipIO_Open
 * \return size of the file / stream
 * ATTENTION: this is not stream_Tell, but stream_Size !
 *****************************************************************************/
static long ZCALLBACK ZipIO_Tell( void *opaque, void *stream )
{
    (void) stream;
    stream_t *s = (stream_t*) opaque;
    return (long) stream_Size( s->p_source ); /* /!\ not stream_Tell /!\ */
}
예제 #23
0
파일: id3tag.c 프로젝트: FLYKingdom/vlc
/*****************************************************************************
 * CheckFooter: check for ID3/APE at the end of the file
 * CheckHeader: check for ID3/APE at the begining of the file
 *****************************************************************************/
static void CheckFooter( demux_meta_t *p_demux_meta )
{
    demux_t      *p_demux = (demux_t *)p_demux_meta->p_demux;
    const int64_t i_pos = stream_Size( p_demux->s );
    const size_t i_peek = 128+APE_TAG_HEADERSIZE;
    const uint8_t *p_peek;
    const uint8_t *p_peek_id3;
    int64_t i_id3v2_pos = -1;
    int64_t i_apevx_pos = -1;
    int i_id3v2_size;
    int i_apevx_size;
    size_t i_id3v1_size;

    if( i_pos < i_peek )
        return;
    if( stream_Seek( p_demux->s, i_pos - i_peek ) )
        return;

    if( stream_Peek( p_demux->s, &p_peek, i_peek ) < i_peek )
        return;
    p_peek_id3 = &p_peek[APE_TAG_HEADERSIZE];

    /* Check/Parse ID3v1 */
    i_id3v1_size = id3_tag_query( p_peek_id3, ID3_TAG_QUERYSIZE );
    if( i_id3v1_size == 128 )
    {
        msg_Dbg( p_demux, "found ID3v1 tag" );
        ParseID3Tag( p_demux_meta, p_peek_id3, i_id3v1_size );
    }

    /* Compute ID3v2 position */
    i_id3v2_size = -id3_tag_query( &p_peek_id3[128-ID3_TAG_QUERYSIZE], ID3_TAG_QUERYSIZE );
    if( i_id3v2_size > 0 )
        i_id3v2_pos = i_pos - i_id3v2_size;

    /* Compute APE2v2 position */
    i_apevx_size = GetAPEvXSize( &p_peek[128+0], APE_TAG_HEADERSIZE );
    if( i_apevx_size > 0 )
    {
        i_apevx_pos = i_pos - i_apevx_size;
    }
    else if( i_id3v1_size > 0 )
    {
        /* it can be before ID3v1 */
        i_apevx_size = GetAPEvXSize( p_peek, APE_TAG_HEADERSIZE );
        if( i_apevx_size > 0 )
            i_apevx_pos = i_pos - 128 - i_apevx_size;
    }

    if( i_id3v2_pos > 0 && i_apevx_pos > 0 )
    {
        msg_Warn( p_demux,
                  "Both ID3v2 and APEv1/2 at the end of file, ignoring APEv1/2" );
        i_apevx_pos = -1;
    }

    /* Parse ID3v2.4 */
    if( i_id3v2_pos > 0 )
    {
        if( !stream_Seek( p_demux->s, i_id3v2_pos ) &&
            stream_Peek( p_demux->s, &p_peek, i_id3v2_size ) == i_id3v2_size )
        {
            msg_Dbg( p_demux, "found ID3v2 tag at end of file" );
            ParseID3Tag( p_demux_meta, p_peek, i_id3v2_size );
        }
    }

    /* Parse APEv1/2 */
    if( i_apevx_pos > 0 )
    {
        if( !stream_Seek( p_demux->s, i_apevx_pos ) &&
            stream_Peek( p_demux->s, &p_peek, i_apevx_size ) == i_apevx_size )
        {
            msg_Dbg( p_demux, "found APEvx tag at end of file" );
            ParseAPEvXTag( p_demux_meta, p_peek, i_apevx_size );
        }
    }
}
예제 #24
0
파일: gme.c 프로젝트: 0xheart0/vlc
static int Open (vlc_object_t *obj)
{
    demux_t *demux = (demux_t *)obj;

    int64_t size = stream_Size (demux->s);
    if (size > LONG_MAX /* too big for GME */)
        return VLC_EGENERIC;

    /* Auto detection */
    const uint8_t *peek;
    if (stream_Peek (demux->s, &peek, 4) < 4)
        return VLC_EGENERIC;

    const char *type = gme_identify_header (peek);
    if (!*type)
        return VLC_EGENERIC;
    msg_Dbg (obj, "detected file type %s", type);

    block_t *data = NULL;
    if (size <= 0)
    {
        data = stream_Block (demux->s, 1 << 24);
        if (data == NULL)
            return VLC_EGENERIC;
    }

    /* Initialization */
    demux_sys_t *sys = malloc (sizeof (*sys));
    if (unlikely(sys == NULL))
        return VLC_ENOMEM;

    sys->emu = gme_new_emu (gme_identify_extension (type), RATE);
    if (sys->emu == NULL)
    {
        free (sys);
        return VLC_ENOMEM;
    }
    if (data)
    {
        gme_load_custom (sys->emu, ReaderBlock, data->i_buffer, data);
        block_Release(data);
    }
    else
    {
        gme_load_custom (sys->emu, ReaderStream, size, demux->s);
    }
    gme_start_track (sys->emu, sys->track_id = 0);

    es_format_t fmt;
    es_format_Init (&fmt, AUDIO_ES, VLC_CODEC_S16N);
    fmt.audio.i_rate = RATE;
    fmt.audio.i_bytes_per_frame = 4;
    fmt.audio.i_frame_length = 4;
    fmt.audio.i_channels = 2;
    fmt.audio.i_blockalign = 4;
    fmt.audio.i_bitspersample = 16;
    fmt.i_bitrate = RATE * 4;

    sys->es = es_out_Add (demux->out, &fmt);
    date_Init (&sys->pts, RATE, 1);
    date_Set (&sys->pts, 0);

    /* Titles */
    unsigned n = gme_track_count (sys->emu);
    sys->titlev = malloc (n * sizeof (*sys->titlev));
    if (unlikely(sys->titlev == NULL))
        n = 0;
    sys->titlec = n;
    for (unsigned i = 0; i < n; i++)
    {
         input_title_t *title = vlc_input_title_New ();
         sys->titlev[i] = title;
         if (unlikely(title == NULL))
             continue;

         gme_info_t *infos;
         if (gme_track_info (sys->emu, &infos, i))
             continue;
         msg_Dbg (obj, "track %u: %s %d ms", i, infos->song, infos->length);
         if (infos->length != -1)
             title->i_length = infos->length * INT64_C(1000);
         if (infos->song[0])
             title->psz_name = strdup (infos->song);
         gme_free_info (infos);
    }

    /* Callbacks */
    demux->pf_demux = Demux;
    demux->pf_control = Control;
    demux->p_sys = sys;
    return VLC_SUCCESS;
}