예제 #1
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);
}
예제 #2
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;
}
예제 #3
0
파일: access.c 프로젝트: Ackhuman/vlc
static int Seek(access_t *access, uint64_t position)
{
    access_sys_t *sys = access->p_sys;
    const rar_file_t *file = sys->file;

    if (position > file->real_size)
        position = file->real_size;

    /* Search the chunk */
    const rar_file_chunk_t *old_chunk = sys->chunk;
    for (int i = 0; i < file->chunk_count; i++) {
        sys->chunk = file->chunk[i];
        if (position < sys->chunk->cummulated_size + sys->chunk->size)
            break;
    }
    access->info.i_pos = position;
    access->info.b_eof = false;

    const uint64_t offset = sys->chunk->offset +
                            (position - sys->chunk->cummulated_size);

    if (strcmp(old_chunk->mrl, sys->chunk->mrl)) {
        if (sys->s)
            stream_Delete(sys->s);
        sys->s = stream_UrlNew(access, sys->chunk->mrl);
    }
    return sys->s ? stream_Seek(sys->s, offset) : VLC_EGENERIC;
}
예제 #4
0
파일: access.c 프로젝트: 9034725985/vlc
static ssize_t SkipCallback(struct archive *p_archive, void *p_object, ssize_t i_request)
{
    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_skipped = 0;

    /* be smart as small seeks converts to reads */
    if (p_sys->b_source_canseek)
    {
        int64_t i_pos = stream_Tell(p_sys->p_stream);
        if (i_pos >=0)
            stream_Seek(p_sys->p_stream, i_pos + i_request);
        i_skipped = stream_Tell(p_sys->p_stream) - i_pos;
    }
    else while(i_request)
    {
        int i_skip = __MIN(INT32_MAX, i_request);
        int i_read = stream_Read(p_sys->p_stream, NULL, i_skip);
        if (i_read > 0)
            i_skipped += i_read;
        else
            break;
        i_request -= i_read;
    }

    return i_skipped;
}
예제 #5
0
static int Seek( stream_t *p_stream, uint64_t i_pos )
{
    int i_ret = stream_Seek( p_stream->p_source, i_pos );
    if ( i_ret == VLC_SUCCESS )
        RemainFlush( p_stream->p_sys );
    return i_ret;
}
예제 #6
0
파일: id3tag.c 프로젝트: FLYKingdom/vlc
/*****************************************************************************
 * ParseTags: check if ID3/APE tags at common locations.
 ****************************************************************************/
static int ParseTags( vlc_object_t *p_this )
{
    demux_meta_t *p_demux_meta = (demux_meta_t *)p_this;
    demux_t      *p_demux = (demux_t *)p_demux_meta->p_demux;
    bool    b_seekable;
    int64_t       i_init;

    msg_Dbg( p_demux_meta, "checking for ID3v1/2 and APEv1/2 tags" );
    stream_Control( p_demux->s, STREAM_CAN_FASTSEEK, &b_seekable );
    if( !b_seekable )
        return VLC_EGENERIC;

    i_init = stream_Tell( p_demux->s );

    TAB_INIT( p_demux_meta->i_attachments, p_demux_meta->attachments );
    p_demux_meta->p_meta = NULL;

    /* */
    CheckFooter( p_demux_meta );

    /* */
    CheckHeader( p_demux_meta );

    /* Restore position
     *  Demuxer will not see tags at the start as src/input/demux.c skips it
     *  for them
     */
    stream_Seek( p_demux->s, i_init );
    if( !p_demux_meta->p_meta && p_demux_meta->i_attachments <= 0 )
        return VLC_EGENERIC;
    return VLC_SUCCESS;
}
예제 #7
0
파일: id3tag.c 프로젝트: FLYKingdom/vlc
static void CheckHeader( demux_meta_t *p_demux_meta )
{
    const uint8_t *p_peek;
    int i_size;

    demux_t      *p_demux = (demux_t *)p_demux_meta->p_demux;

    if( stream_Seek( p_demux->s, 0 ) )
        return;

    /* Test ID3v2 first */
    if( stream_Peek( p_demux->s, &p_peek, ID3_TAG_QUERYSIZE ) != ID3_TAG_QUERYSIZE )
        return;
    i_size = id3_tag_query( p_peek, ID3_TAG_QUERYSIZE );
    if( i_size > 0 &&
        stream_Peek( p_demux->s, &p_peek, i_size ) == i_size )
    {
        msg_Dbg( p_demux, "found ID3v2 tag" );
        ParseID3Tag( p_demux_meta, p_peek, i_size );
        return;
    }

    /* Test APEv1 */
    if( stream_Peek( p_demux->s, &p_peek, APE_TAG_HEADERSIZE ) != APE_TAG_HEADERSIZE )
        return;
    i_size = GetAPEvXSize( p_peek, APE_TAG_HEADERSIZE );
    if( i_size > 0 &&
        stream_Peek( p_demux->s, &p_peek, i_size ) == i_size )
    {
        msg_Dbg( p_demux, "found APEv1/2 tag" );
        ParseAPEvXTag( p_demux_meta, p_peek, i_size );
    }
}
예제 #8
0
static int AVI_NextChunk( stream_t *s, avi_chunk_t *p_chk )
{
    avi_chunk_t chk;

    if( !p_chk )
    {
        if( AVI_ChunkReadCommon( s, &chk ) )
        {
            return VLC_EGENERIC;
        }
        p_chk = &chk;
    }

    if( p_chk->common.p_father )
    {
        if( p_chk->common.p_father->common.i_chunk_pos +
                __EVEN( p_chk->common.p_father->common.i_chunk_size ) + 8 <
            p_chk->common.i_chunk_pos +
                __EVEN( p_chk->common.i_chunk_size ) + 8 )
        {
            return VLC_EGENERIC;
        }
    }
    return stream_Seek( s, p_chk->common.i_chunk_pos +
                                 __EVEN( p_chk->common.i_chunk_size ) + 8 );
}
예제 #9
0
static int SeekSet0 (demux_t *demux)
{
    stream_t *stream = demux->s;
    demux_sys_t *sys = demux->p_sys;

    /* Default SMF tempo is 120BPM, i.e. half a second per quarter note */
    date_Init (&sys->pts, sys->ppqn * 2, 1);
    date_Set (&sys->pts, VLC_TS_0);
    sys->pulse = 0;
    sys->tick = VLC_TS_0;

    for (unsigned i = 0; i < sys->trackc; i++)
    {
        mtrk_t *tr = sys->trackv + i;

        tr->offset = 0;
        tr->next = 0;
        /* Why 0xF6 (Tuning Calibration)?
         * Because it has zero bytes of data, so the parser will detect the
         * error if the first event uses running status. */
        tr->running_event = 0xF6;

        if (stream_Seek (stream, tr->start)
         || ReadDeltaTime (stream, tr))
        {
            msg_Err (demux, "fatal parsing error");
            return -1;
        }
    }

    return 0;
}
예제 #10
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;
}
예제 #11
0
파일: zipstream.c 프로젝트: qdk0901/vlc
/** **************************************************************************
 * \brief seek in the stream
 * \param opaque should be the stream
 * \param stream stream created by ZipIO_Open
 * \param offset positive offset to seek
 * \param origin current position in stream
 * \return ¿ VLC_SUCCESS or an error code ?
 *****************************************************************************/
