mxpi_videodecoder插件无法解码
收藏回复举报
mxpi_videodecoder插件无法解码
新人帖
发表于2026-04-15 15:44:59
0 查看

大佬好,目前做了个简单的测试来验证mxpi_videodecoder的功能,方便后面做视频质量排查。但是发现通过读取264文件给mxpi_videodecoder没有办法正常解码。

pipeline如下:

{

    "video_decode_simple": {

        "stream_config": {

            "deviceId": "0"

        },

        "appsrc0": {

            "props": {

                "blocksize": "409600"

            },

            "factory": "appsrc",

            "next": "mxpi_videodecoder0"

        },

        "mxpi_videodecoder0": {

            "props": {

                "dataSource": "appsrc0"

            },

            "factory": "mxpi_videodecoder",

            "next": "appsink0"

        },

        "appsink0": {

            "props": {

                "blocksize": "40960000"

            },

            "factory": "appsink"

        }

    }

}

代码如下:

#include <iostream>

#include <fstream>

#include <vector>

#include <string>

#include <memory>

// MxStream headers

#include "MxStream/StreamManager/MxStreamManager.h"

using namespace MxStream;

int main(int argc, char* argv[]) {

    if (argc < 2) {

        std::cerr << "Usage: " << argv[0] << " <h264_file>" << std::endl;

        return -1;

    }

    

    std::string h264_file = argv[1];

    std::string pipeline_file = "/root/work/VidQualityChk/config/video_decode_test.pipeline";

    std::string stream_name = "video_decode_test";

    std::string output_file = "/tmp/decoded_frame.yuv";

    

    std::cout << "=== mxpi_videodecoder Unit Test ===" << std::endl;

    std::cout << "Input: " << h264_file << std::endl;

    std::cout << "Pipeline: " << pipeline_file << std::endl;

    

    // 创建StreamManager

    auto stream_manager = std::make_shared<MxStreamManager>();

    

    // 加载pipeline

    APP_ERROR ret = stream_manager->CreateMultipleStreamsFromFile(pipeline_file);

    if (ret != APP_ERR_OK) {

        std::cerr << "Failed to load pipeline: " << ret << std::endl;

        return -1;

    }

    std::cout << "✓ Pipeline loaded" << std::endl;

    

    // 读取H.264文件并提取SPS+PPS+IDR

    std::ifstream file(h264_file, std::ios::binary);

    if (!file.is_open()) {

        std::cerr << "Failed to open file" << std::endl;

        return -1;

    }

    

    file.seekg(0, std::ios::end);

    size_t file_size = file.tellg();

    file.seekg(0, std::ios::beg);

    

    std::vector<uint8_t> file_data(file_size);

    file.read(reinterpret_cast<char*>(file_data.data()), file_size);

    file.close();

    

    std::cout << "✓ Loaded " << file_size << " bytes" << std::endl;

    

    // 简单查找SPS(7), PPS(8), IDR(5)

    std::vector<uint8_t> first_frame;

    size_t sps_start = 0, pps_start = 0, idr_start = 0;

    size_t sps_size = 0, pps_size = 0, idr_size = 0;

    bool found_sps = false, found_pps = false, found_idr = false;

    

    for (size_t i = 0; i + 4 < file_size; i++) {

        if (file_data[i] == 0 && file_data[i+1] == 0 && file_data[i+2] == 0 && file_data[i+3] == 1) {

            if (i + 4 < file_size) {

                uint8_t nal_type = file_data[i+4] & 0x1F;

                

                // 找到下一个NAL

                size_t next_nal = file_size;

                for (size_t j = i + 4; j + 3 < file_size; j++) {

                    if (file_data[j] == 0 && file_data[j+1] == 0 && file_data[j+2] == 0 && file_data[j+3] == 1) {

                        next_nal = j;

                        break;

                    }

                }

                

                if (nal_type == 7 && !found_sps) {

                    found_sps = true;

                    sps_start = i;

                    sps_size = next_nal - i;

                    std::cout << "✓ Found SPS at offset " << i << ", size=" << sps_size << std::endl;

                } else if (nal_type == 8 && found_sps && !found_pps) {

                    found_pps = true;

                    pps_start = i;

                    pps_size = next_nal - i;

                    std::cout << "✓ Found PPS at offset " << i << ", size=" << pps_size << std::endl;

                } else if (nal_type == 5 && found_sps && found_pps && !found_idr) {

                    found_idr = true;

                    idr_start = i;

                    idr_size = next_nal - i;

                    std::cout << "✓ Found IDR at offset " << i << ", size=" << idr_size << std::endl;

                    

                    // 组合SPS+PPS+IDR

                    first_frame.insert(first_frame.end(), file_data.begin() + sps_start, file_data.begin() + sps_start + sps_size);

                    first_frame.insert(first_frame.end(), file_data.begin() + pps_start, file_data.begin() + pps_start + pps_size);

                    first_frame.insert(first_frame.end(), file_data.begin() + idr_start, file_data.begin() + idr_start + idr_size);

                    

                    std::cout << "✓ Combined frame size: " << first_frame.size() << " bytes (SPS+PPS+IDR)" << std::endl;

                    break;

                }

            }

        }

    }

    

    if (first_frame.empty()) {

        std::cerr << "ERROR: Could not extract first frame" << std::endl;

        return -1;

    }

    

    // 发送数据

    MxstDataInput dataInput;

    dataInput.dataPtr = reinterpret_cast<uint32_t*>(first_frame.data());

    dataInput.dataSize = static_cast<int>(first_frame.size());

    

    std::cout << "Sending frame to appsrc..." << std::endl;

    ret = stream_manager->SendData(stream_name, "appsrc0", dataInput);

    if (ret != APP_ERR_OK) {

        std::cerr << "ERROR: SendData failed: " << ret << std::endl;

        return -1;

    }

    std::cout << "✓ Data sent" << std::endl;

    

    // 获取结果

    std::cout << "Waiting for decoded result (timeout 5s)..." << std::endl;

    MxstBufferAndMetadataOutput output = stream_manager->GetResult(stream_name, "appsink0", {}, 5000);

    

    if (output.bufferOutput == nullptr || output.bufferOutput->dataPtr == nullptr) {

        std::cerr << "ERROR: GetResult returned null (decode failed or timeout)" << std::endl;

        std::cerr << "This means mxpi_videodecoder could not decode the frame" << std::endl;

        return -1;

    }

    

    std::cout << "✓ SUCCESS! Decoded frame received" << std::endl;

    std::cout << "  Size: " << output.bufferOutput->dataSize << " bytes" << std::endl;

    

    // 保存

    std::ofstream out_file(output_file, std::ios::binary);

    if (out_file.is_open()) {

        out_file.write(reinterpret_cast<const char*>(output.bufferOutput->dataPtr), output.bufferOutput->dataSize);

        out_file.close();

        std::cout << "✓ Saved to: " << output_file << std::endl;

    }

    

    // 打印前16字节

    std::cout << "  First 16 bytes: ";

    for (int i = 0; i < 16 && i < output.bufferOutput->dataSize; i++) {

        printf("%02X ", ((uint8_t*)output.bufferOutput->dataPtr)[i]);

    }

    std::cout << std::endl;

    

    std::cout << "\n=== TEST PASSED ===" << std::endl;

    return 0;

}

目前使用的硬件和软件环境如下:

ascend-toolkit:8.3.RC1

mxVision版本: 7.2.RC1

设备型号: Ascend 310P3

操作系统: OPENEULER 22.03

请问具体的原因可能是什么?是软硬件不匹配吗?

我要发帖子