示例#1
0
/*****************************************************************************
 * GetAoutBuffer:
 *****************************************************************************/
static block_t *GetAoutBuffer( decoder_t *p_dec )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    block_t *p_buf;

    /* Hack for DTS S/PDIF filter which needs to send 3 frames at a time
     * (plus a few header bytes) */
    p_buf = decoder_NewAudioBuffer( p_dec, p_sys->i_frame_length * 4 );
    if( p_buf == NULL ) return NULL;

    p_buf->i_nb_samples = p_sys->i_frame_length;
    p_buf->i_buffer = p_sys->i_frame_size;

    p_buf->i_pts = date_Get( &p_sys->end_date );
    p_buf->i_length = date_Increment( &p_sys->end_date, p_sys->i_frame_length )
                      - p_buf->i_pts;

    return p_buf;
}
示例#2
0
文件: wma.c 项目: CSRedRat/vlc
/*****************************************************************************
 * SplitBuffer: Needed because aout really doesn't like big audio chunk and
 * wma produces easily > 30000 samples...
 *****************************************************************************/
static aout_buffer_t *SplitBuffer( decoder_t *p_dec )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    unsigned int i_samples = __MIN( p_sys->i_samples, 2048 );
    aout_buffer_t *p_buffer;

    if( i_samples == 0 ) return NULL;

    if( !( p_buffer = decoder_NewAudioBuffer( p_dec, i_samples ) ) )
        return NULL;

    p_buffer->i_pts = date_Get( &p_sys->end_date );
    p_buffer->i_length = date_Increment( &p_sys->end_date, i_samples )
                         - p_buffer->i_pts;

    memcpy( p_buffer->p_buffer, p_sys->p_samples, p_buffer->i_buffer );
    p_sys->p_samples += p_buffer->i_buffer;
    p_sys->i_samples -= i_samples;

    return p_buffer;
}
示例#3
0
文件: opus.c 项目: MSalmo/vlc
/*****************************************************************************
 * DecodePacket: decodes a Opus packet.
 *****************************************************************************/
static block_t *DecodePacket( decoder_t *p_dec, ogg_packet *p_oggpacket,
                              int i_nb_samples, int i_end_trim )
{
    decoder_sys_t *p_sys = p_dec->p_sys;

    if( !p_oggpacket->bytes )
        return NULL;

    int spp;
    spp=opus_packet_get_nb_frames(p_oggpacket->packet,p_oggpacket->bytes);
    if(spp>0)spp*=opus_packet_get_samples_per_frame(p_oggpacket->packet,48000);
    if(spp<120||spp>120*48)return NULL;

    /* Since the information isn't always available at the demux level
     * use the packet's sample number */
    if(!i_nb_samples)
        i_nb_samples = spp;

    block_t *p_aout_buffer=decoder_NewAudioBuffer( p_dec, spp );
    if ( !p_aout_buffer )
    {
        msg_Err(p_dec, "Oops: No new buffer was returned!");
        return NULL;
    }

    spp=opus_multistream_decode_float(p_sys->p_st, p_oggpacket->packet,
         p_oggpacket->bytes, (float *)p_aout_buffer->p_buffer, spp, 0);
    if( spp < 0 || i_nb_samples <= 0 || i_end_trim >= i_nb_samples)
    {
        block_Release(p_aout_buffer);
        if( spp < 0 )
            msg_Err( p_dec, "Error: corrupted stream?" );
        return NULL;
    }
    if( spp > i_nb_samples )
    {
        p_aout_buffer->i_buffer = (i_nb_samples - i_end_trim) *
                                  p_sys->header.channels * sizeof(float);
        memmove(p_aout_buffer->p_buffer,
            p_aout_buffer->p_buffer
            + (spp - i_nb_samples)*p_sys->header.channels*sizeof(float),
            p_aout_buffer->i_buffer);
    }
    i_nb_samples -= i_end_trim;

#ifndef OPUS_SET_GAIN
    if(p_sys->header.gain!=0)
    {
        float gain = pow(10., p_sys->header.gain/5120.);
        float *buf =(float *)p_aout_buffer->p_buffer;
        int i;
        for( i = 0; i < i_nb_samples*p_sys->header.channels; i++)
            buf[i] *= gain;
    }
#endif
    p_aout_buffer->i_nb_samples = i_nb_samples;
    p_aout_buffer->i_pts = date_Get( &p_sys->end_date );
    p_aout_buffer->i_length = date_Increment( &p_sys->end_date, i_nb_samples )
        - p_aout_buffer->i_pts;
    return p_aout_buffer;
}
示例#4
0
文件: lpcm.c 项目: shanewfx/vlc-arib
/*****************************************************************************
 * DecodeFrame: decodes an lpcm frame.
 ****************************************************************************
 * Beware, this function must be fed with complete frames (PES packet).
 *****************************************************************************/
static void *DecodeFrame( decoder_t *p_dec, block_t **pp_block )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    block_t       *p_block;
    unsigned int  i_rate = 0, i_original_channels = 0, i_channels = 0, i_bits = 0;
    int           i_frame_length;

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

    p_block = *pp_block;
    *pp_block = NULL; /* So the packet doesn't get re-sent */

    /* Date management */
    if( p_block->i_pts > 0 &&
        p_block->i_pts != date_Get( &p_sys->end_date ) )
    {
        date_Set( &p_sys->end_date, p_block->i_pts );
    }

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

    if( p_block->i_buffer <= p_sys->i_header_size )
    {
        msg_Err(p_dec, "frame is too short");
        block_Release( p_block );
        return NULL;
    }

    int i_ret;
    unsigned i_padding = 0;
    aob_group_t p_aob_group[2];
    switch( p_sys->i_type )
    {
    case LPCM_VOB:
        i_ret = VobHeader( &i_rate, &i_channels, &i_original_channels, &i_bits,
                           p_block->p_buffer );
        break;
    case LPCM_AOB:
        i_ret = AobHeader( &i_rate, &i_channels, &i_original_channels, &i_bits, &i_padding,
                           p_aob_group,
                           p_block->p_buffer );
        break;
    case LPCM_BD:
        i_ret = BdHeader( &i_rate, &i_channels, &i_original_channels, &i_bits,
                          p_block->p_buffer );
        break;
    default:
        assert(0);
    }

    if( i_ret || p_block->i_buffer <= p_sys->i_header_size + i_padding )
    {
        msg_Warn( p_dec, "no frame sync or too small frame" );
        block_Release( p_block );
        return NULL;
    }

    /* Set output properties */
    if( p_dec->fmt_out.audio.i_rate != i_rate )
    {
        date_Init( &p_sys->end_date, i_rate, 1 );
        date_Set( &p_sys->end_date, p_block->i_pts );
    }
    p_dec->fmt_out.audio.i_rate = i_rate;
    p_dec->fmt_out.audio.i_channels = i_channels;
    p_dec->fmt_out.audio.i_original_channels = i_original_channels;
    p_dec->fmt_out.audio.i_physical_channels = i_original_channels & AOUT_CHAN_PHYSMASK;

    i_frame_length = (p_block->i_buffer - p_sys->i_header_size - i_padding) / i_channels * 8 / i_bits;

    if( p_sys->b_packetizer )
    {
        p_block->i_pts = p_block->i_dts = date_Get( &p_sys->end_date );
        p_block->i_length =
            date_Increment( &p_sys->end_date, i_frame_length ) -
            p_block->i_pts;

        /* Just pass on the incoming frame */
        return p_block;
    }
    else
    {
        /* */
        if( i_bits == 16 )
        {
            p_dec->fmt_out.i_codec = VLC_CODEC_S16B;
            p_dec->fmt_out.audio.i_bitspersample = 16;
        }
        else
        {
            p_dec->fmt_out.i_codec = VLC_CODEC_S24B;
            p_dec->fmt_out.audio.i_bitspersample = 24;
        }

        /* */
        aout_buffer_t *p_aout_buffer;
        p_aout_buffer = decoder_NewAudioBuffer( p_dec, i_frame_length );
        if( !p_aout_buffer )
            return NULL;

        p_aout_buffer->i_pts = date_Get( &p_sys->end_date );
        p_aout_buffer->i_length =
            date_Increment( &p_sys->end_date, i_frame_length )
            - p_aout_buffer->i_pts;

        p_block->p_buffer += p_sys->i_header_size + i_padding;
        p_block->i_buffer -= p_sys->i_header_size + i_padding;

        switch( p_sys->i_type )
        {
        case LPCM_VOB:
            VobExtract( p_aout_buffer, p_block, i_bits );
            break;
        case LPCM_AOB:
            AobExtract( p_aout_buffer, p_block, i_bits, p_aob_group );
            break;
        default:
            assert(0);
        case LPCM_BD:
            BdExtract( p_aout_buffer, p_block );
            break;
        }

        block_Release( p_block );
        return p_aout_buffer;
    }
}
示例#5
0
文件: adpcm.c 项目: 9034725985/vlc
/*****************************************************************************
 * DecodeBlock:
 *****************************************************************************/
