Exemple #1
0
static int Demux( demux_t* p_demux )
{
    demux_sys_t* p_sys = p_demux->p_sys;

    /* Last one must be an end time */
    while( p_sys->times.i_current + 1 < p_sys->times.i_count &&
           tt_time_Convert( &p_sys->times.p_array[p_sys->times.i_current] ) <= p_sys->i_next_demux_time )
    {
        const vlc_tick_t i_playbacktime =
                tt_time_Convert( &p_sys->times.p_array[p_sys->times.i_current] );
        const vlc_tick_t i_playbackendtime =
                tt_time_Convert( &p_sys->times.p_array[p_sys->times.i_current + 1] ) - 1;

        if ( !p_sys->b_slave && p_sys->b_first_time )
        {
            es_out_SetPCR( p_demux->out, VLC_TICK_0 + i_playbacktime );
            p_sys->b_first_time = false;
        }

        struct vlc_memstream stream;

        if( vlc_memstream_open( &stream ) )
            return VLC_DEMUXER_EGENERIC;

        tt_node_ToText( &stream, (tt_basenode_t *) p_sys->p_rootnode,
                        &p_sys->times.p_array[p_sys->times.i_current] );

        if( vlc_memstream_close( &stream ) == VLC_SUCCESS )
        {
            block_t* p_block = block_heap_Alloc( stream.ptr, stream.length );
            if( p_block )
            {
                p_block->i_dts =
                    p_block->i_pts = VLC_TICK_0 + i_playbacktime;
                p_block->i_length = i_playbackendtime - i_playbacktime;

                es_out_Send( p_demux->out, p_sys->p_es, p_block );
            }
        }

        p_sys->times.i_current++;
    }

    if ( !p_sys->b_slave )
    {
        es_out_SetPCR( p_demux->out, VLC_TICK_0 + p_sys->i_next_demux_time );
        p_sys->i_next_demux_time += VLC_TICK_FROM_MS(125);
    }

    if( p_sys->times.i_current + 1 >= p_sys->times.i_count )
        return VLC_DEMUXER_EOF;

    return VLC_DEMUXER_SUCCESS;
}
Exemple #2
0
/*****************************************************************************
 * Demux: read packet and send them to decoders
 *****************************************************************************
 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
 *****************************************************************************/
static int Demux( demux_t *p_demux )
{
    demux_sys_t *p_sys = p_demux->p_sys;
    block_t     *p_block;
    int64_t     i_offset = vlc_stream_Tell( p_demux->s );
    unsigned    i_frames = p_sys->i_block_frames;

    if( p_sys->i_data_size > 0 &&
        (i_offset - HEADER_LENGTH) >= p_sys->i_data_size )
    {
        return VLC_DEMUXER_EOF;
    }

    p_block = vlc_stream_Block( p_demux->s, p_sys->i_frame_size * i_frames );
    if( p_block == NULL )
    {
        msg_Warn( p_demux, "cannot read data" );
        return VLC_DEMUXER_EOF;
    }

    i_frames = p_block->i_buffer / p_sys->i_frame_size;
    p_block->i_dts = p_block->i_pts = date_Get( &p_sys->pts );
    es_out_SetPCR( p_demux->out, p_block->i_pts );
    es_out_Send( p_demux->out, p_sys->p_es, p_block );

    date_Increment( &p_sys->pts, i_frames * FRAME_LENGTH );

    return VLC_DEMUXER_SUCCESS;
}
Exemple #3
0
Fichier : cdg.c Projet : IAPark/vlc
/*****************************************************************************
 * Demux: read packet and send them to decoders
 *****************************************************************************
 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
 *****************************************************************************/
static int Demux( demux_t *p_demux )
{
    demux_sys_t *p_sys = p_demux->p_sys;
    block_t     *p_block;
    mtime_t     i_date;
    mtime_t     i_delta;

    i_delta = INT64_C(1000000) / CDG_FRAME_RATE;

    p_block = vlc_stream_Block( p_demux->s, CDG_FRAME_SIZE );
    if( p_block == NULL )
    {
        msg_Dbg( p_demux, "cannot read data, eof" );
        return 0;
    }

    i_date = vlc_stream_Tell( p_demux->s ) / CDG_FRAME_SIZE * i_delta;
    if( i_date >= date_Get( &p_sys->pts ) + i_delta )
    {
        p_block->i_dts = p_block->i_pts = i_date;
        date_Set( &p_sys->pts, i_date );
    }
    else
    {
        p_block->i_dts = i_date;
        p_block->i_pts = date_Get( &p_sys->pts );
    }

    es_out_SetPCR( p_demux->out, p_block->i_pts );

    es_out_Send( p_demux->out, p_sys->p_es, p_block );

    return 1;
}
Exemple #4
0
static int DemuxOnce (demux_t *demux, bool master)
{
    demux_sys_t *sys = demux->p_sys;
    mtime_t pts = date_Get (&sys->date);
    lldiv_t d;
    unsigned h, m, s, f;

    d = lldiv (pts, CLOCK_FREQ);
    f = d.rem * sys->date.i_divider_num / sys->date.i_divider_den / CLOCK_FREQ;
    d = lldiv (d.quot, 60);
    s = d.rem;
    d = lldiv (d.quot, 60);
    m = d.rem;
    h = d.quot;

    char *str;
    int len = asprintf (&str, "%02u:%02u:%02u:%02u", h, m, s, f);
    if (len == -1)
        return -1;

    block_t *block = block_heap_Alloc (str, len + 1);
    if (unlikely(block == NULL))
        return -1;

    block->i_buffer = len;
    assert(str[len] == '\0');

    block->i_pts = block->i_dts = pts;
    block->i_length = date_Increment (&sys->date, 1) - pts;
    es_out_Send (demux->out, sys->es, block);
    if (master)
        es_out_SetPCR(demux->out, pts);
    return 1;
}
Exemple #5
0
/*****************************************************************************
 * Demux: read packet and send them to decoders
 *****************************************************************************
 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
 *****************************************************************************/
