如何将 Openh264 解码帧无延迟输出格式转换为 OpenCV 矩阵

How to convert Openh264 DecodeFrameNoDelay output format to OpenCV matrix?

本文关键字:格式 输出 转换 矩阵 OpenCV 延迟 Openh264 解码      更新时间:2023-10-16

我想将DecodeFrameNoDelay函数的输出格式转换为yuvDatabufferInfo到OpenCV矩阵,我可以使用imshow函数在窗口上显示框架

链接 git to DecodeFrameNoDelay 详细信息:https://github.com/cisco/openh264/wiki/ISVCDecoder#decodeframenodelay

以下是我使用 Openh264 解码帧的代码

ISVCDecoder *decoder;
SBufferInfo bufferInfo;
SDecodingParam decodingParam;
uint8_t** yuvData;
void init(int width, int height) {
    WelsCreateDecoder(&decoder);
    decodingParam = {0};
    decodingParam.sVideoProperty.eVideoBsType = VIDEO_BITSTREAM_AVC;
    decoder->Initialize(&decodingParam);
    bufferInfo = {0};
    bufferInfo.iBufferStatus = 1;
    yuvData = new uint8_t*[3];
    yuvData[0] = new uint8_t[width * height];
    yuvData[1] = new uint8_t[width * height / 4];
    yuvData[2] = new uint8_t[width * height / 4];
}
bool decode(const unsigned char* rawEncodedData, int rawEncodedDataLength, uint8_t** yuvData, char *name) {
    int err = decoder->DecodeFrameNoDelay(rawEncodedData, rawEncodedDataLength, yuvData, &bufferInfo);
    if (err != 0) {
        std::cout << "H264 decoding failed. Error code: " << err << "." << std::endl;
        parseErrorCode(err);
        return false;
    }
    printf("H264 decoding success, err: %d, name: %s, status: %dn", err, name, bufferInfo.iBufferStatus);
    return true;
}

任何帮助,不胜感激。

谢谢和最好的问候。

执行复制时应考虑一个stride参数。这是一个将帧解码为 opencv cv::Mat的代码:

inline void copyWithStride(
        void* dst, const void* src,
        size_t width, size_t height, size_t stride
) {
    for (size_t row = 0; row < height; ++row) {
        uint8_t* posFrom = (uint8_t*)src + row * stride;
        uint8_t* posTo = (uint8_t*)dst + row * width;
        memcpy(posTo, posFrom, width);
    }
}
cv::Mat decode(const unsigned char* rawEncodedData, int rawEncodedDataLength) {
    SBufferInfo sDstBufInfo;
    memset(&sDstBufInfo, 0, sizeof(SBufferInfo));
    unsigned char *pData[3] = {nullptr, nullptr, nullptr};
    int rv = decoder->DecodeFrameNoDelay(
        rawEncodedData,
        rawEncodedDataLength,
        pData,
        &sDstBufInfo
    );
    int stride0 = sDstBufInfo.UsrData.sSystemBuffer.iStride[0];
    int stride1 = sDstBufInfo.UsrData.sSystemBuffer.iStride[1];
    
    cv::Mat imageYuvCh[3];
    cv::Mat imageYuvMiniCh[3];
    copyWithStride(imageYuvCh[0].data, pData[0], width, height, stride0);
    copyWithStride(imageYuvMiniCh[1].data, pData[1], width/2, height/2, stride1);
    copyWithStride(imageYuvMiniCh[2].data, pData[2], width/2, height/2, stride1);
    
    cv::resize(imageYuvMiniCh[1], imageYuvCh[1], cv::Size(width, height));
    cv::resize(imageYuvMiniCh[2], imageYuvCh[2], cv::Size(width, height));
    
    cv::Mat resultYuv;
    cv::merge(imageYuvCh, 3, resultYuv);
    
    cv::Mat result;
    cvtColor(imgYUV, result, cv::COLOR_YUV2BGR);
    return result;
}