- Timestamp:
- Jan 24, 2017 1:55:14 PM (8 years ago)
- svn:sync-xref-src-repo-rev:
- 113034
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Main/src-client/VideoRec.cpp
r65418 r65421 120 120 /** Screen ID. */ 121 121 uint16_t uScreen; 122 /** Target X resolution (in pixels). */123 uint32_t uDstWidth;124 /** Target Y resolution (in pixels). */125 uint32_t uDstHeight;126 /** X resolution of the last encoded frame. */127 uint32_t uSrcLastWidth;128 /** Y resolution of the last encoded frame. */129 uint32_t uSrcLastHeight;130 /** Current frame number. */131 uint64_t cFrame;132 /** RGB buffer containing the most recent frame of the framebuffer. */133 uint8_t *pu8RgbBuf;134 /** YUV buffer the encode function fetches the frame from. */135 uint8_t *pu8YuvBuf;136 122 /** Whether video recording is enabled or not. */ 137 123 bool fEnabled; 138 /** Whether the RGB buffer is filled or not. */139 bool fRgbFilled;140 /** Pixel format of the current frame. */141 uint32_t u32PixelFormat;142 /** Minimal delay between two frames. */143 uint32_t uDelay;144 124 /** Time stamp (in ms) of the last frame we encoded. */ 145 125 uint64_t uLastTimeStampMs; 146 126 /** Time stamp (in ms) of the current frame. */ 147 127 uint64_t uCurTimeStampMs; 148 /** Encoder deadline. */ 149 unsigned int uEncoderDeadline; 128 129 struct 130 { 131 /** Target X resolution (in pixels). */ 132 uint32_t uDstWidth; 133 /** Target Y resolution (in pixels). */ 134 uint32_t uDstHeight; 135 /** X resolution of the last encoded frame. */ 136 uint32_t uSrcLastWidth; 137 /** Y resolution of the last encoded frame. */ 138 uint32_t uSrcLastHeight; 139 /** Current frame number. */ 140 uint64_t cFrame; 141 /** RGB buffer containing the most recent frame of the framebuffer. */ 142 uint8_t *pu8RgbBuf; 143 /** YUV buffer the encode function fetches the frame from. */ 144 uint8_t *pu8YuvBuf; 145 /** Whether the RGB buffer is filled or not. */ 146 bool fRgbFilled; 147 /** Pixel format of the current frame. */ 148 uint32_t uPixelFormat; 149 /** Minimal delay between two frames. */ 150 uint32_t uDelay; 151 /** Encoder deadline. */ 152 unsigned int uEncoderDeadline; 153 } Video; 154 150 155 } VIDEORECSTREAM, *PVIDEORECSTREAM; 151 156 … … 461 466 462 467 if ( pStream->fEnabled 463 && ASMAtomicReadBool(&pStream-> fRgbFilled))468 && ASMAtomicReadBool(&pStream->Video.fRgbFilled)) 464 469 { 465 470 rc = videoRecRGBToYUV(pStream); 466 471 467 ASMAtomicWriteBool(&pStream-> fRgbFilled, false);472 ASMAtomicWriteBool(&pStream->Video.fRgbFilled, false); 468 473 469 474 if (RT_SUCCESS(rc)) … … 472 477 if (RT_FAILURE(rc)) 473 478 { 474 static unsigned cErrors= 100;475 if ( cErrors> 0)479 static unsigned s_cErrEnc = 100; 480 if (s_cErrEnc > 0) 476 481 { 477 482 LogRel(("VideoRec: Error %Rrc encoding / writing video frame\n", rc)); 478 cErrors--;483 s_cErrEnc--; 479 484 } 480 485 } … … 615 620 Assert(rcv == VPX_CODEC_OK); RT_NOREF(rcv); 616 621 617 if (pStream-> pu8RgbBuf)622 if (pStream->Video.pu8RgbBuf) 618 623 { 619 RTMemFree(pStream-> pu8RgbBuf);620 pStream-> pu8RgbBuf = NULL;624 RTMemFree(pStream->Video.pu8RgbBuf); 625 pStream->Video.pu8RgbBuf = NULL; 621 626 } 622 627 … … 701 706 pCtx->uMaxSizeMB = uMaxSizeMB; 702 707 703 pStream-> uDstWidth = uWidth;704 pStream-> uDstHeight = uHeight;705 pStream-> pu8RgbBuf = (uint8_t *)RTMemAllocZ(uWidth * uHeight * 4);706 AssertReturn(pStream-> pu8RgbBuf, VERR_NO_MEMORY);708 pStream->Video.uDstWidth = uWidth; 709 pStream->Video.uDstHeight = uHeight; 710 pStream->Video.pu8RgbBuf = (uint8_t *)RTMemAllocZ(uWidth * uHeight * 4); 711 AssertReturn(pStream->Video.pu8RgbBuf, VERR_NO_MEMORY); 707 712 708 713 /* Play safe: the file must not exist, overwriting is potentially … … 711 716 712 717 #ifdef VBOX_WITH_LIBVPX 713 pStream-> uEncoderDeadline = VPX_DL_REALTIME;718 pStream->Video.uEncoderDeadline = VPX_DL_REALTIME; 714 719 715 720 vpx_codec_err_t rcv = vpx_codec_enc_config_default(DEFAULTCODEC, &pStream->Codec.VPX.Config, 0); … … 738 743 { 739 744 #ifdef VBOX_WITH_LIBVPX 740 pStream-> uEncoderDeadline = VPX_DL_REALTIME;745 pStream->Video.uEncoderDeadline = VPX_DL_REALTIME; 741 746 #endif 742 747 } 743 748 else if (value.compare("good", Utf8Str::CaseInsensitive) == 0) 744 749 { 745 pStream-> uEncoderDeadline = 1000000 / uFPS;750 pStream->Video.uEncoderDeadline = 1000000 / uFPS; 746 751 } 747 752 else if (value.compare("best", Utf8Str::CaseInsensitive) == 0) 748 753 { 749 754 #ifdef VBOX_WITH_LIBVPX 750 pStream-> uEncoderDeadline = VPX_DL_BEST_QUALITY;755 pStream->Video.uEncoderDeadline = VPX_DL_BEST_QUALITY; 751 756 #endif 752 757 } … … 754 759 { 755 760 LogRel(("VideoRec: Setting quality deadline to '%s'\n", value.c_str())); 756 pStream-> uEncoderDeadline = value.toUInt32();761 pStream->Video.uEncoderDeadline = value.toUInt32(); 757 762 } 758 763 } … … 796 801 } 797 802 798 pStream-> uDelay = 1000 / uFPS;803 pStream->Video.uDelay = 1000 / uFPS; 799 804 800 805 if (fHasVideoTrack) … … 852 857 } 853 858 854 pStream-> pu8YuvBuf = pStream->Codec.VPX.RawImage.planes[0];859 pStream->Video.pu8YuvBuf = pStream->Codec.VPX.RawImage.planes[0]; 855 860 #endif 856 861 … … 899 904 } 900 905 901 if (u64TimeStampMs < pStream->uLastTimeStampMs + pStream-> uDelay)906 if (u64TimeStampMs < pStream->uLastTimeStampMs + pStream->Video.uDelay) 902 907 return false; 903 908 904 if (ASMAtomicReadBool(&pStream-> fRgbFilled))909 if (ASMAtomicReadBool(&pStream->Video.fRgbFilled)) 905 910 return false; 906 911 … … 961 966 962 967 #ifdef VBOX_WITH_LIBVPX 963 /* presentation time stamp*/968 /* Presentation Time Stamp (PTS). */ 964 969 vpx_codec_pts_t pts = pStream->uCurTimeStampMs; 965 970 vpx_codec_err_t rcv = vpx_codec_encode(&pStream->Codec.VPX.CodecCtx, 966 971 &pStream->Codec.VPX.RawImage, 967 pts /* time stamp */,968 pStream-> uDelay /* how long to show this frame */,969 0 /* flags */,970 pStream-> uEncoderDeadline /* quality setting */);972 pts /* Time stamp */, 973 pStream->Video.uDelay /* How long to show this frame */, 974 0 /* Flags */, 975 pStream->Video.uEncoderDeadline /* Quality setting */); 971 976 if (rcv != VPX_CODEC_OK) 972 977 { 973 LogF low(("Failed to encode:%s\n", vpx_codec_err_to_string(rcv)));978 LogFunc(("Failed to encode video frame: %s\n", vpx_codec_err_to_string(rcv))); 974 979 return VERR_GENERAL_FAILURE; 975 980 } … … 994 999 default: 995 1000 AssertFailed(); 996 LogFunc(("Unexpected CODEC packet kind%ld\n", pPacket->kind));1001 LogFunc(("Unexpected video packet type %ld\n", pPacket->kind)); 997 1002 break; 998 1003 } 999 1004 } 1000 1005 1001 pStream-> cFrame++;1006 pStream->Video.cFrame++; 1002 1007 #else 1003 1008 RT_NOREF(pStream); … … 1013 1018 * @param pStrm Strm. 1014 1019 */ 1015 static int videoRecRGBToYUV(PVIDEORECSTREAM pStr m)1016 { 1017 switch (pStr m->u32PixelFormat)1020 static int videoRecRGBToYUV(PVIDEORECSTREAM pStream) 1021 { 1022 switch (pStream->Video.uPixelFormat) 1018 1023 { 1019 1024 case VIDEORECPIXELFMT_RGB32: 1020 1025 LogFlow(("32 bit\n")); 1021 if (!colorConvWriteYUV420p<ColorConvBGRA32Iter>(pStr m->uDstWidth,1022 pStr m->uDstHeight,1023 pStr m->pu8YuvBuf,1024 pStr m->pu8RgbBuf))1026 if (!colorConvWriteYUV420p<ColorConvBGRA32Iter>(pStream->Video.uDstWidth, 1027 pStream->Video.uDstHeight, 1028 pStream->Video.pu8YuvBuf, 1029 pStream->Video.pu8RgbBuf)) 1025 1030 return VERR_INVALID_PARAMETER; 1026 1031 break; 1027 1032 case VIDEORECPIXELFMT_RGB24: 1028 1033 LogFlow(("24 bit\n")); 1029 if (!colorConvWriteYUV420p<ColorConvBGR24Iter>(pStr m->uDstWidth,1030 pStr m->uDstHeight,1031 pStr m->pu8YuvBuf,1032 pStr m->pu8RgbBuf))1034 if (!colorConvWriteYUV420p<ColorConvBGR24Iter>(pStream->Video.uDstWidth, 1035 pStream->Video.uDstHeight, 1036 pStream->Video.pu8YuvBuf, 1037 pStream->Video.pu8RgbBuf)) 1033 1038 return VERR_INVALID_PARAMETER; 1034 1039 break; 1035 1040 case VIDEORECPIXELFMT_RGB565: 1036 1041 LogFlow(("565 bit\n")); 1037 if (!colorConvWriteYUV420p<ColorConvBGR565Iter>(pStr m->uDstWidth,1038 pStr m->uDstHeight,1039 pStr m->pu8YuvBuf,1040 pStr m->pu8RgbBuf))1042 if (!colorConvWriteYUV420p<ColorConvBGR565Iter>(pStream->Video.uDstWidth, 1043 pStream->Video.uDstHeight, 1044 pStream->Video.pu8YuvBuf, 1045 pStream->Video.pu8RgbBuf)) 1041 1046 return VERR_INVALID_PARAMETER; 1042 1047 break; … … 1086 1091 uint64_t uTimeStampMs) 1087 1092 { 1088 /* Do not execute during termination and guard against termination */1093 /* Do not execute during termination and guard against termination. */ 1089 1094 if (!ASMAtomicCmpXchgU32(&g_enmState, VIDEORECSTS_BUSY, VIDEORECSTS_IDLE)) 1090 1095 return VINF_TRY_AGAIN; … … 1110 1115 break; 1111 1116 } 1112 if (uTimeStampMs < pStream->uLastTimeStampMs + pStream-> uDelay)1117 if (uTimeStampMs < pStream->uLastTimeStampMs + pStream->Video.uDelay) 1113 1118 { 1114 1119 rc = VINF_TRY_AGAIN; /* respect maximum frames per second */ 1115 1120 break; 1116 1121 } 1117 if (ASMAtomicReadBool(&pStream-> fRgbFilled))1122 if (ASMAtomicReadBool(&pStream->Video.fRgbFilled)) 1118 1123 { 1119 1124 rc = VERR_TRY_AGAIN; /* previous frame not yet encoded */ … … 1123 1128 pStream->uLastTimeStampMs = uTimeStampMs; 1124 1129 1125 int xDiff = ((int)pStream-> uDstWidth - (int)uSrcWidth) / 2;1130 int xDiff = ((int)pStream->Video.uDstWidth - (int)uSrcWidth) / 2; 1126 1131 uint32_t w = uSrcWidth; 1127 1132 if ((int)w + xDiff + (int)x <= 0) /* nothing visible */ … … 1142 1147 1143 1148 uint32_t h = uSrcHeight; 1144 int yDiff = ((int)pStream-> uDstHeight - (int)uSrcHeight) / 2;1149 int yDiff = ((int)pStream->Video.uDstHeight - (int)uSrcHeight) / 2; 1145 1150 if ((int)h + yDiff + (int)y <= 0) /* nothing visible */ 1146 1151 { … … 1159 1164 destY = y + yDiff; 1160 1165 1161 if ( destX > pStream-> uDstWidth1162 || destY > pStream-> uDstHeight)1166 if ( destX > pStream->Video.uDstWidth 1167 || destY > pStream->Video.uDstHeight) 1163 1168 { 1164 1169 rc = VERR_INVALID_PARAMETER; /* nothing visible */ … … 1166 1171 } 1167 1172 1168 if (destX + w > pStream-> uDstWidth)1169 w = pStream-> uDstWidth - destX;1170 1171 if (destY + h > pStream-> uDstHeight)1172 h = pStream-> uDstHeight - destY;1173 1174 /* Calculate bytes per pixel */1173 if (destX + w > pStream->Video.uDstWidth) 1174 w = pStream->Video.uDstWidth - destX; 1175 1176 if (destY + h > pStream->Video.uDstHeight) 1177 h = pStream->Video.uDstHeight - destY; 1178 1179 /* Calculate bytes per pixel. */ 1175 1180 uint32_t bpp = 1; 1176 1181 if (uPixelFormat == BitmapFormat_BGR) … … 1179 1184 { 1180 1185 case 32: 1181 pStream-> u32PixelFormat = VIDEORECPIXELFMT_RGB32;1186 pStream->Video.uPixelFormat = VIDEORECPIXELFMT_RGB32; 1182 1187 bpp = 4; 1183 1188 break; 1184 1189 case 24: 1185 pStream-> u32PixelFormat = VIDEORECPIXELFMT_RGB24;1190 pStream->Video.uPixelFormat = VIDEORECPIXELFMT_RGB24; 1186 1191 bpp = 3; 1187 1192 break; 1188 1193 case 16: 1189 pStream-> u32PixelFormat = VIDEORECPIXELFMT_RGB565;1194 pStream->Video.uPixelFormat = VIDEORECPIXELFMT_RGB565; 1190 1195 bpp = 2; 1191 1196 break; … … 1196 1201 } 1197 1202 else 1198 AssertMsgFailed(("Unknown pixel format! mPixelFormat=%d\n", uPixelFormat));1203 AssertMsgFailed(("Unknown pixel format! mPixelFormat=%d\n", pStream->Video.uPixelFormat)); 1199 1204 1200 1205 /* One of the dimensions of the current frame is smaller than before so 1201 * clear the entire buffer to prevent artifacts from the previous frame */1202 if ( uSrcWidth < pStream-> uSrcLastWidth1203 || uSrcHeight < pStream-> uSrcLastHeight)1204 memset(pStream-> pu8RgbBuf, 0, pStream->uDstWidth * pStream->uDstHeight * 4);1205 1206 pStream-> uSrcLastWidth = uSrcWidth;1207 pStream-> uSrcLastHeight = uSrcHeight;1208 1209 /* Calculate start offset in source and destination buffers */1206 * clear the entire buffer to prevent artifacts from the previous frame. */ 1207 if ( uSrcWidth < pStream->Video.uSrcLastWidth 1208 || uSrcHeight < pStream->Video.uSrcLastHeight) 1209 memset(pStream->Video.pu8RgbBuf, 0, pStream->Video.uDstWidth * pStream->Video.uDstHeight * 4); 1210 1211 pStream->Video.uSrcLastWidth = uSrcWidth; 1212 pStream->Video.uSrcLastHeight = uSrcHeight; 1213 1214 /* Calculate start offset in source and destination buffers. */ 1210 1215 uint32_t offSrc = y * uBytesPerLine + x * bpp; 1211 uint32_t offDst = (destY * pStream->uDstWidth + destX) * bpp; 1212 /* do the copy */ 1216 uint32_t offDst = (destY * pStream->Video.uDstWidth + destX) * bpp; 1217 1218 /* Do the copy. */ 1213 1219 for (unsigned int i = 0; i < h; i++) 1214 1220 { 1215 1221 /* Overflow check */ 1216 1222 Assert(offSrc + w * bpp <= uSrcHeight * uBytesPerLine); 1217 Assert(offDst + w * bpp <= pStream-> uDstHeight * pStream->uDstWidth * bpp);1218 memcpy(pStream-> pu8RgbBuf + offDst, puSrcData + offSrc, w * bpp);1223 Assert(offDst + w * bpp <= pStream->Video.uDstHeight * pStream->Video.uDstWidth * bpp); 1224 memcpy(pStream->Video.pu8RgbBuf + offDst, puSrcData + offSrc, w * bpp); 1219 1225 offSrc += uBytesPerLine; 1220 offDst += pStream-> uDstWidth * bpp;1226 offDst += pStream->Video.uDstWidth * bpp; 1221 1227 } 1222 1228 1223 1229 pStream->uCurTimeStampMs = uTimeStampMs; 1224 1230 1225 ASMAtomicWriteBool(&pStream-> fRgbFilled, true);1231 ASMAtomicWriteBool(&pStream->Video.fRgbFilled, true); 1226 1232 RTSemEventSignal(pCtx->WaitEvent); 1233 1227 1234 } while (0); 1228 1235
Note:
See TracChangeset
for help on using the changeset viewer.