mpp icon indicating copy to clipboard operation
mpp copied to clipboard

mpi_->decode_put_packet(mpp_ctx_, mpp_pkt_); Failed to put packet into MPP, error code: -1012

Open HuKai97 opened this issue 4 months ago • 0 comments

想实现的功能:使用mmp代替cv::Mat image = cv::imdecode(cv::Mat(1, buf.bytesused, CV_8UC1, buffers_[buf.index].start), cv::IMREAD_COLOR); 减少cpu使用率

代码: #include <ros/ros.h> #include <sensor_msgs/Image.h> #include <linux/videodev2.h> #include <fcntl.h> #include <sys/ioctl.h> #include <sys/mman.h> #include <unistd.h> #include #include #include <opencv2/opencv.hpp> #include <rockchip/mpp_buffer.h> // #include <rockchip/mpp_dec.h> #include <rockchip/mpp_frame.h> #include <rockchip/mpp_packet.h> #include <rockchip/rk_mpi.h>

#define HEIGHT 480 #define WIDTH 640 #define FPS 30

class V4L2CameraNode { public: V4L2CameraNode() : mpp_ctx_(nullptr), mpp_pkt_(nullptr), mpp_frm_(nullptr), mpp_buf_grp_(nullptr) { fd_ = open("/dev/video0", O_RDWR); if (fd_ == -1) { ROS_ERROR("Failed to open V4L2 device"); return; }

    if (initializeMPP() != MPP_OK)
    {
        ROS_ERROR("Failed to initialize MPP");
        close(fd_);
        return;
    }

    struct v4l2_capability cap;
    if (ioctl(fd_, VIDIOC_QUERYCAP, &cap) == -1)
    {
        ROS_ERROR("Failed to query V4L2 capabilities");
        close(fd_);
        return;
    }

    struct v4l2_format fmt;
    fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    fmt.fmt.pix.width = WIDTH;
    fmt.fmt.pix.height = HEIGHT;
    fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_MJPEG;
    fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
    if (ioctl(fd_, VIDIOC_S_FMT, &fmt) == -1)
    {
        ROS_ERROR("Failed to set V4L2 format");
        close(fd_);
        return;
    }

    struct v4l2_requestbuffers req;
    req.count = 4;
    req.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    req.memory = V4L2_MEMORY_MMAP;
    if (ioctl(fd_, VIDIOC_REQBUFS, &req) == -1)
    {
        ROS_ERROR("Failed to request buffers");
        close(fd_);
        return;
    }

    buffers_.resize(req.count);
    for (unsigned int i = 0; i < req.count; ++i)
    {
        struct v4l2_buffer buf;
        memset(&buf, 0, sizeof(buf));
        buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        buf.memory = V4L2_MEMORY_MMAP;
        buf.index = i;

        if (ioctl(fd_, VIDIOC_QUERYBUF, &buf) == -1)
        {
            ROS_ERROR("Failed to query buffer");
            close(fd_);
            return;
        }

        buffers_[i].length = buf.length;
        buffers_[i].start = mmap(NULL, buf.length, PROT_READ | PROT_WRITE, MAP_SHARED, fd_, buf.m.offset);
        ROS_INFO("BUffer[%d] mapped at address: %p, length: %zu", i, buffers_[i].start, buffers_[i].length);

        if (buffers_[i].start == MAP_FAILED)
        {
            ROS_ERROR("Failed to map buffer");
            close(fd_);
            return;
        }

        if (ioctl(fd_, VIDIOC_QBUF, &buf) == -1)
        {
            ROS_ERROR("Failed to queue buffer");
            close(fd_);
            return;
        }
    }

    v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    if (ioctl(fd_, VIDIOC_STREAMON, &type) == -1)
    {
        ROS_ERROR("Failed to start streaming");
        close(fd_);
        return;
    }

