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