Changeset 65401 in vbox for trunk/src/VBox
- Timestamp:
- Jan 23, 2017 1:33:45 PM (8 years ago)
- Location:
- trunk/src/VBox/Main
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/include/DisplayImpl.h
r65381 r65401 504 504 505 505 #ifdef VBOX_WITH_VIDEOREC 506 VIDEORECCONTEXT *mpVideoRecCtx;507 bool maVideoRecEnabled[SchemaDefs::MaxGuestMonitors];506 VIDEORECCONTEXT *mpVideoRecCtx; 507 bool maVideoRecEnabled[SchemaDefs::MaxGuestMonitors]; 508 508 #endif 509 509 -
trunk/src/VBox/Main/src-client/DisplayImpl.cpp
r65381 r65401 2349 2349 if (RT_SUCCESS(rc)) 2350 2350 { 2351 #ifndef DEUBG_andy2352 2351 if (mcMonitors > 1) 2353 2352 rc = RTStrAPrintf(&pszName, "%s-%u%s", pszAbsPath, uScreen+1, pszSuff); 2354 2353 else 2355 2354 rc = RTStrAPrintf(&pszName, "%s%s", pszAbsPath, pszSuff); 2356 #else2357 if (mcMonitors > 1)2358 rc = RTStrAPrintf(&pszName, "/tmp/avcap-%u.webm", uScreen+1);2359 else2360 rc = RTStrAPrintf(&pszName, "/tmp/avcap.webm");2361 #endif2362 2355 } 2363 2356 if (RT_SUCCESS(rc)) … … 2392 2385 if (RT_SUCCESS(rc)) 2393 2386 { 2394 LogRel(("Display::VideoCaptureStart: WebM/VP8 video recording screen #%u with %ux%u @ %u kbps, %u fps to '%s' "2395 "enabled\n", uScreen, ulWidth, ulHeight, ulRate, ulFPS, pszName));2396 2397 2387 videoCaptureScreenChanged(uScreen); 2398 2388 } 2399 2389 else 2400 LogRel(("Display::VideoCaptureStart: Failed to initialize video recording context #%u (%Rrc)!\n", uScreen, rc)); 2390 LogRel(("Display::VideoCaptureStart: Failed to initialize video recording context #%u, (%Rrc)\n", uScreen, rc)); 2391 2401 2392 RTStrFree(pszName); 2402 2393 RTStrFree(pszSuff); … … 2415 2406 { 2416 2407 #ifdef VBOX_WITH_VIDEOREC 2417 if (VideoRecIsEnabled(mpVideoRecCtx)) 2418 LogRel(("Display::VideoCaptureStop: WebM/VP8 video recording stopped\n")); 2408 if (!VideoRecIsEnabled(mpVideoRecCtx)) 2409 return; 2410 2419 2411 VideoRecContextDestroy(mpVideoRecCtx); 2420 2412 mpVideoRecCtx = NULL; … … 2429 2421 void Display::videoCaptureScreenChanged(unsigned uScreenId) 2430 2422 { 2423 if ( !VideoRecIsEnabled(mpVideoRecCtx) 2424 || !maVideoRecEnabled[uScreenId]) 2425 { 2426 /* Skip recording this screen. */ 2427 return; 2428 } 2429 2430 /* Get a new source bitmap which will be used by video capture code. */ 2431 2431 ComPtr<IDisplaySourceBitmap> pSourceBitmap; 2432 2433 if (VideoRecIsEnabled(mpVideoRecCtx) && maVideoRecEnabled[uScreenId]) 2434 { 2435 /* Get a new source bitmap which will be used by video capture code. */ 2436 QuerySourceBitmap(uScreenId, pSourceBitmap.asOutParam()); 2437 } 2438 2439 int rc = RTCritSectEnter(&mVideoCaptureLock); 2440 if (RT_SUCCESS(rc)) 2432 QuerySourceBitmap(uScreenId, pSourceBitmap.asOutParam()); 2433 2434 int rc2 = RTCritSectEnter(&mVideoCaptureLock); 2435 if (RT_SUCCESS(rc2)) 2441 2436 { 2442 2437 maFramebuffers[uScreenId].videoCapture.pSourceBitmap = pSourceBitmap; 2443 RTCritSectLeave(&mVideoCaptureLock); 2438 2439 rc2 = RTCritSectLeave(&mVideoCaptureLock); 2440 AssertRC(rc2); 2444 2441 } 2445 2442 } … … 3186 3183 continue; 3187 3184 3188 if (VideoRec IsFull(pDisplay->mpVideoRecCtx, uScreenId, u64Now))3185 if (VideoRecLimitReached(pDisplay->mpVideoRecCtx, uScreenId, u64Now)) 3189 3186 { 3190 3187 pDisplay->i_VideoCaptureStop(); -
trunk/src/VBox/Main/src-client/VideoRec.cpp
r65330 r65401 18 18 #define LOG_GROUP LOG_GROUP_MAIN 19 19 20 #include <stdexcept> 20 21 #include <vector> 21 22 … … 79 80 80 81 /* Must be always accessible and therefore cannot be part of VIDEORECCONTEXT */ 81 static uint32_t g_enmState = VIDEORECSTS_UNINITIALIZED; 82 static uint32_t g_enmState = VIDEORECSTS_UNINITIALIZED; /** @todo r=andy Make this part of VIDEORECCONTEXT + remove busy waiting. */ 82 83 83 84 /** … … 109 110 /** Container context. */ 110 111 WebMWriter *pEBML; 112 /** Track number of audio stream. */ 113 uint8_t uTrackAudio; 111 114 /** Track number of video stream. */ 112 115 uint8_t uTrackVideo; 113 116 /** Codec data. */ 114 117 VIDEORECCODEC Codec; 118 /** Screen ID. */ 119 uint16_t uScreen; 115 120 /** Target X resolution (in pixels). */ 116 121 uint32_t uTargetWidth; … … 135 140 /** Minimal delay between two frames. */ 136 141 uint32_t uDelay; 137 /** Time stamp of the last frame we encoded. */138 uint64_t u 64LastTimeStamp;139 /** Time stamp of the current frame. */140 uint64_t u 64TimeStamp;142 /** Time stamp (in ms) of the last frame we encoded. */ 143 uint64_t uLastTimeStampMs; 144 /** Time stamp (in ms) of the current frame. */ 145 uint64_t uCurTimeStampMs; 141 146 /** Encoder deadline. */ 142 147 unsigned int uEncoderDeadline; … … 159 164 /** Worker thread. */ 160 165 RTTHREAD Thread; 161 /** Maximal time stamp. */ 162 uint64_t u64MaxTimeStamp; 163 /** Maximal file size in MB. */ 164 uint32_t uMaxFileSize; 166 uint64_t tsStartMs; 167 /** Maximal time (in ms) to record. */ 168 uint64_t uMaxTimeMs; 169 /** Maximal file size (in MB) to record. */ 170 uint32_t uMaxSizeMB; 165 171 /** Vector of current video recording stream contexts. */ 166 172 VideoRecStreams vecStreams; … … 440 446 RT_NOREF(hThreadSelf); 441 447 PVIDEORECCONTEXT pCtx = (PVIDEORECCONTEXT)pvUser; 448 442 449 for (;;) 443 450 { … … 509 516 try 510 517 { 518 pStream->uScreen = uScreen; 519 511 520 pCtx->vecStreams.push_back(pStream); 512 521 … … 610 619 pStream->pu8RgbBuf = NULL; 611 620 } 621 622 LogRel(("VideoRec: Recording screen #%u stopped\n", pStream->uScreen)); 612 623 } 613 624 … … 628 639 629 640 ASMAtomicWriteU32(&g_enmState, VIDEORECSTS_UNINITIALIZED); 641 } 642 643 /** 644 * Retrieves a specific recording stream of a recording context. 645 * 646 * @returns Pointer to recording if found, or NULL if not found. 647 * @param Recording context to look up stream for. 648 * @param Screen number of recording stream to look up. 649 */ 650 DECLINLINE(PVIDEORECSTREAM) videoRecStreamGet(PVIDEORECCONTEXT pCtx, uint32_t uScreen) 651 { 652 AssertPtrReturn(pCtx, NULL); 653 654 PVIDEORECSTREAM pStream; 655 656 try 657 { 658 pStream = pCtx->vecStreams.at(uScreen); 659 } 660 catch (std::out_of_range) 661 { 662 pStream = NULL; 663 } 664 665 return pStream; 630 666 } 631 667 … … 634 670 * 635 671 * @returns IPRT status code. 636 * @param pCtx Pointer to video recording context to initialize Framebuffer width.637 * @param uScreen Screen number .638 * @param pszFile File to save the recorded data639 * @param uWidth Width of the target image in the video recoriding file (movie)640 * @param uHeight Height of the target image in video recording file.641 * @param uRate Rate.642 * @param uFps FPS.643 * @param uMaxTime 644 * @param uMaxFileSize 645 * @param pszOptions 672 * @param pCtx Pointer to video recording context. 673 * @param uScreen Screen number to record. 674 * @param pszFile File to save recording to. 675 * @param uWidth Target video resolution (width). 676 * @param uHeight Target video resolution (height). 677 * @param uRate Target encoding bit rate. 678 * @param uFps Target FPS (Frame Per Second). 679 * @param uMaxTimeS Maximum time (in s) to record, or 0 for no time limit. 680 * @param uMaxFileSizeMB Maximum file size (in MB) to record, or 0 for no limit. 681 * @param pszOptions Additional options in "key=value" array format. Optional. 646 682 */ 647 683 int VideoRecStreamInit(PVIDEORECCONTEXT pCtx, uint32_t uScreen, const char *pszFile, 648 uint32_t uWidth, uint32_t uHeight, uint32_t uRate, uint32_t uFps, 649 uint32_t uMaxTime, uint32_t uMaxFileSize, const char *pszOptions) 650 { 651 AssertPtrReturn(pCtx, VERR_INVALID_PARAMETER); 652 AssertReturn(uScreen < pCtx->vecStreams.size(), VERR_INVALID_PARAMETER); 653 654 pCtx->u64MaxTimeStamp = (uMaxTime > 0 ? RTTimeProgramMilliTS() + uMaxTime * 1000 : 0); 655 pCtx->uMaxFileSize = uMaxFileSize; 656 657 PVIDEORECSTREAM pStream = pCtx->vecStreams.at(uScreen); 684 uint32_t uWidth, uint32_t uHeight, uint32_t uRate, uint32_t uFPS, 685 uint32_t uMaxTimeS, uint32_t uMaxSizeMB, const char *pszOptions) 686 { 687 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 688 AssertPtrReturn(pszFile, VERR_INVALID_POINTER); 689 AssertReturn(uWidth, VERR_INVALID_PARAMETER); 690 AssertReturn(uHeight, VERR_INVALID_PARAMETER); 691 AssertReturn(uRate, VERR_INVALID_PARAMETER); 692 AssertReturn(uFPS, VERR_INVALID_PARAMETER); 693 /* pszOptions is optional. */ 694 695 PVIDEORECSTREAM pStream = videoRecStreamGet(pCtx, uScreen); 696 if (!pStream) 697 return VERR_NOT_FOUND; 698 699 pCtx->uMaxTimeMs = (uMaxTimeS > 0 ? RTTimeProgramMilliTS() + uMaxTimeS * 1000 : 0); 700 pCtx->uMaxSizeMB = uMaxSizeMB; 658 701 659 702 pStream->uTargetWidth = uWidth; … … 699 742 else if (value.compare("good", Utf8Str::CaseInsensitive) == 0) 700 743 { 701 pStream->uEncoderDeadline = 1000000 / uF ps;744 pStream->uEncoderDeadline = 1000000 / uFPS; 702 745 } 703 746 else if (value.compare("best", Utf8Str::CaseInsensitive) == 0) … … 752 795 } 753 796 754 pStream->uDelay = 1000 / uF ps;797 pStream->uDelay = 1000 / uFPS; 755 798 756 799 if (fHasVideoTrack) 757 800 { 758 rc = pStream->pEBML->AddVideoTrack(uWidth, uHeight, uF ps, &pStream->uTrackVideo);801 rc = pStream->pEBML->AddVideoTrack(uWidth, uHeight, uFPS, &pStream->uTrackVideo); 759 802 if (RT_FAILURE(rc)) 760 803 { … … 764 807 } 765 808 809 #ifdef VBOX_WITH_AUDIO_VIDEOREC 810 if (fHasAudioTrack) 811 { 812 rc = pStream->pEBML->AddAudioTrack(48000, 2, 16, &pStream->uTrackAudio); 813 if (RT_FAILURE(rc)) 814 { 815 LogRel(("VideoRec: Failed to add audio track to output file '%s' (%Rrc)\n", pszFile, rc)); 816 return rc; 817 } 818 } 819 #endif 820 766 821 #ifdef VBOX_WITH_LIBVPX 767 /* target bitrate in kilobits per second*/822 /* Target bitrate in kilobits per second. */ 768 823 pStream->Codec.VPX.Config.rc_target_bitrate = uRate; 769 /* frame width*/824 /* Frame width. */ 770 825 pStream->Codec.VPX.Config.g_w = uWidth; 771 /* frame height*/826 /* Frame height. */ 772 827 pStream->Codec.VPX.Config.g_h = uHeight; 773 /* 1ms per frame */828 /* 1ms per frame. */ 774 829 pStream->Codec.VPX.Config.g_timebase.num = 1; 775 830 pStream->Codec.VPX.Config.g_timebase.den = 1000; 776 /* disable multithreading*/831 /* Disable multithreading. */ 777 832 pStream->Codec.VPX.Config.g_threads = 0; 778 833 … … 796 851 pCtx->fEnabled = true; 797 852 pStream->fEnabled = true; 853 854 LogRel(("VideoRec: Recording screen #%u with %ux%u @ %u kbps, %u fps to '%s' started\n", 855 uScreen, uWidth, uHeight, uRate, uFPS, pszFile)); 798 856 799 857 return VINF_SUCCESS; … … 821 879 * @param pCtx Pointer to video recording context. 822 880 * @param uScreen Screen ID. 823 * @param u64TimeStamp Current time stamp.824 */ 825 bool VideoRecIsReady(PVIDEORECCONTEXT pCtx, uint32_t uScreen, uint64_t u64TimeStamp )881 * @param u64TimeStampMs Current time stamp (in ms). 882 */ 883 bool VideoRecIsReady(PVIDEORECCONTEXT pCtx, uint32_t uScreen, uint64_t u64TimeStampMs) 826 884 { 827 885 uint32_t enmState = ASMAtomicReadU32(&g_enmState); … … 829 887 return false; 830 888 831 PVIDEORECSTREAM pStream = pCtx->vecStreams.at(uScreen); 832 if (!pStream->fEnabled) 889 PVIDEORECSTREAM pStream = videoRecStreamGet(pCtx, uScreen); 890 if ( !pStream 891 || !pStream->fEnabled) 892 { 833 893 return false; 834 835 if (u64TimeStamp < pStream->u64LastTimeStamp + pStream->uDelay) 894 } 895 896 if (u64TimeStampMs < pStream->uLastTimeStampMs + pStream->uDelay) 836 897 return false; 837 898 … … 843 904 844 905 /** 845 * VideoRec utility function to check if the file size has reached846 * specified limits (if any).906 * VideoRec utility function to check if a specified limit for recording 907 * has been reached. 847 908 * 848 909 * @returns true if any limit has been reached. 849 910 * @param pCtx Pointer to video recording context. 850 911 * @param uScreen Screen ID. 851 * @param u64TimeStamp Current time stamp. 852 */ 853 854 bool VideoRecIsFull(PVIDEORECCONTEXT pCtx, uint32_t uScreen, uint64_t u64TimeStamp) 855 { 856 PVIDEORECSTREAM pStream = pCtx->vecStreams.at(uScreen); 857 if(!pStream->fEnabled) 912 * @param tsNowMs Current time stamp (in ms). 913 */ 914 915 bool VideoRecLimitReached(PVIDEORECCONTEXT pCtx, uint32_t uScreen, uint64_t tsNowMs) 916 { 917 PVIDEORECSTREAM pStream = videoRecStreamGet(pCtx, uScreen); 918 if ( !pStream 919 || !pStream->fEnabled) 920 { 858 921 return false; 859 860 if(pCtx->u64MaxTimeStamp > 0 && u64TimeStamp >= pCtx->u64MaxTimeStamp) 922 } 923 924 if ( pCtx->uMaxTimeMs 925 && (tsNowMs - pCtx->tsStartMs) >= pCtx->uMaxTimeMs) 926 { 861 927 return true; 862 863 if (pCtx->uMaxFileSize > 0) 928 } 929 930 if (pCtx->uMaxSizeMB) 864 931 { 865 932 uint64_t sizeInMB = pStream->pEBML->GetFileSize() / (1024 * 1024); 866 if(sizeInMB >= pCtx->uMax FileSize)933 if(sizeInMB >= pCtx->uMaxSizeMB) 867 934 return true; 868 935 } … … 890 957 #ifdef VBOX_WITH_LIBVPX 891 958 /* presentation time stamp */ 892 vpx_codec_pts_t pts = pStream->u 64TimeStamp;959 vpx_codec_pts_t pts = pStream->uCurTimeStampMs; 893 960 vpx_codec_err_t rcv = vpx_codec_encode(&pStream->Codec.VPX.CodecCtx, 894 961 &pStream->Codec.VPX.RawImage, … … 921 988 922 989 default: 923 LogFlow(("Unexpected CODEC packet kind %ld\n", pPacket->kind)); 990 AssertFailed(); 991 LogFunc(("Unexpected CODEC packet kind %ld\n", pPacket->kind)); 924 992 break; 925 993 } … … 991 1059 * @param uSourceHeight Height of the source image (framebuffer). 992 1060 * @param pu8BufAddr Pointer to source image(framebuffer). 993 * @param u64TimeStamp Time stamp (milliseconds).1061 * @param u64TimeStampMs Time stamp (in ms). 994 1062 */ 995 1063 int VideoRecCopyToIntBuf(PVIDEORECCONTEXT pCtx, uint32_t uScreen, uint32_t x, uint32_t y, 996 1064 uint32_t uPixelFormat, uint32_t uBitsPerPixel, uint32_t uBytesPerLine, 997 1065 uint32_t uSourceWidth, uint32_t uSourceHeight, uint8_t *pu8BufAddr, 998 uint64_t u 64TimeStamp)1066 uint64_t uTimeStampMs) 999 1067 { 1000 1068 /* Do not execute during termination and guard against termination */ … … 1005 1073 do 1006 1074 { 1007 AssertPtrBreakStmt(pu8BufAddr, rc = VERR_INVALID_PARAMETER); 1008 AssertBreakStmt(uSourceWidth, rc = VERR_INVALID_PARAMETER); 1009 AssertBreakStmt(uSourceHeight, rc = VERR_INVALID_PARAMETER); 1010 AssertBreakStmt(uScreen < pCtx->vecStreams.size(), rc = VERR_INVALID_PARAMETER); 1011 1012 PVIDEORECSTREAM pStream = pCtx->vecStreams.at(uScreen); 1075 AssertPtrBreakStmt(pCtx, rc = VERR_INVALID_POINTER); 1076 AssertPtrBreakStmt(pu8BufAddr, rc = VERR_INVALID_POINTER); 1077 AssertBreakStmt(uSourceWidth, rc = VERR_INVALID_PARAMETER); 1078 AssertBreakStmt(uSourceHeight, rc = VERR_INVALID_PARAMETER); 1079 1080 PVIDEORECSTREAM pStream = videoRecStreamGet(pCtx, uScreen); 1081 if (!pStream) 1082 { 1083 rc = VERR_NOT_FOUND; 1084 break; 1085 } 1086 1013 1087 if (!pStream->fEnabled) 1014 1088 { … … 1016 1090 break; 1017 1091 } 1018 if (u 64TimeStamp < pStream->u64LastTimeStamp+ pStream->uDelay)1092 if (uTimeStampMs < pStream->uLastTimeStampMs + pStream->uDelay) 1019 1093 { 1020 1094 rc = VINF_TRY_AGAIN; /* respect maximum frames per second */ … … 1027 1101 } 1028 1102 1029 pStream->u 64LastTimeStamp = u64TimeStamp;1103 pStream->uLastTimeStampMs = uTimeStampMs; 1030 1104 1031 1105 int xDiff = ((int)pStream->uTargetWidth - (int)uSourceWidth) / 2; … … 1127 1201 } 1128 1202 1129 pStream->u 64TimeStamp = u64TimeStamp;1203 pStream->uCurTimeStampMs = uTimeStampMs; 1130 1204 1131 1205 ASMAtomicWriteBool(&pStream->fRgbFilled, true); -
trunk/src/VBox/Main/src-client/VideoRec.h
r65173 r65401 36 36 uint32_t x, uint32_t y, uint32_t uPixelFormat, uint32_t uBitsPerPixel, 37 37 uint32_t uBytesPerLine, uint32_t uGuestWidth, uint32_t uGuestHeight, 38 uint8_t *pu8BufferAddress, uint64_t u64TimeStamp );39 bool VideoRecIsReady(PVIDEORECCONTEXT pCtx, uint32_t uScreen, uint64_t u64TimeStamp );40 bool VideoRec IsFull(PVIDEORECCONTEXT pCtx, uint32_t uScreen, uint64_t u64TimeStamp);38 uint8_t *pu8BufferAddress, uint64_t u64TimeStampMs); 39 bool VideoRecIsReady(PVIDEORECCONTEXT pCtx, uint32_t uScreen, uint64_t u64TimeStampMs); 40 bool VideoRecLimitReached(PVIDEORECCONTEXT pCtx, uint32_t uScreen, uint64_t u64TimeStampMs); 41 41 42 42 #endif /* !____H_VIDEOREC */
Note:
See TracChangeset
for help on using the changeset viewer.