static long ZCALLBACK ZipIO_Seek ( void *opaque, void *stream,
                                   unsigned long offset, int origin )
{
    (void) stream;
    stream_t *s = (stream_t*) opaque;
    long l_ret;

    uint64_t pos = offset + origin;
    l_ret = (long) stream_Seek( s->p_source, pos );
    return l_ret;
}
예제 #12
0
파일: oggseek.c 프로젝트: brendonjustin/vlc
static void seek_byte( demux_t *p_demux, int64_t i_pos )
{
    demux_sys_t *p_sys  = p_demux->p_sys;

    if ( ! stream_Seek( p_demux->s, i_pos ) )
    {
        ogg_sync_reset( &p_sys->oy );

        p_sys->i_input_position = i_pos;
        p_sys->b_page_waiting = false;
    }
}
예제 #13
0
파일: m3u.c 프로젝트: Akilklk/vlc
/*****************************************************************************
 * Import_M3U: main import function
 *****************************************************************************/
int Import_M3U( vlc_object_t *p_this )
{
    demux_t *p_demux = (demux_t *)p_this;
    const uint8_t *p_peek;
    char *(*pf_dup) (const char *) = GuessEncoding;
    int offset = 0;

    CHECK_FILE();
    if( stream_Peek( p_demux->s, &p_peek, 3 ) == 3
     && !memcmp( p_peek, "\xef\xbb\xbf", 3) )
    {
        pf_dup = CheckUnicode; /* UTF-8 Byte Order Mark */
        offset = 3;
    }

    if( demux_IsPathExtension( p_demux, ".m3u8" )
     || demux_IsForced( p_demux, "m3u8" )
     || CheckContentType( p_demux->s, "application/vnd.apple.mpegurl" ) )
        pf_dup = CheckUnicode; /* UTF-8 file type */
    else
    if( demux_IsPathExtension( p_demux, ".m3u" )
     || demux_IsPathExtension( p_demux, ".vlc" )
     || demux_IsForced( p_demux, "m3u" )
     || ContainsURL( p_demux )
     || CheckContentType( p_demux->s, "audio/x-mpegurl") )
        ; /* Guess encoding */
    else
    {
        if( stream_Peek( p_demux->s, &p_peek, 8 + offset ) < (8 + offset) )
            return VLC_EGENERIC;

        p_peek += offset;

        if( !strncasecmp( (const char *)p_peek, "RTSPtext", 8 ) ) /* QuickTime */
            pf_dup = CheckUnicode; /* UTF-8 */
        else
        if( !memcmp( p_peek, "#EXTM3U", 7 ) )
            ; /* Guess encoding */
        else
            return VLC_EGENERIC;
    }

    stream_Seek( p_demux->s, offset );

    STANDARD_DEMUX_INIT_MSG( "found valid M3U playlist" );
    p_demux->p_sys->psz_prefix = FindPrefix( p_demux );
    p_demux->p_sys->pf_dup = pf_dup;

    return VLC_SUCCESS;
}
예제 #14
0
/* Allow to append indexes after starting playback */
int AVI_ChunkFetchIndexes( stream_t *s, avi_chunk_t *p_riff )
{
    avi_chunk_t *p_movi = AVI_ChunkFind( p_riff, AVIFOURCC_movi, 0 );
    if ( !p_movi )
        return VLC_EGENERIC;

    avi_chunk_t *p_chk;
    uint64_t i_indexpos = 8 + p_movi->common.i_chunk_pos + p_movi->common.i_chunk_size;
    bool b_seekable = false;
    int i_ret = VLC_SUCCESS;

    stream_Control( s, STREAM_CAN_SEEK, &b_seekable );
    if ( !b_seekable || stream_Seek( s, i_indexpos ) )
        return VLC_EGENERIC;

    for( ; ; )
    {
        p_chk = xmalloc( sizeof( avi_chunk_t ) );
        memset( p_chk, 0, sizeof( avi_chunk_t ) );
        if (unlikely( !p_riff->common.p_first ))
            p_riff->common.p_first = p_chk;
        else
            p_riff->common.p_last->common.p_next = p_chk;
        p_riff->common.p_last = p_chk;

        i_ret = AVI_ChunkRead( s, p_chk, p_riff );
        if( i_ret )
            break;

        if( p_chk->common.p_father->common.i_chunk_size > 0 &&
           ( 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 any index */
        if( p_chk->common.i_chunk_fourcc == AVIFOURCC_indx ||
            p_chk->common.i_chunk_fourcc == AVIFOURCC_idx1 )
        {
            break;
        }

    }

    return i_ret;
}
예제 #15
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;
}
예제 #16
0
파일: cache_read.c 프로젝트: qdk0901/vlc
static int AStreamSeekStream(stream_t *s, uint64_t i_pos)
{
    stream_sys_t *sys = s->p_sys;
    stream_track_t *p_current = &sys->tk[sys->i_tk];

    if (p_current->i_start >= p_current->i_end  && i_pos >= p_current->i_end)
        return 0; /* EOF */

#ifdef STREAM_DEBUG
    msg_Dbg(s, "AStreamSeekStream: to %"PRId64" pos=%"PRId64
             " tk=%d start=%"PRId64" offset=%d end=%"PRId64,
             i_pos, sys->i_pos, sys->i_tk, p_current->i_start,
             sys->i_offset, p_current->i_end);
#endif

    bool   b_aseek;
    stream_Control(s->p_source, STREAM_CAN_SEEK, &b_aseek);
    if (!b_aseek && i_pos < p_current->i_start)
    {
        msg_Warn(s, "AStreamSeekStream: can't seek");
        return VLC_EGENERIC;
    }

    bool   b_afastseek;
    stream_Control(s->p_source, STREAM_CAN_FASTSEEK, &b_afastseek);

    /* FIXME compute seek cost (instead of static 'stupid' value) */
    uint64_t i_skip_threshold;
    if (b_aseek)
        i_skip_threshold = b_afastseek ? 128 : 3 * sys->i_read_size;
    else
        i_skip_threshold = INT64_MAX;

    /* Date the current track */
    p_current->date = mdate();

    /* Search a new track slot */
    stream_track_t *tk = NULL;
    int i_tk_idx = -1;

    /* Prefer the current track */
    if (p_current->i_start <= i_pos && i_pos <= p_current->i_end + i_skip_threshold)
    {
        tk = p_current;
        i_tk_idx = sys->i_tk;
    }
    if (!tk)
    {
        /* Try to maximize already read data */
        for (int i = 0; i < STREAM_CACHE_TRACK; i++)
        {
            stream_track_t *t = &sys->tk[i];

            if (t->i_start > i_pos || i_pos > t->i_end)
                continue;

            if (!tk || tk->i_end < t->i_end)
            {
                tk = t;
                i_tk_idx = i;
            }
        }
    }
    if (!tk)
    {
        /* Use the oldest unused */
        for (int i = 0; i < STREAM_CACHE_TRACK; i++)
        {
            stream_track_t *t = &sys->tk[i];

            if (!tk || tk->date > t->date)
            {
                tk = t;
                i_tk_idx = i;
            }
        }
    }
    assert(i_tk_idx >= 0 && i_tk_idx < STREAM_CACHE_TRACK);

    if (tk != p_current)
        i_skip_threshold = 0;
    if (tk->i_start <= i_pos && i_pos <= tk->i_end + i_skip_threshold)
    {
#ifdef STREAM_DEBUG
        msg_Err(s, "AStreamSeekStream: reusing %d start=%"PRId64
                 " end=%"PRId64"(%s)",
                 i_tk_idx, tk->i_start, tk->i_end,
                 tk != p_current ? "seek" : i_pos > tk->i_end ? "skip" : "noseek");
#endif
        if (tk != p_current)
        {
            assert(b_aseek);

            /* Seek at the end of the buffer
             * TODO it is stupid to seek now, it would be better to delay it
             */
            if (stream_Seek(s->p_source, tk->i_end))
            {
                msg_Err(s, "AStreamSeekStream: hard seek failed");
                return VLC_EGENERIC;
            }
        }
        else if (i_pos > tk->i_end)
        {
            uint64_t i_skip = i_pos - tk->i_end;
            while (i_skip > 0)
            {
                const int i_read_max = __MIN(10 * STREAM_READ_ATONCE, i_skip);
                int i_read = 0;
                if ((i_read = AStreamReadNoSeekStream(s, NULL, i_read_max)) < 0)
                {
                    msg_Err(s, "AStreamSeekStream: skip failed");
                    return VLC_EGENERIC;
                } else if (i_read == 0)
                    return VLC_SUCCESS; /* EOF */
                i_skip -= i_read_max;
            }
        }
    }
    else
    {
#ifdef STREAM_DEBUG
        msg_Err(s, "AStreamSeekStream: hard seek");
#endif
        /* Nothing good, seek and choose oldest segment */
        if (stream_Seek(s->p_source, i_pos))
        {
            msg_Err(s, "AStreamSeekStream: hard seek failed");
            return VLC_EGENERIC;
        }

        tk->i_start = i_pos;
        tk->i_end   = i_pos;
    }
    sys->i_offset = i_pos - tk->i_start;
    sys->i_tk = i_tk_idx;
    sys->i_pos = i_pos;

    /* If there is not enough data left in the track, refill  */
    /* TODO How to get a correct value for
     *    - refilling threshold
     *    - how much to refill
     */
    if (tk->i_end < tk->i_start + sys->i_offset + sys->i_read_size)
    {
        if (sys->i_used < STREAM_READ_ATONCE / 2)
            sys->i_used = STREAM_READ_ATONCE / 2;

        if (AStreamRefillStream(s))
            return VLC_EGENERIC;
    }
    return VLC_SUCCESS;
}
예제 #17
0
파일: access.c 프로젝트: 9034725985/vlc
int RarAccessOpen(vlc_object_t *object)
{
    access_t *access = (access_t*)object;

    const char *name = strchr(access->psz_location, '|');
    if (name == NULL)
        return VLC_EGENERIC;

    char *base = strndup(access->psz_location, name - access->psz_location);
    if (unlikely(base == NULL))
        return VLC_ENOMEM;

    name++;
    decode_URI(base);

    stream_t *s = stream_UrlNew(access, base);
    if (!s || RarProbe(s))
        goto error;

    struct
    {
        int filescount;
        rar_file_t **files;
        unsigned int i_nbvols;
    } newscheme = { 0, NULL, 0 }, oldscheme = { 0, NULL, 0 }, *p_scheme;

    if (RarParse(s, &newscheme.filescount, &newscheme.files, &newscheme.i_nbvols, false)
            || newscheme.filescount < 1 || newscheme.i_nbvols < 2 )
    {
        /* We might want to lookup old naming scheme, could be a part1.rar,part1.r00 */
        stream_Seek(s, 0);
        RarParse(s, &oldscheme.filescount, &oldscheme.files, &oldscheme.i_nbvols, true);
    }

    if (oldscheme.filescount >= newscheme.filescount && oldscheme.i_nbvols > newscheme.i_nbvols)
    {
        for (int i = 0; i < newscheme.filescount; i++)
            RarFileDelete(newscheme.files[i]);
        free(newscheme.files);
        p_scheme = &oldscheme;
        msg_Dbg(s, "using rar old naming for %d files nbvols %u", p_scheme->filescount, oldscheme.i_nbvols);
    }
    else if (newscheme.filescount)
    {
        for (int i = 0; i < oldscheme.filescount; i++)
            RarFileDelete(oldscheme.files[i]);
        free(oldscheme.files);
        p_scheme = &newscheme;
        msg_Dbg(s, "using rar new naming for %d files nbvols %u", p_scheme->filescount, oldscheme.i_nbvols);
    }
    else
    {
        msg_Info(s, "Invalid or unsupported RAR archive");
        for (int i = 0; i < oldscheme.filescount; i++)
            RarFileDelete(oldscheme.files[i]);
        free(oldscheme.files);
        for (int i = 0; i < newscheme.filescount; i++)
            RarFileDelete(newscheme.files[i]);
        free(newscheme.files);
        goto error;
    }

    rar_file_t *file = NULL;
    for (int i = 0; i < p_scheme->filescount; i++) {
        if (!file && !strcmp(p_scheme->files[i]->name, name))
            file = p_scheme->files[i];
        else
            RarFileDelete(p_scheme->files[i]);
    }
    free(p_scheme->files);
    if (!file)
        goto error;

    access_sys_t *sys = access->p_sys = malloc(sizeof(*sys));
    sys->s    = s;
    sys->file = file;

    access->pf_read    = Read;
    access->pf_block   = NULL;
    access->pf_control = Control;
    access->pf_seek    = Seek;

    access_InitFields(access);

    rar_file_chunk_t dummy = {
        .mrl = base,
    };
    sys->chunk = &dummy;
    Seek(access, 0);

    free(base);
    return VLC_SUCCESS;

error:
    if (s)
        stream_Delete(s);
    free(base);
    return VLC_EGENERIC;
}
예제 #18
0
파일: smf.c 프로젝트: CSRedRat/vlc
static
int HandleMessage (demux_t *p_demux, mtrk_t *tr)
{
    stream_t *s = p_demux->s;
    block_t *block;
    uint8_t first, event;
    unsigned datalen;

    if (stream_Seek (s, tr->offset)
     || (stream_Read (s, &first, 1) != 1))
        return -1;

    event = (first & 0x80) ? first : tr->running_event;

    switch (event & 0xf0)
    {
        case 0xF0: /* System Exclusive */
            switch (event)
            {
                case 0xF0: /* System Specific start */
                case 0xF7: /* System Specific continuation */
                {
                    /* Variable length followed by SysEx event data */
                    int32_t len = ReadVarInt (s);
                    if (len == -1)
                        return -1;

                    block = stream_Block (s, len);
                    if (block == NULL)
                        return -1;
                    block = block_Realloc (block, 1, len);
                    if (block == NULL)
                        return -1;
                    block->p_buffer[0] = event;
                    goto send;
                }
                case 0xFF: /* SMF Meta Event */
                    if (HandleMeta (p_demux, tr))
                        return -1;
                    /* We MUST NOT pass this event forward. It would be
                     * confused as a MIDI Reset real-time event. */
                    goto skip;
                case 0xF1:
                case 0xF3:
                    datalen = 1;
                    break;
                case 0xF2:
                    datalen = 2;
                    break;
                case 0xF4:
                case 0xF5:
                    /* We cannot handle undefined "common" (non-real-time)
                     * events inside SMF, as we cannot differentiate a
                     * one byte delta-time (< 0x80) from event data. */
                default:
                    datalen = 0;
                    break;
            }
            break;
        case 0xC0:
        case 0xD0:
            datalen = 1;
            break;
        default:
            datalen = 2;
            break;
    }

    /* FIXME: one message per block is very inefficient */
    block = block_New (p_demux, 1 + datalen);
    if (block == NULL)
        goto skip;

    block->p_buffer[0] = event;
    if (first & 0x80)
    {
        stream_Read (s, block->p_buffer + 1, datalen);
    }
    else
    {
        if (datalen == 0)
        {
            msg_Err (p_demux, "malformatted MIDI event");
            return -1; /* can't use implicit running status with empty payload! */
        }

        block->p_buffer[1] = first;
        if (datalen > 1)
            stream_Read (s, block->p_buffer + 2, datalen - 1);
    }

send:
    block->i_dts = block->i_pts = VLC_TS_0 + date_Get (&p_demux->p_sys->pts);
    es_out_Send (p_demux->out, p_demux->p_sys->es, block);

skip:
    if (event < 0xF8)
        /* If event is not real-time, update running status */
        tr->running_event = event;

    tr->offset = stream_Tell (s);
    return 0;
}
예제 #19
0
파일: smf.c 프로젝트: CSRedRat/vlc
/*****************************************************************************
 * Open: check file and initializes structures
 *****************************************************************************/
static int Open (vlc_object_t * p_this)
{
    demux_t       *p_demux = (demux_t *)p_this;
    stream_t      *stream = p_demux->s;
    demux_sys_t   *p_sys;
    const uint8_t *peek;
    unsigned       tracks, ppqn;
    bool     multitrack;

    /* (Try to) parse the SMF header */
    /* Header chunk always has 6 bytes payload */
    if (stream_Peek (stream, &peek, 14) < 14)
        return VLC_EGENERIC;

    /* Skip RIFF MIDI header if present */
    if (!memcmp (peek, "RIFF", 4) && !memcmp (peek + 8, "RMID", 4))
    {
        uint32_t riff_len = GetDWLE (peek + 4);

        msg_Dbg (p_this, "detected RIFF MIDI file (%u bytes)",
                 (unsigned)riff_len);
        if ((stream_Read (stream, NULL, 12) < 12))
            return VLC_EGENERIC;

        /* Look for the RIFF data chunk */
        for (;;)
        {
            char chnk_hdr[8];
            uint32_t chnk_len;

            if ((riff_len < 8)
             || (stream_Read (stream, chnk_hdr, 8) < 8))
                return VLC_EGENERIC;

            riff_len -= 8;
            chnk_len = GetDWLE (chnk_hdr + 4);
            if (riff_len < chnk_len)
                return VLC_EGENERIC;
            riff_len -= chnk_len;

            if (!memcmp (chnk_hdr, "data", 4))
                break; /* found! */

            if (stream_Read (stream, NULL, chnk_len) < (ssize_t)chnk_len)
                return VLC_EGENERIC;
        }

        /* Read real SMF header. Assume RIFF data chunk length is proper. */
        if (stream_Peek (stream, &peek, 14) < 14)
            return VLC_EGENERIC;
    }

    if (memcmp (peek, "MThd\x00\x00\x00\x06", 8))
        return VLC_EGENERIC;
    peek += 8;

    /* First word: SMF type */
    switch (GetWBE (peek))
    {
        case 0:
            multitrack = false;
            break;
        case 1:
            multitrack = true;
            break;
        default:
            /* We don't implement SMF2 (as do many) */
            msg_Err (p_this, "unsupported SMF file type %u", GetWBE (peek));
            return VLC_EGENERIC;
    }
    peek += 2;

    /* Second word: number of tracks */
    tracks = GetWBE (peek);
    peek += 2;
    if (!multitrack && (tracks != 1))
    {
        msg_Err (p_this, "invalid SMF type 0 file");
        return VLC_EGENERIC;
    }

    msg_Dbg (p_this, "detected Standard MIDI File (type %u) with %u track(s)",
             multitrack, tracks);

    /* Third/last word: timing */
    ppqn = GetWBE (peek);
    if (ppqn & 0x8000)
    {
        /* FIXME */
        msg_Err (p_this, "SMPTE timestamps not implemented");
        return VLC_EGENERIC;
    }
    else
    {
        msg_Dbg (p_this, " %u pulses per quarter note", ppqn);
    }

    p_sys = malloc (sizeof (*p_sys) + (sizeof (mtrk_t) * tracks));
    if (p_sys == NULL)
        return VLC_ENOMEM;

    /* We've had a valid SMF header - now skip it*/
    if (stream_Read (stream, NULL, 14) < 14)
        goto error;

    p_demux->pf_demux   = Demux;
    p_demux->pf_control = Control;
    p_demux->p_sys      = p_sys;

    /* Default SMF tempo is 120BPM, i.e. half a second per quarter note */
    date_Init (&p_sys->pts, ppqn * 2, 1);
    date_Set (&p_sys->pts, 0);
    p_sys->pulse        = 0;
    p_sys->ppqn         = ppqn;

    p_sys->trackc       = tracks;
    /* Prefetch track offsets */
    for (unsigned i = 0; i < tracks; i++)
    {
        uint8_t head[8];

        if (i > 0)
        {
            /* Seeking screws streaming up, but there is no way around this,
             * as SMF1 tracks are performed simultaneously.
             * Not a big deal as SMF1 are usually only a few kbytes anyway. */
            if (stream_Seek (stream,  p_sys->trackv[i-1].end))
            {
                msg_Err (p_this, "cannot build SMF index (corrupted file?)");
                goto error;
            }
        }

        for (;;)
        {
            if (stream_Read (stream, head, 8) < 8)
            {
                /* FIXME: don't give up if we have at least one valid track */
                msg_Err (p_this, "incomplete SMF chunk, file is corrupted");
                goto error;
            }

            if (memcmp (head, "MTrk", 4) == 0)
                break;

            msg_Dbg (p_this, "skipping unknown SMF chunk");
            stream_Read (stream, NULL, GetDWBE (head + 4));
        }

        p_sys->trackv[i].offset = stream_Tell (stream);
        p_sys->trackv[i].end = p_sys->trackv[i].offset + GetDWBE (head + 4);
        p_sys->trackv[i].next = 0;
        ReadDeltaTime (stream, p_sys->trackv + i);
        p_sys->trackv[i].running_event = 0xF6;
        /* Why 0xF6 (Tuning Calibration)?
         * Because it has zero bytes of data, so the parser will detect the
         * error if the first event uses running status. */
    }

    es_format_t  fmt;
    es_format_Init (&fmt, AUDIO_ES, VLC_CODEC_MIDI);
    fmt.audio.i_channels = 2;
    fmt.audio.i_rate = 44100; /* dummy value */
    p_sys->es = es_out_Add (p_demux->out, &fmt);

    return VLC_SUCCESS;

error:
    free (p_sys);
    return VLC_EGENERIC;
}
예제 #20
0
파일: stream.c 프로젝트: 743848887/vlc
static int
stream_seek( struct reader *p_reader, uint64_t i_offset )
{
    return stream_Seek( p_reader->u.s, i_offset );
}
예제 #21
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 );
        }
    }
}
예제 #22
0
파일: rawvid.c 프로젝트: 0xheart0/vlc
/*****************************************************************************
 * Open: initializes raw DV demux structures
 *****************************************************************************/
