[Libav-user] avcodec_decode_audio4() help
Gonzalo Garramuno
ggarra13 at gmail.com
Mon May 6 16:51:57 CEST 2013
On 05/05/13 21:40, Gonzalo Garramuno wrote:
> On 03/05/13 01:30, Kalileo wrote:
>> If you decode aac, then you might get hit by the change to planar
>> format, which happened November 16, 2012 in the ffmpeg sources
>> (although the effect is usually not a 'frying pan noise').
>> _______________________________________________
>>
> The change happened between ffmpeg-1.0.6 (which works fine) and
> ffmpeg-1.1.4 (which does not).
>
> Alternatively, can anyone show me the smallest piece of code that they
> use for avcodec_decode_audio4.
Here is my code:
int CMedia::decode_audio3(AVCodecContext *avctx, int16_t *samples,
int *frame_size_ptr,
AVPacket *avpkt)
{
AVFrame frame = { { 0 } };
int ret, got_frame = 0;
if (avctx->get_buffer != avcodec_default_get_buffer) {
avctx->get_buffer = avcodec_default_get_buffer;
avctx->release_buffer = avcodec_default_release_buffer;
}
ret = avcodec_decode_audio4(avctx, &frame, &got_frame, avpkt);
if (ret >= 0 && got_frame) {
int ch, plane_size;
int planar = av_sample_fmt_is_planar(avctx->sample_fmt);
int data_size = av_samples_get_buffer_size(&plane_size,
avctx->channels,
frame.nb_samples,
avctx->sample_fmt, 1);
if (*frame_size_ptr < data_size) {
IMG_ERROR( "decode_audio3 - Output buffer size is too small for "
"the current frame ("
<< *frame_size_ptr << " < " << data_size << ")" );
return AVERROR(EINVAL);
}
memcpy(samples, frame.extended_data[0], plane_size);
if (planar && avctx->channels > 1) {
uint8_t *out = ((uint8_t *)samples) + plane_size;
for (ch = 1; ch < avctx->channels; ch++) {
memcpy(out, frame.extended_data[ch], plane_size);
out += plane_size;
}
}
*frame_size_ptr = data_size;
} else {
*frame_size_ptr = 0;
}
return ret;
}
/**
* Given an audio packet, decode it
*
* @param ptsframe returned frame we decoded
* @param frame frame we expect
* @param pkt packet to decode
*
* @return status whether frame was decoded correctly or not.
*/
CMedia::DecodeStatus
CMedia::decode_audio_packet( boost::int64_t& ptsframe,
const boost::int64_t frame,
const AVPacket& pkt )
AVStream* stream = get_audio_stream();
if ( !stream ) return kDecodeNoStream;
// Get the audio codec context
AVCodecContext* ctx = stream->codec;
assert( !_audio_packets.is_seek( pkt ) );
assert( !_audio_packets.is_flush( pkt ) );
assert( !_audio_packets.is_preroll( pkt ) );
assert( !_audio_packets.is_loop_end( pkt ) );
assert( !_audio_packets.is_loop_start( pkt ) );
ptsframe = get_frame( stream, pkt );
// Make sure audio frames are continous during playback to
// accomodate weird sample rates not evenly divisable by frame rate
if ( _audio_buf_used != 0 && (!_audio.empty()) )
{
ptsframe = _audio_last_frame + 1;
// assert( ptsframe <= last_frame() );
}
#ifdef DEBUG
if ( _audio_buf_used + pkt.size >= _audio_max )
{
IMG_ERROR( _("Too much audio used:") << _audio_buf_used );
}
#endif
AVPacket pkt_temp;
av_init_packet(&pkt_temp);
pkt_temp.data = pkt.data;
pkt_temp.size = pkt.size;
assert( pkt.data != NULL );
assert( _audio_buf != NULL );
assert( pkt.size + _audio_buf_used < _audio_max );
int audio_size = AVCODEC_MAX_AUDIO_FRAME_SIZE; //< correct
assert( pkt_temp.size <= audio_size );
while ( pkt_temp.size > 0 )
{
// Decode the audio into the buffer
assert( _audio_buf_used + pkt_temp.size <= _audio_max );
assert( pkt_temp.data != NULL );
assert( _audio_buf_used % 16 == 0 );
assert( audio_size > 0 );
int ret = decode_audio3( ctx,
( int16_t * )( (char*)_audio_buf +
_audio_buf_used ),
&audio_size, &pkt_temp );
// If no samples are returned, then break now
if ( ret <= 0 )
{
pkt_temp.size = 0;
IMG_ERROR( _("Audio missed for frame: ") << ptsframe
<< _(" ret: ") << ret
<< _(" audio max: ") << _audio_max
<< _(" audio used: ") << _audio_buf_used
);
return kDecodeMissingSamples;
}
assert( audio_size > 0 );
assert( ret <= pkt_temp.size );
assert( ret > 0 );
assert( audio_size + _audio_buf_used <= _audio_max );
// Decrement the length by the number of bytes parsed
pkt_temp.data += ret;
pkt_temp.size -= ret;
if ( audio_size <= 0 ) continue;
_audio_buf_used += audio_size;
}
if ( pkt_temp.size == 0 ) return kDecodeOK;
IMG_ERROR( _("decode_audio - missed decoding some samples") );
return kDecodeMissingSamples;
}
More information about the Libav-user
mailing list