static int Demux( demux_t *p_demux )
{
    demux_sys_t *p_sys = p_demux->p_sys;
    block_t     *p_block;
    vlc_tick_t  i_date;

    p_block = vlc_stream_Block( p_demux->s, CDG_FRAME_SIZE );
    if( p_block == NULL )
    {
        msg_Dbg( p_demux, "cannot read data, eof" );
        return VLC_DEMUXER_EOF;
    }

    i_date = PosToDate( p_demux );
    if( i_date >= date_Get( &p_sys->pts ) + CDG_FRAME_DELTA )
    {
        p_block->i_dts = p_block->i_pts = VLC_TICK_0 + i_date;
        date_Set( &p_sys->pts, VLC_TICK_0 + i_date );
    }
    else
    {
        p_block->i_dts = VLC_TICK_0 + i_date;
        p_block->i_pts = date_Get( &p_sys->pts );
    }

    es_out_SetPCR( p_demux->out, p_block->i_pts );
    es_out_Send( p_demux->out, p_sys->p_es, p_block );
    return VLC_DEMUXER_SUCCESS;
}
Exemple #6
0
/*****************************************************************************
 * Demux:
 *****************************************************************************/
static int Demux( demux_t *p_demux )
{
    demux_sys_t *p_sys = p_demux->p_sys;
    block_t     *p_frame;
    const int i_bk = ( p_sys->fmt.audio.i_bitspersample / 8 ) *
                       p_sys->fmt.audio.i_channels;

    p_frame = block_Alloc( p_sys->fmt.audio.i_rate / 10 * i_bk );
    if( !p_frame )
        return VLC_DEMUXER_EGENERIC;

    const int i_read = ModPlug_Read( p_sys->f, p_frame->p_buffer, p_frame->i_buffer );
    if( i_read <= 0 )
    {
        /* EOF */
        block_Release( p_frame );
        return VLC_DEMUXER_EOF;
    }
    p_frame->i_buffer = i_read;
    p_frame->i_dts =
    p_frame->i_pts = date_Get( &p_sys->pts );

    es_out_SetPCR( p_demux->out, p_frame->i_pts );
    es_out_Send( p_demux->out, p_sys->es, p_frame );
    date_Increment( &p_sys->pts, i_read / i_bk );
    return VLC_DEMUXER_SUCCESS;
}
Exemple #7
0
Fichier : gme.c Projet : IAPark/vlc
static int Demux (demux_t *demux)
{
    demux_sys_t *sys = demux->p_sys;

    /* Next track */
    if (gme_track_ended (sys->emu))
    {
        msg_Dbg (demux, "track %u ended", sys->track_id);
        if (++sys->track_id >= (unsigned)gme_track_count (sys->emu))
            return 0;

        demux->info.i_update |= INPUT_UPDATE_TITLE;
        demux->info.i_title = sys->track_id;
        gme_start_track (sys->emu, sys->track_id);
    }


    block_t *block = block_Alloc (2 * 2 * SAMPLES);
    if (unlikely(block == NULL))
        return 0;

    gme_err_t ret = gme_play (sys->emu, 2 * SAMPLES, (void *)block->p_buffer);
    if (ret != NULL)
    {
        block_Release (block);
        msg_Err (demux, "%s", ret);
        return 0;
    }

    block->i_pts = block->i_dts = VLC_TS_0 + date_Get (&sys->pts);
    es_out_SetPCR (demux->out, block->i_pts);
    es_out_Send (demux->out, sys->es, block);
    date_Increment (&sys->pts, SAMPLES);
    return 1;
}
Exemple #8
0
static void *DemuxThread( void *p_data )
{
    demux_t *p_demux = (demux_t *) p_data;
    demux_sys_t  *p_sys = p_demux->p_sys;
    vlc_tick_t i_next_frame_date = vlc_tick_now() + p_sys->i_frame_interval;
    int i_status;

    for(;;)
    {
        p_sys->i_cancel_state = vlc_savecancel();
        i_status = WaitForMessage( p_sys->p_client, p_sys->i_frame_interval );
        vlc_restorecancel( p_sys->i_cancel_state );

        /* Ensure we're not building frames too fast */
        /* as WaitForMessage takes only a maximum wait */
        vlc_tick_wait( i_next_frame_date );
        i_next_frame_date += p_sys->i_frame_interval;

        if ( i_status > 0 )
        {
            p_sys->p_client->frameBuffer = p_sys->p_block->p_buffer;
            p_sys->i_cancel_state = vlc_savecancel();
            i_status = HandleRFBServerMessage( p_sys->p_client );
            vlc_restorecancel( p_sys->i_cancel_state );
            if ( ! i_status )
            {
                msg_Warn( p_demux, "Cannot get announced data. Server closed ?" );
                es_out_Del( p_demux->out, p_sys->es );
                p_sys->es = NULL;
                return NULL;
            }
            else
            {
                block_t *p_block = block_Duplicate( p_sys->p_block );
                if ( p_block ) /* drop frame/content if no next block */
                {
                    p_sys->p_block->i_dts = p_sys->p_block->i_pts = vlc_tick_now();
                    es_out_SetPCR( p_demux->out, p_sys->p_block->i_pts );
                    es_out_Send( p_demux->out, p_sys->es, p_sys->p_block );
                    p_sys->p_block = p_block;
                }
            }
        }
    }
    return NULL;
}
Exemple #9
0
/*****************************************************************************
 * Demux: reads and demuxes data packets
 *****************************************************************************
 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
 *****************************************************************************/
