Example #1
0
/***********************************************************************
 * Encode
 ***********************************************************************
 *
 **********************************************************************/
static hb_buffer_t * Encode( hb_work_object_t * w )
{
    hb_work_private_t * pv = w->private_data;
    hb_buffer_t * buf;
    float ** buffer;
    int i, j;

    /* Try to extract more data */
    if( ( buf = Flush( w ) ) )
    {
        return buf;
    }

    if( hb_list_bytes( pv->list ) < pv->input_samples * sizeof( float ) )
    {
        return NULL;
    }

    /* Process more samples */
    hb_list_getbytes( pv->list, pv->buf, pv->input_samples * sizeof( float ),
                      &pv->pts, NULL );
    buffer = vorbis_analysis_buffer( &pv->vd, OGGVORBIS_FRAME_SIZE );
    for( i = 0; i < OGGVORBIS_FRAME_SIZE; i++ )
    {
        for( j = 0; j < pv->out_discrete_channels; j++)
        {
            buffer[j][i] = ((float *) pv->buf)[(pv->out_discrete_channels * i + pv->channel_map[j])];
        }
    }

    vorbis_analysis_wrote( &pv->vd, OGGVORBIS_FRAME_SIZE );

    /* Try to extract again */
    return Flush( w );
}
Example #2
0
/***********************************************************************
 * Encode
 ***********************************************************************
 *
 **********************************************************************/
