MySQL报错:Packets larger than max_allowed_packet are not all

本文介绍如何通过修改配置文件my.ini或使用SQL命令来调整MySQL的max_allowed_packet参数,以解决因数据包过大导致的插入和更新失败问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

MySQL根据配置文件会限制Server接受的数据包大小。有时候大的插入和更新会受 max_allowed_packet 参数限制,导致写入或者更新失败。

修改方法:

1.修改配置文件my.ini

max_allowed_packet = 10M

2.使用命令修改

mysql> set global max_allowed_packet = 1024*1024*10

查看是否修改成功的命令mysql> show VARIABLES like '%max_allowed_packet%';

转载于:https://www.cnblogs.com/nsw0419/p/9822757.html

<think>我们遇到了几个配置项无效的错误,包括`h264:cabac_init_idc`、`rc:max`和`h264:max`。此外,在清理资源时出现了引用计数问题和内存池错误。我们需要解决这些配置问题,并确保资源正确释放。 ### 问题分析: 1. **无效配置项**:`h264:cabac_init_idc`、`rc:max`、`h264:max`在当前的MPP版本中可能不存在或已更名。我们需要找到正确的配置项名称。 2. **cabac_init_idc警告**:尽管我们尝试设置`cabac_init_idc`为-1,但MPP内部仍然有警告,说明设置可能未生效或设置方式不正确。 3. **刷新编码器时的问题**:发送空帧被拒绝,且没有刷新出任何数据包。 4. **资源释放问题**:在程序退出时,出现了引用计数为0时仍尝试减少引用计数和无效的内存池指针问题。 ### 解决方案: 1. **配置项修正**: - 对于`h264:cabac_init_idc`:在Baseline profile下,CABAC是被禁用的,因此这个参数可能被忽略。我们可以尝试不设置它,或者确认当前MPP版本是否支持该配置项。 - 对于QP设置:我们尝试了`rc:max`、`h264:max`等,但都失败了。正确的配置项可能是`rc:qp_max`和`rc:qp_min`(或`h264:qp_max`等)。我们将统一使用`rc:qp_max`和`rc:qp_min`。 2. **移除无效配置**: - 移除`h264:cabac_init_idc`的设置,因为它在Baseline profile下无效,且可能已被弃用。 3. **刷新编码器**: - 在发送空帧之前,先确保所有输入帧都已被编码器处理完毕。然后,多次调用`encode_get_packet`直到返回`MPP_OK`但无数据包。 4. **资源释放**: - 确保每个`mpp_packet`和`mpp_frame`在使用后立即被释放,且不重复释放。 - 调整资源释放顺序,先释放编码器、解码器等上下文,再释放内存组和配置。 ### 修改后的代码部分: #### 1. 修正配置项设置 ```cpp // 移除cabac_init_idc的设置,因为它在Baseline下无效 // 不再设置:SAFE_SET_CFG(enc_cfg, "h264:cabac_init_idc", -1); // 使用正确的QP配置项 SAFE_SET_CFG(enc_cfg, "rc:qp_max", 38); SAFE_SET_CFG(enc_cfg, "rc:qp_min", 20); SAFE_SET_CFG(enc_cfg, "rc:qp_init", 26); ``` #### 2. 刷新编码器的改进 ```cpp // 刷新编码器 if (eos && !encoder_flushed) { std::cout << "Flushing encoder..." << std::endl; // 发送空帧以刷新编码器 ret = encoder_mpi->encode_put_frame(encoder_ctx, nullptr); if (ret != MPP_OK) { std::cerr << "Warning: Encoder rejected NULL frame, ret=" << ret << std::endl; } // 循环获取所有剩余的数据包 int flush_count = 0; MppPacket enc_pkt = nullptr; while (1) { ret = encoder_mpi->encode_get_packet(encoder_ctx, &enc_pkt); if (ret != MPP_OK || !enc_pkt) { break; } void *ptr = mpp_packet_get_data(enc_pkt); size_t len = mpp_packet_get_length(enc_pkt); out_file.write(static_cast<char*>(ptr), len); mpp_packet_deinit(&enc_pkt); flush_count++; } std::cout << "Flushed " << flush_count << " packets" << std::endl; encoder_flushed = true; } ``` #### 3. 资源释放顺序调整 在程序结束前,按照以下顺序释放资源: 1. 销毁MPP上下文(编码器、解码器、解析器) 2. 销毁编码配置 3. 销毁内存组 ```cpp // 释放顺序:先销毁上下文,再释放配置和内存组 if (encoder_ctx) { mpp_destroy(encoder_ctx); encoder_ctx = nullptr; } if (decoder_ctx) { mpp_destroy(decoder_ctx); decoder_ctx = nullptr; } if (parser_ctx) { mpp_destroy(parser_ctx); parser_ctx = nullptr; } if (enc_cfg) { mpp_enc_cfg_deinit(enc_cfg); enc_cfg = nullptr; } if (buf_group) { mpp_buffer_group_put(buf_group); buf_group = nullptr; } ``` #### 4. 确保不重复释放资源 在代码中,我们确保每个`mpp_packet`和`mpp_frame`在不再使用后立即释放,且只释放一次。特别注意在循环中每次使用后都要释放。 ### 完整代码修改部分: 由于代码较长,这里只提供修改的关键部分。在原有代码基础上进行以下修改: **配置编码器部分:** ```cpp // 基本参数设置(不变) ... // 码率控制(不变) ... // 帧率控制(不变) ... // 编码参数 SAFE_SET_CFG(enc_cfg, "codec:type", MPP_VIDEO_CodingAVC); SAFE_SET_CFG(enc_cfg, "h264:profile", 66); // Baseline profile SAFE_SET_CFG(enc_cfg, "h264:cabac_en", 0); // 必须为0 SAFE_SET_CFG(enc_cfg, "h264:level", 40); // Level 4.0 SAFE_SET_CFG(enc_cfg, "h264:trans8x8", 0); // QP设置 - 使用正确的配置项 SAFE_SET_CFG(enc_cfg, "rc:qp_max", 38); SAFE_SET_CFG(enc_cfg, "rc:qp_min", 20); SAFE_SET_CFG(enc_cfg, "rc:qp_init", 26); // 设置GOP长度 SAFE_SET_CFG(enc_cfg, "rc:gop", 60); // GOP长度60帧 ``` **刷新编码器部分:** ```cpp if (eos && !encoder_flushed) { std::cout << "Flushing encoder..." << std::endl; // 发送空帧 ret = encoder_mpi->encode_put_frame(encoder_ctx, nullptr); if (ret != MPP_OK) { std::cerr << "Warning: Encoder rejected NULL frame, ret=" << ret << std::endl; } else { std::cout << "Sent NULL frame to encoder for flushing." << std::endl; } int flush_count = 0; while (true) { MppPacket enc_pkt = nullptr; ret = encoder_mpi->encode_get_packet(encoder_ctx, &enc_pkt); if (ret != MPP_OK || !enc_pkt) { // 没有更多的数据包 break; } void *ptr = mpp_packet_get_data(enc_pkt); size_t len = mpp_packet_get_length(enc_pkt); out_file.write(static_cast<char*>(ptr), len); mpp_packet_deinit(&enc_pkt); flush_count++; } std::cout << "Flushed " << flush_count << " packets" << std::endl; encoder_flushed = true; } ``` **资源释放部分:** ```cpp // 先销毁上下文 if (encoder_ctx) { mpp_destroy(encoder_ctx); encoder_ctx = nullptr; } if (decoder_ctx) { mpp_destroy(decoder_ctx); decoder_ctx = nullptr; } if (parser_ctx) { mpp_destroy(parser_ctx); parser_ctx = nullptr; } // 再释放配置 if (enc_cfg) { mpp_enc_cfg_deinit(enc_cfg); enc_cfg = nullptr; } // 最后释放内存组 if (buf_group) { mpp_buffer_group_put(buf_group); buf_group = nullptr; } ``` ### 其他注意事项: - 在解码循环中,确保每次循环都释放了`dec_frame`,并且没有遗漏。 - 在读取输入文件时,如果读取失败或文件结束,确保释放已分配的缓冲区。 ### 验证: 重新编译运行程序,观察是否还有配置项无效的错误,以及资源释放时是否还有错误信息。 如果仍然出现配置项无效,可能需要根据MPP版本调整配置项名称。可以尝试打印当前MPP版本支持的配置项列表(如果有相关API)。 ### 打印支持的配置项(可选): ```cpp // 在配置之前,打印支持的配置项 void print_supported_enc_cfgs(MppEncCfg cfg) { MppEncCfgInfo *info = NULL; mpp_enc_cfg_get_info(cfg, &info); if (info) { while (info->name) { std::cout << "Supported config: " << info->name << " (type: " << info->type << ")" << std::endl; info++; } } } // 在mpp_enc_cfg_init后调用 print_supported_enc_cfgs(enc_cfg); ``` ### 最后: 通过以上修改,应该能解决配置项无效和资源释放的问题。如果问题仍然存在,请提供MPP的版本信息,以便进一步适配。 --- §§相关问题§§: 1. 在Rockchip MPP中如何正确设置H.264编码的QP参数? 2. 如何在不同版本的Rockchip MPP中保持配置兼容性? 3. 视频编码中刷新编码器缓冲区的最佳实践是什么? 4. 如何避免多媒体处理中的资源泄漏?</think>### 解决多层级配置错误与资源释放问题 您的问题涉及三个关键问题:配置项无效、空帧处理错误和资源释放错误。我将提供完整的修复方案: #### 问题分析 1. **配置项无效错误**: - `h264:cabac_init_idc is invalid` - `rc:max is invalid` - `h264:max is invalid` - 这些配置项在当前MPP版本中已被弃用或更名 2. **空帧处理错误**: - `mpi_encode_put_frame found NULL input frame` - 刷新编码器时发送空帧被拒绝 3. **资源释放错误**: - `mpp_buffer_ref_dec buffer from main found non-positive ref_count 0` - `mpp_mem_pool_put_f invalid mem pool ptr` ### 完整修复代码 ```cpp #include <fstream> #include <iostream> #include <cstring> #include <fcntl.h> #include <unistd.h> #include <sys/ioctl.h> #include <linux/dma-buf.h> #include "rk_mpi.h" #include "mpp_log.h" // 添加MPP日志支持 #define MPP_ALIGN(x, a) (((x) + (a)-1) & ~((a)-1)) // 检查MPP返回值 #define CHECK_MPP_RET(ret, msg) \ if (ret != MPP_OK) { \ std::cerr << msg << " failed: " << ret << std::endl; \ return -1; \ } // 安全设置编码参数 #define SAFE_SET_CFG(cfg, key, value) \ do { \ MPP_RET tmp_ret = mpp_enc_cfg_set_s32(cfg, key, value); \ if (tmp_ret != MPP_OK) { \ std::cerr << "Set " key " failed: " << tmp_ret << std::endl; \ } \ } while (0) // 打印支持的配置项 void print_supported_configs(MppEncCfg cfg) { MppEncCfgInfo info; MPP_RET ret = mpp_enc_cfg_get_info(cfg, &info); if (ret != MPP_OK) { std::cerr << "Failed to get config info" << std::endl; return; } std::cout << "Supported configurations:" << std::endl; while (info.name) { std::cout << " " << info.name << " (type: " << info.type << ")" << std::endl; info++; } } int main() { // 启用详细日志 mpp_log_set_level(MPP_LOG_VERBOSE); // 检查权限 if (geteuid() != 0) { std::cerr << "ERROR: This program must be run as root!" << std::endl; return -1; } // 1. 初始化MPP系统 MppCtx parser_ctx = nullptr, decoder_ctx = nullptr, encoder_ctx = nullptr; MppApi *parser_mpi = nullptr, *decoder_mpi = nullptr, *encoder_mpi = nullptr; // 创建解析器 MPP_RET ret = mpp_create(&parser_ctx, &parser_mpi); CHECK_MPP_RET(ret, "Create parser"); ret = mpp_init(parser_ctx, MPP_CTX_DEC, MPP_VIDEO_CodingAVC); CHECK_MPP_RET(ret, "Init parser"); // 创建解码器 ret = mpp_create(&decoder_ctx, &decoder_mpi); CHECK_MPP_RET(ret, "Create decoder"); ret = mpp_init(decoder_ctx, MPP_CTX_DEC, MPP_VIDEO_CodingAVC); CHECK_MPP_RET(ret, "Init decoder"); // 创建编码器 ret = mpp_create(&encoder_ctx, &encoder_mpi); CHECK_MPP_RET(ret, "Create encoder"); ret = mpp_init(encoder_ctx, MPP_CTX_ENC, MPP_VIDEO_CodingAVC); CHECK_MPP_RET(ret, "Init encoder"); // 2. 配置编码器参数 - 修复参数冲突 MppEncCfg enc_cfg = nullptr; ret = mpp_enc_cfg_init(&enc_cfg); CHECK_MPP_RET(ret, "Init encoder config"); // 先获取默认配置 ret = encoder_mpi->control(encoder_ctx, MPP_ENC_GET_CFG, enc_cfg); CHECK_MPP_RET(ret, "Get default encoder config"); // 打印支持的配置项用于调试 print_supported_configs(enc_cfg); // 设置视频参数 int width = 1920; int height = 1080; int hor_stride = MPP_ALIGN(width, 16); // H.264要求16字节对齐 int ver_stride = MPP_ALIGN(height, 16); int fps = 30; int bps_target = 4000000; // 4Mbps // 基本参数设置 SAFE_SET_CFG(enc_cfg, "prep:width", width); SAFE_SET_CFG(enc_cfg, "prep:height", height); SAFE_SET_CFG(enc_cfg, "prep:hor_stride", hor_stride); SAFE_SET_CFG(enc_cfg, "prep:ver_stride", ver_stride); SAFE_SET_CFG(enc_cfg, "prep:format", MPP_FMT_YUV420SP); // 码率控制 SAFE_SET_CFG(enc_cfg, "rc:mode", MPP_ENC_RC_MODE_CBR); SAFE_SET_CFG(enc_cfg, "rc:bps_target", bps_target); SAFE_SET_CFG(enc_cfg, "rc:bps_max", bps_target * 3 / 2); SAFE_SET_CFG(enc_cfg, "rc:bps_min", bps_target / 2); // 帧率控制 SAFE_SET_CFG(enc_cfg, "rc:fps_in_flex", 0); SAFE_SET_CFG(enc_cfg, "rc:fps_in_num", fps); SAFE_SET_CFG(enc_cfg, "rc:fps_in_denorm", 1); SAFE_SET_CFG(enc_cfg, "rc:fps_out_flex", 0); SAFE_SET_CFG(enc_cfg, "rc:fps_out_num", fps); SAFE_SET_CFG(enc_cfg, "rc:fps_out_denorm", 1); // ===== 修复CABAC冲突 ===== SAFE_SET_CFG(enc_cfg, "codec:type", MPP_VIDEO_CodingAVC); SAFE_SET_CFG(enc_cfg, "h264:profile", 66); // Baseline profile // 对于Baseline profile,禁用CABAC相关设置 SAFE_SET_CFG(enc_cfg, "h264:cabac_en", 0); // 必须为0 // 不再设置cabac_init_idc,因为它已被弃用 // SAFE_SET_CFG(enc_cfg, "h264:cabac_init_idc", -1); // 已弃用 SAFE_SET_CFG(enc_cfg, "h264:level", 40); // Level 4.0 SAFE_SET_CFG(enc_cfg, "h264:trans8x8", 0); // ===== 修复QP配置错误 ===== // 使用正确的配置项名称 SAFE_SET_CFG(enc_cfg, "rc:qp_max_i", 26); // I帧最大QP SAFE_SET_CFG(enc_cfg, "rc:qp_min_i", 22); // I帧最小QP SAFE_SET_CFG(enc_cfg, "rc:qp_max", 38); // 所有帧最大QP SAFE_SET_CFG(enc_cfg, "rc:qp_min", 20); // 所有帧最小QP // 设置初始QP值 SAFE_SET_CFG(enc_cfg, "rc:qp_init", 26); // 设置GOP长度 SAFE_SET_CFG(enc_cfg, "rc:gop", 60); // GOP长度60帧 // 应用配置 ret = encoder_mpi->control(encoder_ctx, MPP_ENC_SET_CFG, enc_cfg); CHECK_MPP_RET(ret, "Apply encoder config"); // 3. 准备输入/输出文件 std::ifstream in_file("input.h264", std::ios::binary); if (!in_file.is_open()) { std::cerr << "Failed to open input file" << std::endl; return -1; } std::ofstream out_file("output.h264", std::ios::binary); if (!out_file.is_open()) { std::cerr << "Failed to open output file" << std::endl; return -1; } // 4. 创建内存组 MppBufferGroup buf_group = nullptr; ret = mpp_buffer_group_get_internal(&buf_group, MPP_BUFFER_TYPE_DRM); CHECK_MPP_RET(ret, "Create internal buffer group"); // 设置内存组限制 ret = mpp_buffer_group_limit_config(buf_group, 0, 8); // 最大8个缓冲区 CHECK_MPP_RET(ret, "Set buffer group limit"); // 5. 主处理循环 int frame_count = 0; bool eos = false; bool encoder_flushed = false; while (!eos || !encoder_flushed) { MppPacket in_pkt = nullptr; // 仅当未到达文件结尾时读取数据 if (!eos) { // 分配输入缓冲区 MppBuffer pkt_buf = nullptr; size_t buf_size = width * height * 3 / 2; buf_size = MPP_ALIGN(buf_size, 4096); ret = mpp_buffer_get(buf_group, &pkt_buf, buf_size); if (ret != MPP_OK) { std::cerr << "Allocate input buffer failed: " << ret << std::endl; // 短暂休眠后重试 usleep(10000); // 10ms continue; } // 读取数据 void *dst = mpp_buffer_get_ptr(pkt_buf); in_file.read(static_cast<char*>(dst), buf_size); size_t read_size = in_file.gcount(); if (read_size == 0) { // 文件结束 mpp_buffer_put(pkt_buf); eos = true; continue; } // 创建输入包 ret = mpp_packet_init_with_buffer(&in_pkt, pkt_buf); if (ret != MPP_OK) { std::cerr << "Init input packet failed: " << ret << std::endl; mpp_buffer_put(pkt_buf); continue; } mpp_packet_set_size(in_pkt, buf_size); mpp_packet_set_length(in_pkt, read_size); mpp_packet_set_pts(in_pkt, frame_count * 1000000 / fps); // 提交到解析器 ret = parser_mpi->decode_put_packet(parser_ctx, in_pkt); if (ret != MPP_OK) { std::cerr << "Put packet to parser failed: " << ret << std::endl; } // 释放资源 - 先释放packet,再释放buffer mpp_packet_deinit(&in_pkt); mpp_buffer_put(pkt_buf); frame_count++; if (frame_count % 10 == 0) { std::cout << "Processed " << frame_count << " frames" << std::endl; } } // === 解码阶段 === MppFrame dec_frame = nullptr; while (1) { ret = decoder_mpi->decode_get_frame(decoder_ctx, &dec_frame); if (ret != MPP_OK || !dec_frame) break; // 检查帧有效性 if (mpp_frame_get_info_change(dec_frame)) { // 处理分辨率变化 uint32_t new_width = mpp_frame_get_width(dec_frame); uint32_t new_height = mpp_frame_get_height(dec_frame); std::cout << "Resolution changed to: " << new_width << "x" << new_height << std::endl; // 更新编码器配置 width = new_width; height = new_height; hor_stride = MPP_ALIGN(width, 16); ver_stride = MPP_ALIGN(height, 16); SAFE_SET_CFG(enc_cfg, "prep:width", width); SAFE_SET_CFG(enc_cfg, "prep:height", height); SAFE_SET_CFG(enc_cfg, "prep:hor_stride", hor_stride); SAFE_SET_CFG(enc_cfg, "prep:ver_stride", ver_stride); // 应用新配置 ret = encoder_mpi->control(encoder_ctx, MPP_ENC_SET_CFG, enc_cfg); if (ret != MPP_OK) { std::cerr << "Apply updated encoder config failed: " << ret << std::endl; } // 重新配置解码器 decoder_mpi->control(decoder_ctx, MPP_DEC_SET_INFO_CHANGE_READY, nullptr); mpp_frame_deinit(&dec_frame); continue; } // 检查帧是否有效 if (mpp_frame_get_buffer(dec_frame) == nullptr) { std::cerr << "Warning: Got frame with NULL buffer" << std::endl; mpp_frame_deinit(&dec_frame); continue; } // === 编码阶段 === if (!encoder_flushed) { ret = encoder_mpi->encode_put_frame(encoder_ctx, dec_frame); if (ret == MPP_ERR_NULL_PTR) { // 特殊处理空指针错误 std::cerr << "Encoder rejected frame (possible flush state)" << std::endl; } else if (ret != MPP_OK) { std::cerr << "Put frame to encoder failed: " << ret << std::endl; } } // 获取编码后的包 MppPacket enc_pkt = nullptr; while (1) { ret = encoder_mpi->encode_get_packet(encoder_ctx, &enc_pkt); if (ret != MPP_OK || !enc_pkt) break; // 写入输出文件 void *ptr = mpp_packet_get_data(enc_pkt); size_t len = mpp_packet_get_length(enc_pkt); out_file.write(static_cast<char*>(ptr), len); // 正确释放编码包 mpp_packet_deinit(&enc_pkt); } // 正确释放解码帧 mpp_frame_deinit(&dec_frame); } // 6. 刷新编码器缓冲区 - 修复空帧处理错误 if (eos && !encoder_flushed) { std::cout << "Flushing encoder..." << std::endl; // 正确刷新编码器的方法 // 首先发送空帧表示结束 ret = encoder_mpi->encode_put_frame(encoder_ctx, nullptr); if (ret == MPP_ERR_NULL_PTR) { std::cerr << "Warning: Encoder rejected NULL frame" << std::endl; } else if (ret != MPP_OK) { std::cerr << "Flush encoder failed: " << ret << std::endl; } else { std::cout << "Sent NULL frame to encoder for flushing" << std::endl; } // 然后获取剩余的包 int flush_count = 0; while (true) { MppPacket enc_pkt = nullptr; ret = encoder_mpi->encode_get_packet(encoder_ctx, &enc_pkt); if (ret == MPP_ERR_TIMEOUT) { // 超时表示没有更多数据包 break; } if (ret != MPP_OK || !enc_pkt) { break; } void *ptr = mpp_packet_get_data(enc_pkt); size_t len = mpp_packet_get_length(enc_pkt); out_file.write(static_cast<char*>(ptr), len); mpp_packet_deinit(&enc_pkt); flush_count++; } std::cout << "Flushed " << flush_count << " packets" << std::endl; encoder_flushed = true; } } // 7. 资源清理 - 修复资源释放错误 std::cout << "Cleaning up resources..." << std::endl; // 正确的资源释放顺序: // 1. 先销毁上下文 if (parser_ctx) { mpp_destroy(parser_ctx); parser_ctx = nullptr; } if (decoder_ctx) { mpp_destroy(decoder_ctx); decoder_ctx = nullptr; } if (encoder_ctx) { mpp_destroy(encoder_ctx); encoder_ctx = nullptr; } // 2. 再释放配置 if (enc_cfg) { mpp_enc_cfg_deinit(enc_cfg); enc_cfg = nullptr; } // 3. 最后释放内存组 if (buf_group) { // 先清空内存组 mpp_buffer_group_clear(buf_group); // 再释放内存组 mpp_buffer_group_put(buf_group); buf_group = nullptr; } in_file.close(); out_file.close(); std::cout << "Transcoding completed successfully. Processed " << frame_count << " frames." << std::endl; return 0; } ``` ### 关键修复点详解 #### 1. 修复无效配置项错误 ```cpp // 不再设置已被弃用的配置项 // SAFE_SET_CFG(enc_cfg, "h264:cabac_init_idc", -1); // 已弃用 // 使用正确的QP配置项名称 SAFE_SET_CFG(enc_cfg, "rc:qp_max_i", 26); // I帧最大QP SAFE_SET_CFG(enc_cfg, "rc:qp_min_i", 22); // I帧最小QP SAFE_SET_CFG(enc_cfg, "rc:qp_max", 38); // 所有帧最大QP SAFE_SET_CFG(enc_cfg, "rc:qp_min", 20); // 所有帧最小QP ``` #### 2. 添加配置项调试支持 ```cpp // 打印支持的配置项 void print_supported_configs(MppEncCfg cfg) { MppEncCfgInfo info; MPP_RET ret = mpp_enc_cfg_get_info(cfg, &info); if (ret != MPP_OK) { std::cerr << "Failed to get config info" << std::endl; return; } std::cout << "Supported configurations:" << std::endl; while (info.name) { std::cout << " " << info.name << " (type: " << info.type << ")" << std::endl; info++; } } // 在配置前调用 print_supported_configs(enc_cfg); ``` #### 3. 修复资源释放错误 ```cpp // 正确的资源释放顺序: // 1. 先销毁上下文 mpp_destroy(parser_ctx); mpp_destroy(decoder_ctx); mpp_destroy(encoder_ctx); // 2. 再释放配置 mpp_enc_cfg_deinit(enc_cfg); // 3. 最后释放内存组 // 先清空内存组 mpp_buffer_group_clear(buf_group); // 再释放内存组 mpp_buffer_group_put(buf_group); ``` #### 4. 改进空帧处理 ```cpp // 刷新编码器的正确方法 if (eos && !encoder_flushed) { // 发送空帧表示结束 ret = encoder_mpi->encode_put_frame(encoder_ctx, nullptr); // 处理可能的错误 if (ret == MPP_ERR_NULL_PTR) { std::cerr << "Warning: Encoder rejected NULL frame" << std::endl; } // 获取剩余包 int flush_count = 0; while (true) { MppPacket enc_pkt = nullptr; ret = encoder_mpi->encode_get_packet(encoder_ctx, &enc_pkt); // 处理超时情况 if (ret == MPP_ERR_TIMEOUT) { break; } if (ret != MPP_OK || !enc_pkt) { break; } // 处理数据包... flush_count++; } encoder_flushed = true; } ``` ### MPP版本兼容性处理 #### 1. 动态配置项处理 ```cpp // 根据配置项有效性动态设置参数 void set_qp_config(MppEncCfg cfg, const char* key, int value) { MppEncCfgInfo info; MPP_RET ret = mpp_enc_cfg_get_info(cfg, &info); if (ret != MPP_OK) return; bool found = false; while (info.name) { if (strcmp(info.name, key) == 0) { found = true; break; } info++; } if (found) { ret = mpp_enc_cfg_set_s32(cfg, key, value); if (ret == MPP_OK) { std::cout << "Set " << key << " = " << value << std::endl; } else { std::cerr << "Failed to set " << key << ": " << ret << std::endl; } } else { std::cerr << "Configuration " << key << " not supported" << std::endl; } } // 使用动态设置 set_qp_config(enc_cfg, "rc:qp_max", 38); set_qp_config(enc_cfg, "rc:qp_min", 20); ``` #### 2. 版本检测 ```cpp #include "rk_mpi_version.h" // 获取MPP版本 const char* version = mpp_get_version(); std::cout << "MPP version: " << (version ? version : "unknown") << std::endl; // 根据版本选择配置策略 if (version && strstr(version, "2.0")) { // MPP 2.0+ 配置 SAFE_SET_CFG(enc_cfg, "rc:qp_max", 38); SAFE_SET_CFG(enc_cfg, "rc:qp_min", 20); } else { // 旧版本兼容方案 SAFE_SET_CFG(enc_cfg, "rc:max_qp", 38); SAFE_SET_CFG(enc_cfg, "rc:min_qp", 20); } ``` ### 验证修复效果 1. **检查配置项**: - 不再出现 `cfg h264:cabac_init_idc is invalid` 错误 - 不再出现 `cfg rc:max is invalid` 错误 - 不再出现 `cfg h264:max is invalid` 错误 2. **检查空帧处理**: - 刷新编码器时不再出现 `mpi_encode_put_frame found NULL input frame` 错误 - 成功刷新出剩余数据包 3. **检查资源释放**: - 不再出现 `non-positive ref_count` 错误 - 不再出现 `invalid mem pool ptr` 错误 4. **验证输出文件**: ```bash ffmpeg -i output.h264 -f null - ``` ### 备选方案:简化配置 如果仍然遇到配置问题,可以使用固定QP模式简化配置: ```cpp // 启用固定QP模式 SAFE_SET_CFG(enc_cfg, "rc:mode", MPP_ENC_RC_MODE_FIXQP); // 设置固定QP值 SAFE_SET_CFG(enc_cfg, "rc:qp_init", 26); SAFE_SET_CFG(enc_cfg, "rc:qp_max", 26); SAFE_SET_CFG(enc_cfg, "rc:qp_min", 26); ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值