static int Open( vlc_object_t * p_this )
{
    demux_t     *p_demux = (demux_t*)p_this;
    demux_sys_t *p_sys;
    int i_width=-1, i_height=-1;
    unsigned u_fps_num, u_fps_den;
    vlc_fourcc_t i_chroma = 0;
    unsigned int i_sar_num;
    unsigned int i_sar_den;
    const struct preset_t *p_preset = NULL;
    const uint8_t *p_peek;
    bool b_y4m = false;

    if( stream_Peek( p_demux->s, &p_peek, 9 ) == 9 )
    {
        /* http://wiki.multimedia.cx/index.php?title=YUV4MPEG2 */
        if( !strncmp( (char *)p_peek, "YUV4MPEG2", 9 ) )
        {
            b_y4m = true;
            goto valid;
        }
    }

    if( !p_demux->b_force )
    {
        /* guess preset based on file extension */
        if( !p_demux->psz_file )
            return VLC_EGENERIC;

        const char *psz_ext = strrchr( p_demux->psz_file, '.' );
        if( !psz_ext )
            return VLC_EGENERIC;
        psz_ext++;

        for( unsigned i = 0; p_presets[i].psz_ext ; i++ )
        {
            if( !strcasecmp( psz_ext, p_presets[i].psz_ext ) )
            {
                p_preset = &p_presets[i];
                goto valid;
            }
        }
        return VLC_EGENERIC;
    }
valid:
    p_demux->p_sys      = p_sys = malloc( sizeof( demux_sys_t ) );
    if( !p_sys )
        return VLC_ENOMEM;

    p_sys->b_y4m = b_y4m;

    /* guess the parameters based on the preset */
    if( p_preset )
    {
        i_width = p_preset->i_width;
        i_height = p_preset->i_height;
        u_fps_num = p_preset->u_fps_num;
        u_fps_den = p_preset->u_fps_den;
        i_sar_num = p_preset->u_ar_num * p_preset->i_height;
        i_sar_den = p_preset->u_ar_den * p_preset->i_width;
        i_chroma = p_preset->i_chroma;
    }

    /* override presets if yuv4mpeg2 */
    if( b_y4m )
    {
        /* The string should start with "YUV4MPEG2" */
        char *psz = stream_ReadLine( p_demux->s );
        char *psz_buf;
        int a = 1;
        int b = 1;

        if( unlikely(psz == NULL) )
            goto error;

        /* NB, it is not possible to handle interlaced here, since the
         * interlaced picture flags are in picture_t not block_t */

#define READ_FRAC( key, num, den ) do { \
        psz_buf = strstr( psz+9, key );\
        if( psz_buf )\
        {\
            char *end = strchr( psz_buf+1, ' ' );\
            char *sep;\
            if( end ) *end = '\0';\
            sep = strchr( psz_buf+1, ':' );\
            if( sep )\
            {\
                *sep = '\0';\
                den = atoi( sep+1 );\
            }\
            else\
            {\
                den = 1;\
            }\
            num = atoi( psz_buf+2 );\
            if( sep ) *sep = ':';\
            if( end ) *end = ' ';\
        } } while(0)
        READ_FRAC( " W", i_width, a );
        READ_FRAC( " H", i_height, a );
        READ_FRAC( " F", u_fps_num, u_fps_den );
        READ_FRAC( " A", a, b );
#undef READ_FRAC
        if( b != 0 )
        {
            i_sar_num = a;
            i_sar_den = b;
        }

        psz_buf = strstr( psz+9, " C" );
        if( psz_buf )
        {
            static const struct { const char *psz_name; vlc_fourcc_t i_fcc; } formats[] =
            {
                { "420jpeg",    VLC_CODEC_I420 },
                { "420paldv",   VLC_CODEC_I420 },
                { "420",        VLC_CODEC_I420 },
                { "422",        VLC_CODEC_I422 },
                { "444",        VLC_CODEC_I444 },
                { "mono",       VLC_CODEC_GREY },
                { NULL, 0 }
            };
            bool b_found = false;
            char *psz_end = strchr( psz_buf+1, ' ' );
            if( psz_end )
                *psz_end = '\0';
            psz_buf += 2;

            for( int i = 0; formats[i].psz_name != NULL; i++ )
            {
                if( !strncmp( psz_buf, formats[i].psz_name, strlen(formats[i].psz_name) ) )
                {
                    i_chroma = formats[i].i_fcc;
                    b_found = true;
                    break;
                }
            }
            if( !b_found )
                msg_Warn( p_demux, "Unknown YUV4MPEG2 chroma type \"%s\"", psz_buf );
            if( psz_end )
                *psz_end = ' ';
        }

        free( psz );
    }

    /* allow the user to override anything guessed from the input */
    int i_tmp;
    i_tmp = var_CreateGetInteger( p_demux, "rawvid-width" );
    if( i_tmp ) i_width = i_tmp;

    i_tmp = var_CreateGetInteger( p_demux, "rawvid-height" );
    if( i_tmp ) i_height = i_tmp;

    char *psz_tmp;
    psz_tmp = var_CreateGetNonEmptyString( p_demux, "rawvid-chroma" );
    if( psz_tmp )
    {
        if( strlen( psz_tmp ) != 4 )
        {
            msg_Err( p_demux, "Invalid fourcc format/chroma specification %s"
                     " expecting four characters eg, UYVY", psz_tmp );
            free( psz_tmp );
            goto error;
        }
        memcpy( &i_chroma, psz_tmp, 4 );
        msg_Dbg( p_demux, "Forcing chroma to 0x%.8x (%4.4s)", i_chroma, (char*)&i_chroma );
        free( psz_tmp );
    }

    if( var_InheritURational( p_demux, &u_fps_num, &u_fps_den, "rawvid-fps" ) )
    {
        u_fps_num = 0;
        u_fps_den = 1;
    }

    if( var_InheritURational( p_demux, &i_sar_num, &i_sar_den,
                              "rawvid-aspect-ratio" ) )
        i_sar_num = i_sar_den = 1;

    /* moan about anything wrong */
    if( i_width <= 0 || i_height <= 0 )
    {
        msg_Err( p_demux, "width and height must be strictly positive." );
        goto error;
    }

    if( !u_fps_num || !u_fps_den )
    {
        msg_Err( p_demux, "invalid or no framerate specified." );
        goto error;
    }

    if( i_chroma == 0 )
    {
        msg_Err( p_demux, "invalid or no chroma specified." );
        goto error;
    }

    /* fixup anything missing with sensible assumptions */
    if( i_sar_num <= 0 || i_sar_den <= 0 )
    {
        /* assume 1:1 sar */
        i_sar_num = 1;
        i_sar_den = 1;
    }

    es_format_Init( &p_sys->fmt_video, VIDEO_ES, i_chroma );
    video_format_Setup( &p_sys->fmt_video.video, i_chroma,
                        i_width, i_height, i_width, i_height,
                        i_sar_num, i_sar_den );

    vlc_ureduce( &p_sys->fmt_video.video.i_frame_rate,
                 &p_sys->fmt_video.video.i_frame_rate_base,
                 u_fps_num, u_fps_den, 0);
    date_Init( &p_sys->pcr, p_sys->fmt_video.video.i_frame_rate,
               p_sys->fmt_video.video.i_frame_rate_base );
    date_Set( &p_sys->pcr, 0 );

    if( !p_sys->fmt_video.video.i_bits_per_pixel )
    {
        msg_Err( p_demux, "Unsupported chroma 0x%.8x (%4.4s)", i_chroma,
                 (char*)&i_chroma );
        goto error;
    }
    p_sys->frame_size = i_width * i_height
                        * p_sys->fmt_video.video.i_bits_per_pixel / 8;
    p_sys->p_es_video = es_out_Add( p_demux->out, &p_sys->fmt_video );

    p_demux->pf_demux   = Demux;
    p_demux->pf_control = Control;
    return VLC_SUCCESS;

