rockchip-linux / mpp

Media Process Platform (MPP) module
598 stars 171 forks source link

mpp_dec_parser 和mpp_dec_hal 无法释放,导致内存泄漏 #623

Open HouLingLXH opened 5 months ago

HouLingLXH commented 5 months ago

一下是我的初始化和释放代码: ` MppDecoder::~MppDecoder() { std::cout << "====析构==MppDecoder=" << std::endl; if (loop_data.packet) { mpp_packet_deinit(&loop_data.packet); loop_data.packet = NULL; } if (frame) { mpp_frame_deinit(&frame); frame = NULL; } if (mpp_ctx) { mpp_destroy(mpp_ctx); mpp_ctx = NULL; }

if (loop_data.frm_grp) {
    mpp_buffer_group_put(loop_data.frm_grp);
    loop_data.frm_grp = NULL;
}

}

int MppDecoder::Init(int video_type, int fps, void* userdata) { std::thread::id this_thread_id = std::this_thread::get_id(); // 获取本线程的ID std::cout << " MppDecoder::Init Thread ID = " << this_thread_id << std::endl;

MPP_RET ret         = MPP_OK;
this->userdata = userdata;
this->fps = fps;
this->last_frame_time_ms = 0;
if(video_type == 264) {
    mpp_type  = MPP_VIDEO_CodingAVC;
} else if (video_type == 265) {
    mpp_type  =MPP_VIDEO_CodingHEVC;
} else {
    LOGD("unsupport video_type %d", video_type);
    return -1;
}
LOGD("mpi_dec_test start ");
memset(&loop_data, 0, sizeof(loop_data));
LOGD("mpi_dec_test decoder test start mpp_type %d ", mpp_type);

MppDecCfg cfg       = NULL;

MppCtx mpp_ctx          = NULL;
ret = mpp_create(&mpp_ctx, &mpp_mpi);
if (MPP_OK != ret) {
    LOGD("mpp_create failed ");
    return 0;
}

ret = mpp_init(mpp_ctx, MPP_CTX_DEC, mpp_type);
if (ret) {
    LOGD("%p mpp_init failed ", mpp_ctx);
    return -1;
}

mpp_dec_cfg_init(&cfg);

/* get default config from decoder context */
ret = mpp_mpi->control(mpp_ctx, MPP_DEC_GET_CFG, cfg);
if (ret) {
    LOGD("%p failed to get decoder cfg ret %d ", mpp_ctx, ret);
    return -1;
}

/*
 * split_parse is to enable mpp internal frame spliter when the input
 * packet is not aplited into frames.
 */
ret = mpp_dec_cfg_set_u32(cfg, "base:split_parse", need_split);
if (ret) {
    LOGD("%p failed to set split_parse ret %d ", mpp_ctx, ret);
    return -1;
}

ret = mpp_mpi->control(mpp_ctx, MPP_DEC_SET_CFG, cfg);
if (ret) {
    LOGD("%p failed to set cfg %p ret %d ", mpp_ctx, cfg, ret);
    return -1;
}

mpp_dec_cfg_deinit(cfg);

loop_data.ctx            = mpp_ctx;
loop_data.mpi            = mpp_mpi;
loop_data.eos            = 0;
loop_data.packet_size    = packet_size;
loop_data.frame          = 0;
loop_data.frame_count    = 0;
return 1;

}`

析构之后,我在htop中查看,发现依然有很多mpp_dec_parser 和mpp_dec_hal 无法释放, 随着我多次反复创建于析构,他们会越来越多,内存也在不断被占用, 应该怎么办?

HermanChen commented 4 months ago

MppDecoder::Init 里的 mpp_ctx 是个局部变量吧,你打印下创新和销毁时候的指针值?

HouLingLXH commented 4 months ago

确实应该是局部变量,但是通过 mpp_create(&mpp_ctx, &mpp_mpi); 初始化 然后用mpp_destroy方法释放后,不能正常的释放mpp_dec_parser 和mpp_dec_hal, 他们会越来越多,在htop中可以明显的看到

HermanChen commented 4 months ago

确认是用的mpp_destroy销毁么?mpp_dec_parser mpp_dec_hal 这些线程肯定会被销毁的,最多有些结构体泄漏

HouLingLXH commented 4 months ago

这是析构函数,而且确定这个析构函数是执行了的

MppDecoder::~MppDecoder() { std::cout << "====析构==MppDecoder=" << std::endl; if (loop_data.packet) { mpp_packet_deinit(&loop_data.packet); loop_data.packet = NULL; } if (frame) { mpp_frame_deinit(&frame); frame = NULL; } if (mpp_ctx) { mpp_destroy(mpp_ctx); // 释放 mpp_ctx = NULL; }

if (loop_data.frm_grp) { mpp_buffer_group_put(loop_data.frm_grp); loop_data.frm_grp = NULL; } }

HermanChen commented 4 months ago

打印下 mpp_destroy(mpp_ctx) 的 mpp_ctx 指针和分配时候的指针

HouLingLXH commented 4 months ago

找到了一个问题,确实错用了局部变量, 现在改正以后,出现了新问题: 在多个线程(4个线程)同时调用mpp_destroy(分别释放四个ctx) 时会崩溃 (Segmentation fault) (如果只有一个线程执行mpp_destroy 则正常)

HouLingLXH commented 4 months ago

用最新的mpp代码编译并替换了 librockchip_mpp库 就能正常使用了, 非常感谢!