- Timestamp:
- Jan 6, 2017 10:00:01 AM (8 years ago)
- Location:
- trunk/src/VBox/Main/src-client
- Files:
-
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-client/DisplayImpl.cpp
r65120 r65173 2293 2293 return VINF_SUCCESS; 2294 2294 2295 int rc = VideoRecContextCreate( &mpVideoRecCtx, mcMonitors);2295 int rc = VideoRecContextCreate(mcMonitors, &mpVideoRecCtx); 2296 2296 if (RT_FAILURE(rc)) 2297 2297 { … … 2355 2355 if (RT_SUCCESS(rc)) 2356 2356 { 2357 rc = VideoRecStr mInit(mpVideoRecCtx, uScreen,2358 pszName, ulWidth, ulHeight,2359 ulRate, ulFPS, ulMaxTime,2360 ulMaxSize, com::Utf8Str(strOptions).c_str());2357 rc = VideoRecStreamInit(mpVideoRecCtx, uScreen, 2358 pszName, ulWidth, ulHeight, 2359 ulRate, ulFPS, ulMaxTime, 2360 ulMaxSize, com::Utf8Str(strOptions).c_str()); 2361 2361 if (rc == VERR_ALREADY_EXISTS) 2362 2362 { … … 2375 2375 pszSuff); 2376 2376 if (RT_SUCCESS(rc)) 2377 rc = VideoRecStr mInit(mpVideoRecCtx, uScreen,2378 pszName, ulWidth, ulHeight, ulRate,2379 ulFPS, ulMaxTime,2380 ulMaxSize, com::Utf8Str(strOptions).c_str());2377 rc = VideoRecStreamInit(mpVideoRecCtx, uScreen, 2378 pszName, ulWidth, ulHeight, ulRate, 2379 ulFPS, ulMaxTime, 2380 ulMaxSize, com::Utf8Str(strOptions).c_str()); 2381 2381 } 2382 2382 } … … 2409 2409 if (VideoRecIsEnabled(mpVideoRecCtx)) 2410 2410 LogRel(("Display::VideoCaptureStop: WebM/VP8 video recording stopped\n")); 2411 VideoRecContext Close(mpVideoRecCtx);2411 VideoRecContextDestroy(mpVideoRecCtx); 2412 2412 mpVideoRecCtx = NULL; 2413 2413 … … 4394 4394 HRESULT hrc = pMachine->COMGETTER(VideoCaptureEnabled)(&fEnabled); 4395 4395 AssertComRCReturn(hrc, VERR_COM_UNEXPECTED); 4396 4397 #ifdef DEBUG_andy 4398 fEnabled = true; 4399 #endif 4400 4396 4401 if (fEnabled) 4397 4402 { -
trunk/src/VBox/Main/src-client/VideoRec.cpp
r65088 r65173 5 5 6 6 /* 7 * Copyright (C) 2012-201 6Oracle Corporation7 * Copyright (C) 2012-2017 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 17 17 18 18 #define LOG_GROUP LOG_GROUP_MAIN 19 20 #include <vector> 21 19 22 #include <VBox/log.h> 20 23 #include <iprt/asm.h> … … 35 38 #include <vpx/vpx_image.h> 36 39 37 /** Default VPX codec to use */40 /** Default VPX codec to use. */ 38 41 #define DEFAULTCODEC (vpx_codec_vp8_cx()) 39 42 … … 41 44 static int videoRecRGBToYUV(PVIDEORECSTREAM pStrm); 42 45 43 /* state to synchronized between threads */ 46 /** 47 * Enumeration for a video recording state. 48 */ 44 49 enum 45 50 { 51 /** Not initialized. */ 46 52 VIDREC_UNINITIALIZED = 0, 47 /* initialized, idle*/53 /** Initialized, idle. */ 48 54 VIDREC_IDLE = 1, 49 /* currently in VideoRecCopyToIntBuf(), delay termination*/55 /** Currently in VideoRecCopyToIntBuf(), delay termination. */ 50 56 VIDREC_COPYING = 2, 51 /* signal that we are terminating*/57 /** Signal that we are terminating. */ 52 58 VIDREC_TERMINATING = 3 53 59 }; … … 56 62 static uint32_t g_enmState = VIDREC_UNINITIALIZED; 57 63 58 64 /** 65 * Strucutre for maintaining a video recording stream. 66 */ 59 67 typedef struct VIDEORECSTREAM 60 68 { 61 /* container context*/62 WebMWriter Ebml;63 /* VPX codec context*/69 /** Container context. */ 70 WebMWriter *pEBML; 71 /** VPX codec context. */ 64 72 vpx_codec_ctx_t VpxCodec; 65 /* VPX configuration*/73 /** VPX configuration. */ 66 74 vpx_codec_enc_cfg_t VpxConfig; 67 /* X resolution*/75 /** Target X resolution (in pixels). */ 68 76 uint32_t uTargetWidth; 69 /* Y resolution*/77 /** Target Y resolution (in pixels). */ 70 78 uint32_t uTargetHeight; 71 /* X resolution of the last encoded picture*/79 /** X resolution of the last encoded frame. */ 72 80 uint32_t uLastSourceWidth; 73 /* Y resolution of the last encoded picture*/81 /** Y resolution of the last encoded frame. */ 74 82 uint32_t uLastSourceHeight; 75 /* current frame number*/76 uint 32_t cFrame;77 /* RGB buffer containing the most recent frame of the framebuffer*/78 uint8_t 79 /* YUV buffer the encode function fetches the frame from*/80 uint8_t 81 /* VPX image context*/83 /** Current frame number. */ 84 uint64_t cFrame; 85 /** RGB buffer containing the most recent frame of the framebuffer. */ 86 uint8_t *pu8RgbBuf; 87 /** YUV buffer the encode function fetches the frame from. */ 88 uint8_t *pu8YuvBuf; 89 /** VPX image context. */ 82 90 vpx_image_t VpxRawImage; 83 /* true if video recording is enabled*/91 /** Whether video recording is enabled or not. */ 84 92 bool fEnabled; 85 /* true if the RGB buffer is filled*/93 /** Whether the RGB buffer is filled or not. */ 86 94 bool fRgbFilled; 87 /* pixel format of the current frame*/95 /** Pixel format of the current frame. */ 88 96 uint32_t u32PixelFormat; 89 /* minimal delay between two frames*/97 /** Minimal delay between two frames. */ 90 98 uint32_t uDelay; 91 /* time stamp of the last frame we encoded*/99 /** Time stamp of the last frame we encoded. */ 92 100 uint64_t u64LastTimeStamp; 93 /* time stamp of the current frame*/101 /** Time stamp of the current frame. */ 94 102 uint64_t u64TimeStamp; 95 /* encoder deadline*/103 /** Encoder deadline. */ 96 104 unsigned int uEncoderDeadline; 97 } VIDEORECSTREAM; 98 105 } VIDEORECSTREAM, *PVIDEORECSTREAM; 106 107 /** Vector of video recording streams. */ 108 typedef std::vector <PVIDEORECSTREAM> VideoRecStreams; 109 110 /** 111 * Structure for keeping a video recording context. 112 */ 99 113 typedef struct VIDEORECCONTEXT 100 114 { 101 /* semaphore to signal the encoding worker thread*/115 /** Semaphore to signal the encoding worker thread. */ 102 116 RTSEMEVENT WaitEvent; 103 /* semaphore required during termination*/117 /** Semaphore required during termination. */ 104 118 RTSEMEVENT TermEvent; 105 /* true if video recording is enabled*/119 /** Whether video recording is enabled or not. */ 106 120 bool fEnabled; 107 /* worker thread*/121 /** Worker thread. */ 108 122 RTTHREAD Thread; 109 /* number of stream contexts */123 /** Number of stream contexts */ 110 124 uint32_t cScreens; 111 /* maximal time stamp*/125 /** Maximal time stamp. */ 112 126 uint64_t u64MaxTimeStamp; 113 /* maximal file size in MB*/127 /** Maximal file size in MB. */ 114 128 uint32_t uMaxFileSize; 115 /* video recording stream contexts*/116 V IDEORECSTREAM Strm[1];117 } VIDEORECCONTEXT ;129 /** Vector of current video recording stream contexts. */ 130 VideoRecStreams lstStreams; 131 } VIDEORECCONTEXT, *PVIDEORECCONTEXT; 118 132 119 133 … … 382 396 383 397 /** 384 * Worker thread for all streams .385 * 386 * RGB/YUV conversion and encoding.398 * Worker thread for all streams of a video recording context. 399 * 400 * Does RGB/YUV conversion and encoding. 387 401 */ 388 402 static DECLCALLBACK(int) videoRecThread(RTTHREAD hThreadSelf, void *pvUser) … … 397 411 if (ASMAtomicReadU32(&g_enmState) == VIDREC_TERMINATING) 398 412 break; 399 for (unsigned uScreen = 0; uScreen < pCtx->cScreens; uScreen++) 400 { 401 PVIDEORECSTREAM pStrm = &pCtx->Strm[uScreen]; 402 if ( pStrm->fEnabled 403 && ASMAtomicReadBool(&pStrm->fRgbFilled)) 413 414 for (VideoRecStreams::iterator it = pCtx->lstStreams.begin(); it != pCtx->lstStreams.end(); it++) 415 { 416 PVIDEORECSTREAM pStream = (*it); 417 418 if ( pStream->fEnabled 419 && ASMAtomicReadBool(&pStream->fRgbFilled)) 404 420 { 405 rc = videoRecRGBToYUV(pStrm); 406 ASMAtomicWriteBool(&pStrm->fRgbFilled, false); 421 rc = videoRecRGBToYUV(pStream); 422 423 ASMAtomicWriteBool(&pStream->fRgbFilled, false); 424 407 425 if (RT_SUCCESS(rc)) 408 rc = videoRecEncodeAndWrite(pStrm); 426 rc = videoRecEncodeAndWrite(pStream); 427 409 428 if (RT_FAILURE(rc)) 410 429 { … … 424 443 425 444 /** 426 * VideoRec utility function to createvideo recording context.445 * Creates a video recording context. 427 446 * 428 447 * @returns IPRT status code. 429 * @param ppCtx Video recording context 430 * @param cScreens Number of screens. 431 */ 432 int VideoRecContextCreate(PVIDEORECCONTEXT *ppCtx, uint32_t cScreens) 433 { 448 * @param cScreens Number of screens to create context for. 449 * @param ppCtx Pointer to created video recording context on success. 450 */ 451 int VideoRecContextCreate(uint32_t cScreens, PVIDEORECCONTEXT *ppCtx) 452 { 453 AssertReturn(cScreens, VERR_INVALID_PARAMETER); 454 AssertPtrReturn(ppCtx, VERR_INVALID_POINTER); 455 434 456 Assert(ASMAtomicReadU32(&g_enmState) == VIDREC_UNINITIALIZED); 435 457 436 PVIDEORECCONTEXT pCtx = (PVIDEORECCONTEXT)RTMemAllocZ(RT_OFFSETOF(VIDEORECCONTEXT, Strm[cScreens])); 437 *ppCtx = pCtx; 438 AssertPtrReturn(pCtx, VERR_NO_MEMORY); 439 440 pCtx->cScreens = cScreens; 441 for (unsigned uScreen = 0; uScreen < cScreens; uScreen++) 442 { 443 /* Since we allocate without using standard C++ new mechanism 444 * it is required to call placement new for correct initialization 445 * of the object. */ 446 new (&pCtx->Strm[uScreen] + RT_OFFSETOF(VIDEORECSTREAM, Ebml)) WebMWriter(); 447 } 448 449 int rc = RTSemEventCreate(&pCtx->WaitEvent); 450 AssertRCReturn(rc, rc); 451 452 rc = RTSemEventCreate(&pCtx->TermEvent); 453 AssertRCReturn(rc, rc); 454 455 rc = RTThreadCreate(&pCtx->Thread, videoRecThread, (void*)pCtx, 0, 456 RTTHREADTYPE_MAIN_WORKER, RTTHREADFLAGS_WAITABLE, "VideoRec"); 457 AssertRCReturn(rc, rc); 458 459 ASMAtomicWriteU32(&g_enmState, VIDREC_IDLE); 460 return VINF_SUCCESS; 458 int rc = VINF_SUCCESS; 459 460 PVIDEORECCONTEXT pCtx = (PVIDEORECCONTEXT)RTMemAllocZ(sizeof(VIDEORECCONTEXT)); 461 if (!pCtx) 462 return VERR_NO_MEMORY; 463 464 for (uint32_t uScreen = 0; uScreen < cScreens; uScreen++) 465 { 466 PVIDEORECSTREAM pStream = (PVIDEORECSTREAM)RTMemAllocZ(sizeof(VIDEORECSTREAM)); 467 if (!pStream) 468 { 469 rc = VERR_NO_MEMORY; 470 break; 471 } 472 473 try 474 { 475 pCtx->lstStreams.push_back(pStream); 476 477 pStream->pEBML = new WebMWriter(); 478 } 479 catch (std::bad_alloc) 480 { 481 rc = VERR_NO_MEMORY; 482 break; 483 } 484 } 485 486 if (RT_SUCCESS(rc)) 487 { 488 pCtx->cScreens = cScreens; 489 490 rc = RTSemEventCreate(&pCtx->WaitEvent); 491 AssertRCReturn(rc, rc); 492 493 rc = RTSemEventCreate(&pCtx->TermEvent); 494 AssertRCReturn(rc, rc); 495 496 rc = RTThreadCreate(&pCtx->Thread, videoRecThread, (void*)pCtx, 0, 497 RTTHREADTYPE_MAIN_WORKER, RTTHREADFLAGS_WAITABLE, "VideoRec"); 498 AssertRCReturn(rc, rc); 499 500 ASMAtomicWriteU32(&g_enmState, VIDREC_IDLE); 501 502 if (ppCtx) 503 *ppCtx = pCtx; 504 } 505 else 506 { 507 /* Roll back allocations on error. */ 508 VideoRecStreams::iterator it = pCtx->lstStreams.begin(); 509 while (it != pCtx->lstStreams.end()) 510 { 511 PVIDEORECSTREAM pStream = (*it); 512 513 if (pStream->pEBML) 514 delete pStream->pEBML; 515 516 RTMemFree(pStream); 517 pStream = NULL; 518 519 it = pCtx->lstStreams.erase(it); 520 } 521 522 Assert(pCtx->lstStreams.empty()); 523 } 524 525 return rc; 526 } 527 528 /** 529 * Destroys a video recording context. 530 * 531 * @param pCtx Video recording context to destroy. 532 */ 533 void VideoRecContextDestroy(PVIDEORECCONTEXT pCtx) 534 { 535 if (!pCtx) 536 return; 537 538 uint32_t enmState = VIDREC_IDLE; 539 540 for (;;) /** @todo r=andy Remove busy waiting! */ 541 { 542 if (ASMAtomicCmpXchgExU32(&g_enmState, VIDREC_TERMINATING, enmState, &enmState)) 543 break; 544 if (enmState == VIDREC_UNINITIALIZED) 545 return; 546 } 547 548 if (enmState == VIDREC_COPYING) 549 { 550 int rc = RTSemEventWait(pCtx->TermEvent, RT_INDEFINITE_WAIT); 551 AssertRC(rc); 552 } 553 554 RTSemEventSignal(pCtx->WaitEvent); 555 RTThreadWait(pCtx->Thread, 10 * 1000, NULL); 556 RTSemEventDestroy(pCtx->WaitEvent); 557 RTSemEventDestroy(pCtx->TermEvent); 558 559 for (VideoRecStreams::iterator it = pCtx->lstStreams.begin(); it != pCtx->lstStreams.end(); it++) 560 { 561 PVIDEORECSTREAM pStream = (*it); 562 563 if (pStream->fEnabled) 564 { 565 AssertPtr(pStream->pEBML); 566 int rc = pStream->pEBML->writeFooter(0); 567 AssertRC(rc); 568 569 pStream->pEBML->close(); 570 571 vpx_img_free(&pStream->VpxRawImage); 572 vpx_codec_err_t rcv = vpx_codec_destroy(&pStream->VpxCodec); 573 Assert(rcv == VPX_CODEC_OK); RT_NOREF(rcv); 574 575 if (pStream->pu8RgbBuf) 576 { 577 RTMemFree(pStream->pu8RgbBuf); 578 pStream->pu8RgbBuf = NULL; 579 } 580 } 581 582 delete pStream->pEBML; 583 } 584 585 RTMemFree(pCtx); 586 587 ASMAtomicWriteU32(&g_enmState, VIDREC_UNINITIALIZED); 461 588 } 462 589 … … 476 603 * @param pszOptions 477 604 */ 478 int VideoRecStr mInit(PVIDEORECCONTEXT pCtx, uint32_t uScreen, const char *pszFile,479 uint32_t uWidth, uint32_t uHeight, uint32_t uRate, uint32_t uFps,480 uint32_t uMaxTime, uint32_t uMaxFileSize, const char *pszOptions)481 { 482 AssertPtrReturn(pCtx, VERR_INVALID_PARAMETER);605 int VideoRecStreamInit(PVIDEORECCONTEXT pCtx, uint32_t uScreen, const char *pszFile, 606 uint32_t uWidth, uint32_t uHeight, uint32_t uRate, uint32_t uFps, 607 uint32_t uMaxTime, uint32_t uMaxFileSize, const char *pszOptions) 608 { 609 AssertPtrReturn(pCtx, VERR_INVALID_PARAMETER); 483 610 AssertReturn(uScreen < pCtx->cScreens, VERR_INVALID_PARAMETER); 484 611 … … 486 613 pCtx->uMaxFileSize = uMaxFileSize; 487 614 488 PVIDEORECSTREAM pStrm = &pCtx->Strm[uScreen]; 489 pStrm->uTargetWidth = uWidth; 490 pStrm->uTargetHeight = uHeight; 491 pStrm->pu8RgbBuf = (uint8_t *)RTMemAllocZ(uWidth * uHeight * 4); 492 AssertReturn(pStrm->pu8RgbBuf, VERR_NO_MEMORY); 493 pStrm->uEncoderDeadline = VPX_DL_REALTIME; 615 PVIDEORECSTREAM pStream = pCtx->lstStreams.at(uScreen); 616 617 pStream->uTargetWidth = uWidth; 618 pStream->uTargetHeight = uHeight; 619 pStream->pu8RgbBuf = (uint8_t *)RTMemAllocZ(uWidth * uHeight * 4); 620 AssertReturn(pStream->pu8RgbBuf, VERR_NO_MEMORY); 621 pStream->uEncoderDeadline = VPX_DL_REALTIME; 494 622 495 623 /* Play safe: the file must not exist, overwriting is potentially … … 497 625 * other important file, causing unintentional data loss. */ 498 626 499 int rc = pStr m->Ebml.create(pszFile);627 int rc = pStream->pEBML->create(pszFile); 500 628 if (RT_FAILURE(rc)) 501 629 { … … 504 632 } 505 633 506 vpx_codec_err_t rcv = vpx_codec_enc_config_default(DEFAULTCODEC, &pStr m->VpxConfig, 0);634 vpx_codec_err_t rcv = vpx_codec_enc_config_default(DEFAULTCODEC, &pStream->VpxConfig, 0); 507 635 if (rcv != VPX_CODEC_OK) 508 636 { … … 523 651 if (value == "realtime") 524 652 { 525 pStr m->uEncoderDeadline = VPX_DL_REALTIME;653 pStream->uEncoderDeadline = VPX_DL_REALTIME; 526 654 } 527 655 else if (value == "good") 528 656 { 529 pStr m->uEncoderDeadline = 1000000 / uFps;657 pStream->uEncoderDeadline = 1000000 / uFps; 530 658 } 531 659 else if (value == "best") 532 660 { 533 pStr m->uEncoderDeadline = VPX_DL_BEST_QUALITY;661 pStream->uEncoderDeadline = VPX_DL_BEST_QUALITY; 534 662 } 535 663 else 536 664 { 537 665 LogRel(("Settings quality deadline to = %s\n", value.c_str())); 538 pStr m->uEncoderDeadline = value.toUInt32();666 pStream->uEncoderDeadline = value.toUInt32(); 539 667 } 540 668 } … … 544 672 545 673 /* target bitrate in kilobits per second */ 546 pStr m->VpxConfig.rc_target_bitrate = uRate;674 pStream->VpxConfig.rc_target_bitrate = uRate; 547 675 /* frame width */ 548 pStr m->VpxConfig.g_w = uWidth;676 pStream->VpxConfig.g_w = uWidth; 549 677 /* frame height */ 550 pStr m->VpxConfig.g_h = uHeight;678 pStream->VpxConfig.g_h = uHeight; 551 679 /* 1ms per frame */ 552 pStr m->VpxConfig.g_timebase.num = 1;553 pStr m->VpxConfig.g_timebase.den = 1000;680 pStream->VpxConfig.g_timebase.num = 1; 681 pStream->VpxConfig.g_timebase.den = 1000; 554 682 /* disable multithreading */ 555 pStr m->VpxConfig.g_threads = 0;556 557 pStr m->uDelay = 1000 / uFps;683 pStream->VpxConfig.g_threads = 0; 684 685 pStream->uDelay = 1000 / uFps; 558 686 559 687 struct vpx_rational arg_framerate = { (int)uFps, 1 }; 560 rc = pStr m->Ebml.writeHeader(&pStrm->VpxConfig, &arg_framerate);688 rc = pStream->pEBML->writeHeader(&pStream->VpxConfig, &arg_framerate); 561 689 AssertRCReturn(rc, rc); 562 690 563 691 /* Initialize codec */ 564 rcv = vpx_codec_enc_init(&pStr m->VpxCodec, DEFAULTCODEC, &pStrm->VpxConfig, 0);692 rcv = vpx_codec_enc_init(&pStream->VpxCodec, DEFAULTCODEC, &pStream->VpxConfig, 0); 565 693 if (rcv != VPX_CODEC_OK) 566 694 { … … 569 697 } 570 698 571 if (!vpx_img_alloc(&pStr m->VpxRawImage, VPX_IMG_FMT_I420, uWidth, uHeight, 1))699 if (!vpx_img_alloc(&pStream->VpxRawImage, VPX_IMG_FMT_I420, uWidth, uHeight, 1)) 572 700 { 573 701 LogFlow(("Failed to allocate image %dx%d", uWidth, uHeight)); 574 702 return VERR_NO_MEMORY; 575 703 } 576 pStr m->pu8YuvBuf = pStrm->VpxRawImage.planes[0];704 pStream->pu8YuvBuf = pStream->VpxRawImage.planes[0]; 577 705 578 706 pCtx->fEnabled = true; 579 pStr m->fEnabled = true;707 pStream->fEnabled = true; 580 708 return VINF_SUCCESS; 581 709 } 582 710 583 711 /** 584 * VideoRec utility function to close the video recording context.585 *586 * @param pCtx Pointer to video recording context.587 */588 void VideoRecContextClose(PVIDEORECCONTEXT pCtx)589 {590 if (!pCtx)591 return;592 593 uint32_t enmState = VIDREC_IDLE;594 for (;;)595 {596 if (ASMAtomicCmpXchgExU32(&g_enmState, VIDREC_TERMINATING, enmState, &enmState))597 break;598 if (enmState == VIDREC_UNINITIALIZED)599 return;600 }601 if (enmState == VIDREC_COPYING)602 {603 int rc = RTSemEventWait(pCtx->TermEvent, RT_INDEFINITE_WAIT);604 AssertRC(rc);605 }606 607 RTSemEventSignal(pCtx->WaitEvent);608 RTThreadWait(pCtx->Thread, 10000, NULL);609 RTSemEventDestroy(pCtx->WaitEvent);610 RTSemEventDestroy(pCtx->TermEvent);611 612 for (unsigned uScreen = 0; uScreen < pCtx->cScreens; uScreen++)613 {614 PVIDEORECSTREAM pStrm = &pCtx->Strm[uScreen];615 if (pStrm->fEnabled)616 {617 int rc = pStrm->Ebml.writeFooter(0);618 AssertRC(rc);619 pStrm->Ebml.close();620 vpx_img_free(&pStrm->VpxRawImage);621 vpx_codec_err_t rcv = vpx_codec_destroy(&pStrm->VpxCodec);622 Assert(rcv == VPX_CODEC_OK); RT_NOREF(rcv);623 RTMemFree(pStrm->pu8RgbBuf);624 pStrm->pu8RgbBuf = NULL;625 }626 /* Explicitly deinitilize Ebml object since it was created using placement new. */627 pStrm->Ebml.~WebMWriter();628 }629 630 RTMemFree(pCtx);631 632 ASMAtomicWriteU32(&g_enmState, VIDREC_UNINITIALIZED);633 }634 635 /**636 712 * VideoRec utility function to check if recording is enabled. 637 713 * 638 714 * @returns true if recording is enabled 639 * @param pCtx Pointer to video recording context.715 * @param pCtx Pointer to video recording context. 640 716 */ 641 717 bool VideoRecIsEnabled(PVIDEORECCONTEXT pCtx) … … 652 728 * 653 729 * @returns true if recording engine is ready 654 * @param pCtx Pointer to video recording context.655 * @param uScreen screen id.656 * @param u64TimeStamp current time stamp730 * @param pCtx Pointer to video recording context. 731 * @param uScreen Screen ID. 732 * @param u64TimeStamp Current time stamp. 657 733 */ 658 734 bool VideoRecIsReady(PVIDEORECCONTEXT pCtx, uint32_t uScreen, uint64_t u64TimeStamp) … … 662 738 return false; 663 739 664 PVIDEORECSTREAM pStr m = &pCtx->Strm[uScreen];665 if (!pStr m->fEnabled)740 PVIDEORECSTREAM pStream = pCtx->lstStreams.at(uScreen); 741 if (!pStream->fEnabled) 666 742 return false; 667 743 668 if (u64TimeStamp < pStr m->u64LastTimeStamp + pStrm->uDelay)744 if (u64TimeStamp < pStream->u64LastTimeStamp + pStream->uDelay) 669 745 return false; 670 746 671 if (ASMAtomicReadBool(&pStr m->fRgbFilled))747 if (ASMAtomicReadBool(&pStream->fRgbFilled)) 672 748 return false; 673 749 … … 679 755 * specified limits (if any). 680 756 * 681 * @returns true if any limit has been reached 682 * @param pCtx Pointer to video recording context683 * @param uScreen screen id684 * @param u64TimeStamp current time stamp757 * @returns true if any limit has been reached. 758 * @param pCtx Pointer to video recording context. 759 * @param uScreen Screen ID. 760 * @param u64TimeStamp Current time stamp. 685 761 */ 686 762 687 763 bool VideoRecIsFull(PVIDEORECCONTEXT pCtx, uint32_t uScreen, uint64_t u64TimeStamp) 688 764 { 689 PVIDEORECSTREAM pStr m = &pCtx->Strm[uScreen];690 if(!pStr m->fEnabled)765 PVIDEORECSTREAM pStream = pCtx->lstStreams.at(uScreen); 766 if(!pStream->fEnabled) 691 767 return false; 692 768 … … 696 772 if (pCtx->uMaxFileSize > 0) 697 773 { 698 uint64_t sizeInMB = pStr m->Ebml.getFileSize() / (1024 * 1024);774 uint64_t sizeInMB = pStream->pEBML->getFileSize() / (1024 * 1024); 699 775 if(sizeInMB >= pCtx->uMaxFileSize) 700 776 return true; 701 777 } 702 778 /* Check for available free disk space */ 703 if (pStr m->Ebml.getAvailableSpace() < 0x100000)779 if (pStream->pEBML->getAvailableSpace() < 0x100000) 704 780 { 705 781 LogRel(("Storage has not enough free space available, stopping video capture\n")); … … 715 791 * 716 792 * @returns IPRT status code. 717 * @param pStr m Stream.718 */ 719 static int videoRecEncodeAndWrite(PVIDEORECSTREAM pStr m)793 * @param pStream Stream to encode and write. 794 */ 795 static int videoRecEncodeAndWrite(PVIDEORECSTREAM pStream) 720 796 { 721 797 /* presentation time stamp */ 722 vpx_codec_pts_t pts = pStr m->u64TimeStamp;723 vpx_codec_err_t rcv = vpx_codec_encode(&pStr m->VpxCodec,724 &pStr m->VpxRawImage,798 vpx_codec_pts_t pts = pStream->u64TimeStamp; 799 vpx_codec_err_t rcv = vpx_codec_encode(&pStream->VpxCodec, 800 &pStream->VpxRawImage, 725 801 pts /* time stamp */, 726 pStr m->uDelay /* how long to show this frame */,802 pStream->uDelay /* how long to show this frame */, 727 803 0 /* flags */, 728 pStr m->uEncoderDeadline /* quality setting */);804 pStream->uEncoderDeadline /* quality setting */); 729 805 if (rcv != VPX_CODEC_OK) 730 806 { … … 737 813 for (;;) 738 814 { 739 const vpx_codec_cx_pkt_t *pkt = vpx_codec_get_cx_data(&pStr m->VpxCodec, &iter);815 const vpx_codec_cx_pkt_t *pkt = vpx_codec_get_cx_data(&pStream->VpxCodec, &iter); 740 816 if (!pkt) 741 817 break; … … 743 819 { 744 820 case VPX_CODEC_CX_FRAME_PKT: 745 rc = pStr m->Ebml.writeBlock(&pStrm->VpxConfig, pkt);821 rc = pStream->pEBML->writeBlock(&pStream->VpxConfig, pkt); 746 822 break; 747 823 default: … … 751 827 } 752 828 753 pStr m->cFrame++;829 pStream->cFrame++; 754 830 return rc; 755 831 } … … 831 907 AssertBreakStmt(uScreen < pCtx->cScreens, rc = VERR_INVALID_PARAMETER); 832 908 833 PVIDEORECSTREAM pStr m = &pCtx->Strm[uScreen];834 if (!pStr m->fEnabled)909 PVIDEORECSTREAM pStream = pCtx->lstStreams.at(uScreen); 910 if (!pStream->fEnabled) 835 911 { 836 912 rc = VINF_TRY_AGAIN; /* not (yet) enabled */ 837 913 break; 838 914 } 839 if (u64TimeStamp < pStr m->u64LastTimeStamp + pStrm->uDelay)915 if (u64TimeStamp < pStream->u64LastTimeStamp + pStream->uDelay) 840 916 { 841 917 rc = VINF_TRY_AGAIN; /* respect maximum frames per second */ 842 918 break; 843 919 } 844 if (ASMAtomicReadBool(&pStr m->fRgbFilled))920 if (ASMAtomicReadBool(&pStream->fRgbFilled)) 845 921 { 846 922 rc = VERR_TRY_AGAIN; /* previous frame not yet encoded */ … … 848 924 } 849 925 850 pStr m->u64LastTimeStamp = u64TimeStamp;851 852 int xDiff = ((int)pStr m->uTargetWidth - (int)uSourceWidth) / 2;926 pStream->u64LastTimeStamp = u64TimeStamp; 927 928 int xDiff = ((int)pStream->uTargetWidth - (int)uSourceWidth) / 2; 853 929 uint32_t w = uSourceWidth; 854 930 if ((int)w + xDiff + (int)x <= 0) /* nothing visible */ … … 869 945 870 946 uint32_t h = uSourceHeight; 871 int yDiff = ((int)pStr m->uTargetHeight - (int)uSourceHeight) / 2;947 int yDiff = ((int)pStream->uTargetHeight - (int)uSourceHeight) / 2; 872 948 if ((int)h + yDiff + (int)y <= 0) /* nothing visible */ 873 949 { … … 886 962 destY = y + yDiff; 887 963 888 if ( destX > pStr m->uTargetWidth889 || destY > pStr m->uTargetHeight)964 if ( destX > pStream->uTargetWidth 965 || destY > pStream->uTargetHeight) 890 966 { 891 967 rc = VERR_INVALID_PARAMETER; /* nothing visible */ … … 893 969 } 894 970 895 if (destX + w > pStr m->uTargetWidth)896 w = pStr m->uTargetWidth - destX;897 898 if (destY + h > pStr m->uTargetHeight)899 h = pStr m->uTargetHeight - destY;971 if (destX + w > pStream->uTargetWidth) 972 w = pStream->uTargetWidth - destX; 973 974 if (destY + h > pStream->uTargetHeight) 975 h = pStream->uTargetHeight - destY; 900 976 901 977 /* Calculate bytes per pixel */ … … 906 982 { 907 983 case 32: 908 pStr m->u32PixelFormat = VPX_IMG_FMT_RGB32;984 pStream->u32PixelFormat = VPX_IMG_FMT_RGB32; 909 985 bpp = 4; 910 986 break; 911 987 case 24: 912 pStr m->u32PixelFormat = VPX_IMG_FMT_RGB24;988 pStream->u32PixelFormat = VPX_IMG_FMT_RGB24; 913 989 bpp = 3; 914 990 break; 915 991 case 16: 916 pStr m->u32PixelFormat = VPX_IMG_FMT_RGB565;992 pStream->u32PixelFormat = VPX_IMG_FMT_RGB565; 917 993 bpp = 2; 918 994 break; … … 927 1003 /* One of the dimensions of the current frame is smaller than before so 928 1004 * clear the entire buffer to prevent artifacts from the previous frame */ 929 if ( uSourceWidth < pStr m->uLastSourceWidth930 || uSourceHeight < pStr m->uLastSourceHeight)931 memset(pStr m->pu8RgbBuf, 0, pStrm->uTargetWidth * pStrm->uTargetHeight * 4);932 933 pStr m->uLastSourceWidth = uSourceWidth;934 pStr m->uLastSourceHeight = uSourceHeight;1005 if ( uSourceWidth < pStream->uLastSourceWidth 1006 || uSourceHeight < pStream->uLastSourceHeight) 1007 memset(pStream->pu8RgbBuf, 0, pStream->uTargetWidth * pStream->uTargetHeight * 4); 1008 1009 pStream->uLastSourceWidth = uSourceWidth; 1010 pStream->uLastSourceHeight = uSourceHeight; 935 1011 936 1012 /* Calculate start offset in source and destination buffers */ 937 1013 uint32_t offSrc = y * uBytesPerLine + x * bpp; 938 uint32_t offDst = (destY * pStr m->uTargetWidth + destX) * bpp;1014 uint32_t offDst = (destY * pStream->uTargetWidth + destX) * bpp; 939 1015 /* do the copy */ 940 1016 for (unsigned int i = 0; i < h; i++) … … 942 1018 /* Overflow check */ 943 1019 Assert(offSrc + w * bpp <= uSourceHeight * uBytesPerLine); 944 Assert(offDst + w * bpp <= pStr m->uTargetHeight * pStrm->uTargetWidth * bpp);945 memcpy(pStr m->pu8RgbBuf + offDst, pu8BufAddr + offSrc, w * bpp);1020 Assert(offDst + w * bpp <= pStream->uTargetHeight * pStream->uTargetWidth * bpp); 1021 memcpy(pStream->pu8RgbBuf + offDst, pu8BufAddr + offSrc, w * bpp); 946 1022 offSrc += uBytesPerLine; 947 offDst += pStr m->uTargetWidth * bpp;948 } 949 950 pStr m->u64TimeStamp = u64TimeStamp;951 952 ASMAtomicWriteBool(&pStr m->fRgbFilled, true);1023 offDst += pStream->uTargetWidth * bpp; 1024 } 1025 1026 pStream->u64TimeStamp = u64TimeStamp; 1027 1028 ASMAtomicWriteBool(&pStream->fRgbFilled, true); 953 1029 RTSemEventSignal(pCtx->WaitEvent); 954 1030 } while (0); -
trunk/src/VBox/Main/src-client/VideoRec.h
r62485 r65173 5 5 6 6 /* 7 * Copyright (C) 2012-201 6Oracle Corporation7 * Copyright (C) 2012-2017 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 25 25 typedef struct VIDEORECSTREAM *PVIDEORECSTREAM; 26 26 27 int VideoRecContextCreate(PVIDEORECCONTEXT *ppCtx, uint32_t cScreens); 28 int VideoRecStrmInit(PVIDEORECCONTEXT pCtx, uint32_t uScreen, const char *pszFile, 29 uint32_t uWidth, uint32_t uHeight, uint32_t uRate, uint32_t uFps, 30 uint32_t uMaxTime, uint32_t uMaxFileSize, const char *pszOptions); 31 void VideoRecContextClose(PVIDEORECCONTEXT pCtx); 27 int VideoRecContextCreate(uint32_t cScreens, PVIDEORECCONTEXT *ppCtx); 28 void VideoRecContextDestroy(PVIDEORECCONTEXT pCtx); 29 30 int VideoRecStreamInit(PVIDEORECCONTEXT pCtx, uint32_t uScreen, const char *pszFile, 31 uint32_t uWidth, uint32_t uHeight, uint32_t uRate, uint32_t uFps, 32 uint32_t uMaxTime, uint32_t uMaxFileSize, const char *pszOptions); 33 32 34 bool VideoRecIsEnabled(PVIDEORECCONTEXT pCtx); 33 35 int VideoRecCopyToIntBuf(PVIDEORECCONTEXT pCtx, uint32_t uScreen,
Note:
See TracChangeset
for help on using the changeset viewer.