Greetings,

I am trying to decode an audio stream from audio files (no video).  

The function is included below. The main idea is to read nbsecs of audio
from the file's audio stream, converting to sr sample rate and number
channels. (For now, just one destination channel.) The signal is put in
the sigbuf float array and returned.  (If the array is not big enough, a
new one is allocated).  

The problem is I cannot free the packets at the end of each
av_read_frame loop without getting double free or corruption heap
errors. Naturally, it will work if I replace av_free_packet() with
av_destruct_nofree, but nothing is free'd, leading to obvious memory
leaks.  What is the proper way to free audio packets in this instance?
I have read the example source code, and everything points to using
av_free_packet() to release each packet after each av_read_frame().
Does anyone recognize any errors here ? 

I am using pure audio files here (wav, mp3, ogg and flac). Is there
another way to free these packets when decoding audio files?  Or does it
have to be a video container format ?

Thanks for all your efforts,
D G Starkweather

code:

float* readaudio(const char *filename, float *sigbuf, int &buflen, const
float nbsecs, const int sr, const int channels)
{
        av_log_set_level(AV_LOG_QUIET);
        av_register_all();

        AVFormatContext *pFormatCtx;
        
        // Open file
        if(av_open_input_file(&pFormatCtx, filename, NULL, 0, NULL)!=0){
            buflen=0;
            return NULL ; // Couldn't open file
        }
         
        // Retrieve stream information
        if(av_find_stream_info(pFormatCtx)<0){
            buflen=0;
            av_close_input_file(pFormatCtx);
            return NULL; // Couldn't find stream information
        }
        
        //dump_format(pFormatCtx,0,NULL,0);//debugging function to print
infomation about format

        unsigned int i;
        AVCodecContext *pCodecCtx;

        // Find the video stream
        int audioStream=-1;
        for(i=0; i<pFormatCtx->nb_streams; i++)
        {
             if(pFormatCtx->streams[i]->codec->codec_type==CODEC_TYPE_AUDIO) 
             {
                    audioStream=i;
                    break;
             }
        }
        if(audioStream==-1){
             buflen = 0;
             av_close_input_file(pFormatCtx);
             return NULL; //no video stream
        }
        
        // Get a pointer to the codec context for the audio stream
        pCodecCtx=pFormatCtx->streams[audioStream]->codec;

        int src_sr = pCodecCtx->sample_rate;
        int src_channels = pCodecCtx->channels;
        int64_t totalduration =
pFormatCtx->streams[audioStream]->duration;
        int64_t duration = (nbsecs > 0.0f) ? (int64_t)(sr*nbsecs) :
totalduration;
        duration = (duration <= totalduration) ? duration :
totalduration;
        float *buf = NULL;
        if (!sigbuf || buflen <= duration){
            buf = (float*)malloc(duration*sizeof(float)); /* alloc new buffer
*/ 
            buflen = duration;
        } else {
            buf = sigbuf; /* use buffer handed in param */ 
        }
        AVCodec *pCodec;

        // Find the decoder
        pCodec=avcodec_find_decoder(pCodecCtx->codec_id);
        if(pCodec==NULL) 
        {
                buflen=0;
                av_close_input_file(pFormatCtx);
                return NULL ; // Codec not found
        }
        // Open codec
        if(avcodec_open(pCodecCtx, pCodec)<0){
            buflen=0;
            av_close_input_file(pFormatCtx);
            return NULL; // Could not open codec
        }
        ReSampleContext *rsctx =
audio_resample_init(channels,src_channels,sr,src_sr);

        uint8_t *inbuf = (uint8_t*)av_mallocz(AVCODEC_MAX_AUDIO_FRAME_SIZE
                                                    
+FF_INPUT_BUFFER_PADDING_SIZE);
        uint8_t *outbuf= (uint8_t*)av_mallocz(AVCODEC_MAX_AUDIO_FRAME_SIZE
                                              +FF_INPUT_BUFFER_PADDING_SIZE);
        int nbsamples, numbytesread, bufsize =
AVCODEC_MAX_AUDIO_FRAME_SIZE;

        int64_t index = 0;
        AVPacket packet;
        while(av_read_frame(pFormatCtx, &packet)>=0 && index < duration) 
        {
            while (packet.size > 0){
                nbsamples = bufsize;
                numbytesread =
avcodec_decode_audio2(pCodecCtx,(short*)inbuf,&nbsamples,packet.data,packet.size);
  
                if (nbsamples > 0){
                    int cnt = audio_resample(rsctx, (short*)outbuf, 
(short*)inbuf,
nbsamples);

                    if (index + cnt > duration){
                        duration = index + cnt; 
                    }
                    for (int i=0;i < cnt;i++){
                        short val = ((short*)outbuf)[i];
                        buf[index+i] = (float)(val)/(float)SHRT_MAX;
                    }
   
                    index += cnt;
                }
                packet.size -= numbytesread;
                packet.data += numbytesread;
            }
            av_free_packet(&packet);
        }

 audio_cleanup:
        av_free(inbuf);
        audio_resample_close(rsctx);
        avcodec_close(pCodecCtx);
        av_close_input_file(pFormatCtx);
        buflen = (int)index;
        
        return buf;
} 



 

_______________________________________________
libav-user mailing list
[email protected]
https://lists.mplayerhq.hu/mailman/listinfo/libav-user

Reply via email to