使用avcodec_fill_audio_frame()和内存泄漏进行音频编码

时间:2013-05-17 08:32:08

标签: ffmpeg

作为编码解码音频数据包的一部分,我正在使用avcodec_fill_audio_frame()。我正在传递分配的AVFrame指针以及包含解码样本和其他参数数量的通道,样本格式,缓冲区大小的缓冲区。虽然编码工作正常,但我无法完全消除内存泄漏。我已经处理了大部分事情,但我仍然无法检测到泄漏。 下面是我用于编码的函数。请提出建议。 AudioSample包含解码数据,它完全在不同的类中管理(类析构函数中的免费)。我正在释放FFmpegEncoder析构函数中的AVFrame,并且每次使用av_free_packet()并启用av_packet_destruct时都会释放AVPacket。我还需要免费提供什么?

void FfmpegEncoder::WriteAudioSample(AudioSample *audS) 
{ 


    int num_audio_frame = 0; 
    AVCodecContext *c = NULL; 
   // AVFrame *frame; 
    AVPacket pkt; 

    av_init_packet(&pkt); 
    pkt.destruct = av_destruct_packet; 
    pkt.data = NULL; 
    pkt.size = 0; 
    int ret = 0, got_packet = 0; 
    c = m_out_aud_strm->codec; 
     static int64_t aud_pts_in = -1; 

    if((audS != NULL) && (audS->GetSampleLength() > 0) ) 
    { 
        int byte_per_sample = av_get_bytes_per_sample(c->sample_fmt); 

        PRINT_VAL("Byte Per Sample ", byte_per_sample) 
        m_frame->nb_samples = (audS->GetSampleLength())/(c->channels*av_get_bytes_per_sample(c->sample_fmt)); 
        if(m_frame->nb_samples == c->frame_size) 
        {   

#if 1 
        if(m_need_resample && (c->channels >= 2)) 
           { 
               uint8_t * t_buff1 = new uint8_t[audS->GetSampleLength()]; 
               if(t_buff1 != NULL) 
                { 
                     for(int64_t i = 0; i< m_frame->nb_samples; i++) 
                    { 
                        memcpy(t_buff1 + i*byte_per_sample, (uint8_t*)((uint8_t*)audS->GetAudioSampleData() + i*byte_per_sample*c->channels), byte_per_sample); 
                        memcpy(t_buff1 + (audS->GetSampleLength())/2 + i*byte_per_sample, (uint8_t*)((uint8_t*)audS->GetAudioSampleData() + i*byte_per_sample*c->channels+ byte_per_sample), byte_per_sample); 
                    } 
                    audS->FillAudioSample(t_buff1, audS->GetSampleLength()); 
                    delete[] t_buff1; 
                } 
            } 
#endif 
            ret = avcodec_fill_audio_frame(m_frame, c->channels, c->sample_fmt, (uint8_t*)audS->GetAudioSampleData(),m_frame->nb_samples*byte_per_sample*c->channels, 0); 
            //ret = avcodec_fill_audio_frame(&frame, c->channels, c->sample_fmt, t_buff,frame.nb_samples*byte_per_sample*c->channels, 0); 
            if(ret != 0) 
            { 
                PRINT_MSG("Avcodec Fill Audio Failed ") 
            } 
            else 
            { 
                got_packet = 0; 
                ret = avcodec_encode_audio2(c, &pkt, m_frame, &got_packet); 
                if(ret < 0 || got_packet == 0) 
                { 
                    PRINT_MSG("failed to encode audio ")     
                } 
                else 
                { 
                    PRINT_MSG("Audio Packet Encoded "); 
                    aud_pts_in++; 
                    pkt.pts = aud_pts_in; 
                    pkt.dts = pkt.pts; 
                    pkt.stream_index = m_out_aud_strm->index; 

                    ret = av_interleaved_write_frame(oc, &pkt); 
                    if(ret != 0) 
                    { 
                        PRINT_MSG("Error Write Audio PKT ")     
                    } 
                    else 
                    { 
                        PRINT_MSG("Audio PKT Writen ")     
                    } 
                } 
             } 
        } 
        avcodec_flush_buffers(c); 
     //   avcodec_free_frame(&frame); 
     } 

     av_free_packet(&pkt); 
} 

谢谢, 普拉迪普

1 个答案:

答案 0 :(得分:1)

    //================== SEND AUDIO OUTPUT =======================
