Пример #1
0
static void* EncoderThread( void *obj )
{
    sout_stream_sys_t *p_sys = (sout_stream_sys_t*)obj;
    sout_stream_id_sys_t *id = p_sys->id_video;
    picture_t *p_pic = NULL;
    int canc = vlc_savecancel ();
    block_t *p_block = NULL;

    vlc_mutex_lock( &p_sys->lock_out );

    for( ;; )
    {
        while( !p_sys->b_abort &&
               (p_pic = picture_fifo_Pop( p_sys->pp_pics )) == NULL )
            vlc_cond_wait( &p_sys->cond, &p_sys->lock_out );

        if( p_pic )
        {
            /* release lock while encoding */
            vlc_mutex_unlock( &p_sys->lock_out );
            p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
            picture_Release( p_pic );
            vlc_mutex_lock( &p_sys->lock_out );

            block_ChainAppend( &p_sys->p_buffers, p_block );
        }

        if( p_sys->b_abort )
            break;
    }

    /*Encode what we have in the buffer on closing*/
    while( (p_pic = picture_fifo_Pop( p_sys->pp_pics )) != NULL )
    {
        p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
        picture_Release( p_pic );
        block_ChainAppend( &p_sys->p_buffers, p_block );
    }

    /*Now flush encoder*/
    do {
        p_block = id->p_encoder->pf_encode_video(id->p_encoder, NULL );
        block_ChainAppend( &p_sys->p_buffers, p_block );
    } while( p_block );

    vlc_mutex_unlock( &p_sys->lock_out );

    vlc_restorecancel (canc);

    return NULL;
}
Пример #2
0
block_t *scan_GetM3U( scan_t *p_scan )
{
    vlc_object_t *p_obj = p_scan->p_obj;
    block_t *p_playlist = NULL;

    if( p_scan->i_service <= 0 )
        return NULL;

    /* */
    qsort( p_scan->pp_service, p_scan->i_service, sizeof(scan_service_t*), ScanServiceCmp );

    /* */
    p_playlist = BlockString( "#EXTM3U\n\n" );/* */

    for( int i = 0; i < p_scan->i_service; i++ )
    {
        scan_service_t *s = p_scan->pp_service[i];

        if( s->type == SERVICE_UNKNOWN )
        {
            /* We should only select service that have been described by SDT */
            msg_Dbg( p_obj, "scan_GetM3U: ignoring service number %d", s->i_program );
            continue;
        }

        const char *psz_type;
        switch( s->type )
        {
        case SERVICE_DIGITAL_TELEVISION:       psz_type = "Digital television"; break;
        case SERVICE_DIGITAL_TELEVISION_AC_SD: psz_type = "Digital television advanced codec SD"; break;
        case SERVICE_DIGITAL_TELEVISION_AC_HD: psz_type = "Digital television advanced codec HD"; break;
        case SERVICE_DIGITAL_RADIO:            psz_type = "Digital radio"; break;
        default:
            psz_type = "Unknown";
            break;
        }
        msg_Warn( p_obj, "scan_GetM3U: service number %d type '%s' name '%s' channel %d cypted=%d| network_id %d (nit:%d sdt:%d)| f=%d bw=%d snr=%d",
                  s->i_program, psz_type, s->psz_name, s->i_channel, s->b_crypted,
                  s->i_network_id, s->i_nit_version, s->i_sdt_version,
                  s->cfg.i_frequency, s->cfg.i_bandwidth, s->i_snr );

        char *psz;
        if( asprintf( &psz, "#EXTINF:,,%s\n"
                        "#EXTVLCOPT:program=%d\n"
                        "dvb://frequency=%d:bandwidth=%d\n"
                        "\n",
                      s->psz_name && * s->psz_name ? s->psz_name : "Unknown",
                      s->i_program,
                      s->cfg.i_frequency, s->cfg.i_bandwidth ) < 0 )
            psz = NULL;
        if( psz )
        {
            block_t *p_block = BlockString( psz );
            if( p_block )
                block_ChainAppend( &p_playlist, p_block );
        }
    }

    return p_playlist ? block_ChainGather( p_playlist ) : NULL;
}
Пример #3
0
static block_t *PacketizeParse(void *p_private, bool *pb_ts_used, block_t *p_block)
{
    decoder_t *p_dec = p_private;
    decoder_sys_t *p_sys = p_dec->p_sys;

    block_t * p_nal = NULL;

    while (p_block->i_buffer > 5 && p_block->p_buffer[p_block->i_buffer-1] == 0x00 )
        p_block->i_buffer--;

    bs_t bs;
    bs_init(&bs, p_block->p_buffer+3, p_block->i_buffer-3);

    /* Get NALU type */
    uint32_t forbidden_zero_bit = bs_read1(&bs);

    if (forbidden_zero_bit)
    {
        msg_Err(p_dec,"Forbidden zero bit not null, corrupted NAL");
        p_sys->p_frame = NULL;
        p_sys->b_vcl = false;
        return NULL;
    }
    uint32_t nalu_type = bs_read(&bs,6);
    bs_skip(&bs, 9);

    if (nalu_type < VPS)
    {
        /* NAL is a VCL NAL */
        p_sys->b_vcl = true;

        uint32_t first_slice_in_pic = bs_read1(&bs);

        if (first_slice_in_pic && p_sys->p_frame)
        {
            p_nal = block_ChainGather(p_sys->p_frame);
            p_sys->p_frame = NULL;
        }

        block_ChainAppend(&p_sys->p_frame, p_block);
    }
    else
    {
        if (p_sys->b_vcl)
        {
            p_nal = block_ChainGather(p_sys->p_frame);
            p_nal->p_next = p_block;
            p_sys->p_frame = NULL;
            p_sys->b_vcl =false;
        }
        else
            p_nal = p_block;
    }

    *pb_ts_used = false;
    return p_nal;
}
Пример #4
0
static block_t *EncodeFrame( encoder_t *p_enc, block_t *p_block )
{
    if (!p_block) /* TODO: flush */
        return NULL;

    encoder_sys_t *p_sys = p_enc->p_sys;
    block_t *p_pcm_block;
    block_t *p_chain = NULL;
    unsigned int i_samples = p_block->i_buffer >> 2 /* s16l stereo */;
    mtime_t start_date = p_block->i_pts;
    start_date -= (mtime_t)i_samples * (mtime_t)1000000 / (mtime_t)p_enc->fmt_out.audio.i_rate;

    VLC_UNUSED(p_enc);

    do {
        p_pcm_block = GetPCM( p_enc, p_block );
        if( !p_pcm_block )
            break;

        p_block = NULL; /* we don't need it anymore */
        int16_t pcm_planar_buf[SHINE_MAX_SAMPLES * 2];
        int16_t *pcm_planar_buf_chans[2] = {
            &pcm_planar_buf[0],
            &pcm_planar_buf[p_sys->samples_per_frame],
        };
        aout_Deinterleave( pcm_planar_buf, p_pcm_block->p_buffer,
                p_sys->samples_per_frame, p_enc->fmt_in.audio.i_channels, p_enc->fmt_in.i_codec);

        long written;
        unsigned char *buf = shine_encode_buffer(p_sys->s, pcm_planar_buf_chans, &written);
        block_Release( p_pcm_block );

        if (written <= 0)
            break;

        block_t *p_mp3_block = block_Alloc( written );
        if( !p_mp3_block )
            break;

        memcpy( p_mp3_block->p_buffer, buf, written );

        /* date management */
        p_mp3_block->i_length = p_sys->samples_per_frame * 1000000 /
            p_enc->fmt_out.audio.i_rate;

        start_date += p_mp3_block->i_length;
        p_mp3_block->i_dts = p_mp3_block->i_pts = start_date;

        p_mp3_block->i_nb_samples = p_sys->samples_per_frame;

        block_ChainAppend( &p_chain, p_mp3_block );

    } while( p_pcm_block );

    return p_chain;
}
Пример #5
0
/****************************************************************************
 * PacketizeAVC1: Takes VCL blocks of data and creates annexe B type NAL stream
 * Will always use 4 byte 0 0 0 1 startcodes
 * Will prepend a SPS and PPS before each keyframe
 ****************************************************************************/
