[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