obs-qsv11硬编h264源码解析(一)

这几天在研究intel media sdk的硬编功能,在obs里面正好有这个模块,这里将硬编原理进行研究一下,硬编内容主要在这两个文件里,QSV_Encoder.cpp和QSV_Encoder_Internal.cpp
先研究QSV_Encoder.cpp文件

1、获取编码器版本号

mfxIMPL              impl = MFX_IMPL_HARDWARE_ANY;
mfxVersion           ver = {{0, 1}}; // for backward compatibility
std::atomic<bool>    is_active{false};

void qsv_encoder_version(unsigned short *major, unsigned short *minor)
{
    *major = ver.Major;
    *minor = ver.Minor;
}

2、根据传入的参数打开编码器

qsv_t *qsv_encoder_open(qsv_param_t *pParams)
{
    bool false_value = false;
    if (!is_active.compare_exchange_strong(false_value, true)) {
        do_log(LOG_ERROR, "Cannot have more than one encoder "
                "active at a time");
        return NULL;
    }

    QSV_Encoder_Internal *pEncoder = new QSV_Encoder_Internal(impl, ver);
    mfxStatus sts = pEncoder->Open(pParams);
    if (sts != MFX_ERR_NONE) {
        delete pEncoder;
        if (pEncoder)
            is_active.store(false);
        return NULL;
    }

    return (qsv_t *) pEncoder;
}

3、得到编码器的关键帧SPS、PPS

int qsv_encoder_headers(qsv_t *pContext, uint8_t **pSPS, uint8_t **pPPS,
        uint16_t *pnSPS, uint16_t *pnPPS)
{
    QSV_Encoder_Internal *pEncoder = (QSV_Encoder_Internal *)pContext;
    pEncoder->GetSPSPPS(pSPS, pPPS, pnSPS, pnPPS);

    return 0;
}

4、传入帧数据进行编码

int qsv_encoder_encode(qsv_t * pContext, uint64_t ts, uint8_t *pDataY,
        uint8_t *pDataUV, uint32_t strideY, uint32_t strideUV,
        mfxBitstream **pBS)
{
    QSV_Encoder_Internal *pEncoder = (QSV_Encoder_Internal *)pContext;
    mfxStatus sts = MFX_ERR_NONE;

    if (pDataY != NULL && pDataUV != NULL)
        sts = pEncoder->Encode(ts, pDataY, pDataUV, strideY, strideUV,
                pBS);

    if (sts == MFX_ERR_NONE)
        return 0;
    else if (sts == MFX_ERR_MORE_DATA)
        return 1;
    else
        return -1;
}

5、关闭编码器

int qsv_encoder_close(qsv_t *pContext)
{
    QSV_Encoder_Internal *pEncoder = (QSV_Encoder_Internal *)pContext;
    delete pEncoder;

    if (pEncoder)
        is_active.store(false);

    return 0;
}

6、编码器重置,即根据新传入的参数结构体重新打开编码器

int qsv_encoder_reconfig(qsv_t *pContext, qsv_param_t *pParams)
{
    QSV_Encoder_Internal *pEncoder = (QSV_Encoder_Internal *)pContext;
    mfxStatus sts = pEncoder->Reset(pParams);

    if (sts == MFX_ERR_NONE)
        return 0;
    else
        return -1;
}

7、获取cpu的平台

enum qsv_cpu_platform qsv_get_cpu_platform()
{
    using std::string;

    int cpuInfo[4];
    __cpuid(cpuInfo, 0);

    string vendor;
    vendor += string((char*)&cpuInfo[1], 4);
    vendor += string((char*)&cpuInfo[3], 4);
    vendor += string((char*)&cpuInfo[2], 4);

    if (vendor != "GenuineIntel")
        return QSV_CPU_PLATFORM_UNKNOWN;

    __cpuid(cpuInfo, 1);
    BYTE model = ((cpuInfo[0] >> 4) & 0xF) + ((cpuInfo[0] >> 12) & 0xF0);
    BYTE family = ((cpuInfo[0] >> 8) & 0xF) + ((cpuInfo[0] >> 20) & 0xFF);

    // See Intel 64 and IA-32 Architectures Software Developer's Manual,
    // Vol 3C Table 35-1
    if (family != 6)
        return QSV_CPU_PLATFORM_UNKNOWN;

    switch (model)
    {
    case 0x1C:
    case 0x26:
    case 0x27:
    case 0x35:
    case 0x36:
        return QSV_CPU_PLATFORM_BNL;

    case 0x2a:
    case 0x2d:
        return QSV_CPU_PLATFORM_SNB;

    case 0x3a:
    case 0x3e:
        return QSV_CPU_PLATFORM_IVB;

    case 0x37:
    case 0x4A:
    case 0x4D:
    case 0x5A:
    case 0x5D:
        return QSV_CPU_PLATFORM_SLM;

    case 0x4C:
        return QSV_CPU_PLATFORM_CHT;

    case 0x3c:
    case 0x3f:
    case 0x45:
    case 0x46:
        return QSV_CPU_PLATFORM_HSW;
    }

    //assume newer revisions are at least as capable as Haswell
    return QSV_CPU_PLATFORM_INTEL;
}

猜你喜欢

转载自blog.csdn.net/tong5956/article/details/81670336