void AVOutputStream::sendAudioOutput (AVFrame* inputFrame)
{
      AVCodecContext *codecCtx = pOutputAudioStream->codec;

        // set source data variables
        sourceNumberOfChannels = inputFrame->channels;
        sourceChannelLayout  = inputFrame->channel_layout;
        sourceSampleRate = inputFrame->sample_rate;
        _sourceSampleFormat = (AVSampleFormat)inputFrame->format;
        sourceNumberOfSamples = inputFrame->nb_samples;


        // set destination data variables
        destinationNumberOfChannels = codecCtx->channels;
        destinationChannelLayout = codecCtx->channel_layout;
        destinationSampleRate = codecCtx->sample_rate;
        destinationSampleFormat =  codecCtx->sample_fmt;//AV_SAMPLE_FMT_FLTP;//EncodecCtx->sample_fmt;
        destinationLineSize = 0;
        destinationData = NULL;

        int returnVal = 0;


        if (startDecode == false)
        {
                startDecode = true;

                resamplerCtx = swr_alloc_set_opts(NULL,
                                                destinationChannelLayout,
                                                destinationSampleFormat,
                                                destinationSampleRate,
                                                sourceChannelLayout,
                                                _sourceSampleFormat,
                                                sourceSampleRate,
                                                0,
                                                NULL);


                if (resamplerCtx == NULL)
                {

                            std::cout <<  "Unable to create the resampler context for the audio frame";
                            isConnected = false;
                }


                // initialize the resampling context
                returnVal = swr_init(resamplerCtx);


                if (returnVal < 0)
                {
                        std::cout <<  "Unable to init the resampler context, error:";
                        isConnected = false;
                }


        } //if (startDecode == false)


        if (sourceSampleRate != 0)
                destinationNumberOfSamples = destinationSampleRate/sourceSampleRate * sourceNumberOfSamples;


        // allocate the destination samples buffer
        returnVal = av_samples_alloc_array_and_samples(&destinationData,
                                                       &destinationLineSize,
                                                       destinationNumberOfChannels,
                                                       destinationNumberOfSamples,
                                                       destinationSampleFormat,
                                                       0);



        if (returnVal < 0)
        {
                std::cout << "Unable to allocate destination samples, error";
                isConnected = false;
        }


        // convert to destination format
        returnVal = swr_convert(resamplerCtx,
                                destinationData,
                                destinationNumberOfSamples,
                                (const uint8_t **)inputFrame->data,     //sourceData,
                                sourceNumberOfSamples);


        if (returnVal < 0)
        {

                std::cout << "Resampling failed, error \n";
                isConnected = false;
        }


        int bufferSize = av_samples_get_buffer_size(&destinationLineSize,
                                                    destinationNumberOfChannels,
                                                    destinationNumberOfSamples,
                                                    destinationSampleFormat,
                                                    0);
        //whithout fifo
                                    pOutputAudioFrame  = av_frame_alloc();

                                    pOutputAudioFrame->nb_samples = codecCtx->frame_size;//frameNumberOfSamples;
                                    pOutputAudioFrame->format = codecCtx->sample_fmt;
                                    pOutputAudioFrame->channel_layout = codecCtx->channel_layout;
                                    pOutputAudioFrame->channels = codecCtx->channels;
                                    pOutputAudioFrame->sample_rate = codecCtx->sample_rate;


                                    returnVal = avcodec_fill_audio_frame(pOutputAudioFrame,
                                                                        pOutputAudioFrame->channels,
                                                                        (AVSampleFormat)pOutputAudioFrame->format,
                                                                        (const uint8_t *)destinationData[0],
                                                                        bufferSize,0);


                                    pOutputAudioFrame->pts = inputFrame->pts;



            if (returnVal < 0)
            {

                                std::cout << "Unable to fill the audio frame wsampleIndexith captured audio data,error";
                                isConnected = false;

            }




                        // encode the audio frame, fill a packet for streaming
                        av_init_packet(&outAudioPacket);
                        outAudioPacket.data = NULL;
                        outAudioPacket.size = 0;
                        outAudioPacket.dts = outAudioPacket.pts = 0;
                        int gotPacket;



                        // encoding
                        returnVal = avcodec_encode_audio2(codecCtx, &outAudioPacket, pOutputAudioFrame, &gotPacket);


                    // free buffers
                              av_freep(&destinationData[0]);
                      av_freep(&destinationData);
                          av_frame_free(&pOutputAudioFrame);



                        if (gotPacket)
                        {


                                outAudioPacket.stream_index = pOutputAudioStream->index;
                                outAudioPacket.flags |= AV_PKT_FLAG_KEY;

                                returnVal = av_interleaved_write_frame(pOutputFormatCtx, &outAudioPacket);
                                //returnVal = av_write_frame(pOutputFormatCtx, &outAudioPacket);





                                if (returnVal != 0)
                                {

                                        std::cout << "Cannot write audio packet \n";
                                        isConnected = false;
                                }

                        av_free_packet(&outAudioPacket);

                        } // if (gotPacket)



            }

您可以在重新采样后看到我免费使用的缓冲区。  //免费缓冲区                     av_freep(安培; destinationData [0]);                     av_freep(安培; destinationData);