Changeset 65435 in vbox for trunk/src/VBox
- Timestamp:
- Jan 24, 2017 4:53:55 PM (8 years ago)
- Location:
- trunk/src/VBox/Main/src-client
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-client/EbmlWriter.cpp
r65392 r65435 585 585 CurSeg.mapTracks[uTrack] = pTrack; 586 586 587 Assert(uTrack == 0);588 589 587 if (puTrack) 590 588 *puTrack = uTrack; … … 784 782 uint64_t tcPTSRaw = lround((CurSeg.uTimecodeScaleFactor * 1000 * Cluster.cbData) / a_pTrack->Audio.uHz); 785 783 786 uint64_t tcPTS = /*Cluster.tcStart +*/ lround(tcPTSRaw / CurSeg.uTimecodeScaleFactor); 784 /* Calculate the absolute PTS. */ 785 uint64_t tcPTS = lround(tcPTSRaw / CurSeg.uTimecodeScaleFactor); 787 786 788 787 if (Cluster.tcStart == UINT64_MAX) -
trunk/src/VBox/Main/src-client/EbmlWriter.h
r65362 r65435 82 82 /** Size (in bytes) of encoded Opus audio data. */ 83 83 size_t cbData; 84 /** Timestamp (in ms). */ 85 uint64_t uTimestampMs; 84 86 }; 85 87 #endif /* VBOX_WITH_LIBOPUS */ -
trunk/src/VBox/Main/src-client/VideoRec.cpp
r65429 r65435 60 60 /** Currently busy, delay termination. */ 61 61 VIDEORECSTS_BUSY = 2, 62 /** Signal that we are terminating. */63 VIDEORECSTS_ TERMINATING = 362 /** The usual 32-bit hack. */ 63 VIDEORECSTS_32BIT_HACK = 0x7fffffff 64 64 }; 65 65 … … 78 78 VIDEORECPIXELFMT_RGB565 = 3 79 79 }; 80 81 /* Must be always accessible and therefore cannot be part of VIDEORECCONTEXT */82 static uint32_t g_enmState = VIDEORECSTS_UNINITIALIZED; /** @todo r=andy Make this part of VIDEORECCONTEXT + remove busy waiting. */83 80 84 81 /** … … 153 150 } VIDEORECSTREAM, *PVIDEORECSTREAM; 154 151 152 #ifdef VBOX_WITH_AUDIO_VIDEOREC 153 typedef struct VIDEORECAUDIOFRAME 154 { 155 uint8_t abBuf[_64K]; /** @todo Fix! */ 156 uint32_t cbBuf; 157 /** Time stamp (in ms). */ 158 uint64_t uTimeStampMs; 159 } VIDEORECAUDIOFRAME, *PVIDEORECAUDIOFRAME; 160 #endif 161 155 162 /** Vector of video recording streams. */ 156 163 typedef std::vector <PVIDEORECSTREAM> VideoRecStreams; … … 161 168 typedef struct VIDEORECCONTEXT 162 169 { 170 /** The current state. */ 171 uint32_t enmState; 163 172 /** Semaphore to signal the encoding worker thread. */ 164 173 RTSEMEVENT WaitEvent; 165 /** Semaphore required during termination. */166 RTSEMEVENT TermEvent;167 174 /** Whether video recording is enabled or not. */ 168 175 bool fEnabled; 176 /** Shutdown indicator. */ 177 bool fShutdown; 169 178 /** Worker thread. */ 170 179 RTTHREAD Thread; … … 177 186 #ifdef VBOX_WITH_AUDIO_VIDEOREC 178 187 bool fHasAudioData; 179 struct 180 { 181 uint8_t buf[_64K]; 182 } Audio; 188 VIDEORECAUDIOFRAME Audio; 183 189 #endif 184 190 } VIDEORECCONTEXT, *PVIDEORECCONTEXT; … … 455 461 static DECLCALLBACK(int) videoRecThread(RTTHREAD hThreadSelf, void *pvUser) 456 462 { 457 RT_NOREF(hThreadSelf);458 463 PVIDEORECCONTEXT pCtx = (PVIDEORECCONTEXT)pvUser; 464 465 /* Signal that we're up and rockin'. */ 466 RTThreadUserSignal(hThreadSelf); 459 467 460 468 for (;;) … … 463 471 AssertRCBreak(rc); 464 472 465 if (ASMAtomicRead U32(&g_enmState) == VIDEORECSTS_TERMINATING)473 if (ASMAtomicReadBool(&pCtx->fShutdown)) 466 474 break; 467 475 … … 503 511 if (fHasAudioData) 504 512 { 505 WebMWriter::BlockData_Opus blockData = { pCtx->Audio. buf,};513 WebMWriter::BlockData_Opus blockData = { pCtx->Audio.abBuf, pCtx->Audio.cbBuf, pCtx->Audio.uTimeStampMs }; 506 514 rc = pStream->pEBML->WriteBlock(pStream->uTrackAudio, &blockData, sizeof(blockData)); 507 515 } … … 529 537 AssertPtrReturn(ppCtx, VERR_INVALID_POINTER); 530 538 531 Assert(ASMAtomicReadU32(&g_enmState) == VIDEORECSTS_UNINITIALIZED);532 533 539 int rc = VINF_SUCCESS; 534 540 … … 563 569 if (RT_SUCCESS(rc)) 564 570 { 571 pCtx->enmState = VIDEORECSTS_UNINITIALIZED; 572 pCtx->fShutdown = false; 573 565 574 rc = RTSemEventCreate(&pCtx->WaitEvent); 566 575 AssertRCReturn(rc, rc); 567 576 568 rc = RTSemEventCreate(&pCtx->TermEvent); 569 AssertRCReturn(rc, rc); 570 571 rc = RTThreadCreate(&pCtx->Thread, videoRecThread, (void*)pCtx, 0, 577 rc = RTThreadCreate(&pCtx->Thread, videoRecThread, (void *)pCtx, 0, 572 578 RTTHREADTYPE_MAIN_WORKER, RTTHREADFLAGS_WAITABLE, "VideoRec"); 573 AssertRCReturn(rc, rc); 574 575 ASMAtomicWriteU32(&g_enmState, VIDEORECSTS_IDLE); 576 577 if (ppCtx) 578 *ppCtx = pCtx; 579 } 580 else 579 580 if (RT_SUCCESS(rc)) /* Wait for the thread to start. */ 581 rc = RTThreadUserWait(pCtx->Thread, 30 * 1000 /* 30s timeout */); 582 583 if (RT_SUCCESS(rc)) 584 { 585 pCtx->enmState = VIDEORECSTS_IDLE; 586 pCtx->fEnabled = true; 587 588 if (ppCtx) 589 *ppCtx = pCtx; 590 } 591 } 592 593 if (RT_FAILURE(rc)) 581 594 { 582 595 /* Roll back allocations on error. */ … … 606 619 * @param pCtx Video recording context to destroy. 607 620 */ 608 voidVideoRecContextDestroy(PVIDEORECCONTEXT pCtx)621 int VideoRecContextDestroy(PVIDEORECCONTEXT pCtx) 609 622 { 610 623 if (!pCtx) 611 return; 612 613 uint32_t enmState = VIDEORECSTS_IDLE; 614 615 for (;;) /** @todo r=andy Remove busy waiting! */ 616 { 617 if (ASMAtomicCmpXchgExU32(&g_enmState, VIDEORECSTS_TERMINATING, enmState, &enmState)) 618 break; 619 if (enmState == VIDEORECSTS_UNINITIALIZED) 620 return; 621 } 622 623 if (enmState == VIDEORECSTS_BUSY) 624 { 625 int rc = RTSemEventWait(pCtx->TermEvent, RT_INDEFINITE_WAIT); 626 AssertRC(rc); 627 } 628 624 return VINF_SUCCESS; 625 626 /* Set shutdown indicator. */ 627 ASMAtomicWriteBool(&pCtx->fShutdown, true); 628 629 /* Signal the thread. */ 629 630 RTSemEventSignal(pCtx->WaitEvent); 630 RTThreadWait(pCtx->Thread, 10 * 1000, NULL); 631 RTSemEventDestroy(pCtx->WaitEvent); 632 RTSemEventDestroy(pCtx->TermEvent); 631 632 int rc = RTThreadWait(pCtx->Thread, 10 * 1000 /* 10s timeout */, NULL); 633 if (RT_FAILURE(rc)) 634 return rc; 635 636 rc = RTSemEventDestroy(pCtx->WaitEvent); 637 AssertRC(rc); 638 639 pCtx->WaitEvent = NIL_RTSEMEVENT; 633 640 634 641 VideoRecStreams::iterator it = pCtx->vecStreams.begin(); … … 668 675 669 676 Assert(pCtx->vecStreams.empty()); 677 670 678 RTMemFree(pCtx); 671 672 ASMAtomicWriteU32(&g_enmState, VIDEORECSTS_UNINITIALIZED); 679 pCtx = NULL; 680 681 return VINF_SUCCESS; 673 682 } 674 683 … … 885 894 pStream->Video.pu8YuvBuf = pStream->Codec.VPX.RawImage.planes[0]; 886 895 #endif 887 888 pCtx->fEnabled = true;889 896 pStream->fEnabled = true; 890 897 … … 895 902 * VideoRec utility function to check if recording is enabled. 896 903 * 897 * @returns true if recording is enabled 904 * @returns true if recording is enabled. 898 905 * @param pCtx Pointer to video recording context. 899 906 */ … … 901 908 { 902 909 RT_NOREF(pCtx); 903 uint32_t enmState = ASMAtomicReadU32(& g_enmState);910 uint32_t enmState = ASMAtomicReadU32(&pCtx->enmState); 904 911 return ( enmState == VIDEORECSTS_IDLE 905 912 || enmState == VIDEORECSTS_BUSY); … … 910 917 * for the given screen. 911 918 * 912 * @returns true if recording engine is ready 919 * @returns true if recording engine is ready. 913 920 * @param pCtx Pointer to video recording context. 914 921 * @param uScreen Screen ID. … … 917 924 bool VideoRecIsReady(PVIDEORECCONTEXT pCtx, uint32_t uScreen, uint64_t uTimeStampMs) 918 925 { 919 uint32_t enmState = ASMAtomicReadU32(& g_enmState);926 uint32_t enmState = ASMAtomicReadU32(&pCtx->enmState); 920 927 if (enmState != VIDEORECSTS_IDLE) 921 928 return false; … … 931 938 return false; 932 939 933 if (ASMAtomicReadBool(&pStream->fHasVideoData)) 940 if ( ASMAtomicReadBool(&pStream->fHasVideoData) 941 #ifdef VBOX_WITH_AUDIO_VIDEOREC 942 /* Check if we have audio data left for the current frame. */ 943 || ASMAtomicReadBool(&pCtx->fHasAudioData) 944 #endif 945 ) 946 { 934 947 return false; 948 } 935 949 936 950 return true; … … 1083 1097 * @param pvData Audio frame data to send. 1084 1098 * @param cbData Size (in bytes) of audio frame data. 1085 * @param uTimestampMs Time stamp (in ms) of audio playback. 1086 */ 1087 int VideoRecSendAudioFrame(PVIDEORECCONTEXT pCtx, const void *pvData, size_t cbData, uint64_t uTimestampMs) 1088 { 1089 RT_NOREF(pCtx, pvData, cbData, uTimestampMs); 1099 * @param uTimeStampMs Time stamp (in ms) of audio playback. 1100 */ 1101 int VideoRecSendAudioFrame(PVIDEORECCONTEXT pCtx, const void *pvData, size_t cbData, uint64_t uTimeStampMs) 1102 { 1103 #ifdef VBOX_WITH_AUDIO_VIDEOREC 1104 AssertReturn(cbData <= _64K, VERR_INVALID_PARAMETER); 1105 1106 /* Do not execute during termination and guard against termination. */ 1107 if (!ASMAtomicCmpXchgU32(&pCtx->enmState, VIDEORECSTS_BUSY, VIDEORECSTS_IDLE)) 1108 return VINF_TRY_AGAIN; 1090 1109 1091 1110 /* To save time spent in EMT, do the required audio multiplexing in the encoding thread. … … 1095 1114 */ 1096 1115 1097 1116 if (ASMAtomicReadBool(&pCtx->fHasAudioData)) 1117 return VERR_TRY_AGAIN; /* Previous frame not yet encoded. */ 1118 1119 memcpy(pCtx->Audio.abBuf, pvData, RT_MIN(_64K, cbData)); 1120 pCtx->Audio.uTimeStampMs = uTimeStampMs; 1121 1122 ASMAtomicWriteBool(&pCtx->fHasAudioData, true); 1123 RTSemEventSignal(pCtx->WaitEvent); 1124 #else 1125 RT_NOREF(pCtx, pvData, cbData, uTimeStampMs); 1126 #endif 1098 1127 return VINF_SUCCESS; 1099 1128 } … … 1124 1153 { 1125 1154 /* Do not execute during termination and guard against termination. */ 1126 if (!ASMAtomicCmpXchgU32(& g_enmState, VIDEORECSTS_BUSY, VIDEORECSTS_IDLE))1155 if (!ASMAtomicCmpXchgU32(&pCtx->enmState, VIDEORECSTS_BUSY, VIDEORECSTS_IDLE)) 1127 1156 return VINF_TRY_AGAIN; 1128 1157 … … 1270 1299 } while (0); 1271 1300 1272 if (!ASMAtomicCmpXchgU32(&g_enmState, VIDEORECSTS_IDLE, VIDEORECSTS_BUSY)) 1273 { 1274 rc = RTSemEventSignal(pCtx->TermEvent); 1275 AssertRC(rc); 1276 } 1301 ASMAtomicCmpXchgU32(&pCtx->enmState, VIDEORECSTS_IDLE, VIDEORECSTS_BUSY); 1277 1302 1278 1303 return rc; -
trunk/src/VBox/Main/src-client/VideoRec.h
r65429 r65435 25 25 typedef struct VIDEORECSTREAM *PVIDEORECSTREAM; 26 26 27 int 28 voidVideoRecContextDestroy(PVIDEORECCONTEXT pCtx);27 int VideoRecContextCreate(uint32_t cScreens, PVIDEORECCONTEXT *ppCtx); 28 int VideoRecContextDestroy(PVIDEORECCONTEXT pCtx); 29 29 30 30 int VideoRecStreamInit(PVIDEORECCONTEXT pCtx, uint32_t uScreen, const char *pszFile,
Note:
See TracChangeset
for help on using the changeset viewer.