static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
{
    decoder_sys_t *p_sys  = p_dec->p_sys;
    block_t *p_block;

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

    p_block = *pp_block;

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

    /* Don't re-use the same pts twice */
    p_block->i_pts = VLC_TS_INVALID;

    if( p_block->i_buffer >= p_sys->i_block )
    {
        block_t *p_out;

        p_out = decoder_NewAudioBuffer( p_dec, p_sys->i_samplesperblock );
        if( p_out == NULL )
        {
            block_Release( p_block );
            return NULL;
        }

        p_out->i_pts = date_Get( &p_sys->end_date );
        p_out->i_length = date_Increment( &p_sys->end_date,
                                     p_sys->i_samplesperblock ) - p_out->i_pts;

        switch( p_sys->codec )
        {
        case ADPCM_IMA_QT:
            DecodeAdpcmImaQT( p_dec, (int16_t*)p_out->p_buffer,
                              p_block->p_buffer );
            break;
        case ADPCM_IMA_WAV:
            DecodeAdpcmImaWav( p_dec, (int16_t*)p_out->p_buffer,
                               p_block->p_buffer );
            break;
        case ADPCM_MS:
            DecodeAdpcmMs( p_dec, (int16_t*)p_out->p_buffer,
                           p_block->p_buffer );
            break;
        case ADPCM_DK4:
            DecodeAdpcmDk4( p_dec, (int16_t*)p_out->p_buffer,
                            p_block->p_buffer );
            break;
        case ADPCM_DK3:
            DecodeAdpcmDk3( p_dec, (int16_t*)p_out->p_buffer,
                            p_block->p_buffer );
            break;
        case ADPCM_EA:
            DecodeAdpcmEA( p_dec, (int16_t*)p_out->p_buffer,
                           p_block->p_buffer );
        default:
            break;
        }

        p_block->p_buffer += p_sys->i_block;
        p_block->i_buffer -= p_sys->i_block;
        return p_out;
    }

    block_Release( p_block );
    return NULL;
}
示例#6
0
/*****************************************************************************
 * DecodeAudio:
 *****************************************************************************/