    image_pub_ = nh_.advertise<sensor_msgs::Image>("camera/image_raw", 1);
    ros_timer_ = nh_.createTimer(ros::Duration(1.0 / FPS), &V4L2CameraNode::captureImage, this);
}

~V4L2CameraNode()
{
    ros_timer_.stop();
    v4l2_buf_type type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    ioctl(fd_, VIDIOC_STREAMOFF, &type);

    for (auto& buffer : buffers_)
    {
        if (buffer.start != MAP_FAILED)
        {
            munmap(buffer.start, buffer.length);
        }
    }

    close(fd_);
    deinitializeMPP();
}

private: MPP_RET initializeMPP() { MPP_RET ret = mpp_create(&mpp_ctx_, &mpi_); ROS_INFO("mpp create ret: %d", ret); if (ret != MPP_OK) return ret;

    ret = mpp_init(mpp_ctx_, MPP_CTX_DEC, MPP_VIDEO_CodingMJPEG);
ROS_INFO("mpp init  ret: %d", ret);
    if (ret != MPP_OK)
        return ret;

    return MPP_OK;
}

void deinitializeMPP()
{
    if (mpp_ctx_)
    {
        mpp_destroy(mpp_ctx_);
        mpp_ctx_ = nullptr;
    }
}

void captureImage(const ros::TimerEvent&)
{
    struct v4l2_buffer buf;
    memset(&buf, 0, sizeof(buf));
    buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
    buf.memory = V4L2_MEMORY_MMAP;

    if (ioctl(fd_, VIDIOC_DQBUF, &buf) == -1)
    {
        ROS_ERROR("Failed to dequeue buffer");
        return;
    }
    ROS_INFO("buf.bytesused: %d", buf.bytesused);

 // 保存捕获的 JPEG 数据以供验证
	std::ofstream outfile("captured_frame.jpg", std::ios::binary);
	outfile.write(static_cast<char*>(buffers_[buf.index].start), buf.bytesused);
	outfile.close();

// 验证 MJPEG 数据的格式
const uint8_t* data = static_cast<const uint8_t*>(buffers_[buf.index].start);
if (buf.bytesused < 2 || data[0] != 0xFF || data[1] != 0xD8)
{
    ROS_ERROR("Captured data is not valid MJPEG format");
    if (ioctl(fd_, VIDIOC_QBUF, &buf) == -1)
    {
        ROS_ERROR("Failed to requeue buffer");
    }
    return;
}	

    // 创建 MPP 包
    // 增加调试信息:打印缓冲区的字节大小和起始地址
    ROS_INFO("Dequeued buffer: index=%d, bytesused=%d, start address=%p", buf.index, buf.bytesused, buffers_[buf.index].start);
    MPP_RET ret = mpp_packet_init(&mpp_pkt_, buffers_[buf.index].start, buf.bytesused);
    if (ret != MPP_OK)
    {
        ROS_ERROR("Failed to initialize MPP packet, error code: %d", ret);
        return;
    }
    ROS_INFO("MPP packet initialized successfully");
    
    // 将包传递给解码器前增加调试信息
    ROS_INFO("Putting packet into MPP for decoding with size:%d", buf.bytesused);
    std::cout << "mpp_ctx_" << mpp_ctx_ << std::endl;
    std::cout << "mpp_pkt_" << mpp_pkt_ << std::endl;
    ret = mpi_->decode_put_packet(mpp_ctx_, mpp_pkt_);
    if (ret != MPP_OK)
    {
        ROS_ERROR("MPP packet data ptr: %p, size: %d", buffers_[buf.index].start, buf.bytesused);
        ROS_ERROR("Failed to put packet into MPP, error code: %d", ret);
        return;
    }
    ROS_INFO("Packet successfully put into MPP");

    // 解码输出
    ROS_INFO("decode get frame");
    ret = mpi_->decode_get_frame(mpp_ctx_, &mpp_frm_);
    if (ret != MPP_OK || mpp_frm_ == NULL)
    {
        ROS_ERROR("Failed to decode MJPEG frame");
        return;
    }
    ROS_INFO("Frame successfully decoded");


    if (mpp_frame_get_info_change(mpp_frm_))
    {
        ROS_WARN("Detected MPP frame info change");
    }

    // 获取解码后的图像
    MppBuffer mpp_buf = mpp_frame_get_buffer(mpp_frm_);
    if (mpp_buf)
    {
        void* ptr = mpp_buffer_get_ptr(mpp_buf);
        cv::Mat image(HEIGHT, WIDTH, CV_8UC3, ptr);  // 这里直接使用解码后的数据

        // 创建 ROS 图像消息并设置其属性
        sensor_msgs::ImagePtr image_msg = boost::make_shared<sensor_msgs::Image>();
        image_msg->header.stamp = ros::Time::now();
        image_msg->height = image.rows;
        image_msg->width = image.cols;
        image_msg->encoding = "bgr8";   // 设置为 BGR8 编码
        image_msg->step = image.step[0]; 
        image_msg->data.assign(image.data, image.data + image.total() * image.elemSize());

        // 发布图像消息
        image_pub_.publish(image_msg);
    }

    // 释放 MPP 资源
    mpp_packet_deinit(&mpp_pkt_);
    mpp_frame_deinit(&mpp_frm_);

    // 重新将缓冲区放回捕获队列
    if (ioctl(fd_, VIDIOC_QBUF, &buf) == -1)
    {
        ROS_ERROR("Failed to requeue buffer");
    }
}

ros::NodeHandle nh_;
ros::Timer ros_timer_;
int fd_;
MppCtx mpp_ctx_;
MppApi* mpi_;
MppPacket mpp_pkt_;
MppFrame mpp_frm_;
MppBufferGroup mpp_buf_grp_;

struct buffer
{
    void* start;
    size_t length;
};
std::vector<struct buffer> buffers_;
ros::Publisher image_pub_;

};

int main(int argc, char** argv) { ros::init(argc, argv, "v4l2_camera_node"); V4L2CameraNode node; ros::spin(); return 0; }

报错: (base) orangepi@orangepi5plus:~/hk/code/v4l2$ rosrun v4l2 publisher [ INFO] [1728982422.451431991]: mpp create ret: 0 [ INFO] [1728982422.459096268]: mpp init ret: 0 [ INFO] [1728982422.470774681]: BUffer[0] mapped at address: 0x7f89ec0000, length: 614400 [ INFO] [1728982422.724946479]: buf.bytesused: 63660 [ INFO] [1728982422.727768302]: Dequeued buffer: index=0, bytesused=63660, start address=0x7f89ec0000 [ INFO] [1728982422.728311668]: MPP packet initialized successfully [ INFO] [1728982422.730474920]: Putting packet into MPP for decoding with size:63660 mpp_ctx_0x5571f6c2c0 mpp_pkt_0x5571f7b4a8 [ INFO] [1728982422.731062034]: MPP packet data ptr: 0x7f89ec0000, size: 63660 [ERROR] [1728982422.731212823]: Failed to put packet into MPP, error code: -1012 有大佬知道怎么回事吗?

HuKai97 avatar Oct 15 '24 09:10 HuKai97