Changeset 75040 in vbox
- Timestamp:
- Oct 24, 2018 1:54:50 PM (7 years ago)
- svn:sync-xref-src-repo-rev:
- 126083
- Location:
- trunk/src/VBox/Main
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/include/VideoRecStream.h
r74999 r75040 169 169 PVIDEORECSTREAM videoRecStreamGet(PVIDEORECCONTEXT pCtx, uint32_t uScreen); 170 170 int videoRecStreamOpen(PVIDEORECSTREAM pStream, PVIDEORECCFG pCfg); 171 int VideoRecStreamProcess(PVIDEORECSTREAM pStream); 171 172 int videoRecStreamUninit(PVIDEORECSTREAM pStream); 172 173 int videoRecStreamUnitVideo(PVIDEORECSTREAM pStream); -
trunk/src/VBox/Main/src-client/VideoRec.cpp
r74992 r75040 122 122 AssertRCBreak(rc); 123 123 124 Log2Func(("Processing %zu streams\n", pCtx->vecStreams.size())); 125 124 126 /** @todo r=andy This is inefficient -- as we already wake up this thread 125 127 * for every screen from Main, we here go again (on every wake up) through 126 128 * all screens. */ 127 for (VideoRecStreams::iterator itStream = pCtx->vecStreams.begin(); itStream != pCtx->vecStreams.end(); itStream++) 129 VideoRecStreams::iterator itStream = pCtx->vecStreams.begin(); 130 while (itStream != pCtx->vecStreams.end()) 128 131 { 129 132 PVIDEORECSTREAM pStream = (*itStream); 130 133 131 videoRecStreamLock(pStream); 132 133 if (!pStream->fEnabled) 134 { 135 videoRecStreamUnlock(pStream); 136 continue; 137 } 138 139 VideoRecBlockMap::iterator itBlockStream = pStream->Blocks.Map.begin(); 140 while (itBlockStream != pStream->Blocks.Map.end()) 141 { 142 const uint64_t uTimeStampMs = itBlockStream->first; 143 VideoRecBlocks *pBlocks = itBlockStream->second; 144 145 AssertPtr(pBlocks); 146 147 while (!pBlocks->List.empty()) 148 { 149 PVIDEORECBLOCK pBlock = pBlocks->List.front(); 150 AssertPtr(pBlock); 151 152 #ifdef VBOX_WITH_LIBVPX 153 if (pBlock->enmType == VIDEORECBLOCKTYPE_VIDEO) 154 { 155 PVIDEORECVIDEOFRAME pVideoFrame = (PVIDEORECVIDEOFRAME)pBlock->pvData; 156 157 rc = videoRecRGBToYUV(pVideoFrame->uPixelFormat, 158 /* Destination */ 159 pStream->Video.Codec.VPX.pu8YuvBuf, pVideoFrame->uWidth, pVideoFrame->uHeight, 160 /* Source */ 161 pVideoFrame->pu8RGBBuf, pStream->Video.uWidth, pStream->Video.uHeight); 162 if (RT_SUCCESS(rc)) 163 rc = videoRecStreamWriteVideoVPX(pStream, uTimeStampMs, pVideoFrame); 164 } 165 #endif 166 VideoRecBlockFree(pBlock); 167 pBlock = NULL; 168 169 pBlocks->List.pop_front(); 170 } 171 172 #ifdef VBOX_WITH_AUDIO_VIDEOREC 173 /* As each (enabled) screen has to get the same audio data, look for common (audio) data which needs to be 174 * written to the screen's assigned recording stream. */ 175 VideoRecBlockMap::iterator itCommon = pCtx->mapBlocksCommon.begin(); 176 while (itCommon != pCtx->mapBlocksCommon.end()) 177 { 178 VideoRecBlockList::iterator itBlockCommon = itCommon->second->List.begin(); 179 while (itBlockCommon != itCommon->second->List.end()) 180 { 181 PVIDEORECBLOCK pBlockCommon = (PVIDEORECBLOCK)(*itBlockCommon); 182 switch (pBlockCommon->enmType) 183 { 184 case VIDEORECBLOCKTYPE_AUDIO: 185 { 186 PVIDEORECAUDIOFRAME pAudioFrame = (PVIDEORECAUDIOFRAME)pBlockCommon->pvData; 187 AssertPtr(pAudioFrame); 188 AssertPtr(pAudioFrame->pvBuf); 189 Assert(pAudioFrame->cbBuf); 190 191 WebMWriter::BlockData_Opus blockData = { pAudioFrame->pvBuf, pAudioFrame->cbBuf, 192 pBlockCommon->uTimeStampMs }; 193 rc = pStream->File.pWEBM->WriteBlock(pStream->uTrackAudio, &blockData, sizeof(blockData)); 194 break; 195 } 196 197 default: 198 AssertFailed(); 199 break; 200 } 201 202 Assert(pBlockCommon->cRefs); 203 if (--pBlockCommon->cRefs == 0) 204 { 205 VideoRecBlockFree(pBlockCommon); 206 itCommon->second->List.erase(itBlockCommon); 207 itBlockCommon = itCommon->second->List.begin(); 208 } 209 else 210 ++itBlockCommon; 211 } 212 213 /* If no entries are left over in the block map, remove it altogether. */ 214 if (itCommon->second->List.empty()) 215 { 216 delete itCommon->second; 217 pCtx->mapBlocksCommon.erase(itCommon); 218 } 219 220 itCommon = pCtx->mapBlocksCommon.begin(); 221 222 LogFunc(("Common blocks: %zu\n", pCtx->mapBlocksCommon.size())); 223 } 224 #endif 225 ++itBlockStream; 226 } 227 228 videoRecStreamUnlock(pStream); 229 } 134 rc = VideoRecStreamProcess(pStream); 135 if (RT_FAILURE(rc)) 136 break; 137 138 ++itStream; 139 } 140 141 if (RT_FAILURE(rc)) 142 LogRel(("VideoRec: Encoding thread failed with rc=%Rrc\n", rc)); 230 143 231 144 /* Keep going in case of errors. */ … … 379 292 rc = videoRecThreadNotify(pCtx); 380 293 if (RT_SUCCESS(rc)) 381 rc = RTThreadWait(pCtx->Thread, 10 * 1000 /* 10s timeout */, NULL);294 rc = RTThreadWait(pCtx->Thread, 30 * 1000 /* 10s timeout */, NULL); 382 295 383 296 if (RT_SUCCESS(rc)) -
trunk/src/VBox/Main/src-client/VideoRecStream.cpp
r74999 r75040 38 38 #include "VideoRec.h" 39 39 #include "VideoRecStream.h" 40 #include "VideoRecUtils.h" 40 41 #include "WebMWriter.h" 41 42 … … 193 194 194 195 LogFlowFuncLeaveRC(rc); 196 return rc; 197 } 198 199 /** 200 * Processes a recording stream. 201 * This function takes care of the actual encoding and writing of a certain stream. 202 * As this can be very CPU intensive, this function usually is called from a separate thread. 203 * 204 * @returns IPRT status code. 205 * @param pStream Recording stream to process. 206 */ 207 int VideoRecStreamProcess(PVIDEORECSTREAM pStream) 208 { 209 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 210 211 videoRecStreamLock(pStream); 212 213 if (!pStream->fEnabled) 214 { 215 videoRecStreamUnlock(pStream); 216 return VINF_SUCCESS; 217 } 218 219 int rc = VINF_SUCCESS; 220 221 const PVIDEORECCONTEXT pCtx = pStream->pCtx; 222 AssertPtr(pCtx); 223 224 VideoRecBlockMap::iterator itStreamBlocks = pStream->Blocks.Map.begin(); 225 while (itStreamBlocks != pStream->Blocks.Map.end()) 226 { 227 const uint64_t uTimeStampMs = itStreamBlocks->first; 228 VideoRecBlocks *pBlocks = itStreamBlocks->second; 229 230 AssertPtr(pBlocks); 231 232 while (!pBlocks->List.empty()) 233 { 234 PVIDEORECBLOCK pBlock = pBlocks->List.front(); 235 AssertPtr(pBlock); 236 237 #ifdef VBOX_WITH_LIBVPX 238 if (pBlock->enmType == VIDEORECBLOCKTYPE_VIDEO) 239 { 240 PVIDEORECVIDEOFRAME pVideoFrame = (PVIDEORECVIDEOFRAME)pBlock->pvData; 241 242 rc = videoRecRGBToYUV(pVideoFrame->uPixelFormat, 243 /* Destination */ 244 pStream->Video.Codec.VPX.pu8YuvBuf, pVideoFrame->uWidth, pVideoFrame->uHeight, 245 /* Source */ 246 pVideoFrame->pu8RGBBuf, pStream->Video.uWidth, pStream->Video.uHeight); 247 if (RT_SUCCESS(rc)) 248 { 249 rc = videoRecStreamWriteVideoVPX(pStream, uTimeStampMs, pVideoFrame); 250 } 251 else 252 break; 253 } 254 #endif 255 VideoRecBlockFree(pBlock); 256 pBlock = NULL; 257 258 pBlocks->List.pop_front(); 259 } 260 261 ++itStreamBlocks; 262 } 263 264 #ifdef VBOX_WITH_AUDIO_VIDEOREC 265 /* As each (enabled) screen has to get the same audio data, look for common (audio) data which needs to be 266 * written to the screen's assigned recording stream. */ 267 VideoRecBlockMap::iterator itCommonBlocks = pCtx->mapBlocksCommon.begin(); 268 while (itCommonBlocks != pCtx->mapBlocksCommon.end()) 269 { 270 VideoRecBlockList::iterator itBlock = itCommonBlocks->second->List.begin(); 271 while (itBlock != itCommonBlocks->second->List.end()) 272 { 273 PVIDEORECBLOCK pBlockCommon = (PVIDEORECBLOCK)(*itBlock); 274 switch (pBlockCommon->enmType) 275 { 276 case VIDEORECBLOCKTYPE_AUDIO: 277 { 278 PVIDEORECAUDIOFRAME pAudioFrame = (PVIDEORECAUDIOFRAME)pBlockCommon->pvData; 279 AssertPtr(pAudioFrame); 280 AssertPtr(pAudioFrame->pvBuf); 281 Assert(pAudioFrame->cbBuf); 282 283 WebMWriter::BlockData_Opus blockData = { pAudioFrame->pvBuf, pAudioFrame->cbBuf, 284 pBlockCommon->uTimeStampMs }; 285 AssertPtr(pStream->File.pWEBM); 286 rc = pStream->File.pWEBM->WriteBlock(pStream->uTrackAudio, &blockData, sizeof(blockData)); 287 break; 288 } 289 290 default: 291 AssertFailed(); 292 break; 293 } 294 295 if (RT_FAILURE(rc)) 296 break; 297 298 Assert(pBlockCommon->cRefs); 299 pBlockCommon->cRefs--; 300 if (pBlockCommon->cRefs == 0) 301 { 302 VideoRecBlockFree(pBlockCommon); 303 itCommonBlocks->second->List.erase(itBlock); 304 itBlock = itCommonBlocks->second->List.begin(); 305 } 306 else 307 ++itBlock; 308 } 309 310 /* If no entries are left over in the block map, remove it altogether. */ 311 if (itCommonBlocks->second->List.empty()) 312 { 313 delete itCommonBlocks->second; 314 pCtx->mapBlocksCommon.erase(itCommonBlocks); 315 itCommonBlocks = pCtx->mapBlocksCommon.begin(); 316 } 317 else 318 ++itCommonBlocks; 319 320 LogFunc(("Common blocks: %zu\n", pCtx->mapBlocksCommon.size())); 321 322 if (RT_FAILURE(rc)) 323 break; 324 } 325 #endif 326 327 videoRecStreamUnlock(pStream); 328 195 329 return rc; 196 330 }
Note:
See TracChangeset
for help on using the changeset viewer.