Changeset 96260 in vbox
- Timestamp:
- Aug 17, 2022 12:02:46 PM (3 years ago)
- svn:sync-xref-src-repo-rev:
- 153072
- Location:
- trunk/src/VBox/Main
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/include/Recording.h
r96229 r96260 83 83 RecordingStream *getStreamInternal(unsigned uScreen) const; 84 84 85 int writeCommonData(PRECORDINGCODEC pCodec, const void *pvData, size_t cbData, uint64_t msAbsPTS, uint32_t uFlags); 85 int processCommonData(RecordingBlockMap &mapCommon, RTMSINTERVAL msTimeout); 86 int writeCommonData(RecordingBlockMap &mapCommon, PRECORDINGCODEC pCodec, const void *pvData, size_t cbData, uint64_t msAbsPTS, uint32_t uFlags); 86 87 87 88 int lock(void); … … 145 146 RECORDINGCODEC CodecAudio; 146 147 #endif /* VBOX_WITH_AUDIO_RECORDING */ 147 /** Block map of common blocks which need to get multiplexed 148 * to all recording streams. This common block maps should help 149 * reducing the time spent in EMT and avoid doing the (expensive) 150 * multiplexing work in there. 148 /** Block map of raw common data blocks which need to get encoded first. */ 149 RecordingBlockMap mapBlocksRaw; 150 /** Block map of encoded common blocks. 151 * 152 * Only do the encoding of common data blocks only once and then multiplex 153 * the encoded data to all affected recording streams. 154 * 155 * This avoids doing the (expensive) encoding + multiplexing work in other 156 * threads like EMT / audio async I/O.. 151 157 * 152 158 * For now this only affects audio, e.g. all recording streams 153 159 * need to have the same audio data at a specific point in time. */ 154 RecordingBlockMap mapBlocks Common;160 RecordingBlockMap mapBlocksEncoded; 155 161 }; 156 162 #endif /* !MAIN_INCLUDED_Recording_h */ -
trunk/src/VBox/Main/include/RecordingStream.h
r96229 r96260 120 120 121 121 int Process(RecordingBlockMap &mapBlocksCommon); 122 int SendAudioFrame(const void *pvData, size_t cbData, uint64_t msTimestamp); 122 123 int SendVideoFrame(uint32_t x, uint32_t y, uint32_t uPixelFormat, uint32_t uBPP, uint32_t uBytesPerLine, 123 124 uint32_t uSrcWidth, uint32_t uSrcHeight, uint8_t *puSrcData, uint64_t msTimestamp); -
trunk/src/VBox/Main/src-client/DrvAudioRec.cpp
r96229 r96260 171 171 typedef struct AVRECSINK 172 172 { 173 /** Pointer (weak) to audio codec to use. */174 PRECORDINGCODEC pCodec;173 /** Pointer (weak) to recording stream to bind to. */ 174 RecordingStream *pRecStream; 175 175 /** Container data to use for data processing. */ 176 176 AVRECCONTAINER Con; … … 323 323 */ 324 324 static int avRecCreateStreamOut(PDRVAUDIORECORDING pThis, PAVRECSTREAM pStreamAV, 325 PAVRECSINK pSink, P RECORDINGCODEC pCodec, PCPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq)325 PAVRECSINK pSink, PCPDMAUDIOSTREAMCFG pCfgReq, PPDMAUDIOSTREAMCFG pCfgAcq) 326 326 { 327 327 AssertPtrReturn(pThis, VERR_INVALID_POINTER); 328 328 AssertPtrReturn(pStreamAV, VERR_INVALID_POINTER); 329 329 AssertPtrReturn(pSink, VERR_INVALID_POINTER); 330 AssertPtrReturn(pCodec, VERR_INVALID_POINTER);331 330 AssertPtrReturn(pCfgReq, VERR_INVALID_POINTER); 332 331 AssertPtrReturn(pCfgAcq, VERR_INVALID_POINTER); … … 338 337 return VERR_NOT_SUPPORTED; 339 338 } 339 340 PRECORDINGCODEC pCodec = pSink->pRecStream->GetAudioCodec(); 340 341 341 342 /* Stuff which has to be set by now. */ … … 357 358 /* Make sure to let the driver backend know that we need the audio data in 358 359 * a specific sampling rate the codec is optimized for. */ 359 /** @todo r=bird: pCfgAcq->Props isn't initialized at all, except for uHz... */ 360 pCfgAcq->Props.uHz = pCodec->Parms.Audio.PCMProps.uHz; 361 // pCfgAcq->Props.cShift = PDMAUDIOPCMPROPS_MAKE_SHIFT_PARMS(pCfgAcq->Props.cbSample, pCfgAcq->Props.cChannels); 362 363 /* Every Opus frame marks a period for now. Optimize this later. */ 360 pCfgAcq->Props = pCodec->Parms.Audio.PCMProps; 361 362 /* Every codec frame marks a period for now. Optimize this later. */ 364 363 pCfgAcq->Backend.cFramesPeriod = PDMAudioPropsMilliToFrames(&pCfgAcq->Props, pCodec->Parms.msFrame); 365 pCfgAcq->Backend.cFramesBufferSize = PDMAudioPropsMilliToFrames(&pCfgAcq->Props, 100 /*ms*/); /** @todo Make this configurable. */366 pCfgAcq->Backend.cFramesPreBuffering = pCfgAcq->Backend.cFramesPeriod * 2;364 pCfgAcq->Backend.cFramesBufferSize = pCfgAcq->Backend.cFramesPeriod * 2; 365 pCfgAcq->Backend.cFramesPreBuffering = pCfgAcq->Backend.cFramesPeriod; 367 366 } 368 367 else … … 394 393 PAVRECSINK pSink = &pThis->Sink; 395 394 396 int vrc = avRecCreateStreamOut(pThis, pStreamAV, pSink, p Sink->pCodec, pCfgReq, pCfgAcq);395 int vrc = avRecCreateStreamOut(pThis, pStreamAV, pSink, pCfgReq, pCfgAcq); 397 396 PDMAudioStrmCfgCopy(&pStreamAV->Cfg, pCfgAcq); 398 397 … … 516 515 static DECLCALLBACK(uint32_t) drvAudioVideoRecHA_StreamGetWritable(PPDMIHOSTAUDIO pInterface, PPDMAUDIOBACKENDSTREAM pStream) 517 516 { 518 RT_NOREF(pInterface, pStream); 519 return UINT32_MAX; 517 RT_NOREF(pInterface); 518 PAVRECSTREAM pStreamAV = (PAVRECSTREAM)pStream; 519 520 RecordingStream *pRecStream = pStreamAV->pSink->pRecStream; 521 PRECORDINGCODEC pCodec = pRecStream->GetAudioCodec(); 522 523 return pCodec->Parms.cbFrame; 520 524 } 521 525 … … 540 544 PAVRECSINK pSink = pStreamAV->pSink; 541 545 AssertPtr(pSink); 542 PRECORDINGCODEC pCodec = pSink->pCodec;543 AssertPtr(pCodec);544 546 PRTCIRCBUF pCircBuf = pStreamAV->pCircBuf; 545 547 AssertPtr(pCircBuf); 546 548 547 uint32_t cbToWrite = cbBuf; 549 uint32_t cbToWrite = RT_MIN(cbBuf, RTCircBufFree(pCircBuf)); 550 AssertReturn(cbToWrite, VERR_BUFFER_OVERFLOW); 548 551 549 552 /* 550 553 * Write as much as we can into our internal ring buffer. 551 554 */ 552 while ( cbToWrite > 0 553 && RTCircBufFree(pCircBuf)) 555 while (cbToWrite) 554 556 { 555 557 void *pvCircBuf = NULL; … … 557 559 RTCircBufAcquireWriteBlock(pCircBuf, cbToWrite, &pvCircBuf, &cbCircBuf); 558 560 559 if (cbCircBuf)560 { 561 562 563 Assert(cbToWrite >= cbCircBuf);564 cbToWrite -= (uint32_t)cbCircBuf;565 }561 Log3Func(("cbToWrite=%RU32, cbCircBuf=%zu\n", cbToWrite, cbCircBuf)); 562 563 memcpy(pvCircBuf, (uint8_t *)pvBuf + cbWrittenTotal, cbCircBuf), 564 cbWrittenTotal += (uint32_t)cbCircBuf; 565 Assert(cbWrittenTotal <= cbBuf); 566 Assert(cbToWrite >= cbCircBuf); 567 cbToWrite -= (uint32_t)cbCircBuf; 566 568 567 569 RTCircBufReleaseWriteBlock(pCircBuf, cbCircBuf); 568 AssertBreak(cbCircBuf);569 } 570 571 /*572 * Process our internal ring buffer and encode the data. 573 */574 575 /* Only encode data if we have data for at least one full frame.*/576 while (RTCircBufUsed(pCircBuf) >= pCodec->Parms.cbFrame)577 { 578 LogFunc(("cbAvail=%zu, csFrame=%RU32, cbFrame=%RU32\n",579 RTCircBufUsed(pCircBuf), pCodec->Parms.csFrame, pCodec->Parms.cbFrame));580 581 /** @todo Can we encode more than a frame at a time? Optimize this!*/582 uint32_t const cbFramesToEncode = pCodec->Parms.cbFrame; /* 1 frame. */583 570 } 571 572 RecordingStream *pRecStream = pStreamAV->pSink->pRecStream; 573 PRECORDINGCODEC pCodec = pRecStream->GetAudioCodec(); 574 575 /* 576 * Process our internal ring buffer and send the obtained audio data to our encoding thread. 577 */ 578 cbToWrite = RTCircBufUsed(pCircBuf); 579 580 /** @todo Can we encode more than a frame at a time? Optimize this! */ 581 uint32_t const cbFrame = pCodec->Parms.cbFrame; 582 583 /* Only encode data if we have data for at least one full codec frame. */ 584 while (cbToWrite >= cbFrame) 585 { 584 586 uint32_t cbSrc = 0; 585 while (cbSrc < cbFramesToEncode)587 do 586 588 { 587 589 void *pvCircBuf = NULL; 588 590 size_t cbCircBuf = 0; 589 RTCircBufAcquireReadBlock(pCircBuf, cbFramesToEncode - cbSrc, &pvCircBuf, &cbCircBuf); 590 591 if (cbCircBuf) 591 RTCircBufAcquireReadBlock(pCircBuf, cbFrame - cbSrc, &pvCircBuf, &cbCircBuf); 592 593 Log3Func(("cbSrc=%RU32, cbCircBuf=%zu\n", cbSrc, cbCircBuf)); 594 595 memcpy((uint8_t *)pStreamAV->pvSrcBuf + cbSrc, pvCircBuf, cbCircBuf); 596 597 cbSrc += (uint32_t)cbCircBuf; 598 Assert(cbSrc <= pStreamAV->cbSrcBuf); 599 Assert(cbSrc <= cbFrame); 600 601 RTCircBufReleaseReadBlock(pCircBuf, cbCircBuf); 602 603 if (cbSrc == cbFrame) /* Only send full codec frames. */ 592 604 { 593 memcpy((uint8_t *)pStreamAV->pvSrcBuf + cbSrc, pvCircBuf, cbCircBuf); 594 595 cbSrc += (uint32_t)cbCircBuf; 596 Assert(cbSrc <= pStreamAV->cbSrcBuf); 605 vrc = pRecStream->SendAudioFrame(pStreamAV->pvSrcBuf, cbSrc, 0); 606 if (RT_FAILURE(vrc)) 607 break; 597 608 } 598 609 599 RTCircBufReleaseReadBlock(pCircBuf, cbCircBuf); 600 AssertBreak(cbCircBuf); 601 } 602 603 Assert(cbSrc == cbFramesToEncode); 604 605 RECORDINGFRAME Frame; 606 Frame.Audio.cbBuf = cbFramesToEncode; 607 Frame.Audio.pvBuf = (uint8_t *)pStreamAV->pvSrcBuf; 608 609 size_t cEncoded /* Blocks encoded */, cbEncoded /* Bytes encoded */; 610 vrc = recordingCodecEncode(pSink->pCodec, 611 /* Source */ 612 &Frame, &cEncoded, &cbEncoded); 613 if ( RT_SUCCESS(vrc) 614 && cEncoded) 615 { 616 Assert(cbEncoded); 617 } 618 else if (RT_FAILURE(vrc)) /* Something went wrong -- report all bytes as being processed, to not hold up others. */ 619 cbWrittenTotal = cbBuf; 610 } while (cbSrc < cbFrame); 611 612 Assert(cbToWrite >= cbFrame); 613 cbToWrite -= cbFrame; 620 614 621 615 if (RT_FAILURE(vrc)) … … 626 620 *pcbWritten = cbWrittenTotal; 627 621 628 LogFlowFunc(("c sReadTotal=%RU32, vrc=%Rrc\n", cbWrittenTotal, vrc));622 LogFlowFunc(("cbBuf=%RU32, cbWrittenTotal=%RU32, vrc=%Rrc\n", cbBuf, cbWrittenTotal, vrc)); 629 623 return VINF_SUCCESS; /* Don't propagate encoding errors to the caller. */ 630 624 } … … 685 679 AssertPtrReturnVoid(pSink); 686 680 687 pSink->p Codec= NULL;681 pSink->pRecStream = NULL; 688 682 689 683 switch (pSink->Con.Parms.enmType) … … 768 762 * @param pSink Sink to initialize. 769 763 * @param pConParms Container parameters to set. 770 * @param p Codec Codec to use.771 */ 772 static int avRecSinkInit(PDRVAUDIORECORDING pThis, PAVRECSINK pSink, PAVRECCONTAINERPARMS pConParms, PRECORDINGCODEC pCodec)773 { 774 AssertReturn(pCodec->Parms.enmType == RECORDINGCODECTYPE_AUDIO, VERR_INVALID_PARAMETER);764 * @param pStream Recording stream to asssign sink to. 765 */ 766 static int avRecSinkInit(PDRVAUDIORECORDING pThis, PAVRECSINK pSink, PAVRECCONTAINERPARMS pConParms, RecordingStream *pStream) 767 { 768 pSink->pRecStream = pStream; 775 769 776 770 int vrc = VINF_SUCCESS; 777 778 pSink->pCodec = pCodec;779 771 780 772 /* … … 798 790 case AVRECCONTAINERTYPE_WEBM: 799 791 { 792 #if 0 800 793 /* If we only record audio, create our own WebM writer instance here. */ 801 794 if (!pSink->Con.WebM.pWebM) /* Do we already have our WebM writer instance? */ … … 828 821 } 829 822 break; 823 #endif 830 824 } 831 825 … … 948 942 * Obtain the recording context. 949 943 */ 950 pThis->pRecCtx = 944 pThis->pRecCtx = pConsole->i_recordingGetContext(); 951 945 AssertPtrReturn(pThis->pRecCtx, VERR_INVALID_POINTER); 952 946 … … 957 951 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 958 952 959 const PRECORDINGCODEC pCodec = pStream->GetAudioCodec();960 AssertPtrReturn(pCodec, VERR_INVALID_POINTER);961 962 953 /* 963 954 * Init the recording sink. 964 955 */ 965 vrc = avRecSinkInit(pThis, &pThis->Sink, &pThis->ContainerParms, p Codec);956 vrc = avRecSinkInit(pThis, &pThis->Sink, &pThis->ContainerParms, pStream); 966 957 if (RT_SUCCESS(vrc)) 967 958 LogRel2(("Recording: Audio recording driver initialized\n")); -
trunk/src/VBox/Main/src-client/Recording.cpp
r96230 r96260 115 115 RTThreadUserSignal(hThreadSelf); 116 116 117 Log Func(("Thread started\n"));117 LogRel2(("Recording: Thread started\n")); 118 118 119 119 for (;;) … … 123 123 124 124 Log2Func(("Processing %zu streams\n", pThis->vecStreams.size())); 125 126 /* Process common raw blocks (data which not has been encoded yet). */ 127 vrc = pThis->processCommonData(pThis->mapBlocksRaw, 100 /* ms timeout */); 125 128 126 129 /** @todo r=andy This is inefficient -- as we already wake up this thread … … 132 135 RecordingStream *pStream = (*itStream); 133 136 134 vrc = pStream->Process(pThis->mapBlocksCommon); 137 /* Hand-in common encoded blocks. */ 138 vrc = pStream->Process(pThis->mapBlocksEncoded); 135 139 if (RT_FAILURE(vrc)) 136 140 { … … 155 159 } /* for */ 156 160 157 Log Func(("Thread ended\n"));161 LogRel2(("Recording: Thread ended\n")); 158 162 return VINF_SUCCESS; 159 163 } … … 170 174 171 175 /** 172 * Writes block data which are common (shared) between all streams. 173 * 174 * To save time spent in EMT or other important threads (such as audio async I/O), 175 * do the required audio multiplexing in the encoding thread. 176 * Worker function for processing common block data. 177 * 178 * @returns VBox status code. 179 * @param mapCommon Common block map to handle. 180 * @param msTimeout Timeout to use for maximum time spending to process data. 181 * Use RT_INDEFINITE_WAIT for processing all data. 182 * 183 * @note Runs in recording thread. 184 */ 185 int RecordingContext::processCommonData(RecordingBlockMap &mapCommon, RTMSINTERVAL msTimeout) 186 { 187 Log2Func(("Processing %zu common blocks (%RU32ms timeout)\n", mapCommon.size(), msTimeout)); 188 189 int vrc = VINF_SUCCESS; 190 191 uint64_t const msStart = RTTimeMilliTS(); 192 RecordingBlockMap::iterator itCommonBlocks = mapCommon.begin(); 193 while (itCommonBlocks != mapCommon.end()) 194 { 195 RecordingBlockList::iterator itBlock = itCommonBlocks->second->List.begin(); 196 while (itBlock != itCommonBlocks->second->List.end()) 197 { 198 RecordingBlock *pBlockCommon = (RecordingBlock *)(*itBlock); 199 switch (pBlockCommon->enmType) 200 { 201 #ifdef VBOX_WITH_AUDIO_RECORDING 202 case RECORDINGBLOCKTYPE_AUDIO: 203 { 204 PRECORDINGAUDIOFRAME pAudioFrame = (PRECORDINGAUDIOFRAME)pBlockCommon->pvData; 205 206 RECORDINGFRAME Frame; 207 Frame.msTimestamp = pBlockCommon->msTimestamp; 208 Frame.Audio.pvBuf = pAudioFrame->pvBuf; 209 Frame.Audio.cbBuf = pAudioFrame->cbBuf; 210 211 vrc = recordingCodecEncode(&this->CodecAudio, &Frame, NULL, NULL); 212 break; 213 } 214 #endif /* VBOX_WITH_AUDIO_RECORDING */ 215 default: 216 /* Skip unknown stuff. */ 217 break; 218 } 219 220 itCommonBlocks->second->List.erase(itBlock); 221 delete pBlockCommon; 222 itBlock = itCommonBlocks->second->List.begin(); 223 224 if (RT_FAILURE(vrc) || RTTimeMilliTS() > msStart + msTimeout) 225 break; 226 } 227 228 /* If no entries are left over in the block map, remove it altogether. */ 229 if (itCommonBlocks->second->List.empty()) 230 { 231 delete itCommonBlocks->second; 232 mapCommon.erase(itCommonBlocks); 233 itCommonBlocks = mapCommon.begin(); 234 } 235 else 236 ++itCommonBlocks; 237 238 if (RT_FAILURE(vrc)) 239 break; 240 } 241 242 return vrc; 243 } 244 245 /** 246 * Writes common block data (i.e. shared / the same) in all streams. 176 247 * 177 248 * The multiplexing is needed to supply all recorded (enabled) screens with the same … … 179 250 * 180 251 * Currently this only is being used for audio data. 181 */ 182 int RecordingContext::writeCommonData(PRECORDINGCODEC pCodec, const void *pvData, size_t cbData, 183 uint64_t msAbsPTS, uint32_t uFlags) 252 * 253 * @returns VBox status code. 254 * @param mapCommon Common block map to write data to. 255 * @param pCodec Pointer to codec instance which has written the data. 256 * @param pvData Pointer to written data (encoded). 257 * @param cbData Size (in bytes) of \a pvData. 258 * @param msTimestamp Absolute PTS (in ms) of the written data. 259 * @param uFlags Encoding flags of type RECORDINGCODEC_ENC_F_XXX. 260 */ 261 int RecordingContext::writeCommonData(RecordingBlockMap &mapCommon, PRECORDINGCODEC pCodec, const void *pvData, size_t cbData, 262 uint64_t msTimestamp, uint32_t uFlags) 184 263 { 185 264 AssertPtrReturn(pvData, VERR_INVALID_POINTER); 186 265 AssertReturn(cbData, VERR_INVALID_PARAMETER); 187 266 188 LogFlowFunc(("pCodec=%p, cbData=%zu, ms AbsPTS=%zu, uFlags=%#x\n",189 pCodec, cbData, ms AbsPTS, uFlags));267 LogFlowFunc(("pCodec=%p, cbData=%zu, msTimestamp=%zu, uFlags=%#x\n", 268 pCodec, cbData, msTimestamp, uFlags)); 190 269 191 270 /** @todo Optimize this! Three allocations in here! */ … … 215 294 pBlock->cbData = sizeof(RECORDINGAUDIOFRAME) + cbData; 216 295 pBlock->cRefs = this->cStreamsEnabled; 217 pBlock->msTimestamp = ms AbsPTS;296 pBlock->msTimestamp = msTimestamp; 218 297 pBlock->uFlags = uFlags; 219 298 … … 232 311 try 233 312 { 234 RecordingBlockMap::iterator itBlocks = this->mapBlocksCommon.find(msAbsPTS);235 if (itBlocks == this->mapBlocksCommon.end())313 RecordingBlockMap::iterator itBlocks = mapCommon.find(msTimestamp); 314 if (itBlocks == mapCommon.end()) 236 315 { 237 316 RecordingBlocks *pRecordingBlocks = new RecordingBlocks(); 238 317 pRecordingBlocks->List.push_back(pBlock); 239 318 240 this->mapBlocksCommon.insert(std::make_pair(msAbsPTS, pRecordingBlocks));319 mapCommon.insert(std::make_pair(msTimestamp, pRecordingBlocks)); 241 320 } 242 321 else … … 261 340 #ifdef VBOX_WITH_AUDIO_RECORDING 262 341 /** 263 * Callback function for taking care of multiplexing the encoded audio data to all connected streams. 342 * Callback function for writing encoded audio data into the common encoded block map. 343 * 344 * This is called by the audio codec when finishing encoding audio data. 264 345 * 265 346 * @copydoc RECORDINGCODECCALLBACKS::pfnWriteData … … 269 350 uint64_t msAbsPTS, uint32_t uFlags, void *pvUser) 270 351 { 271 #if 0272 352 RecordingContext *pThis = (RecordingContext *)pvUser; 273 274 int vrc = VINF_SUCCESS; 275 276 RecordingStreams::iterator itStream = pThis->vecStreams.begin(); 277 while (itStream != pThis->vecStreams.end()) 278 { 279 RecordingStream *pStream = (*itStream); 280 281 LogFlowFunc(("pStream=%p\n", pStream)); 282 283 if (pStream->GetConfig().isFeatureEnabled(RecordingFeature_Audio)) /** @todo Optimize this! Use a dedicated stream group for video-only / audio-only streams. */ 284 { 285 vrc = RecordingStream::codecWriteDataCallback(pCodec, pvData, cbData, msAbsPTS, uFlags, pStream); 286 if (RT_FAILURE(vrc)) 287 { 288 LogRel(("Recording: Calling audio write callback for stream #%RU16 failed (%Rrc)\n", pStream->GetID(), vrc)); 289 break; 290 } 291 } 292 293 ++itStream; 294 } 295 296 return vrc; 297 #else 298 RecordingContext *pThis = (RecordingContext *)pvUser; 299 300 return pThis->writeCommonData(pCodec, pvData, cbData, msAbsPTS, uFlags); 301 #endif 353 return pThis->writeCommonData(pThis->mapBlocksEncoded, pCodec, pvData, cbData, msAbsPTS, uFlags); 302 354 } 303 355 … … 503 555 /* Sanity. */ 504 556 Assert(this->vecStreams.empty()); 505 Assert(this->mapBlocksCommon.size() == 0); 557 Assert(this->mapBlocksRaw.size() == 0); 558 Assert(this->mapBlocksEncoded.size() == 0); 506 559 507 560 this->enmState = RECORDINGSTS_UNINITIALIZED; … … 779 832 * Sends an audio frame to the video encoding thread. 780 833 * 781 * @thread EMT782 *783 834 * @returns VBox status code. 784 835 * @param pvData Audio frame data to send. … … 789 840 { 790 841 #ifdef VBOX_WITH_AUDIO_RECORDING 791 return writeCommonData(&this->CodecAudio, pvData, cbData, msTimestamp, RECORDINGCODEC_ENC_F_BLOCK_IS_KEY); 842 return writeCommonData(this->mapBlocksRaw, &this->CodecAudio, 843 pvData, cbData, msTimestamp, RECORDINGCODEC_ENC_F_BLOCK_IS_KEY); 792 844 #else 793 845 RT_NOREF(pvData, cbData, msTimestamp); 794 return V INF_SUCCESS;846 return VERR_NOT_SUPPORTED; 795 847 #endif 796 848 } -
trunk/src/VBox/Main/src-client/RecordingStream.cpp
r96243 r96260 319 319 AssertPtr(pBlock); 320 320 321 if (pBlock->enmType == RECORDINGBLOCKTYPE_VIDEO) 322 { 323 RECORDINGFRAME Frame; 324 Frame.VideoPtr = (PRECORDINGVIDEOFRAME)pBlock->pvData; 325 Frame.msTimestamp = msTimestamp; 326 327 int vrc2 = recordingCodecEncode(&this->CodecVideo, &Frame, NULL, NULL); 328 AssertRC(vrc2); 329 if (RT_SUCCESS(vrc)) 330 vrc = vrc2; 321 switch (pBlock->enmType) 322 { 323 case RECORDINGBLOCKTYPE_VIDEO: 324 { 325 RECORDINGFRAME Frame; 326 Frame.VideoPtr = (PRECORDINGVIDEOFRAME)pBlock->pvData; 327 Frame.msTimestamp = msTimestamp; 328 329 int vrc2 = recordingCodecEncode(&this->CodecVideo, &Frame, NULL, NULL); 330 AssertRC(vrc2); 331 if (RT_SUCCESS(vrc)) 332 vrc = vrc2; 333 334 break; 335 } 336 337 default: 338 /* Note: Audio data already is encoded. */ 339 break; 331 340 } 332 341 … … 410 419 LogFlowFuncLeaveRC(vrc); 411 420 return vrc; 421 } 422 423 /** 424 * Sends a raw (e.g. not yet encoded) audio frame to the recording stream. 425 * 426 * @returns VBox status code. 427 * @param pvData Pointer to audio data. 428 * @param cbData Size (in bytes) of \a pvData. 429 * @param msTimestamp Absolute PTS timestamp (in ms). 430 */ 431 int RecordingStream::SendAudioFrame(const void *pvData, size_t cbData, uint64_t msTimestamp) 432 { 433 /* As audio data is common across all streams, re-route this to the recording context, where 434 * the data is being encoded and stored in the common blocks queue. */ 435 return m_pCtx->SendAudioFrame(pvData, cbData, msTimestamp); 412 436 } 413 437
Note:
See TracChangeset
for help on using the changeset viewer.