Changeset 75441 in vbox
- Timestamp:
- Nov 14, 2018 9:08:51 AM (6 years ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/include/Recording.h
r75361 r75441 118 118 * Per VM screen (display) one recording stream is being used. */ 119 119 RecordingStreams vecStreams; 120 /** Number of streams in vecStreams which currently are enabled for recording. */ 121 uint16_t cStreamsEnabled; 120 122 /** Timestamp (in ms) of when recording has been started. */ 121 123 uint64_t tsStartMs; -
trunk/src/VBox/Main/include/RecordingInternals.h
r75354 r75441 19 19 #define ____H_RECORDING_INTERNALS 20 20 21 #include <iprt/assert.h> 21 22 #include <iprt/types.h> /* drag in stdint.h before vpx does it. */ 22 23 #include <list> … … 115 116 } RECORDINGBLOCKTYPE; 116 117 118 #ifdef VBOX_WITH_AUDIO_RECORDING 119 void RecordingAudioFrameFree(PRECORDINGAUDIOFRAME pFrame); 120 #endif 121 void RecordingVideoFrameFree(PRECORDINGVIDEOFRAME pFrame); 122 117 123 /** 118 124 * Generic structure for keeping a single video recording (data) block. 119 125 */ 120 typedef struct RECORDINGBLOCK 126 struct RecordingBlock 121 127 { 128 RecordingBlock() 129 : enmType(RECORDINGBLOCKTYPE_UNKNOWN) 130 , cRefs(0) 131 , pvData(NULL) 132 , cbData(0) { } 133 134 virtual ~RecordingBlock() 135 { 136 Reset(); 137 } 138 139 void Reset(void) 140 { 141 switch (enmType) 142 { 143 case RECORDINGBLOCKTYPE_UNKNOWN: 144 break; 145 146 case RECORDINGBLOCKTYPE_VIDEO: 147 RecordingVideoFrameFree((PRECORDINGVIDEOFRAME)pvData); 148 break; 149 150 #ifdef VBOX_WITH_AUDIO_RECORDING 151 case RECORDINGBLOCKTYPE_AUDIO: 152 RecordingAudioFrameFree((PRECORDINGAUDIOFRAME)pvData); 153 break; 154 #endif 155 default: 156 AssertFailed(); 157 break; 158 } 159 160 enmType = RECORDINGBLOCKTYPE_UNKNOWN; 161 cRefs = 0; 162 pvData = NULL; 163 cbData = 0; 164 } 165 122 166 /** The block's type. */ 123 167 RECORDINGBLOCKTYPE enmType; … … 130 174 /** Size (in bytes) of the (opaque) data block. */ 131 175 size_t cbData; 132 } RECORDINGBLOCK, *PRECORDINGBLOCK;176 }; 133 177 134 178 /** List for keeping video recording (data) blocks. */ 135 typedef std::list<PRECORDINGBLOCK> RECORDINGBLOCKList; 136 137 void RecordingBlockFree(PRECORDINGBLOCK pBlock); 138 #ifdef VBOX_WITH_AUDIO_RECORDING 139 void RecordingAudioFrameFree(PRECORDINGAUDIOFRAME pFrame); 140 #endif 141 void RecordingVideoFrameFree(PRECORDINGVIDEOFRAME pFrame); 179 typedef std::list<RecordingBlock *> RecordingBlockList; 142 180 143 181 #endif /* ____H_RECORDING_INTERNALS */ -
trunk/src/VBox/Main/include/RecordingStream.h
r75417 r75441 51 51 while (!List.empty()) 52 52 { 53 PRECORDINGBLOCK pBlock = List.front(); 54 RecordingBlockFree(pBlock); 53 RecordingBlock *pBlock = List.front(); 55 54 List.pop_front(); 55 delete pBlock; 56 56 } 57 57 … … 60 60 61 61 /** The actual block list for this timecode. */ 62 R ECORDINGBLOCKList List;62 RecordingBlockList List; 63 63 }; 64 64 … … 125 125 126 126 const settings::RecordingScreenSettings &GetConfig(void) const; 127 uint16_t GetID(void) const { return this->uScreenID; }; 127 128 bool IsLimitReached(uint64_t tsNowMs) const; 128 129 bool IsReady(void) const; … … 167 168 168 169 /** Recording context this stream is associated to. */ 169 RecordingContext 170 RecordingContext *pCtx; 170 171 /** The current state. */ 171 172 RECORDINGSTREAMSTATE enmState; … … 206 207 /** Common set of recording (data) blocks, needed for 207 208 * multiplexing to all recording streams. */ 208 RecordingBlockSet Blocks;209 RecordingBlockSet Blocks; 209 210 }; 210 211 -
trunk/src/VBox/Main/src-client/Recording.cpp
r75392 r75441 92 92 RecordingContext::RecordingContext(Console *a_pConsole) 93 93 : pConsole(a_pConsole) 94 , enmState(RECORDINGSTS_UNINITIALIZED) { } 94 , enmState(RECORDINGSTS_UNINITIALIZED) 95 , cStreamsEnabled(0) { } 95 96 96 97 RecordingContext::RecordingContext(Console *a_pConsole, const settings::RecordingSettings &a_Settings) 97 98 : pConsole(a_pConsole) 98 99 , enmState(RECORDINGSTS_UNINITIALIZED) 100 , cStreamsEnabled(0) 99 101 { 100 102 int rc = RecordingContext::createInternal(a_Settings); … … 139 141 rc = pStream->Process(pThis->mapBlocksCommon); 140 142 if (RT_FAILURE(rc)) 143 { 144 LogRel(("Recording: Processing stream #%RU16 failed (%Rrc)\n", pStream->GetID(), rc)); 141 145 break; 146 } 142 147 143 148 ++itStream; … … 191 196 pStream = new RecordingStream(this, itScreen->first /* Screen ID */, itScreen->second); 192 197 this->vecStreams.push_back(pStream); 198 if (itScreen->second.fEnabled) 199 this->cStreamsEnabled++; 193 200 } 194 201 catch (std::bad_alloc &) … … 533 540 * audio data at the same given point in time. 534 541 */ 535 PRECORDINGBLOCK pBlock = (PRECORDINGBLOCK)RTMemAlloc(sizeof(RECORDINGBLOCK)); 536 AssertPtrReturn(pBlock, VERR_NO_MEMORY); 542 RecordingBlock *pBlock = new RecordingBlock(); 537 543 pBlock->enmType = RECORDINGBLOCKTYPE_AUDIO; 538 544 … … 548 554 pBlock->pvData = pFrame; 549 555 pBlock->cbData = sizeof(RECORDINGAUDIOFRAME) + cbData; 550 pBlock->cRefs = (uint16_t)this->vecStreams.size(); /* All streams need the same audio data. */556 pBlock->cRefs = this->cStreamsEnabled; 551 557 pBlock->uTimeStampMs = uTimeStampMs; 552 558 -
trunk/src/VBox/Main/src-client/RecordingInternals.cpp
r75356 r75441 61 61 } 62 62 63 /**64 * Frees a recording (data) block.65 *66 * @returns IPRT status code.67 * @param pBlock Recording (data) block to free. The pointer will be invalid after return.68 */69 void RecordingBlockFree(PRECORDINGBLOCK pBlock)70 {71 if (!pBlock)72 return;73 74 switch (pBlock->enmType)75 {76 case RECORDINGBLOCKTYPE_VIDEO:77 RecordingVideoFrameFree((PRECORDINGVIDEOFRAME)pBlock->pvData);78 break;79 80 #ifdef VBOX_WITH_AUDIO_RECORDING81 case RECORDINGBLOCKTYPE_AUDIO:82 RecordingAudioFrameFree((PRECORDINGAUDIOFRAME)pBlock->pvData);83 break;84 #endif85 default:86 AssertFailed();87 break;88 }89 90 RTMemFree(pBlock);91 pBlock = NULL;92 }93 -
trunk/src/VBox/Main/src-client/RecordingStream.cpp
r75417 r75441 276 276 && tsNowMs >= this->tsStartMs + (this->ScreenSettings.ulMaxTimeS * RT_MS_1SEC)) 277 277 { 278 LogRel(("Recording: Time limit for stream #%RU16 has been reached (%RU32s)\n", 279 this->uScreenID, this->ScreenSettings.ulMaxTimeS)); 278 280 return true; 279 281 } … … 281 283 if (this->ScreenSettings.enmDest == RecordingDestination_File) 282 284 { 283 284 285 if (this->ScreenSettings.File.ulMaxSizeMB) 285 286 { 286 287 uint64_t sizeInMB = this->File.pWEBM->GetFileSize() / _1M; 287 288 if(sizeInMB >= this->ScreenSettings.File.ulMaxSizeMB) 289 { 290 LogRel(("Recording: File size limit for stream #%RU16 has been reached (%RU64MB)\n", 291 this->uScreenID, this->ScreenSettings.File.ulMaxSizeMB)); 288 292 return true; 293 } 289 294 } 290 295 … … 293 298 && this->File.pWEBM->GetAvailableSpace() < 0x100000) /** @todo r=andy WTF? Fix this. */ 294 299 { 295 LogRel(("Recording: Not enough free storage space available, stopping video capture\n"));300 LogRel(("Recording: Not enough free storage space available, stopping recording\n")); 296 301 return true; 297 302 } … … 321 326 int RecordingStream::Process(RecordingBlockMap &mapBlocksCommon) 322 327 { 328 LogFlowFuncEnter(); 329 323 330 lock(); 324 331 … … 341 348 while (!pBlocks->List.empty()) 342 349 { 343 PRECORDINGBLOCKpBlock = pBlocks->List.front();350 RecordingBlock *pBlock = pBlocks->List.front(); 344 351 AssertPtr(pBlock); 345 352 … … 349 356 PRECORDINGVIDEOFRAME pVideoFrame = (PRECORDINGVIDEOFRAME)pBlock->pvData; 350 357 351 rc= RecordingUtilsRGBToYUV(pVideoFrame->uPixelFormat,352 /* Destination */353 this->Video.Codec.VPX.pu8YuvBuf, pVideoFrame->uWidth, pVideoFrame->uHeight,354 /* Source */355 pVideoFrame->pu8RGBBuf, this->ScreenSettings.Video.ulWidth, this->ScreenSettings.Video.ulHeight);356 if (RT_SUCCESS(rc ))358 int rc2 = RecordingUtilsRGBToYUV(pVideoFrame->uPixelFormat, 359 /* Destination */ 360 this->Video.Codec.VPX.pu8YuvBuf, pVideoFrame->uWidth, pVideoFrame->uHeight, 361 /* Source */ 362 pVideoFrame->pu8RGBBuf, this->ScreenSettings.Video.ulWidth, this->ScreenSettings.Video.ulHeight); 363 if (RT_SUCCESS(rc2)) 357 364 { 358 rc = writeVideoVPX(uTimeStampMs, pVideoFrame); 365 rc2 = writeVideoVPX(uTimeStampMs, pVideoFrame); 366 AssertRC(rc2); 367 if (RT_SUCCESS(rc)) 368 rc = rc2; 359 369 } 360 else 361 break; 362 } 363 #endif 364 RecordingBlockFree(pBlock); 365 pBlock = NULL; 366 370 } 371 #endif 367 372 pBlocks->List.pop_front(); 368 } 369 370 ++itStreamBlocks; 373 delete pBlock; 374 } 375 376 Blocks.Map.erase(itStreamBlocks); 377 itStreamBlocks = Blocks.Map.begin(); 371 378 } 372 379 … … 379 386 while (itCommonBlocks != mapBlocksCommon.end()) 380 387 { 381 R ECORDINGBLOCKList::iterator itBlock = itCommonBlocks->second->List.begin();388 RecordingBlockList::iterator itBlock = itCommonBlocks->second->List.begin(); 382 389 while (itBlock != itCommonBlocks->second->List.end()) 383 390 { 384 PRECORDINGBLOCK pBlockCommon = (PRECORDINGBLOCK)(*itBlock);391 RecordingBlock *pBlockCommon = (RecordingBlock *)(*itBlock); 385 392 switch (pBlockCommon->enmType) 386 393 { … … 395 402 pBlockCommon->uTimeStampMs }; 396 403 AssertPtr(this->File.pWEBM); 397 rc = this->File.pWEBM->WriteBlock(this->uTrackAudio, &blockData, sizeof(blockData)); 404 int rc2 = this->File.pWEBM->WriteBlock(this->uTrackAudio, &blockData, sizeof(blockData)); 405 AssertRC(rc2); 406 if (RT_SUCCESS(rc)) 407 rc = rc2; 398 408 break; 399 409 } … … 404 414 } 405 415 406 if (RT_FAILURE(rc))407 break;408 409 416 Assert(pBlockCommon->cRefs); 410 417 pBlockCommon->cRefs--; 411 418 if (pBlockCommon->cRefs == 0) 412 419 { 413 RecordingBlockFree(pBlockCommon);414 420 itCommonBlocks->second->List.erase(itBlock); 421 delete pBlockCommon; 415 422 itBlock = itCommonBlocks->second->List.begin(); 416 423 } … … 430 437 431 438 LogFunc(("Common blocks: %zu\n", mapBlocksCommon.size())); 432 433 if (RT_FAILURE(rc))434 break;435 439 } 436 440 #endif … … 438 442 unlock(); 439 443 444 LogFlowFuncLeaveRC(rc); 440 445 return rc; 441 446 } … … 637 642 if (rc == VINF_SUCCESS) /* Note: Also could be VINF_TRY_AGAIN. */ 638 643 { 639 PRECORDINGBLOCK pBlock = (PRECORDINGBLOCK)RTMemAlloc(sizeof(RECORDINGBLOCK));644 RecordingBlock *pBlock = new RecordingBlock(); 640 645 if (pBlock) 641 646 { … … 680 685 * @param a_pCtx Pointer to recording context. 681 686 * @param uScreen Screen number to use for this recording stream. 682 * @param Settings Capturingconfiguration to use for initialization.687 * @param Settings Recording screen configuration to use for initialization. 683 688 */ 684 689 int RecordingStream::Init(RecordingContext *a_pCtx, uint32_t uScreen, const settings::RecordingScreenSettings &Settings) … … 693 698 * @param a_pCtx Pointer to recording context. 694 699 * @param uScreen Screen number to use for this recording stream. 695 * @param Settings Capturingconfiguration to use for initialization.700 * @param Settings Recording screen configuration to use for initialization. 696 701 */ 697 702 int RecordingStream::initInternal(RecordingContext *a_pCtx, uint32_t uScreen, const settings::RecordingScreenSettings &Settings) … … 701 706 this->ScreenSettings = Settings; 702 707 703 int rc = parseOptionsString( Settings.strOptions);708 int rc = parseOptionsString(this->ScreenSettings.strOptions); 704 709 if (RT_FAILURE(rc)) 705 710 return rc; 711 712 const settings::RecordingScreenSettings *pSettings = &this->ScreenSettings; 706 713 707 714 rc = RTCritSectInit(&this->CritSect); … … 709 716 return rc; 710 717 711 rc = open( Settings);718 rc = open(this->ScreenSettings); 712 719 if (RT_FAILURE(rc)) 713 720 return rc; 714 721 715 const bool fVideoEnabled = Settings.isFeatureEnabled(RecordingFeature_Video);716 const bool fAudioEnabled = Settings.isFeatureEnabled(RecordingFeature_Audio);722 const bool fVideoEnabled = pSettings->isFeatureEnabled(RecordingFeature_Video); 723 const bool fAudioEnabled = pSettings->isFeatureEnabled(RecordingFeature_Audio); 717 724 718 725 if (fVideoEnabled) … … 734 741 case RecordingDestination_File: 735 742 { 736 Assert( this->ScreenSettings.File.strName.isNotEmpty());737 const char *pszFile = this->ScreenSettings.File.strName.c_str();743 Assert(pSettings->File.strName.isNotEmpty()); 744 const char *pszFile = pSettings->File.strName.c_str(); 738 745 739 746 AssertPtr(File.pWEBM); 740 747 rc = File.pWEBM->OpenEx(pszFile, &this->File.hFile, 741 748 #ifdef VBOX_WITH_AUDIO_RECORDING 742 Settings.isFeatureEnabled(RecordingFeature_Audio) 743 ? WebMWriter::AudioCodec_Opus : WebMWriter::AudioCodec_None, 749 fAudioEnabled ? WebMWriter::AudioCodec_Opus : WebMWriter::AudioCodec_None, 744 750 #else 745 WebMWriter::AudioCodec_None, 746 #endif 747 Settings.isFeatureEnabled(RecordingFeature_Video) 748 ? WebMWriter::VideoCodec_VP8 : WebMWriter::VideoCodec_None); 751 WebMWriter::AudioCodec_None, 752 #endif 753 fVideoEnabled ? WebMWriter::VideoCodec_VP8 : WebMWriter::VideoCodec_None); 749 754 if (RT_FAILURE(rc)) 750 755 { … … 755 760 if (fVideoEnabled) 756 761 { 757 rc = this->File.pWEBM->AddVideoTrack( Settings.Video.ulWidth, Settings.Video.ulHeight,758 Settings.Video.ulFPS,&this->uTrackVideo);762 rc = this->File.pWEBM->AddVideoTrack(pSettings->Video.ulWidth, pSettings->Video.ulHeight, pSettings->Video.ulFPS, 763 &this->uTrackVideo); 759 764 if (RT_FAILURE(rc)) 760 765 { … … 764 769 765 770 LogRel(("Recording: Recording video of screen #%u with %RU32x%RU32 @ %RU32 kbps, %RU32 FPS (track #%RU8)\n", 766 this->uScreenID, Settings.Video.ulWidth, Settings.Video.ulHeight, Settings.Video.ulRate,767 Settings.Video.ulFPS, this->uTrackVideo));771 this->uScreenID, pSettings->Video.ulWidth, pSettings->Video.ulHeight, 772 pSettings->Video.ulRate, pSettings->Video.ulFPS, this->uTrackVideo)); 768 773 } 769 774 … … 771 776 if (fAudioEnabled) 772 777 { 773 rc = this->File.pWEBM->AddAudioTrack( Settings.Audio.uHz, Settings.Audio.cChannels, Settings.Audio.cBits,778 rc = this->File.pWEBM->AddAudioTrack(pSettings->Audio.uHz, pSettings->Audio.cChannels, pSettings->Audio.cBits, 774 779 &this->uTrackAudio); 775 780 if (RT_FAILURE(rc)) … … 780 785 781 786 LogRel(("Recording: Recording audio of screen #%u in %RU16Hz, %RU8 bit, %RU8 %s (track #%RU8)\n", 782 this->uScreenID, Settings.Audio.uHz, Settings.Audio.cBits, Settings.Audio.cChannels,783 Settings.Audio.cChannels ? "channels" : "channel", this->uTrackAudio));787 this->uScreenID, pSettings->Audio.uHz, pSettings->Audio.cBits, pSettings->Audio.cChannels, 788 pSettings->Audio.cChannels ? "channels" : "channel", this->uTrackAudio)); 784 789 } 785 790 #endif … … 990 995 991 996 this->Video.cFailedEncodingFrames = 0; 992 this->Video.uDelayMs = RT_MS_1SEC / this->ScreenSettings.Video.ulFPS; 997 this->Video.uLastTimeStampMs = 0; 998 this->Video.uDelayMs = RT_MS_1SEC / this->ScreenSettings.Video.ulFPS; 993 999 994 1000 int rc; … … 998 1004 rc = initVideoVPX(); 999 1005 #else 1000 rc = V INF_SUCCESS;1006 rc = VERR_NOT_SUPPORTED; 1001 1007 #endif 1002 1008 -
trunk/src/VBox/Main/src-server/RecordingScreenSettingsImpl.cpp
r75418 r75441 810 810 Assert(m); 811 811 812 int rc = VINF_SUCCESS; 812 int rc = i_parseOptionsString(m->bd->strOptions, *m->bd.data()); 813 if (RT_FAILURE(rc)) 814 return rc; 813 815 814 816 switch (m->bd->enmDest)
Note:
See TracChangeset
for help on using the changeset viewer.