static block_t *PacketizeAVC1( decoder_t *p_dec, block_t **pp_block )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    block_t       *p_block;
    block_t       *p_ret = NULL;
    uint8_t       *p;

    if( !pp_block || !*pp_block )
        return NULL;
    if( (*pp_block)->i_flags&(BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
    {
        block_Release( *pp_block );
        return NULL;
    }

    p_block = *pp_block;
    *pp_block = NULL;

    for( p = p_block->p_buffer; p < &p_block->p_buffer[p_block->i_buffer]; )
    {
        block_t *p_pic;
        bool b_dummy;
        int i_size = 0;
        int i;

        for( i = 0; i < p_sys->i_avcC_length_size; i++ )
        {
            i_size = (i_size << 8) | (*p++);
        }

        if( i_size <= 0 ||
            i_size > ( p_block->p_buffer + p_block->i_buffer - p ) )
        {
            msg_Err( p_dec, "Broken frame : size %d is too big", i_size );
            break;
        }

        block_t *p_part = CreateAnnexbNAL( p_dec, p, i_size );
        if( !p_part )
            break;

        p_part->i_dts = p_block->i_dts;
        p_part->i_pts = p_block->i_pts;

        /* Parse the NAL */
        if( ( p_pic = ParseNALBlock( p_dec, &b_dummy, p_part ) ) )
        {
            block_ChainAppend( &p_ret, p_pic );
        }
        p += i_size;
    }
    block_Release( p_block );

    return p_ret;
}
Пример #6
0
int transcode_audio_process( sout_stream_t *p_stream,
                                    sout_stream_id_t *id,
                                    block_t *in, block_t **out )
{
    sout_stream_sys_t *p_sys = p_stream->p_sys;
    block_t *p_block, *p_audio_buf;
    *out = NULL;

    while( (p_audio_buf = id->p_decoder->pf_decode_audio( id->p_decoder,
                                                          &in )) )
    {
        sout_UpdateStatistic( p_stream->p_sout, SOUT_STATISTIC_DECODED_AUDIO, 1 );
        if( p_sys->b_master_sync )
        {
            mtime_t i_dts = date_Get( &id->interpolated_pts ) + 1;
            if ( p_audio_buf->i_pts - i_dts > MASTER_SYNC_MAX_DRIFT
                  || p_audio_buf->i_pts - i_dts < -MASTER_SYNC_MAX_DRIFT )
            {
                msg_Dbg( p_stream, "drift is too high, resetting master sync" );
                date_Set( &id->interpolated_pts, p_audio_buf->i_pts );
                i_dts = p_audio_buf->i_pts + 1;
            }
            p_sys->i_master_drift = p_audio_buf->i_pts - i_dts;
            date_Increment( &id->interpolated_pts, p_audio_buf->i_nb_samples );
            p_audio_buf->i_pts -= p_sys->i_master_drift;
        }

        p_audio_buf->i_dts = p_audio_buf->i_pts;

        /* Run filter chain */
        if( id->p_uf_chain )
        {
            p_audio_buf = filter_chain_AudioFilter( id->p_uf_chain,
                                                    p_audio_buf );
            if( !p_audio_buf )
                abort();
        }

        p_audio_buf = filter_chain_AudioFilter( id->p_f_chain, p_audio_buf );
        if( !p_audio_buf )
            abort();

        p_audio_buf->i_dts = p_audio_buf->i_pts;

        audio_timer_start( id->p_encoder );
        p_block = id->p_encoder->pf_encode_audio( id->p_encoder, p_audio_buf );
        audio_timer_stop( id->p_encoder );

        block_ChainAppend( out, p_block );
        block_Release( p_audio_buf );
    }

    return VLC_SUCCESS;
}
Пример #7
0
static bool RemainAdd( stream_t *p_stream, const uint8_t *p_data, size_t i_size )
{
    stream_sys_t *p_sys = p_stream->p_sys;
    if ( i_size == 0 )
        return true;
    block_t *p_block = block_Alloc( i_size );
    if ( !p_block )
        return false;
    memcpy( p_block->p_buffer, p_data, i_size );
    p_block->i_buffer = i_size;
    block_ChainAppend( & p_sys->remain.p_list, p_block );
    p_sys->remain.i_size += i_size;
    return true;
}
Пример #8
0
static void* EncoderThread( vlc_object_t* p_this )
{
    sout_stream_sys_t *p_sys = (sout_stream_sys_t*)p_this;
    sout_stream_id_t *id = p_sys->id_video;
    picture_t *p_pic;
    int canc = vlc_savecancel ();

    while( vlc_object_alive (p_sys) && !p_sys->b_error )
    {
        block_t *p_block;

        vlc_mutex_lock( &p_sys->lock_out );
        while( p_sys->i_last_pic == p_sys->i_first_pic )
        {
            vlc_cond_wait( &p_sys->cond, &p_sys->lock_out );
            if( !vlc_object_alive (p_sys) || p_sys->b_error ) break;
        }
        if( !vlc_object_alive (p_sys) || p_sys->b_error )
        {
            vlc_mutex_unlock( &p_sys->lock_out );
            break;
        }

        p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
        p_sys->i_first_pic %= PICTURE_RING_SIZE;
        vlc_mutex_unlock( &p_sys->lock_out );

        video_timer_start( id->p_encoder );
        p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
        video_timer_stop( id->p_encoder );

        vlc_mutex_lock( &p_sys->lock_out );
        block_ChainAppend( &p_sys->p_buffers, p_block );

        vlc_mutex_unlock( &p_sys->lock_out );
        picture_Release( p_pic );
    }

    while( p_sys->i_last_pic != p_sys->i_first_pic )
    {
        p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
        p_sys->i_first_pic %= PICTURE_RING_SIZE;
        picture_Release( p_pic );
    }
    block_ChainRelease( p_sys->p_buffers );

    vlc_restorecancel (canc);
    return NULL;
}
Пример #9
0
static block_t *Encode( encoder_t *p_enc, aout_buffer_t *p_aout_buf )
{
    encoder_sys_t *p_sys = p_enc->p_sys;
    int16_t *p_buffer = (int16_t *)p_aout_buf->p_buffer;
    int i_nb_samples = p_aout_buf->i_nb_samples;
    block_t *p_chain = NULL;
    mtime_t i_computed_pts = p_aout_buf->start_date -
                             (mtime_t)1000000 * (mtime_t)p_sys->i_nb_samples /
                             (mtime_t)p_enc->fmt_in.audio.i_rate;

    if ( aout_DateGet( &p_sys->pts ) - i_computed_pts > 10000 ||
            aout_DateGet( &p_sys->pts ) - i_computed_pts < -10000 )
    {
        msg_Dbg( p_enc, "resetting audio date" );
        aout_DateSet( &p_sys->pts, i_computed_pts );
    }

    while ( p_sys->i_nb_samples + i_nb_samples >= MPEG_FRAME_SIZE )
    {
        int i_used;
        block_t *p_block;

        Uninterleave( p_enc, p_buffer, MPEG_FRAME_SIZE - p_sys->i_nb_samples );
        i_nb_samples -= MPEG_FRAME_SIZE - p_sys->i_nb_samples;
        p_buffer += (MPEG_FRAME_SIZE - p_sys->i_nb_samples) * 2;

        toolame_encode_buffer( p_sys->p_toolame, p_sys->p_left,
                               p_sys->p_right, MPEG_FRAME_SIZE,
                               p_sys->p_out_buffer, MAX_CODED_FRAME_SIZE,
                               &i_used );
        p_sys->i_nb_samples = 0;
        p_block = block_New( p_enc, i_used );
        p_enc->p_vlc->pf_memcpy( p_block->p_buffer, p_sys->p_out_buffer,
                                 i_used );
        p_block->i_length = (mtime_t)1000000 *
                            (mtime_t)MPEG_FRAME_SIZE / (mtime_t)p_enc->fmt_in.audio.i_rate;
        p_block->i_dts = p_block->i_pts = aout_DateGet( &p_sys->pts );
        aout_DateIncrement( &p_sys->pts, MPEG_FRAME_SIZE );
        block_ChainAppend( &p_chain, p_block );
    }

    if ( i_nb_samples )
    {
        Uninterleave( p_enc, p_buffer, i_nb_samples );
        p_sys->i_nb_samples += i_nb_samples;
    }

    return p_chain;
}
Пример #10
0
static block_t *Encode( encoder_t *p_enc, block_t *p_aout_buf )
{
    encoder_sys_t *p_sys = p_enc->p_sys;

    /* FIXME:p_aout_buf is NULL when it's time to flush, does twolame has buffer to flush?*/
    if( unlikely( !p_aout_buf ) ) return NULL;

    int16_t *p_buffer = (int16_t *)p_aout_buf->p_buffer;
    int i_nb_samples = p_aout_buf->i_nb_samples;
    block_t *p_chain = NULL;

    p_sys->i_pts = p_aout_buf->i_pts -
                (mtime_t)1000000 * (mtime_t)p_sys->i_nb_samples /
                (mtime_t)p_enc->fmt_out.audio.i_rate;

    while ( p_sys->i_nb_samples + i_nb_samples >= MPEG_FRAME_SIZE )
    {
        int i_used;
        block_t *p_block;

        Bufferize( p_enc, p_buffer, MPEG_FRAME_SIZE - p_sys->i_nb_samples );
        i_nb_samples -= MPEG_FRAME_SIZE - p_sys->i_nb_samples;
        p_buffer += (MPEG_FRAME_SIZE - p_sys->i_nb_samples) * 2;

        i_used = twolame_encode_buffer_interleaved( p_sys->p_twolame,
                               p_sys->p_buffer, MPEG_FRAME_SIZE,
                               p_sys->p_out_buffer, MAX_CODED_FRAME_SIZE );
        p_sys->i_nb_samples = 0;
        p_block = block_Alloc( i_used );
        memcpy( p_block->p_buffer, p_sys->p_out_buffer, i_used );
        p_block->i_length = (mtime_t)1000000 *
                (mtime_t)MPEG_FRAME_SIZE / (mtime_t)p_enc->fmt_out.audio.i_rate;
        p_block->i_dts = p_block->i_pts = p_sys->i_pts;
        p_sys->i_pts += p_block->i_length;
        block_ChainAppend( &p_chain, p_block );
    }

    if ( i_nb_samples )
    {
        Bufferize( p_enc, p_buffer, i_nb_samples );
        p_sys->i_nb_samples += i_nb_samples;
    }

    return p_chain;
}
Пример #11
0
/*****************************************************************************
 * Send: Process an input packet
 *****************************************************************************/
static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
                 block_t *p_buffer )
{
    sout_stream_sys_t *p_sys = p_stream->p_sys;

    if ( !id->id )
    {
        block_Release( p_buffer );
        return VLC_EGENERIC;
    }

    if ( !id->b_switcher_video && !id->b_switcher_audio )
    {
        return p_sys->p_out->pf_send( p_sys->p_out, id->id, p_buffer );
    }

    block_ChainAppend( &id->p_queued, p_buffer );

    if ( id->b_switcher_video )
    {
        /* Check for commands for every video frame. */
        NetCommand( p_stream );

        while ( id->p_queued != NULL )
        {
            mtime_t i_dts = 0;
            int i;

            if ( p_sys->i_old_cmd != p_sys->i_cmd )
            {
                i_dts = VideoCommand( p_stream, id );
            }

            i_dts = Process( p_stream, id, i_dts );

            for ( i = 0; i < MAX_AUDIO; i++ )
            {
                if ( p_sys->pp_audio_ids[i] != NULL )
                    Process( p_stream, p_sys->pp_audio_ids[i], i_dts );
            }
        }
    }

    return VLC_SUCCESS;
}
Пример #12
0
static void* EncoderThread( void *obj )
{
    sout_stream_sys_t *p_sys = (sout_stream_sys_t*)obj;
    sout_stream_id_t *id = p_sys->id_video;
    picture_t *p_pic;
    int canc = vlc_savecancel ();

    for( ;; )
    {
        block_t *p_block;

        vlc_mutex_lock( &p_sys->lock_out );
        while( !p_sys->b_abort && p_sys->i_last_pic == p_sys->i_first_pic )
            vlc_cond_wait( &p_sys->cond, &p_sys->lock_out );

        if( p_sys->b_abort )
        {
            vlc_mutex_unlock( &p_sys->lock_out );
            break;
        }

        p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
        p_sys->i_first_pic %= PICTURE_RING_SIZE;
        vlc_mutex_unlock( &p_sys->lock_out );

        p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );

        vlc_mutex_lock( &p_sys->lock_out );
        block_ChainAppend( &p_sys->p_buffers, p_block );

        vlc_mutex_unlock( &p_sys->lock_out );
        picture_Release( p_pic );
    }

    while( p_sys->i_last_pic != p_sys->i_first_pic )
    {
        p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
        p_sys->i_first_pic %= PICTURE_RING_SIZE;
        picture_Release( p_pic );
    }
    block_ChainRelease( p_sys->p_buffers );

    vlc_restorecancel (canc);
    return NULL;
}
Пример #13
0
static block_t *EncodeFrame( encoder_t *p_enc, aout_buffer_t *p_block )
{
    block_t *p_pcm_block;
    block_t *p_chain = NULL;
    unsigned int i_samples = p_block->i_buffer >> 2 /* s16l stereo */;
    mtime_t start_date = p_block->i_pts;
    start_date -= (mtime_t)i_samples * (mtime_t)1000000 / (mtime_t)p_enc->fmt_out.audio.i_rate;

    VLC_UNUSED(p_enc);

    do {
        p_pcm_block = GetPCM( p_enc, p_block );
        if( !p_pcm_block )
            break;

        p_block = NULL; /* we don't need it anymore */

        uint32_t enc_buffer[16384]; /* storage for 65536 Bytes XXX: too much */
        struct enc_chunk_hdr *chunk = (void*) enc_buffer;
        chunk->enc_data = ENC_CHUNK_SKIP_HDR(chunk->enc_data, chunk);

        encode_frame( (char*)p_pcm_block->p_buffer, chunk );
        block_Release( p_pcm_block );

        block_t *p_mp3_block = block_New( p_enc, chunk->enc_size );
        if( !p_mp3_block )
            break;

        vlc_memcpy( p_mp3_block->p_buffer, chunk->enc_data, chunk->enc_size );

        /* date management */
        p_mp3_block->i_length = SAMP_PER_FRAME1 * 1000000 /
            p_enc->fmt_out.audio.i_rate;

        start_date += p_mp3_block->i_length;
        p_mp3_block->i_dts = p_mp3_block->i_pts = start_date;

        p_mp3_block->i_nb_samples = SAMP_PER_FRAME1;

        block_ChainAppend( &p_chain, p_mp3_block );

    } while( p_pcm_block );

    return p_chain;
}
Пример #14
0
Файл: osd.c Проект: 0xheart0/vlc
int transcode_osd_process( sout_stream_t *p_stream, sout_stream_id_sys_t *id,
                                  block_t *in, block_t **out )
{
    sout_stream_sys_t *p_sys = p_stream->p_sys;
    subpicture_t *p_subpic = NULL;

    /* Check if we have a subpicture to send */
    if( p_sys->p_spu && in->i_dts > VLC_TS_INVALID )
    {
        video_format_t fmt;
        video_format_Init( &fmt, 0 );
        video_format_Setup( &fmt, 0, 720, 576, 720, 576, 1, 1 );
        p_subpic = spu_Render( p_sys->p_spu, NULL, &fmt, &fmt, in->i_dts, in->i_dts, false );
    }
    else
    {
        msg_Warn( p_stream, "spu channel not initialized, doing it now" );
        if( !p_sys->p_spu )
            p_sys->p_spu = spu_Create( p_stream );
    }

    if( p_subpic )
    {
        block_t *p_block = NULL;

        if( p_sys->b_master_sync && p_sys->i_master_drift )
        {
            p_subpic->i_start -= p_sys->i_master_drift;
            if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
        }

        p_block = id->p_encoder->pf_encode_sub( id->p_encoder, p_subpic );
        subpicture_Delete( p_subpic );
        if( p_block )
        {
            p_block->i_dts = p_block->i_pts = in->i_dts;
            block_ChainAppend( out, p_block );
            return VLC_SUCCESS;
        }
    }
    return VLC_EGENERIC;
}
Пример #15
0
/****************************************************************************
 * PacketizeAVC1: Takes VCL blocks of data and creates annexe B type NAL stream
 * Will always use 4 byte 0 0 0 1 startcodes
 * Will prepend a SPS and PPS before each keyframe
 ****************************************************************************/