static int Demux( demux_t *p_demux )
{
    demux_sys_t *p_sys  = p_demux->p_sys;
    block_t     *p_block;

    p_block = vlc_stream_Block( p_demux->s, p_sys->i_frame_size );
    if( p_block == NULL )
        return VLC_DEMUXER_EOF;

    p_block->i_dts = p_block->i_pts = date_Get( &p_sys->pts );

    es_out_SetPCR( p_demux->out, p_block->i_pts );
    es_out_Send( p_demux->out, p_sys->p_es, p_block );

    date_Increment( &p_sys->pts, p_sys->i_frame_samples );

    return VLC_DEMUXER_SUCCESS;
}
Exemple #10
0
static void *Thread(void *data)
{
    demux_t *demux = data;
    demux_sys_t *sys = demux->p_sys;
    struct wl_display *display = sys->display;
    struct pollfd ufd[1];
    unsigned interval = lroundf(CLOCK_FREQ / (sys->rate * 1000.f));

    int canc = vlc_savecancel();
    vlc_cleanup_push(cleanup_wl_display_read, display);

    ufd[0].fd = wl_display_get_fd(display);
    ufd[0].events = POLLIN;

    for (;;)
    {
        if (DisplayError(demux, display))
            break;

        if (sys->es != NULL)
        {
            block_t *block = Shoot(demux);

            block->i_pts = block->i_dts = vlc_tick_now();
            es_out_SetPCR(demux->out, block->i_pts);
            es_out_Send(demux->out, sys->es, block);
        }

        while (wl_display_prepare_read(display) != 0)
            wl_display_dispatch_pending(display);
        wl_display_flush(display);
        vlc_restorecancel(canc);

        while (poll(ufd, 1, interval) < 0);

        canc = vlc_savecancel();
        wl_display_read_events(display);
        wl_display_dispatch_pending(display);
    }
    vlc_cleanup_pop();
    vlc_restorecancel(canc);
    return NULL;
}
Exemple #11
0
Fichier : au.c Projet : IAPark/vlc
/*****************************************************************************
 * Demux: read packet and send them to decoders
 *****************************************************************************
 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
 *****************************************************************************/
static int Demux( demux_t *p_demux )
{
    demux_sys_t *p_sys = p_demux->p_sys;
    block_t     *p_block;

    /* set PCR */
    es_out_SetPCR( p_demux->out, VLC_TS_0 + p_sys->i_time );

    p_block = vlc_stream_Block( p_demux->s, p_sys->i_frame_size );
    if( p_block == NULL )
    {
        msg_Warn( p_demux, "cannot read data" );
        return 0;
    }

    p_block->i_dts =
    p_block->i_pts = VLC_TS_0 + p_sys->i_time;

    es_out_Send( p_demux->out, p_sys->es, p_block );

    p_sys->i_time += p_sys->i_frame_length;

    return 1;
}
Exemple #12
0
Fichier : xcb.c Projet : IAPark/vlc
/**
 * Processing callback
 */
