Невозможно контролировать скорость воспроизведения с OpenH264 - PullRequest
0 голосов
/ 05 мая 2020

Я пытаюсь записать кадры экрана в файл, используя 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
   ...
}

Есть идеи, что не так?

...