static block_t *PacketizeAVC1( decoder_t *p_dec, block_t **pp_block )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    block_t       *p_block;
    block_t       *p_ret = NULL;
    uint8_t       *p;

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

    p_block = *pp_block;
    *pp_block = NULL;

    for( p = p_block->p_buffer; p < &p_block->p_buffer[p_block->i_buffer]; )
    {
        block_t *p_pic;
        int i_size = 0;
        int i;

        for( i = 0; i < p_sys->i_avcC_length_size; i++ )
        {
            i_size = (i_size << 8) | (*p++);
        }

        if( i_size > 0 )
        {
            block_t *p_part = nal_get_annexeb( p_dec, p, i_size );

            p_part->i_dts = p_block->i_dts;
            p_part->i_pts = p_block->i_pts;

            /* Parse the NAL */
            if( ( p_pic = ParseNALBlock( p_dec, p_part ) ) )
            {
                block_ChainAppend( &p_ret, p_pic );
            }
        }
        p += i_size;
    }
    block_Release( p_block );

    return p_ret;
}
Пример #16
0
static block_t *Encode( encoder_t *p_enc, aout_buffer_t *p_aout_buf )
{
    encoder_sys_t *p_sys = p_enc->p_sys;
    int16_t *p_buffer = (int16_t *)p_aout_buf->p_buffer;
    int i_nb_samples = p_aout_buf->i_nb_samples;
    block_t *p_chain = NULL;

    p_sys->i_pts = p_aout_buf->start_date -
                (mtime_t)1000000 * (mtime_t)p_sys->i_nb_samples /
                (mtime_t)p_enc->fmt_out.audio.i_rate;

    while ( p_sys->i_nb_samples + i_nb_samples >= MPEG_FRAME_SIZE )
    {
        int i_used;
        block_t *p_block;

        Bufferize( p_enc, p_buffer, MPEG_FRAME_SIZE - p_sys->i_nb_samples );
        i_nb_samples -= MPEG_FRAME_SIZE - p_sys->i_nb_samples;
        p_buffer += (MPEG_FRAME_SIZE - p_sys->i_nb_samples) * 2;

        i_used = twolame_encode_buffer_interleaved( p_sys->p_twolame,
                               p_sys->p_buffer, MPEG_FRAME_SIZE,
                               p_sys->p_out_buffer, MAX_CODED_FRAME_SIZE );
        p_sys->i_nb_samples = 0;
        p_block = block_New( p_enc, i_used );
        vlc_memcpy( p_block->p_buffer, p_sys->p_out_buffer, i_used );
        p_block->i_length = (mtime_t)1000000 *
                (mtime_t)MPEG_FRAME_SIZE / (mtime_t)p_enc->fmt_out.audio.i_rate;
        p_block->i_dts = p_block->i_pts = p_sys->i_pts;
        p_sys->i_pts += p_block->i_length;
        block_ChainAppend( &p_chain, p_block );
    }

    if ( i_nb_samples )
    {
        Bufferize( p_enc, p_buffer, i_nb_samples );
        p_sys->i_nb_samples += i_nb_samples;
    }

    return p_chain;
}
Пример #17
0
Файл: spu.c Проект: qdk0901/vlc
int transcode_spu_process( sout_stream_t *p_stream,
                                  sout_stream_id_sys_t *id,
                                  block_t *in, block_t **out )
{
    sout_stream_sys_t *p_sys = p_stream->p_sys;
    subpicture_t *p_subpic;
    *out = NULL;

    p_subpic = id->p_decoder->pf_decode_sub( id->p_decoder, &in );
    if( !p_subpic )
    {
        /* We just don't have anything to handle now, go own*/
        return VLC_SUCCESS;
    }

    if( p_sys->b_master_sync && p_sys->i_master_drift )
    {
        p_subpic->i_start -= p_sys->i_master_drift;
        if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
    }

    if( p_sys->b_soverlay )
    {
        spu_PutSubpicture( p_sys->p_spu, p_subpic );
        return VLC_SUCCESS;
    }
    else
    {
        block_t *p_block;

        p_block = id->p_encoder->pf_encode_sub( id->p_encoder, p_subpic );
        subpicture_Delete( p_subpic );
        if( p_block )
        {
            block_ChainAppend( out, p_block );
            return VLC_SUCCESS;
        }
    }

    return VLC_EGENERIC;
}
Пример #18
0
int transcode_spu_process( sout_stream_t *p_stream,
                                  sout_stream_id_t *id,
                                  block_t *in, block_t **out )
{
    sout_stream_sys_t *p_sys = p_stream->p_sys;
    subpicture_t *p_subpic;
    *out = NULL;

    p_subpic = id->p_decoder->pf_decode_sub( id->p_decoder, &in );
    if( !p_subpic )
        return VLC_EGENERIC;

    sout_UpdateStatistic( p_stream->p_sout, SOUT_STATISTIC_DECODED_SUBTITLE, 1 );

    if( p_sys->b_master_sync && p_sys->i_master_drift )
    {
        p_subpic->i_start -= p_sys->i_master_drift;
        if( p_subpic->i_stop ) p_subpic->i_stop -= p_sys->i_master_drift;
    }

    if( p_sys->b_soverlay )
    {
        spu_PutSubpicture( p_sys->p_spu, p_subpic );
    }
    else
    {
        block_t *p_block;

        p_block = id->p_encoder->pf_encode_sub( id->p_encoder, p_subpic );
        spu_del_buffer( id->p_decoder, p_subpic );
        if( p_block )
        {
            block_ChainAppend( out, p_block );
            return VLC_SUCCESS;
        }
    }

    return VLC_EGENERIC;
}
Пример #19
0
Файл: video.c Проект: AsamQi/vlc
static void* EncoderThread( void *obj )
{
    sout_stream_sys_t *p_sys = (sout_stream_sys_t*)obj;
    sout_stream_id_t *id = p_sys->id_video;
    picture_t *p_pic;
    int canc = vlc_savecancel ();

    for( ;; )
    {
        block_t *p_block;

        vlc_mutex_lock( &p_sys->lock_out );
        while( !p_sys->b_abort &&
               (p_pic = picture_fifo_Pop( p_sys->pp_pics )) == NULL )
            vlc_cond_wait( &p_sys->cond, &p_sys->lock_out );

        if( p_sys->b_abort )
        {
            vlc_mutex_unlock( &p_sys->lock_out );
            break;
        }
        vlc_mutex_unlock( &p_sys->lock_out );

        p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );

        vlc_mutex_lock( &p_sys->lock_out );
        block_ChainAppend( &p_sys->p_buffers, p_block );

        vlc_mutex_unlock( &p_sys->lock_out );
        picture_Release( p_pic );
    }

    block_ChainRelease( p_sys->p_buffers );

    vlc_restorecancel (canc);
    return NULL;
}
Пример #20
0
Файл: opus.c Проект: MSalmo/vlc
static block_t *Encode(encoder_t *enc, block_t *buf)
{
    encoder_sys_t *sys = enc->p_sys;

    if (!buf)
        return NULL;

    mtime_t i_pts = buf->i_pts -
                (mtime_t) CLOCK_FREQ * (mtime_t) sys->i_samples_delay /
                (mtime_t) enc->fmt_in.audio.i_rate;

    sys->i_samples_delay += buf->i_nb_samples;

    block_t *result = NULL;
    unsigned src_start = 0;
    unsigned padding_start = 0;
    /* The maximum Opus frame size is 1275 bytes + TOC sequence length. */
    const unsigned OPUS_MAX_ENCODED_BYTES = ((1275 + 3) * sys->nb_streams) - 2;

    while (sys->i_nb_samples + buf->i_nb_samples >= OPUS_FRAME_SIZE)
    {
        block_t *out_block = block_Alloc(OPUS_MAX_ENCODED_BYTES);

        /* add padding to beginning */
        if (sys->padding)
        {
            const size_t leftover_space = OPUS_FRAME_SIZE - sys->i_nb_samples;
            padding_start = fill_buffer(enc, padding_start, sys->padding,
                    __MIN(sys->padding->i_nb_samples, leftover_space));
            if (sys->padding->i_nb_samples <= 0)
            {
                block_Release(sys->padding);
                sys->padding = NULL;
            }
        }

        /* padding may have been freed either before or inside previous
         * if-statement */
        if (!sys->padding)
        {
            const size_t leftover_space = OPUS_FRAME_SIZE - sys->i_nb_samples;
            src_start = fill_buffer(enc, src_start, buf,
                    __MIN(buf->i_nb_samples, leftover_space));
        }

        opus_int32 bytes_encoded = opus_multistream_encode_float(sys->enc, sys->buffer,
                OPUS_FRAME_SIZE, out_block->p_buffer, out_block->i_buffer);

        if (bytes_encoded < 0)
        {
            block_Release(out_block);
        }
        else
        {
            out_block->i_length = (mtime_t) CLOCK_FREQ *
                (mtime_t) OPUS_FRAME_SIZE / (mtime_t) enc->fmt_in.audio.i_rate;

            out_block->i_dts = out_block->i_pts = i_pts;

            sys->i_samples_delay -= OPUS_FRAME_SIZE;

            i_pts += out_block->i_length;

            sys->i_nb_samples = 0;

            out_block->i_buffer = bytes_encoded;
            block_ChainAppend(&result, out_block);
        }
    }

    /* put leftover samples at beginning of buffer */
    if (buf->i_nb_samples > 0)
        fill_buffer(enc, src_start, buf, buf->i_nb_samples);

    return result;
}
Пример #21
0
/****************************************************************************
 * Encode: the whole thing
 ****************************************************************************
 * This function spits out encapsulation units.
 ****************************************************************************/