static void Demux (void *opaque)
{
    demux_t *demux = opaque;
    demux_sys_t *sys = demux->p_sys;
    xcb_connection_t *conn = sys->conn;

    /* Determine capture region */
    xcb_get_geometry_cookie_t gc;
    xcb_query_pointer_cookie_t qc;

    gc = xcb_get_geometry (conn, sys->window);
    if (sys->follow_mouse)
        qc = xcb_query_pointer (conn, sys->window);

    xcb_get_geometry_reply_t *geo = xcb_get_geometry_reply (conn, gc, NULL);
    if (geo == NULL)
    {
        msg_Err (demux, "bad X11 drawable 0x%08"PRIx32, sys->window);
discard:
        if (sys->follow_mouse)
            xcb_discard_reply (conn, gc.sequence);
        return;
    }

    unsigned w = sys->w;
    unsigned h = sys->h;
    int x, y;

    if (sys->follow_mouse)
    {
        xcb_query_pointer_reply_t *ptr =
            xcb_query_pointer_reply (conn, qc, NULL);
        if (ptr == NULL)
        {
            free (geo);
            return;
        }

        if (w == 0 || w > geo->width)
            w = geo->width;
        x = ptr->win_x;
        if (x < (int)(w / 2))
            x = 0;
        else if (x >= (int)(geo->width - (w / 2)))
            x = geo->width - w;
        else
            x -= w / 2;

        if (h == 0 || h > geo->height)
            h = geo->height;
        y = ptr->win_y;
        if (y < (int)(h / 2))
            y = 0;
        else if (y >= (int)(geo->height - (h / 2)))
            y = geo->height - h;
        else
            y -= h / 2;
    }
    else
    {
        int max;

        x = sys->x;
        max = (int)geo->width - x;
        if (max <= 0)
            goto discard;
        if (w == 0 || w > (unsigned)max)
            w = max;

        y = sys->y;
        max = (int)geo->height - y;
        if (max <= 0)
            goto discard;
        if (h == 0 || h > (unsigned)max)
            h = max;
    }

    /* Update elementary stream format (if needed) */
    if (w != sys->cur_w || h != sys->cur_h)
    {
        if (sys->es != NULL)
            es_out_Del (demux->out, sys->es);

        /* Update composite pixmap */
        if (sys->window != geo->root)
        {
            xcb_free_pixmap (conn, sys->pixmap); /* no-op first time */
            xcb_composite_name_window_pixmap (conn, sys->window, sys->pixmap);
            xcb_create_pixmap (conn, geo->depth, sys->pixmap,
                               geo->root, geo->width, geo->height);
        }

        sys->es = InitES (demux, w, h, geo->depth, &sys->bpp);
        if (sys->es != NULL)
        {
            sys->cur_w = w;
            sys->cur_h = h;
            sys->bpp /= 8; /* bits -> bytes */
        }
    }

    /* Capture screen */
    xcb_drawable_t drawable =
        (sys->window != geo->root) ? sys->pixmap : sys->window;
    free (geo);

    block_t *block = NULL;
#if HAVE_SYS_SHM_H
    if (sys->shm)
    {   /* Capture screen through shared memory */
        size_t size = w * h * sys->bpp;
        int id = shmget (IPC_PRIVATE, size, IPC_CREAT | 0777);
        if (id == -1) /* XXX: fallback */
        {
            msg_Err (demux, "shared memory allocation error: %s",
                     vlc_strerror_c(errno));
            goto noshm;
        }

        /* Attach the segment to X and capture */
        xcb_shm_get_image_reply_t *img;
        xcb_shm_get_image_cookie_t ck;

        xcb_shm_attach (conn, sys->segment, id, 0 /* read/write */);
        ck = xcb_shm_get_image (conn, drawable, x, y, w, h, ~0,
                                XCB_IMAGE_FORMAT_Z_PIXMAP, sys->segment, 0);
        xcb_shm_detach (conn, sys->segment);
        img = xcb_shm_get_image_reply (conn, ck, NULL);
        xcb_flush (conn); /* ensure eventual detach */

        if (img == NULL)
        {
            shmctl (id, IPC_RMID, 0);
            goto noshm;
        }
        free (img);

        /* Attach the segment to VLC */
        void *shm = shmat (id, NULL, 0 /* read/write */);
        shmctl (id, IPC_RMID, 0);
        if (-1 == (intptr_t)shm)
        {
            msg_Err (demux, "shared memory attachment error: %s",
                     vlc_strerror_c(errno));
            return;
        }

        block = block_shm_Alloc (shm, size);
        if (unlikely(block == NULL))
            shmdt (shm);
    }
noshm:
#endif
    if (block == NULL)
    {   /* Capture screen through socket (fallback) */
        xcb_get_image_reply_t *img;

        img = xcb_get_image_reply (conn,
            xcb_get_image (conn, XCB_IMAGE_FORMAT_Z_PIXMAP, drawable,
                           x, y, w, h, ~0), NULL);
        if (img == NULL)
            return;

        uint8_t *data = xcb_get_image_data (img);
        size_t datalen = xcb_get_image_data_length (img);
        block = block_heap_Alloc (img, data + datalen - (uint8_t *)img);
        if (block == NULL)
            return;
        block->p_buffer = data;
        block->i_buffer = datalen;
    }

    /* Send block - zero copy */
    if (sys->es != NULL)
    {
        block->i_pts = block->i_dts = mdate ();

        es_out_SetPCR(demux->out, block->i_pts);
        es_out_Send (demux->out, sys->es, block);
    }
    else
        block_Release (block);
}
Exemple #13
0
static void *Thread (void *data)
{
    demux_t *demux = data;
    demux_sys_t *sys = demux->p_sys;
    snd_pcm_t *pcm = sys->pcm;
    size_t bytes;
    int canc, val;

    canc = vlc_savecancel ();
    bytes = snd_pcm_frames_to_bytes (pcm, sys->period_size);
    val = snd_pcm_start (pcm);
    if (val)
    {
        msg_Err (demux, "cannot prepare device: %s", snd_strerror (val));
        return NULL;
    }

    for (;;)
    {
        block_t *block = block_Alloc (bytes);
        if (unlikely(block == NULL))
            break;

        /* Wait for data */
        Poll (pcm, canc);

        /* Read data */
        snd_pcm_sframes_t frames, delay;
        mtime_t pts;

        frames = snd_pcm_readi (pcm, block->p_buffer, sys->period_size);
        pts = mdate ();
        if (frames < 0)
        {
            block_Release (block);
            if (frames == -EAGAIN)
                continue;

            val = snd_pcm_recover (pcm, frames, 1);
            if (val == 0)
            {
                msg_Warn (demux, "cannot read samples: %s",
                          snd_strerror (frames));
                snd_pcm_state_t state = snd_pcm_state (pcm);
                switch (state)
                {
                case SND_PCM_STATE_PREPARED:
                    val = snd_pcm_start (pcm);
                    if (val < 0)
                    {
                        msg_Err (demux, "cannot prepare device: %s",
                                 snd_strerror (val));
                        return NULL;
                    }
                    continue;
                case SND_PCM_STATE_RUNNING:
                    continue;
                default:
                    break;
                }
            }
            msg_Err (demux, "cannot recover record stream: %s",
                     snd_strerror (val));
            DumpDeviceStatus (demux, pcm);
            break;
        }

        /* Compute time stamp */
        if (snd_pcm_delay (pcm, &delay))
            delay = 0;
        delay += frames;
        pts -= (CLOCK_FREQ * delay) / sys->rate;

        block->i_buffer = snd_pcm_frames_to_bytes (pcm, frames);
        block->i_nb_samples = frames;
        block->i_pts = pts;
        block->i_length = (CLOCK_FREQ * frames) / sys->rate;

        es_out_SetPCR(demux->out, block->i_pts);
        es_out_Send (demux->out, sys->es, block);
    }
    return NULL;
}
Exemple #14
0
/*****************************************************************************
 * Demux:
 *****************************************************************************/