static aout_buffer_t *DecodeAudio( decoder_t *p_dec, block_t **pp_block )
{
    decoder_sys_t *p_sys = p_dec->p_sys;

    block_t     *p_block;
    int         i_error;

#ifdef LOADER
    /* We must do open and close in the same thread (unless we do
     * Setup_LDT_Keeper in the main thread before all others */
    if( p_sys == NULL )
    {
        if( OpenAudio( p_dec ) )
        {
            /* Fatal */
            p_dec->b_error = true;
            return NULL;
        }

        p_sys = p_dec->p_sys;
    }
#endif

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

    if( p_sys->i_out_frames > 0 && p_sys->i_out >= p_sys->i_out_frames )
    {
        /* Ask new data */
        p_sys->i_out = 0;
        p_sys->i_out_frames = 0;

        *pp_block = NULL;
        return NULL;
    }

    if( p_sys->i_out_frames <= 0 )
    {
        p_sys->pts = p_block->i_pts;

        mtime_t i_display_date = 0;
        if( !(p_block->i_flags & BLOCK_FLAG_PREROLL) )
            i_display_date = decoder_GetDisplayDate( p_dec, p_block->i_pts );

        if( i_display_date > 0 && i_display_date < mdate() )
        {
            block_Release( p_block );
            *pp_block = NULL;
            return NULL;
        }

        /* Append data */
        if( p_sys->i_buffer_size < p_sys->i_buffer + p_block->i_buffer )
        {
            p_sys->i_buffer_size = p_sys->i_buffer + p_block->i_buffer + 1024;
            p_sys->p_buffer = realloc( p_sys->p_buffer, p_sys->i_buffer_size );
        }
        memcpy( &p_sys->p_buffer[p_sys->i_buffer], p_block->p_buffer,
                p_block->i_buffer );
        p_sys->i_buffer += p_block->i_buffer;

        if( p_sys->i_buffer > p_sys->InFrameSize )
        {
            int i_frames = p_sys->i_buffer / p_sys->InFrameSize;
            unsigned long i_out_frames, i_out_bytes;
            vlc_mutex_lock( &qt_mutex );

            i_error = p_sys->SoundConverterConvertBuffer( p_sys->myConverter,
                                                          p_sys->p_buffer,
                                                          i_frames,
                                                          p_sys->out_buffer,
                                                          &i_out_frames,
                                                          &i_out_bytes );
            vlc_mutex_unlock( &qt_mutex );

            /*
            msg_Dbg( p_dec, "decoded %d frames -> %ld frames (error=%d)",
                     i_frames, i_out_frames, i_error );

            msg_Dbg( p_dec, "decoded %ld frames = %ld bytes",
                     i_out_frames, i_out_bytes );
            */

            p_sys->i_buffer -= i_frames * p_sys->InFrameSize;
            if( p_sys->i_buffer > 0 )
            {
                memmove( &p_sys->p_buffer[0],
                         &p_sys->p_buffer[i_frames * p_sys->InFrameSize],
                         p_sys->i_buffer );
            }

            if( p_sys->pts != 0 &&
                p_sys->pts != date_Get( &p_sys->date ) )
            {
                date_Set( &p_sys->date, p_sys->pts );
            }
            else if( !date_Get( &p_sys->date ) )
            {
                return NULL;
            }

            if( !i_error && i_out_frames > 0 )
            {
                /* we have others samples */
                p_sys->i_out_frames = i_out_frames;
                p_sys->i_out = 0;
            }
        }
    }

    if( p_sys->i_out < p_sys->i_out_frames )
    {
        aout_buffer_t *p_out;
        int  i_frames = __MIN( p_sys->i_out_frames - p_sys->i_out, 1000 );

        p_out = decoder_NewAudioBuffer( p_dec, i_frames );

        if( p_out )
        {
            p_out->i_pts = date_Get( &p_sys->date );
            p_out->i_length = date_Increment( &p_sys->date, i_frames )
                              - p_out->i_pts;

            memcpy( p_out->p_buffer,
                    &p_sys->out_buffer[2 * p_sys->i_out * p_dec->fmt_out.audio.i_channels],
                    p_out->i_buffer );

            p_sys->i_out += i_frames;
        }
        return p_out;
    }

    return NULL;
}
static block_t *DecodeBlock (decoder_t *p_dec, block_t **pp_block)
{
    block_t *p_block;
    decoder_sys_t *p_sys = p_dec->p_sys;
    block_t *p_out = NULL;

    if (pp_block == NULL)
        return NULL;
    p_block = *pp_block;
    if (p_block == NULL)
        return NULL;
    *pp_block = NULL;

    if (p_block->i_pts > VLC_TS_INVALID && !date_Get (&p_sys->end_date))
        date_Set (&p_sys->end_date, p_block->i_pts);
    else
    if (p_block->i_pts < date_Get (&p_sys->end_date))
    {
        msg_Warn (p_dec, "MIDI message in the past?");
        goto drop;
    }

    if (p_block->i_buffer < 1)
        goto drop;

    uint8_t event = p_block->p_buffer[0];
    uint8_t channel = p_block->p_buffer[0] & 0xf;
    event &= 0xF0;

    if (event == 0xF0)
        switch (channel)
        {
            case 0:
                if (p_block->p_buffer[p_block->i_buffer - 1] != 0xF7)
                {
            case 7:
                    msg_Warn (p_dec, "fragmented SysEx not implemented");
                    goto drop;
                }
                fluid_synth_sysex (p_sys->synth, (char *)p_block->p_buffer + 1,
                                   p_block->i_buffer - 2, NULL, NULL, NULL, 0);
                break;
            case 0xF:
                fluid_synth_system_reset (p_sys->synth);
                break;
        }

    uint8_t p1 = (p_block->i_buffer > 1) ? (p_block->p_buffer[1] & 0x7f) : 0;
    uint8_t p2 = (p_block->i_buffer > 2) ? (p_block->p_buffer[2] & 0x7f) : 0;

    switch (event & 0xF0)
    {
        case 0x80:
            fluid_synth_noteoff (p_sys->synth, channel, p1);
            break;
        case 0x90:
            fluid_synth_noteon (p_sys->synth, channel, p1, p2);
            break;
        /*case 0xA0: note aftertouch not implemented */
        case 0xB0:
            fluid_synth_cc (p_sys->synth, channel, p1, p2);
            break;
        case 0xC0:
            fluid_synth_program_change (p_sys->synth, channel, p1);
            break;
        case 0xD0:
            fluid_synth_channel_pressure (p_sys->synth, channel, p1);
            break;
        case 0xE0:
            fluid_synth_pitch_bend (p_sys->synth, channel, (p2 << 7) | p1);
            break;
    }

    unsigned samples =
        (p_block->i_pts - date_Get (&p_sys->end_date)) * 441 / 10000;
    if (samples == 0)
        goto drop;

    p_out = decoder_NewAudioBuffer (p_dec, samples);
    if (p_out == NULL)
        goto drop;

    p_out->i_pts = date_Get (&p_sys->end_date );
    p_out->i_length = date_Increment (&p_sys->end_date, samples)
                      - p_out->i_pts;
    fluid_synth_write_float (p_sys->synth, samples, p_out->p_buffer, 0, 2,
                             p_out->p_buffer, 1, 2);
drop:
    block_Release (p_block);
    return p_out;
}
示例#8
0
static aout_buffer_t *DecodeBlock (decoder_t *p_dec, block_t **pp_block)
{
    block_t *p_block;
    decoder_sys_t *p_sys = p_dec->p_sys;
    aout_buffer_t *p_out = NULL;

    if (pp_block == NULL)
        return NULL;
    p_block = *pp_block;
    if (p_block == NULL)
        return NULL;
    *pp_block = NULL;

    if (p_block->i_pts && !date_Get (&p_sys->end_date))
        date_Set (&p_sys->end_date, p_block->i_pts);
    else
    if (p_block->i_pts < date_Get (&p_sys->end_date))
    {
        msg_Warn (p_dec, "MIDI message in the past?");
        goto drop;
    }

    if (p_block->i_buffer < 1)
        goto drop;

    uint8_t channel = p_block->p_buffer[0] & 0xf;
    uint8_t p1 = (p_block->i_buffer > 1) ? (p_block->p_buffer[1] & 0x7f) : 0;
    uint8_t p2 = (p_block->i_buffer > 2) ? (p_block->p_buffer[2] & 0x7f) : 0;

    switch (p_block->p_buffer[0] & 0xf0)
    {
        case 0x80:
            fluid_synth_noteoff (p_sys->synth, channel, p1);
            break;
        case 0x90:
            fluid_synth_noteon (p_sys->synth, channel, p1, p2);
            break;
        case 0xB0:
            fluid_synth_cc (p_sys->synth, channel, p1, p2);
            break;
        case 0xC0:
            fluid_synth_program_change (p_sys->synth, channel, p1);
            break;
        case 0xE0:
            fluid_synth_pitch_bend (p_sys->synth, channel, (p1 << 7) | p2);
            break;
    }

    unsigned samples =
        (p_block->i_pts - date_Get (&p_sys->end_date)) * 441 / 10000;
    if (samples == 0)
        return NULL;

    p_out = decoder_NewAudioBuffer (p_dec, samples);
    if (p_out == NULL)
        goto drop;

    p_out->i_pts = date_Get (&p_sys->end_date );
    p_out->i_length = date_Increment (&p_sys->end_date, samples)
                      - p_out->i_pts;
    if (!p_sys->fixed)
        fluid_synth_write_float (p_sys->synth, samples,
                                 p_out->p_buffer, 0, 2,
                                 p_out->p_buffer, 1, 2);
    else
        fluid_synth_write_s16 (p_sys->synth, samples,
                               (int16_t *)p_out->p_buffer, 0, 2,
                               (int16_t *)p_out->p_buffer, 1, 2);
drop:
    block_Release (p_block);
    return p_out;
}
示例#9
0
文件: mft.c 项目: IAPark/vlc
static int ProcessOutputStream(decoder_t *p_dec, DWORD stream_id)
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    HRESULT hr;
    picture_t *picture = NULL;
    block_t *aout_buffer = NULL;

    DWORD output_status = 0;
    MFT_OUTPUT_DATA_BUFFER output_buffer = { stream_id, p_sys->output_sample, 0, NULL };
    hr = IMFTransform_ProcessOutput(p_sys->mft, 0, 1, &output_buffer, &output_status);
    if (output_buffer.pEvents)
        IMFCollection_Release(output_buffer.pEvents);
    /* Use the returned sample since it can be provided by the MFT. */
    IMFSample *output_sample = output_buffer.pSample;

    if (hr == S_OK)
    {
        if (!output_sample)
            return VLC_SUCCESS;

        LONGLONG sample_time;
        hr = IMFSample_GetSampleTime(output_sample, &sample_time);
        if (FAILED(hr))
            goto error;
        /* Convert from 100 nanoseconds unit to microseconds. */
        sample_time /= 10;

        DWORD total_length = 0;
        hr = IMFSample_GetTotalLength(output_sample, &total_length);
        if (FAILED(hr))
            goto error;

        if (p_dec->fmt_in.i_cat == VIDEO_ES)
        {
            if (decoder_UpdateVideoFormat(p_dec))
                return VLC_SUCCESS;
            picture = decoder_NewPicture(p_dec);
            if (!picture)
                return VLC_SUCCESS;

            UINT32 interlaced = false;
            hr = IMFSample_GetUINT32(output_sample, &MFSampleExtension_Interlaced, &interlaced);
            picture->b_progressive = !interlaced;

            picture->date = sample_time;
        }
        else
        {
            if (decoder_UpdateAudioFormat(p_dec))
                goto error;
            if (p_dec->fmt_out.audio.i_bitspersample == 0 || p_dec->fmt_out.audio.i_channels == 0)
                goto error;
            int samples = total_length / (p_dec->fmt_out.audio.i_bitspersample * p_dec->fmt_out.audio.i_channels / 8);
            aout_buffer = decoder_NewAudioBuffer(p_dec, samples);
            if (!aout_buffer)
                return VLC_SUCCESS;
            if (aout_buffer->i_buffer < total_length)
                goto error;

            aout_buffer->i_pts = sample_time;
        }

        IMFMediaBuffer *output_media_buffer = NULL;
        hr = IMFSample_GetBufferByIndex(output_sample, 0, &output_media_buffer);

        BYTE *buffer_start;
        hr = IMFMediaBuffer_Lock(output_media_buffer, &buffer_start, NULL, NULL);
        if (FAILED(hr))
            goto error;

        if (p_dec->fmt_in.i_cat == VIDEO_ES)
            CopyPackedBufferToPicture(picture, buffer_start);
        else
            memcpy(aout_buffer->p_buffer, buffer_start, total_length);

        hr = IMFMediaBuffer_Unlock(output_media_buffer);
        IMFSample_Release(output_media_buffer);
        if (FAILED(hr))
            goto error;

        if (p_sys->output_sample)
        {
            /* Sample is not provided by the MFT: clear its content. */
            hr = IMFMediaBuffer_SetCurrentLength(output_media_buffer, 0);
            if (FAILED(hr))
                goto error;
        }
        else
        {
            /* Sample is provided by the MFT: decrease refcount. */
            IMFSample_Release(output_sample);
        }
    }
    else if (hr == MF_E_TRANSFORM_STREAM_CHANGE || hr == MF_E_TRANSFORM_TYPE_NOT_SET)
    {
        if (p_sys->output_type)
            IMFMediaType_Release(p_sys->output_type);
        if (SetOutputType(p_dec, p_sys->output_stream_id, &p_sys->output_type))
            goto error;

        /* Reallocate output sample. */
        if (p_sys->output_sample)
            IMFSample_Release(p_sys->output_sample);
        p_sys->output_sample = NULL;
        if (AllocateOutputSample(p_dec, 0, &p_sys->output_sample))
            goto error;
        return VLC_SUCCESS;
    }
    else if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT)
    {
        return VLC_SUCCESS;
    }
    else /* An error not listed above occurred */
    {
        msg_Err(p_dec, "Unexpected error in IMFTransform::ProcessOutput: %#lx",
                hr);
        goto error;
    }

    if (p_dec->fmt_in.i_cat == VIDEO_ES)
        decoder_QueueVideo(p_dec, picture);
    else
        decoder_QueueAudio(p_dec, aout_buffer);

    return VLC_SUCCESS;