static hb_buffer_t * Encode( hb_work_object_t * w )
{
    hb_work_private_t * pv = w->private_data;
    hb_audio_t * audio = w->audio;
    hb_buffer_t * buf;
    float samples[2][1152];
    uint64_t pts, pos;
    int      i, j;

    if( hb_list_bytes( pv->list ) < pv->input_samples * sizeof( float ) )
    {
        return NULL;
    }

    hb_list_getbytes( pv->list, pv->buf, pv->input_samples * sizeof( float ),
                      &pts, &pos);

    for( i = 0; i < 1152; i++ )
    {
        for( j = 0; j < pv->out_discrete_channels; j++ )
        {
            samples[j][i] = ((float *) pv->buf)[(pv->out_discrete_channels * i + j)];
        }
    }

    buf        = hb_buffer_init( pv->output_bytes );
    buf->s.start = pts + 90000 * pos / pv->out_discrete_channels / sizeof( float ) / audio->config.out.samplerate;
    buf->s.stop  = buf->s.start + 90000 * 1152 / audio->config.out.samplerate;
    pv->pts = buf->s.stop;
    buf->size  = lame_encode_buffer_float( 
            pv->lame, samples[0], samples[1],
            1152, buf->data, LAME_MAXMP3BUFFER );

    buf->s.type = AUDIO_BUF;
    buf->s.frametype = HB_FRAME_AUDIO;

    if( !buf->size )
    {
        /* Encoding was successful but we got no data. Try to encode
           more */
        hb_buffer_close( &buf );
        return Encode( w );
    }
    else if( buf->size < 0 )
    {
        hb_log( "enclame: lame_encode_buffer failed" );
        hb_buffer_close( &buf );
        return NULL;
    }
    return buf;
}
Example #3
0
/* Called whenever necessary by AudioConverterFillComplexBuffer */
static OSStatus inInputDataProc( AudioConverterRef converter, UInt32 *npackets,
                          AudioBufferList *buffers,
                          AudioStreamPacketDescription** ignored,
                          void *userdata )
{
    hb_work_private_t *pv = userdata;

    if( pv->ibytes == 0 )
    {
        *npackets = 0;
        hb_log( "CoreAudio: no data to use in inInputDataProc" );
        return noErr;
    }

    if( pv->buf != NULL )
        free( pv->buf );

    uint64_t pts, pos;
    buffers->mBuffers[0].mDataByteSize = MIN( *npackets * pv->isamplesiz, pv->ibytes );
    buffers->mBuffers[0].mData = pv->buf = calloc(1 , buffers->mBuffers[0].mDataByteSize );

    if( hb_list_bytes( pv->list ) >= buffers->mBuffers[0].mDataByteSize )
    {
        hb_list_getbytes( pv->list, buffers->mBuffers[0].mData,
                          buffers->mBuffers[0].mDataByteSize, &pts, &pos );
    }
    else
    {
        hb_log( "CoreAudio: Not enought data, exiting inInputDataProc" );
        *npackets = 0;
        return 1;
    }

    *npackets = buffers->mBuffers[0].mDataByteSize / pv->isamplesiz;

    /* transform data from [-32768,32767] to [-1.0,1.0] */
    float *fdata = buffers->mBuffers[0].mData;
    int i;

    for( i = 0; i < *npackets * pv->nchannels; i++ ) {
        fdata[i] = fdata[i] / 32768.f;
    }

    pv->ibytes -= buffers->mBuffers[0].mDataByteSize;

    return noErr;
}
Example #4
0
/* Called whenever necessary by AudioConverterFillComplexBuffer */
static OSStatus inInputDataProc( AudioConverterRef converter, UInt32 *npackets,
                                 AudioBufferList *buffers,
                                 AudioStreamPacketDescription** ignored,
                                 void *userdata )
{
    hb_work_private_t *pv = userdata;

    if( pv->ibytes == 0 )
    {
        *npackets = 0;
        hb_log( "CoreAudio: no data to use in inInputDataProc" );
        return 1;
    }

    if( pv->buf != NULL )
        free( pv->buf );

    uint64_t pts, pos;
    buffers->mBuffers[0].mDataByteSize = MIN( *npackets * pv->isamplesiz, pv->ibytes );
    buffers->mBuffers[0].mData = pv->buf = calloc( 1, buffers->mBuffers[0].mDataByteSize );

    if( hb_list_bytes( pv->list ) >= buffers->mBuffers[0].mDataByteSize )
    {
        hb_list_getbytes( pv->list, buffers->mBuffers[0].mData,
                          buffers->mBuffers[0].mDataByteSize, &pts, &pos );
    }
    else
    {
        hb_log( "CoreAudio: Not enough data, exiting inInputDataProc" );
        *npackets = 0;
        return 1;
    }

    if( pv->ichanmap != &hb_qt_chan_map )
    {
        hb_layout_remap( pv->ichanmap, &hb_qt_chan_map, pv->layout,
                         (float*)buffers->mBuffers[0].mData,
                         buffers->mBuffers[0].mDataByteSize / pv->isamplesiz );
    }

    *npackets = buffers->mBuffers[0].mDataByteSize / pv->isamplesiz;

    pv->ibytes -= buffers->mBuffers[0].mDataByteSize;

    return noErr;
}
Example #5
0
/* Called whenever necessary by AudioConverterFillComplexBuffer */
static OSStatus inInputDataProc(AudioConverterRef converter, UInt32 *npackets,
                                AudioBufferList *buffers,
                                AudioStreamPacketDescription **ignored,
                                void *userdata)
{
    hb_work_private_t *pv = userdata;

    if (!pv->ibytes)
    {
        *npackets = 0;
        return 1;
    }

    if (pv->buf != NULL)
    {
        free(pv->buf);
    }

    buffers->mBuffers[0].mDataByteSize = MIN(pv->ibytes,
                                             pv->isamplesiz * *npackets);
    pv->buf = calloc(1, buffers->mBuffers[0].mDataByteSize);
    buffers->mBuffers[0].mData = pv->buf;

    if (hb_list_bytes(pv->list) >= buffers->mBuffers[0].mDataByteSize)
    {
        hb_list_getbytes(pv->list, buffers->mBuffers[0].mData,
                         buffers->mBuffers[0].mDataByteSize, NULL, NULL);
    }
    else
    {
        *npackets = 0;
        return 1;
    }

    *npackets = buffers->mBuffers[0].mDataByteSize / pv->isamplesiz;
    pv->ibytes -= buffers->mBuffers[0].mDataByteSize;

    if (pv->ichanmap != &hb_qt_chan_map)
    {
        hb_layout_remap(pv->ichanmap, &hb_qt_chan_map, pv->layout,
                        (float*)buffers->mBuffers[0].mData, *npackets);
    }

    return noErr;
}
Example #6
0
/***********************************************************************
 * Encode
 ***********************************************************************
 *
 **********************************************************************/