static void *DemuxThread( void *p_data )
{
    demux_t *p_demux = (demux_t *) p_data;
    demux_sys_t *p_sys = p_demux->p_sys;
    p_sys->i_starttime = vlc_tick_now();
    vlc_tick_t i_next_frame_date = vlc_tick_now() + p_sys->i_frame_interval;
    int i_ret;

    for(;;)
    {
        i_ret = 0;
        p_sys->i_cancel_state = vlc_savecancel();
        if ( freerdp_shall_disconnect( p_sys->p_instance ) )
        {
            vlc_restorecancel( p_sys->i_cancel_state );
            msg_Warn( p_demux, "RDP server closed session" );
            es_out_Del( p_demux->out, p_sys->es );
            p_sys->es = NULL;
            return NULL;
        }

        struct
        {
            void* pp_rfds[RDP_MAX_FD]; /* Declared by rdp */
            void* pp_wfds[RDP_MAX_FD];
            int i_nbr;
            int i_nbw;
            struct pollfd ufds[RDP_MAX_FD];
        } fds;

        fds.i_nbr = fds.i_nbw = 0;

        if ( freerdp_get_fds( p_sys->p_instance, fds.pp_rfds, &fds.i_nbr,
                              fds.pp_wfds, &fds.i_nbw ) != true )
        {
            vlc_restorecancel( p_sys->i_cancel_state );
            msg_Err( p_demux, "cannot get FDS" );
        }
        else
        if ( (fds.i_nbr + fds.i_nbw) > 0 && p_sys->es )
        {
            vlc_restorecancel( p_sys->i_cancel_state );
            int i_count = 0;

            for( int i = 0; i < fds.i_nbr; i++ )
            {
                fds.ufds[ i_count ].fd = (long) fds.pp_rfds[ i ];
                fds.ufds[ i_count ].events = POLLIN ;
                fds.ufds[ i_count++ ].revents = 0;
            }
            for( int i = 0; i < fds.i_nbw && i_count < RDP_MAX_FD; i++ )
            {   /* may be useless */
                fds.ufds[ i_count ].fd = (long) fds.pp_wfds[ i ];
                fds.ufds[ i_count ].events = POLLOUT;
                fds.ufds[ i_count++ ].revents = 0;
            }
            i_ret = poll( fds.ufds, i_count, p_sys->i_frame_interval * 1000/2 );
        } else {
            vlc_restorecancel( p_sys->i_cancel_state );
        }

        vlc_tick_wait( i_next_frame_date );
        i_next_frame_date += p_sys->i_frame_interval;

        if ( i_ret >= 0 )
        {
            /* Do the rendering */
            p_sys->i_cancel_state = vlc_savecancel();
            freerdp_check_fds( p_sys->p_instance );
            vlc_restorecancel( p_sys->i_cancel_state );
            block_t *p_block = block_Duplicate( p_sys->p_block );
            if (likely( p_block && p_sys->p_block ))
            {
                p_sys->p_block->i_dts = p_sys->p_block->i_pts = vlc_tick_now() - p_sys->i_starttime;
                es_out_SetPCR( p_demux->out, p_sys->p_block->i_pts );
                es_out_Send( p_demux->out, p_sys->es, p_sys->p_block );
                p_sys->p_block = p_block;
            }
        }
    }
    return NULL;
}
Exemple #15
0
/*****************************************************************************
 * Demux:
 *****************************************************************************/