error:
    msg_Err(p_dec, "Error in ProcessOutputStream()");
    if (picture)
        picture_Release(picture);
    if (aout_buffer)
        block_Release(aout_buffer);
    return VLC_EGENERIC;
}
示例#10
0
文件: faad.c 项目: abhi1302/vlc
/*****************************************************************************
 * DecodeBlock:
 *****************************************************************************/
static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    block_t *p_block;

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

    p_block = *pp_block;

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

    /* Remove ADTS header if we have decoder specific config */
    if( p_dec->fmt_in.i_extra && p_block->i_buffer > 7 )
    {
        if( p_block->p_buffer[0] == 0xff &&
            ( p_block->p_buffer[1] & 0xf0 ) == 0xf0 ) /* syncword */
        {   /* ADTS header present */
            size_t i_header_size; /* 7 bytes (+ 2 bytes for crc) */
            i_header_size = 7 + ( ( p_block->p_buffer[1] & 0x01 ) ? 0 : 2 );
            /* FIXME: multiple blocks per frame */
            if( p_block->i_buffer > i_header_size )
            {
                p_block->p_buffer += i_header_size;
                p_block->i_buffer -= i_header_size;
            }
        }
    }

    /* Append the block to the temporary buffer */
    if( p_sys->i_buffer_size < p_sys->i_buffer + p_block->i_buffer )
    {
        size_t  i_buffer_size = p_sys->i_buffer + p_block->i_buffer;
        uint8_t *p_buffer     = realloc( p_sys->p_buffer, i_buffer_size );
        if( p_buffer )
        {
            p_sys->i_buffer_size = i_buffer_size;
            p_sys->p_buffer      = p_buffer;
        }
        else
        {
            p_block->i_buffer = 0;
        }
    }

    if( p_block->i_buffer > 0 )
    {
        memcpy( &p_sys->p_buffer[p_sys->i_buffer],
                     p_block->p_buffer, p_block->i_buffer );
        p_sys->i_buffer += p_block->i_buffer;
        p_block->i_buffer = 0;
    }

    if( p_dec->fmt_out.audio.i_rate == 0 && p_dec->fmt_in.i_extra > 0 )
    {
        /* We have a decoder config so init the handle */
        unsigned long i_rate;
        unsigned char i_channels;

        if( faacDecInit2( p_sys->hfaad, p_dec->fmt_in.p_extra,
                          p_dec->fmt_in.i_extra,
                          &i_rate, &i_channels ) >= 0 )
        {
            p_dec->fmt_out.audio.i_rate = i_rate;
            p_dec->fmt_out.audio.i_channels = i_channels;
            p_dec->fmt_out.audio.i_physical_channels
                = p_dec->fmt_out.audio.i_original_channels
                = pi_channels_guessed[i_channels];

            date_Init( &p_sys->date, i_rate, 1 );
        }
    }

    if( p_dec->fmt_out.audio.i_rate == 0 && p_sys->i_buffer )
    {
        unsigned long i_rate;
        unsigned char i_channels;

        /* Init faad with the first frame */
        if( faacDecInit( p_sys->hfaad,
                         p_sys->p_buffer, p_sys->i_buffer,
                         &i_rate, &i_channels ) < 0 )
        {
            block_Release( p_block );
            return NULL;
        }

        p_dec->fmt_out.audio.i_rate = i_rate;
        p_dec->fmt_out.audio.i_channels = i_channels;
        p_dec->fmt_out.audio.i_physical_channels
            = p_dec->fmt_out.audio.i_original_channels
            = pi_channels_guessed[i_channels];
        date_Init( &p_sys->date, i_rate, 1 );
    }

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

    /* Decode all data */
    if( p_sys->i_buffer )
    {
        void *samples;
        faacDecFrameInfo frame;
        block_t *p_out;

        samples = faacDecDecode( p_sys->hfaad, &frame,
                                 p_sys->p_buffer, p_sys->i_buffer );

        if( frame.error > 0 )
        {
            msg_Warn( p_dec, "%s", faacDecGetErrorMessage( frame.error ) );

            if( frame.error == 21 || frame.error == 12 )
            {
                /*
                 * Once an "Unexpected channel configuration change"
                 * or a "Invalid number of channels" error
                 * occurs, it will occurs afterwards, and we got no sound.
                 * Reinitialization of the decoder is required.
                 */
                unsigned long i_rate;
                unsigned char i_channels;
                faacDecHandle *hfaad;
                faacDecConfiguration *cfg,*oldcfg;

                oldcfg = faacDecGetCurrentConfiguration( p_sys->hfaad );
                hfaad = faacDecOpen();
                cfg = faacDecGetCurrentConfiguration( hfaad );
                if( oldcfg->defSampleRate )
                    cfg->defSampleRate = oldcfg->defSampleRate;
                cfg->defObjectType = oldcfg->defObjectType;
                cfg->outputFormat = oldcfg->outputFormat;
                faacDecSetConfiguration( hfaad, cfg );

                if( faacDecInit( hfaad, p_sys->p_buffer, p_sys->i_buffer,
                                &i_rate,&i_channels ) < 0 )
                {
                    /* reinitialization failed */
                    faacDecClose( hfaad );
                    faacDecSetConfiguration( p_sys->hfaad, oldcfg );
                }
                else
                {
                    faacDecClose( p_sys->hfaad );
                    p_sys->hfaad = hfaad;
                    p_dec->fmt_out.audio.i_rate = i_rate;
                    p_dec->fmt_out.audio.i_channels = i_channels;
                    p_dec->fmt_out.audio.i_physical_channels
                        = p_dec->fmt_out.audio.i_original_channels
                        = pi_channels_guessed[i_channels];
                    date_Init( &p_sys->date, i_rate, 1 );
                }
            }

            /* Flush the buffer */
            p_sys->i_buffer = 0;
            block_Release( p_block );
            return NULL;
        }

        if( frame.channels <= 0 || frame.channels > 8 || frame.channels == 7 )
        {
            msg_Warn( p_dec, "invalid channels count: %i", frame.channels );

            /* Flush the buffer */
            p_sys->i_buffer -= frame.bytesconsumed;
            if( p_sys->i_buffer > 0 )
            {
                memmove( p_sys->p_buffer,&p_sys->p_buffer[frame.bytesconsumed],
                         p_sys->i_buffer );
            }
            block_Release( p_block );
            return NULL;
        }

        if( frame.samples <= 0 )
        {
            msg_Warn( p_dec, "decoded zero sample" );

            /* Flush the buffer */
            p_sys->i_buffer -= frame.bytesconsumed;
            if( p_sys->i_buffer > 0 )
            {
                memmove( p_sys->p_buffer,&p_sys->p_buffer[frame.bytesconsumed],
                         p_sys->i_buffer );
            }
            block_Release( p_block );
            return NULL;
        }

        /* We decoded a valid frame */
        if( p_dec->fmt_out.audio.i_rate != frame.samplerate )
        {
            date_Init( &p_sys->date, frame.samplerate, 1 );
            date_Set( &p_sys->date, p_block->i_pts );
        }
        p_block->i_pts = VLC_TS_INVALID;  /* PTS is valid only once */

        p_dec->fmt_out.audio.i_rate = frame.samplerate;
        p_dec->fmt_out.audio.i_channels = frame.channels;

        /* Adjust stream info when dealing with SBR/PS */
        bool b_sbr = (frame.sbr == 1) || (frame.sbr == 2);
        if( p_sys->b_sbr != b_sbr || p_sys->b_ps != frame.ps )
        {
            const char *psz_ext = (b_sbr && frame.ps) ? "SBR+PS" :
                                    b_sbr ? "SBR" : "PS";

            msg_Dbg( p_dec, "AAC %s (channels: %u, samplerate: %lu)",
                    psz_ext, frame.channels, frame.samplerate );

            if( !p_dec->p_description )
                p_dec->p_description = vlc_meta_New();
            if( p_dec->p_description )
                vlc_meta_AddExtra( p_dec->p_description, _("AAC extension"), psz_ext );

            p_sys->b_sbr = b_sbr;
            p_sys->b_ps = frame.ps;
        }

        /* Convert frame.channel_position to our own channel values */
        p_dec->fmt_out.audio.i_physical_channels = 0;
        const uint32_t nbChannels = frame.channels;
        unsigned j;
        for( unsigned i = 0; i < nbChannels; i++ )
        {
            /* Find the channel code */
            for( j = 0; j < MAX_CHANNEL_POSITIONS; j++ )
            {
                if( frame.channel_position[i] == pi_channels_in[j] )
                    break;
            }
            if( j >= MAX_CHANNEL_POSITIONS )
            {
                msg_Warn( p_dec, "unknown channel ordering" );
                /* Invent something */
                j = i;
            }
            /* */
            p_sys->pi_channel_positions[i] = pi_channels_out[j];
            if( p_dec->fmt_out.audio.i_physical_channels & pi_channels_out[j] )
                frame.channels--; /* We loose a duplicated channel */
            else
                p_dec->fmt_out.audio.i_physical_channels |= pi_channels_out[j];
        }
        if ( nbChannels != frame.channels )
        {
            p_dec->fmt_out.audio.i_physical_channels
                = p_dec->fmt_out.audio.i_original_channels
                = pi_channels_guessed[nbChannels];
        }
        else
        {
            p_dec->fmt_out.audio.i_original_channels =
                p_dec->fmt_out.audio.i_physical_channels;
        }
        p_dec->fmt_out.audio.i_channels = nbChannels;
        p_out = decoder_NewAudioBuffer( p_dec, frame.samples / nbChannels );
        if( p_out == NULL )
        {
            p_sys->i_buffer = 0;
            block_Release( p_block );
            return NULL;
        }

        p_out->i_pts = date_Get( &p_sys->date );
        p_out->i_length = date_Increment( &p_sys->date,
                                          frame.samples / nbChannels )
                          - p_out->i_pts;

        DoReordering( (uint32_t *)p_out->p_buffer, samples,
                      frame.samples / nbChannels, nbChannels,
                      p_sys->pi_channel_positions );

        p_sys->i_buffer -= frame.bytesconsumed;
        if( p_sys->i_buffer > 0 )
        {
            memmove( p_sys->p_buffer, &p_sys->p_buffer[frame.bytesconsumed],
                     p_sys->i_buffer );
        }

        return p_out;
    }

    block_Release( p_block );
    return NULL;
}
示例#11
0
/*****************************************************************************
 * DecodeAudio: Called to decode one frame
 *****************************************************************************/