error:
    stream_Seek( p_demux->s, 0 ); // Workaround, but y4m uses stream_ReadLines
    free( p_sys );
    return VLC_EGENERIC;
}
예제 #23
0
int RarStreamOpen(vlc_object_t *object)
{
    stream_t *s = (stream_t*)object;

    if (RarProbe(s->p_source))
        return VLC_EGENERIC;

    int count;
    rar_file_t **files;
    const int64_t position = stream_Tell(s->p_source);
    if ((RarParse(s->p_source, &count, &files, false) &&
         RarParse(s->p_source, &count, &files, true )) || count == 0 )
    {
        stream_Seek(s->p_source, position);
        msg_Info(s, "Invalid or unsupported RAR archive");
        free(files);
        return VLC_EGENERIC;
    }

    /* TODO use xspf to have node for directories
     * Reusing WriteXSPF from the zip access is probably a good idea
     * (becareful about '\' and '/'.
     */
    char *mrl;
    if (asprintf(&mrl, "%s://%s", s->psz_access, s->psz_path)< 0)
        mrl = NULL;
    char *base;
    char *encoded = mrl ? encode_URI_component(mrl) : NULL;
    free(mrl);

    if (!encoded || asprintf(&base, "rar://%s", encoded) < 0)
        base = NULL;
    free(encoded);

    char *data = strdup("#EXTM3U\n");
    for (int i = 0; i < count; i++) {
        rar_file_t *f = files[i];
        char *next;
        if (base && data &&
            asprintf(&next, "%s"
                            "#EXTINF:,,%s\n"
                            "%s|%s\n",
                            data, f->name, base, f->name) >= 0) {
            free(data);
            data = next;
        }
        RarFileDelete(f);
    }
    free(base);
    free(files);
    if (!data)
        return VLC_EGENERIC;
    stream_t *payload = stream_MemoryNew(s, (uint8_t*)data, strlen(data), false);
    if (!payload) {
        free(data);
        return VLC_EGENERIC;
    }

    s->pf_read = Read;
    s->pf_peek = Peek;
    s->pf_control = Control;

    stream_sys_t *sys = s->p_sys = malloc(sizeof(*sys));
    if (!sys) {
        stream_Delete(payload);
        return VLC_ENOMEM;
    }
    sys->payload = payload;

    char *tmp;
    if (asprintf(&tmp, "%s.m3u", s->psz_path) < 0) {
        RarStreamClose(object);
        return VLC_ENOMEM;
    }
    free(s->psz_path);
    s->psz_path = tmp;

    return VLC_SUCCESS;
}