static int Demux( demux_t *p_demux )
{
    demux_sys_t *p_sys = p_demux->p_sys;
    int i_ret, i_mux_rate;
    block_t *p_pkt;

    i_ret = ps_pkt_resynch( p_demux->s, p_sys->format, p_sys->b_have_pack );
    if( i_ret < 0 )
    {
        return VLC_DEMUXER_EOF;
    }
    else if( i_ret == 0 )
    {
        if( !p_sys->b_lost_sync )
        {
            msg_Warn( p_demux, "garbage at input from %"PRIu64", trying to resync...",
                                vlc_stream_Tell(p_demux->s) );
            NotifyDiscontinuity( p_sys->tk, p_demux->out );
        }

        p_sys->b_lost_sync = true;
        return VLC_DEMUXER_SUCCESS;
    }

    if( p_sys->b_lost_sync ) msg_Warn( p_demux, "found sync code" );
    p_sys->b_lost_sync = false;

    if( p_sys->i_length == VLC_TICK_INVALID && p_sys->b_seekable )
    {
        if( !FindLength( p_demux ) )
            return VLC_DEMUXER_EGENERIC;
    }

    if( ( p_pkt = ps_pkt_read( p_demux->s ) ) == NULL )
    {
        return VLC_DEMUXER_EOF;
    }

    if( p_pkt->i_buffer < 4 )
    {
        block_Release( p_pkt );
        return VLC_DEMUXER_EGENERIC;
    }

    const uint8_t i_stream_id = p_pkt->p_buffer[3];
    switch( i_stream_id )
    {
    case PS_STREAM_ID_END_STREAM:
        block_Release( p_pkt );
        break;

    case PS_STREAM_ID_PACK_HEADER:
        if( !ps_pkt_parse_pack( p_pkt, &p_sys->i_pack_scr, &i_mux_rate ) )
        {
            if( p_sys->i_first_scr == VLC_TICK_INVALID )
                p_sys->i_first_scr = p_sys->i_pack_scr;
            CheckPCR( p_sys, p_demux->out, p_sys->i_pack_scr );
            p_sys->i_scr = p_sys->i_pack_scr;
            p_sys->i_lastpack_byte = vlc_stream_Tell( p_demux->s );
            if( !p_sys->b_have_pack ) p_sys->b_have_pack = true;
            /* done later on to work around bad vcd/svcd streams */
            /* es_out_SetPCR( p_demux->out, p_sys->i_scr ); */
            if( i_mux_rate > 0 ) p_sys->i_mux_rate = i_mux_rate;
        }
        block_Release( p_pkt );
        break;

    case PS_STREAM_ID_SYSTEM_HEADER:
        if( !ps_pkt_parse_system( p_pkt, &p_sys->psm, p_sys->tk ) )
        {
            int i;
            for( i = 0; i < PS_TK_COUNT; i++ )
            {
                ps_track_t *tk = &p_sys->tk[i];

                if( !tk->b_configured && tk->fmt.i_cat != UNKNOWN_ES )
                {
                    if( tk->b_seen )
                        tk->es = es_out_Add( p_demux->out, &tk->fmt );
                     /* else create when seeing packet */
                    tk->b_configured = true;
                }
            }
        }
        block_Release( p_pkt );
        break;

    case PS_STREAM_ID_MAP:
        if( p_sys->psm.i_version == 0xFFFF )
            msg_Dbg( p_demux, "contains a PSM");

        ps_psm_fill( &p_sys->psm, p_pkt, p_sys->tk, p_demux->out );
        block_Release( p_pkt );
        break;

    default:
        /* Reject non video/audio nor PES */
        if( i_stream_id < 0xC0 || i_stream_id > 0xEF )
        {
            block_Release( p_pkt );
            break;
        }
        /* fallthrough */
    case PS_STREAM_ID_PRIVATE_STREAM1:
    case PS_STREAM_ID_EXTENDED:
        {
            int i_id = ps_pkt_id( p_pkt );
            /* Small heuristic to improve MLP detection from AOB */
            if( i_id == 0xa001 &&
                p_sys->i_aob_mlp_count < 500 )
            {
                p_sys->i_aob_mlp_count++;
            }
            else if( i_id == 0xbda1 &&
                     p_sys->i_aob_mlp_count > 0 )
            {
                p_sys->i_aob_mlp_count--;
                i_id = 0xa001;
            }

            bool b_new = false;
            ps_track_t *tk = &p_sys->tk[ps_id_to_tk(i_id)];

            if( !tk->b_configured )
            {
                if( !ps_track_fill( tk, &p_sys->psm, i_id, p_pkt, false ) )
                {
                    /* No PSM and no probing yet */
                    if( p_sys->format == PSMF_PS )
                    {
                        if( tk->fmt.i_cat == VIDEO_ES )
                            tk->fmt.i_codec = VLC_CODEC_H264;
#if 0
                        if( i_stream_id == PS_STREAM_ID_PRIVATE_STREAM1 )
                        {
                            es_format_Change( &tk->fmt, AUDIO_ES, VLC_CODEC_ATRAC3P );
                            tk->fmt.audio.i_blockalign = 376;
                            tk->fmt.audio.i_channels = 2;
                            tk->fmt.audio.i_rate = 44100;
                        }
#endif
                    }

                    tk->es = es_out_Add( p_demux->out, &tk->fmt );
                    b_new = true;
                    tk->b_configured = true;
                }
                else
                {
                    msg_Dbg( p_demux, "es id=0x%x format unknown", i_id );
                }
            }

            /* Late creation from system header */
            if( !tk->b_seen && tk->b_configured && !tk->es && tk->fmt.i_cat != UNKNOWN_ES )
                tk->es = es_out_Add( p_demux->out, &tk->fmt );

            tk->b_seen = true;

            /* The popular VCD/SVCD subtitling WinSubMux does not
             * renumber the SCRs when merging subtitles into the PES */
            if( tk->b_seen && !p_sys->b_bad_scr &&
                ( tk->fmt.i_codec == VLC_CODEC_OGT ||
                  tk->fmt.i_codec == VLC_CODEC_CVD ) )
            {
                p_sys->b_bad_scr = true;
                p_sys->i_first_scr = VLC_TICK_INVALID;
            }

            if( p_sys->i_pack_scr != VLC_TICK_INVALID && !p_sys->b_bad_scr )
            {
                if( (tk->fmt.i_cat == AUDIO_ES || tk->fmt.i_cat == VIDEO_ES) &&
                    tk->i_first_pts != VLC_TICK_INVALID && tk->i_first_pts - p_sys->i_pack_scr > VLC_TICK_FROM_SEC(2))
                {
                    msg_Warn( p_demux, "Incorrect SCR timing offset by of %"PRId64 "ms, disabling",
                                       MS_FROM_VLC_TICK(tk->i_first_pts - p_sys->i_pack_scr) );
                    p_sys->b_bad_scr = true; /* Disable Offset SCR */
                    p_sys->i_first_scr = VLC_TICK_INVALID;
                }
                else
                    es_out_SetPCR( p_demux->out, p_sys->i_pack_scr );
            }

            if( tk->b_configured && tk->es &&
                !ps_pkt_parse_pes( VLC_OBJECT(p_demux), p_pkt, tk->i_skip ) )
            {
                if( tk->fmt.i_cat == AUDIO_ES || tk->fmt.i_cat == VIDEO_ES )
                {
                    if( !p_sys->b_bad_scr && p_sys->i_pack_scr != VLC_TICK_INVALID && p_pkt->i_pts != VLC_TICK_INVALID &&
                        p_sys->i_pack_scr > p_pkt->i_pts + VLC_TICK_FROM_MS(250) )
                    {
                        msg_Warn( p_demux, "Incorrect SCR timing in advance of %" PRId64 "ms, disabling",
                                           MS_FROM_VLC_TICK(p_sys->i_pack_scr - p_pkt->i_pts) );
                        p_sys->b_bad_scr = true;
                        p_sys->i_first_scr = VLC_TICK_INVALID;
                    }

                    if( (p_sys->b_bad_scr || !p_sys->b_have_pack) && !p_sys->i_scr_track_id )
                    {
                        p_sys->i_scr_track_id = tk->i_id;
                    }
                }

                if( ((!b_new && !p_sys->b_have_pack) || p_sys->b_bad_scr) &&
                    p_sys->i_scr_track_id == tk->i_id &&
                    p_pkt->i_pts != VLC_TICK_INVALID )
                {
                    /* A hack to sync the A/V on PES files. */
                    msg_Dbg( p_demux, "force SCR: %"PRId64, p_pkt->i_pts );
                    CheckPCR( p_sys, p_demux->out, p_pkt->i_pts );
                    p_sys->i_scr = p_pkt->i_pts;
                    if( p_sys->i_first_scr == VLC_TICK_INVALID )
                        p_sys->i_first_scr = p_sys->i_scr;
                    es_out_SetPCR( p_demux->out, p_pkt->i_pts );
                }

                if( tk->fmt.i_codec == VLC_CODEC_TELETEXT &&
                    p_pkt->i_pts == VLC_TICK_INVALID && p_sys->i_scr != VLC_TICK_INVALID )
                {
                    /* Teletext may have missing PTS (ETSI EN 300 472 Annexe A)
                     * In this case use the last SCR + 40ms */
                    p_pkt->i_pts = p_sys->i_scr + VLC_TICK_FROM_MS(40);
                }

                if( p_pkt->i_pts > p_sys->i_current_pts )
                {
                    p_sys->i_current_pts = p_pkt->i_pts;
                }

                if( tk->i_next_block_flags )
                {
                    p_pkt->i_flags = tk->i_next_block_flags;
                    tk->i_next_block_flags = 0;
                }
#if 0
                if( tk->fmt.i_codec == VLC_CODEC_ATRAC3P )
                {
                    p_pkt->p_buffer += 14;
                    p_pkt->i_buffer -= 14;
                }
#endif
                es_out_Send( p_demux->out, tk->es, p_pkt );
            }
            else
            {
                block_Release( p_pkt );
            }

            p_sys->i_pack_scr = VLC_TICK_INVALID;
        }
        break;
    }

    demux_UpdateTitleFromStream( p_demux );
    return VLC_DEMUXER_SUCCESS;
}
Exemple #16
0
/*****************************************************************************
 * Demux:
 *****************************************************************************/