block_t * DecodeAudio ( decoder_t *p_dec, block_t **pp_block )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    AVCodecContext *ctx = p_sys->p_context;

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

    block_t *p_block = *pp_block;

    if( !ctx->extradata_size && p_dec->fmt_in.i_extra && p_sys->b_delayed_open)
    {
        InitDecoderConfig( p_dec, ctx );
        if( ffmpeg_OpenCodec( p_dec ) )
            msg_Err( p_dec, "Cannot open decoder %s", p_sys->psz_namecodec );
    }

    if( p_sys->b_delayed_open )
        goto end;

    if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
    {
        avcodec_flush_buffers( ctx );
        date_Set( &p_sys->end_date, 0 );

        if( p_sys->i_codec_id == AV_CODEC_ID_MP2 || p_sys->i_codec_id == AV_CODEC_ID_MP3 )
            p_sys->i_reject_count = 3;

        goto end;
    }

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

    if( p_block->i_buffer <= 0 )
        goto end;

    if( (p_block->i_flags & BLOCK_FLAG_PRIVATE_REALLOCATED) == 0 )
    {
        p_block = block_Realloc( p_block, 0, p_block->i_buffer + FF_INPUT_BUFFER_PADDING_SIZE );
        if( !p_block )
            return NULL;
        p_block->i_buffer -= FF_INPUT_BUFFER_PADDING_SIZE;
        memset( &p_block->p_buffer[p_block->i_buffer], 0, FF_INPUT_BUFFER_PADDING_SIZE );

        p_block->i_flags |= BLOCK_FLAG_PRIVATE_REALLOCATED;
    }

    AVFrame frame;
    memset( &frame, 0, sizeof( frame ) );

    for( int got_frame = 0; !got_frame; )
    {
        if( p_block->i_buffer == 0 )
            goto end;

        AVPacket pkt;
        av_init_packet( &pkt );
        pkt.data = p_block->p_buffer;
        pkt.size = p_block->i_buffer;

        int used = avcodec_decode_audio4( ctx, &frame, &got_frame, &pkt );
        if( used < 0 )
        {
            msg_Warn( p_dec, "cannot decode one frame (%zu bytes)",
                      p_block->i_buffer );
            goto end;
        }

        assert( p_block->i_buffer >= (unsigned)used );
        p_block->p_buffer += used;
        p_block->i_buffer -= used;
    }

    if( ctx->channels <= 0 || ctx->channels > 8 || ctx->sample_rate <= 0 )
    {
        msg_Warn( p_dec, "invalid audio properties channels count %d, sample rate %d",
                  ctx->channels, ctx->sample_rate );
        goto end;
    }

    if( p_dec->fmt_out.audio.i_rate != (unsigned int)ctx->sample_rate )
        date_Init( &p_sys->end_date, ctx->sample_rate, 1 );

    if( p_block->i_pts > VLC_TS_INVALID &&
        p_block->i_pts > date_Get( &p_sys->end_date ) )
    {
        date_Set( &p_sys->end_date, p_block->i_pts );
    }

    if( p_block->i_buffer == 0 )
    {   /* Done with this buffer */
        block_Release( p_block );
        *pp_block = NULL;
    }

    /* NOTE WELL: Beyond this point, p_block now refers to the DECODED block */
    p_block = frame.opaque;
    SetupOutputFormat( p_dec, true );

    /* Silent unwanted samples */
    if( p_sys->i_reject_count > 0 )
    {
        memset( p_block->p_buffer, 0, p_block->i_buffer );
        p_sys->i_reject_count--;
    }

    block_t *p_buffer = decoder_NewAudioBuffer( p_dec, p_block->i_nb_samples );
    if (!p_buffer)
        return NULL;
    assert( p_block->i_nb_samples >= (unsigned)frame.nb_samples );
    assert( p_block->i_nb_samples == p_buffer->i_nb_samples );
    p_block->i_buffer = p_buffer->i_buffer; /* drop buffer padding */

    /* Interleave audio if required */
    if( av_sample_fmt_is_planar( ctx->sample_fmt ) )
    {
        aout_Interleave( p_buffer->p_buffer, p_block->p_buffer,
                         p_block->i_nb_samples, ctx->channels,
                         p_dec->fmt_out.audio.i_format );
        if( ctx->channels > AV_NUM_DATA_POINTERS )
            free( frame.extended_data );
        block_Release( p_block );
        p_block = p_buffer;
    }
    else /* FIXME: improve decoder_NewAudioBuffer(), avoid useless buffer... */
        block_Release( p_buffer );

    if (p_sys->b_extract)
    {   /* TODO: do not drop channels... at least not here */
        p_buffer = block_Alloc( p_dec->fmt_out.audio.i_bytes_per_frame
                                * frame.nb_samples );
        if( unlikely(p_buffer == NULL) )
        {
            block_Release( p_block );
            return NULL;
        }
        aout_ChannelExtract( p_buffer->p_buffer,
                             p_dec->fmt_out.audio.i_channels,
                             p_block->p_buffer, ctx->channels,
                             frame.nb_samples, p_sys->pi_extraction,
                             p_dec->fmt_out.audio.i_bitspersample );
        block_Release( p_block );
        p_block = p_buffer;
    }

    p_block->i_nb_samples = frame.nb_samples;
    p_block->i_buffer = frame.nb_samples
                        * p_dec->fmt_out.audio.i_bytes_per_frame;
    p_block->i_pts = date_Get( &p_sys->end_date );
    p_block->i_length = date_Increment( &p_sys->end_date, frame.nb_samples )
                        - p_block->i_pts;
    return p_block;