static block_t *Encode( encoder_t *p_enc, picture_t *p_pic )
{
    encoder_sys_t *p_sys = p_enc->p_sys;
    block_t *p_block, *p_output_chain = NULL;
    int i_plane, i_line, i_width, i_src_stride;
    uint8_t *p_dst;

    if( !p_pic ) return NULL;
    /* we only know if the sequence is interlaced when the first
     * picture arrives, so final setup is done here */
    /* XXX todo, detect change of interlace */
    p_sys->ctx.src_params.topfieldfirst = p_pic->b_top_field_first;
    p_sys->ctx.src_params.source_sampling = !p_pic->b_progressive;

    if( p_sys->b_auto_field_coding )
        p_sys->ctx.enc_params.picture_coding_mode = !p_pic->b_progressive;

    if( !p_sys->p_dirac )
    {
        date_t date;
        /* Initialise the encoder with the encoder context */
        p_sys->p_dirac = dirac_encoder_init( &p_sys->ctx, 0 );
        if( !p_sys->p_dirac )
        {
            msg_Err( p_enc, "Failed to initialize dirac encoder" );
            return NULL;
        }
        date_Init( &date, p_enc->fmt_in.video.i_frame_rate, p_enc->fmt_in.video.i_frame_rate_base );
#if DIRAC_RESEARCH_VERSION_ATLEAST(1,0,2)
        int i_delayinpics = dirac_encoder_pts_offset( p_sys->p_dirac );
        i_delayinpics /= p_sys->ctx.enc_params.picture_coding_mode + 1;
        date_Increment( &date, i_delayinpics );
#else
        date_Increment( &date, 1 );
#endif
        p_sys->i_pts_offset = date_Get( &date );

        /* picture_coding_mode = 1 == FIELD_CODING, two pictures are produced
         * for each frame input. Calculate time between fields for offsetting
         * the second field later. */
        if( 1 == p_sys->ctx.enc_params.picture_coding_mode )
        {
            date_Set( &date, 0 );
            date_Increment( &date, 1 );
            p_sys->i_field_time = date_Get( &date ) / 2;
        }
    }

    /* Copy input picture into encoder input buffer (stride by stride) */
    /* Would be lovely to just pass the picture in, but there is noway for the
     * library to free it */
    p_dst = p_sys->p_buffer_in;
    for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
    {
        uint8_t *p_src = p_pic->p[i_plane].p_pixels;
        i_width = p_pic->p[i_plane].i_visible_pitch;
        i_src_stride = p_pic->p[i_plane].i_pitch;

        for( i_line = 0; i_line < p_pic->p[i_plane].i_visible_lines; i_line++ )
        {
            vlc_memcpy( p_dst, p_src, i_width );
            p_dst += i_width;
            p_src += i_src_stride;
        }
    }

    /* Load one frame of data into encoder */
    if( dirac_encoder_load( p_sys->p_dirac, p_sys->p_buffer_in,
                            p_sys->i_buffer_in ) < 0 )
    {
        msg_Dbg( p_enc, "dirac_encoder_load() error" );
        return NULL;
    }

    /* store pts in a lookaside buffer, so that the same pts may
     * be used for the picture in coded order */
    StorePicturePTS( p_enc, p_sys->i_input_picnum, p_pic->date );
    p_sys->i_input_picnum++;

    /* store dts in a queue, so that they appear in order in
     * coded order */
    p_block = block_New( p_enc, 1 );
    if( !p_block )
        return NULL;
    p_block->i_dts = p_pic->date - p_sys->i_pts_offset;
    block_FifoPut( p_sys->p_dts_fifo, p_block );
    p_block = NULL;

    /* for field coding mode, insert an extra value into both the
     * pts lookaside buffer and dts queue, offset to correspond
     * to a one field delay. */
    if( 1 == p_sys->ctx.enc_params.picture_coding_mode )
    {
        StorePicturePTS( p_enc, p_sys->i_input_picnum, p_pic->date + p_sys->i_field_time );
        p_sys->i_input_picnum++;

        p_block = block_New( p_enc, 1 );
        if( !p_block )
            return NULL;
        p_block->i_dts = p_pic->date - p_sys->i_pts_offset + p_sys->i_field_time;
        block_FifoPut( p_sys->p_dts_fifo, p_block );
        p_block = NULL;
    }

    dirac_encoder_state_t state;
    /* Retrieve encoded frames from encoder */
    do
    {
        p_sys->p_dirac->enc_buf.buffer = p_sys->p_buffer_out;
        p_sys->p_dirac->enc_buf.size = p_sys->i_buffer_out;
        state = dirac_encoder_output( p_sys->p_dirac );
        switch( state )
        {
        case ENC_STATE_AVAIL: {
            uint32_t pic_num;

            /* extract data from encoder temporary buffer. */
            p_block = block_New( p_enc, p_sys->p_dirac->enc_buf.size );
            if( !p_block )
                return NULL;
            memcpy( p_block->p_buffer, p_sys->p_dirac->enc_buf.buffer,
                    p_sys->p_dirac->enc_buf.size );

            /* if some flags were set for a previous block, prevent
             * them from getting lost */
            if( p_sys->p_chain )
                p_block->i_flags |= p_sys->p_chain->i_flags;

            /* store all extracted blocks in a chain and gather up when an
             * entire encapsulation unit is avaliable (ends with a picture) */
            block_ChainAppend( &p_sys->p_chain, p_block );

            /* Presence of a Sequence header indicates a seek point */
            if( 0 == p_block->p_buffer[4] )
            {
                p_block->i_flags |= BLOCK_FLAG_TYPE_I;

                if( !p_enc->fmt_out.p_extra ) {
                    const uint8_t eos[] = { 'B','B','C','D',0x10,0,0,0,13,0,0,0,0 };
                    uint32_t len = GetDWBE( p_block->p_buffer + 5 );
                    /* if it hasn't been done so far, stash a copy of the
                     * sequence header for muxers such as ogg */
                    /* The OggDirac spec advises that a Dirac EOS DataUnit
                     * is appended to the sequence header to allow guard
                     * against poor streaming servers */
                    /* XXX, should this be done using the packetizer ? */
                    p_enc->fmt_out.p_extra = malloc( len + sizeof(eos) );
                    if( !p_enc->fmt_out.p_extra )
                        return NULL;
                    memcpy( p_enc->fmt_out.p_extra, p_block->p_buffer, len);
                    memcpy( (uint8_t*)p_enc->fmt_out.p_extra + len, eos, sizeof(eos) );
                    SetDWBE( (uint8_t*)p_enc->fmt_out.p_extra + len + 10, len );
                    p_enc->fmt_out.i_extra = len + sizeof(eos);
                }
            }

            if( ReadDiracPictureNumber( &pic_num, p_block ) )
            {
                /* Finding a picture terminates an ecapsulation unit, gather
                 * all data and output; use the next dts value queued up
                 * and find correct pts in the tlb */
                p_block = block_FifoGet( p_sys->p_dts_fifo );
                p_sys->p_chain->i_dts = p_block->i_dts;
                p_sys->p_chain->i_pts = GetPicturePTS( p_enc, pic_num );
                block_Release( p_block );
                block_ChainAppend( &p_output_chain, block_ChainGather( p_sys->p_chain ) );
                p_sys->p_chain = NULL;
            } else {
                p_block = NULL;
            }
            break;
            }

        case ENC_STATE_BUFFER:
            break;
        case ENC_STATE_INVALID:
        default:
            break;
        }
    } while( state == ENC_STATE_AVAIL );

    return p_output_chain;
}
Пример #22
0
Файл: dv.c Проект: 0xheart0/vlc
static enum raw1394_iso_disposition
Raw1394Handler(raw1394handle_t handle, unsigned char *data,
        unsigned int length, unsigned char channel,
        unsigned char tag, unsigned char sy, unsigned int cycle,
        unsigned int dropped)
{
    access_t *p_access = NULL;
    access_sys_t *p_sys = NULL;
    block_t *p_block = NULL;
    VLC_UNUSED(channel); VLC_UNUSED(tag);
    VLC_UNUSED(sy); VLC_UNUSED(cycle); VLC_UNUSED(dropped);

    p_access = (access_t *) raw1394_get_userdata( handle );
    if( !p_access ) return 0;

    p_sys = p_access->p_sys;

    /* skip empty packets */
    if( length > 16 )
    {
        unsigned char * p = data + 8;
        int section_type = p[ 0 ] >> 5;           /* section type is in bits 5 - 7 */
        int dif_sequence = p[ 1 ] >> 4;           /* dif sequence number is in bits 4 - 7 */
        int dif_block = p[ 2 ];

        vlc_mutex_lock( &p_sys->p_ev->lock );

        /* if we are at the beginning of a frame, we put the previous
           frame in our output_queue. */
        if( (section_type == 0) && (dif_sequence == 0) )
        {
            vlc_mutex_lock( &p_sys->lock );
            if( p_sys->p_ev->p_frame )
            {
                /* Push current frame to p_access thread. */
                //p_sys->p_ev->p_frame->i_pts = mdate();
                block_ChainAppend( &p_sys->p_frame, p_sys->p_ev->p_frame );
            }
            /* reset list */
            p_sys->p_ev->p_frame = block_Alloc( 144000 );
            p_sys->p_ev->pp_last = &p_sys->p_frame;
            vlc_mutex_unlock( &p_sys->lock );
        }

        p_block = p_sys->p_ev->p_frame;
        if( p_block )
        {
            switch ( section_type )
            {
            case 0:    /* 1 Header block */
                /* p[3] |= 0x80; // hack to force PAL data */
                memcpy( p_block->p_buffer + dif_sequence * 150 * 80, p, 480 );
                break;

            case 1:    /* 2 Subcode blocks */
                memcpy( p_block->p_buffer + dif_sequence * 150 * 80 + ( 1 + dif_block ) * 80, p, 480 );
                break;

            case 2:    /* 3 VAUX blocks */
                memcpy( p_block->p_buffer + dif_sequence * 150 * 80 + ( 3 + dif_block ) * 80, p, 480 );
                break;

            case 3:    /* 9 Audio blocks interleaved with video */
                memcpy( p_block->p_buffer + dif_sequence * 150 * 80 + ( 6 + dif_block * 16 ) * 80, p, 480 );
                break;

            case 4:    /* 135 Video blocks interleaved with audio */
                memcpy( p_block->p_buffer + dif_sequence * 150 * 80 + ( 7 + ( dif_block / 15 ) + dif_block ) * 80, p, 480 );
                break;

            default:    /* we can´t handle any other data */
                block_Release( p_block );
                p_block = NULL;
                break;
            }
        }

        vlc_mutex_unlock( &p_sys->p_ev->lock );
    }
Пример #23
0
Файл: hevc.c Проект: Akilklk/vlc
static block_t *ParseVCL(decoder_t *p_dec, uint8_t i_nal_type, block_t *p_frag)
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    block_t *p_frame = NULL;

    const uint8_t *p_buffer = p_frag->p_buffer;
    size_t i_buffer = p_frag->i_buffer;

    if(unlikely(!hxxx_strip_AnnexB_startcode(&p_buffer, &i_buffer) || i_buffer < 3))
    {
        block_ChainAppend(&p_sys->p_frame, p_frag); /* might corrupt */
        return NULL;
    }

    bool b_first_slice_in_pic = p_buffer[2] & 0x80;
    if (b_first_slice_in_pic)
    {
        if(p_sys->p_frame)
        {
            /* Starting new frame, gather and return previous frame data */
            p_frame = block_ChainGather(p_sys->p_frame);
            p_sys->p_frame = NULL;
            p_sys->pp_frame_last = &p_sys->p_frame;
        }

        switch(i_nal_type)
        {
            case HEVC_NAL_BLA_W_LP:
            case HEVC_NAL_BLA_W_RADL:
            case HEVC_NAL_BLA_N_LP:
            case HEVC_NAL_IDR_W_RADL:
            case HEVC_NAL_IDR_N_LP:
            case HEVC_NAL_CRA:
                p_frag->i_flags |= BLOCK_FLAG_TYPE_I;
                break;

            default:
            {
                hevc_slice_segment_header_t *p_sli = hevc_decode_slice_header( p_buffer, i_buffer, true,
                                                                               p_sys->rgi_p_decsps, p_sys->rgi_p_decpps );
                if( p_sli )
                {
                    enum hevc_slice_type_e type;
                    if( hevc_get_slice_type( p_sli, &type ) )
                    {
                        if( type == HEVC_SLICE_TYPE_P )
                            p_frag->i_flags |= BLOCK_FLAG_TYPE_P;
                        else
                            p_frag->i_flags |= BLOCK_FLAG_TYPE_B;
                    }
                    hevc_rbsp_release_slice_header( p_sli );
                }
                else p_frag->i_flags |= BLOCK_FLAG_TYPE_B;
            }
            break;
        }
    }

    block_ChainLastAppend(&p_sys->pp_frame_last, p_frag);

    return p_frame;
}
Пример #24
0
/*****************************************************************************
 * Process: Process and dispatch buffers
 *****************************************************************************/
