Пример #1
0
/****************************************************************************
 * Packetize: the whole thing
 * Search for the startcodes 3 or more bytes
 * Feed ParseNALBlock ALWAYS with 4 byte startcode prepended NALs
 ****************************************************************************/
static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    block_t       *p_pic;

    if( !pp_block || !*pp_block ) return NULL;

    block_BytestreamPush( &p_sys->bytestream, *pp_block );

    for( ;; )
    {
        switch( p_sys->i_state )
        {
            case STATE_NOSYNC:
                /* Skip until 3 byte startcode 0 0 1 */
                if( block_FindStartcodeFromOffset( &p_sys->bytestream,
                      &p_sys->i_offset, p_sys->startcode+1, 3 ) == VLC_SUCCESS)
                {
                    p_sys->i_state = STATE_NEXT_SYNC;
                }

                if( p_sys->i_offset )
                {
                    /* skip the data */
                    block_SkipBytes( &p_sys->bytestream, p_sys->i_offset );
                    p_sys->i_offset = 0;
                    block_BytestreamFlush( &p_sys->bytestream );
                }

                if( p_sys->i_state != STATE_NEXT_SYNC )
                {
                    /* Need more data */
                    return NULL;
                }

                p_sys->i_offset = 1; /* To find next startcode */

            case STATE_NEXT_SYNC:
                /* Find the next 3 byte startcode 0 0 1*/
                if( block_FindStartcodeFromOffset( &p_sys->bytestream,
                      &p_sys->i_offset, p_sys->startcode+1, 3 ) != VLC_SUCCESS)
                {
                    /* Need more data */
                    return NULL;
                }

                /* Get the new fragment and set the pts/dts */
                p_pic = block_New( p_dec, p_sys->i_offset +1 );
                p_pic->i_pts = p_sys->bytestream.p_block->i_pts;
                p_pic->i_dts = p_sys->bytestream.p_block->i_dts;
                /* Force 4 byte startcode 0 0 0 1 */
                p_pic->p_buffer[0] = 0;

                block_GetBytes( &p_sys->bytestream, &p_pic->p_buffer[1],
                                p_pic->i_buffer-1 );

                /* Remove trailing 0 bytes */
                while( p_pic->i_buffer && (!p_pic->p_buffer[p_pic->i_buffer-1] ) )
                    p_pic->i_buffer--;
                p_sys->i_offset = 0;

                /* Parse the NAL */
                if( !( p_pic = ParseNALBlock( p_dec, p_pic ) ) )
                {
                    p_sys->i_state = STATE_NOSYNC;
                    break;
                }
#if 0
                msg_Dbg( p_dec, "pts="I64Fd" dts="I64Fd,
                         p_pic->i_pts, p_pic->i_dts );
#endif

                /* So p_block doesn't get re-added several times */
                *pp_block = block_BytestreamPop( &p_sys->bytestream );

                p_sys->i_state = STATE_NOSYNC;

                return p_pic;
        }
    }
}
Пример #2
0
/****************************************************************************
 * DecodeBlock: the whole thing
 ****************************************************************************
 * This function is called just after the thread is launched.
 ****************************************************************************/