static hb_buffer_t * Encode( hb_work_object_t * w )
{
    hb_work_private_t * pv = w->private_data;

    if( hb_list_bytes( pv->list ) < pv->input_samples * sizeof( float ) )
    {
        /* Need more data */
        return NULL;
    }

    uint64_t pts, pos;
    hb_list_getbytes( pv->list, pv->buf, pv->input_samples * sizeof( float ),
                      &pts, &pos );

    int i;
    float *fltBuf = (float*)pv->buf;
    for ( i = 0; i < pv->input_samples; i++ )
        fltBuf[i] *= 32768.0;
        
    int size = faacEncEncode( pv->faac, (int32_t *)pv->buf, pv->input_samples,
                              pv->obuf, pv->output_bytes );

    // AAC needs four frames before it can start encoding so we'll get nothing
    // on the first three calls to the encoder.
    if ( size > 0 )
    {
        hb_buffer_t * buf = hb_buffer_init( size );
        memcpy( buf->data, pv->obuf, size );
        buf->size        = size;
        buf->s.start     = pv->pts;
        buf->s.duration  = pv->framedur;
        buf->s.stop      = buf->s.start + buf->s.duration;
        buf->s.type      = AUDIO_BUF;
        buf->s.frametype = HB_FRAME_AUDIO;
        pv->pts += pv->framedur;
        return buf;
    }
    return NULL;
}
Example #7
0
/***********************************************************************
 * Decode
 ***********************************************************************
 *
 **********************************************************************/