static mtime_t Process( sout_stream_t *p_stream, sout_stream_id_t *id,
                        mtime_t i_max_dts )
{
    sout_stream_sys_t *p_sys = p_stream->p_sys;
    mtime_t i_dts = 0;
    block_t *p_blocks = NULL;
    block_t *p_blocks_out = NULL;

    /* Find out the blocks we need. */
    while ( id->p_queued != NULL
             && (!i_max_dts || id->p_queued->i_dts <= i_max_dts) )
    {
        block_t *p_next = id->p_queued->p_next;
        id->p_queued->p_next = NULL;
        i_dts = id->p_queued->i_dts;
        block_ChainAppend( &p_blocks, id->p_queued );
        id->p_queued = p_next;
    }

    if ( p_sys->i_old_cmd == 0 )
    {
        /* Full forward */
        if ( p_blocks != NULL )
            p_sys->p_out->pf_send( p_sys->p_out, id->id, p_blocks );
        return i_dts;
    }

    if ( p_sys->i_old_cmd == -1 )
    {
        /* No output at all */
        while ( p_blocks != NULL )
        {
            block_t * p_next = p_blocks->p_next;
            block_Release( p_blocks );
            p_blocks = p_next;
        }
        return i_dts;
    }

    while ( p_blocks != NULL )
    {
        block_t * p_next = p_blocks->p_next;
        block_t * p_out;

        if ( id->b_switcher_video )
        {
            p_out = VideoGetBuffer( p_stream, id, p_blocks );
        }
        else
        {
            p_out = AudioGetBuffer( p_stream, id, p_blocks );
        }
        p_blocks = p_next;
        if ( p_out != NULL )
        {
            block_ChainAppend( &p_blocks_out, p_out );
        }
    }

    if ( p_blocks_out != NULL )
        p_sys->p_out->pf_send( p_sys->p_out, id->id, p_blocks_out );
    return i_dts;
}
Пример #25
0
int transcode_audio_process( sout_stream_t *p_stream,
                                    sout_stream_id_t *id,
                                    block_t *in, block_t **out )
{
    sout_stream_sys_t *p_sys = p_stream->p_sys;
    block_t *p_block, *p_audio_buf;
    *out = NULL;

    if( unlikely( in == NULL ) )
    {
        block_t *p_block;
        do {
           p_block = id->p_encoder->pf_encode_audio(id->p_encoder, NULL );
           block_ChainAppend( out, p_block );
        } while( p_block );
        return VLC_SUCCESS;
    }

    while( (p_audio_buf = id->p_decoder->pf_decode_audio( id->p_decoder,
                                                          &in )) )
    {
        if( p_sys->b_master_sync )
        {
            mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
            mtime_t i_drift = 0;

            if( likely( p_audio_buf->i_pts != VLC_TS_INVALID ) )
                i_drift = p_audio_buf->i_pts - i_pts;

            if ( unlikely(i_drift > MASTER_SYNC_MAX_DRIFT
                 || i_drift < -MASTER_SYNC_MAX_DRIFT) )
            {
                msg_Dbg( p_stream,
                    "audio drift is too high (%"PRId64"), resetting master sync",
                    i_drift );
                date_Set( &id->interpolated_pts, p_audio_buf->i_pts );
                i_pts = p_audio_buf->i_pts + 1;
            }
            if( likely(p_audio_buf->i_pts != VLC_TS_INVALID ) )
                p_sys->i_master_drift = p_audio_buf->i_pts - i_pts;
            date_Increment( &id->interpolated_pts, p_audio_buf->i_nb_samples );
            p_audio_buf->i_pts = i_pts;
        }

        p_audio_buf->i_dts = p_audio_buf->i_pts;

        /* Check if audio format has changed, and filters need reinit */
        if( unlikely( ( id->p_decoder->fmt_out.audio.i_rate != p_sys->fmt_audio.i_rate ) ||
                      ( id->p_decoder->fmt_out.audio.i_physical_channels != p_sys->fmt_audio.i_physical_channels ) ) )
        {
            msg_Info( p_stream, "Audio changed, trying to reinitialize filters" );
            if( id->p_af_chain != NULL )
                aout_FiltersDelete( (vlc_object_t *)NULL, id->p_af_chain );

            /* decoders don't set audio.i_format, but audio filters use it */
            id->p_decoder->fmt_out.audio.i_format = id->p_decoder->fmt_out.i_codec;
            aout_FormatPrepare( &id->p_decoder->fmt_out.audio );

            if( transcode_audio_initialize_filters( p_stream, id, p_sys, &id->p_decoder->fmt_out.audio ) != VLC_SUCCESS )
                return VLC_EGENERIC;

        }

        /* Run filter chain */
        p_audio_buf = aout_FiltersPlay( id->p_af_chain, p_audio_buf,
                                        INPUT_RATE_DEFAULT );
        if( !p_audio_buf )
            abort();

        p_audio_buf->i_dts = p_audio_buf->i_pts;

        p_block = id->p_encoder->pf_encode_audio( id->p_encoder, p_audio_buf );

        block_ChainAppend( out, p_block );
        block_Release( p_audio_buf );
    }

    return VLC_SUCCESS;
}
Пример #26
0
static block_t *
Resample( filter_t *p_filter, block_t *p_in )
{
    filter_sys_t *p_sys = p_filter->p_sys;
    const vlc_tick_t i_pts = p_in->i_pts;

    if( p_sys->vr_soxr )
    {
        /* "audio resampler" with variable ratio: use the fixed resampler when
         * the ratio is the same than the fixed one, otherwise use the variable
         * resampler. */

        soxr_t soxr;
        block_t *p_flushed_out = NULL, *p_out = NULL;
        const double f_ratio = p_filter->fmt_out.audio.i_rate
                             / (double) p_filter->fmt_in.audio.i_rate;
        const size_t i_olen = SoXR_GetOutLen( p_in->i_nb_samples, f_ratio );

        if( f_ratio != p_sys->f_fixed_ratio )
        {
            /* using variable resampler */
            soxr_set_io_ratio( p_sys->vr_soxr, 1 / f_ratio, i_olen );
            soxr = p_sys->vr_soxr;
        }
        else if( f_ratio == 1.0f )
        {
            /* not using any resampler */
            soxr = NULL;
            p_out = p_in;
        }
        else
        {
            /* using fixed resampler */
            soxr = p_sys->soxr;
        }

        /* If the new soxr is different than the last one, flush it */
        if( p_sys->last_soxr && soxr != p_sys->last_soxr && p_sys->i_last_olen )
        {
            p_flushed_out = SoXR_Resample( p_filter, p_sys->last_soxr,
                                           NULL, p_sys->i_last_olen );
            if( soxr )
                msg_Dbg( p_filter, "Using '%s' engine", soxr_engine( soxr ) );
        }

        if( soxr )
        {
            assert( !p_out );
            p_out = SoXR_Resample( p_filter, soxr, p_in, i_olen );
            if( !p_out )
                goto error;
        }

        if( p_flushed_out )
        {
            /* Prepend the flushed output data to p_out */
            const unsigned i_nb_samples = p_flushed_out->i_nb_samples
                                        + p_out->i_nb_samples;

            block_ChainAppend( &p_flushed_out, p_out );
            p_out = block_ChainGather( p_flushed_out );
            if( !p_out )
                goto error;
            p_out->i_nb_samples = i_nb_samples;
        }
        p_out->i_pts = i_pts;
        return p_out;
    }
    else
    {
        /* "audio converter" with fixed ratio */

        const size_t i_olen = SoXR_GetOutLen( p_in->i_nb_samples,
                                              p_sys->f_fixed_ratio );
        block_t *p_out = SoXR_Resample( p_filter, p_sys->soxr, p_in, i_olen );
        if( p_out )
            p_out->i_pts = i_pts;
        return p_out;
    }
error:
    block_Release( p_in );
    return NULL;
}
Пример #27
0
int transcode_video_process( sout_stream_t *p_stream, sout_stream_id_t *id,
                                    block_t *in, block_t **out )
{
    sout_stream_sys_t *p_sys = p_stream->p_sys;
    bool b_need_duplicate = false;
    picture_t *p_pic, *p_pic2 = NULL;
    *out = NULL;

    if( in == NULL )
    {
        if( p_sys->i_threads == 0 )
        {
            block_t *p_block;
            do {
                video_timer_start( id->p_encoder );
                p_block = id->p_encoder->pf_encode_video(id->p_encoder, NULL );
                video_timer_stop( id->p_encoder );
                block_ChainAppend( out, p_block );
            } while( p_block );
        }
        else
        {
            /*
             * FIXME: we need EncoderThread() to flush buffers and signal us
             * when it's done so we can send the last frames to the chain
             */
        }
        return VLC_SUCCESS;
    }


    while( (p_pic = id->p_decoder->pf_decode_video( id->p_decoder, &in )) )
    {

        if( p_stream->p_sout->i_out_pace_nocontrol && p_sys->b_hurry_up )
        {
            mtime_t current_date = mdate();
            if( current_date + 50000 > p_pic->date )
            {
                msg_Dbg( p_stream, "late picture skipped (%"PRId64")",
                         current_date + 50000 - p_pic->date );
                picture_Release( p_pic );
                continue;
            }
        }

        if( p_sys->b_master_sync )
        {
            mtime_t i_video_drift;
            mtime_t i_master_drift = p_sys->i_master_drift;
            mtime_t i_pts;

            i_pts = date_Get( &id->interpolated_pts ) + 1;
            if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
                  || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
            {
                msg_Dbg( p_stream, "drift is too high, resetting master sync" );
                date_Set( &id->interpolated_pts, p_pic->date );
                i_pts = p_pic->date + 1;
            }
            i_video_drift = p_pic->date - i_pts;
            b_need_duplicate = false;

            /* Set the pts of the frame being encoded */
            p_pic->date = i_pts;

            if( i_video_drift < (i_master_drift - 50000) )
            {
#if 0
                msg_Dbg( p_stream, "dropping frame (%i)",
                         (int)(i_video_drift - i_master_drift) );
#endif
                picture_Release( p_pic );
                continue;
            }
            else if( i_video_drift > (i_master_drift + 50000) )
            {
#if 0
                msg_Dbg( p_stream, "adding frame (%i)",
                         (int)(i_video_drift - i_master_drift) );
#endif
                b_need_duplicate = true;
            }
        }

        if( unlikely( !id->p_encoder->p_module ) )
        {
            transcode_video_encoder_init( p_stream, id );

            transcode_video_filter_init( p_stream, id );

            if( transcode_video_encoder_open( p_stream, id ) != VLC_SUCCESS )
            {
                picture_Release( p_pic );
                transcode_video_close( p_stream, id );
                id->b_transcode = false;
                return VLC_EGENERIC;
            }
        }

        /* Run filter chain */
        if( id->p_f_chain )
            p_pic = filter_chain_VideoFilter( id->p_f_chain, p_pic );

        /*
         * Encoding
         */

        /* Check if we have a subpicture to overlay */
        if( p_sys->p_spu )
        {
            video_format_t fmt;
            if( filter_chain_GetLength( id->p_f_chain ) > 0 )
                fmt = filter_chain_GetFmtOut( id->p_f_chain )->video;
            else
                fmt = id->p_decoder->fmt_out.video;

            subpicture_t *p_subpic = spu_Render( p_sys->p_spu, NULL, &fmt, &fmt,
                                                 p_pic->date, p_pic->date, false );

            /* Overlay subpicture */
            if( p_subpic )
            {
                if( picture_IsReferenced( p_pic ) && !filter_chain_GetLength( id->p_f_chain ) )
                {
                    /* We can't modify the picture, we need to duplicate it */
                    picture_t *p_tmp = video_new_buffer_decoder( id->p_decoder );
                    if( p_tmp )
                    {
                        picture_Copy( p_tmp, p_pic );
                        picture_Release( p_pic );
                        p_pic = p_tmp;
                    }
                }
                if( !p_sys->p_spu_blend )
                    p_sys->p_spu_blend = filter_NewBlend( VLC_OBJECT( p_sys->p_spu ), &fmt );
                if( p_sys->p_spu_blend )
                    picture_BlendSubpicture( p_pic, p_sys->p_spu_blend, p_subpic );
                subpicture_Delete( p_subpic );
            }
        }

        /* Run user specified filter chain */
        if( id->p_uf_chain )
            p_pic = filter_chain_VideoFilter( id->p_uf_chain, p_pic );

        if( p_sys->i_threads == 0 )
        {
            block_t *p_block;

            video_timer_start( id->p_encoder );
            p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
            video_timer_stop( id->p_encoder );

            block_ChainAppend( out, p_block );
        }

        if( p_sys->b_master_sync )
        {
            mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
            if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
                  || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
            {
                msg_Dbg( p_stream, "drift is too high, resetting master sync" );
                date_Set( &id->interpolated_pts, p_pic->date );
                i_pts = p_pic->date + 1;
            }
            date_Increment( &id->interpolated_pts, 1 );

            if( unlikely( b_need_duplicate ) )
            {

               if( p_sys->i_threads >= 1 )
               {
                   /* We can't modify the picture, we need to duplicate it */
                   p_pic2 = video_new_buffer_decoder( id->p_decoder );
                   if( p_pic2 != NULL )
                   {
                       picture_Copy( p_pic2, p_pic );
                       p_pic2->date = i_pts;
                   }
               }
               else
               {
                   block_t *p_block;
                   p_pic->date = i_pts;
                   video_timer_start( id->p_encoder );
                   p_block = id->p_encoder->pf_encode_video(id->p_encoder, p_pic);
                   video_timer_stop( id->p_encoder );
                   block_ChainAppend( out, p_block );
               }
           }
        }

        if( p_sys->i_threads == 0 )
        {
            picture_Release( p_pic );
        }
        else
        {
            vlc_mutex_lock( &p_sys->lock_out );
            p_sys->pp_pics[p_sys->i_last_pic++] = p_pic;
            p_sys->i_last_pic %= PICTURE_RING_SIZE;
            *out = p_sys->p_buffers;
            p_sys->p_buffers = NULL;
            if( p_pic2 != NULL )
            {
                p_sys->pp_pics[p_sys->i_last_pic++] = p_pic2;
                p_sys->i_last_pic %= PICTURE_RING_SIZE;
            }
            vlc_cond_signal( &p_sys->cond );
            vlc_mutex_unlock( &p_sys->lock_out );
        }
    }

    return VLC_SUCCESS;
}
Пример #28
0
/****************************************************************************
 * Encode: the whole thing
 ****************************************************************************
 * This function spits out ogg packets.
 ****************************************************************************/
