这几天在研究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;
}