2

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

将 git 链接到 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: %d\n", err, name, bufferInfo.iBufferStatus);

    return true;
}

任何帮助表示赞赏。

谢谢和最好的问候。

4

1 回答 1

0

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;
}
于 2021-09-03T09:33:11.403 回答