static block_t *Encode( encoder_t *p_enc, block_t *p_aout_buf )
{
    encoder_sys_t *p_sys = p_enc->p_sys;
    ogg_packet oggpacket;
    block_t *p_block, *p_chain = NULL;
    float **buffer;

    /* FIXME: flush buffers in here */
    if( unlikely( !p_aout_buf ) ) return NULL;

    mtime_t i_pts = p_aout_buf->i_pts -
                    (mtime_t)1000000 * (mtime_t)p_sys->i_samples_delay /
                    (mtime_t)p_enc->fmt_in.audio.i_rate;

    p_sys->i_samples_delay += p_aout_buf->i_nb_samples;

    buffer = vorbis_analysis_buffer( &p_sys->vd, p_aout_buf->i_nb_samples );

    /* convert samples to float and uninterleave */
    for( unsigned int i = 0; i < p_sys->i_channels; i++ )
    {
        for( unsigned int j = 0 ; j < p_aout_buf->i_nb_samples ; j++ )
        {
            buffer[i][j]= ((float *)p_aout_buf->p_buffer)
                          [j * p_sys->i_channels + p_sys->pi_chan_table[i]];
        }
    }

    vorbis_analysis_wrote( &p_sys->vd, p_aout_buf->i_nb_samples );

    while( vorbis_analysis_blockout( &p_sys->vd, &p_sys->vb ) == 1 )
    {
        int i_samples;

        vorbis_analysis( &p_sys->vb, NULL );
        vorbis_bitrate_addblock( &p_sys->vb );

        while( vorbis_bitrate_flushpacket( &p_sys->vd, &oggpacket ) )
        {
            int i_block_size;
            p_block = block_Alloc( oggpacket.bytes );
            memcpy( p_block->p_buffer, oggpacket.packet, oggpacket.bytes );

            i_block_size = vorbis_packet_blocksize( &p_sys->vi, &oggpacket );

            if( i_block_size < 0 ) i_block_size = 0;
            i_samples = ( p_sys->i_last_block_size + i_block_size ) >> 2;
            p_sys->i_last_block_size = i_block_size;

            p_block->i_length = (mtime_t)1000000 *
                                (mtime_t)i_samples / (mtime_t)p_enc->fmt_in.audio.i_rate;

            p_block->i_dts = p_block->i_pts = i_pts;

            p_sys->i_samples_delay -= i_samples;

            /* Update pts */
            i_pts += p_block->i_length;
            block_ChainAppend( &p_chain, p_block );
        }
    }

    return p_chain;
}
Пример #29
0
/****************************************************************************
 * EncodeAudio: the whole thing
 ****************************************************************************/