end:
    block_Release(p_block);
    *pp_block = NULL;
    return NULL;
}
示例#12
0
/*****************************************************************************
 * DecodeAudio:
 *****************************************************************************/
static aout_buffer_t *Decode( decoder_t *p_dec, block_t **pp_block )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    aout_buffer_t *p_aout_buffer = 0;
    unsigned int i_result;
    int i_samples;
    block_t *p_block;

#ifdef LOADER
    if( !p_sys->win32_dll && !p_sys->dll )
    {
        /* We must do open and close in the same thread (unless we do
         * Setup_LDT_Keeper in the main thread before all others */
        if( OpenDll( p_dec ) != VLC_SUCCESS )
        {
            /* Fatal */
            p_dec->b_error = true;
            return NULL;
        }
    }
#endif

    if( pp_block == NULL || *pp_block == NULL ) return NULL;
    p_block = *pp_block;

    if( p_sys->dll )
        i_result = p_sys->raDecode( p_sys->context, (char *)p_block->p_buffer,
                                    (unsigned long)p_block->i_buffer,
                                    p_sys->p_out, &p_sys->i_out, -1 );
    else
        i_result = p_sys->wraDecode( p_sys->context, (char *)p_block->p_buffer,
                                     (unsigned long)p_block->i_buffer,
                                     p_sys->p_out, &p_sys->i_out, -1 );

#if 0
    msg_Err( p_dec, "decoded: %i samples (%i)",
             p_sys->i_out * 8 / p_dec->fmt_out.audio.i_bitspersample /
             p_dec->fmt_out.audio.i_channels, i_result );
#endif

    /* Date management */
    if( p_block->i_pts > 0 &&
        p_block->i_pts != date_Get( &p_sys->end_date ) )
    {
        date_Set( &p_sys->end_date, p_block->i_pts );
    }

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

    i_samples = p_sys->i_out * 8 /
        p_dec->fmt_out.audio.i_bitspersample /p_dec->fmt_out.audio.i_channels;

    p_aout_buffer =
        decoder_NewAudioBuffer( p_dec, i_samples );
    if( p_aout_buffer )
    {
        memcpy( p_aout_buffer->p_buffer, p_sys->p_out, p_sys->i_out );

        /* Date management */
        p_aout_buffer->start_date = date_Get( &p_sys->end_date );
        p_aout_buffer->end_date =
            date_Increment( &p_sys->end_date, i_samples );
    }

    block_Release( p_block );
    *pp_block = 0;
    return p_aout_buffer;
}
示例#13
0
文件: faad.c 项目: Kafay/vlc
/*****************************************************************************
 * DecodeBlock:
 *****************************************************************************/
