更新时间:2021-03-18 GMT+08:00
分享

实现VENC功能

若需要将多张图片编码成一个视频,则调用一次CreateVenc接口创建实例后,必须使用同一个实例调用RunVenc接口进行视频编码,最后再调用一次DestroyVenc接口释放实例。

本调用示例是调用VENC接口将yuv图片编码成h265或者h264格式的码流。

std::string vencOutFileName("venc.bin");
std::shared_ptr<FILE> vencOutFile(nullptr);
void VencCallBackDumpFile(struct VencOutMsg* vencOutMsg, void* userData)
{
    if (vencOutFile.get() == nullptr) {
        HIAI_ENGINE_LOG(HIAI_VENC_CTL_ERROR, "get venc out file fail!");
        return;
    }
    fwrite(vencOutMsg->outputData, 1, vencOutMsg->outputDataSize, vencOutFile.get());
    fflush(vencOutFile.get());
}

/*
 * venc new interface to achieve venc basic functions.
 */
void TEST_VENC()
{
    std::shared_ptr<FILE> fpIn(fopen(g_inFileName, "rb"), fclose);
    vencOutFile.reset(fopen(vencOutFileName.c_str(), "wb"), fclose);

    if (fpIn.get() == nullptr || vencOutFile.get() == nullptr) {
        HIAI_ENGINE_LOG(HIAI_OPEN_FILE_ERROR, "open open venc in/out file failed.");
        return;
    }

    fseek(fpIn.get(), 0, SEEK_END);
    uint32_t fileLen = ftell(fpIn.get());
    fseek(fpIn.get(), 0, SEEK_SET);

    struct VencConfig vencConfig;
    vencConfig.width = g_width;
    vencConfig.height = g_high;
    vencConfig.codingType = g_format;
    vencConfig.yuvStoreType = g_yuvStoreType;
    vencConfig.keyFrameInterval = 16;
    vencConfig.vencOutMsgCallBack = VencCallBackDumpFile;
    vencConfig.userData = nullptr;

    int32_t vencHandle = CreateVenc(&vencConfig);
    if (vencHandle == -1) {
        HIAI_ENGINE_LOG(HIAI_VENC_CTL_ERROR, "CreateVenc fail!");
        return;
    }

    // input 16 frames once
    uint32_t inDataLenMaxOnce = g_width * g_high * 3 / 2;
    std::shared_ptr<char> inBuffer(static_cast<char*>(malloc(inDataLenMaxOnce)), free);

    if (inBuffer.get() == nullptr) {
        HIAI_ENGINE_LOG(HIAI_OPEN_FILE_ERROR, "alloc input buffer failed");
        DestroyVenc(vencHandle);
        return;
    }

    uint32_t inDataUnhandledLen = fileLen;

    auto start = std::chrono::system_clock::now();
    uint32_t frameCount = 0;

    while (inDataUnhandledLen > 0) {
        uint32_t inDataLen     = inDataUnhandledLen;
        if (inDataUnhandledLen > inDataLenMaxOnce) {
            inDataLen          = inDataLenMaxOnce;
        }
        inDataUnhandledLen    -= inDataLen;
        uint32_t readLen       = fread(inBuffer.get(), 1, inDataLen, fpIn.get());
        if (readLen != inDataLen) {
            HIAI_ENGINE_LOG(HIAI_OPEN_FILE_ERROR, "error in read input file");
            DestroyVenc(vencHandle);
            return;
        }

        struct VencInMsg vencInMsg;
        vencInMsg.inputData = inBuffer.get();
        vencInMsg.inputDataSize = inDataLen;
        vencInMsg.keyFrameInterval = 16;
        vencInMsg.forceIFrame = 0;
        vencInMsg.eos = 0;

        if (RunVenc(vencHandle, &vencInMsg) == -1) {
            HIAI_ENGINE_LOG(HIAI_VENC_CTL_ERROR, "call video encode fail");
            break;
        }
        ++frameCount;
    }

    auto end = std::chrono::system_clock::now();
    auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
    size_t timeCount = static_cast<size_t>(duration.count());
    HIAI_ENGINE_LOG("Total frame count: %u", frameCount);
    HIAI_ENGINE_LOG("Time cost: %lu us", timeCount);
    HIAI_ENGINE_LOG("FPS: %lf", frameCount * 1.0 / (timeCount / 1000000.0));

    DestroyVenc(vencHandle);
    return;
}
分享:

    相关文档

    相关产品