Exemple #1
0
static int Open( vlc_object_t *p_this )
{
    stream_t *s = (stream_t*)p_this;
    stream_sys_t *p_sys;

    if( !isSmoothStreaming( s ) || s->psz_url == NULL )
        return VLC_EGENERIC;

    msg_Info( p_this, "Smooth Streaming (%s)", s->psz_url );

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

    char *uri = strdup( s->psz_url );
    if( unlikely( uri == NULL ) )
    {
        free( p_sys );
        return VLC_ENOMEM;
    }

    /* remove the last part of the url */
    char *pos = strrchr( uri, '/');
    *pos = '\0';
    p_sys->download.base_url = uri;

    ARRAY_INIT( p_sys->sms );
    ARRAY_INIT( p_sys->sms_selected );

    /* Parse SMS ismc content. */
    if( parse_Manifest( s ) != VLC_SUCCESS )
    {
        SysCleanup( p_sys );
        free( p_sys );
        return VLC_EGENERIC;
    }

    if( !p_sys->vod_duration )
       p_sys->b_live = true;

    /* Choose first video / audio / subtitle stream available */
    sms_stream_t *selected = NULL;
    FOREACH_ARRAY( sms_stream_t *sms, p_sys->sms );
    selected = SMS_GET_SELECTED_ST( sms->type );
    if( !selected )
        ARRAY_APPEND( p_sys->sms_selected, sms );
    FOREACH_END();

    /* Choose lowest quality for the first chunks */
    FOREACH_ARRAY( sms_stream_t *sms, p_sys->sms );
    quality_level_t *wanted = NULL;
    if ( sms->qlevels.i_size )
    {
        wanted = sms->qlevels.p_elems[0];
        for( int i=1; i < sms->qlevels.i_size; i++ )
        {
            if( sms->qlevels.p_elems[i]->Bitrate < wanted->Bitrate )
                wanted = sms->qlevels.p_elems[i];
        }
        sms->current_qlvl = wanted;
    }
    FOREACH_END();

    /* Init our playback queue */
    p_sys->p_current_stream = next_playback_stream( p_sys );
    if ( !p_sys->p_current_stream )
    {
        SysCleanup( p_sys );
        free( p_sys );
        return VLC_EGENERIC;
    }
    p_sys->playback.next_chunk_offset = CHUNK_OFFSET_UNSET;
    p_sys->i_probe_length = SMS_PROBE_LENGTH;

    vlc_mutex_init( &p_sys->lock );
    vlc_cond_init( &p_sys->download.wait );
    vlc_cond_init( &p_sys->playback.wait );
    vlc_mutex_init( &p_sys->playback.lock );

    /* */
    s->pf_read = Read;
    s->pf_control = Control;

    if( vlc_clone( &p_sys->download.thread, sms_Thread, s, VLC_THREAD_PRIORITY_INPUT ) )
    {
        SysCleanup( p_sys );
        vlc_mutex_destroy( &p_sys->lock );
        vlc_cond_destroy( &p_sys->download.wait );
        vlc_mutex_destroy( &p_sys->playback.lock );
        vlc_cond_destroy( &p_sys->playback.wait );
        free( p_sys );
        return VLC_EGENERIC;
    }

    return VLC_SUCCESS;
}
Exemple #2
0
static int Open( vlc_object_t *p_this )
{
    stream_t *s = (stream_t*)p_this;
    stream_sys_t *p_sys;

    if( !isSmoothStreaming( s ) )
        return VLC_EGENERIC;

    msg_Info( p_this, "Smooth Streaming (%s)", s->psz_path );

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

    char *uri = NULL;
    if( unlikely( asprintf( &uri, "%s://%s", s->psz_access, s->psz_path ) < 0 ) )
    {
        free( p_sys );
        return VLC_ENOMEM;
    }

    /* remove the last part of the url */
    char *pos = strrchr( uri, '/');
    *pos = '\0';
    p_sys->base_url = uri;

    /* XXX I don't know wether or not we should allow caching */
    p_sys->b_cache = false;

    p_sys->sms_streams = vlc_array_new();
    p_sys->selected_st = vlc_array_new();
    p_sys->download.chunks = vlc_array_new();
    p_sys->init_chunks = vlc_array_new();
    if( unlikely( !p_sys->sms_streams || !p_sys->download.chunks ||
                  !p_sys->selected_st || !p_sys->init_chunks ) )
    {
        free( p_sys );
        return VLC_ENOMEM;
    }

    /* Parse SMS ismc content. */
    if( parse_Manifest( s ) != VLC_SUCCESS )
    {
        free( p_sys );
        return VLC_EGENERIC;
    }

    if( !p_sys->vod_duration )
       p_sys->b_live = true;

    p_sys->i_tracks = vlc_array_count( p_sys->sms_streams );

    /* Choose first video / audio / subtitle stream available */
    sms_stream_t *tmp = NULL, *selected = NULL;
    for( unsigned i = 0; i < p_sys->i_tracks; i++ )
    {
        tmp = vlc_array_item_at_index( p_sys->sms_streams, i );
        selected = SMS_GET_SELECTED_ST( tmp->type );
        if( !selected )
            vlc_array_append( p_sys->selected_st, tmp );
    }

    /* Choose lowest quality for the first chunks */
    quality_level_t *wanted, *qlvl;
    sms_stream_t *sms = NULL;

    for( unsigned i = 0; i < p_sys->i_tracks; i++ )
    {
        wanted = qlvl = NULL;
        sms = vlc_array_item_at_index( p_sys->sms_streams, i );
        wanted = vlc_array_item_at_index( sms->qlevels, 0 );
        for( unsigned i=1; i < sms->qlevel_nb; i++ )
        {
            qlvl = vlc_array_item_at_index( sms->qlevels, i );
            if( qlvl->Bitrate < wanted->Bitrate )
                wanted = qlvl;
        }
        sms->download_qlvl = wanted->id;
    }

    vlc_mutex_init( &p_sys->download.lock_wait );
    vlc_cond_init( &p_sys->download.wait );

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

    if( vlc_clone( &p_sys->thread, sms_Thread, s, VLC_THREAD_PRIORITY_INPUT ) )
    {
        free( p_sys );
        vlc_mutex_destroy( &p_sys->download.lock_wait );
        vlc_cond_destroy( &p_sys->download.wait );
        return VLC_EGENERIC;
    }

    return VLC_SUCCESS;
}
Exemple #3
0
static int sms_Read( stream_t *s, uint8_t *p_read, int i_read )
{
    stream_sys_t *p_sys = s->p_sys;
    int copied = 0;
    chunk_t *chunk = NULL;

    do
    {
        chunk = get_chunk( s, true );
        if( !chunk )
            return copied;

        if( chunk->read_pos >= (int)chunk->size )
        {
            if( chunk->type == VIDEO_ES ||
                ( !SMS_GET_SELECTED_ST( VIDEO_ES ) && chunk->type == AUDIO_ES ) )
            {
                vlc_mutex_lock( &p_sys->download.lock_wait );
                p_sys->playback.toffset += chunk->duration;
                vlc_mutex_unlock( &p_sys->download.lock_wait );
                vlc_cond_signal( &p_sys->download.wait);
            }
            if( !p_sys->b_cache || p_sys->b_live )
            {
                FREENULL( chunk->data );
                chunk->read_pos = 0;
            }

            chunk->read_pos = 0;

            p_sys->playback.index += 1;
            msg_Dbg( s, "Incrementing playback index" );

            continue;
        }

        if( chunk->read_pos == 0 )
        {
            const char *verb = p_read == NULL ? "skipping" : "reading";
            msg_Dbg( s, "%s chunk %u (%u bytes), type %i",
                        verb, chunk->sequence, i_read, chunk->type );
            /* check integrity */
            uint32_t type;
            uint8_t *slice = chunk->data;
            SMS_GET4BYTES( type );
            SMS_GETFOURCC( type );
            assert( type == ATOM_moof || type == ATOM_uuid );
        }

        int len = -1;
        uint8_t *src = chunk->data + chunk->read_pos;
        if( i_read <= chunk->size - chunk->read_pos )
            len = i_read;
        else
            len = chunk->size - chunk->read_pos;

        if( len > 0 )
        {
            if( p_read ) /* otherwise caller skips data */
                memcpy( p_read + copied, src, len );
            chunk->read_pos += len;
            copied += len;
            i_read -= len;
        }


    } while ( i_read > 0 );

    return copied;
}
Exemple #4
0
static unsigned int sms_Read( stream_t *s, uint8_t *p_read, unsigned int i_read )
{
    stream_sys_t *p_sys = s->p_sys;
    unsigned int copied = 0;
    chunk_t *chunk = NULL;

    do
    {
        bool b_isinitchunk = false;
        chunk = get_chunk( s, true, &b_isinitchunk );
        /* chunk here won't be processed further */
//        msg_Dbg( s, "chunk %"PRIu64" init %d", (uint64_t) chunk, b_isinitchunk );
        if( !chunk )
            return copied;

        if( chunk->read_pos >= chunk->size )
        {
            if( chunk->type == VIDEO_ES ||
                ( !SMS_GET_SELECTED_ST( VIDEO_ES ) && chunk->type == AUDIO_ES ) )
            {
                p_sys->playback.toffset += chunk->duration;
                vlc_cond_signal( &p_sys->download.wait );
            }

            if ( b_isinitchunk )
            {
                assert( chunk->read_pos == chunk->size );
                vlc_mutex_lock( &p_sys->playback.lock );
                p_sys->playback.init.p_startchunk = NULL;
                p_sys->playback.init.p_datachunk = NULL;
                chunk_Free( chunk );
                vlc_mutex_unlock( &p_sys->playback.lock );
            }
            else
            {
                vlc_mutex_lock( &p_sys->lock );
                if( gotoNextChunk( p_sys ) == NULL )
                {
                    vlc_mutex_unlock( &p_sys->lock );
                    return 0;
                }
                vlc_mutex_unlock( &p_sys->lock );
            }

            continue;
        }

        if( chunk->read_pos == 0 )
        {
            const char *verb = p_read == NULL ? "skipping" : "reading";
            msg_Dbg( s, "%s chunk time %"PRIu64" (%u bytes), type %i",
                        verb, chunk->start_time, i_read, chunk->type );
        }

        uint64_t len = 0;
        uint8_t *src = chunk->data + chunk->read_pos;
        if( i_read <= chunk->size - chunk->read_pos )
            len = i_read;
        else
            len = chunk->size - chunk->read_pos;

        if( len > 0 )
        {
            if( p_read ) /* otherwise caller skips data */
                memcpy( p_read + copied, src, len );
            chunk->read_pos += len;
            copied += len;
            i_read -= len;
            p_sys->playback.boffset += len;
        }

    } while ( i_read > 0 );

    return copied;
}