vbox的更動 46549 路徑 trunk/src/VBox/Main/src-client/VideoRec.cpp
- 時間撮記:
- 2013-6-14 上午10:08:20 (11 年 以前)
- 檔案:
-
- 修改 1 筆資料
圖例:
- 未更動
- 新增
- 刪除
-
trunk/src/VBox/Main/src-client/VideoRec.cpp
r45962 r46549 40 40 static int videoRecRGBToYUV(PVIDEORECSTREAM pStrm); 41 41 42 /* encoding*/42 /* state to synchronized between threads */ 43 43 enum 44 44 { 45 45 VIDREC_UNINITIALIZED = 0, 46 /* initialized */ 47 VIDREC_INITIALIZED = 1, 46 /* initialized, idle */ 47 VIDREC_IDLE = 1, 48 /* currently in VideoRecCopyToIntBuf(), delay termination */ 49 VIDREC_COPYING = 2, 48 50 /* signal that we are terminating */ 49 VIDREC_TERMINATING = 2, 50 /* confirmation that the worker thread terminated */ 51 VIDREC_TERMINATED = 3 51 VIDREC_TERMINATING = 2 52 52 }; 53 static uint32_t g_enmState = VIDREC_UNINITIALIZED; 54 53 55 54 56 typedef struct VIDEORECSTREAM … … 92 94 typedef struct VIDEORECCONTEXT 93 95 { 94 /* semaphore */96 /* semaphore to signal the encoding worker thread */ 95 97 RTSEMEVENT WaitEvent; 98 /* semaphore required during termination */ 99 RTSEMEVENT TermEvent; 96 100 /* true if video recording is enabled */ 97 101 bool fEnabled; 98 102 /* worker thread */ 99 103 RTTHREAD Thread; 100 /* see VIDREC_xxx */101 uint32_t uState;102 104 /* number of stream contexts */ 103 105 uint32_t cScreens; … … 387 389 AssertRCBreak(rc); 388 390 389 if (ASMAtomicReadU32(& pCtx->uState) == VIDREC_TERMINATING)391 if (ASMAtomicReadU32(&g_enmState) == VIDREC_TERMINATING) 390 392 break; 391 393 for (unsigned uScreen = 0; uScreen < pCtx->cScreens; uScreen++) … … 411 413 } 412 414 413 ASMAtomicWriteU32(&pCtx->uState, VIDREC_TERMINATED);414 415 return VINF_SUCCESS; 415 416 } … … 424 425 int VideoRecContextCreate(PVIDEORECCONTEXT *ppCtx, uint32_t cScreens) 425 426 { 427 Assert(ASMAtomicReadU32(&g_enmState) == VIDREC_UNINITIALIZED); 428 426 429 PVIDEORECCONTEXT pCtx = (PVIDEORECCONTEXT)RTMemAllocZ(RT_OFFSETOF(VIDEORECCONTEXT, Strm[cScreens])); 427 430 *ppCtx = pCtx; … … 435 438 AssertRCReturn(rc, rc); 436 439 440 rc = RTSemEventCreate(&pCtx->TermEvent); 441 AssertRCReturn(rc, rc); 442 437 443 rc = RTThreadCreate(&pCtx->Thread, videoRecThread, (void*)pCtx, 0, 438 444 RTTHREADTYPE_MAIN_WORKER, RTTHREADFLAGS_WAITABLE, "VideoRec"); 439 445 AssertRCReturn(rc, rc); 440 446 441 ASMAtomicWriteU32(& pCtx->uState, VIDREC_INITIALIZED);447 ASMAtomicWriteU32(&g_enmState, VIDREC_IDLE); 442 448 return VINF_SUCCESS; 443 449 } … … 527 533 return; 528 534 529 if (ASMAtomicReadU32(&pCtx->uState) != VIDREC_INITIALIZED) 530 return; 531 532 ASMAtomicWriteU32(&pCtx->uState, VIDREC_TERMINATING); 535 uint32_t enmState = VIDREC_IDLE; 536 for (;;) 537 { 538 if (ASMAtomicCmpXchgExU32(&g_enmState, VIDREC_TERMINATING, enmState, &enmState)) 539 break; 540 if (enmState == VIDREC_UNINITIALIZED) 541 return; 542 } 543 if (enmState == VIDREC_COPYING) 544 { 545 int rc = RTSemEventWait(pCtx->TermEvent, RT_INDEFINITE_WAIT); 546 AssertRC(rc); 547 } 548 533 549 RTSemEventSignal(pCtx->WaitEvent); 534 550 RTThreadWait(pCtx->Thread, 10000, NULL); 535 551 RTSemEventDestroy(pCtx->WaitEvent); 552 RTSemEventDestroy(pCtx->TermEvent); 536 553 537 554 for (unsigned uScreen = 0; uScreen < pCtx->cScreens; uScreen++) … … 560 577 } 561 578 562 ASMAtomicWriteU32(&pCtx->uState, VIDREC_UNINITIALIZED); 579 RTMemFree(pCtx); 580 581 ASMAtomicWriteU32(&g_enmState, VIDREC_UNINITIALIZED); 563 582 } 564 583 … … 665 684 666 685 /** 667 * VideoRec utility function to copy source image (FrameBuf) to 668 * intermediate RGB buffer. 686 * VideoRec utility function to copy a source image (FrameBuf) to the intermediate 687 * RGB buffer. This function is executed only once per time. 688 * 689 * @thread EMT 669 690 * 670 691 * @returns IPRT status code. … … 686 707 uint64_t u64TimeStamp) 687 708 { 688 AssertPtrReturn(pu8BufAddr, VERR_INVALID_PARAMETER); 689 AssertReturn(uSourceWidth, VERR_INVALID_PARAMETER); 690 AssertReturn(uSourceHeight, VERR_INVALID_PARAMETER); 691 AssertReturn(uScreen < pCtx->cScreens, VERR_INVALID_PARAMETER); 692 AssertReturn(pCtx->uState == VIDREC_INITIALIZED, VERR_INVALID_STATE); 693 694 PVIDEORECSTREAM pStrm = &pCtx->Strm[uScreen]; 695 696 if (u64TimeStamp < pStrm->u64LastTimeStamp + pStrm->uDelay) 697 return VINF_TRY_AGAIN; /* respect maximum frames per second */ 698 699 if (ASMAtomicReadBool(&pStrm->fRgbFilled)) 700 return VERR_TRY_AGAIN; /* previous frame not yet encoded */ 701 702 pStrm->u64LastTimeStamp = u64TimeStamp; 703 704 int xDiff = ((int)pStrm->uTargetWidth - (int)uSourceWidth) / 2; 705 uint32_t w = uSourceWidth; 706 if ((int)w + xDiff + (int)x <= 0) /* nothing visible */ 707 return VERR_INVALID_PARAMETER; 708 709 uint32_t destX; 710 if ((int)x < -xDiff) 711 { 712 w += xDiff + x; 713 x = -xDiff; 714 destX = 0; 715 } 716 else 717 destX = x + xDiff; 718 719 uint32_t h = uSourceHeight; 720 int yDiff = ((int)pStrm->uTargetHeight - (int)uSourceHeight) / 2; 721 if ((int)h + yDiff + (int)y <= 0) /* nothing visible */ 722 return VERR_INVALID_PARAMETER; 723 724 uint32_t destY; 725 if ((int)y < -yDiff) 726 { 727 h += yDiff + (int)y; 728 y = -yDiff; 729 destY = 0; 730 } 731 else 732 destY = y + yDiff; 733 734 if ( destX > pStrm->uTargetWidth 735 || destY > pStrm->uTargetHeight) 736 return VERR_INVALID_PARAMETER; /* nothing visible */ 737 738 if (destX + w > pStrm->uTargetWidth) 739 w = pStrm->uTargetWidth - destX; 740 741 if (destY + h > pStrm->uTargetHeight) 742 h = pStrm->uTargetHeight - destY; 743 744 /* Calculate bytes per pixel */ 745 uint32_t bpp = 1; 746 if (uPixelFormat == FramebufferPixelFormat_FOURCC_RGB) 747 { 748 switch (uBitsPerPixel) 749 { 750 case 32: 751 pStrm->u32PixelFormat = VPX_IMG_FMT_RGB32; 752 bpp = 4; 753 break; 754 case 24: 755 pStrm->u32PixelFormat = VPX_IMG_FMT_RGB24; 756 bpp = 3; 757 break; 758 case 16: 759 pStrm->u32PixelFormat = VPX_IMG_FMT_RGB565; 760 bpp = 2; 761 break; 762 default: 763 AssertMsgFailed(("Unknown color depth! mBitsPerPixel=%d\n", uBitsPerPixel)); 764 break; 765 } 766 } 767 else 768 AssertMsgFailed(("Unknown pixel format! mPixelFormat=%d\n", uPixelFormat)); 769 770 /* One of the dimensions of the current frame is smaller than before so 771 * clear the entire buffer to prevent artifacts from the previous frame */ 772 if ( uSourceWidth < pStrm->uLastSourceWidth 773 || uSourceHeight < pStrm->uLastSourceHeight) 774 memset(pStrm->pu8RgbBuf, 0, pStrm->uTargetWidth * pStrm->uTargetHeight * 4); 775 776 pStrm->uLastSourceWidth = uSourceWidth; 777 pStrm->uLastSourceHeight = uSourceHeight; 778 779 /* Calculate start offset in source and destination buffers */ 780 uint32_t offSrc = y * uBytesPerLine + x * bpp; 781 uint32_t offDst = (destY * pStrm->uTargetWidth + destX) * bpp; 782 /* do the copy */ 783 for (unsigned int i = 0; i < h; i++) 784 { 785 /* Overflow check */ 786 Assert(offSrc + w * bpp <= uSourceHeight * uBytesPerLine); 787 Assert(offDst + w * bpp <= pStrm->uTargetHeight * pStrm->uTargetWidth * bpp); 788 memcpy(pStrm->pu8RgbBuf + offDst, pu8BufAddr + offSrc, w * bpp); 789 offSrc += uBytesPerLine; 790 offDst += pStrm->uTargetWidth * bpp; 791 } 792 793 pStrm->u64TimeStamp = u64TimeStamp; 794 795 ASMAtomicWriteBool(&pStrm->fRgbFilled, true); 796 RTSemEventSignal(pCtx->WaitEvent); 797 798 return VINF_SUCCESS; 799 } 709 /* Do not execute during termination and guard against termination */ 710 if (!ASMAtomicCmpXchgU32(&g_enmState, VIDREC_COPYING, VIDREC_IDLE)) 711 return VINF_TRY_AGAIN; 712 713 int rc = VINF_SUCCESS; 714 do 715 { 716 AssertPtrBreakStmt(pu8BufAddr, rc = VERR_INVALID_PARAMETER); 717 AssertBreakStmt(uSourceWidth, rc = VERR_INVALID_PARAMETER); 718 AssertBreakStmt(uSourceHeight, rc = VERR_INVALID_PARAMETER); 719 AssertBreakStmt(uScreen < pCtx->cScreens, rc = VERR_INVALID_PARAMETER); 720 721 PVIDEORECSTREAM pStrm = &pCtx->Strm[uScreen]; 722 723 if (u64TimeStamp < pStrm->u64LastTimeStamp + pStrm->uDelay) 724 { 725 rc = VINF_TRY_AGAIN; /* respect maximum frames per second */ 726 break; 727 } 728 729 if (ASMAtomicReadBool(&pStrm->fRgbFilled)) 730 { 731 rc = VERR_TRY_AGAIN; /* previous frame not yet encoded */ 732 break; 733 } 734 735 pStrm->u64LastTimeStamp = u64TimeStamp; 736 737 int xDiff = ((int)pStrm->uTargetWidth - (int)uSourceWidth) / 2; 738 uint32_t w = uSourceWidth; 739 if ((int)w + xDiff + (int)x <= 0) /* nothing visible */ 740 { 741 rc = VERR_INVALID_PARAMETER; 742 break; 743 } 744 745 uint32_t destX; 746 if ((int)x < -xDiff) 747 { 748 w += xDiff + x; 749 x = -xDiff; 750 destX = 0; 751 } 752 else 753 destX = x + xDiff; 754 755 uint32_t h = uSourceHeight; 756 int yDiff = ((int)pStrm->uTargetHeight - (int)uSourceHeight) / 2; 757 if ((int)h + yDiff + (int)y <= 0) /* nothing visible */ 758 { 759 rc = VERR_INVALID_PARAMETER; 760 break; 761 } 762 763 uint32_t destY; 764 if ((int)y < -yDiff) 765 { 766 h += yDiff + (int)y; 767 y = -yDiff; 768 destY = 0; 769 } 770 else 771 destY = y + yDiff; 772 773 if ( destX > pStrm->uTargetWidth 774 || destY > pStrm->uTargetHeight) 775 { 776 rc = VERR_INVALID_PARAMETER; /* nothing visible */ 777 break; 778 } 779 780 if (destX + w > pStrm->uTargetWidth) 781 w = pStrm->uTargetWidth - destX; 782 783 if (destY + h > pStrm->uTargetHeight) 784 h = pStrm->uTargetHeight - destY; 785 786 /* Calculate bytes per pixel */ 787 uint32_t bpp = 1; 788 if (uPixelFormat == FramebufferPixelFormat_FOURCC_RGB) 789 { 790 switch (uBitsPerPixel) 791 { 792 case 32: 793 pStrm->u32PixelFormat = VPX_IMG_FMT_RGB32; 794 bpp = 4; 795 break; 796 case 24: 797 pStrm->u32PixelFormat = VPX_IMG_FMT_RGB24; 798 bpp = 3; 799 break; 800 case 16: 801 pStrm->u32PixelFormat = VPX_IMG_FMT_RGB565; 802 bpp = 2; 803 break; 804 default: 805 AssertMsgFailed(("Unknown color depth! mBitsPerPixel=%d\n", uBitsPerPixel)); 806 break; 807 } 808 } 809 else 810 AssertMsgFailed(("Unknown pixel format! mPixelFormat=%d\n", uPixelFormat)); 811 812 /* One of the dimensions of the current frame is smaller than before so 813 * clear the entire buffer to prevent artifacts from the previous frame */ 814 if ( uSourceWidth < pStrm->uLastSourceWidth 815 || uSourceHeight < pStrm->uLastSourceHeight) 816 memset(pStrm->pu8RgbBuf, 0, pStrm->uTargetWidth * pStrm->uTargetHeight * 4); 817 818 pStrm->uLastSourceWidth = uSourceWidth; 819 pStrm->uLastSourceHeight = uSourceHeight; 820 821 /* Calculate start offset in source and destination buffers */ 822 uint32_t offSrc = y * uBytesPerLine + x * bpp; 823 uint32_t offDst = (destY * pStrm->uTargetWidth + destX) * bpp; 824 /* do the copy */ 825 for (unsigned int i = 0; i < h; i++) 826 { 827 /* Overflow check */ 828 Assert(offSrc + w * bpp <= uSourceHeight * uBytesPerLine); 829 Assert(offDst + w * bpp <= pStrm->uTargetHeight * pStrm->uTargetWidth * bpp); 830 memcpy(pStrm->pu8RgbBuf + offDst, pu8BufAddr + offSrc, w * bpp); 831 offSrc += uBytesPerLine; 832 offDst += pStrm->uTargetWidth * bpp; 833 } 834 835 pStrm->u64TimeStamp = u64TimeStamp; 836 837 ASMAtomicWriteBool(&pStrm->fRgbFilled, true); 838 RTSemEventSignal(pCtx->WaitEvent); 839 } while (0); 840 841 if (!ASMAtomicCmpXchgU32(&g_enmState, VIDREC_IDLE, VIDREC_COPYING)) 842 { 843 rc = RTSemEventSignal(pCtx->TermEvent); 844 AssertRC(rc); 845 } 846 847 return rc; 848 }
注意:
瀏覽 TracChangeset
來幫助您使用更動檢視器