static hb_buffer_t * Decode( hb_work_object_t * w )
{
    hb_work_private_t * pv = w->private_data;
    hb_buffer_t * buf;
    hb_audio_t  * audio = w->audio;
    int           i, j, k;
    int64_t       pts, pos;
    uint64_t      upts, upos;
    int           num_blocks;

    /* Get a frame header if don't have one yet */
    if( !pv->sync )
    {
        while( hb_list_bytes( pv->list ) >= 14 )
        {
            /* We have 14 bytes, check if this is a correct header */
            hb_list_seebytes( pv->list, pv->frame, 14 );
            pv->size = dca_syncinfo( pv->state, pv->frame, &pv->flags_in, &pv->rate,
                                    &pv->bitrate, &pv->frame_length );
            if( pv->size )
            {
                /* It is. W00t. */
                if( pv->error )
                {
                    hb_log( "dca_syncinfo ok" );
                }
                pv->error = 0;
                pv->sync  = 1;
                break;
            }

            /* It is not */
            if( !pv->error )
            {
                hb_log( "dca_syncinfo failed" );
                pv->error = 1;
            }

            /* Try one byte later */
            hb_list_getbytes( pv->list, pv->frame, 1, NULL, NULL );
        }
    }

    if( !pv->sync || hb_list_bytes( pv->list ) < pv->size )
    {
        /* Need more data */
        return NULL;
    }

    /* Get the whole frame */
    hb_list_getbytes( pv->list, pv->frame, pv->size, &upts, &upos );
    pts = (int64_t)upts;
    pos = (int64_t)upos;

    if ( pts != pv->last_buf_pts )
    {
        pv->last_buf_pts = pts;
    }
    else
    {
        // spec says that the PTS is the start time of the first frame
        // that starts in the PES frame so we only use the PTS once then
        // get the following frames' PTS from the frame length.
        pts = -1;
    }

    // mkv files typically use a 1ms timebase which results in a lot of
    // truncation error in their timestamps. Also, TSMuxer or something
    // in the m2ts-to-mkv toolchain seems to take a very casual attitude
    // about time - timestamps seem to randomly offset by ~40ms for a few
    // seconds then recover. So, if the pts we got is within 50ms of the
    // pts computed from the data stream, use the data stream pts.
    if ( pts == -1 || ( pv->next_pts && fabs( pts - pv->next_pts ) < 50.*90. ) )
    {
        pts = pv->next_pts;
    }

    double frame_dur = (double)(pv->frame_length & ~0xFF) / (double)pv->rate * 90000.;

    /* DCA passthrough: don't decode the DCA frame */
    if( audio->config.out.codec == HB_ACODEC_DCA_PASS )
    {
        buf = hb_buffer_init( pv->size );
        memcpy( buf->data, pv->frame, pv->size );
        buf->start = pts;
        pv->next_pts = pts + frame_dur;
        buf->stop  = pv->next_pts;
        pv->sync = 0;
        return buf;
    }

    /* Feed libdca */
    dca_frame( pv->state, pv->frame, &pv->flags_out, &pv->level, 0 );

    /* find out how many blocks are in this frame */
    num_blocks = dca_blocks_num( pv->state );

    /* num_blocks blocks per frame, 256 samples per block, channelsused channels */
    int nsamp = num_blocks * 256;
    buf = hb_buffer_init( nsamp * pv->out_discrete_channels * sizeof( float ) );

    buf->start = pts;
    pv->next_pts = pts + (double)nsamp / (double)pv->rate * 90000.;
    buf->stop  = pv->next_pts;

    for( i = 0; i < num_blocks; i++ )
    {
        dca_sample_t * samples_in;
        float    * samples_out;

        dca_block( pv->state );
        samples_in  = dca_samples( pv->state );
        samples_out = ((float *) buf->data) + 256 * pv->out_discrete_channels * i;

        /* Interleave */
        for( j = 0; j < 256; j++ )
        {
            for ( k = 0; k < pv->out_discrete_channels; k++ )
            {
                samples_out[(pv->out_discrete_channels*j)+k]   = samples_in[(256*k)+j] * 32767;
            }
        }

    }

    pv->sync = 0;
    return buf;
}
Example #8
0
static hb_buffer_t* Encode(hb_work_object_t *w)
{
    hb_work_private_t *pv = w->private_data;
    hb_audio_t *audio = w->audio;
    uint64_t pts, pos;

    if (hb_list_bytes(pv->list) < pv->input_samples * sizeof(float))
    {
        return NULL;
    }

    hb_list_getbytes(pv->list, pv->input_buf, pv->input_samples * sizeof(float),
                     &pts, &pos);

    // Prepare input frame
    int out_linesize;
    int out_size = av_samples_get_buffer_size(&out_linesize,
                                              pv->context->channels,
                                              pv->samples_per_frame,
                                              pv->context->sample_fmt, 1);
    AVFrame frame = { .nb_samples = pv->samples_per_frame, };
    avcodec_fill_audio_frame(&frame,
                             pv->context->channels, pv->context->sample_fmt,
                             pv->output_buf, out_size, 1);
    if (pv->avresample != NULL)
    {
        int in_linesize;
        av_samples_get_buffer_size(&in_linesize, pv->context->channels,
                                   frame.nb_samples, AV_SAMPLE_FMT_FLT, 1);
        int out_samples = avresample_convert(pv->avresample,
                                             frame.extended_data, out_linesize,
                                             frame.nb_samples,
                                             &pv->input_buf,       in_linesize,
                                             frame.nb_samples);
        if (out_samples != pv->samples_per_frame)
        {
            // we're not doing sample rate conversion, so this shouldn't happen
            hb_log("encavcodecaWork: avresample_convert() failed");
            return NULL;
        }
    }

    // Libav requires that timebase of audio frames be in sample_rate units
    frame.pts = pts + (90000 * pos / (sizeof(float) *
                                      pv->out_discrete_channels *
                                      audio->config.out.samplerate));
    frame.pts = av_rescale(frame.pts, pv->context->sample_rate, 90000);

    // Prepare output packet
    AVPacket pkt;
    int got_packet;
    hb_buffer_t *out = hb_buffer_init(pv->max_output_bytes);
    av_init_packet(&pkt);
    pkt.data = out->data;
    pkt.size = out->alloc;

    // Encode
    int ret = avcodec_encode_audio2(pv->context, &pkt, &frame, &got_packet);
    if (ret < 0)
    {
        hb_log("encavcodeca: avcodec_encode_audio failed");
        hb_buffer_close(&out);
        return NULL;
    }

    if (got_packet && pkt.size)
    {
        out->size = pkt.size;

        // The output pts from libav is in context->time_base. Convert it back
        // to our timebase.
        //
        // Also account for the "delay" factor that libav seems to arbitrarily
        // subtract from the packet.  Not sure WTH they think they are doing by
        // offsetting the value in a negative direction.
        out->s.start = av_rescale_q(pv->context->delay + pkt.pts,
                                    pv->context->time_base,
                                    (AVRational){1, 90000});

        out->s.stop  = out->s.start + (90000 * pv->samples_per_frame /
                                       audio->config.out.samplerate);

        out->s.type = AUDIO_BUF;
        out->s.frametype = HB_FRAME_AUDIO;
    }
    else
    {
        hb_buffer_close(&out);
        return Encode(w);
    }

    return out;
}