static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    uint8_t p_header[VLC_A52_HEADER_SIZE];
    uint8_t *p_buf;
    block_t *p_out_buffer;

    if( !pp_block || !*pp_block ) return NULL;

    if( (*pp_block)->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
    {
        if( (*pp_block)->i_flags&BLOCK_FLAG_CORRUPTED )
        {
            p_sys->i_state = STATE_NOSYNC;
            block_BytestreamEmpty( &p_sys->bytestream );
        }
        date_Set( &p_sys->end_date, 0 );
        block_Release( *pp_block );
        return NULL;
    }

    if( !date_Get( &p_sys->end_date ) && (*pp_block)->i_pts <= VLC_TS_INVALID)
    {
        /* We've just started the stream, wait for the first PTS. */
        block_Release( *pp_block );
        return NULL;
    }

    block_BytestreamPush( &p_sys->bytestream, *pp_block );

    while( 1 )
    {
        switch( p_sys->i_state )
        {
        case STATE_NOSYNC:
            while( block_PeekBytes( &p_sys->bytestream, p_header, 2 )
                   == VLC_SUCCESS )
            {
                if( p_header[0] == 0x0b && p_header[1] == 0x77 )
                {
                    p_sys->i_state = STATE_SYNC;
                    break;
                }
                block_SkipByte( &p_sys->bytestream );
            }
            if( p_sys->i_state != STATE_SYNC )
            {
                block_BytestreamFlush( &p_sys->bytestream );

                /* Need more data */
                return NULL;
            }

        case STATE_SYNC:
            /* New frame, set the Presentation Time Stamp */
            p_sys->i_pts = p_sys->bytestream.p_block->i_pts;
            if( p_sys->i_pts > VLC_TS_INVALID &&
                p_sys->i_pts != date_Get( &p_sys->end_date ) )
            {
                date_Set( &p_sys->end_date, p_sys->i_pts );
            }
            p_sys->i_state = STATE_HEADER;

        case STATE_HEADER:
            /* Get A/52 frame header (VLC_A52_HEADER_SIZE bytes) */
            if( block_PeekBytes( &p_sys->bytestream, p_header,
                                 VLC_A52_HEADER_SIZE ) != VLC_SUCCESS )
            {
                /* Need more data */
                return NULL;
            }

            /* Check if frame is valid and get frame info */
            if( vlc_a52_header_Parse( &p_sys->frame, p_header, VLC_A52_HEADER_SIZE ) )
            {
                msg_Dbg( p_dec, "emulated sync word" );
                block_SkipByte( &p_sys->bytestream );
                p_sys->i_state = STATE_NOSYNC;
                break;
            }

            p_sys->i_state = STATE_NEXT_SYNC;

        case STATE_NEXT_SYNC:
            /* TODO: If pp_block == NULL, flush the buffer without checking the
             * next sync word */

            /* Check if next expected frame contains the sync word */
            if( block_PeekOffsetBytes( &p_sys->bytestream,
                                       p_sys->frame.i_size, p_header, 2 )
                != VLC_SUCCESS )
            {
                /* Need more data */
                return NULL;
            }

            if( p_sys->b_packetizer &&
                p_header[0] == 0 && p_header[1] == 0 )
            {
                /* A52 wav files and audio CD's use stuffing */
                p_sys->i_state = STATE_GET_DATA;
                break;
            }

            if( p_header[0] != 0x0b || p_header[1] != 0x77 )
            {
                msg_Dbg( p_dec, "emulated sync word "
                         "(no sync on following frame)" );
                p_sys->i_state = STATE_NOSYNC;
                block_SkipByte( &p_sys->bytestream );
                break;
            }
            p_sys->i_state = STATE_SEND_DATA;
            break;

        case STATE_GET_DATA:
            /* Make sure we have enough data.
             * (Not useful if we went through NEXT_SYNC) */
            if( block_WaitBytes( &p_sys->bytestream,
                                 p_sys->frame.i_size ) != VLC_SUCCESS )
            {
                /* Need more data */
                return NULL;
            }
            p_sys->i_state = STATE_SEND_DATA;

        case STATE_SEND_DATA:
            if( !(p_buf = GetOutBuffer( p_dec, &p_out_buffer )) )
            {
                //p_dec->b_error = true;
                return NULL;
            }

            /* Copy the whole frame into the buffer. When we reach this point
             * we already know we have enough data available. */
            block_GetBytes( &p_sys->bytestream,
                            p_buf, __MIN( p_sys->frame.i_size, p_out_buffer->i_buffer ) );

            /* Make sure we don't reuse the same pts twice */
            if( p_sys->i_pts == p_sys->bytestream.p_block->i_pts )
                p_sys->i_pts = p_sys->bytestream.p_block->i_pts = VLC_TS_INVALID;

            /* So p_block doesn't get re-added several times */
            *pp_block = block_BytestreamPop( &p_sys->bytestream );

            p_sys->i_state = STATE_NOSYNC;

            return p_out_buffer;
        }
    }
}
Пример #3
0
Файл: dts.c Проект: etix/vlc
static block_t *PacketizeBlock( decoder_t *p_dec, block_t **pp_block )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    uint8_t p_header[VLC_DTS_HEADER_SIZE];
    block_t *p_out_buffer;

    block_t *p_block = pp_block ? *pp_block : NULL;

    if( p_block )
    {
        if ( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) ) {
            /* First always drain complete blocks before discontinuity */
            block_t *p_drain = PacketizeBlock( p_dec, NULL );
            if(p_drain)
                return p_drain;

            PacketizeFlush( p_dec );

            if ( p_block->i_flags & BLOCK_FLAG_CORRUPTED ) {
                block_Release( p_block );
                return NULL;
            }
        }

        if ( !date_Get( &p_sys->end_date ) && p_block->i_pts <= VLC_TS_INVALID ) {
            /* We've just started the stream, wait for the first PTS. */
            block_Release( p_block );
            return NULL;
        }

        block_BytestreamPush( &p_sys->bytestream, p_block );
    }

    while( 1 )
    {
        switch( p_sys->i_state )
        {
        case STATE_NOSYNC:
            while( block_PeekBytes( &p_sys->bytestream, p_header, 6 )
                   == VLC_SUCCESS )
            {
                if( vlc_dts_header_IsSync( p_header, 6 ) )
                {
                    p_sys->i_state = STATE_SYNC;
                    break;
                }
                block_SkipByte( &p_sys->bytestream );
            }
            if( p_sys->i_state != STATE_SYNC )
            {
                block_BytestreamFlush( &p_sys->bytestream );

                /* Need more data */
                return NULL;
            }

        case STATE_SYNC:
            /* New frame, set the Presentation Time Stamp */
            p_sys->i_pts = p_sys->bytestream.p_block->i_pts;
            if( p_sys->i_pts > VLC_TS_INVALID &&
                p_sys->i_pts != date_Get( &p_sys->end_date ) )
            {
                date_Set( &p_sys->end_date, p_sys->i_pts );
            }
            p_sys->i_state = STATE_HEADER;

        case STATE_HEADER:
            /* Get DTS frame header (VLC_DTS_HEADER_SIZE bytes) */
            if( block_PeekBytes( &p_sys->bytestream, p_header,
                                 VLC_DTS_HEADER_SIZE ) != VLC_SUCCESS )
            {
                /* Need more data */
                return NULL;
            }

            /* Check if frame is valid and get frame info */
            if( vlc_dts_header_Parse( &p_sys->dts, p_header,
                                      VLC_DTS_HEADER_SIZE ) != VLC_SUCCESS )
            {
                msg_Dbg( p_dec, "emulated sync word" );
                block_SkipByte( &p_sys->bytestream );
                p_sys->i_state = STATE_NOSYNC;
                break;
            }

            if( p_sys->dts.b_substream  )
            {
                msg_Warn( p_dec, "substream without the paired core stream, "
                          "skip it" );
                p_sys->i_state = STATE_NOSYNC;
                if( block_SkipBytes( &p_sys->bytestream,
                                     p_sys->dts.i_frame_size ) != VLC_SUCCESS )
                    return NULL;
                break;
            }
            p_sys->i_input_size = p_sys->i_next_offset
                                = p_sys->dts.i_frame_size;
            p_sys->i_state = STATE_NEXT_SYNC;

        case STATE_NEXT_SYNC:
            /* Check if next expected frame contains the sync word */
            while( p_sys->i_state == STATE_NEXT_SYNC )
            {
                if( block_PeekOffsetBytes( &p_sys->bytestream,
                                           p_sys->i_next_offset, p_header,
                                           VLC_DTS_HEADER_SIZE )
                                           != VLC_SUCCESS )
                {
                    if( p_block == NULL ) /* drain */
                    {
                        p_sys->i_state = STATE_GET_DATA;
                        break;
                    }
                    /* Need more data */
                    return NULL;
                }

                if( p_header[0] == 0 )
                {
                    /* DTS wav files, audio CD's and some mkvs use stuffing */
                    p_sys->i_next_offset++;
                    continue;
                }

                if( !vlc_dts_header_IsSync( p_header, VLC_DTS_HEADER_SIZE ) )
                {
                    msg_Dbg( p_dec, "emulated sync word "
                             "(no sync on following frame)" );
                    p_sys->i_state = STATE_NOSYNC;
                    block_SkipByte( &p_sys->bytestream );
                    break;
                }

                /* Check if a DTS substream packet is located just after
                 * the core packet */
                if( p_sys->i_next_offset == p_sys->dts.i_frame_size )
                {
                    vlc_dts_header_t next_header;
                    if( vlc_dts_header_Parse( &next_header, p_header,
                                              VLC_DTS_HEADER_SIZE )
                        == VLC_SUCCESS && next_header.b_substream )
                    {
                        p_sys->i_input_size += next_header.i_frame_size;
                    }
                }
                p_sys->i_state = STATE_GET_DATA;
            }
            break;

        case STATE_GET_DATA:
            /* Make sure we have enough data. */
            if( block_WaitBytes( &p_sys->bytestream,
                                 p_sys->i_input_size ) != VLC_SUCCESS )
            {
                /* Need more data */
                return NULL;
            }
            p_sys->i_state = STATE_SEND_DATA;

        case STATE_SEND_DATA:
            if( !(p_out_buffer = GetOutBuffer( p_dec )) )
            {
                return NULL;
            }

            /* Copy the whole frame into the buffer. When we reach this point
             * we already know we have enough data available. */
            block_GetBytes( &p_sys->bytestream, p_out_buffer->p_buffer,
                            p_out_buffer->i_buffer );

            /* Make sure we don't reuse the same pts twice */
            if( p_sys->i_pts == p_sys->bytestream.p_block->i_pts )
                p_sys->i_pts = p_sys->bytestream.p_block->i_pts = VLC_TS_INVALID;

            if( p_sys->b_discontinuity )
            {
                p_sys->b_discontinuity = false;
                p_out_buffer->i_flags |= BLOCK_FLAG_DISCONTINUITY;
            }

            /* So p_block doesn't get re-added several times */
            if( pp_block )
                *pp_block = block_BytestreamPop( &p_sys->bytestream );

            p_sys->i_state = STATE_NOSYNC;

            return p_out_buffer;
        }
    }
}
Пример #4
0
Файл: dirac.c Проект: AsamQi/vlc
/***
 * Bytestream synchronizer
 * maps [Bytes] -> DataUnit
 */
