Vencat
Vencat

Reputation: 1622

Cleaning AVFrame properly

I'm creating AVFrame object using av_frame_alloc() function and clearing it using av_frame_free(&frame) which internally calls av_frame_unref(), but it's not cleaning the memory properly. Heap size of my app grows exponentially in run time.

Not working:

AVFrame* frame = av_frame_alloc();
av_frame_free(&frame);

Working:

AVFrame* frame = av_frame_alloc();
av_free(frame->data[0]);

As far as I know, av_frame_free() calls av_freep() which calls av_free() to free the dynamic memory. Memory gets cleaned, If I use av_free(frame->data[0]) directly instead of av_frame_free(&frame)

Upvotes: 0

Views: 2301

Answers (2)

Monaco
Monaco

Reputation: 51

I have met this problem when i convert cv Mat to av frame in my program, the demo like this

for ( int i = 0; i < 10000; i++ ) {
    cv::Mat img = cv::Mat::zeros(2160, 3840, CV_8UC3);

    //std::shared_ptr<cv::Mat> mat_ptr = std::make_shared<cv::Mat>( img.clone() );
    cv::Mat tmp = img.clone();
    AVFrame* frame = nullptr;
    frame = cv_mat_bgr_to_av_frame_yuv420p( tmp, i );

    if ( i % 10 == 0) {
        std::cout << "#####" << i << std::endl;
    }
    //av_frame_unref(frame);
    av_freep(&frame->data[0]);
}

The cv_mat_bgr_to_av_frame_yuv420p function is defined as:

AVFrame* cv_mat_bgr_to_av_frame_yuv420p( cv::Mat& mat , int frame_number ) {

AVFrame* frame = av_frame_alloc();
frame->format = AV_PIX_FMT_YUV420P;
frame->width = mat.cols;
frame->height = mat.rows;
frame->pts = (int64_t) ( frame_number *  TIME_BASE / FPS  );

cv::Mat mat_yuv;
cvtColor( mat, mat_yuv, cv::COLOR_BGR2YUV_I420 );

av_image_alloc(frame->data, frame->linesize, frame->width, frame->height, 
                    static_cast<AVPixelFormat>(frame->format), 16);


// ergodic rows
int width = frame->width;
int height = frame->height;

for ( int j = 0; j < height; j++ ) {
    memcpy( frame->data[0] + j * frame->linesize[0], mat_yuv.data + j * width, width);
}

for ( int j = 0; j < height / 2; j++ ) {
    memcpy( frame->data[1] + j * frame->linesize[1], 
        mat_yuv.data + height * width + j * width / 2 , width / 2 );
}

for ( int j = 0; j < height / 2; j++ ) {
    memcpy(  frame->data[2] + j * frame->linesize[2], 
        mat_yuv.data + height * width * 5 / 4 + j * width / 2, width / 2 );
}

//av_frame_free(&frame);
return frame;

}

When i just use av_frame_free(&frame) to free the memory, i met the problem like you. However, when i use av_freep(&frame->data[0]), the problem is solved.

Upvotes: 0

Fabio Crispino
Fabio Crispino

Reputation: 731

I developed a personal project about video screen sharing application using libav with H.264, in order to do 60 FPS video encoding.

To fix my memory leak issues, I allocate frame using av_frame_alloc, I make it writable every cycle with av_frame_make_writable and I free their memory using av_free or av_freep.

So, use one of these:

av_free(frame);
av_freep(frame);

Upvotes: 0

Related Questions