static hb_buffer_t * Flush( hb_work_object_t * w )
{
    hb_buffer_t *first, *buf, *last;

    first = last = buf = Encode( w );
    while( buf )
    {
        last = buf;
        buf->next = Encode( w );
        buf = buf->next;
    }

    if( last )
    {
        last->next = hb_buffer_init( 0 );
    }
    else
    {
        first = hb_buffer_init( 0 );
    }

    return first;
}
Example #9
0
static hb_buffer_t * Encode( hb_work_object_t * w )
{
    hb_work_private_t * pv = w->private_data;
    uint64_t pts, pos;
    hb_audio_t * audio = w->audio;
    hb_buffer_t * buf;
    int ii;

    if( hb_list_bytes( pv->list ) < pv->input_samples * sizeof( float ) )
    {
        return NULL;
    }

    hb_list_getbytes( pv->list, pv->buf, pv->input_samples * sizeof( float ),
                      &pts, &pos);

    hb_chan_map_t *map = NULL;
    if ( audio->config.in.codec == HB_ACODEC_AC3 )
    {
        map = &hb_ac3_chan_map;
    }
    else if ( audio->config.in.codec == HB_ACODEC_DCA )
    {
        map = &hb_qt_chan_map;
    }
    if ( map )
    {
        int layout;
        switch (audio->config.out.mixdown)
        {
            case HB_AMIXDOWN_MONO:
                layout = HB_INPUT_CH_LAYOUT_MONO;
                break;
            case HB_AMIXDOWN_STEREO:
            case HB_AMIXDOWN_DOLBY:
            case HB_AMIXDOWN_DOLBYPLII:
                layout = HB_INPUT_CH_LAYOUT_STEREO;
                break;
            case HB_AMIXDOWN_6CH:
            default:
                layout = HB_INPUT_CH_LAYOUT_3F2R | HB_INPUT_CH_LAYOUT_HAS_LFE;
                break;
        }
        hb_layout_remap( map, &hb_smpte_chan_map, layout, 
                        (float*)pv->buf, AC3_SAMPLES_PER_FRAME);
    }
    
    for (ii = 0; ii < pv->input_samples; ii++)
    {
        // ffmpeg float samples are -1.0 to 1.0
        pv->samples[ii] = ((float*)pv->buf)[ii] / 32768.0;
    }

    buf = hb_buffer_init( pv->output_bytes );
    buf->size = avcodec_encode_audio( pv->context, buf->data, buf->alloc,
                                      (short*)pv->samples );

    buf->start = pts + 90000 * pos / pv->out_discrete_channels / sizeof( float ) / audio->config.out.samplerate;
    buf->stop  = buf->start + 90000 * AC3_SAMPLES_PER_FRAME / audio->config.out.samplerate;

    buf->frametype = HB_FRAME_AUDIO;

    if ( !buf->size )
    {
        hb_buffer_close( &buf );
        return Encode( w );
    }
    else if (buf->size < 0)
    {
        hb_log( "encac3: avcodec_encode_audio failed" );
        hb_buffer_close( &buf );
        return NULL;
    }

    return buf;
}
Example #10
0
static hb_buffer_t* Encode(hb_work_object_t *w)
{
    hb_work_private_t *pv = w->private_data;
    hb_audio_t *audio = w->audio;
    uint64_t pts, pos;

    if (hb_list_bytes(pv->list) < pv->input_samples * sizeof(float))
    {
        return NULL;
    }

    hb_list_getbytes(pv->list, pv->input_buf, pv->input_samples * sizeof(float),
                     &pts, &pos);

    // Prepare input frame
    int out_linesize;
    int out_size = av_samples_get_buffer_size(&out_linesize,
                                              pv->context->channels,
                                              pv->samples_per_frame,
                                              pv->context->sample_fmt, 1);
    AVFrame frame = { .nb_samples = pv->samples_per_frame, };
    avcodec_fill_audio_frame(&frame,
                             pv->context->channels, pv->context->sample_fmt,
                             pv->output_buf, out_size, 1);
    if (pv->avresample != NULL)
    {
        int in_linesize;
        av_samples_get_buffer_size(&in_linesize, pv->context->channels,
                                   frame.nb_samples, AV_SAMPLE_FMT_FLT, 1);
        int out_samples = avresample_convert(pv->avresample,
                                             frame.extended_data, out_linesize,
                                             frame.nb_samples,
                                             &pv->input_buf,       in_linesize,
                                             frame.nb_samples);
        if (out_samples != pv->samples_per_frame)
        {
            // we're not doing sample rate conversion, so this shouldn't happen
            hb_log("encavcodecaWork: avresample_convert() failed");
            return NULL;
        }
    }

    // Libav requires that timebase of audio frames be in sample_rate units
    frame.pts = pts + (90000 * pos / (sizeof(float) *
                                      pv->out_discrete_channels *
                                      audio->config.out.samplerate));
    frame.pts = av_rescale(frame.pts, pv->context->sample_rate, 90000);

    // Prepare output packet
    AVPacket pkt;
    int got_packet;
    hb_buffer_t *out = hb_buffer_init(pv->max_output_bytes);
    av_init_packet(&pkt);
    pkt.data = out->data;
    pkt.size = out->alloc;

    // Encode
    int ret = avcodec_encode_audio2(pv->context, &pkt, &frame, &got_packet);
    if (ret < 0)
    {
        hb_log("encavcodeca: avcodec_encode_audio failed");
        hb_buffer_close(&out);
        return NULL;
    }

    if (got_packet && pkt.size)
    {
        out->size = pkt.size;
        // The output pts from libav is in context->time_base. Convert it back
        // to our timebase.
        out->s.start     = av_rescale_q(pkt.pts, pv->context->time_base,
                                        (AVRational){1, 90000});
        out->s.duration  = (double)90000 * pv->samples_per_frame /
                                           audio->config.out.samplerate;
        out->s.stop      = out->s.start + out->s.duration;
        out->s.type      = AUDIO_BUF;
        out->s.frametype = HB_FRAME_AUDIO;
    }
    else
    {
        hb_buffer_close(&out);
        return Encode(w);
    }

    return out;
}