static aout_buffer_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
{
    decoder_sys_t *p_sys = p_dec->p_sys;
    block_t *p_block;

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

    p_block = *pp_block;

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

    /* Remove ADTS header if we have decoder specific config */
    if( p_dec->fmt_in.i_extra && p_block->i_buffer > 7 )
    {
        if( p_block->p_buffer[0] == 0xff &&
            ( p_block->p_buffer[1] & 0xf0 ) == 0xf0 ) /* syncword */
        {   /* ADTS header present */
            size_t i_header_size; /* 7 bytes (+ 2 bytes for crc) */
            i_header_size = 7 + ( ( p_block->p_buffer[1] & 0x01 ) ? 0 : 2 );
            /* FIXME: multiple blocks per frame */
            if( p_block->i_buffer > i_header_size )
            {
                vlc_memcpy( p_block->p_buffer,
                            p_block->p_buffer + i_header_size,
                            p_block->i_buffer - i_header_size );
                p_block->i_buffer -= i_header_size;
            }
        }
    }

    /* Append the block to the temporary buffer */
    if( p_sys->i_buffer_size < p_sys->i_buffer + p_block->i_buffer )
    {
        p_sys->i_buffer_size = p_sys->i_buffer + p_block->i_buffer;
        p_sys->p_buffer = realloc( p_sys->p_buffer, p_sys->i_buffer_size );
    }

    if( p_block->i_buffer > 0 )
    {
        vlc_memcpy( &p_sys->p_buffer[p_sys->i_buffer],
                     p_block->p_buffer, p_block->i_buffer );
        p_sys->i_buffer += p_block->i_buffer;
        p_block->i_buffer = 0;
    }

    if( p_dec->fmt_out.audio.i_rate == 0 && p_dec->fmt_in.i_extra > 0 )
    {
        /* We have a decoder config so init the handle */
        unsigned long i_rate;
        unsigned char i_channels;

        if( faacDecInit2( p_sys->hfaad, p_dec->fmt_in.p_extra,
                          p_dec->fmt_in.i_extra,
                          &i_rate, &i_channels ) >= 0 )
        {
            p_dec->fmt_out.audio.i_rate = i_rate;
            p_dec->fmt_out.audio.i_channels = i_channels;
            p_dec->fmt_out.audio.i_physical_channels
                = p_dec->fmt_out.audio.i_original_channels
                = pi_channels_guessed[i_channels];

            aout_DateInit( &p_sys->date, i_rate );
        }
    }

    if( p_dec->fmt_out.audio.i_rate == 0 && p_sys->i_buffer )
    {
        unsigned long i_rate;
        unsigned char i_channels;

        /* Init faad with the first frame */
        if( faacDecInit( p_sys->hfaad,
                         p_sys->p_buffer, p_sys->i_buffer,
                         &i_rate, &i_channels ) < 0 )
        {
            block_Release( p_block );
            return NULL;
        }

        p_dec->fmt_out.audio.i_rate = i_rate;
        p_dec->fmt_out.audio.i_channels = i_channels;
        p_dec->fmt_out.audio.i_physical_channels
            = p_dec->fmt_out.audio.i_original_channels
            = pi_channels_guessed[i_channels];
        aout_DateInit( &p_sys->date, i_rate );
    }

    if( p_block->i_pts != 0 && p_block->i_pts != aout_DateGet( &p_sys->date ) )
    {
        aout_DateSet( &p_sys->date, p_block->i_pts );
    }
    else if( !aout_DateGet( &p_sys->date ) )
    {
        /* We've just started the stream, wait for the first PTS. */
        block_Release( p_block );
        p_sys->i_buffer = 0;
        return NULL;
    }

    /* Decode all data */
    if( p_sys->i_buffer )
    {
        void *samples;
        faacDecFrameInfo frame;
        aout_buffer_t *p_out;
        int i, j;

        samples = faacDecDecode( p_sys->hfaad, &frame,
                                 p_sys->p_buffer, p_sys->i_buffer );

        if( frame.error > 0 )
        {
            msg_Warn( p_dec, "%s", faacDecGetErrorMessage( frame.error ) );

            /* Flush the buffer */
            p_sys->i_buffer = 0;
            block_Release( p_block );
            return NULL;
        }

        if( frame.channels <= 0 || frame.channels > 8 || frame.channels == 7 )
        {
            msg_Warn( p_dec, "invalid channels count: %i", frame.channels );

            /* Flush the buffer */
            p_sys->i_buffer -= frame.bytesconsumed;
            if( p_sys->i_buffer > 0 )
            {
                memmove( p_sys->p_buffer,&p_sys->p_buffer[frame.bytesconsumed],
                         p_sys->i_buffer );
            }
            block_Release( p_block );
            return NULL;
        }

        if( frame.samples <= 0 )
        {
            msg_Warn( p_dec, "decoded zero sample" );

            /* Flush the buffer */
            p_sys->i_buffer -= frame.bytesconsumed;
            if( p_sys->i_buffer > 0 )
            {
                memmove( p_sys->p_buffer,&p_sys->p_buffer[frame.bytesconsumed],
                         p_sys->i_buffer );
            }
            block_Release( p_block );
            return NULL;
        }

        /* We decoded a valid frame */
        if( p_dec->fmt_out.audio.i_rate != frame.samplerate )
        {
            aout_DateInit( &p_sys->date, frame.samplerate );
            aout_DateSet( &p_sys->date, p_block->i_pts );
        }
        p_block->i_pts = 0;  /* PTS is valid only once */

        p_dec->fmt_out.audio.i_rate = frame.samplerate;
        p_dec->fmt_out.audio.i_channels = frame.channels;
        p_dec->fmt_out.audio.i_physical_channels
            = p_dec->fmt_out.audio.i_original_channels
            = pi_channels_guessed[frame.channels];

        /* Adjust stream info when dealing with SBR/PS */
        if( p_sys->b_sbr != frame.sbr || p_sys->b_ps != frame.ps )
        {
            const char *psz_ext = (frame.sbr && frame.ps) ? "SBR+PS" :
                                    frame.sbr ? "SBR" : "PS";

            msg_Dbg( p_dec, "AAC %s (channels: %u, samplerate: %lu)",
                    psz_ext, frame.channels, frame.samplerate );

            if( !p_dec->p_description )
                p_dec->p_description = vlc_meta_New();
            if( p_dec->p_description )
                vlc_meta_AddExtra( p_dec->p_description, _("AAC extension"), psz_ext );

            p_sys->b_sbr = frame.sbr; p_sys->b_ps = frame.ps;
        }

        /* Convert frame.channel_position to our own channel values */
        p_dec->fmt_out.audio.i_physical_channels = 0;
        for( i = 0; i < frame.channels; i++ )
        {
            /* Find the channel code */
            for( j = 0; j < MAX_CHANNEL_POSITIONS; j++ )
            {
                if( frame.channel_position[i] == pi_channels_in[j] )
                    break;
            }
            if( j >= MAX_CHANNEL_POSITIONS )
            {
                msg_Warn( p_dec, "unknown channel ordering" );
                /* Invent something */
                j = i;
            }
            /* */
            p_sys->pi_channel_positions[i] = pi_channels_out[j];
            if( p_dec->fmt_out.audio.i_physical_channels & pi_channels_out[j] )
                frame.channels--; /* We loose a duplicated channel */
            else
                p_dec->fmt_out.audio.i_physical_channels |= pi_channels_out[j];
        }
        p_dec->fmt_out.audio.i_original_channels =
            p_dec->fmt_out.audio.i_physical_channels;

        p_out = decoder_NewAudioBuffer(p_dec, frame.samples/frame.channels);
        if( p_out == NULL )
        {
            p_sys->i_buffer = 0;
            block_Release( p_block );
            return NULL;
        }

        p_out->start_date = aout_DateGet( &p_sys->date );
        p_out->end_date = aout_DateIncrement( &p_sys->date, frame.samples / frame.channels );

        DoReordering( (uint32_t *)p_out->p_buffer, samples,
                      frame.samples / frame.channels, frame.channels,
                      p_sys->pi_channel_positions );

        p_sys->i_buffer -= frame.bytesconsumed;
        if( p_sys->i_buffer > 0 )
        {
            memmove( p_sys->p_buffer, &p_sys->p_buffer[frame.bytesconsumed],
                     p_sys->i_buffer );
        }

        return p_out;
    }

    block_Release( p_block );
    return NULL;
}
示例#14
0
文件: adpcm.c 项目: IAPark/vlc
/*****************************************************************************
 * DecodeBlock:
 *****************************************************************************/