static block_t *dirac_DoSync( decoder_t *p_dec )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    parse_info_t pu;

    static const uint8_t p_parsecode[4] = {'B','B','C','D'};
    do {
        switch( p_sys->i_state )
        {
        case NOT_SYNCED:
        {
            if( VLC_SUCCESS !=
                block_FindStartcodeFromOffset( &p_sys->bytestream, &p_sys->i_offset, p_parsecode, 4 ) )
            {
                /* p_sys->i_offset will have been set to:
                 *   end of bytestream - amount of prefix found
                 * can resume search from this point when more data arrives */
                return NULL;
            }
            /* candidate parse_code_prefix has been found at p_sys->i_offset */
            if( VLC_SUCCESS != block_PeekOffsetBytes( &p_sys->bytestream, p_sys->i_offset + 12, NULL, 0 ) )
            {
                /* insufficient data has been accumulated to fully extract
                 * a parse_info header. exit for now in the hope of more
                 * data later to retry at exactly the same point */
                return NULL;
            }
            p_sys->i_state = TRY_SYNC;
            break; /* candidate found, try to sync */
        }
        case SYNCED: /* -> TRY_SYNC | NOT_SYNCED */
            /* sanity: can only reach this after having extracted a DU,
             * which causes data to be consumed and local i_offset to be reset */
            assert( p_sys->i_offset == 0 );
            if( VLC_SUCCESS != block_PeekOffsetBytes( &p_sys->bytestream, 12, NULL, 0 ) )
            {
                /* insufficient data has been accumulated to fully extract
                 * a parse_info header, retry later */
                return NULL;
            }
            if( !dirac_UnpackParseInfo( &pu, &p_sys->bytestream, 0 )
             || !pu.u_next_offset || (p_sys->u_last_npo != pu.u_prev_offset) )
            {
                /* !a: not a valid parse info.
                 * !pu.u_next_offset: don't know the length of the data unit
                 *                    search for the next one that points back
                 *                    to this one to determine length.
                 * (p_sys->u_last_npo != pu.u_prev_offset): some desync
                 */
                p_sys->i_state = NOT_SYNCED;
                break;
            }
            if( pu.u_next_offset > 1024*1024 )
            {
                /* sanity check for erronious hugs next_parse_offsets
                 * (eg, 2^32-1) that would cause a very long wait
                 * and large space consumption: fall back to try sync */
                p_sys->i_state = TRY_SYNC;
                break;
            }
            /* check that the start of the next data unit is avaliable */
            if( VLC_SUCCESS !=
                block_PeekOffsetBytes( &p_sys->bytestream, pu.u_next_offset + 12, NULL, 0 ) )
            {
                return NULL; /* retry later */
            }
            /* attempt to synchronise backwards from pu.u_next_offset */
            p_sys->i_offset = pu.u_next_offset;
            /* fall through */
        case TRY_SYNC: /* -> SYNCED | NOT_SYNCED */
        {
            if( !p_sys->i_offset )
                goto sync_fail; /* if a is at start of bytestream, b can't be in buffer */

            parse_info_t pu_a;
            bool a = dirac_UnpackParseInfo( &pu_a, &p_sys->bytestream, p_sys->i_offset );
            if( !a || (pu_a.u_prev_offset > p_sys->i_offset) )
                goto sync_fail; /* b lies beyond start of bytestream: can't sync */

            if( !pu_a.u_prev_offset )
            {
                if( p_sys->i_state == TRY_SYNC )
                {
                    goto sync_fail; /* can't find different pu_b from pu_a */
                }
                /* state == SYNCED: already know where pu_b is.
                 * pu_a has probably been inserted by something that doesn't
                 * know what the last next_parse_offset was */
                pu_a.u_prev_offset = pu.u_next_offset;
            }

            parse_info_t *pu_b = &pu;
            bool b = dirac_UnpackParseInfo( pu_b, &p_sys->bytestream, p_sys->i_offset - pu_a.u_prev_offset );
            if( !b || (pu_b->u_next_offset && pu_a.u_prev_offset != pu_b->u_next_offset) )
            {
                /* if pu_b->u_next_offset = 0, have to assume we've synced, ie,
                 * just rely on finding a valid pu_b from pu_a. */
                goto sync_fail;
            }
            p_sys->u_last_npo = pu_b->u_next_offset;
            if( !pu_b->u_next_offset ) pu_b->u_next_offset = pu_a.u_prev_offset;
            /* offset was pointing at pu_a, rewind to point at pu_b */
            p_sys->i_offset -= pu_a.u_prev_offset;
            p_sys->i_state = SYNCED;
            break;
        }
sync_fail:
            if( p_sys->i_state == SYNCED ) p_sys->i_offset = 0;
            p_sys->i_offset++;
            p_sys->i_state = NOT_SYNCED;
            break; /* find somewhere else to try again */
        default:;
        }
    } while( SYNCED != p_sys->i_state );

    /*
     * synced, attempt to extract a data unit
     */

    /* recover any timestamps from the data that is about to be flushed */
    dirac_RecoverTimestamps( p_dec, p_sys->i_offset );

    /* flush everything up to the start of the DU */
    block_SkipBytes( &p_sys->bytestream, p_sys->i_offset );
    block_BytestreamFlush( &p_sys->bytestream );
    p_sys->i_offset = 0;

    /* setup the data unit buffer */
    block_t *p_block = block_Alloc( pu.u_next_offset );
    if( !p_block )
        return NULL;

    p_block->i_pts = p_sys->i_sync_pts;
    p_block->i_dts = p_sys->i_sync_dts;
    p_sys->i_sync_pts = p_sys->i_sync_dts = VLC_TS_INVALID;

    /* recover any new timestamps from the data that is about to be consumed */
    dirac_RecoverTimestamps( p_dec, p_sys->i_offset );

    block_GetBytes( &p_sys->bytestream, p_block->p_buffer, p_block->i_buffer );

    /* save parse offset in private area for later use */
    dirac_block_encap_t *p_dbe = dirac_NewBlockEncap( &p_block );
    if( p_dbe ) p_dbe->u_last_next_offset = pu.u_next_offset;

    return p_block;
}
Пример #5
0
Файл: a52.c Проект: IAPark/vlc
static block_t *PacketizeBlock( decoder_t *p_dec, block_t **pp_block )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    uint8_t p_header[VLC_A52_HEADER_SIZE];
    block_t *p_out_buffer;

    block_t *p_block = pp_block ? *pp_block : NULL;

    if( p_block )
    {
        if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY | BLOCK_FLAG_CORRUPTED) )
        {
            /* First always drain complete blocks before discontinuity */
            block_t *p_drain = PacketizeBlock( p_dec, NULL );
            if(p_drain)
                return p_drain;

            PacketizeFlush( p_dec );

            if( p_block->i_flags & BLOCK_FLAG_CORRUPTED )
            {
                block_Release( p_block );
                return NULL;
            }
        }

        if( !date_Get( &p_sys->end_date ) && p_block->i_pts <= VLC_TS_INVALID)
        {
            /* We've just started the stream, wait for the first PTS. */
            block_Release( p_block );
            return NULL;
        }

        block_BytestreamPush( &p_sys->bytestream, p_block );
    }

    while( 1 )
    {
        switch( p_sys->i_state )
        {
        case STATE_NOSYNC:
            while( block_PeekBytes( &p_sys->bytestream, p_header, 2 )
                   == VLC_SUCCESS )
            {
                if( p_header[0] == 0x0b && p_header[1] == 0x77 )
                {
                    p_sys->i_state = STATE_SYNC;
                    break;
                }
                block_SkipByte( &p_sys->bytestream );
            }
            if( p_sys->i_state != STATE_SYNC )
            {
                block_BytestreamFlush( &p_sys->bytestream );

                /* Need more data */
                return NULL;
            }

        case STATE_SYNC:
            /* New frame, set the Presentation Time Stamp */
            p_sys->i_pts = p_sys->bytestream.p_block->i_pts;
            if( p_sys->i_pts > VLC_TS_INVALID &&
                p_sys->i_pts != date_Get( &p_sys->end_date ) )
            {
                date_Set( &p_sys->end_date, p_sys->i_pts );
            }
            p_sys->i_state = STATE_HEADER;

        case STATE_HEADER:
            /* Get A/52 frame header (VLC_A52_HEADER_SIZE bytes) */
            if( block_PeekBytes( &p_sys->bytestream, p_header,
                                 VLC_A52_HEADER_SIZE ) != VLC_SUCCESS )
            {
                /* Need more data */
                return NULL;
            }

            /* Check if frame is valid and get frame info */
            vlc_a52_header_t a52;
            if( vlc_a52_header_Parse( &a52, p_header, VLC_A52_HEADER_SIZE ) )
            {
                msg_Dbg( p_dec, "emulated sync word" );
                block_SkipByte( &p_sys->bytestream );
                p_sys->i_state = STATE_NOSYNC;
                break;
            }

            if( a52.b_eac3 && a52.eac3.strmtyp != EAC3_STRMTYP_INDEPENDENT )
            {
                /* Use the channel configuration of the independent stream */
                p_sys->frame.i_samples = a52.i_samples;
                p_sys->frame.i_size = a52.i_size;
            }
            else
                p_sys->frame = a52;

            p_sys->i_state = STATE_NEXT_SYNC;

        case STATE_NEXT_SYNC:
            /* Check if next expected frame contains the sync word */
            if( block_PeekOffsetBytes( &p_sys->bytestream,
                                       p_sys->frame.i_size, p_header, 2 )
                != VLC_SUCCESS )
            {
                if( p_block == NULL ) /* drain */
                {
                    p_sys->i_state = STATE_GET_DATA;
                    break;
                }
                /* Need more data */
                return NULL;
            }

            if( p_header[0] == 0 && p_header[1] == 0 )
            {
                /* A52 wav files and audio CD's use stuffing */
                p_sys->i_state = STATE_GET_DATA;
                break;
            }

            if( p_header[0] != 0x0b || p_header[1] != 0x77 )
            {
                msg_Dbg( p_dec, "emulated sync word "
                         "(no sync on following frame)" );
                p_sys->i_state = STATE_NOSYNC;
                block_SkipByte( &p_sys->bytestream );
                break;
            }
            p_sys->i_state = STATE_GET_DATA;
            break;

        case STATE_GET_DATA:
            /* Make sure we have enough data. */
            if( block_WaitBytes( &p_sys->bytestream,
                                 p_sys->frame.i_size ) != VLC_SUCCESS )
            {
                /* Need more data */
                return NULL;
            }
            p_sys->i_state = STATE_SEND_DATA;

        case STATE_SEND_DATA:
            if( !(p_out_buffer = GetOutBuffer( p_dec )) )
            {
                return NULL;
            }

            /* Copy the whole frame into the buffer. When we reach this point
             * we already know we have enough data available. */
            block_GetBytes( &p_sys->bytestream, p_out_buffer->p_buffer,
                            __MIN( p_sys->frame.i_size, p_out_buffer->i_buffer ) );

            /* Make sure we don't reuse the same pts twice */
            if( p_sys->i_pts == p_sys->bytestream.p_block->i_pts )
                p_sys->i_pts = p_sys->bytestream.p_block->i_pts = VLC_TS_INVALID;

            if( p_sys->b_discontuinity )
            {
                p_out_buffer->i_flags |= BLOCK_FLAG_DISCONTINUITY;
                p_sys->b_discontuinity = false;
            }

            /* So p_block doesn't get re-added several times */
            if( pp_block )
                *pp_block = block_BytestreamPop( &p_sys->bytestream );

            p_sys->i_state = STATE_NOSYNC;

            return p_out_buffer;
        }
    }
}
Пример #6
0
/*****************************************************************************
 * Packetize:
 *****************************************************************************/