static hb_buffer_t * Flush( hb_work_object_t * w )
{
    hb_buffer_list_t list;
    hb_buffer_t *buf;

    hb_buffer_list_clear(&list);
    buf = Encode( w );
    while (buf != NULL)
    {
        hb_buffer_list_append(&list, buf);
        buf = Encode( w );
    }

    hb_buffer_list_append(&list, hb_buffer_eof_init());
    return hb_buffer_list_clear(&list);
}
Example #11
0
static hb_buffer_t * Encode( hb_work_object_t * w )
{
    hb_work_private_t * pv = w->private_data;
    uint64_t pts, pos;
    hb_audio_t * audio = w->audio;
    hb_buffer_t * buf;

    if( hb_list_bytes( pv->list ) < pv->input_samples * sizeof( float ) )
    {
        return NULL;
    }

    hb_list_getbytes( pv->list, pv->buf, pv->input_samples * sizeof( float ),
                      &pts, &pos);

    // XXX: ffaac fails to remap from the internal libav* channel map (SMPTE) to the native AAC channel map
    //      do it here - this hack should be removed if Libav fixes the bug
    hb_chan_map_t * out_map = ( w->codec_param == CODEC_ID_AAC ) ? &hb_qt_chan_map : &hb_smpte_chan_map;

    if ( audio->config.in.channel_map != out_map )
    {
        hb_layout_remap( audio->config.in.channel_map, out_map, pv->layout,
                         (float*)pv->buf, pv->samples_per_frame );
    }

    // Do we need to convert our internal float format?
    if ( pv->context->sample_fmt != AV_SAMPLE_FMT_FLT )
    {
        int isamp, osamp;
        AVAudioConvert *ctx;

        isamp = av_get_bytes_per_sample( AV_SAMPLE_FMT_FLT );
        osamp = av_get_bytes_per_sample( pv->context->sample_fmt );
        ctx = av_audio_convert_alloc( pv->context->sample_fmt, 1,
                                      AV_SAMPLE_FMT_FLT, 1,
                                      NULL, 0 );

        // get output buffer size then malloc a buffer
        //nsamples = out_size / isamp;
        //buffer = av_malloc( nsamples * sizeof(hb_sample_t) );

        // we're doing straight sample format conversion which 
        // behaves as if there were only one channel.
        const void * const ibuf[6] = { pv->buf };
        void * const obuf[6] = { pv->buf };
        const int istride[6] = { isamp };
        const int ostride[6] = { osamp };

        av_audio_convert( ctx, obuf, ostride, ibuf, istride, pv->input_samples );
        av_audio_convert_free( ctx );
    }
    
    buf = hb_buffer_init( pv->output_bytes );
    buf->size = avcodec_encode_audio( pv->context, buf->data, buf->alloc,
                                      (short*)pv->buf );

    buf->start = pts + 90000 * pos / pv->out_discrete_channels / sizeof( float ) / audio->config.out.samplerate;
    buf->stop  = buf->start + 90000 * pv->samples_per_frame / audio->config.out.samplerate;

    buf->frametype = HB_FRAME_AUDIO;

    if ( !buf->size )
    {
        hb_buffer_close( &buf );
        return Encode( w );
    }
    else if (buf->size < 0)
    {
        hb_log( "encavcodeca: avcodec_encode_audio failed" );
        hb_buffer_close( &buf );
        return NULL;
    }

    return buf;
}