static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
{
    decoder_sys_t *p_sys  = p_dec->p_sys;
    block_t *p_block;

    if( !*pp_block ) return NULL;

    p_block = *pp_block;

    if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
    {
        Flush( p_dec );
        if( p_block->i_flags & BLOCK_FLAG_CORRUPTED )
            goto drop;
    }

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

    /* Don't re-use the same pts twice */
    p_block->i_pts = VLC_TS_INVALID;

    if( p_block->i_buffer >= p_sys->i_block )
    {
        block_t *p_out;

        if( decoder_UpdateAudioFormat( p_dec ) )
            goto drop;
        p_out = decoder_NewAudioBuffer( p_dec, p_sys->i_samplesperblock );
        if( p_out == NULL )
            goto drop;

        p_out->i_pts = date_Get( &p_sys->end_date );
        p_out->i_length = date_Increment( &p_sys->end_date,
                                     p_sys->i_samplesperblock ) - p_out->i_pts;

        switch( p_sys->codec )
        {
        case ADPCM_IMA_QT:
            DecodeAdpcmImaQT( p_dec, (int16_t*)p_out->p_buffer,
                              p_block->p_buffer );
            break;
        case ADPCM_IMA_WAV:
            DecodeAdpcmImaWav( p_dec, (int16_t*)p_out->p_buffer,
                               p_block->p_buffer );
            break;
        case ADPCM_MS:
            DecodeAdpcmMs( p_dec, (int16_t*)p_out->p_buffer,
                           p_block->p_buffer );
            break;
        case ADPCM_DK4:
            DecodeAdpcmDk4( p_dec, (int16_t*)p_out->p_buffer,
                            p_block->p_buffer );
            break;
        case ADPCM_DK3:
            DecodeAdpcmDk3( p_dec, (int16_t*)p_out->p_buffer,
                            p_block->p_buffer );
            break;
        case ADPCM_EA:
            DecodeAdpcmEA( p_dec, (int16_t*)p_out->p_buffer,
                           p_block->p_buffer );
        default:
            break;
        }

        p_block->p_buffer += p_sys->i_block;
        p_block->i_buffer -= p_sys->i_block;
        return p_out;
    }

drop:
    block_Release( p_block );
    *pp_block = NULL;
    return NULL;
}
示例#15
0
static block_t *DecodeRtpSpeexPacket( decoder_t *p_dec, block_t **pp_block )
{
    block_t *p_speex_bit_block = *pp_block;
    decoder_sys_t *p_sys = p_dec->p_sys;
    block_t *p_aout_buffer;
    int i_decode_ret;
    unsigned int i_speex_frame_size;

    if ( !p_speex_bit_block || p_speex_bit_block->i_pts <= VLC_TS_INVALID )
        return NULL;

    /*
      If the SpeexBits buffer size is 0 (a default value),
      we know that a proper initialization has not yet been done.
    */
    if ( p_sys->bits.buf_size==0 )
    {
        p_sys->p_header = (SpeexHeader *)malloc(sizeof(SpeexHeader));
        if ( !p_sys->p_header )
        {
            msg_Err( p_dec, "Could not allocate a Speex header.");
            return NULL;
        }
        speex_init_header( p_sys->p_header,p_sys->rtp_rate,1,&speex_nb_mode );
            speex_bits_init( &p_sys->bits );
        p_sys->p_state = speex_decoder_init( &speex_nb_mode );
        if ( !p_sys->p_state )
        {
            msg_Err( p_dec, "Could not allocate a Speex decoder." );
            free( p_sys->p_header );
            return NULL;
        }

            /*
          Assume that variable bit rate is enabled. Also assume
          that there is only one frame per packet.
        */
        p_sys->p_header->vbr = 1;
        p_sys->p_header->frames_per_packet = 1;

            p_dec->fmt_out.audio.i_channels = p_sys->p_header->nb_channels;
        p_dec->fmt_out.audio.i_physical_channels =
        p_dec->fmt_out.audio.i_original_channels =
            pi_channels_maps[p_sys->p_header->nb_channels];
            p_dec->fmt_out.audio.i_rate = p_sys->p_header->rate;

            if ( speex_mode_query( &speex_nb_mode,
            SPEEX_MODE_FRAME_SIZE,
            &i_speex_frame_size ) )
        {
            msg_Err( p_dec, "Could not determine the frame size." );
            speex_decoder_destroy( p_sys->p_state );
            free( p_sys->p_header );
            return NULL;
        }
        p_dec->fmt_out.audio.i_bytes_per_frame = i_speex_frame_size;

        date_Init(&p_sys->end_date, p_sys->p_header->rate, 1);
    }

    /*
      If the SpeexBits are initialized but there is
      still no header, an error must be thrown.
    */
    if ( !p_sys->p_header )
    {
        msg_Err( p_dec, "There is no valid Speex header found." );
        return NULL;
    }
    *pp_block = NULL;

    if ( !date_Get( &p_sys->end_date ) )
        date_Set( &p_sys->end_date, p_speex_bit_block->i_dts );

    /*
      Ask for a new audio output buffer and make sure
      we get one.
    */
    p_aout_buffer = decoder_NewAudioBuffer( p_dec,
        p_sys->p_header->frame_size );
    if ( !p_aout_buffer || p_aout_buffer->i_buffer == 0 )
    {
        msg_Err(p_dec, "Oops: No new buffer was returned!");
        return NULL;
    }

    /*
      Read the Speex payload into the SpeexBits buffer.
    */
    speex_bits_read_from( &p_sys->bits,
        (char*)p_speex_bit_block->p_buffer,
        p_speex_bit_block->i_buffer );

    /*
      Decode the input and ensure that no errors
      were encountered.
    */
    i_decode_ret = speex_decode_int( p_sys->p_state, &p_sys->bits,
            (int16_t*)p_aout_buffer->p_buffer );
    if ( i_decode_ret < 0 )
    {
        msg_Err( p_dec, "Decoding failed. Perhaps we have a bad stream?" );
        return NULL;
    }

    /*
      Handle date management on the audio output buffer.
    */
    p_aout_buffer->i_pts = date_Get( &p_sys->end_date );
    p_aout_buffer->i_length = date_Increment( &p_sys->end_date,
        p_sys->p_header->frame_size ) - p_aout_buffer->i_pts;


    p_sys->i_frame_in_packet++;
    block_Release( p_speex_bit_block );

    return p_aout_buffer;
}
示例#16
0
文件: mpg123.c 项目: AWaddingham/vlc
/****************************************************************************
 * DecodeBlock: the whole thing
 ****************************************************************************/
static block_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
{
    int i_err;
    block_t *p_block = pp_block ? *pp_block : NULL;
    decoder_sys_t *p_sys = p_dec->p_sys;

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

    if( p_block->i_buffer == 0 )
        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. */
        msg_Dbg( p_dec, "waiting for PTS" );
        goto error;
    }

    if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY | BLOCK_FLAG_CORRUPTED) )
    {
        date_Set( &p_sys->end_date, 0 );
        if( p_block->i_flags & BLOCK_FLAG_CORRUPTED )
            goto error;
    }

    /* Feed mpg123 with raw data */
    i_err = mpg123_feed( p_sys->p_handle, p_block->p_buffer,
                         p_block->i_buffer );

    if( i_err != MPG123_OK )
    {
        msg_Err( p_dec, "mpg123_feed failed: %s", mpg123_plain_strerror( i_err ) );
        goto error;
    }

    /* Get details about the stream */
    i_err = mpg123_info( p_sys->p_handle, &p_sys->frame_info );

    if( i_err == MPG123_NEED_MORE )
    {
        /* Need moar data */
        goto error;
    }
    else if( i_err != MPG123_OK )
    {
        msg_Err( p_dec, "mpg123_info failed: %s", mpg123_plain_strerror( i_err ) );
        goto error;
    }

    /* Configure the output */
    p_block->i_nb_samples = mpg123_spf( p_sys->p_handle );
    p_dec->fmt_out.i_bitrate = p_sys->frame_info.bitrate * 1000;

    switch( p_sys->frame_info.mode )
    {
        case MPG123_M_STEREO:
        case MPG123_M_JOINT:
            p_dec->fmt_out.audio.i_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT;
            break;
        case MPG123_M_DUAL:
            p_dec->fmt_out.audio.i_original_channels = AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT
                                                     | AOUT_CHAN_DUALMONO;
            break;
        case MPG123_M_MONO:
            p_dec->fmt_out.audio.i_original_channels = AOUT_CHAN_CENTER;
            break;
        default:
            msg_Err( p_dec, "Unknown mode");
            goto error;
    }

    p_dec->fmt_out.audio.i_physical_channels =
        p_dec->fmt_out.audio.i_original_channels & AOUT_CHAN_PHYSMASK;

    /* Date management */
    if( p_dec->fmt_out.audio.i_rate != p_sys->frame_info.rate )
    {
        p_dec->fmt_out.audio.i_rate = p_sys->frame_info.rate;
        date_Init( &p_sys->end_date, p_dec->fmt_out.audio.i_rate, 1 );
        date_Set( &p_sys->end_date, 0 );
    }

    if( p_block->i_pts > VLC_TS_INVALID &&
        p_block->i_pts != date_Get( &p_sys->end_date ) )
    {
        date_Set( &p_sys->end_date, p_block->i_pts );
    }

    /* Request a new audio buffer */
    block_t *p_out = decoder_NewAudioBuffer( p_dec, p_block->i_nb_samples );
    if( unlikely( !p_out ) )
        goto error;

    /* Configure the buffer */
    p_out->i_nb_samples = p_block->i_nb_samples;
    p_out->i_dts = p_out->i_pts = date_Get( &p_sys->end_date );
    p_out->i_length = date_Increment( &p_sys->end_date, p_block->i_nb_samples )
        - p_out->i_pts;

    /* Make mpg123 write directly into the VLC output buffer */
    i_err = mpg123_replace_buffer( p_sys->p_handle, p_out->p_buffer, p_out->i_buffer );
    if( i_err != MPG123_OK )
    {
        msg_Err( p_dec, "could not replace buffer: %s", mpg123_plain_strerror( i_err ) );
        block_Release( p_out );
        goto error;
    }

    *pp_block = NULL; /* avoid being fed the same packet again */

    /* Do the actual decoding now */
    i_err = mpg123_decode_frame( p_sys->p_handle, NULL, NULL, NULL );
    if( i_err != MPG123_OK )
    {
        if( i_err != MPG123_NEW_FORMAT )
            msg_Err( p_dec, "mpg123_decode_frame error: %s", mpg123_plain_strerror( i_err ) );
        block_Release( p_out );
        goto error;
    }

    block_Release( p_block );
    return p_out;

error:
    block_Release( p_block );
    return NULL;
}