static int Demux( demux_t *p_demux )
{
    demux_sys_t *p_sys = p_demux->p_sys;
    AVPacket    pkt;
    block_t     *p_frame;
    vlc_tick_t  i_start_time;

    /* Read a frame */
    int i_av_ret = av_read_frame( p_sys->ic, &pkt );
    if( i_av_ret )
    {
        /* Avoid EOF if av_read_frame returns AVERROR(EAGAIN) */
        if( i_av_ret == AVERROR(EAGAIN) )
            return 1;

        return 0;
    }
    if( pkt.stream_index < 0 || (unsigned) pkt.stream_index >= p_sys->i_tracks )
    {
        av_packet_unref( &pkt );
        return 1;
    }
    struct avformat_track_s *p_track = &p_sys->tracks[pkt.stream_index];
    const AVStream *p_stream = p_sys->ic->streams[pkt.stream_index];
    if( p_stream->time_base.den <= 0 )
    {
        msg_Warn( p_demux, "Invalid time base for the stream %d", pkt.stream_index );
        av_packet_unref( &pkt );
        return 1;
    }
    if( p_stream->codecpar->codec_id == AV_CODEC_ID_SSA )
    {
        p_frame = BuildSsaFrame( &pkt, p_sys->i_ssa_order++ );
        if( !p_frame )
        {
            av_packet_unref( &pkt );
            return 1;
        }
    }
    else if( p_stream->codecpar->codec_id == AV_CODEC_ID_DVB_SUBTITLE )
    {
        if( ( p_frame = block_Alloc( pkt.size + 3 ) ) == NULL )
        {
            av_packet_unref( &pkt );
            return 0;
        }
        p_frame->p_buffer[0] = 0x20;
        p_frame->p_buffer[1] = 0x00;
        memcpy( &p_frame->p_buffer[2], pkt.data, pkt.size );
        p_frame->p_buffer[p_frame->i_buffer - 1] = 0x3f;
    }
    else
    {
        if( ( p_frame = block_Alloc( pkt.size ) ) == NULL )
        {
            av_packet_unref( &pkt );
            return 0;
        }
        memcpy( p_frame->p_buffer, pkt.data, pkt.size );
    }

    if( pkt.flags & AV_PKT_FLAG_KEY )
        p_frame->i_flags |= BLOCK_FLAG_TYPE_I;

    /* Used to avoid timestamps overlow */
    if( p_sys->ic->start_time != (int64_t)AV_NOPTS_VALUE )
    {
        i_start_time = vlc_tick_from_frac(p_sys->ic->start_time, AV_TIME_BASE);
    }
    else
        i_start_time = 0;

    if( pkt.dts == (int64_t)AV_NOPTS_VALUE )
        p_frame->i_dts = VLC_TICK_INVALID;
    else
    {
        p_frame->i_dts = vlc_tick_from_frac( pkt.dts * p_stream->time_base.num, p_stream->time_base.den )
                - i_start_time + VLC_TICK_0;
    }

    if( pkt.pts == (int64_t)AV_NOPTS_VALUE )
        p_frame->i_pts = VLC_TICK_INVALID;
    else
    {
        p_frame->i_pts = vlc_tick_from_frac( pkt.pts * p_stream->time_base.num, p_stream->time_base.den )
                - i_start_time + VLC_TICK_0;
    }
    if( pkt.duration > 0 && p_frame->i_length <= 0 )
        p_frame->i_length = vlc_tick_from_samples(pkt.duration *
            p_stream->time_base.num,
            p_stream->time_base.den );

    /* Add here notoriously bugged file formats/samples */
    if( !strcmp( p_sys->fmt->name, "flv" ) )
    {
        /* FLV and video PTS */
        if( p_stream->codecpar->codec_type == AVMEDIA_TYPE_VIDEO &&
            pkt.dts != (int64_t)AV_NOPTS_VALUE && pkt.dts == pkt.pts )
                p_frame->i_pts = VLC_TICK_INVALID;

        /* Handle broken dts/pts increase with AAC. Duration is correct.
         * sky_the80s_aacplus.flv #8195 */
        if( p_stream->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
            p_stream->codecpar->codec_id == AV_CODEC_ID_AAC )
        {
            if( p_track->i_pcr != VLC_TICK_INVALID &&
                p_track->i_pcr + p_frame->i_length > p_frame->i_dts )
            {
                p_frame->i_dts = p_frame->i_pts = p_track->i_pcr + p_frame->i_length;
            }
        }
    }
#ifdef AVFORMAT_DEBUG
    msg_Dbg( p_demux, "tk[%d] dts=%"PRId64" pts=%"PRId64,
             pkt.stream_index, p_frame->i_dts, p_frame->i_pts );
#endif
    if( p_frame->i_dts != VLC_TICK_INVALID && p_track->p_es != NULL )
        p_track->i_pcr = p_frame->i_dts;

    vlc_tick_t i_ts_max = INT64_MIN;
    for( unsigned i = 0; i < p_sys->i_tracks; i++ )
    {
        if( p_sys->tracks[i].p_es != NULL )
            i_ts_max = __MAX( i_ts_max, p_sys->tracks[i].i_pcr );
    }

    vlc_tick_t i_ts_min = INT64_MAX;
    for( unsigned i = 0; i < p_sys->i_tracks; i++ )
    {
        if( p_sys->tracks[i].p_es != NULL &&
                p_sys->tracks[i].i_pcr != VLC_TICK_INVALID &&
                p_sys->tracks[i].i_pcr + VLC_TICK_FROM_SEC(10)>= i_ts_max )
            i_ts_min = __MIN( i_ts_min, p_sys->tracks[i].i_pcr );
    }
    if( i_ts_min >= p_sys->i_pcr && likely(i_ts_min != INT64_MAX) )
    {
        p_sys->i_pcr = i_ts_min;
        es_out_SetPCR( p_demux->out, p_sys->i_pcr );
        UpdateSeekPoint( p_demux, p_sys->i_pcr );
    }

    if( p_track->p_es != NULL )
        es_out_Send( p_demux->out, p_track->p_es, p_frame );
    else
        block_Release( p_frame );

    av_packet_unref( &pkt );
    return 1;
}
Exemple #17
0
/*****************************************************************************
 * Demux: reads and demuxes data packets
 *****************************************************************************
 * Returns -1 in case of error, 0 in case of EOF, 1 otherwise
 *****************************************************************************/
