大佬好,目前做了个简单的测试来验证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
请问具体的原因可能是什么?是软硬件不匹配吗?
大佬好,目前做了个简单的测试来验证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
请问具体的原因可能是什么?是软硬件不匹配吗?