Я пытаюсь записать кадры экрана в файл, используя OpenH264 на Windows, используя DLL, которую я могу загрузить с Cisco. Я хочу кодировать кадры только при смене экрана, поэтому решил, что должен использовать RC_TIMESTAMP_MODE. Я могу кодировать кадры и записывать их в файл .264, который можно воспроизводить, например, с помощью VL C Player, НО проблема в том, что кадры воспроизводятся со скоростью 25 кадров в секунду, независимо от того, как я настраиваю параметры.
Код выглядит примерно так (захват экрана каждые 100 мс):
int FillSpecificParametersBasic(SEncParamBase& sParam)
{
/* Test for temporal, spatial, SNR scalability */
sParam.iUsageType = SCREEN_CONTENT_REAL_TIME;
sParam.iPicWidth = 0; // width of picture in samples
sParam.iPicHeight = 0; // height of picture in samples
sParam.fMaxFrameRate = 20.0f; // input frame rate
sParam.iTargetBitrate = 2000000; // target bitrate bs desired
sParam.iRCMode = RC_TIMESTAMP_MODE;//RC_BUFFERBASED_MODE;// RC_QUALITY_MODE; // rc mode control
return 0;
}
int ProcessEncodingBasic(ISVCEncoder* pPtrEnc) {
int iRet = 0;
if (pPtrEnc == NULL)
return 1;
...
SFilesSet fs;
memset(&sFbi, 0, sizeof(SFrameBSInfo));
FillSpecificParametersBasic(sSvcParam);
pSrcPic = new SSourcePicture;
if (pSrcPic == NULL) {
iRet = 1;
goto INSIDE_MEM_FREE;
}
//fill default pSrcPic
pSrcPic->iColorFormat = videoFormatI420;
pSrcPic->uiTimeStamp = 0;
fs.strBsFile.assign("Recording.264"); // Save recording to this file
pSrcPic->iPicWidth = PIC_WIDTH; //source width
pSrcPic->iPicHeight = PIC_HEIGHT; //source height
pPtrEnc->SetOption(ENCODER_OPTION_TRACE_LEVEL, &g_LevelSetting);
iSourceWidth = pSrcPic->iPicWidth;
iSourceHeight = pSrcPic->iPicHeight;
kiPicResSize = iSourceWidth * iSourceHeight * 3 >> 1;
pYUV = new uint8_t[kiPicResSize]; // Captured screen data
if (pYUV == NULL) {
iRet = 1;
goto INSIDE_MEM_FREE;
}
//update pSrcPic
pSrcPic->iStride[0] = iSourceWidth;
pSrcPic->iStride[1] = pSrcPic->iStride[2] = pSrcPic->iStride[0] >> 1;
pSrcPic->pData[0] = pYUV;
pSrcPic->pData[1] = pSrcPic->pData[0] + (iSourceWidth * iSourceHeight);
pSrcPic->pData[2] = pSrcPic->pData[1] + (iSourceWidth * iSourceHeight >> 2);
//if target output resolution is not set, use the source size
sSvcParam.iPicWidth = (!sSvcParam.iPicWidth) ? iSourceWidth : sSvcParam.iPicWidth;
sSvcParam.iPicHeight = (!sSvcParam.iPicHeight) ? iSourceHeight : sSvcParam.iPicHeight;
int res = pPtrEnc->Initialize(&sSvcParam);
if (cmResultSuccess != res) { // SVC encoder initialization
fprintf(stderr, "SVC encoder Initialize failed\n");
iRet = 1;
goto INSIDE_MEM_FREE;
}
while (true) {
//Update buffer pYUV with screen data
if (!CaptureScreen(pYUV, kiPicResSize))
break;
// Encode this frame
iStart = WelsTime();
if (timeStampStart == 0) {
timeStampStart = WelsTime();
pSrcPic->uiTimeStamp = 0;
}
else
pSrcPic->uiTimeStamp = WELS_ROUND((WelsTime() - timeStampStart)/1000);
int rcEncFrame = pPtrEnc->EncodeFrame(pSrcPic, &sFbi);
iTotal += WelsTime() - iStart;
++iFrameIdx;
if (videoFrameTypeSkip == sFbi.eFrameType) {
continue;
}
if (rcEncFrame == cmResultSuccess) {
int iLayer = 0;
int iFrameSize = 0;
while (iLayer < sFbi.iLayerNum) {
SLayerBSInfo* pLayerBsInfo = &sFbi.sLayerInfo[iLayer];
if (pLayerBsInfo != NULL) {
int iLayerSize = 0;
int iNalIdx = pLayerBsInfo->iNalCount - 1;
do {
iLayerSize += pLayerBsInfo->pNalLengthInByte[iNalIdx];
--iNalIdx;
} while (iNalIdx >= 0);
fwrite(pLayerBsInfo->pBsBuf, 1, iLayerSize, pFpBs); // Write pure bit stream into file
iFrameSize += iLayerSize;
}
++iLayer;
}
++iActualFrameEncodedCount; // excluding skipped frame time
}
else {
fprintf(stderr, "EncodeFrame(), ret: %d, frame index: %d.\n", rcEncFrame, iFrameIdx);
}
Sleep(100);
}
// Clean up
...
}
Есть идеи, что не так?