Skip to content

RK3576 上解码 MJPEG 时 decode_get_frame 返回的 ret 为 MPP_SUCCESS,但是frame始终为空 #896

@rtmfpuser

Description

@rtmfpuser

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

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions