-
Notifications
You must be signed in to change notification settings - Fork 242
Open
Description
RK3576 上解码 MJPEG 时 decode_get_frame 返回的 ret 为 MPP_SUCCESS,但是frame始终为空,解码前将帧数据保存为图片文件,发现图片完全正常,解码失败后使用 OpenCV 解码,发现解码成功。同时 mp_dec_test 执行的时候没有任何输出。以下是相关程序代码:
`bool CameraManager::decodeMJPEGWithMPP(CameraDevice* camera, void* data, size_t size, cv::Mat& output_frame) {
if (!camera->mpp_dec_initialized) {
if (!initMPPDecoder(camera)) {
return false;
}
}
MPP_RET ret = MPP_OK;
MppPacket packet = nullptr;
MppFrame frame = nullptr;
MppFrame frame_ret = nullptr;
MppMeta meta = nullptr;
/*mpp_packet_init_with_buffer(&packet, data);*/
// 创建输入包
ret = mpp_packet_init(&packet, data, size);
if (ret != MPP_OK) {
std::cerr << "Failed to init MPP packet: " << ret << std::endl;
return false;
}
mpp_packet_set_data(packet, data);
mpp_packet_set_size(packet, size);
mpp_packet_set_pos(packet, data);
mpp_packet_set_length(packet, size);
mpp_packet_set_eos(packet);
//saveFrame(data, size);
meta = mpp_packet_get_meta(packet);
if (meta)
mpp_meta_set_frame(meta, KEY_OUTPUT_FRAME, frame); // 设置输出帧
else{
std::cerr << "Failed to put packet to get meta" << std::endl;
}
// 发送数据到解码器
ret = camera->mpp_dec_mpi->decode_put_packet(camera->mpp_dec_ctx, packet);
if (ret != MPP_OK) {
std::cerr << "Failed to put packet to decoder: " << ret << std::endl;
mpp_packet_deinit(&packet);
return false;
}
// 尝试获取帧
ret = camera->mpp_dec_mpi->decode_get_frame(camera->mpp_dec_ctx, &frame_ret);
if (ret != MPP_OK || frame_ret == nullptr) {
std::cout << "No frame available from decoder: " << ret << std::endl;
mpp_packet_deinit(&packet);
return false;
}
if (frame_ret != frame)
std::cout << "mismatch frame" << std::endl;
// 检查信息变化
if (mpp_frame_get_info_change(frame)) {
std::cout << "Info change detected, resetting decoder" << std::endl;
mpp_frame_deinit(&frame);
mpp_packet_deinit(&packet);
// 重置解码器
resetMPPDecoder(camera);
return decodeMJPEGWithMPP(camera, data, size, output_frame);
}
// 获取帧数据
MppBuffer buffer = mpp_frame_get_buffer(frame);
if (buffer == nullptr) {
std::cerr << "Failed to get buffer from frame" << std::endl;
mpp_packet_deinit(&packet);
mpp_frame_deinit(&frame);
return false;
}
void* frame_data = mpp_buffer_get_ptr(buffer);
size_t frame_size = mpp_buffer_get_size(buffer);
if (frame_data == nullptr || frame_size == 0) {
std::cerr << "Invalid frame data" << std::endl;
mpp_packet_deinit(&packet);
mpp_frame_deinit(&frame);
return false;
}
// 获取帧信息
int width = mpp_frame_get_width(frame);
int height = mpp_frame_get_height(frame);
MppFrameFormat format = mpp_frame_get_fmt(frame);
int hor_stride = mpp_frame_get_hor_stride(frame);
int ver_stride = mpp_frame_get_ver_stride(frame);
std::cout << "Decoded frame: " << width << "x" << height
<< ", format: " << format
<< ", stride: " << hor_stride << "x" << ver_stride
<< ", size: " << frame_size << std::endl;
// 转换为OpenCV格式
try {
if (format == MPP_FMT_YUV420SP) {
// NV12格式
cv::Mat nv12_mat(height * 3 / 2, hor_stride, CV_8UC1, frame_data);
cv::Mat cropped = nv12_mat(cv::Rect(0, 0, width, height * 3 / 2));
cv::cvtColor(cropped, output_frame, cv::COLOR_YUV2BGR_NV12);
} else if (format == MPP_FMT_YUV420SP_VU) {
// NV21格式
cv::Mat nv21_mat(height * 3 / 2, hor_stride, CV_8UC1, frame_data);
cv::Mat cropped = nv21_mat(cv::Rect(0, 0, width, height * 3 / 2));
cv::cvtColor(cropped, output_frame, cv::COLOR_YUV2BGR_NV21);
} else if (format == MPP_FMT_YUV420P) {
// YUV420P格式
cv::Mat yuv420p_mat(height * 3 / 2, hor_stride, CV_8UC1, frame_data);
cv::Mat cropped = yuv420p_mat(cv::Rect(0, 0, width, height * 3 / 2));
cv::cvtColor(cropped, output_frame, cv::COLOR_YUV2BGR_I420);
} else {
std::cerr << "Unsupported MPP format: " << format << std::endl;
mpp_packet_deinit(&packet);
mpp_frame_deinit(&frame);
return false;
}
} catch (const cv::Exception& e) {
std::cerr << "OpenCV exception during color conversion: " << e.what() << std::endl;
mpp_packet_deinit(&packet);
mpp_frame_deinit(&frame);
return false;
}
mpp_packet_deinit(&packet);
mpp_frame_deinit(&frame);
std::cout << "MPP decoding successful" << std::endl;
return true;
}`
Metadata
Metadata
Assignees
Labels
No labels