static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    block_t       *p_pic;

    if( pp_block == NULL || *pp_block == NULL )
    {
        return NULL;
    }

    if( (*pp_block)->i_flags & BLOCK_FLAG_DISCONTINUITY )
    {
        p_sys->i_state = STATE_NOSYNC;
        if( p_sys->p_frame ) block_ChainRelease( p_sys->p_frame );
        p_sys->p_frame = NULL;
        p_sys->pp_last = &p_sys->p_frame;
        p_sys->b_frame_slice = VLC_FALSE;
        block_Release( *pp_block );
        return NULL;
    }

    block_BytestreamPush( &p_sys->bytestream, *pp_block );

    while( 1 )
    {
        switch( p_sys->i_state )
        {

        case STATE_NOSYNC:
            if( block_FindStartcodeFromOffset( &p_sys->bytestream,
                    &p_sys->i_offset, p_sys->p_startcode, 3 ) == VLC_SUCCESS )
            {
                p_sys->i_state = STATE_NEXT_SYNC;
            }

            if( p_sys->i_offset )
            {
                block_SkipBytes( &p_sys->bytestream, p_sys->i_offset );
                p_sys->i_offset = 0;
                block_BytestreamFlush( &p_sys->bytestream );
            }

            if( p_sys->i_state != STATE_NEXT_SYNC )
            {
                /* Need more data */
                return NULL;
            }

            p_sys->i_offset = 1; /* To find next startcode */

        case STATE_NEXT_SYNC:
            /* TODO: If p_block == NULL, flush the buffer without checking the
             * next sync word */

            /* Find the next startcode */
            if( block_FindStartcodeFromOffset( &p_sys->bytestream,
                    &p_sys->i_offset, p_sys->p_startcode, 3 ) != VLC_SUCCESS )
            {
                /* Need more data */
                return NULL;
            }

            /* Get the new fragment and set the pts/dts */
            p_pic = block_New( p_dec, p_sys->i_offset );
            block_BytestreamFlush( &p_sys->bytestream );
            p_pic->i_pts = p_sys->bytestream.p_block->i_pts;
            p_pic->i_dts = p_sys->bytestream.p_block->i_dts;

            block_GetBytes( &p_sys->bytestream, p_pic->p_buffer,
                            p_pic->i_buffer );

            /* don't reuse the same timestamps several times */
            if( p_pic->i_buffer >= 4 && p_pic->p_buffer[3] == 0x00 )
            {
                /* We have a picture start code */
                p_sys->bytestream.p_block->i_pts = 0;
                p_sys->bytestream.p_block->i_dts = 0;
            }

            p_sys->i_offset = 0;

            /* Get picture if any */
            if( !( p_pic = ParseMPEGBlock( p_dec, p_pic ) ) )
            {
                p_sys->i_state = STATE_NOSYNC;
                break;
            }

            /* We've just started the stream, wait for the first PTS.
             * We discard here so we can still get the sequence header. */
            if( p_sys->i_dts <= 0 && p_sys->i_pts <= 0 &&
                p_sys->i_interpolated_dts <= 0 )
            {
                msg_Dbg( p_dec, "need a starting pts/dts" );
                p_sys->i_state = STATE_NOSYNC;
                block_Release( p_pic );
                break;
            }

            /* When starting the stream we can have the first frame with
             * a null DTS (i_interpolated_pts is initialized to 0) */
            if( !p_pic->i_dts ) p_pic->i_dts = p_pic->i_pts;

            /* So p_block doesn't get re-added several times */
            *pp_block = block_BytestreamPop( &p_sys->bytestream );

            p_sys->i_state = STATE_NOSYNC;

            return p_pic;
        }
    }
}
Пример #7
0
/****************************************************************************
 * Packetize: the whole thing
 ****************************************************************************/