static int Demux( demux_t *p_demux)
{
    demux_sys_t *p_sys = p_demux->p_sys;
    block_t *p_block_in, *p_block_out;
    bool b_eof = false;

    p_block_in = vlc_stream_Block( p_demux->s, H26X_PACKET_SIZE );
    if( p_block_in == NULL )
    {
        b_eof = true;
    }
    else
    {
        p_block_in->i_dts = date_Get( &p_sys->dts );
    }

    while( (p_block_out = p_sys->p_packetizer->pf_packetize( p_sys->p_packetizer,
                                                             p_block_in ? &p_block_in : NULL )) )
    {
        while( p_block_out )
        {
            block_t *p_next = p_block_out->p_next;

            p_block_out->p_next = NULL;

            if( p_block_in )
            {
                p_block_in->i_dts = date_Get( &p_sys->dts );
                p_block_in->i_pts = VLC_TICK_INVALID;
            }

            if( p_sys->p_es == NULL )
            {
                p_sys->p_packetizer->fmt_out.b_packetized = true;
                p_sys->p_es = es_out_Add( p_demux->out, &p_sys->p_packetizer->fmt_out );
                if( !p_sys->p_es )
                {
                    block_ChainRelease( p_block_out );
                    return VLC_DEMUXER_EOF;
                }
            }

            /* h264 packetizer does merge multiple NAL into AU, but slice flag persists */
            bool frame = p_block_out->i_flags & BLOCK_FLAG_TYPE_MASK;
            const vlc_tick_t i_frame_dts = p_block_out->i_dts;
            const vlc_tick_t i_frame_length = p_block_out->i_length;
            es_out_Send( p_demux->out, p_sys->p_es, p_block_out );
            if( frame )
            {
                if( !p_sys->frame_rate_den )
                {
                    /* Use packetizer's one */
                    if( p_sys->p_packetizer->fmt_out.video.i_frame_rate_base &&
                        p_sys->p_packetizer->fmt_out.video.i_frame_rate )
                    {
                        p_sys->frame_rate_num = p_sys->p_packetizer->fmt_out.video.i_frame_rate;
                        p_sys->frame_rate_den = p_sys->p_packetizer->fmt_out.video.i_frame_rate_base;
                    }
                    else
                    {
                        p_sys->frame_rate_num = 25000;
                        p_sys->frame_rate_den = 1000;
                    }
                    date_Init( &p_sys->dts, 2 * p_sys->frame_rate_num, p_sys->frame_rate_den );
                    date_Set( &p_sys->dts, VLC_TICK_0 );
                    msg_Dbg( p_demux, "using %.2f fps", (double) p_sys->frame_rate_num / p_sys->frame_rate_den );
                }

                es_out_SetPCR( p_demux->out, date_Get( &p_sys->dts ) );
                unsigned i_nb_fields;
                if( i_frame_length > 0 )
                {
                    i_nb_fields = round( (double)i_frame_length * 2 * p_sys->frame_rate_num /
                                  ( p_sys->frame_rate_den * CLOCK_FREQ ) );
                }
                else i_nb_fields = 2;
                if( i_nb_fields <= 6 ) /* in the legit range */
                    date_Increment( &p_sys->dts, i_nb_fields );
                else /* Somehow some discontinuity */
                    date_Set( &p_sys->dts, i_frame_dts );
            }

            p_block_out = p_next;
        }
    }
    return (b_eof) ? VLC_DEMUXER_EOF : VLC_DEMUXER_SUCCESS;
}