static block_t *EncodeAudio( encoder_t *p_enc, aout_buffer_t *p_aout_buf )
{
    encoder_sys_t *p_sys = p_enc->p_sys;
    block_t *p_block, *p_chain = NULL;

    char *p_buffer = p_aout_buf->p_buffer;
    int i_samples = p_aout_buf->i_nb_samples;
    int i_samples_delay = p_sys->i_samples_delay;

    p_sys->i_pts = p_aout_buf->start_date -
                (mtime_t)1000000 * (mtime_t)p_sys->i_samples_delay /
                (mtime_t)p_enc->fmt_in.audio.i_rate;

    p_sys->i_samples_delay += i_samples;

    while( p_sys->i_samples_delay >= p_sys->p_context->frame_size )
    {
        int16_t *p_samples;
        int i_out;

        if( i_samples_delay )
        {
            /* Take care of the left-over from last time */
            int i_delay_size = i_samples_delay * 2 *
                                 p_sys->p_context->channels;
            int i_size = p_sys->i_frame_size - i_delay_size;

            p_samples = (int16_t *)p_sys->p_buffer;
            memcpy( p_sys->p_buffer + i_delay_size, p_buffer, i_size );
            p_buffer -= i_delay_size;
            i_samples += i_samples_delay;
            i_samples_delay = 0;
        }
        else
        {
            p_samples = (int16_t *)p_buffer;
        }

        i_out = avcodec_encode_audio( p_sys->p_context, p_sys->p_buffer_out,
                                      2 * AVCODEC_MAX_AUDIO_FRAME_SIZE,
                                      p_samples );

#if 0
        msg_Warn( p_enc, "avcodec_encode_audio: %d", i_out );
#endif
        if( i_out < 0 ) break;

        p_buffer += p_sys->i_frame_size;
        p_sys->i_samples_delay -= p_sys->p_context->frame_size;
        i_samples -= p_sys->p_context->frame_size;

        if( i_out == 0 ) continue;

        p_block = block_New( p_enc, i_out );
        memcpy( p_block->p_buffer, p_sys->p_buffer_out, i_out );

        p_block->i_length = (mtime_t)1000000 *
            (mtime_t)p_sys->p_context->frame_size /
            (mtime_t)p_sys->p_context->sample_rate;

        p_block->i_dts = p_block->i_pts = p_sys->i_pts;

        /* Update pts */
        p_sys->i_pts += p_block->i_length;
        block_ChainAppend( &p_chain, p_block );
    }

    /* Backup the remaining raw samples */
    if( i_samples )
    {
        memcpy( p_sys->p_buffer + i_samples_delay * 2 *
                p_sys->p_context->channels, p_buffer,
                i_samples * 2 * p_sys->p_context->channels );
    }

    return p_chain;
}
Пример #30
0
static block_t *Encode( encoder_t *p_enc, block_t *p_aout_buf )
{
    encoder_sys_t *p_sys = p_enc->p_sys;
    block_t *p_chain = NULL;

    if( unlikely( !p_aout_buf ) ) {
        int i_used = 0;
        block_t *p_block;

        i_used = twolame_encode_flush( p_sys->p_twolame,
                                p_sys->p_out_buffer, MAX_CODED_FRAME_SIZE );
        if( i_used <= 0 )
            return NULL;

        p_block = block_Alloc( i_used );
        if( !p_block )
            return NULL;
        memcpy( p_block->p_buffer, p_sys->p_out_buffer, i_used );
        p_block->i_length = vlc_tick_from_samples( MPEG_FRAME_SIZE,
                                                   p_enc->fmt_out.audio.i_rate );
        p_block->i_dts = p_block->i_pts = p_sys->i_pts;
        p_sys->i_pts += p_block->i_length;

        return p_block;
    }

    int16_t *p_buffer = (int16_t *)p_aout_buf->p_buffer;
    int i_nb_samples = p_aout_buf->i_nb_samples;

    p_sys->i_pts = p_aout_buf->i_pts -
                vlc_tick_from_samples( p_sys->i_nb_samples,
                                       p_enc->fmt_out.audio.i_rate );

    while ( p_sys->i_nb_samples + i_nb_samples >= MPEG_FRAME_SIZE )
    {
        int i_used;
        block_t *p_block;

        Bufferize( p_enc, p_buffer, MPEG_FRAME_SIZE - p_sys->i_nb_samples );
        i_nb_samples -= MPEG_FRAME_SIZE - p_sys->i_nb_samples;
        p_buffer += (MPEG_FRAME_SIZE - p_sys->i_nb_samples) * 2;

        i_used = twolame_encode_buffer_interleaved( p_sys->p_twolame,
                               p_sys->p_buffer, MPEG_FRAME_SIZE,
                               p_sys->p_out_buffer, MAX_CODED_FRAME_SIZE );
        /* On error, buffer samples and return what was already encoded */
        if( i_used < 0 )
        {
            msg_Err( p_enc, "encoder error: %d", i_used );
            break;
        }

        p_sys->i_nb_samples = 0;
        p_block = block_Alloc( i_used );
        if( !p_block )
        {
            if( p_chain )
                block_ChainRelease( p_chain );
            return NULL;
        }
        memcpy( p_block->p_buffer, p_sys->p_out_buffer, i_used );
        p_block->i_length = vlc_tick_from_samples( MPEG_FRAME_SIZE,
                                                   p_enc->fmt_out.audio.i_rate );
        p_block->i_dts = p_block->i_pts = p_sys->i_pts;
        p_sys->i_pts += p_block->i_length;
        block_ChainAppend( &p_chain, p_block );
    }

    if ( i_nb_samples )
    {
        Bufferize( p_enc, p_buffer, i_nb_samples );
        p_sys->i_nb_samples += i_nb_samples;
    }

    return p_chain;
}