static block_t *Packetize( decoder_t *p_dec, block_t **pp_block )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    block_t       *p_pic;

    if( !pp_block || !*pp_block ) return NULL;

    block_BytestreamPush( &p_sys->bytestream, *pp_block );

    for( ;; )
    {
        switch( p_sys->i_state )
        {
        case STATE_NOSYNC:
            if( block_FindStartcodeFromOffset( &p_sys->bytestream,
                                               &p_sys->i_offset, p_sys->startcode+1, 3 ) == VLC_SUCCESS)
            {
                p_sys->i_state = STATE_NEXT_SYNC;
            }

            if( p_sys->i_offset )
            {
                block_SkipBytes( &p_sys->bytestream, p_sys->i_offset );
                p_sys->i_offset = 0;
                block_BytestreamFlush( &p_sys->bytestream );
            }

            if( p_sys->i_state != STATE_NEXT_SYNC )
            {
                /* Need more data */
                return NULL;
            }

            p_sys->i_offset = 1; /* To find next startcode */

        case STATE_NEXT_SYNC:
            /* Find the next startcode */
            if( block_FindStartcodeFromOffset( &p_sys->bytestream,
                                               &p_sys->i_offset, p_sys->startcode, 3 ) != VLC_SUCCESS)
            {
                if( block_FindStartcodeFromOffset( &p_sys->bytestream,
                                                   &p_sys->i_offset, p_sys->startcode+1, 3 ) !=
                        VLC_SUCCESS )
                {
                    /* Need more data */
                    return NULL;
                }
            }

            /* Get the new fragment and set the pts/dts */
            p_pic = block_New( p_dec, p_sys->i_offset );
            p_pic->i_pts = p_sys->bytestream.p_block->i_pts;
            p_pic->i_dts = p_sys->bytestream.p_block->i_dts;

            block_GetBytes( &p_sys->bytestream, p_pic->p_buffer,
                            p_pic->i_buffer );

            p_sys->i_offset = 0;

            /* Parse the NAL */
            if( !( p_pic = ParseNALBlock( p_dec, p_pic ) ) )
            {
                p_sys->i_state = STATE_NOSYNC;
                break;
            }

            /* So p_block doesn't get re-added several times */
            *pp_block = block_BytestreamPop( &p_sys->bytestream );

            p_sys->i_state = STATE_NOSYNC;

            return p_pic;
        }
    }
}