Я пытаюсь создать простой медиа-плеер для знакомства с миром ffmpeg, проблема в том, что каждый раз, когда я звоню av_freep(void*ptr)
приложение вылетает.
Если я не позвоню av_freep
Я получаю утечку памяти, и объем памяти, используемой программой, увеличивается до 1000 МБ (уже измерено), вот код:
int16_t* audioBuffer=(int16_t*)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE+FF_INPUT_BUFFER_PADDING_SIZE);
if(!audioBuffer){
MessageBox(0,"Error allocating in audioBuffer","Error: Mem",MB_ICONWARNING | MB_OK);
return -1;
}
int sz = MEDIA->DecodeAudioFrame((void*)audioBuffer,0);
Pa_WriteStream(MEDIA->output_stream,(int16_t*)audioBuffer,MEDIA->_audio_ccontext->frame_size);
av_freep(audioBuffer);
Вот мой код функции ‘DecodeAudioFrame’:
int WbMedia::DecodeAudioFrame(void *audio_buf, int buf_size){
static AVFrame frame;
static AVPacket pkt;
static uint8_t *audio_pkt_data = NULL;
static int audio_pkt_size = 0;
int len1=0;
for(;;){
bool do_rt = false;while(audio_pkt_size > 0){
int obt_frame = 0;
len1 = avcodec_decode_audio4(_audio_ccontext,&frame,&obt_frame,&pkt);
if(len1 < 0){
audio_pkt_size = 0;
break;
}
audio_pkt_data+=len1;
audio_pkt_size-=len1;
if(obt_frame){
data_size = av_samples_get_buffer_size(frame.linesize,channel_count,sample_fr,_audio_ccontext->sample_fmt,1);
memcpy(audio_buf,frame.data[0],data_size);
}
if(data_size < 0){
continue;
}
if(pkt.data){
av_free_packet(&pkt);
}
return data_size;
}
if(pkt.data){
av_free_packet(&pkt);
}
if(do_rt){
return data_size;
}
// Try to get a new packet
if(!audio_packets.empty()){
WaitForSingleObject(Queue_Audio_Mutex,INFINITE);
pkt = audio_packets.front();
audio_packets.pop();
ReleaseMutex(Queue_Audio_Mutex);
audio_pkt_size = pkt.size;
audio_pkt_data = pkt.data;
}else{
return -1;
}
}
return 0;
}
Мне нужна помощь в этом вопросе, я не знаю, является ли это ошибкой или что мне нужно сделать. Что там происходит? Почему он падает на av_freep
вызов? Как я могу это исправить?
Спасибо
av_freep
занимает указатель на указатель хочешь освободить; освобождает указатель NULL
после этого. Поэтому вам нужно использовать его как
av_freep(&audioBuffer);
Кроме того, вы можете использовать
av_free(audioBuffer);
audioBuffer = NULL;
что эквивалентно.
int16_t* audioBuffer=(int16_t*)av_malloc(AVCODEC_MAX_AUDIO_FRAME_SIZE+FF_INPUT_BUFFER_PADDING_SIZE);
Это не верно. AVCODEC_MAX_AUDIO_FRAME_SIZE
устарела (удалена в новых версиях). С новым API декодирования вы можете получить больше декодированных кадров, чем это.
static AVFrame frame;
Нет. Не размещайте AVFrame в стеке, он сломается. использование avcodec_alloc_frame()
(или же av_frame_alloc()
с новыми версиями).
data_size = av_samples_get_buffer_size(frame.linesize,channel_count,sample_fr,_audio_ccontext->sample_fmt,1);
Вы понимаете, что переписываете исходный размер линии кадра (AKA размер плоскости), верно? Интересно, предназначено ли это.
Кроме того, что является sample_fr
? Это какая-то постоянная откуда-то? Просто используйте AVFrame.nb_samples.
Наконец, ваш код, по-видимому, предполагает чередованное аудио (т. Е. Аудиосэмплы для всех каналов, чередующихся в одном буфере). Многие декодеры теперь выводят плоское аудио (т.е. сэмплы для каждого канала в отдельном буфере). Это может быть причиной аварии, так как av_samples_get_buffer_size
рассчитывает общий размер для всех выборок во всех каналах, в то время как data[0]
будет содержать только сэмплы для первого канала.
Если плоское аудио действительно является причиной, вы должны либо изменить свой код для его поддержки, либо использовать libavresample преобразовать планарный в чередующийся