Changeset 75251 in vbox
- Timestamp:
- Nov 5, 2018 5:55:29 PM (6 years ago)
- svn:sync-xref-src-repo-rev:
- 126353
- Location:
- trunk
- Files:
-
- 4 added
- 44 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/log.h
r74761 r75251 354 354 /** Main group, IBIOSSettings. */ 355 355 LOG_GROUP_MAIN_BIOSSETTINGS, 356 /** Main group, ICaptureChangedEvent. */ 357 LOG_GROUP_MAIN_CAPTURECHANGEDEVENT, 358 /** Main group, ICaptureSettings. */ 359 LOG_GROUP_MAIN_CAPTURESETTINGS, 360 /** Main group, ICaptureScreenSettings. */ 361 LOG_GROUP_MAIN_CAPTURESCREENSETTINGS, 356 362 /** Main group, ICanShowWindowEvent. */ 357 363 LOG_GROUP_MAIN_CANSHOWWINDOWEVENT, … … 662 668 /** Main group, IVFSExplorer. */ 663 669 LOG_GROUP_MAIN_VFSEXPLORER, 664 /** Main group, IVideoCaptureChangedEvent. */665 LOG_GROUP_MAIN_VIDEOCAPTURECHANGEDEVENT,666 670 /** Main group, IVirtualBox. */ 667 671 LOG_GROUP_MAIN_VIRTUALBOX, … … 1000 1004 "MAIN_BANDWIDTHGROUPCHANGEDEVENT", \ 1001 1005 "MAIN_BIOSSETTINGS", \ 1006 "MAIN_CAPTURECHANGEDEVENT", \ 1007 "MAIN_CAPTURESETTINGS", \ 1008 "MAIN_CAPTURESCREENSETTINGS", \ 1002 1009 "MAIN_CANSHOWWINDOWEVENT", \ 1003 1010 "MAIN_CERTIFICATE", \ -
trunk/include/VBox/settings.h
r74431 r75251 18 18 19 19 /* 20 * Copyright (C) 2007-201 7Oracle Corporation20 * Copyright (C) 2007-2018 Oracle Corporation 21 21 * 22 22 * This file is part of VirtualBox Open Source Edition (OSE), as … … 481 481 }; 482 482 483 /** List for keeping a capturing feature list. */ 484 typedef std::map<CaptureFeature_T, bool> CaptureFeatureMap; 485 486 class CaptureScreenSettings 487 { 488 public: 489 490 CaptureScreenSettings(); 491 492 virtual ~CaptureScreenSettings(); 493 494 void applyDefaults(void); 495 496 bool areDefaultSettings(void) const; 497 498 bool isFeatureEnabled(CaptureFeature_T enmFeature) const; 499 500 bool operator==(const CaptureScreenSettings &d) const; 501 502 bool fEnabled; // requires settings version 1.14 (VirtualBox 4.3) 503 CaptureDestination_T enmDest; // new since VirtualBox 6.0. 504 CaptureFeatureMap featureMap; // new since VirtualBox 6.0. 505 uint32_t ulMaxTimeS; // requires settings version 1.14 (VirtualBox 4.3) 506 com::Utf8Str strOptions; // new since VirtualBox 5.2. 507 508 struct Audio 509 { 510 Audio() 511 : enmAudioCodec(CaptureAudioCodec_Opus) 512 , uHz(22050) 513 , cBits(16) 514 , cChannels(2) { } 515 516 /** The audio codec type to use. */ 517 CaptureAudioCodec_T enmAudioCodec; // new since VirtualBox 6.0. 518 /** Hz rate. */ 519 uint16_t uHz; // new since VirtualBox 6.0. 520 /** Bits per sample. */ 521 uint8_t cBits; // new since VirtualBox 6.0. 522 /** Number of audio channels. */ 523 uint8_t cChannels; // new since VirtualBox 6.0. 524 } Audio; 525 526 struct Video 527 { 528 Video() 529 : enmCodec(CaptureVideoCodec_VP8) 530 , ulWidth(1024) 531 , ulHeight(768) 532 , ulRate(512) 533 , ulFPS(25) { } 534 535 CaptureVideoCodec_T enmCodec; // new since VirtualBox 6.0. 536 uint32_t ulWidth; // requires settings version 1.14 (VirtualBox 4.3) 537 uint32_t ulHeight; // requires settings version 1.14 (VirtualBox 4.3) 538 uint32_t ulRate; // requires settings version 1.14 (VirtualBox 4.3) 539 uint32_t ulFPS; // requires settings version 1.14 (VirtualBox 4.3) 540 } Video; 541 542 struct File 543 { 544 File() 545 : ulMaxSizeMB(0) { } 546 547 uint32_t ulMaxSizeMB; // requires settings version 1.14 (VirtualBox 4.3) 548 com::Utf8Str strName; // requires settings version 1.14 (VirtualBox 4.3) 549 } File; 550 }; 551 552 /** Map for keeping settings per virtual screen. */ 553 typedef std::map<unsigned long, CaptureScreenSettings> CaptureScreenMap; 554 555 /** 556 * NOTE: If you add any fields in here, you must update a) the constructor and b) 557 * the operator== which is used by MachineConfigFile::operator==(), or otherwise 558 * your settings might never get saved. 559 */ 560 struct CaptureSettings 561 { 562 CaptureSettings(); 563 564 void applyDefaults(void); 565 566 bool areDefaultSettings(void) const; 567 568 bool operator==(const CaptureSettings &d) const; 569 570 bool fEnabled; // requires settings version 1.14 (VirtualBox 4.3) 571 CaptureScreenMap mapScreens; 572 }; 573 483 574 /** 484 575 * NOTE: If you add any fields in here, you must update a) the constructor and b) … … 890 981 bool areBootOrderDefaultSettings() const; 891 982 bool areDisplayDefaultSettings() const; 892 bool areVideoCaptureDefaultSettings() const;893 983 bool areAllNetworkAdaptersDefaultSettings(SettingsVersion_T sv) const; 894 984 … … 937 1027 fAccelerate2DVideo; // requires settings version 1.8 (VirtualBox 3.1) 938 1028 939 uint32_t ulVideoCaptureHorzRes; // requires settings version 1.14 (VirtualBox 4.3)940 uint32_t ulVideoCaptureVertRes; // requires settings version 1.14 (VirtualBox 4.3)941 uint32_t ulVideoCaptureRate; // requires settings version 1.14 (VirtualBox 4.3)942 uint32_t ulVideoCaptureFPS; // requires settings version 1.14 (VirtualBox 4.3)943 uint32_t ulVideoCaptureMaxTime; // requires settings version 1.14 (VirtualBox 4.3)944 uint32_t ulVideoCaptureMaxSize; // requires settings version 1.14 (VirtualBox 4.3)945 bool fVideoCaptureEnabled; // requires settings version 1.14 (VirtualBox 4.3)946 uint64_t u64VideoCaptureScreens; // requires settings version 1.14 (VirtualBox 4.3)947 com::Utf8Str strVideoCaptureFile; // requires settings version 1.14 (VirtualBox 4.3)948 com::Utf8Str strVideoCaptureOptions; // new since VirtualBox 5.2.949 950 1029 FirmwareType_T firmwareType; // requires settings version 1.9 (VirtualBox 3.1) 951 1030 … … 962 1041 963 1042 BIOSSettings biosSettings; 1043 CaptureSettings captureSettings; 964 1044 USB usbSettings; 965 1045 NetworkAdaptersList llNetworkAdapters; -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageControlVM.cpp
r72826 r75251 5 5 6 6 /* 7 * Copyright (C) 2006-201 7Oracle Corporation7 * Copyright (C) 2006-2018 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 395 395 /* get the associated console */ 396 396 CHECK_ERROR_BREAK(a->session, COMGETTER(Console)(console.asOutParam())); 397 if (!console) 398 return RTMsgErrorExit(RTEXITCODE_FAILURE, "Machine '%s' is not currently running", a->argv[0]); 399 397 400 /* ... and session machine */ 398 401 CHECK_ERROR_BREAK(a->session, COMGETTER(Machine)(sessionMachine.asOutParam())); 399 400 if (!console)401 return RTMsgErrorExit(RTEXITCODE_FAILURE, "Machine '%s' is not currently running", a->argv[0]);402 402 403 403 /* which command? */ … … 1855 1855 } 1856 1856 #ifdef VBOX_WITH_VIDEOREC 1857 /* 1858 * Note: Commands starting with "vcp" are the deprecated versions and are 1859 * kept to ensure backwards compatibility. 1860 */ 1861 else if ( !strcmp(a->argv[1], "videocap") 1862 || !strcmp(a->argv[1], "vcpenabled")) 1863 { 1864 if (a->argc != 3) 1857 else if (!strcmp(a->argv[1], "capture")) 1858 { 1859 if (a->argc < 3) 1865 1860 { 1866 1861 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters"); … … 1868 1863 break; 1869 1864 } 1870 if (!strcmp(a->argv[2], "on")) 1871 { 1872 CHECK_ERROR_RET(sessionMachine, COMSETTER(VideoCaptureEnabled)(TRUE), RTEXITCODE_FAILURE); 1873 } 1874 else if (!strcmp(a->argv[2], "off")) 1875 { 1876 CHECK_ERROR_RET(sessionMachine, COMSETTER(VideoCaptureEnabled)(FALSE), RTEXITCODE_FAILURE); 1877 } 1878 else 1879 { 1880 errorArgument("Invalid state '%s'", Utf8Str(a->argv[2]).c_str()); 1881 rc = E_FAIL; 1882 break; 1883 } 1884 } 1885 else if ( !strcmp(a->argv[1], "videocapscreens") 1886 || !strcmp(a->argv[1], "vcpscreens")) 1887 { 1888 ULONG cMonitors = 64; 1889 CHECK_ERROR_BREAK(machine, COMGETTER(MonitorCount)(&cMonitors)); 1890 com::SafeArray<BOOL> saScreens(cMonitors); 1891 if ( a->argc == 3 1892 && !strcmp(a->argv[2], "all")) 1893 { 1894 /* enable all screens */ 1895 for (unsigned i = 0; i < cMonitors; i++) 1896 saScreens[i] = true; 1897 } 1898 else if ( a->argc == 3 1899 && !strcmp(a->argv[2], "none")) 1900 { 1901 /* disable all screens */ 1902 for (unsigned i = 0; i < cMonitors; i++) 1903 saScreens[i] = false; 1904 1905 /** @todo r=andy What if this is specified? */ 1906 } 1907 else 1908 { 1909 /* enable selected screens */ 1910 for (unsigned i = 0; i < cMonitors; i++) 1911 saScreens[i] = false; 1912 for (int i = 2; SUCCEEDED(rc) && i < a->argc; i++) 1913 { 1914 uint32_t iScreen; 1915 int vrc = RTStrToUInt32Ex(a->argv[i], NULL, 0, &iScreen); 1916 if (vrc != VINF_SUCCESS) 1917 { 1918 errorArgument("Error parsing display number '%s'", a->argv[i]); 1919 rc = E_FAIL; 1920 break; 1921 } 1922 if (iScreen >= cMonitors) 1923 { 1924 errorArgument("Invalid screen ID specified '%u'", iScreen); 1925 rc = E_FAIL; 1926 break; 1927 } 1928 saScreens[iScreen] = true; 1929 } 1930 } 1931 1932 CHECK_ERROR_BREAK(sessionMachine, COMSETTER(VideoCaptureScreens)(ComSafeArrayAsInParam(saScreens))); 1933 } 1934 else if ( !strcmp(a->argv[1], "videocapfile") 1935 || !strcmp(a->argv[1], "vcpfile")) 1936 { 1937 if (a->argc != 3) 1938 { 1939 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters"); 1940 rc = E_FAIL; 1941 break; 1942 } 1943 1944 CHECK_ERROR_BREAK(sessionMachine, COMSETTER(VideoCaptureFile)(Bstr(a->argv[2]).raw())); 1945 } 1946 else if (!strcmp(a->argv[1], "videocapres")) 1947 { 1948 if (a->argc != 4) 1949 { 1950 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters"); 1951 rc = E_FAIL; 1952 break; 1953 } 1954 1955 uint32_t uVal; 1956 int vrc = RTStrToUInt32Ex(a->argv[2], NULL, 0, &uVal); 1957 if (RT_FAILURE(vrc)) 1958 { 1959 errorArgument("Error parsing width '%s'", a->argv[2]); 1960 rc = E_FAIL; 1961 break; 1962 } 1963 CHECK_ERROR_BREAK(sessionMachine, COMSETTER(VideoCaptureWidth)(uVal)); 1964 1965 vrc = RTStrToUInt32Ex(a->argv[3], NULL, 0, &uVal); 1966 if (RT_FAILURE(vrc)) 1967 { 1968 errorArgument("Error parsing height '%s'", a->argv[3]); 1969 rc = E_FAIL; 1970 break; 1971 } 1972 CHECK_ERROR_BREAK(sessionMachine, COMSETTER(VideoCaptureHeight)(uVal)); 1973 } 1974 else if (!strcmp(a->argv[1], "vcpwidth")) /* Deprecated; keeping for compatibility. */ 1975 { 1976 uint32_t uVal; 1977 int vrc = RTStrToUInt32Ex(a->argv[2], NULL, 0, &uVal); 1978 if (RT_FAILURE(vrc)) 1979 { 1980 errorArgument("Error parsing width '%s'", a->argv[2]); 1981 rc = E_FAIL; 1982 break; 1983 } 1984 CHECK_ERROR_BREAK(sessionMachine, COMSETTER(VideoCaptureWidth)(uVal)); 1985 } 1986 else if (!strcmp(a->argv[1], "vcpheight")) /* Deprecated; keeping for compatibility. */ 1987 { 1988 uint32_t uVal; 1989 int vrc = RTStrToUInt32Ex(a->argv[2], NULL, 0, &uVal); 1990 if (RT_FAILURE(vrc)) 1991 { 1992 errorArgument("Error parsing height '%s'", a->argv[2]); 1993 rc = E_FAIL; 1994 break; 1995 } 1996 CHECK_ERROR_BREAK(sessionMachine, COMSETTER(VideoCaptureHeight)(uVal)); 1997 } 1998 else if ( !strcmp(a->argv[1], "videocaprate") 1999 || !strcmp(a->argv[1], "vcprate")) 2000 { 2001 if (a->argc != 3) 2002 { 2003 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters"); 2004 rc = E_FAIL; 2005 break; 2006 } 2007 2008 uint32_t uVal; 2009 int vrc = RTStrToUInt32Ex(a->argv[2], NULL, 0, &uVal); 2010 if (RT_FAILURE(vrc)) 2011 { 2012 errorArgument("Error parsing rate '%s'", a->argv[2]); 2013 rc = E_FAIL; 2014 break; 2015 } 2016 CHECK_ERROR_BREAK(sessionMachine, COMSETTER(VideoCaptureRate)(uVal)); 2017 } 2018 else if ( !strcmp(a->argv[1], "videocapfps") 2019 || !strcmp(a->argv[1], "vcpfps")) 2020 { 2021 if (a->argc != 3) 2022 { 2023 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters"); 2024 rc = E_FAIL; 2025 break; 2026 } 2027 2028 uint32_t uVal; 2029 int vrc = RTStrToUInt32Ex(a->argv[2], NULL, 0, &uVal); 2030 if (RT_FAILURE(vrc)) 2031 { 2032 errorArgument("Error parsing FPS '%s'", a->argv[2]); 2033 rc = E_FAIL; 2034 break; 2035 } 2036 CHECK_ERROR_BREAK(sessionMachine, COMSETTER(VideoCaptureFPS)(uVal)); 2037 } 2038 else if ( !strcmp(a->argv[1], "videocapmaxtime") 2039 || !strcmp(a->argv[1], "vcpmaxtime")) 2040 { 2041 if (a->argc != 3) 2042 { 2043 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters"); 2044 rc = E_FAIL; 2045 break; 2046 } 2047 2048 uint32_t uVal; 2049 int vrc = RTStrToUInt32Ex(a->argv[2], NULL, 0, &uVal); 2050 if (RT_FAILURE(vrc)) 2051 { 2052 errorArgument("Error parsing maximum time '%s'", a->argv[2]); 2053 rc = E_FAIL; 2054 break; 2055 } 2056 CHECK_ERROR_BREAK(sessionMachine, COMSETTER(VideoCaptureMaxTime)(uVal)); 2057 } 2058 else if ( !strcmp(a->argv[1], "videocapmaxsize") 2059 || !strcmp(a->argv[1], "vcpmaxsize")) 2060 { 2061 if (a->argc != 3) 2062 { 2063 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters"); 2064 rc = E_FAIL; 2065 break; 2066 } 2067 2068 uint32_t uVal; 2069 int vrc = RTStrToUInt32Ex(a->argv[2], NULL, 0, &uVal); 2070 if (RT_FAILURE(vrc)) 2071 { 2072 errorArgument("Error parsing maximum file size '%s'", a->argv[2]); 2073 rc = E_FAIL; 2074 break; 2075 } 2076 CHECK_ERROR_BREAK(sessionMachine, COMSETTER(VideoCaptureMaxFileSize)(uVal)); 2077 } 2078 else if ( !strcmp(a->argv[1], "videocapopts") 2079 || !strcmp(a->argv[1], "vcpoptions")) 2080 { 2081 if (a->argc != 3) 2082 { 2083 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters"); 2084 rc = E_FAIL; 2085 break; 2086 } 2087 2088 CHECK_ERROR_BREAK(sessionMachine, COMSETTER(VideoCaptureOptions)(Bstr(a->argv[3]).raw())); 1865 1866 ComPtr<ICaptureSettings> captureSettings; 1867 CHECK_ERROR_BREAK(machine, COMGETTER(CaptureSettings)(captureSettings.asOutParam())); 1868 1869 SafeIfaceArray <ICaptureScreenSettings> saCaptureScreenScreens; 1870 CHECK_ERROR_BREAK(captureSettings, COMGETTER(Screens)(ComSafeArrayAsOutParam(saCaptureScreenScreens))); 1871 1872 /* Note: For now all screens have the same configuration. */ 1873 1874 /* 1875 * Note: Commands starting with "vcp" are the deprecated versions and are 1876 * kept to ensure backwards compatibility. 1877 */ 1878 if (!strcmp(a->argv[2], "enable")) 1879 { 1880 CHECK_ERROR_RET(captureSettings, COMSETTER(Enabled)(TRUE), RTEXITCODE_FAILURE); 1881 } 1882 else if (!strcmp(a->argv[2], "disable")) 1883 { 1884 CHECK_ERROR_RET(captureSettings, COMSETTER(Enabled)(FALSE), RTEXITCODE_FAILURE); 1885 } 1886 else if (!strcmp(a->argv[2], "screens")) 1887 { 1888 ULONG cMonitors = 64; 1889 CHECK_ERROR_BREAK(machine, COMGETTER(MonitorCount)(&cMonitors)); 1890 com::SafeArray<BOOL> saScreens(cMonitors); 1891 if ( a->argc == 4 1892 && !strcmp(a->argv[3], "all")) 1893 { 1894 /* enable all screens */ 1895 for (unsigned i = 0; i < cMonitors; i++) 1896 saScreens[i] = true; 1897 } 1898 else if ( a->argc == 4 1899 && !strcmp(a->argv[3], "none")) 1900 { 1901 /* disable all screens */ 1902 for (unsigned i = 0; i < cMonitors; i++) 1903 saScreens[i] = false; 1904 1905 /** @todo r=andy What if this is specified? */ 1906 } 1907 else 1908 { 1909 /* enable selected screens */ 1910 for (unsigned i = 0; i < cMonitors; i++) 1911 saScreens[i] = false; 1912 for (int i = 3; SUCCEEDED(rc) && i < a->argc; i++) 1913 { 1914 uint32_t iScreen; 1915 int vrc = RTStrToUInt32Ex(a->argv[i], NULL, 0, &iScreen); 1916 if (vrc != VINF_SUCCESS) 1917 { 1918 errorArgument("Error parsing display number '%s'", a->argv[i]); 1919 rc = E_FAIL; 1920 break; 1921 } 1922 if (iScreen >= cMonitors) 1923 { 1924 errorArgument("Invalid screen ID specified '%u'", iScreen); 1925 rc = E_FAIL; 1926 break; 1927 } 1928 saScreens[iScreen] = true; 1929 } 1930 } 1931 1932 for (size_t i = 0; i < saCaptureScreenScreens.size(); ++i) 1933 CHECK_ERROR_BREAK(saCaptureScreenScreens[i], COMSETTER(Enabled)(saScreens[i])); 1934 } 1935 else if (!strcmp(a->argv[2], "filename")) 1936 { 1937 if (a->argc != 3) 1938 { 1939 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters"); 1940 rc = E_FAIL; 1941 break; 1942 } 1943 1944 for (size_t i = 0; i < saCaptureScreenScreens.size(); ++i) 1945 CHECK_ERROR_BREAK(saCaptureScreenScreens[i], COMSETTER(FileName)(Bstr(a->argv[2]).raw())); 1946 } 1947 else if ( !strcmp(a->argv[2], "res") 1948 || !strcmp(a->argv[2], "resolution")) 1949 { 1950 if (a->argc != 5) 1951 { 1952 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters"); 1953 rc = E_FAIL; 1954 break; 1955 } 1956 1957 uint32_t uVal; 1958 int vrc = RTStrToUInt32Ex(a->argv[3], NULL, 0, &uVal); 1959 if (RT_FAILURE(vrc)) 1960 { 1961 errorArgument("Error parsing width '%s'", a->argv[3]); 1962 rc = E_FAIL; 1963 break; 1964 } 1965 1966 vrc = RTStrToUInt32Ex(a->argv[4], NULL, 0, &uVal); 1967 if (RT_FAILURE(vrc)) 1968 { 1969 errorArgument("Error parsing height '%s'", a->argv[4]); 1970 rc = E_FAIL; 1971 break; 1972 } 1973 1974 for (size_t i = 0; i < saCaptureScreenScreens.size(); ++i) 1975 { 1976 CHECK_ERROR_BREAK(saCaptureScreenScreens[i], COMSETTER(VideoWidth)(uVal)); 1977 CHECK_ERROR_BREAK(saCaptureScreenScreens[i], COMSETTER(VideoHeight)(uVal)); 1978 } 1979 } 1980 else if (!strcmp(a->argv[2], "videorate")) 1981 { 1982 if (a->argc != 4) 1983 { 1984 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters"); 1985 rc = E_FAIL; 1986 break; 1987 } 1988 1989 uint32_t uVal; 1990 int vrc = RTStrToUInt32Ex(a->argv[3], NULL, 0, &uVal); 1991 if (RT_FAILURE(vrc)) 1992 { 1993 errorArgument("Error parsing rate '%s'", a->argv[3]); 1994 rc = E_FAIL; 1995 break; 1996 } 1997 1998 for (size_t i = 0; i < saCaptureScreenScreens.size(); ++i) 1999 CHECK_ERROR_BREAK(saCaptureScreenScreens[i], COMSETTER(VideoRate)(uVal)); 2000 } 2001 else if (!strcmp(a->argv[2], "videofps")) 2002 { 2003 if (a->argc != 4) 2004 { 2005 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters"); 2006 rc = E_FAIL; 2007 break; 2008 } 2009 2010 uint32_t uVal; 2011 int vrc = RTStrToUInt32Ex(a->argv[3], NULL, 0, &uVal); 2012 if (RT_FAILURE(vrc)) 2013 { 2014 errorArgument("Error parsing FPS '%s'", a->argv[3]); 2015 rc = E_FAIL; 2016 break; 2017 } 2018 2019 for (size_t i = 0; i < saCaptureScreenScreens.size(); ++i) 2020 CHECK_ERROR_BREAK(saCaptureScreenScreens[i], COMSETTER(VideoFPS)(uVal)); 2021 } 2022 else if (!strcmp(a->argv[2], "maxtime")) 2023 { 2024 if (a->argc != 4) 2025 { 2026 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters"); 2027 rc = E_FAIL; 2028 break; 2029 } 2030 2031 uint32_t uVal; 2032 int vrc = RTStrToUInt32Ex(a->argv[3], NULL, 0, &uVal); 2033 if (RT_FAILURE(vrc)) 2034 { 2035 errorArgument("Error parsing maximum time '%s'", a->argv[3]); 2036 rc = E_FAIL; 2037 break; 2038 } 2039 2040 for (size_t i = 0; i < saCaptureScreenScreens.size(); ++i) 2041 CHECK_ERROR_BREAK(saCaptureScreenScreens[i], COMSETTER(MaxTime)(uVal)); 2042 } 2043 else if (!strcmp(a->argv[2], "maxfilesize")) 2044 { 2045 if (a->argc != 4) 2046 { 2047 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters"); 2048 rc = E_FAIL; 2049 break; 2050 } 2051 2052 uint32_t uVal; 2053 int vrc = RTStrToUInt32Ex(a->argv[3], NULL, 0, &uVal); 2054 if (RT_FAILURE(vrc)) 2055 { 2056 errorArgument("Error parsing maximum file size '%s'", a->argv[3]); 2057 rc = E_FAIL; 2058 break; 2059 } 2060 2061 for (size_t i = 0; i < saCaptureScreenScreens.size(); ++i) 2062 CHECK_ERROR_BREAK(saCaptureScreenScreens[i], COMSETTER(MaxFileSize)(uVal)); 2063 } 2064 else if (!strcmp(a->argv[2], "opts")) 2065 { 2066 if (a->argc != 4) 2067 { 2068 errorSyntax(USAGE_CONTROLVM, "Incorrect number of parameters"); 2069 rc = E_FAIL; 2070 break; 2071 } 2072 2073 for (size_t i = 0; i < saCaptureScreenScreens.size(); ++i) 2074 CHECK_ERROR_BREAK(saCaptureScreenScreens[i], COMSETTER(Options)(Bstr(a->argv[3]).raw())); 2075 } 2089 2076 } 2090 2077 #endif /* VBOX_WITH_VIDEOREC */ -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageHelp.cpp
r74474 r75251 713 713 #endif 714 714 #ifdef VBOX_WITH_VIDEOREC 715 " [-- videocapon|off]\n"716 " [-- videocapscreens all|<screen ID> [<screen ID> ...]]\n"717 " [-- videocapfile <filename>]\n"718 " [-- videocapres<width> <height>]\n"719 " [-- videocaprate <rate>]\n"720 " [-- videocapfps <fps>]\n"721 " [-- videocapmaxtime <ms>]\n"722 " [-- videocapmaxsize <MB>]\n"723 " [-- videocapopts <key=value> [,<key=value> ...]]\n"715 " [--capture on|off]\n" 716 " [--capture screens all|<screen ID> [<screen ID> ...]]\n" 717 " [--capture filename <filename>]\n" 718 " [--capture resolution <width> <height>]\n" 719 " [--capture videorate <rate>]\n" 720 " [--capture videofps <fps>]\n" 721 " [--capture maxtime <ms>]\n" 722 " [--capture maxfilesize <MB>]\n" 723 " [--capture opts <key=value> [,<key=value> ...]]\n" 724 724 #endif 725 725 " [--defaultfrontend default|<name>]\n" … … 831 831 " setscreenlayout <display> on|primary <xorigin> <yorigin> <xres> <yres> <bpp> | off\n" 832 832 " screenshotpng <file> [display] |\n" 833 " videocap on|off |\n" 834 " videocapscreens all|none|<screen>,[<screen>...] |\n" 835 " videocapfile <file>\n" 836 " videocapres <width>x<height>\n" 837 " videocaprate <rate>\n" 838 " videocapfps <fps>\n" 839 " videocapmaxtime <ms>\n" 840 " videocapmaxsize <MB>\n" 833 #ifdef VBOX_WITH_VIDEOREC 834 " capture on|off |\n" 835 " capture screens all|none|<screen>,[<screen>...] |\n" 836 " capture filename <file> |\n" 837 " capture resolution <width>x<height> |\n" 838 " capture videorate <rate> |\n" 839 " capture videofps <fps> |\n" 840 " capture maxtime <s> |\n" 841 " capture maxfilesize <MB> |\n" 842 #endif /* VBOX_WITH_VIDEOREC */ 841 843 " setcredentials <username>\n" 842 844 " --passwordfile <file> | <password>\n" -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageInfo.cpp
r73768 r75251 2379 2379 # endif 2380 2380 2381 CHECK_ERROR_RET(machine, COMGETTER(VideoCaptureEnabled)(&fCaptureVideo), rc); 2382 com::SafeArray<BOOL> screens; 2383 CHECK_ERROR_RET(machine, COMGETTER(VideoCaptureScreens)(ComSafeArrayAsOutParam(screens)), rc); 2381 ComPtr<ICaptureSettings> captureSettings; 2382 CHECK_ERROR_RET(machine, COMGETTER(CaptureSettings)(captureSettings.asOutParam()), rc); 2383 2384 SafeIfaceArray <ICaptureScreenSettings> saCaptureScreenScreens; 2385 CHECK_ERROR_RET(captureSettings, COMGETTER(Screens)(ComSafeArrayAsOutParam(saCaptureScreenScreens)), rc); 2386 2387 /* For now all screens have the same configuration; so take screen 0 and work with that. */ 2388 ULONG fFeatures; 2389 CHECK_ERROR_RET(saCaptureScreenScreens[0], COMGETTER(Features)(&fFeatures), rc); 2384 2390 ULONG Width; 2385 CHECK_ERROR_RET( machine, COMGETTER(VideoCaptureWidth)(&Width), rc);2391 CHECK_ERROR_RET(saCaptureScreenScreens[0], COMGETTER(VideoWidth)(&Width), rc); 2386 2392 ULONG Height; 2387 CHECK_ERROR_RET( machine, COMGETTER(VideoCaptureHeight)(&Height), rc);2393 CHECK_ERROR_RET(saCaptureScreenScreens[0], COMGETTER(VideoHeight)(&Height), rc); 2388 2394 ULONG Rate; 2389 CHECK_ERROR_RET( machine, COMGETTER(VideoCaptureRate)(&Rate), rc);2395 CHECK_ERROR_RET(saCaptureScreenScreens[0], COMGETTER(VideoRate)(&Rate), rc); 2390 2396 ULONG Fps; 2391 CHECK_ERROR_RET( machine, COMGETTER(VideoCaptureFPS)(&Fps), rc);2397 CHECK_ERROR_RET(saCaptureScreenScreens[0], COMGETTER(VideoFPS)(&Fps), rc); 2392 2398 Bstr bstrFile; 2393 CHECK_ERROR_RET( machine, COMGETTER(VideoCaptureFile)(bstrFile.asOutParam()), rc);2399 CHECK_ERROR_RET(saCaptureScreenScreens[0], COMGETTER(FileName)(bstrFile.asOutParam()), rc); 2394 2400 Bstr bstrOptions; 2395 CHECK_ERROR_RET( machine, COMGETTER(VideoCaptureOptions)(bstrOptions.asOutParam()), rc);2401 CHECK_ERROR_RET(saCaptureScreenScreens[0], COMGETTER(Options)(bstrOptions.asOutParam()), rc); 2396 2402 2397 2403 Utf8Str strOptions(bstrOptions); … … 2417 2423 # endif 2418 2424 szValue[0] = '\0'; 2419 for (size_t i = 0, off = 0; i < screens.size(); i++) 2420 if (screens[i] && off < sizeof(szValue) - 3) 2425 for (size_t i = 0, off = 0; i < saCaptureScreenScreens.size(); i++) 2426 { 2427 BOOL fEnabled; 2428 CHECK_ERROR_RET(saCaptureScreenScreens[i], COMGETTER(Enabled)(&fEnabled), rc); 2429 if (fEnabled && off < sizeof(szValue) - 3) 2421 2430 off += RTStrPrintf(&szValue[off], sizeof(szValue) - off, off ? ",%zu" : "%zu", i); 2422 SHOW_UTF8_STRING("videocapscreens", "Capture screens:", szValue); 2423 SHOW_BSTR_STRING("videocapfile", "Capture file:", bstrFile); 2431 } 2432 SHOW_UTF8_STRING("capturescreens", "Capture screens:", szValue); 2433 SHOW_BSTR_STRING("capturefilename", "Capture file:", bstrFile); 2424 2434 RTStrPrintf(szValue, sizeof(szValue), "%ux%u", Width, Height); 2425 SHOW_UTF8_STRING(" videocapres", "Capture dimensions:", szValue);2426 SHOW_ULONG_VALUE(" videocaprate", "Capture rate:", Rate, "kbps");2427 SHOW_ULONG_VALUE(" videocapfps", "Capture FPS:", Fps, "kbps");2428 SHOW_BSTR_STRING(" videocapopts", "Capture options:", bstrOptions);2435 SHOW_UTF8_STRING("captureres", "Capture dimensions:", szValue); 2436 SHOW_ULONG_VALUE("capturevideorate", "Capture rate:", Rate, "kbps"); 2437 SHOW_ULONG_VALUE("capturevideofps", "Capture FPS:", Fps, "kbps"); 2438 SHOW_BSTR_STRING("captureopts", "Capture options:", bstrOptions); 2429 2439 2430 2440 if (details != VMINFO_MACHINEREADABLE) -
trunk/src/VBox/Frontends/VBoxManage/VBoxManageModifyVM.cpp
r75138 r75251 2929 2929 #ifdef VBOX_WITH_VIDEOREC 2930 2930 case MODIFYVM_CAPTURE: 2931 { 2932 CHECK_ERROR(sessionMachine, COMSETTER(VideoCaptureEnabled)(ValueUnion.f)); 2933 break; 2934 } 2931 RT_FALL_THROUGH(); 2935 2932 case MODIFYVM_CAPTURE_SCREENS: 2936 { 2937 ULONG cMonitors = 64; 2938 CHECK_ERROR(sessionMachine, COMGETTER(MonitorCount)(&cMonitors)); 2939 com::SafeArray<BOOL> screens(cMonitors); 2940 if (parseScreens(ValueUnion.psz, &screens)) 2941 { 2942 errorArgument("Invalid list of screens specified\n"); 2943 rc = E_FAIL; 2944 break; 2945 } 2946 CHECK_ERROR(sessionMachine, COMSETTER(VideoCaptureScreens)(ComSafeArrayAsInParam(screens))); 2947 break; 2948 } 2933 RT_FALL_THROUGH(); 2949 2934 case MODIFYVM_CAPTURE_FILENAME: 2950 { 2951 Bstr bstr; 2952 /* empty string will fall through, leaving bstr empty */ 2953 if (*ValueUnion.psz) 2954 { 2955 char szVCFileAbs[RTPATH_MAX] = ""; 2956 int vrc = RTPathAbs(ValueUnion.psz, szVCFileAbs, sizeof(szVCFileAbs)); 2957 if (RT_FAILURE(vrc)) 2958 { 2959 errorArgument("Cannot convert filename \"%s\" to absolute path\n", ValueUnion.psz); 2960 rc = E_FAIL; 2935 RT_FALL_THROUGH(); 2936 case MODIFYVM_CAPTURE_WIDTH: 2937 RT_FALL_THROUGH(); 2938 case MODIFYVM_CAPTURE_HEIGHT: 2939 RT_FALL_THROUGH(); 2940 case MODIFYVM_CAPTURE_VIDEO_RES: 2941 RT_FALL_THROUGH(); 2942 case MODIFYVM_CAPTURE_VIDEO_RATE: 2943 RT_FALL_THROUGH(); 2944 case MODIFYVM_CAPTURE_VIDEO_FPS: 2945 RT_FALL_THROUGH(); 2946 case MODIFYVM_CAPTURE_MAXTIME: 2947 RT_FALL_THROUGH(); 2948 case MODIFYVM_CAPTURE_MAXSIZE: 2949 RT_FALL_THROUGH(); 2950 case MODIFYVM_CAPTURE_OPTIONS: 2951 { 2952 ComPtr<ICaptureSettings> captureSettings; 2953 CHECK_ERROR_BREAK(machine, COMGETTER(CaptureSettings)(captureSettings.asOutParam())); 2954 SafeIfaceArray <ICaptureScreenSettings> saCaptureScreenScreens; 2955 CHECK_ERROR_BREAK(captureSettings, COMGETTER(Screens)(ComSafeArrayAsOutParam(saCaptureScreenScreens))); 2956 2957 switch (c) 2958 { 2959 case MODIFYVM_CAPTURE: 2960 { 2961 CHECK_ERROR(captureSettings, COMSETTER(Enabled)(ValueUnion.f)); 2961 2962 break; 2962 2963 } 2963 bstr = szVCFileAbs; 2964 } 2965 CHECK_ERROR(sessionMachine, COMSETTER(VideoCaptureFile)(bstr.raw())); 2966 break; 2967 } 2968 case MODIFYVM_CAPTURE_WIDTH: 2969 { 2970 CHECK_ERROR(sessionMachine, COMSETTER(VideoCaptureWidth)(ValueUnion.u32)); 2971 break; 2972 } 2973 case MODIFYVM_CAPTURE_HEIGHT: 2974 { 2975 CHECK_ERROR(sessionMachine, COMSETTER(VideoCaptureHeight)(ValueUnion.u32)); 2976 break; 2977 } 2978 case MODIFYVM_CAPTURE_VIDEO_RES: 2979 { 2980 uint32_t uWidth = 0; 2981 char *pszNext; 2982 int vrc = RTStrToUInt32Ex(ValueUnion.psz, &pszNext, 0, &uWidth); 2983 if (RT_FAILURE(vrc) || vrc != VWRN_TRAILING_CHARS || !pszNext || *pszNext != 'x') 2984 { 2985 errorArgument("Error parsing geomtry '%s' (expected <width>x<height>)", ValueUnion.psz); 2986 rc = E_FAIL; 2987 break; 2988 } 2989 uint32_t uHeight = 0; 2990 vrc = RTStrToUInt32Ex(pszNext+1, NULL, 0, &uHeight); 2991 if (vrc != VINF_SUCCESS) 2992 { 2993 errorArgument("Error parsing geomtry '%s' (expected <width>x<height>)", ValueUnion.psz); 2994 rc = E_FAIL; 2995 break; 2996 } 2997 CHECK_ERROR(sessionMachine, COMSETTER(VideoCaptureWidth)(uWidth)); 2998 CHECK_ERROR(sessionMachine, COMSETTER(VideoCaptureHeight)(uHeight)); 2999 break; 3000 } 3001 case MODIFYVM_CAPTURE_VIDEO_RATE: 3002 { 3003 CHECK_ERROR(sessionMachine, COMSETTER(VideoCaptureRate)(ValueUnion.u32)); 3004 break; 3005 } 3006 case MODIFYVM_CAPTURE_VIDEO_FPS: 3007 { 3008 CHECK_ERROR(sessionMachine, COMSETTER(VideoCaptureFPS)(ValueUnion.u32)); 3009 break; 3010 } 3011 case MODIFYVM_CAPTURE_MAXTIME: 3012 { 3013 CHECK_ERROR(sessionMachine, COMSETTER(VideoCaptureMaxTime)(ValueUnion.u32)); 3014 break; 3015 } 3016 case MODIFYVM_CAPTURE_MAXSIZE: 3017 { 3018 CHECK_ERROR(sessionMachine, COMSETTER(VideoCaptureMaxFileSize)(ValueUnion.u32)); 3019 break; 3020 } 3021 case MODIFYVM_CAPTURE_OPTIONS: 3022 { 3023 Bstr bstr(ValueUnion.psz); 3024 CHECK_ERROR(sessionMachine, COMSETTER(VideoCaptureOptions)(bstr.raw())); 2964 case MODIFYVM_CAPTURE_SCREENS: 2965 { 2966 ULONG cMonitors = 64; 2967 CHECK_ERROR(sessionMachine, COMGETTER(MonitorCount)(&cMonitors)); 2968 com::SafeArray<BOOL> screens(cMonitors); 2969 if (parseScreens(ValueUnion.psz, &screens)) 2970 { 2971 errorArgument("Invalid list of screens specified\n"); 2972 rc = E_FAIL; 2973 break; 2974 } 2975 2976 if (cMonitors > saCaptureScreenScreens.size()) /* Paranoia. */ 2977 cMonitors = saCaptureScreenScreens.size(); 2978 2979 for (size_t i = 0; i < cMonitors; ++i) 2980 CHECK_ERROR_BREAK(saCaptureScreenScreens[i], COMSETTER(Enabled)(screens[i])); 2981 break; 2982 } 2983 case MODIFYVM_CAPTURE_FILENAME: 2984 { 2985 Bstr bstr; 2986 /* empty string will fall through, leaving bstr empty */ 2987 if (*ValueUnion.psz) 2988 { 2989 char szVCFileAbs[RTPATH_MAX] = ""; 2990 int vrc = RTPathAbs(ValueUnion.psz, szVCFileAbs, sizeof(szVCFileAbs)); 2991 if (RT_FAILURE(vrc)) 2992 { 2993 errorArgument("Cannot convert filename \"%s\" to absolute path\n", ValueUnion.psz); 2994 rc = E_FAIL; 2995 break; 2996 } 2997 bstr = szVCFileAbs; 2998 } 2999 3000 for (size_t i = 0; i < saCaptureScreenScreens.size(); ++i) 3001 CHECK_ERROR(saCaptureScreenScreens[i], COMSETTER(FileName)(bstr.raw())); 3002 break; 3003 } 3004 case MODIFYVM_CAPTURE_WIDTH: 3005 { 3006 for (size_t i = 0; i < saCaptureScreenScreens.size(); ++i) 3007 CHECK_ERROR(saCaptureScreenScreens[i], COMSETTER(VideoWidth)(ValueUnion.u32)); 3008 break; 3009 } 3010 case MODIFYVM_CAPTURE_HEIGHT: 3011 { 3012 for (size_t i = 0; i < saCaptureScreenScreens.size(); ++i) 3013 CHECK_ERROR(saCaptureScreenScreens[i], COMSETTER(VideoHeight)(ValueUnion.u32)); 3014 break; 3015 } 3016 case MODIFYVM_CAPTURE_VIDEO_RES: 3017 { 3018 uint32_t uWidth = 0; 3019 char *pszNext; 3020 int vrc = RTStrToUInt32Ex(ValueUnion.psz, &pszNext, 0, &uWidth); 3021 if (RT_FAILURE(vrc) || vrc != VWRN_TRAILING_CHARS || !pszNext || *pszNext != 'x') 3022 { 3023 errorArgument("Error parsing geomtry '%s' (expected <width>x<height>)", ValueUnion.psz); 3024 rc = E_FAIL; 3025 break; 3026 } 3027 uint32_t uHeight = 0; 3028 vrc = RTStrToUInt32Ex(pszNext+1, NULL, 0, &uHeight); 3029 if (vrc != VINF_SUCCESS) 3030 { 3031 errorArgument("Error parsing geomtry '%s' (expected <width>x<height>)", ValueUnion.psz); 3032 rc = E_FAIL; 3033 break; 3034 } 3035 3036 for (size_t i = 0; i < saCaptureScreenScreens.size(); ++i) 3037 { 3038 CHECK_ERROR(saCaptureScreenScreens[i], COMSETTER(VideoWidth)(uWidth)); 3039 CHECK_ERROR(saCaptureScreenScreens[i], COMSETTER(VideoHeight)(uHeight)); 3040 } 3041 break; 3042 } 3043 case MODIFYVM_CAPTURE_VIDEO_RATE: 3044 { 3045 for (size_t i = 0; i < saCaptureScreenScreens.size(); ++i) 3046 CHECK_ERROR(saCaptureScreenScreens[i], COMSETTER(VideoRate)(ValueUnion.u32)); 3047 break; 3048 } 3049 case MODIFYVM_CAPTURE_VIDEO_FPS: 3050 { 3051 for (size_t i = 0; i < saCaptureScreenScreens.size(); ++i) 3052 CHECK_ERROR(saCaptureScreenScreens[i], COMSETTER(VideoFPS)(ValueUnion.u32)); 3053 break; 3054 } 3055 case MODIFYVM_CAPTURE_MAXTIME: 3056 { 3057 for (size_t i = 0; i < saCaptureScreenScreens.size(); ++i) 3058 CHECK_ERROR(saCaptureScreenScreens[i], COMSETTER(MaxTime)(ValueUnion.u32)); 3059 break; 3060 } 3061 case MODIFYVM_CAPTURE_MAXSIZE: 3062 { 3063 for (size_t i = 0; i < saCaptureScreenScreens.size(); ++i) 3064 CHECK_ERROR(saCaptureScreenScreens[i], COMSETTER(MaxFileSize)(ValueUnion.u32)); 3065 break; 3066 } 3067 case MODIFYVM_CAPTURE_OPTIONS: 3068 { 3069 Bstr bstr(ValueUnion.psz); 3070 for (size_t i = 0; i < saCaptureScreenScreens.size(); ++i) 3071 CHECK_ERROR(saCaptureScreenScreens[i], COMSETTER(Options)(bstr.raw())); 3072 break; 3073 } 3074 } 3075 3025 3076 break; 3026 3077 } -
trunk/src/VBox/Frontends/VirtualBox/src/converter/UIConverterBackendGlobal.cpp
r75087 r75251 1403 1403 case IndicatorType_SharedFolders: strResult = "SharedFolders"; break; 1404 1404 case IndicatorType_Display: strResult = "Display"; break; 1405 case IndicatorType_ VideoCapture:strResult = "VideoCapture"; break;1405 case IndicatorType_Capture: strResult = "VideoCapture"; break; 1406 1406 case IndicatorType_Features: strResult = "Features"; break; 1407 1407 case IndicatorType_Mouse: strResult = "Mouse"; break; … … 1430 1430 keys << "SharedFolders"; values << IndicatorType_SharedFolders; 1431 1431 keys << "Display"; values << IndicatorType_Display; 1432 keys << "VideoCapture"; values << IndicatorType_ VideoCapture;1432 keys << "VideoCapture"; values << IndicatorType_Capture; 1433 1433 keys << "Features"; values << IndicatorType_Features; 1434 1434 keys << "Mouse"; values << IndicatorType_Mouse; … … 1455 1455 case IndicatorType_SharedFolders: strResult = QApplication::translate("VBoxGlobal", "Shared Folders", "IndicatorType"); break; 1456 1456 case IndicatorType_Display: strResult = QApplication::translate("VBoxGlobal", "Display", "IndicatorType"); break; 1457 case IndicatorType_ VideoCapture: strResult = QApplication::translate("VBoxGlobal", "Video Capture", "IndicatorType"); break;1457 case IndicatorType_Capture: strResult = QApplication::translate("VBoxGlobal", "Video Capture", "IndicatorType"); break; 1458 1458 case IndicatorType_Features: strResult = QApplication::translate("VBoxGlobal", "Features", "IndicatorType"); break; 1459 1459 case IndicatorType_Mouse: strResult = QApplication::translate("VBoxGlobal", "Mouse", "IndicatorType"); break; … … 1481 1481 case IndicatorType_SharedFolders: return UIIconPool::iconSet(":/sf_16px.png"); 1482 1482 case IndicatorType_Display: return UIIconPool::iconSet(":/display_software_16px.png"); 1483 case IndicatorType_ VideoCapture: return UIIconPool::iconSet(":/video_capture_16px.png");1483 case IndicatorType_Capture: return UIIconPool::iconSet(":/video_capture_16px.png"); 1484 1484 case IndicatorType_Features: return UIIconPool::iconSet(":/vtx_amdv_16px.png"); 1485 1485 case IndicatorType_Mouse: return UIIconPool::iconSet(":/mouse_16px.png"); -
trunk/src/VBox/Frontends/VirtualBox/src/extradata/UIExtraDataDefs.h
r75224 r75251 765 765 IndicatorType_SharedFolders, 766 766 IndicatorType_Display, 767 IndicatorType_ VideoCapture,767 IndicatorType_Capture, 768 768 IndicatorType_Features, 769 769 IndicatorType_Mouse, -
trunk/src/VBox/Frontends/VirtualBox/src/globals/UIActionPoolRuntime.cpp
r75209 r75251 3307 3307 m_pool[UIActionIndexRT_M_View_S_TakeScreenshot] = new UIActionSimpleRuntimePerformTakeScreenshot(this); 3308 3308 m_pool[UIActionIndexRT_M_View_M_VideoCapture] = new UIActionMenuRuntimeVideoCapture(this); 3309 m_pool[UIActionIndexRT_M_View_M_ VideoCapture_S_Settings] = new UIActionSimpleRuntimeShowVideoCaptureSettings(this);3310 m_pool[UIActionIndexRT_M_View_M_ VideoCapture_T_Start] = new UIActionToggleRuntimeVideoCapture(this);3309 m_pool[UIActionIndexRT_M_View_M_Capture_S_Settings] = new UIActionSimpleRuntimeShowVideoCaptureSettings(this); 3310 m_pool[UIActionIndexRT_M_View_M_Capture_T_Start] = new UIActionToggleRuntimeVideoCapture(this); 3311 3311 m_pool[UIActionIndexRT_M_View_T_VRDEServer] = new UIActionToggleRuntimeVRDEServer(this); 3312 3312 m_pool[UIActionIndexRT_M_View_M_MenuBar] = new UIActionMenuRuntimeMenuBar(this); … … 3662 3662 updateMenuViewVideoCapture(); 3663 3663 /* 'Video Capture Start' action: */ 3664 fSeparator = addAction(pMenu, action(UIActionIndexRT_M_View_M_ VideoCapture_T_Start)) || fSeparator;3664 fSeparator = addAction(pMenu, action(UIActionIndexRT_M_View_M_Capture_T_Start)) || fSeparator; 3665 3665 /* 'VRDE Server' action: */ 3666 3666 fSeparator = addAction(pMenu, action(UIActionIndexRT_M_View_T_VRDEServer)) || fSeparator; … … 3777 3777 3778 3778 /* 'Video Capture Settings' action: */ 3779 fSeparator = addAction(pMenu, action(UIActionIndexRT_M_View_M_ VideoCapture_S_Settings)) || fSeparator;3779 fSeparator = addAction(pMenu, action(UIActionIndexRT_M_View_M_Capture_S_Settings)) || fSeparator; 3780 3780 3781 3781 /* Separator: */ … … 3787 3787 3788 3788 /* 'Start Video Capture' action: */ 3789 fSeparator = addAction(pMenu, action(UIActionIndexRT_M_View_M_ VideoCapture_T_Start)) || fSeparator;3789 fSeparator = addAction(pMenu, action(UIActionIndexRT_M_View_M_Capture_T_Start)) || fSeparator; 3790 3790 3791 3791 /* Mark menu as valid: */ -
trunk/src/VBox/Frontends/VirtualBox/src/globals/UIActionPoolRuntime.h
r75207 r75251 65 65 UIActionIndexRT_M_View_S_TakeScreenshot, 66 66 UIActionIndexRT_M_View_M_VideoCapture, 67 UIActionIndexRT_M_View_M_ VideoCapture_S_Settings,68 UIActionIndexRT_M_View_M_ VideoCapture_T_Start,67 UIActionIndexRT_M_View_M_Capture_S_Settings, 68 UIActionIndexRT_M_View_M_Capture_T_Start, 69 69 UIActionIndexRT_M_View_T_VRDEServer, 70 70 UIActionIndexRT_M_View_M_MenuBar, -
trunk/src/VBox/Frontends/VirtualBox/src/globals/UIMainEventListener.cpp
r73469 r75251 375 375 break; 376 376 } 377 case KVBoxEventType_On VideoCaptureChanged:378 { 379 emit sig VideoCaptureChange();377 case KVBoxEventType_OnCaptureChanged: 378 { 379 emit sigCaptureChange(); 380 380 break; 381 381 } -
trunk/src/VBox/Frontends/VirtualBox/src/globals/UIMainEventListener.h
r74942 r75251 124 124 /** Notifies about VRDE device state change. */ 125 125 void sigVRDEChange(); 126 /** Notifies about Video Capture device state change. */127 void sig VideoCaptureChange();126 /** Notifies about capture state change. */ 127 void sigCaptureChange(); 128 128 /** Notifies about USB controller state change. */ 129 129 void sigUSBControllerChange(); -
trunk/src/VBox/Frontends/VirtualBox/src/globals/UIPopupCenter.cpp
r73953 r75251 570 570 } 571 571 572 void UIPopupCenter::cannotToggle VideoCapture(QWidget *pParent, const CMachine &comMachine, bool fEnable)572 void UIPopupCenter::cannotToggleCapture(QWidget *pParent, const CMachine &comMachine, bool fEnable) 573 573 { 574 574 /* Get machine-name preserving error-info: */ -
trunk/src/VBox/Frontends/VirtualBox/src/globals/UIPopupCenter.h
r73953 r75251 162 162 void cannotDetachWebCam(QWidget *pParent, const CEmulatedUSB &comDispatcher, 163 163 const QString &strWebCamName, const QString &strMachineName); 164 void cannotToggle VideoCapture(QWidget *pParent, const CMachine &comMachine, bool fEnable);164 void cannotToggleCapture(QWidget *pParent, const CMachine &comMachine, bool fEnable); 165 165 void cannotToggleVRDEServer(QWidget *pParent, const CVRDEServer &comServer, 166 166 const QString &strMachineName, bool fEnable); -
trunk/src/VBox/Frontends/VirtualBox/src/manager/details/UIDetailsElements.cpp
r74049 r75251 5 5 6 6 /* 7 * Copyright (C) 2012-201 7Oracle Corporation7 * Copyright (C) 2012-2018 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 44 44 # include "CMediumAttachment.h" 45 45 # include "CAudioAdapter.h" 46 # include "CCaptureSettings.h" 47 # include "CCaptureScreenSettings.h" 46 48 # include "CNetworkAdapter.h" 47 49 # include "CSerialPort.h" … … 447 449 } 448 450 449 /* Video Capture info: */ 450 if (machine.GetVideoCaptureEnabled()) 451 { 451 /* Capture info: */ 452 CCaptureSettings captureSettings = machine.GetCaptureSettings(); 453 if (captureSettings.GetEnabled()) 454 { 455 /* For now all screens have the same config: */ 456 CCaptureScreenSettings captureScreen0Settings = captureSettings.GetScreenSettings(0); 457 458 /** @todo r=andy Refine these texts (wrt audio and/or video). */ 452 459 table << UITextTableLine(QApplication::translate("UIDetails", "Video Capture File", "details (display/video capture)"), 453 machine.GetVideoCaptureFile());460 captureScreen0Settings.GetFileName()); 454 461 table << UITextTableLine(QApplication::translate("UIDetails", "Video Capture Attributes", "details (display/video capture)"), 455 462 QApplication::translate("UIDetails", "Frame Size: %1x%2, Frame Rate: %3fps, Bit Rate: %4kbps") 456 .arg( machine.GetVideoCaptureWidth()).arg(machine.GetVideoCaptureHeight())457 .arg( machine.GetVideoCaptureFPS()).arg(machine.GetVideoCaptureRate()));463 .arg(captureScreen0Settings.GetVideoWidth()).arg(captureScreen0Settings.GetVideoHeight()) 464 .arg(captureScreen0Settings.GetVideoFPS()).arg(captureScreen0Settings.GetVideoRate())); 458 465 } 459 466 else 460 467 { 468 /** @todo r=andy Refine these texts (wrt audio and/or video). */ 461 469 table << UITextTableLine(QApplication::translate("UIDetails", "Video Capture", "details (display/video capture)"), 462 470 QApplication::translate("UIDetails", "Disabled", "details (display/video capture)")); -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIConsoleEventHandler.cpp
r70075 r75251 188 188 << KVBoxEventType_OnVRDEServerChanged 189 189 << KVBoxEventType_OnVRDEServerInfoChanged 190 << KVBoxEventType_On VideoCaptureChanged190 << KVBoxEventType_OnCaptureChanged 191 191 << KVBoxEventType_OnUSBControllerChanged 192 192 << KVBoxEventType_OnUSBDeviceStateChanged -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIIndicatorsPool.cpp
r74942 r75251 5 5 6 6 /* 7 * Copyright (C) 2010-201 7Oracle Corporation7 * Copyright (C) 2010-2018 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 43 43 /* COM includes: */ 44 44 # include "CAudioAdapter.h" 45 # include "CCaptureSettings.h" 46 # include "CCaptureScreenSettings.h" 45 47 # include "CConsole.h" 46 48 # include "CMachine.h" … … 781 783 782 784 /** UISessionStateStatusBarIndicator extension for Runtime UI: Video-capture indicator. */ 783 class UIIndicator VideoCapture : public UISessionStateStatusBarIndicator785 class UIIndicatorCapture : public UISessionStateStatusBarIndicator 784 786 { 785 787 Q_OBJECT; … … 788 790 Q_PROPERTY(double rotationAngle READ rotationAngle WRITE setRotationAngle); 789 791 790 /** Video-capture states. */791 enum UIIndicatorState VideoCapture792 { 793 UIIndicatorState VideoCapture_Disabled = 0,794 UIIndicatorState VideoCapture_Enabled = 1,795 UIIndicatorState VideoCapture_Paused = 2792 /** Capture states. */ 793 enum UIIndicatorStateCapture 794 { 795 UIIndicatorStateCapture_Disabled = 0, 796 UIIndicatorStateCapture_Enabled = 1, 797 UIIndicatorStateCapture_Paused = 2 796 798 }; 797 799 798 /** Video-capture modes. */799 enum UIIndicatorState VideoCaptureMode800 { 801 UIIndicatorState VideoCaptureMode_None = RT_BIT(0),802 UIIndicatorState VideoCaptureMode_Video = RT_BIT(1),803 UIIndicatorState VideoCaptureMode_Audio = RT_BIT(2)800 /** Capture modes. */ 801 enum UIIndicatorStateCaptureMode 802 { 803 UIIndicatorStateCaptureMode_None = RT_BIT(0), 804 UIIndicatorStateCaptureMode_Video = RT_BIT(1), 805 UIIndicatorStateCaptureMode_Audio = RT_BIT(2) 804 806 }; 805 807 … … 807 809 808 810 /** Constructor, passes @a pSession to the UISessionStateStatusBarIndicator constructor. */ 809 UIIndicator VideoCapture(UISession *pSession)810 : UISessionStateStatusBarIndicator(IndicatorType_ VideoCapture, pSession)811 UIIndicatorCapture(UISession *pSession) 812 : UISessionStateStatusBarIndicator(IndicatorType_Capture, pSession) 811 813 , m_pAnimation(0) 812 814 , m_dRotationAngle(0) 813 , m_eCaptureMode(UIIndicatorState VideoCaptureMode_None)815 , m_eCaptureMode(UIIndicatorStateCaptureMode_None) 814 816 { 815 817 /* Assign state-icons: */ 816 setStateIcon(UIIndicatorState VideoCapture_Disabled, UIIconPool::iconSet(":/video_capture_16px.png"));817 setStateIcon(UIIndicatorState VideoCapture_Enabled, UIIconPool::iconSet(":/movie_reel_16px.png"));818 setStateIcon(UIIndicatorState VideoCapture_Paused, UIIconPool::iconSet(":/movie_reel_16px.png"));818 setStateIcon(UIIndicatorStateCapture_Disabled, UIIconPool::iconSet(":/video_capture_16px.png")); 819 setStateIcon(UIIndicatorStateCapture_Enabled, UIIconPool::iconSet(":/movie_reel_16px.png")); 820 setStateIcon(UIIndicatorStateCapture_Paused, UIIconPool::iconSet(":/movie_reel_16px.png")); 819 821 /* Create *enabled* state animation: */ 820 822 m_pAnimation = UIAnimationLoop::installAnimationLoop(this, "rotationAngle", … … 833 835 switch (iState) 834 836 { 835 case UIIndicatorState VideoCapture_Disabled:837 case UIIndicatorStateCapture_Disabled: 836 838 m_pAnimation->stop(); 837 839 m_dRotationAngle = 0; 838 840 break; 839 case UIIndicatorState VideoCapture_Enabled:841 case UIIndicatorStateCapture_Enabled: 840 842 m_pAnimation->start(); 841 843 break; 842 case UIIndicatorState VideoCapture_Paused:844 case UIIndicatorStateCapture_Paused: 843 845 m_pAnimation->stop(); 844 846 break; … … 858 860 QPainter painter(this); 859 861 /* Configure painter for *enabled* state: */ 860 if (state() == UIIndicatorState VideoCapture_Enabled)862 if (state() == UIIndicatorStateCapture_Enabled) 861 863 { 862 864 /* Configure painter for smooth animation: */ … … 882 884 883 885 /* Update indicator state early: */ 884 if (!machine.GetVideoCaptureEnabled()) 885 setState(UIIndicatorStateVideoCapture_Disabled); 886 CCaptureSettings captureSettings = machine.GetCaptureSettings(); 887 /* For now all screens have the same config: */ 888 CCaptureScreenSettings captureScreen0Settings = captureSettings.GetScreenSettings(0); 889 if (!captureScreen0Settings.GetEnabled()) 890 setState(UIIndicatorStateCapture_Disabled); 886 891 else if (!fMachinePaused) 887 setState(UIIndicatorState VideoCapture_Enabled);892 setState(UIIndicatorStateCapture_Enabled); 888 893 else 889 setState(UIIndicatorState VideoCapture_Paused);894 setState(UIIndicatorStateCapture_Paused); 890 895 891 896 updateCaptureMode(); … … 895 900 switch (state()) 896 901 { 897 case UIIndicatorState VideoCapture_Disabled:902 case UIIndicatorStateCapture_Disabled: 898 903 { 899 strFullData += s_strTableRow1 904 strFullData += s_strTableRow1 /** @todo r=andy Refine this tooltip (audio and/or video). */ 900 905 .arg(QApplication::translate("UIIndicatorsPool", "Video capture disabled", "Video capture tooltip")); 901 906 break; 902 907 } 903 case UIIndicatorState VideoCapture_Enabled:904 case UIIndicatorState VideoCapture_Paused:908 case UIIndicatorStateCapture_Enabled: 909 case UIIndicatorStateCapture_Paused: 905 910 { 906 911 QString strToolTip; 907 if ( m_eCaptureMode & UIIndicatorState VideoCaptureMode_Audio &&908 m_eCaptureMode & UIIndicatorState VideoCaptureMode_Video)912 if ( m_eCaptureMode & UIIndicatorStateCaptureMode_Audio && 913 m_eCaptureMode & UIIndicatorStateCaptureMode_Video) 909 914 strToolTip = "Video/audio capture file"; 910 else if (m_eCaptureMode & UIIndicatorState VideoCaptureMode_Audio)915 else if (m_eCaptureMode & UIIndicatorStateCaptureMode_Audio) 911 916 strToolTip = "Audio capture file"; 912 else if (m_eCaptureMode & UIIndicatorState VideoCaptureMode_Video)917 else if (m_eCaptureMode & UIIndicatorStateCaptureMode_Video) 913 918 strToolTip = "Video capture file"; 914 919 915 strFullData += s_strTableRow2 920 strFullData += s_strTableRow2 /** @todo r=andy Refine this tooltip (audio and/or video). */ 916 921 .arg(QApplication::translate("UIIndicatorsPool", strToolTip.toLatin1().constData(), "Video capture tooltip")) 917 .arg( machine.GetVideoCaptureFile());922 .arg(captureScreen0Settings.GetFileName()); 918 923 break; 919 924 } … … 935 940 void setRotationAngle(double dRotationAngle) { m_dRotationAngle = dRotationAngle; update(); } 936 941 937 /* Parses C Machine::videoCaptureOptions and updates m_eCaptureMode accordingly. */942 /* Parses CaptureScreenSettings::Options and updates m_eCaptureMode accordingly. */ 938 943 void updateCaptureMode() 939 944 { 940 m_eCaptureMode = UIIndicatorState VideoCaptureMode_None;945 m_eCaptureMode = UIIndicatorStateCaptureMode_None; 941 946 942 947 /* Get machine: */ … … 946 951 if (machine.isNull()) 947 952 return; 948 QStringList strOptionsPairList = machine.GetVideoCaptureOptions().split(",", QString::SkipEmptyParts); 953 954 CCaptureSettings captureSettings = machine.GetCaptureSettings(); 955 /* For now all screens have the same config: */ 956 CCaptureScreenSettings captureScreen0Settings = captureSettings.GetScreenSettings(0); 957 958 QStringList strOptionsPairList = captureScreen0Settings.GetOptions().split(",", QString::SkipEmptyParts); 949 959 950 960 for (int i = 0; i < strOptionsPairList.size(); ++i) … … 952 962 if (strOptionsPairList.at(i).contains("vc_enabled", Qt::CaseInsensitive) && 953 963 strOptionsPairList.at(i).contains("true", Qt::CaseInsensitive)) 954 m_eCaptureMode = (UIIndicatorState VideoCaptureMode)((int)m_eCaptureMode | (int)UIIndicatorStateVideoCaptureMode_Video);964 m_eCaptureMode = (UIIndicatorStateCaptureMode)((int)m_eCaptureMode | (int)UIIndicatorStateCaptureMode_Video); 955 965 956 966 if (strOptionsPairList.at(i).contains("ac_enabled", Qt::CaseInsensitive) && 957 967 strOptionsPairList.at(i).contains("true", Qt::CaseInsensitive)) 958 m_eCaptureMode = (UIIndicatorState VideoCaptureMode)((int)m_eCaptureMode | (int)UIIndicatorStateVideoCaptureMode_Audio);968 m_eCaptureMode = (UIIndicatorStateCaptureMode)((int)m_eCaptureMode | (int)UIIndicatorStateCaptureMode_Audio); 959 969 } 960 970 } … … 965 975 double m_dRotationAngle; 966 976 967 UIIndicatorState VideoCaptureMode m_eCaptureMode;977 UIIndicatorStateCaptureMode m_eCaptureMode; 968 978 }; 969 979 … … 1464 1474 case IndicatorType_SharedFolders: m_pool[indicatorType] = new UIIndicatorSharedFolders(m_pSession); break; 1465 1475 case IndicatorType_Display: m_pool[indicatorType] = new UIIndicatorDisplay(m_pSession); break; 1466 case IndicatorType_ VideoCapture: m_pool[indicatorType] = new UIIndicatorVideoCapture(m_pSession); break;1476 case IndicatorType_Capture: m_pool[indicatorType] = new UIIndicatorCapture(m_pSession); break; 1467 1477 case IndicatorType_Features: m_pool[indicatorType] = new UIIndicatorFeatures(m_pSession); break; 1468 1478 case IndicatorType_Mouse: m_pool[indicatorType] = new UIIndicatorMouse(m_pSession); break; -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.cpp
r75158 r75251 5 5 6 6 /* 7 * Copyright (C) 2010-201 7Oracle Corporation7 * Copyright (C) 2010-2018 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 77 77 /* COM includes: */ 78 78 # include "CAudioAdapter.h" 79 # include "CCaptureSettings.h" 79 80 # include "CVirtualBoxErrorInfo.h" 80 81 # include "CMachineDebugger.h" … … 1052 1053 m_pRunningOrPausedActions->addAction(actionPool()->action(UIActionIndexRT_M_View_S_TakeScreenshot)); 1053 1054 m_pRunningOrPausedActions->addAction(actionPool()->action(UIActionIndexRT_M_View_M_VideoCapture)); 1054 m_pRunningOrPausedActions->addAction(actionPool()->action(UIActionIndexRT_M_View_M_ VideoCapture_S_Settings));1055 m_pRunningOrPausedActions->addAction(actionPool()->action(UIActionIndexRT_M_View_M_ VideoCapture_T_Start));1055 m_pRunningOrPausedActions->addAction(actionPool()->action(UIActionIndexRT_M_View_M_Capture_S_Settings)); 1056 m_pRunningOrPausedActions->addAction(actionPool()->action(UIActionIndexRT_M_View_M_Capture_T_Start)); 1056 1057 m_pRunningOrPausedActions->addAction(actionPool()->action(UIActionIndexRT_M_View_T_VRDEServer)); 1057 1058 m_pRunningOrPausedActions->addAction(actionPool()->action(UIActionIndexRT_M_View_M_MenuBar)); … … 1136 1137 connect(actionPool()->action(UIActionIndexRT_M_View_S_TakeScreenshot), SIGNAL(triggered()), 1137 1138 this, SLOT(sltTakeScreenshot())); 1138 connect(actionPool()->action(UIActionIndexRT_M_View_M_ VideoCapture_S_Settings), SIGNAL(triggered()),1139 this, SLOT(sltOpen VideoCaptureOptions()));1140 connect(actionPool()->action(UIActionIndexRT_M_View_M_ VideoCapture_T_Start), SIGNAL(toggled(bool)),1141 this, SLOT(sltToggle VideoCapture(bool)));1139 connect(actionPool()->action(UIActionIndexRT_M_View_M_Capture_S_Settings), SIGNAL(triggered()), 1140 this, SLOT(sltOpenCaptureOptions())); 1141 connect(actionPool()->action(UIActionIndexRT_M_View_M_Capture_T_Start), SIGNAL(toggled(bool)), 1142 this, SLOT(sltToggleCapture(bool))); 1142 1143 connect(actionPool()->action(UIActionIndexRT_M_View_T_VRDEServer), SIGNAL(toggled(bool)), 1143 1144 this, SLOT(sltToggleVRDE(bool))); … … 2090 2091 } 2091 2092 2092 void UIMachineLogic::sltOpen VideoCaptureOptions()2093 void UIMachineLogic::sltOpenCaptureOptions() 2093 2094 { 2094 2095 /* Open VM settings : Display page : Video Capture tab: */ … … 2096 2097 } 2097 2098 2098 void UIMachineLogic::sltToggle VideoCapture(bool fEnabled)2099 void UIMachineLogic::sltToggleCapture(bool fEnabled) 2099 2100 { 2100 2101 /* Do not process if window(s) missed! */ … … 2103 2104 2104 2105 /* Make sure something had changed: */ 2105 if (machine().GetVideoCaptureEnabled() == static_cast<BOOL>(fEnabled)) 2106 CCaptureSettings captureSettings = machine().GetCaptureSettings(); 2107 if (captureSettings.GetEnabled() == static_cast<BOOL>(fEnabled)) 2106 2108 return; 2107 2109 2108 2110 /* Update Video Capture state: */ 2109 machine().SetVideoCaptureEnabled(fEnabled);2110 if (! machine().isOk())2111 captureSettings.SetEnabled(fEnabled); 2112 if (!captureSettings.isOk()) 2111 2113 { 2112 2114 /* Make sure action is updated: */ 2113 uisession()->updateStatus VideoCapture();2115 uisession()->updateStatusCapture(); 2114 2116 /* Notify about the error: */ 2115 return popupCenter().cannotToggle VideoCapture(activeMachineWindow(), machine(), fEnabled);2117 return popupCenter().cannotToggleCapture(activeMachineWindow(), machine(), fEnabled); 2116 2118 } 2117 2119 … … 2121 2123 { 2122 2124 /* Make sure action is updated: */ 2123 uisession()->updateStatus VideoCapture();2125 uisession()->updateStatusCapture(); 2124 2126 /* Notify about the error: */ 2125 2127 return msgCenter().cannotSaveMachineSettings(machine()); -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UIMachineLogic.h
r75158 r75251 291 291 void sltToggleGuestAutoresize(bool fEnabled); 292 292 void sltTakeScreenshot(); 293 void sltOpen VideoCaptureOptions();294 void sltToggle VideoCapture(bool fEnabled);293 void sltOpenCaptureOptions(); 294 void sltToggleCapture(bool fEnabled); 295 295 void sltToggleVRDE(bool fEnabled); 296 296 -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UISession.cpp
r75211 r75251 60 60 /* COM includes: */ 61 61 # include "CAudioAdapter.h" 62 # include "CCaptureSettings.h" 62 63 # include "CSystemProperties.h" 63 64 # include "CStorageController.h" … … 721 722 } 722 723 723 void UISession::sltVideoCaptureChange() 724 { 725 /* Check/Uncheck Video Capture action depending on feature status: */ 726 actionPool()->action(UIActionIndexRT_M_View_M_VideoCapture_T_Start)->blockSignals(true); 727 actionPool()->action(UIActionIndexRT_M_View_M_VideoCapture_T_Start)->setChecked(machine().GetVideoCaptureEnabled()); 728 actionPool()->action(UIActionIndexRT_M_View_M_VideoCapture_T_Start)->blockSignals(false); 729 730 /* Notify listeners about Video Capture change: */ 731 emit sigVideoCaptureChange(); 724 void UISession::sltCaptureChange() 725 { 726 CCaptureSettings captureSettings = machine().GetCaptureSettings(); 727 728 /* Check/Uncheck Capture action depending on feature status: */ 729 actionPool()->action(UIActionIndexRT_M_View_M_Capture_T_Start)->blockSignals(true); 730 actionPool()->action(UIActionIndexRT_M_View_M_Capture_T_Start)->setChecked(captureSettings.GetEnabled()); 731 actionPool()->action(UIActionIndexRT_M_View_M_Capture_T_Start)->blockSignals(false); 732 733 /* Notify listeners about Capture change: */ 734 emit sigCaptureChange(); 732 735 } 733 736 … … 1131 1134 1132 1135 connect(gConsoleEvents, SIGNAL(sigVideoCaptureChange()), 1133 this, SLOT(slt VideoCaptureChange()));1136 this, SLOT(sltCaptureChange())); 1134 1137 1135 1138 connect(gConsoleEvents, SIGNAL(sigNetworkAdapterChange(CNetworkAdapter)), -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/UISession.h
r74942 r75251 259 259 void updateStatusVRDE() { sltVRDEChange(); } 260 260 /** Updates Video Capture action state. */ 261 void updateStatus VideoCapture() { sltVideoCaptureChange(); }261 void updateStatusCapture() { sltCaptureChange(); } 262 262 /** Updates Audio output action state. */ 263 263 void updateAudioOutput() { sltAudioAdapterChange(); } … … 305 305 void sigMediumChange(const CMediumAttachment &mediumAttachment); 306 306 void sigVRDEChange(); 307 void sig VideoCaptureChange();307 void sigCaptureChange(); 308 308 void sigUSBControllerChange(); 309 309 void sigUSBDeviceStateChange(const CUSBDevice &device, bool bIsAttached, const CVirtualBoxErrorInfo &error); … … 357 357 void sltAdditionsChange(); 358 358 void sltVRDEChange(); 359 void slt VideoCaptureChange();359 void sltCaptureChange(); 360 360 void sltGuestMonitorChange(KGuestMonitorChangedEventType changeType, ulong uScreenId, QRect screenGeo); 361 361 /** Handles storage device change for @a attachment, which was @a fRemoved and it was @a fSilent for guest. */ -
trunk/src/VBox/Frontends/VirtualBox/src/runtime/normal/UIMachineWindowNormal.cpp
r75211 r75251 219 219 case IndicatorType_SharedFolders: pAction = actionPool()->action(UIActionIndexRT_M_Devices_M_SharedFolders); break; 220 220 case IndicatorType_Display: pAction = actionPool()->action(UIActionIndexRT_M_ViewPopup); break; 221 case IndicatorType_ VideoCapture: pAction = actionPool()->action(UIActionIndexRT_M_View_M_VideoCapture); break;221 case IndicatorType_Capture: pAction = actionPool()->action(UIActionIndexRT_M_View_M_VideoCapture); break; 222 222 case IndicatorType_Mouse: pAction = actionPool()->action(UIActionIndexRT_M_Input_M_Mouse); break; 223 223 case IndicatorType_Keyboard: pAction = actionPool()->action(UIActionIndexRT_M_Input_M_Keyboard); break; … … 640 640 { 641 641 if (iElement & UIVisualElement_VideoCapture) 642 m_pIndicatorsPool->updateAppearance(IndicatorType_ VideoCapture);642 m_pIndicatorsPool->updateAppearance(IndicatorType_Capture); 643 643 } 644 644 } -
trunk/src/VBox/Frontends/VirtualBox/src/settings/machine/UIMachineSettingsDisplay.cpp
r75080 r75251 5 5 6 6 /* 7 * Copyright (C) 2008-201 7Oracle Corporation7 * Copyright (C) 2008-2018 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 31 31 32 32 /* COM includes: */ 33 # include "CCaptureSettings.h" 34 # include "CCaptureScreenSettings.h" 33 35 # include "CExtPack.h" 34 36 # include "CExtPackManager.h" … … 380 382 } 381 383 382 /* Gather old 'Video Capture' data: */ 383 oldDisplayData.m_fVideoCaptureEnabled = m_machine.GetVideoCaptureEnabled(); 384 oldDisplayData.m_strVideoCaptureFolder = QFileInfo(m_machine.GetSettingsFilePath()).absolutePath(); 385 oldDisplayData.m_strVideoCaptureFilePath = m_machine.GetVideoCaptureFile(); 386 oldDisplayData.m_iVideoCaptureFrameWidth = m_machine.GetVideoCaptureWidth(); 387 oldDisplayData.m_iVideoCaptureFrameHeight = m_machine.GetVideoCaptureHeight(); 388 oldDisplayData.m_iVideoCaptureFrameRate = m_machine.GetVideoCaptureFPS(); 389 oldDisplayData.m_iVideoCaptureBitRate = m_machine.GetVideoCaptureRate(); 390 oldDisplayData.m_screens = m_machine.GetVideoCaptureScreens(); 391 oldDisplayData.m_strVideoCaptureOptions = m_machine.GetVideoCaptureOptions(); 384 /* Gather old 'Capture' data: */ 385 CCaptureSettings captureSettings = m_machine.GetCaptureSettings(); 386 oldDisplayData.m_fVideoCaptureEnabled = captureSettings.GetEnabled(); 387 388 /* For now we're using the same settings for all screens; so get settings from screen 0 and work with that. */ 389 CCaptureScreenSettings captureScreen0Settings = captureSettings.GetScreenSettings(0); 390 if (!captureScreen0Settings.isNull()) 391 { 392 oldDisplayData.m_strVideoCaptureFolder = QFileInfo(m_machine.GetSettingsFilePath()).absolutePath(); 393 oldDisplayData.m_strVideoCaptureFilePath = captureScreen0Settings.GetFileName(); 394 oldDisplayData.m_iVideoCaptureFrameWidth = captureScreen0Settings.GetVideoWidth(); 395 oldDisplayData.m_iVideoCaptureFrameHeight = captureScreen0Settings.GetVideoHeight(); 396 oldDisplayData.m_iVideoCaptureFrameRate = captureScreen0Settings.GetVideoFPS(); 397 oldDisplayData.m_iVideoCaptureBitRate = captureScreen0Settings.GetVideoRate(); 398 oldDisplayData.m_strVideoCaptureOptions = captureScreen0Settings.GetOptions(); 399 } 400 401 CCaptureScreenSettingsVector captureScreenSettingsVector = captureSettings.GetScreens(); 402 for (int iScreenIndex = 0; iScreenIndex < captureScreenSettingsVector.size(); ++iScreenIndex) 403 { 404 CCaptureScreenSettings captureScreenSettings = captureScreenSettingsVector.at(iScreenIndex); 405 oldDisplayData.m_screens[iScreenIndex] = captureScreenSettings.GetEnabled(); 406 } 392 407 393 408 /* Gather other old display data: */ … … 1493 1508 const UIDataSettingsMachineDisplay &newDisplayData = m_pCache->data(); 1494 1509 1510 CCaptureSettings captureSettings = m_machine.GetCaptureSettings(); 1511 1495 1512 /* Save new 'Video Capture' data for online case: */ 1496 1513 if (isMachineOnline()) … … 1499 1516 if (oldDisplayData.m_fVideoCaptureEnabled) 1500 1517 { 1518 /* Save whether capture is enabled: */ 1519 if (fSuccess && newDisplayData.m_fVideoCaptureEnabled != oldDisplayData.m_fVideoCaptureEnabled) 1520 { 1521 captureSettings.SetEnabled(newDisplayData.m_fVideoCaptureEnabled); 1522 fSuccess = captureSettings.isOk(); 1523 } 1524 1501 1525 // We can still save the *screens* option. 1502 // And finally we should *disable* 'Video Capture' if necessary.1503 1526 /* Save video capture screens: */ 1504 1527 if (fSuccess && newDisplayData.m_screens != oldDisplayData.m_screens) 1505 1528 { 1506 m_machine.SetVideoCaptureScreens(newDisplayData.m_screens); 1507 fSuccess = m_machine.isOk(); 1508 } 1509 /* Save whether video capture is enabled: */ 1510 if (fSuccess && newDisplayData.m_fVideoCaptureEnabled != oldDisplayData.m_fVideoCaptureEnabled) 1511 { 1512 m_machine.SetVideoCaptureEnabled(newDisplayData.m_fVideoCaptureEnabled); 1513 fSuccess = m_machine.isOk(); 1529 CCaptureScreenSettingsVector captureScreenSettingsVector = captureSettings.GetScreens(); 1530 for (int iScreenIndex = 0; fSuccess && iScreenIndex < captureScreenSettingsVector.size(); ++iScreenIndex) 1531 { 1532 CCaptureScreenSettings captureScreenSettings = captureScreenSettingsVector.at(iScreenIndex); 1533 captureScreenSettings.SetEnabled(newDisplayData.m_screens[iScreenIndex]); 1534 fSuccess = captureScreenSettings.isOk(); 1535 } 1514 1536 } 1515 1537 } … … 1517 1539 else 1518 1540 { 1519 // We should save all the options *before* 'Video Capture' activation. 1520 // And finally we should *enable* Video Capture if necessary. 1541 /* Save whether capture is enabled: */ 1542 if (fSuccess && newDisplayData.m_fVideoCaptureEnabled != oldDisplayData.m_fVideoCaptureEnabled) 1543 { 1544 captureSettings.SetEnabled(newDisplayData.m_fVideoCaptureEnabled); 1545 fSuccess = captureSettings.isOk(); 1546 } 1547 1548 CCaptureScreenSettingsVector captureScreenSettingsVector = captureSettings.GetScreens(); 1549 for (int iScreenIndex = 0; fSuccess && iScreenIndex < captureScreenSettingsVector.size(); ++iScreenIndex) 1550 { 1551 CCaptureScreenSettings captureScreenSettings = captureScreenSettingsVector.at(iScreenIndex); 1552 1553 // We should save all the options *before* 'Video Capture' activation. 1554 // And finally we should *enable* Video Capture if necessary. 1555 /* Save video capture file path: */ 1556 if (fSuccess && newDisplayData.m_strVideoCaptureFilePath != oldDisplayData.m_strVideoCaptureFilePath) 1557 { 1558 captureScreenSettings.SetFileName(newDisplayData.m_strVideoCaptureFilePath); 1559 fSuccess = captureScreenSettings.isOk(); 1560 } 1561 /* Save video capture frame width: */ 1562 if (fSuccess && newDisplayData.m_iVideoCaptureFrameWidth != oldDisplayData.m_iVideoCaptureFrameWidth) 1563 { 1564 captureScreenSettings.SetVideoWidth(newDisplayData.m_iVideoCaptureFrameWidth); 1565 fSuccess = captureScreenSettings.isOk(); 1566 } 1567 /* Save video capture frame height: */ 1568 if (fSuccess && newDisplayData.m_iVideoCaptureFrameHeight != oldDisplayData.m_iVideoCaptureFrameHeight) 1569 { 1570 captureScreenSettings.SetVideoHeight(newDisplayData.m_iVideoCaptureFrameHeight); 1571 fSuccess = captureScreenSettings.isOk(); 1572 } 1573 /* Save video capture frame rate: */ 1574 if (fSuccess && newDisplayData.m_iVideoCaptureFrameRate != oldDisplayData.m_iVideoCaptureFrameRate) 1575 { 1576 captureScreenSettings.SetVideoFPS(newDisplayData.m_iVideoCaptureFrameRate); 1577 fSuccess = captureScreenSettings.isOk(); 1578 } 1579 /* Save video capture frame bit rate: */ 1580 if (fSuccess && newDisplayData.m_iVideoCaptureBitRate != oldDisplayData.m_iVideoCaptureBitRate) 1581 { 1582 captureScreenSettings.SetVideoRate(newDisplayData.m_iVideoCaptureBitRate); 1583 fSuccess = captureScreenSettings.isOk(); 1584 } 1585 /* Save video capture screens: */ 1586 if (fSuccess && newDisplayData.m_screens != oldDisplayData.m_screens) 1587 { 1588 captureScreenSettings.SetEnabled(newDisplayData.m_screens[iScreenIndex]); 1589 fSuccess = captureScreenSettings.isOk(); 1590 } 1591 /* Save video capture options: */ 1592 if (fSuccess && newDisplayData.m_strVideoCaptureOptions != oldDisplayData.m_strVideoCaptureOptions) 1593 { 1594 captureScreenSettings.SetOptions(newDisplayData.m_strVideoCaptureOptions); 1595 fSuccess = captureScreenSettings.isOk(); 1596 } 1597 } 1598 } 1599 } 1600 /* Save new 'Video Capture' data for offline case: */ 1601 else 1602 { 1603 // For 'offline', 'powered off' and 'saved' states the order is irrelevant. 1604 /* Save whether video capture is enabled: */ 1605 if (fSuccess && newDisplayData.m_fVideoCaptureEnabled != oldDisplayData.m_fVideoCaptureEnabled) 1606 { 1607 captureSettings.SetEnabled(newDisplayData.m_fVideoCaptureEnabled); 1608 fSuccess = captureSettings.isOk(); 1609 } 1610 1611 CCaptureScreenSettingsVector captureScreenSettingsVector = captureSettings.GetScreens(); 1612 for (int iScreenIndex = 0; fSuccess && iScreenIndex < captureScreenSettingsVector.size(); ++iScreenIndex) 1613 { 1614 CCaptureScreenSettings captureScreenSettings = captureScreenSettingsVector.at(iScreenIndex); 1615 1521 1616 /* Save video capture file path: */ 1522 1617 if (fSuccess && newDisplayData.m_strVideoCaptureFilePath != oldDisplayData.m_strVideoCaptureFilePath) 1523 1618 { 1524 m_machine.SetVideoCaptureFile(newDisplayData.m_strVideoCaptureFilePath);1525 fSuccess = m_machine.isOk();1619 captureScreenSettings.SetFileName(newDisplayData.m_strVideoCaptureFilePath); 1620 fSuccess = captureScreenSettings.isOk(); 1526 1621 } 1527 1622 /* Save video capture frame width: */ 1528 1623 if (fSuccess && newDisplayData.m_iVideoCaptureFrameWidth != oldDisplayData.m_iVideoCaptureFrameWidth) 1529 1624 { 1530 m_machine.SetVideoCaptureWidth(newDisplayData.m_iVideoCaptureFrameWidth);1531 fSuccess = m_machine.isOk();1625 captureScreenSettings.SetVideoWidth(newDisplayData.m_iVideoCaptureFrameWidth); 1626 fSuccess = captureScreenSettings.isOk(); 1532 1627 } 1533 1628 /* Save video capture frame height: */ 1534 1629 if (fSuccess && newDisplayData.m_iVideoCaptureFrameHeight != oldDisplayData.m_iVideoCaptureFrameHeight) 1535 1630 { 1536 m_machine.SetVideoCaptureHeight(newDisplayData.m_iVideoCaptureFrameHeight);1537 fSuccess = m_machine.isOk();1631 captureScreenSettings.SetVideoHeight(newDisplayData.m_iVideoCaptureFrameHeight); 1632 fSuccess = captureScreenSettings.isOk(); 1538 1633 } 1539 1634 /* Save video capture frame rate: */ 1540 1635 if (fSuccess && newDisplayData.m_iVideoCaptureFrameRate != oldDisplayData.m_iVideoCaptureFrameRate) 1541 1636 { 1542 m_machine.SetVideoCaptureFPS(newDisplayData.m_iVideoCaptureFrameRate);1543 fSuccess = m_machine.isOk();1637 captureScreenSettings.SetVideoFPS(newDisplayData.m_iVideoCaptureFrameRate); 1638 fSuccess = captureScreenSettings.isOk(); 1544 1639 } 1545 1640 /* Save video capture frame bit rate: */ 1546 1641 if (fSuccess && newDisplayData.m_iVideoCaptureBitRate != oldDisplayData.m_iVideoCaptureBitRate) 1547 1642 { 1548 m_machine.SetVideoCaptureRate(newDisplayData.m_iVideoCaptureBitRate);1549 fSuccess = m_machine.isOk();1643 captureScreenSettings.SetVideoRate(newDisplayData.m_iVideoCaptureBitRate); 1644 fSuccess = captureScreenSettings.isOk(); 1550 1645 } 1551 /* Save video capture screens: */ 1646 /* Save capture options: */ 1647 if (fSuccess && newDisplayData.m_strVideoCaptureOptions != oldDisplayData.m_strVideoCaptureOptions) 1648 { 1649 captureScreenSettings.SetOptions(newDisplayData.m_strVideoCaptureOptions); 1650 fSuccess = captureScreenSettings.isOk(); 1651 } 1652 /* Save screen enabled state: */ 1552 1653 if (fSuccess && newDisplayData.m_screens != oldDisplayData.m_screens) 1553 1654 { 1554 m_machine.SetVideoCaptureScreens(newDisplayData.m_screens);1555 fSuccess = m_machine.isOk();1655 captureScreenSettings.SetEnabled(newDisplayData.m_screens[iScreenIndex]); 1656 fSuccess = captureScreenSettings.isOk(); 1556 1657 } 1557 /* Save video capture options: */1558 if (fSuccess && newDisplayData.m_strVideoCaptureOptions != oldDisplayData.m_strVideoCaptureOptions)1559 {1560 m_machine.SetVideoCaptureOptions(newDisplayData.m_strVideoCaptureOptions);1561 fSuccess = m_machine.isOk();1562 }1563 /* Save whether video capture is enabled: */1564 if (fSuccess && newDisplayData.m_fVideoCaptureEnabled != oldDisplayData.m_fVideoCaptureEnabled)1565 {1566 m_machine.SetVideoCaptureEnabled(newDisplayData.m_fVideoCaptureEnabled);1567 fSuccess = m_machine.isOk();1568 }1569 }1570 }1571 /* Save new 'Video Capture' data for offline case: */1572 else1573 {1574 // For 'offline', 'powered off' and 'saved' states the order is irrelevant.1575 /* Save whether video capture is enabled: */1576 if (fSuccess && newDisplayData.m_fVideoCaptureEnabled != oldDisplayData.m_fVideoCaptureEnabled)1577 {1578 m_machine.SetVideoCaptureEnabled(newDisplayData.m_fVideoCaptureEnabled);1579 fSuccess = m_machine.isOk();1580 }1581 /* Save video capture file path: */1582 if (fSuccess && newDisplayData.m_strVideoCaptureFilePath != oldDisplayData.m_strVideoCaptureFilePath)1583 {1584 m_machine.SetVideoCaptureFile(newDisplayData.m_strVideoCaptureFilePath);1585 fSuccess = m_machine.isOk();1586 }1587 /* Save video capture frame width: */1588 if (fSuccess && newDisplayData.m_iVideoCaptureFrameWidth != oldDisplayData.m_iVideoCaptureFrameWidth)1589 {1590 m_machine.SetVideoCaptureWidth(newDisplayData.m_iVideoCaptureFrameWidth);1591 fSuccess = m_machine.isOk();1592 }1593 /* Save video capture frame height: */1594 if (fSuccess && newDisplayData.m_iVideoCaptureFrameHeight != oldDisplayData.m_iVideoCaptureFrameHeight)1595 {1596 m_machine.SetVideoCaptureHeight(newDisplayData.m_iVideoCaptureFrameHeight);1597 fSuccess = m_machine.isOk();1598 }1599 /* Save video capture frame rate: */1600 if (fSuccess && newDisplayData.m_iVideoCaptureFrameRate != oldDisplayData.m_iVideoCaptureFrameRate)1601 {1602 m_machine.SetVideoCaptureFPS(newDisplayData.m_iVideoCaptureFrameRate);1603 fSuccess = m_machine.isOk();1604 }1605 /* Save video capture frame bit rate: */1606 if (fSuccess && newDisplayData.m_iVideoCaptureBitRate != oldDisplayData.m_iVideoCaptureBitRate)1607 {1608 m_machine.SetVideoCaptureRate(newDisplayData.m_iVideoCaptureBitRate);1609 fSuccess = m_machine.isOk();1610 }1611 /* Save video capture screens: */1612 if (fSuccess && newDisplayData.m_screens != oldDisplayData.m_screens)1613 {1614 m_machine.SetVideoCaptureScreens(newDisplayData.m_screens);1615 fSuccess = m_machine.isOk();1616 }1617 /* Save video capture options: */1618 if (fSuccess && newDisplayData.m_strVideoCaptureOptions != oldDisplayData.m_strVideoCaptureOptions)1619 {1620 m_machine.SetVideoCaptureOptions(newDisplayData.m_strVideoCaptureOptions);1621 fSuccess = m_machine.isOk();1622 1658 } 1623 1659 } -
trunk/src/VBox/Frontends/VirtualBox/src/snapshots/UISnapshotDetailsWidget.cpp
r72856 r75251 5 5 6 6 /* 7 * Copyright (C) 2008-201 7Oracle Corporation7 * Copyright (C) 2008-2018 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 48 48 /* COM includes: */ 49 49 # include "CAudioAdapter.h" 50 # include "CCaptureSettings.h" 51 # include "CCaptureScreenSettings.h" 50 52 # include "CMachine.h" 51 53 # include "CMedium.h" … … 1745 1747 /* Prepare report: */ 1746 1748 QStringList aReport; 1747 /* Acquire video capture status: */ 1748 if (comMachine.GetVideoCaptureEnabled()) 1749 /* Acquire capture status: */ 1750 CCaptureSettings captureSettings = comMachine.GetCaptureSettings(); 1751 /* For now all screens have the same config: */ 1752 CCaptureScreenSettings captureScreen0Settings = captureSettings.GetScreenSettings(0); 1753 if (captureScreen0Settings.GetEnabled()) 1749 1754 { 1750 1755 /* Video Capture File: */ 1751 aReport << c omMachine.GetVideoCaptureFile();1756 aReport << captureScreen0Settings.GetFileName(); 1752 1757 /* Video Capture Attributes: */ 1753 1758 aReport << QApplication::translate("UIGDetails", "Frame Size: %1x%2, Frame Rate: %3fps, Bit Rate: %4kbps") 1754 .arg(c omMachine.GetVideoCaptureWidth())1755 .arg(c omMachine.GetVideoCaptureHeight())1756 .arg(c omMachine.GetVideoCaptureFPS())1757 .arg(c omMachine.GetVideoCaptureRate());1759 .arg(captureScreen0Settings.GetVideoWidth()) 1760 .arg(captureScreen0Settings.GetVideoHeight()) 1761 .arg(captureScreen0Settings.GetVideoFPS()) 1762 .arg(captureScreen0Settings.GetVideoRate()); 1758 1763 } 1759 1764 /* Return report: */ -
trunk/src/VBox/Frontends/VirtualBox/src/widgets/UIMenuBarEditorWindow.cpp
r74942 r75251 1304 1304 pMenu->addSeparator(); 1305 1305 prepareCopiedAction(pMenu, actionPool()->action(UIActionIndexRT_M_View_S_TakeScreenshot)); 1306 prepareCopiedAction(pMenu, actionPool()->action(UIActionIndexRT_M_View_M_ VideoCapture_T_Start));1306 prepareCopiedAction(pMenu, actionPool()->action(UIActionIndexRT_M_View_M_Capture_T_Start)); 1307 1307 prepareCopiedAction(pMenu, actionPool()->action(UIActionIndexRT_M_View_T_VRDEServer)); 1308 1308 pMenu->addSeparator(); -
trunk/src/VBox/Main/Makefile.kmk
r75038 r75251 457 457 src-server/BandwidthGroupImpl.cpp \ 458 458 src-server/BIOSSettingsImpl.cpp \ 459 src-server/CaptureSettingsImpl.cpp \ 460 src-server/CaptureScreenSettingsImpl.cpp \ 459 461 src-server/ClientWatcher.cpp \ 460 462 src-server/ClientToken.cpp \ -
trunk/src/VBox/Main/idl/VirtualBox.xidl
r75044 r75251 4689 4689 </interface> 4690 4690 4691 <enum 4692 name="CaptureDestination" 4693 uuid="E54603A9-6751-4255-93F8-C69E61693391" 4694 > 4695 <desc> 4696 Capturing destination enumeration. 4697 </desc> 4698 4699 <const name="None" value="0"> 4700 <desc>No destination.</desc> 4701 </const> 4702 <const name="File" value="1"> 4703 <desc>Destination is a regular file.</desc> 4704 </const> 4705 </enum> 4706 4707 <enum 4708 name="CaptureFeature" 4709 uuid="F606CDDB-91B2-4E41-9DFE-4713D4DBA96F" 4710 > 4711 <desc> 4712 Capturing features enumeration. 4713 </desc> 4714 4715 <const name="None" value="0"> 4716 <desc>No feature set.</desc> 4717 </const> 4718 <const name="Video" value="1"> 4719 <desc>Video capturing.</desc> 4720 </const> 4721 <const name="Audio" value="2"> 4722 <desc>Audio capturing.</desc> 4723 </const> 4724 </enum> 4725 4726 <enum 4727 name="CaptureAudioCodec" 4728 uuid="9B80C37F-7984-412C-A755-C18FE5859554" 4729 > 4730 <desc> 4731 Capturing audio codec enumeration. 4732 </desc> 4733 4734 <const name="None" value="0"> 4735 <desc>No codec set.</desc> 4736 </const> 4737 <const name="WavPCM" value="1"> 4738 <desc>WAV format, linear PCM, uncompressed. 4739 Not implemented yet.</desc> 4740 </const> 4741 <const name="Opus" value="2"> 4742 <desc>Opus Audio.</desc> 4743 </const> 4744 </enum> 4745 4746 <enum 4747 name="CaptureVideoCodec" 4748 uuid="98BBC021-E119-497D-8C66-4336D539A8D6" 4749 > 4750 <desc> 4751 Capturing video codec enumeration. 4752 </desc> 4753 4754 <const name="None" value="0"> 4755 <desc>No codec set.</desc> 4756 </const> 4757 <const name="VP8" value="1"> 4758 <desc>VP8 codec.</desc> 4759 </const> 4760 <const name="VP9" value="2"> 4761 <desc>VP9 codec. Not implemented yet.</desc> 4762 </const> 4763 <const name="AV1" value="3"> 4764 <desc>AV1 codec. Not implemented yet.</desc> 4765 </const> 4766 </enum> 4767 4768 <interface 4769 name="ICaptureScreenSettings" extends="$unknown" 4770 uuid="9C8FE192-DD9A-45E9-B17B-2BA23B5951F7" 4771 wsmap="managed" 4772 > 4773 4774 <desc> 4775 The ICaptureScreenSettings interface represents capturing settings of a 4776 singke virtual screen. This is used only in the <link to="ICaptureSettings" /> 4777 interface. 4778 </desc> 4779 4780 <method name="isFeatureEnabled"> 4781 <desc>TODO</desc> 4782 <param name="feature" type="CaptureFeature" dir="in"> 4783 <desc>TODO</desc> 4784 </param> 4785 <param name="enabled" type="boolean" dir="return"> 4786 <desc>TODO</desc> 4787 </param> 4788 </method> 4789 4790 <attribute name="enabled" type="boolean" default="false"> 4791 <desc> 4792 This setting determines whether this screen is enabled while capturing. 4793 </desc> 4794 </attribute> 4795 4796 <attribute name="features" type="unsigned long"> 4797 <desc>This setting determines all enabled capturing features for this 4798 screen.</desc> 4799 </attribute> 4800 4801 <attribute name="destination" type="CaptureDestination"> 4802 <desc>This setting determines the capturing destination for this 4803 screen.</desc> 4804 </attribute> 4805 4806 <attribute name="fileName" type="wstring"> 4807 <desc> 4808 This setting determines the filename VirtualBox uses to save 4809 the recorded content. This setting cannot be changed while video 4810 capturing is enabled. 4811 <note> 4812 When setting this attribute, the specified path has to be 4813 absolute (full path). When reading this attribute, a full path is 4814 always returned. 4815 </note> 4816 </desc> 4817 </attribute> 4818 4819 <attribute name="maxTime" type="unsigned long" default="0"> 4820 <desc> 4821 This setting defines the maximum amount of time in milliseconds 4822 to capture. Capturing will stop as soon as the defined time 4823 interval has elapsed. If this value is zero, capturing will not be 4824 limited by time. This setting cannot be changed while capturing is 4825 enabled. 4826 </desc> 4827 </attribute> 4828 4829 <attribute name="maxFileSize" type="unsigned long" default="0"> 4830 <desc> 4831 This setting determines the maximal number of captured file 4832 size in MB. Capturing will stop as soon as the file size has 4833 reached the defined value. If this value is zero, capturing 4834 will not be limited by the file size. This setting cannot be changed 4835 while capturing is enabled. 4836 </desc> 4837 </attribute> 4838 4839 <attribute name="options" type="wstring"> 4840 <desc> 4841 This setting contains any additional capturing options 4842 required in comma-separated key=value format. This setting 4843 cannot be changed while capturing is enabled. 4844 4845 The following keys and their corresponding values are available: 4846 4847 <table> 4848 <tr> 4849 <td>ac_enabled</td> 4850 <td>Enables audio recording when set to <pre>true</pre>, otherwise 4851 set to <pre>false</pre> to disable. 4852 4853 <b>This feature is considered being experimental.</b></td> 4854 </tr> 4855 </table> 4856 4857 </desc> 4858 </attribute> 4859 4860 <attribute name="videoWidth" type="unsigned long" default="1024"> 4861 <desc> 4862 This setting determines the horizontal resolution of the recorded 4863 video. This setting cannot be changed while capturing is enabled. 4864 </desc> 4865 </attribute> 4866 4867 <attribute name="videoHeight" type="unsigned long" default="768"> 4868 <desc> 4869 This setting determines the vertical resolution of the recorded 4870 video. This setting cannot be changed while capturing is enabled. 4871 </desc> 4872 </attribute> 4873 4874 <attribute name="videoRate" type="unsigned long" default="512"> 4875 <desc> 4876 This setting determines the bitrate in kilobits per second. 4877 Increasing this value makes the video look better for the 4878 cost of an increased file size. This setting cannot be changed 4879 while capturing is enabled. 4880 </desc> 4881 </attribute> 4882 4883 <attribute name="videoFPS" type="unsigned long" default="25"> 4884 <desc> 4885 This setting determines the maximum number of frames per second. 4886 Frames with a higher frequency will be skipped. Reducing this 4887 value increases the number of skipped frames and reduces the 4888 file size. This setting cannot be changed while capturing 4889 is enabled. 4890 </desc> 4891 </attribute> 4892 4893 </interface> 4894 4895 <interface 4896 name="ICaptureSettings" extends="$unknown" 4897 uuid="F35B5C06-F6F0-475D-908A-F5FECC820043" 4898 wsmap="managed" 4899 > 4900 4901 <desc> 4902 The ICaptureSettings interface represents capturing settings of the virtual 4903 machine. This is used only in the <link to="IMachine::CaptureSettings" /> 4904 attribute. 4905 </desc> 4906 4907 <method name="getScreenSettings"> 4908 <desc>TODO</desc> 4909 <param name="screenId" type="unsigned long" dir="in"> 4910 <desc>TODO</desc> 4911 </param> 4912 <param name="captureScreenSettings" type="ICaptureScreenSettings" dir="return"> 4913 <desc>TODO</desc> 4914 </param> 4915 </method> 4916 4917 <attribute name="enabled" type="boolean" default="false"> 4918 <desc> 4919 This setting determines whether VirtualBox uses capturing to record a 4920 VM session.</desc> 4921 </attribute> 4922 4923 <attribute name="screens" type="ICaptureScreenSettings" readonly="yes" safearray="yes"> 4924 <desc> 4925 This setting returns an array for capturing settings of all configured 4926 virtual screens.</desc> 4927 </attribute> 4928 4929 </interface> 4930 4691 4931 <interface 4692 4932 name="IPCIAddress" extends="$unknown" … … 4883 5123 <interface 4884 5124 name="IMachine" extends="$unknown" 4885 uuid=" fecae8e8-46da-44cf-8fc0-2ba9aeb796a7"5125 uuid="316A9802-03A5-44BE-B2A6-51261A021353" 4886 5126 wsmap="managed" 4887 5127 wrap-hint-server-addinterfaces="IInternalMachineControl" … … 5164 5404 </attribute> 5165 5405 5166 <attribute name="videoCaptureEnabled" type="boolean" default="false">5167 <desc>5168 This setting determines whether VirtualBox uses video capturing to5169 record a VM session.</desc>5170 </attribute>5171 5172 <attribute name="videoCaptureScreens" type="boolean" safearray="yes">5173 <desc>5174 This setting determines for which screens video capturing is5175 enabled.</desc>5176 </attribute>5177 5178 <attribute name="videoCaptureFile" type="wstring">5179 <desc>5180 This setting determines the filename VirtualBox uses to save5181 the recorded content. This setting cannot be changed while video5182 capturing is enabled.5183 <note>5184 When setting this attribute, the specified path has to be5185 absolute (full path). When reading this attribute, a full path is5186 always returned.5187 </note>5188 </desc>5189 </attribute>5190 5191 <attribute name="videoCaptureWidth" type="unsigned long" default="640">5192 <desc>5193 This setting determines the horizontal resolution of the recorded5194 video. This setting cannot be changed while video capturing is5195 enabled.5196 </desc>5197 </attribute>5198 5199 <attribute name="videoCaptureHeight" type="unsigned long" default="480">5200 <desc>5201 This setting determines the vertical resolution of the recorded5202 video. This setting cannot be changed while video capturing is5203 enabled.5204 </desc>5205 </attribute>5206 5207 <attribute name="videoCaptureRate" type="unsigned long" default="512">5208 <desc>5209 This setting determines the bitrate in kilobits per second.5210 Increasing this value makes the video look better for the5211 cost of an increased file size. This setting cannot be changed5212 while video capturing is enabled.5213 </desc>5214 </attribute>5215 5216 <attribute name="videoCaptureFPS" type="unsigned long" default="25">5217 <desc>5218 This setting determines the maximum number of frames per second.5219 Frames with a higher frequency will be skipped. Reducing this5220 value increases the number of skipped frames and reduces the5221 file size. This setting cannot be changed while video capturing5222 is enabled.5223 </desc>5224 </attribute>5225 5226 <attribute name="videoCaptureMaxTime" type="unsigned long" default="0">5227 <desc>5228 This setting determines the maximum amount of time in milliseconds5229 the video capture will work for. The capture stops as the defined time5230 interval has elapsed. If this value is zero the capturing will not be5231 limited by time. This setting cannot be changed while video capturing is5232 enabled.5233 </desc>5234 </attribute>5235 5236 <attribute name="videoCaptureMaxFileSize" type="unsigned long" default="0">5237 <desc>5238 This setting determines the maximal number of captured video file5239 size in MB. The capture stops as the captured video file size5240 has reached the defined. If this value is zero the capturing5241 will not be limited by file size. This setting cannot be changed5242 while video capturing is enabled.5243 </desc>5244 </attribute>5245 5246 <attribute name="videoCaptureOptions" type="wstring">5247 <desc>5248 This setting contains any additional video capture options5249 required in comma-separated key=value format. This setting5250 cannot be changed while video capturing is enabled.5251 5252 The following keys and their corresponding values are available:5253 5254 <table>5255 <tr>5256 <td>ac_enabled</td>5257 <td>Enables audio recording when set to <pre>true</pre>, otherwise5258 set to <pre>false</pre> to disable.5259 5260 <b>This feature is considered being experimental.</b></td>5261 </tr>5262 </table>5263 5264 </desc>5265 </attribute>5266 5267 5406 <attribute name="BIOSSettings" type="IBIOSSettings" readonly="yes"> 5268 5407 <desc>Object containing all BIOS settings.</desc> 5408 </attribute> 5409 5410 <attribute name="captureSettings" type="ICaptureSettings" readonly="yes"> 5411 <desc>Object containing all capturing settings.</desc> 5269 5412 </attribute> 5270 5413 … … 20411 20554 <interface 20412 20555 name="IInternalSessionControl" extends="$unknown" 20413 uuid=" 747e397e-69c8-45a0-88d9-f7f070960718"20556 uuid="96BDA9B7-92E6-402F-AA8C-2E77818DAE6E" 20414 20557 internal="yes" 20415 20558 wsmap="suppress" … … 20711 20854 </method> 20712 20855 20713 <method name="on VideoCaptureChange">20714 <desc> 20715 Triggered when videocapture settings have changed.20856 <method name="onCaptureChange"> 20857 <desc> 20858 Triggered when capture settings have changed. 20716 20859 </desc> 20717 20860 </method> … … 22895 23038 </desc> 22896 23039 </const> 22897 <const name="On VideoCaptureChanged" value="91">22898 <desc> 22899 See <link to="I VideoCaptureChangedEvent">IVideoCapturedChangeEvent</link>.23040 <const name="OnCaptureChanged" value="91"> 23041 <desc> 23042 See <link to="ICaptureChangedEvent">ICapturedChangeEvent</link>. 22900 23043 </desc> 22901 23044 </const> … … 24282 24425 24283 24426 <interface 24284 name="I VideoCaptureChangedEvent" extends="IEvent"24285 uuid=" 6215d169-25dd-4719-ab34-c908701efb58"24286 wsmap="managed" autogen="VBoxEvent" id="On VideoCaptureChanged"24427 name="ICaptureChangedEvent" extends="IEvent" 24428 uuid="C694687C-F432-4435-B457-F2E55B845C81" 24429 wsmap="managed" autogen="VBoxEvent" id="OnCaptureChanged" 24287 24430 > 24288 24431 <desc> 24289 Notification when videocapture settings have changed.24432 Notification when capture settings have changed. 24290 24433 </desc> 24291 24434 <attribute name="midlDoesNotLikeEmptyInterfaces" readonly="yes" type="boolean"/> -
trunk/src/VBox/Main/include/ConsoleImpl.h
r74765 r75251 24 24 #include "SecretKeyStore.h" 25 25 #include "ConsoleWrap.h" 26 #ifdef VBOX_WITH_VIDEOREC 27 # include "VideoRec.h" 28 #endif 26 29 27 30 class Guest; … … 139 142 #endif 140 143 #ifdef VBOX_WITH_AUDIO_VIDEOREC 141 AudioVideoRec *i_getAudioVideoRec() const { return mAudioVideoRec; } 142 HRESULT i_audioVideoRecSendAudio(const void *pvData, size_t cbData, uint64_t uDurationMs); 144 int i_videoRecLoad(settings::CaptureSettings &Settings); 145 int i_videoRecStart(void); 146 int i_videoRecStop(void); 147 AudioVideoRec *i_videoRecGetAudioDrv(void) const { return Capture.mAudioVideoRec; } 148 CaptureContext *i_videoRecGetContext(void) const { return Capture.mpVideoRecCtx; } 149 HRESULT i_videoRecSendAudio(const void *pvData, size_t cbData, uint64_t uDurationMs); 143 150 #endif 144 151 … … 169 176 HRESULT i_onDnDModeChange(DnDMode_T aDnDMode); 170 177 HRESULT i_onVRDEServerChange(BOOL aRestart); 171 HRESULT i_on VideoCaptureChange();178 HRESULT i_onCaptureChange(); 172 179 HRESULT i_onUSBControllerChange(); 173 180 HRESULT i_onSharedFolderChange(BOOL aGlobal); … … 939 946 VMMDev * m_pVMMDev; 940 947 AudioVRDE * const mAudioVRDE; 941 #ifdef VBOX_WITH_AUDIO_VIDEOREC942 /** The video recording audio backend. */943 AudioVideoRec * const mAudioVideoRec;944 #endif945 948 Nvram * const mNvram; 946 949 #ifdef VBOX_WITH_USB_CARDREADER … … 1028 1031 ComPtr<IEventListener> mVmListener; 1029 1032 1033 #ifdef VBOX_WITH_VIDEOREC 1034 struct Capture 1035 { 1036 Capture() 1037 : mpVideoRecCtx(NULL) 1038 , mAudioVideoRec(NULL) { } 1039 1040 /** The capturing context. */ 1041 CaptureContext *mpVideoRecCtx; 1042 # ifdef VBOX_WITH_AUDIO_VIDEOREC 1043 /** Pointer to capturing audio backend. */ 1044 AudioVideoRec * const mAudioVideoRec; 1045 # endif 1046 } Capture; 1047 #endif /* VBOX_WITH_VIDEOREC */ 1048 1030 1049 friend class VMTask; 1031 1050 friend class ConsoleVRDPServer; -
trunk/src/VBox/Main/include/DisplayImpl.h
r75072 r75251 32 32 #endif 33 33 34 #ifdef VBOX_WITH_VIDEOREC35 # include "VideoRec.h"36 struct VIDEORECCONTEXT;37 #endif38 39 34 #include "DisplaySourceBitmapWrap.h" 40 35 #include "GuestScreenInfoWrap.h" … … 184 179 uint32_t x, uint32_t y, uint32_t uPixelFormat, uint32_t uBitsPerPixel, 185 180 uint32_t uBytesPerLine, uint32_t uGuestWidth, uint32_t uGuestHeight, 186 uint8_t *pu8BufferAddress, uint64_t u64TimeStamp); 187 /** @todo r=bird: u64TimeStamp - using the 'u64' prefix add nothing. 188 * However, using one of the prefixes indicating the timestamp unit 189 * would be very valuable! */ 190 bool i_handleCrVRecScreenshotBegin(uint32_t uScreen, uint64_t u64TimeStamp); 191 void i_handleCrVRecScreenshotEnd(uint32_t uScreen, uint64_t u64TimeStamp); 181 uint8_t *pu8BufferAddress, uint64_t uTimestampMs); 182 bool i_handleCrVRecScreenshotBegin(uint32_t uScreen, uint64_t uTimestampMs); 183 void i_handleCrVRecScreenshotEnd(uint32_t uScreen, uint64_t uTimestampMs); 192 184 void i_handleVRecCompletion(); 193 185 #endif … … 209 201 210 202 #ifdef VBOX_WITH_VIDEOREC 211 PVIDEORECCFG i_videoRecGetConfig(void) { return &mVideoRecCfg; } 212 VIDEORECFEATURES i_videoRecGetFeatures(void); 213 bool i_videoRecStarted(void); 214 void i_videoRecInvalidate(); 215 int i_videoRecSendAudio(const void *pvData, size_t cbData, uint64_t uTimestampMs); 216 int i_videoRecStart(void); 217 void i_videoRecStop(void); 218 void i_videoRecScreenChanged(unsigned uScreenId); 203 int i_videoRecInvalidate(void); 204 void i_videoRecScreenChanged(unsigned uScreenId); 219 205 #endif 220 206 … … 486 472 /* Serializes access to video recording source bitmaps. */ 487 473 RTCRITSECT mVideoRecLock; 488 /** The current video recording configuration being used. */ 489 VIDEORECCFG mVideoRecCfg; 490 /** The video recording context. */ 491 VIDEORECCONTEXT *mpVideoRecCtx; 492 /** Array which defines which screens are being enabled for recording. */ 474 /** Array which defines which screens are being enabled for capturing. */ 493 475 bool maVideoRecEnabled[SchemaDefs::MaxGuestMonitors]; 494 476 #endif -
trunk/src/VBox/Main/include/DrvAudioVideoRec.h
r74955 r75251 20 20 21 21 #include <VBox/com/ptr.h> 22 #include <VBox/settings.h> 22 23 #include <VBox/vmm/pdmdrv.h> 23 24 #include <VBox/vmm/pdmifs.h> … … 44 45 public: 45 46 46 int applyConfiguration(const PVIDEORECCFG pVideoRecCfg);47 int applyConfiguration(const settings::CaptureSettings &a_Settings); 47 48 48 49 public: … … 58 59 59 60 /** Pointer to the associated video recording audio driver. */ 60 struct DRVAUDIOVIDEOREC *mpDrv;61 /** Video recording configuration used for configuring the driver. */62 struct VIDEORECCFGmVideoRecCfg;61 struct DRVAUDIOVIDEOREC *mpDrv; 62 /** Capturing configuration used for configuring the driver. */ 63 struct settings::CaptureSettings mVideoRecCfg; 63 64 }; 64 65 -
trunk/src/VBox/Main/include/MachineImpl.h
r72919 r75251 5 5 6 6 /* 7 * Copyright (C) 2006-201 7Oracle Corporation7 * Copyright (C) 2006-2018 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 32 32 #include "ParallelPortImpl.h" 33 33 #include "BIOSSettingsImpl.h" 34 #include "CaptureSettingsImpl.h" 34 35 #include "StorageControllerImpl.h" // required for MachineImpl.h to compile on Windows 35 36 #include "USBControllerImpl.h" // required for MachineImpl.h to compile on Windows … … 265 266 GraphicsControllerType_T mGraphicsControllerType; 266 267 ULONG mVRAMSize; 267 ULONG mVideoCaptureWidth; 268 ULONG mVideoCaptureHeight; 269 ULONG mVideoCaptureRate; 270 ULONG mVideoCaptureFPS; 271 ULONG mVideoCaptureMaxTime; 272 ULONG mVideoCaptureMaxFileSize; 273 Utf8Str mVideoCaptureOptions; 274 Utf8Str mVideoCaptureFile; 275 BOOL mVideoCaptureEnabled; 276 BOOL maVideoCaptureScreens[SchemaDefs::MaxGuestMonitors]; 268 settings::CaptureSettings mCaptureSettings; 277 269 ULONG mMonitorCount; 278 270 BOOL mHWVirtExEnabled; … … 484 476 IsModified_SharedFolders = 0x0400, 485 477 IsModified_Snapshots = 0x0800, 486 IsModified_BandwidthControl = 0x1000 478 IsModified_BandwidthControl = 0x1000, 479 IsModified_Capture = 0x2000 487 480 }; 488 481 … … 528 521 virtual HRESULT i_onStorageDeviceChange(IMediumAttachment * /* mediumAttachment */, BOOL /* remove */, 529 522 BOOL /* silent */) { return S_OK; } 530 virtual HRESULT i_on VideoCaptureChange() { return S_OK; }523 virtual HRESULT i_onCaptureChange() { return S_OK; } 531 524 532 525 HRESULT i_saveRegistryEntry(settings::MachineRegistryEntry &data); … … 540 533 541 534 void i_composeSavedStateFilename(Utf8Str &strStateFilePath); 542 543 void i_getDefaultVideoCaptureFile(Utf8Str &strFile);544 535 545 536 bool i_isUSBControllerPresent(); … … 783 774 const ComObjPtr<USBDeviceFilters> mUSBDeviceFilters; 784 775 const ComObjPtr<BIOSSettings> mBIOSSettings; 776 const ComObjPtr<CaptureSettings> mCaptureSettings; 785 777 const ComObjPtr<BandwidthControl> mBandwidthControl; 786 778 … … 829 821 void i_deleteConfigHandler(DeleteConfigTask &task); 830 822 823 friend class Appliance; 824 friend class CaptureSettings; 825 friend class CaptureScreenSettings; 831 826 friend class SessionMachine; 832 827 friend class SnapshotMachine; 833 friend class Appliance;834 828 friend class VirtualBox; 835 829 … … 882 876 HRESULT getMonitorCount(ULONG *aMonitorCount); 883 877 HRESULT setMonitorCount(ULONG aMonitorCount); 884 HRESULT getVideoCaptureEnabled(BOOL *aVideoCaptureEnabled);885 HRESULT setVideoCaptureEnabled(BOOL aVideoCaptureEnabled);886 HRESULT getVideoCaptureScreens(std::vector<BOOL> &aVideoCaptureScreens);887 HRESULT setVideoCaptureScreens(const std::vector<BOOL> &aVideoCaptureScreens);888 HRESULT getVideoCaptureFile(com::Utf8Str &aVideoCaptureFile);889 HRESULT setVideoCaptureFile(const com::Utf8Str &aVideoCaptureFile);890 HRESULT getVideoCaptureWidth(ULONG *aVideoCaptureWidth);891 HRESULT setVideoCaptureWidth(ULONG aVideoCaptureWidth);892 HRESULT getVideoCaptureHeight(ULONG *aVideoCaptureHeight);893 HRESULT setVideoCaptureHeight(ULONG aVideoCaptureHeight);894 HRESULT getVideoCaptureRate(ULONG *aVideoCaptureRate);895 HRESULT setVideoCaptureRate(ULONG aVideoCaptureRate);896 HRESULT getVideoCaptureFPS(ULONG *aVideoCaptureFPS);897 HRESULT setVideoCaptureFPS(ULONG aVideoCaptureFPS);898 HRESULT getVideoCaptureMaxTime(ULONG *aVideoCaptureMaxTime);899 HRESULT setVideoCaptureMaxTime(ULONG aVideoCaptureMaxTime);900 HRESULT getVideoCaptureMaxFileSize(ULONG *aVideoCaptureMaxFileSize);901 HRESULT setVideoCaptureMaxFileSize(ULONG aVideoCaptureMaxFileSize);902 HRESULT getVideoCaptureOptions(com::Utf8Str &aVideoCaptureOptions);903 HRESULT setVideoCaptureOptions(const com::Utf8Str &aVideoCaptureOptions);904 878 HRESULT getBIOSSettings(ComPtr<IBIOSSettings> &aBIOSSettings); 879 HRESULT getCaptureSettings(ComPtr<ICaptureSettings> &aCaptureSettings); 905 880 HRESULT getFirmwareType(FirmwareType_T *aFirmwareType); 906 881 HRESULT setFirmwareType(FirmwareType_T aFirmwareType); … … 1348 1323 HRESULT i_onCPUChange(ULONG aCPU, BOOL aRemove); 1349 1324 HRESULT i_onVRDEServerChange(BOOL aRestart); 1350 HRESULT i_on VideoCaptureChange();1325 HRESULT i_onCaptureChange(); 1351 1326 HRESULT i_onUSBControllerChange(); 1352 1327 HRESULT i_onUSBDeviceAttach(IUSBDevice *aDevice, -
trunk/src/VBox/Main/include/SessionImpl.h
r68986 r75251 102 102 HRESULT onCPUExecutionCapChange(ULONG aExecutionCap); 103 103 HRESULT onVRDEServerChange(BOOL aRestart); 104 HRESULT on VideoCaptureChange();104 HRESULT onCaptureChange(); 105 105 HRESULT onUSBControllerChange(); 106 106 HRESULT onSharedFolderChange(BOOL aGlobal); -
trunk/src/VBox/Main/include/VideoRec.h
r75067 r75251 23 23 #include <VBox/com/VirtualBox.h> 24 24 #include <VBox/err.h> 25 #include <VBox/settings.h> 25 26 26 27 using namespace com; … … 29 30 #include "VideoRecStream.h" 30 31 32 #if 0 31 33 /** 32 34 * Enumeration for definining a video / audio … … 54 56 55 57 /** 56 * Structure for keeping a videorecording configuration.57 */ 58 typedef struct VIDEOREC CFG58 * Structure for keeping a screen recording configuration. 59 */ 60 typedef struct VIDEORECSCREENCFG 59 61 { 60 VIDEOREC CFG(void)61 : 62 VIDEORECSCREENCFG(void) 63 : enmDst(VIDEORECDEST_INVALID) 62 64 , uMaxTimeS(0) 63 65 { … … 68 70 } 69 71 70 /** Array of all screens containing whether they're enabled 71 * for recording or not. */ 72 com::SafeArray<BOOL> aScreens; 72 VIDEORECSCREENCFG& operator=(const VIDEORECSCREENCFG &that) 73 { 74 enmDst = that.enmDst; 75 76 File.strName = that.File.strName; 77 File.uMaxSizeMB = that.File.uMaxSizeMB; 78 #ifdef VBOX_WITH_AUDIO_VIDEOREC 79 Audio = that.Audio; 80 #endif 81 Video = that.Video; 82 uMaxTimeS = that.uMaxTimeS; 83 return *this; 84 } 85 86 unsigned long uScreenId; 73 87 /** Destination where to write the stream to. */ 74 88 VIDEORECDEST enmDst; … … 135 149 136 150 } Video; 151 137 152 /** Maximum time (in s) to record. 138 153 * Specify 0 to disable this check. */ 139 154 uint32_t uMaxTimeS; 140 141 VIDEORECCFG& operator=(const VIDEORECCFG &that) 142 { 143 aScreens.resize(that.aScreens.size()); 144 for (size_t i = 0; i < that.aScreens.size(); ++i) 145 aScreens[i] = that.aScreens[i]; 146 147 enmDst = that.enmDst; 148 149 File.strName = that.File.strName; 150 File.uMaxSizeMB = that.File.uMaxSizeMB; 151 #ifdef VBOX_WITH_AUDIO_VIDEOREC 152 Audio = that.Audio; 153 #endif 154 Video = that.Video; 155 uMaxTimeS = that.uMaxTimeS; 156 return *this; 157 } 158 159 } VIDEORECCFG, *PVIDEORECCFG; 155 } VIDEORECSCREENCFG, *PVIDEORECSCREENCFG; 156 #endif 157 158 class Console; 160 159 161 160 /** 162 * Structure for keeping a video recording context.163 */ 164 typedef struct VIDEORECCONTEXT 161 * Class for managing a capturing context. 162 */ 163 class CaptureContext 165 164 { 165 public: 166 167 CaptureContext(Console *pConsole); 168 169 CaptureContext(Console *pConsole, const settings::CaptureSettings &a_Settings); 170 171 virtual ~CaptureContext(void); 172 173 public: 174 175 const settings::CaptureSettings &GetConfig(void) const; 176 CaptureStream *GetStream(unsigned uScreen) const; 177 size_t GetStreamCount(void) const; 178 179 int Create(const settings::CaptureSettings &a_Settings); 180 int Destroy(void); 181 182 int SendAudioFrame(const void *pvData, size_t cbData, uint64_t uTimestampMs); 183 int SendVideoFrame(uint32_t uScreen, 184 uint32_t x, uint32_t y, uint32_t uPixelFormat, uint32_t uBPP, 185 uint32_t uBytesPerLine, uint32_t uSrcWidth, uint32_t uSrcHeight, 186 uint8_t *puSrcData, uint64_t uTimeStampMs); 187 public: 188 189 bool IsFeatureEnabled(CaptureFeature_T enmFeature) const; 190 bool IsReady(void) const; 191 bool IsReady(uint32_t uScreen, uint64_t uTimeStampMs) const; 192 bool IsStarted(void) const; 193 bool IsLimitReached(uint32_t uScreen, uint64_t tsNowMs) const; 194 195 protected: 196 197 int createInternal(const settings::CaptureSettings &a_Settings); 198 199 int destroyInternal(void); 200 201 CaptureStream *getStreamInternal(unsigned uScreen) const; 202 203 static DECLCALLBACK(int) threadMain(RTTHREAD hThreadSelf, void *pvUser); 204 205 int threadNotify(void); 206 207 protected: 208 209 /** Pointer to the console object. */ 210 Console *pConsole; 166 211 /** Used recording configuration. */ 167 VIDEORECCFG Cfg;212 settings::CaptureSettings Settings; 168 213 /** The current state. */ 169 uint32_t enmState;214 uint32_t enmState; 170 215 /** Critical section to serialize access. */ 171 RTCRITSECT CritSect;216 RTCRITSECT CritSect; 172 217 /** Semaphore to signal the encoding worker thread. */ 173 RTSEMEVENT WaitEvent;174 /** Whether this con ext is in started state or not. */175 bool fStarted;218 RTSEMEVENT WaitEvent; 219 /** Whether this context is in started state or not. */ 220 bool fStarted; 176 221 /** Shutdown indicator. */ 177 bool fShutdown;222 bool fShutdown; 178 223 /** Worker thread. */ 179 RTTHREAD Thread;224 RTTHREAD Thread; 180 225 /** Vector of current recording streams. 181 226 * Per VM screen (display) one recording stream is being used. */ 182 VideoRecStreams vecStreams;227 VideoRecStreams vecStreams; 183 228 /** Timestamp (in ms) of when recording has been started. */ 184 uint64_t tsStartMs;229 uint64_t tsStartMs; 185 230 /** Block map of common blocks which need to get multiplexed 186 231 * to all recording streams. This common block maps should help … … 190 235 * For now this only affects audio, e.g. all recording streams 191 236 * need to have the same audio data at a specific point in time. */ 192 VideoRecBlockMap mapBlocksCommon; 193 } VIDEORECCONTEXT, *PVIDEORECCONTEXT; 194 195 int VideoRecContextCreate(uint32_t cScreens, PVIDEORECCFG pVideoRecCfg, PVIDEORECCONTEXT *ppCtx); 196 int VideoRecContextDestroy(PVIDEORECCONTEXT pCtx); 197 198 VIDEORECFEATURES VideoRecGetFeatures(PVIDEORECCFG pCfg); 199 PVIDEORECSTREAM VideoRecGetStream(PVIDEORECCONTEXT pCtx, uint32_t uScreen); 200 201 int VideoRecSendAudioFrame(PVIDEORECCONTEXT pCtx, const void *pvData, size_t cbData, uint64_t uTimestampMs); 202 int VideoRecSendVideoFrame(PVIDEORECCONTEXT pCtx, uint32_t uScreen, 203 uint32_t x, uint32_t y, uint32_t uPixelFormat, uint32_t uBPP, 204 uint32_t uBytesPerLine, uint32_t uSrcWidth, uint32_t uSrcHeight, 205 uint8_t *puSrcData, uint64_t uTimeStampMs); 206 bool VideoRecIsReady(PVIDEORECCONTEXT pCtx, uint32_t uScreen, uint64_t uTimeStampMs); 207 bool VideoRecIsStarted(PVIDEORECCONTEXT pCtx); 208 bool VideoRecIsLimitReached(PVIDEORECCONTEXT pCtx, uint32_t uScreen, uint64_t tsNowMs); 209 237 VideoRecBlockMap mapBlocksCommon; 238 }; 210 239 #endif /* !____H_VIDEOREC */ 211 240 -
trunk/src/VBox/Main/include/VideoRecInternals.h
r75005 r75251 30 30 31 31 /** 32 * Enumeration for video recording destinations.33 */34 typedef enum VIDEORECDEST35 {36 /** Invalid destination, do not use. */37 VIDEORECDEST_INVALID = 0,38 /** Write to a file. */39 VIDEORECDEST_FILE = 140 } VIDEORECDEST;41 42 /**43 * Enumeration for the video recording video codec type.44 */45 typedef enum VIDEORECVIDEOCODECTYPE46 {47 /** Unknown codec type, do not use. */48 VIDEORECVIDEOCODECTYPE_UNKNOWN,49 /** Codec is VP8. */50 VIDEORECVIDEOCODECTYPE_VP8,51 # ifdef VBOX_WITH_LIBVPX_VP952 /** Codec is VP9. */53 VIDEORECVIDEOCODECTYPE_VP954 #endif55 } VIDEORECVIDEOCODECTYPE;56 57 /**58 32 * Structure for keeping specific video recording codec data. 59 33 */ 60 34 typedef struct VIDEORECVIDEOCODEC 61 35 { 62 /** Used codec type. */63 VIDEORECVIDEOCODECTYPE enmType;64 36 #ifdef VBOX_WITH_LIBVPX 65 37 union … … 75 47 /** Pointer to the codec's internal YUV buffer. */ 76 48 uint8_t *pu8YuvBuf; 49 unsigned int uEncoderDeadline; 77 50 } VPX; 78 51 }; -
trunk/src/VBox/Main/include/VideoRecStream.h
r75067 r75251 27 27 #include <VBox/com/VirtualBox.h> 28 28 #include <VBox/err.h> 29 #include <VBox/settings.h> 29 30 30 31 #include "VideoRecInternals.h" … … 32 33 class WebMWriter; 33 34 34 struct VIDEORECCFG; 35 typedef struct VIDEORECCFG *PVIDEORECCFG; 36 37 struct VIDEORECCONTEXT; 38 typedef struct VIDEORECCONTEXT *PVIDEORECCONTEXT; 35 struct CaptureContext; 36 typedef struct CaptureContext *PVIDEORECCONTEXT; 39 37 40 38 41 39 /** Structure for queuing all blocks bound to a single timecode. 42 40 * This can happen if multiple tracks are being involved. */ 43 struct VideoRecBlocks41 struct CaptureBlocks 44 42 { 45 virtual ~ VideoRecBlocks()43 virtual ~CaptureBlocks() 46 44 { 47 45 Clear(); … … 71 69 * The key specifies a unique timecode, whereas the value 72 70 * is a list of blocks which all correlate to the same key (timecode). */ 73 typedef std::map<uint64_t, VideoRecBlocks *> VideoRecBlockMap;71 typedef std::map<uint64_t, CaptureBlocks *> VideoRecBlockMap; 74 72 75 73 /** 76 * Structure for holding a set of videorecording (data) blocks.77 */ 78 struct VideoRecBlockSet74 * Structure for holding a set of recording (data) blocks. 75 */ 76 struct CaptureBlockSet 79 77 { 80 virtual ~ VideoRecBlockSet()78 virtual ~CaptureBlockSet() 81 79 { 82 80 Clear(); … … 84 82 85 83 /** 86 * Resets a videorecording block set by removing (destroying)84 * Resets a recording block set by removing (destroying) 87 85 * all current elements. 88 86 */ 89 void Clear( )87 void Clear(void) 90 88 { 91 89 VideoRecBlockMap::iterator it = Map.begin(); … … 108 106 109 107 /** 110 * Structure for maintaining a videorecording stream.111 */ 112 typedef struct VIDEORECSTREAM 108 * Class for managing a recording stream. 109 */ 110 class CaptureStream 113 111 { 114 /** Video recording context this stream is associated to. */ 115 PVIDEORECCONTEXT pCtx; 116 /** Destination where to write the stream to. */ 117 VIDEORECDEST enmDst; 112 public: 113 114 CaptureStream(void); 115 116 CaptureStream(uint32_t a_uScreen, const settings::CaptureScreenSettings &a_Settings); 117 118 virtual ~CaptureStream(void); 119 120 public: 121 122 int Init(uint32_t a_uScreen, const settings::CaptureScreenSettings &a_Settings); 123 int Uninit(void); 124 125 int Process(VideoRecBlockMap &mapBlocksCommon); 126 int SendVideoFrame(uint32_t x, uint32_t y, uint32_t uPixelFormat, uint32_t uBPP, uint32_t uBytesPerLine, 127 uint32_t uSrcWidth, uint32_t uSrcHeight, uint8_t *puSrcData, uint64_t uTimeStampMs); 128 129 const settings::CaptureScreenSettings &GetConfig(void) const; 130 bool IsLimitReached(uint64_t tsNowMs) const; 131 bool IsReady(void) const; 132 133 protected: 134 135 int open(void); 136 int close(void); 137 138 int initInternal(uint32_t a_uScreen, const settings::CaptureScreenSettings &a_Settings); 139 int uninitInternal(void); 140 141 int initVideo(void); 142 int unitVideo(void); 143 144 int initAudio(void); 145 146 #ifdef VBOX_WITH_LIBVPX 147 int initVideoVPX(void); 148 int uninitVideoVPX(void); 149 int writeVideoVPX(uint64_t uTimeStampMs, PVIDEORECVIDEOFRAME pFrame); 150 #endif 151 void lock(void); 152 void unlock(void); 153 154 int parseOptionsString(const com::Utf8Str &strOptions); 155 156 protected: 157 158 /** Recording context this stream is associated to. */ 159 CaptureContext *pCtx; 118 160 union 119 161 { … … 123 165 RTFILE hFile; 124 166 /** File name being used for this stream. */ 125 char *pszFile;167 Utf8Str strName; 126 168 /** Pointer to WebM writer instance being used. */ 127 169 WebMWriter *pWEBM; 128 170 } File; 129 171 }; 172 bool fEnabled; 130 173 #ifdef VBOX_WITH_AUDIO_VIDEOREC 131 174 /** Track number of audio stream. */ … … 136 179 /** Screen ID. */ 137 180 uint16_t uScreenID; 138 /** Whether video recording is enabled or not. */139 bool fEnabled;140 181 /** Critical section to serialize access. */ 141 182 RTCRITSECT CritSect; 183 /** Timestamp (in ms) of when recording has been start. */ 184 uint64_t tsStartMs; 142 185 143 186 struct 144 187 { 145 /** Codec-specific data. */146 VIDEORECVIDEOCODEC Codec;147 188 /** Minimal delay (in ms) between two video frames. 148 189 * This value is based on the configured FPS rate. */ 149 190 uint32_t uDelayMs; 150 /** Target X resolution (in pixels). */151 uint32_t uWidth;152 /** Target Y resolution (in pixels). */153 uint32_t uHeight;154 191 /** Time stamp (in ms) of the last video frame we encoded. */ 155 192 uint64_t uLastTimeStampMs; 156 193 /** Number of failed attempts to encode the current video frame in a row. */ 157 194 uint16_t cFailedEncodingFrames; 195 VIDEORECVIDEOCODEC Codec; 158 196 } Video; 159 197 198 settings::CaptureScreenSettings Settings; 160 199 /** Common set of video recording (data) blocks, needed for 161 200 * multiplexing to all recording streams. */ 162 VideoRecBlockSetBlocks;163 } VIDEORECSTREAM, *PVIDEORECSTREAM;201 CaptureBlockSet Blocks; 202 }; 164 203 165 204 /** Vector of video recording streams. */ 166 typedef std::vector <PVIDEORECSTREAM> VideoRecStreams; 167 168 int VideoRecStreamClose(PVIDEORECSTREAM pStream); 169 int VideoRecStreamOpen(PVIDEORECSTREAM pStream, PVIDEORECCFG pCfg); 170 int VideoRecStreamProcess(PVIDEORECSTREAM pStream); 171 int VideoRecStreamInit(PVIDEORECSTREAM pStream, PVIDEORECCONTEXT pCtx, uint32_t uScreen); 172 int VideoRecStreamUninit(PVIDEORECSTREAM pStream); 173 int VideoRecStreamUnitVideo(PVIDEORECSTREAM pStream); 174 int VideoRecStreamInitVideo(PVIDEORECSTREAM pStream, PVIDEORECCFG pCfg); 175 #ifdef VBOX_WITH_LIBVPX 176 int VideoRecStreamInitVideoVPX(PVIDEORECSTREAM pStream, PVIDEORECCFG pCfg); 177 int VideoRecStreamUninitVideoVPX(PVIDEORECSTREAM pStream); 178 int VideoRecStreamWriteVideoVPX(PVIDEORECSTREAM pStream, uint64_t uTimeStampMs, PVIDEORECVIDEOFRAME pFrame); 179 #endif 180 void VideoRecStreamLock(PVIDEORECSTREAM pStream); 181 void VideoRecStreamUnlock(PVIDEORECSTREAM pStream); 205 typedef std::vector <CaptureStream *> VideoRecStreams; 182 206 183 207 #endif /* ____H_VIDEOREC_STREAM */ -
trunk/src/VBox/Main/src-client/ConsoleImpl.cpp
r75167 r75251 402 402 , m_pVMMDev(NULL) 403 403 , mAudioVRDE(NULL) 404 #ifdef VBOX_WITH_AUDIO_VIDEOREC405 , mAudioVideoRec(NULL)406 #endif407 404 , mNvram(NULL) 408 405 #ifdef VBOX_WITH_USB_CARDREADER … … 590 587 #endif 591 588 #ifdef VBOX_WITH_AUDIO_VIDEOREC 592 unconst( mAudioVideoRec) = new AudioVideoRec(this);593 AssertReturn( mAudioVideoRec, E_FAIL);589 unconst(Capture.mAudioVideoRec) = new AudioVideoRec(this); 590 AssertReturn(Capture.mAudioVideoRec, E_FAIL); 594 591 #endif 595 592 FirmwareType_T enmFirmwareType; … … 738 735 739 736 #ifdef VBOX_WITH_AUDIO_VIDEOREC 740 if ( mAudioVideoRec)741 { 742 delete mAudioVideoRec;743 unconst( mAudioVideoRec) = NULL;737 if (Capture.mAudioVideoRec) 738 { 739 delete Capture.mAudioVideoRec; 740 unconst(Capture.mAudioVideoRec) = NULL; 744 741 } 745 742 #endif … … 5619 5616 if (pDisplay) 5620 5617 { 5621 if (RT_BOOL(fEnable) != pDisplay->i_videoRecStarted())5618 if (RT_BOOL(fEnable) != Capture.mpVideoRecCtx->IsStarted()) 5622 5619 { 5623 5620 LogRel(("VideoRec: %s\n", fEnable ? "Enabling" : "Disabling")); … … 5629 5626 # ifdef VBOX_WITH_AUDIO_VIDEOREC 5630 5627 /* Attach the video recording audio driver if required. */ 5631 if ( pDisplay->i_videoRecGetFeatures() & VIDEORECFEATURE_AUDIO5632 && mAudioVideoRec)5628 if ( Capture.mpVideoRecCtx->IsFeatureEnabled(CaptureFeature_Audio) 5629 && Capture.mAudioVideoRec) 5633 5630 { 5634 vrc = mAudioVideoRec->applyConfiguration(pDisplay->i_videoRecGetConfig());5631 vrc = Capture.mAudioVideoRec->applyConfiguration(Capture.mpVideoRecCtx->GetConfig()); 5635 5632 if (RT_SUCCESS(vrc)) 5636 vrc = mAudioVideoRec->doAttachDriverViaEmt(mpUVM, pAutoLock);5633 vrc = Capture.mAudioVideoRec->doAttachDriverViaEmt(mpUVM, pAutoLock); 5637 5634 } 5638 5635 # endif 5639 5636 if ( RT_SUCCESS(vrc) 5640 && pDisplay->i_videoRecGetFeatures()) /* Any video recording (audio and/or video) feature enabled? */5637 && Capture.mpVideoRecCtx->IsReady()) /* Any video recording (audio and/or video) feature enabled? */ 5641 5638 { 5642 vrc = pDisplay->i_videoRecStart();5639 vrc = i_videoRecStart(); 5643 5640 } 5644 5641 } 5645 5642 else 5646 5643 { 5647 mDisplay->i_videoRecStop();5644 i_videoRecStop(); 5648 5645 # ifdef VBOX_WITH_AUDIO_VIDEOREC 5649 mAudioVideoRec->doDetachDriverViaEmt(mpUVM, pAutoLock);5646 Capture.mAudioVideoRec->doDetachDriverViaEmt(mpUVM, pAutoLock); 5650 5647 # endif 5651 5648 } … … 5662 5659 #endif /* VBOX_WITH_VIDEOREC */ 5663 5660 5664 HRESULT Console::i_on VideoCaptureChange()5661 HRESULT Console::i_onCaptureChange() 5665 5662 { 5666 5663 AutoCaller autoCaller(this); … … 5675 5672 if (ptrVM.isOk()) 5676 5673 { 5674 ComPtr<ICaptureSettings> CaptureSettings; 5675 rc = mMachine->COMGETTER(CaptureSettings)(CaptureSettings.asOutParam()); 5676 AssertComRCReturnRC(rc); 5677 5677 5678 BOOL fEnabled; 5678 rc = mMachine->COMGETTER(VideoCaptureEnabled)(&fEnabled);5679 rc = CaptureSettings->COMGETTER(Enabled)(&fEnabled); 5679 5680 AssertComRCReturnRC(rc); 5680 5681 … … 5683 5684 { 5684 5685 alock.release(); 5685 fire VideoCaptureChangedEvent(mEventSource);5686 fireCaptureChangedEvent(mEventSource); 5686 5687 } 5687 5688 … … 6867 6868 * @param uTimestampMs Timestamp (in ms) of audio data. 6868 6869 */ 6869 HRESULT Console::i_audioVideoRecSendAudio(const void *pvData, size_t cbData, uint64_t uTimestampMs) 6870 { 6871 if (mDisplay) 6872 { 6873 int rc2 = mDisplay->i_videoRecSendAudio(pvData, cbData, uTimestampMs); 6874 AssertRC(rc2); 6870 HRESULT Console::i_videoRecSendAudio(const void *pvData, size_t cbData, uint64_t uTimestampMs) 6871 { 6872 if (!Capture.mpVideoRecCtx) 6873 return S_OK; 6874 6875 if ( Capture.mpVideoRecCtx->IsStarted() 6876 && Capture.mpVideoRecCtx->IsFeatureEnabled(CaptureFeature_Audio)) 6877 { 6878 return Capture.mpVideoRecCtx->SendAudioFrame(pvData, cbData, uTimestampMs); 6875 6879 } 6876 6880 … … 6878 6882 } 6879 6883 #endif /* VBOX_WITH_AUDIO_VIDEOREC */ 6884 6885 #ifdef VBOX_WITH_VIDEOREC 6886 int Console::i_videoRecLoad(settings::CaptureSettings &Settings) 6887 { 6888 Assert(mMachine.isNotNull()); 6889 6890 ComPtr<ICaptureSettings> pCaptureSettings; 6891 HRESULT hrc = mMachine->COMGETTER(CaptureSettings)(pCaptureSettings.asOutParam()); 6892 AssertComRCReturn(hrc, VERR_INVALID_PARAMETER); 6893 6894 SafeIfaceArray<ICaptureScreenSettings> paCaptureScreens; 6895 hrc = pCaptureSettings->GetScreens(ComSafeArrayAsOutParam(paCaptureScreens)); 6896 AssertComRCReturn(hrc, VERR_INVALID_PARAMETER); 6897 6898 Settings.mapScreens.clear(); 6899 6900 for (size_t i = 0; i < paCaptureScreens.size(); ++i) 6901 { 6902 settings::CaptureScreenSettings CaptureScreenSettings; 6903 ComPtr<ICaptureScreenSettings> pCaptureScreenSettings = paCaptureScreens[i]; 6904 6905 hrc = pCaptureScreenSettings->COMGETTER(MaxTime)((ULONG *)&CaptureScreenSettings.ulMaxTimeS); 6906 AssertComRCReturn(hrc, VERR_INVALID_PARAMETER); 6907 hrc = pCaptureScreenSettings->COMGETTER(MaxFileSize)((ULONG *)&CaptureScreenSettings.File.ulMaxSizeMB); 6908 AssertComRCReturn(hrc, VERR_INVALID_PARAMETER); 6909 Bstr bstrTemp; 6910 hrc = pCaptureScreenSettings->COMGETTER(FileName)(bstrTemp.asOutParam()); 6911 AssertComRCReturn(hrc, VERR_INVALID_PARAMETER); 6912 CaptureScreenSettings.File.strName = bstrTemp; 6913 hrc = pCaptureScreenSettings->COMGETTER(Options)(bstrTemp.asOutParam()); 6914 AssertComRCReturn(hrc, VERR_INVALID_PARAMETER); 6915 CaptureScreenSettings.strOptions = bstrTemp; 6916 hrc = pCaptureScreenSettings->COMGETTER(VideoWidth)((ULONG *)&CaptureScreenSettings.Video.ulWidth); 6917 AssertComRCReturn(hrc, VERR_INVALID_PARAMETER); 6918 hrc = pCaptureScreenSettings->COMGETTER(VideoHeight)((ULONG *)&CaptureScreenSettings.Video.ulHeight); 6919 AssertComRCReturn(hrc, VERR_INVALID_PARAMETER); 6920 hrc = pCaptureScreenSettings->COMGETTER(VideoRate)((ULONG *)&CaptureScreenSettings.Video.ulRate); 6921 AssertComRCReturn(hrc, VERR_INVALID_PARAMETER); 6922 hrc = pCaptureScreenSettings->COMGETTER(VideoFPS)((ULONG *)&CaptureScreenSettings.Video.ulFPS); 6923 AssertComRCReturn(hrc, VERR_INVALID_PARAMETER); 6924 6925 Settings.mapScreens[i] = CaptureScreenSettings; 6926 } 6927 6928 return VINF_SUCCESS; 6929 } 6930 6931 /** 6932 * Starts capturing. Does nothing if capturing is already active. 6933 * 6934 * @returns IPRT status code. 6935 */ 6936 int Console::i_videoRecStart(void) 6937 { 6938 if (Capture.mpVideoRecCtx && Capture.mpVideoRecCtx->IsStarted()) 6939 return VINF_SUCCESS; 6940 6941 LogRel(("VideoRec: Starting ...\n")); 6942 6943 try 6944 { 6945 Capture.mpVideoRecCtx = new CaptureContext(this); 6946 } 6947 catch (std::bad_alloc &) 6948 { 6949 return VERR_NO_MEMORY; 6950 } 6951 catch (int &rc) 6952 { 6953 return rc; 6954 } 6955 6956 settings::CaptureSettings Settings; 6957 int rc = i_videoRecLoad(Settings); 6958 if (RT_SUCCESS(rc)) 6959 { 6960 rc = Capture.mpVideoRecCtx->Create(Settings); 6961 if (RT_SUCCESS(rc)) 6962 { 6963 for (unsigned uScreen = 0; uScreen < Capture.mpVideoRecCtx->GetStreamCount(); uScreen++) 6964 mDisplay->i_videoRecScreenChanged(uScreen); 6965 } 6966 } 6967 6968 if (RT_FAILURE(rc)) 6969 LogRel(("VideoRec: Failed to start video recording (%Rrc)\n", rc)); 6970 6971 return rc; 6972 } 6973 6974 /** 6975 * Stops capturing. Does nothing if capturing is not active. 6976 */ 6977 int Console::i_videoRecStop(void) 6978 { 6979 if (Capture.mpVideoRecCtx && Capture.mpVideoRecCtx->IsStarted()) 6980 return VINF_SUCCESS; 6981 6982 LogRel(("VideoRec: Stopping ...\n")); 6983 6984 const size_t cStreams = Capture.mpVideoRecCtx->GetStreamCount(); 6985 6986 for (unsigned uScreen = 0; uScreen < cStreams; ++uScreen) 6987 mDisplay->i_videoRecScreenChanged(uScreen); 6988 6989 delete Capture.mpVideoRecCtx; 6990 Capture.mpVideoRecCtx = NULL; 6991 6992 ComPtr<ICaptureSettings> pCaptureSettings; 6993 HRESULT hrc = mMachine->COMGETTER(CaptureSettings)(pCaptureSettings.asOutParam()); 6994 ComAssertComRC(hrc); 6995 hrc = pCaptureSettings->COMSETTER(Enabled)(false); 6996 ComAssertComRC(hrc); 6997 6998 LogRel(("VideoRec: Stopped\n")); 6999 7000 return VINF_SUCCESS; 7001 } 7002 #endif /* VBOX_WITH_VIDEOREC */ 6880 7003 6881 7004 /** … … 9966 10089 9967 10090 #ifdef VBOX_WITH_VIDEOREC 9968 BOOL fVideoRecEnabled = FALSE;9969 rc = pConsole->mMachine->COMGETTER( VideoCaptureEnabled)(&fVideoRecEnabled);10091 ComPtr<ICaptureSettings> CaptureSettings; 10092 rc = pConsole->mMachine->COMGETTER(CaptureSettings)(CaptureSettings.asOutParam()); 9970 10093 AssertComRCReturnVoid(rc); 9971 10094 9972 if (fVideoRecEnabled) 9973 { 9974 int vrc2 = pConsole->i_videoCaptureEnable(fVideoRecEnabled, &alock); 10095 BOOL fCaptureEnabled; 10096 rc = CaptureSettings->COMGETTER(Enabled)(&fCaptureEnabled); 10097 AssertComRCReturnVoid(rc); 10098 10099 if (fCaptureEnabled) 10100 { 10101 int vrc2 = pConsole->i_videoCaptureEnable(fCaptureEnabled, &alock); 9975 10102 if (RT_SUCCESS(vrc2)) 9976 10103 { 9977 fire VideoCaptureChangedEvent(pConsole->mEventSource);10104 fireCaptureChangedEvent(pConsole->mEventSource); 9978 10105 } 9979 10106 else -
trunk/src/VBox/Main/src-client/ConsoleImpl2.cpp
r74474 r75251 2998 2998 InsertConfigString(pLunL0, "Driver", "AUDIO"); 2999 2999 AudioDriverCfg DrvCfgVideoRec(strAudioDevice, 0 /* Instance */, uAudioLUN, "AudioVideoRec"); 3000 rc = mAudioVideoRec->InitializeConfig(&DrvCfgVideoRec);3000 rc = Capture.mAudioVideoRec->InitializeConfig(&DrvCfgVideoRec); 3001 3001 if (RT_SUCCESS(rc)) 3002 3002 uAudioLUN++; -
trunk/src/VBox/Main/src-client/DisplayImpl.cpp
r75067 r75251 150 150 AssertRC(rc); 151 151 152 mpVideoRecCtx = NULL;153 152 for (unsigned i = 0; i < RT_ELEMENTS(maVideoRecEnabled); i++) 154 153 maVideoRecEnabled[i] = true; … … 2408 2407 #ifdef VBOX_WITH_VIDEOREC 2409 2408 /** 2410 * Returns the currently enabled video capturing features.2409 * Invalidates the capturing configuration. 2411 2410 * 2412 * @returns Enables video capturing features.2411 * @returns IPRT status code. 2413 2412 */ 2414 VIDEORECFEATURES Display::i_videoRecGetFeatures(void) 2415 { 2416 return VideoRecGetFeatures(&mVideoRecCfg); 2417 } 2418 2419 /** 2420 * Returns whether video capturing is currently is active or not. 2421 * 2422 * @returns True if video capturing is active, false if not. 2423 */ 2424 bool Display::i_videoRecStarted(void) 2425 { 2426 return VideoRecIsStarted(mpVideoRecCtx); 2427 } 2428 2429 /** 2430 * Invalidates the video recording configuration. 2431 */ 2432 void Display::i_videoRecInvalidate(void) 2433 { 2434 AssertPtr(mParent); 2435 ComPtr<IMachine> pMachine = mParent->i_machine(); 2436 Assert(pMachine.isNotNull()); 2437 2438 mVideoRecCfg.enmDst = VIDEORECDEST_FILE; /** @todo Make this configurable once we have more variations. */ 2439 2440 /* 2441 * Cache parameters from API. 2442 */ 2443 com::SafeArray<BOOL> aScreens; 2444 HRESULT hrc = pMachine->COMGETTER(VideoCaptureScreens)(ComSafeArrayAsOutParam(aScreens)); 2445 AssertComRCReturnVoid(hrc); 2446 2447 mVideoRecCfg.aScreens.resize(aScreens.size()); 2448 for (size_t i = 0; i < aScreens.size(); ++i) 2449 mVideoRecCfg.aScreens[i] = aScreens[i]; 2450 2451 hrc = pMachine->COMGETTER(VideoCaptureWidth)((ULONG *)&mVideoRecCfg.Video.uWidth); 2452 AssertComRCReturnVoid(hrc); 2453 hrc = pMachine->COMGETTER(VideoCaptureHeight)((ULONG *)&mVideoRecCfg.Video.uHeight); 2454 AssertComRCReturnVoid(hrc); 2455 hrc = pMachine->COMGETTER(VideoCaptureRate)((ULONG *)&mVideoRecCfg.Video.uRate); 2456 AssertComRCReturnVoid(hrc); 2457 hrc = pMachine->COMGETTER(VideoCaptureFPS)((ULONG *)&mVideoRecCfg.Video.uFPS); 2458 AssertComRCReturnVoid(hrc); 2459 hrc = pMachine->COMGETTER(VideoCaptureFile)(mVideoRecCfg.File.strName.asOutParam()); 2460 AssertComRCReturnVoid(hrc); 2461 hrc = pMachine->COMGETTER(VideoCaptureMaxFileSize)((ULONG *)&mVideoRecCfg.File.uMaxSizeMB); 2462 AssertComRCReturnVoid(hrc); 2463 hrc = pMachine->COMGETTER(VideoCaptureMaxTime)((ULONG *)&mVideoRecCfg.uMaxTimeS); 2464 AssertComRCReturnVoid(hrc); 2465 BSTR bstrOptions; 2466 hrc = pMachine->COMGETTER(VideoCaptureOptions)(&bstrOptions); 2467 AssertComRCReturnVoid(hrc); 2468 2469 /* 2470 * Set sensible defaults. 2471 */ 2472 mVideoRecCfg.Video.fEnabled = true; /* Enabled by default. */ 2473 2474 if (!mVideoRecCfg.Video.uFPS) /* Prevent division by zero. */ 2475 mVideoRecCfg.Video.uFPS = 15; 2476 2477 #ifdef VBOX_WITH_LIBVPX 2478 mVideoRecCfg.Video.Codec.VPX.uEncoderDeadline = 1000000 / mVideoRecCfg.Video.uFPS; 2479 #endif 2480 2481 #ifdef VBOX_WITH_AUDIO_VIDEOREC 2482 mVideoRecCfg.Audio.fEnabled = false; /* Disabled by default, unless set otherwise below. */ 2483 /* By default we use 22,5kHz, 16-bit, stereo for the audio track. */ 2484 mVideoRecCfg.Audio.uHz = 22050; 2485 mVideoRecCfg.Audio.cBits = 16; 2486 mVideoRecCfg.Audio.cChannels = 2; 2487 #endif 2488 2489 /* 2490 * Parse options string. 2491 */ 2492 com::Utf8Str strOptions(bstrOptions); 2493 size_t pos = 0; 2494 com::Utf8Str key, value; 2495 while ((pos = strOptions.parseKeyValue(key, value, pos)) != com::Utf8Str::npos) 2496 { 2497 if (key.compare("vc_quality", Utf8Str::CaseInsensitive) == 0) 2498 { 2499 #ifdef VBOX_WITH_LIBVPX 2500 if (value.compare("realtime", Utf8Str::CaseInsensitive) == 0) 2501 mVideoRecCfg.Video.Codec.VPX.uEncoderDeadline = VPX_DL_REALTIME; 2502 else if (value.compare("good", Utf8Str::CaseInsensitive) == 0) 2503 mVideoRecCfg.Video.Codec.VPX.uEncoderDeadline = 1000000 / mVideoRecCfg.Video.uFPS; 2504 else if (value.compare("best", Utf8Str::CaseInsensitive) == 0) 2505 mVideoRecCfg.Video.Codec.VPX.uEncoderDeadline = VPX_DL_BEST_QUALITY; 2506 else 2507 { 2508 LogRel(("VideoRec: Setting quality deadline to '%s'\n", value.c_str())); 2509 mVideoRecCfg.Video.Codec.VPX.uEncoderDeadline = value.toUInt32(); 2510 #endif 2511 } 2512 } 2513 else if (key.compare("vc_enabled", Utf8Str::CaseInsensitive) == 0) 2514 { 2515 if (value.compare("false", Utf8Str::CaseInsensitive) == 0) 2516 { 2517 mVideoRecCfg.Video.fEnabled = false; 2518 #ifdef VBOX_WITH_AUDIO_VIDEOREC 2519 LogRel(("VideoRec: Only audio will be recorded\n")); 2520 #endif 2521 } 2522 } 2523 else if (key.compare("ac_enabled", Utf8Str::CaseInsensitive) == 0) 2524 { 2525 #ifdef VBOX_WITH_AUDIO_VIDEOREC 2526 if (value.compare("true", Utf8Str::CaseInsensitive) == 0) 2527 { 2528 mVideoRecCfg.Audio.fEnabled = true; 2529 2530 } 2531 else 2532 LogRel(("VideoRec: Only video will be recorded\n")); 2533 #endif 2534 } 2535 else if (key.compare("ac_profile", Utf8Str::CaseInsensitive) == 0) 2536 { 2537 #ifdef VBOX_WITH_AUDIO_VIDEOREC 2538 if (value.compare("low", Utf8Str::CaseInsensitive) == 0) 2539 { 2540 mVideoRecCfg.Audio.uHz = 8000; 2541 mVideoRecCfg.Audio.cBits = 16; 2542 mVideoRecCfg.Audio.cChannels = 1; 2543 } 2544 else if (value.startsWith("med" /* "med[ium]" */, Utf8Str::CaseInsensitive) == 0) 2545 { 2546 /* Stay with the default set above. */ 2547 } 2548 else if (value.compare("high", Utf8Str::CaseInsensitive) == 0) 2549 { 2550 mVideoRecCfg.Audio.uHz = 48000; 2551 mVideoRecCfg.Audio.cBits = 16; 2552 mVideoRecCfg.Audio.cChannels = 2; 2553 } 2554 #endif 2555 } 2556 else 2557 LogRel(("VideoRec: Unknown option '%s' (value '%s'), skipping\n", key.c_str(), value.c_str())); 2558 2559 } /* while */ 2413 int Display::i_videoRecInvalidate(void) 2414 { 2415 CaptureContext *pCtx = mParent->i_videoRecGetContext(); 2416 if (!pCtx || !pCtx->IsStarted()) 2417 return VINF_SUCCESS; 2560 2418 2561 2419 /* 2562 2420 * Invalidate screens. 2563 2421 */ 2564 for (unsigned i = 0; i < mVideoRecCfg.aScreens.size(); i++) 2565 { 2566 bool fChanged = maVideoRecEnabled[i] != RT_BOOL(mVideoRecCfg.aScreens[i]); 2567 2568 maVideoRecEnabled[i] = RT_BOOL(mVideoRecCfg.aScreens[i]); 2569 2570 if (fChanged && i < mcMonitors) 2571 i_videoRecScreenChanged(i); 2572 2573 } 2574 } 2575 2576 /** 2577 * Sends belonging audio samples to the video capturing code. 2578 * Does nothing if capturing is disabled or if audio support for video capturing is disabled. 2579 * 2580 * @returns IPRT status code. 2581 * @param pvData Audio data. 2582 * @param cbData Size (in bytes) of audio data. 2583 * @param uTimestampMs Timestamp (in ms) of the audio data. 2584 */ 2585 int Display::i_videoRecSendAudio(const void *pvData, size_t cbData, uint64_t uTimestampMs) 2586 { 2587 if ( VideoRecIsStarted(mpVideoRecCtx) 2588 && VideoRecGetFeatures(&mVideoRecCfg) & VIDEORECFEATURE_AUDIO) 2589 { 2590 return VideoRecSendAudioFrame(mpVideoRecCtx, pvData, cbData, uTimestampMs); 2422 for (unsigned uScreen = 0; uScreen < mcMonitors; uScreen++) 2423 { 2424 CaptureStream *pCaptureStream = pCtx->GetStream(uScreen); 2425 2426 const bool fStreamEnabled = pCaptureStream->IsReady(); 2427 bool fChanged = maVideoRecEnabled[uScreen] != fStreamEnabled; 2428 2429 maVideoRecEnabled[uScreen] = fStreamEnabled; 2430 2431 if (fChanged && uScreen < mcMonitors) 2432 i_videoRecScreenChanged(uScreen); 2591 2433 } 2592 2434 … … 2594 2436 } 2595 2437 2596 /**2597 * Start video capturing. Does nothing if capturing is already active.2598 *2599 * @param pVideoRecCfg Video recording configuration to use.2600 * @returns IPRT status code.2601 */2602 int Display::i_videoRecStart(void)2603 {2604 if (VideoRecIsStarted(mpVideoRecCtx))2605 return VINF_SUCCESS;2606 2607 LogRel(("VideoRec: Starting ...\n"));2608 2609 int rc = VideoRecContextCreate(mcMonitors, &mVideoRecCfg, &mpVideoRecCtx);2610 if (RT_SUCCESS(rc))2611 {2612 for (unsigned uScreen = 0; uScreen < mcMonitors; uScreen++)2613 {2614 int rc2 = VideoRecStreamInit(VideoRecGetStream(mpVideoRecCtx, uScreen), mpVideoRecCtx, uScreen);2615 if (RT_SUCCESS(rc2))2616 {2617 i_videoRecScreenChanged(uScreen);2618 }2619 else2620 LogRel(("VideoRec: Failed to initialize video recording context #%u (%Rrc)\n", uScreen, rc2));2621 2622 if (RT_SUCCESS(rc))2623 rc = rc2;2624 }2625 }2626 2627 if (RT_FAILURE(rc))2628 LogRel(("VideoRec: Failed to start video recording (%Rrc)\n", rc));2629 2630 return rc;2631 }2632 2633 /**2634 * Stops video capturing. Does nothing if video capturing is not active.2635 */2636 void Display::i_videoRecStop(void)2637 {2638 if (!VideoRecIsStarted(mpVideoRecCtx))2639 return;2640 2641 LogRel(("VideoRec: Stopping ...\n"));2642 2643 VideoRecContextDestroy(mpVideoRecCtx);2644 mpVideoRecCtx = NULL;2645 2646 unsigned uScreenId;2647 for (uScreenId = 0; uScreenId < mcMonitors; ++uScreenId)2648 i_videoRecScreenChanged(uScreenId);2649 }2650 2651 2438 void Display::i_videoRecScreenChanged(unsigned uScreenId) 2652 2439 { 2653 if ( !VideoRecIsStarted(mpVideoRecCtx) 2654 || !maVideoRecEnabled[uScreenId]) 2440 CaptureContext *pCtx = mParent->i_videoRecGetContext(); 2441 2442 if ( RT_LIKELY(!maVideoRecEnabled[uScreenId]) 2443 || !pCtx || !pCtx->IsStarted()) 2655 2444 { 2656 2445 /* Skip recording this screen. */ … … 3599 3388 3600 3389 #ifdef VBOX_WITH_VIDEOREC 3601 if ( VideoRecIsStarted(pDisplay->mpVideoRecCtx) 3602 && VideoRecGetFeatures(&pDisplay->mVideoRecCfg) & VIDEORECFEATURE_VIDEO) 3390 AssertPtr(pDisplay->mParent); 3391 CaptureContext *pCtx = pDisplay->mParent->i_videoRecGetContext(); 3392 3393 if ( pCtx 3394 && pCtx->IsStarted() 3395 && pCtx->IsFeatureEnabled(CaptureFeature_Video)) 3603 3396 { 3604 3397 do { … … 3638 3431 # endif /* VBOX_WITH_HGCM && VBOX_WITH_CROGL */ 3639 3432 3640 uint64_t u64Now= RTTimeProgramMilliTS();3433 uint64_t tsNowMs = RTTimeProgramMilliTS(); 3641 3434 for (uScreenId = 0; uScreenId < pDisplay->mcMonitors; uScreenId++) 3642 3435 { … … 3644 3437 continue; 3645 3438 3646 if ( VideoRecIsLimitReached(pDisplay->mpVideoRecCtx, uScreenId, u64Now))3439 if (pCtx->IsLimitReached(uScreenId, tsNowMs)) 3647 3440 { 3648 pDisplay->i_videoRecStop(); 3649 pDisplay->mParent->i_machine()->COMSETTER(VideoCaptureEnabled)(false); 3441 pDisplay->mParent->i_videoRecStop(); 3650 3442 break; 3651 3443 } … … 3677 3469 &bitmapFormat); 3678 3470 if (SUCCEEDED(hr) && pbAddress) 3679 rc = VideoRecSendVideoFrame(pDisplay->mpVideoRecCtx, uScreenId, 0, 0, 3680 BitmapFormat_BGR, 3681 ulBitsPerPixel, ulBytesPerLine, ulWidth, ulHeight, 3682 pbAddress, u64Now); 3471 rc = pCtx->SendVideoFrame(uScreenId, 0, 0, BitmapFormat_BGR, 3472 ulBitsPerPixel, ulBytesPerLine, ulWidth, ulHeight, 3473 pbAddress, tsNowMs); 3683 3474 else 3684 3475 rc = VERR_NOT_SUPPORTED; … … 4039 3830 } 4040 3831 4041 bool Display::i_handleCrVRecScreenshotBegin(uint32_t uScreen, uint64_t u64Timestamp) 4042 { 4043 /** @todo r=bird: u64Timestamp - using the 'u64' prefix add nothing. 4044 * However, using one of the prefixes indicating the timestamp unit 4045 * would be very valuable! */ 3832 bool Display::i_handleCrVRecScreenshotBegin(uint32_t uScreen, uint64_t uTimestampMs) 3833 { 4046 3834 # ifdef VBOX_WITH_VIDEOREC 4047 return VideoRecIsReady(mpVideoRecCtx, uScreen, u64Timestamp); 3835 CaptureContext *pCtx = mParent->i_videoRecGetContext(); 3836 return ( pCtx 3837 && pCtx->IsReady(uScreen, uTimestampMs)); 4048 3838 # else 4049 RT_NOREF(uScreen, u 64Timestamp);3839 RT_NOREF(uScreen, uTimestampMs); 4050 3840 return false; 4051 3841 # endif 4052 3842 } 4053 3843 4054 void Display::i_handleCrVRecScreenshotEnd(uint32_t uScreen, uint64_t u 64Timestamp)4055 { 4056 RT_NOREF(uScreen, u 64Timestamp);3844 void Display::i_handleCrVRecScreenshotEnd(uint32_t uScreen, uint64_t uTimestampMs) 3845 { 3846 RT_NOREF(uScreen, uTimestampMs); 4057 3847 } 4058 3848 … … 4061 3851 uint32_t uBitsPerPixel, uint32_t uBytesPerLine, 4062 3852 uint32_t uGuestWidth, uint32_t uGuestHeight, 4063 uint8_t *pu8BufferAddress, uint64_t u 64Timestamp)3853 uint8_t *pu8BufferAddress, uint64_t uTimestampMs) 4064 3854 { 4065 3855 Assert(mfCrOglVideoRecState == CRVREC_STATE_SUBMITTED); 4066 3856 # ifdef VBOX_WITH_VIDEOREC 4067 if ( VideoRecIsStarted(mpVideoRecCtx) 4068 && VideoRecGetFeatures(&mVideoRecCfg) & VIDEORECFEATURE_VIDEO) 4069 { 4070 int rc2 = VideoRecSendVideoFrame(mpVideoRecCtx, uScreen, x, y, 4071 uPixelFormat, 4072 uBitsPerPixel, uBytesPerLine, 4073 uGuestWidth, uGuestHeight, 4074 pu8BufferAddress, u64Timestamp); 3857 CaptureContext *pCtx = mParent->i_videoRecGetContext(); 3858 3859 if ( pCtx 3860 && pCtx->IsStarted() 3861 && pCtx->IsFeatureEnabled(CaptureFeature_Video)) 3862 { 3863 int rc2 = pCtx->SendVideoFrame(uScreen, x, y, 3864 uPixelFormat, 3865 uBitsPerPixel, uBytesPerLine, 3866 uGuestWidth, uGuestHeight, 3867 pu8BufferAddress, uTimestampMs); 4075 3868 RT_NOREF(rc2); 4076 3869 Assert(rc2 == VINF_SUCCESS /* || rc == VERR_TRY_AGAIN || rc == VINF_TRY_AGAIN*/); … … 4078 3871 # else 4079 3872 RT_NOREF(uScreen, x, y, uPixelFormat, \ 4080 uBitsPerPixel, uBytesPerLine, uGuestWidth, uGuestHeight, pu8BufferAddress, u 64Timestamp);3873 uBitsPerPixel, uBytesPerLine, uGuestWidth, uGuestHeight, pu8BufferAddress, uTimestampMs); 4081 3874 # endif /* VBOX_WITH_VIDEOREC */ 4082 3875 } … … 4706 4499 AutoWriteLock displayLock(pThis->pDisplay COMMA_LOCKVAL_SRC_POS); 4707 4500 #ifdef VBOX_WITH_VIDEOREC 4708 pThis->pDisplay-> i_videoRecStop();4501 pThis->pDisplay->mParent->i_videoRecStop(); 4709 4502 #endif 4710 4503 #ifdef VBOX_WITH_CRHGSMI -
trunk/src/VBox/Main/src-client/DrvAudioVideoRec.cpp
r75083 r75251 828 828 case AVRECCONTAINERTYPE_MAIN_CONSOLE: 829 829 { 830 HRESULT hr = pSink->Con.Main.pConsole->i_ audioVideoRecSendAudio(pStreamAV->pvDstBuf, cbDst, uPTSMs);830 HRESULT hr = pSink->Con.Main.pConsole->i_videoRecSendAudio(pStreamAV->pvDstBuf, cbDst, uPTSMs); 831 831 Assert(hr == S_OK); 832 832 RT_NOREF(hr); … … 1086 1086 * 1087 1087 * @returns IPRT status code. 1088 * @param pVideoRecCfg Pointer to video recording configuration to apply.1089 */ 1090 int AudioVideoRec::applyConfiguration(const PVIDEORECCFG pVideoRecCfg)1088 * @param Settings Capturing configuration to apply. 1089 */ 1090 int AudioVideoRec::applyConfiguration(const settings::CaptureSettings &a_Settings) 1091 1091 { 1092 1092 /** @todo Do some validation here. */ 1093 mVideoRecCfg = *pVideoRecCfg; /* Note: Does have an own copy operator. */1093 mVideoRecCfg = a_Settings; /* Note: Does have an own copy operator. */ 1094 1094 return VINF_SUCCESS; 1095 1095 } … … 1101 1101 int AudioVideoRec::configureDriver(PCFGMNODE pLunCfg) 1102 1102 { 1103 int rc = CFGMR3InsertInteger(pLunCfg, "Object", (uintptr_t)mpConsole->i_ getAudioVideoRec());1103 int rc = CFGMR3InsertInteger(pLunCfg, "Object", (uintptr_t)mpConsole->i_videoRecGetAudioDrv()); 1104 1104 AssertRCReturn(rc, rc); 1105 1105 rc = CFGMR3InsertInteger(pLunCfg, "ObjectConsole", (uintptr_t)mpConsole); 1106 1106 AssertRCReturn(rc, rc); 1107 1107 1108 rc = CFGMR3InsertInteger(pLunCfg, "ContainerType", (uint64_t)mVideoRecCfg.enmDst); 1108 /** @todo For now we're using the configuration of the first screen here audio-wise. */ 1109 Assert(mVideoRecCfg.mapScreens.size() >= 1); 1110 const settings::CaptureScreenSettings &Screen0Settings = mVideoRecCfg.mapScreens[0]; 1111 1112 rc = CFGMR3InsertInteger(pLunCfg, "ContainerType", (uint64_t)Screen0Settings.enmDest); 1109 1113 AssertRCReturn(rc, rc); 1110 if ( mVideoRecCfg.enmDst == VIDEORECDEST_FILE)1111 { 1112 rc = CFGMR3InsertString(pLunCfg, "ContainerFileName", Utf8Str( mVideoRecCfg.File.strName).c_str());1114 if (Screen0Settings.enmDest == CaptureDestination_File) 1115 { 1116 rc = CFGMR3InsertString(pLunCfg, "ContainerFileName", Utf8Str(Screen0Settings.File.strName).c_str()); 1113 1117 AssertRCReturn(rc, rc); 1114 1118 } 1115 rc = CFGMR3InsertInteger(pLunCfg, "CodecHz", mVideoRecCfg.Audio.uHz);1119 rc = CFGMR3InsertInteger(pLunCfg, "CodecHz", Screen0Settings.Audio.uHz); 1116 1120 AssertRCReturn(rc, rc); 1117 rc = CFGMR3InsertInteger(pLunCfg, "CodecBits", mVideoRecCfg.Audio.cBits);1121 rc = CFGMR3InsertInteger(pLunCfg, "CodecBits", Screen0Settings.Audio.cBits); 1118 1122 AssertRCReturn(rc, rc); 1119 rc = CFGMR3InsertInteger(pLunCfg, "CodecChannels", mVideoRecCfg.Audio.cChannels);1123 rc = CFGMR3InsertInteger(pLunCfg, "CodecChannels", Screen0Settings.Audio.cChannels); 1120 1124 AssertRCReturn(rc, rc); 1121 1125 rc = CFGMR3InsertInteger(pLunCfg, "CodecBitrate", 0); /* Let Opus decide for now. */ -
trunk/src/VBox/Main/src-client/SessionImpl.cpp
r68986 r75251 725 725 } 726 726 727 HRESULT Session::on VideoCaptureChange()728 { 729 LogFlowThisFunc(("\n")); 730 731 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 732 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); 733 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); 734 #ifndef VBOX_COM_INPROC_API_CLIENT 735 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE); 736 737 return mConsole->i_on VideoCaptureChange();727 HRESULT Session::onCaptureChange() 728 { 729 LogFlowThisFunc(("\n")); 730 731 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); 732 AssertReturn(mState == SessionState_Locked, VBOX_E_INVALID_VM_STATE); 733 AssertReturn(mType == SessionType_WriteLock, VBOX_E_INVALID_OBJECT_STATE); 734 #ifndef VBOX_COM_INPROC_API_CLIENT 735 AssertReturn(mConsole, VBOX_E_INVALID_OBJECT_STATE); 736 737 return mConsole->i_onCaptureChange(); 738 738 #else 739 739 return S_OK; -
trunk/src/VBox/Main/src-client/VideoRec.cpp
r75068 r75251 43 43 #include <VBox/com/VirtualBox.h> 44 44 45 #include " WebMWriter.h"45 #include "ConsoleImpl.h" 46 46 #include "VideoRec.h" 47 47 #include "VideoRecInternals.h" 48 48 #include "VideoRecStream.h" 49 49 #include "VideoRecUtils.h" 50 #include "WebMWriter.h" 50 51 51 52 using namespace com; … … 103 104 104 105 106 CaptureContext::CaptureContext(Console *a_pConsole) 107 : pConsole(a_pConsole) { } 108 109 CaptureContext::CaptureContext(Console *a_pConsole, const settings::CaptureSettings &a_Settings) 110 : pConsole(a_pConsole) 111 { 112 int rc = CaptureContext::createInternal(a_Settings); 113 if (RT_FAILURE(rc)) 114 throw rc; 115 } 116 117 CaptureContext::~CaptureContext(void) 118 { 119 destroyInternal(); 120 } 121 105 122 /** 106 123 * Worker thread for all streams of a video recording context. … … 108 125 * For video frames, this also does the RGB/YUV conversion and encoding. 109 126 */ 110 static DECLCALLBACK(int) videoRecThread(RTTHREAD hThreadSelf, void *pvUser)111 { 112 PVIDEORECCONTEXT pCtx = (PVIDEORECCONTEXT)pvUser;127 DECLCALLBACK(int) CaptureContext::threadMain(RTTHREAD hThreadSelf, void *pvUser) 128 { 129 CaptureContext *pThis = (CaptureContext *)pvUser; 113 130 114 131 /* Signal that we're up and rockin'. */ … … 119 136 for (;;) 120 137 { 121 int rc = RTSemEventWait(p Ctx->WaitEvent, RT_INDEFINITE_WAIT);138 int rc = RTSemEventWait(pThis->WaitEvent, RT_INDEFINITE_WAIT); 122 139 AssertRCBreak(rc); 123 140 124 Log2Func(("Processing %zu streams\n", p Ctx->vecStreams.size()));141 Log2Func(("Processing %zu streams\n", pThis->vecStreams.size())); 125 142 126 143 /** @todo r=andy This is inefficient -- as we already wake up this thread 127 144 * for every screen from Main, we here go again (on every wake up) through 128 145 * all screens. */ 129 VideoRecStreams::iterator itStream = p Ctx->vecStreams.begin();130 while (itStream != p Ctx->vecStreams.end())131 { 132 PVIDEORECSTREAMpStream = (*itStream);133 134 rc = VideoRecStreamProcess(pStream);146 VideoRecStreams::iterator itStream = pThis->vecStreams.begin(); 147 while (itStream != pThis->vecStreams.end()) 148 { 149 CaptureStream *pStream = (*itStream); 150 151 rc = pStream->Process(pThis->mapBlocksCommon); 135 152 if (RT_FAILURE(rc)) 136 153 break; … … 144 161 /* Keep going in case of errors. */ 145 162 146 if (ASMAtomicReadBool(&p Ctx->fShutdown))163 if (ASMAtomicReadBool(&pThis->fShutdown)) 147 164 { 148 165 LogFunc(("Thread is shutting down ...\n")); … … 160 177 * 161 178 * @returns IPRT status code. 162 * @param pCtx Video recording context to notify thread for. 163 */ 164 static int videoRecThreadNotify(PVIDEORECCONTEXT pCtx) 165 { 166 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 167 168 return RTSemEventSignal(pCtx->WaitEvent); 179 */ 180 int CaptureContext::threadNotify(void) 181 { 182 return RTSemEventSignal(this->WaitEvent); 169 183 } 170 184 … … 175 189 * @param cScreens Number of screens to create context for. 176 190 * @param pVideoRecCfg Pointer to video recording configuration to use. 177 * @param ppCtx Pointer to created video recording context on success. 178 */ 179 int VideoRecContextCreate(uint32_t cScreens, PVIDEORECCFG pVideoRecCfg, PVIDEORECCONTEXT *ppCtx) 180 { 181 AssertReturn(cScreens, VERR_INVALID_PARAMETER); 182 AssertPtrReturn(pVideoRecCfg, VERR_INVALID_POINTER); 183 AssertPtrReturn(ppCtx, VERR_INVALID_POINTER); 184 185 VIDEORECCONTEXT *pCtx = NULL; 186 try 187 { 188 pCtx = new VIDEORECCONTEXT(); 189 } 190 catch (std::bad_alloc &) 191 { 192 return VERR_NO_MEMORY; 193 } 194 195 int rc = RTCritSectInit(&pCtx->CritSect); 191 */ 192 int CaptureContext::createInternal(const settings::CaptureSettings &a_Settings) 193 { 194 int rc = RTCritSectInit(&this->CritSect); 196 195 if (RT_FAILURE(rc)) 197 {198 delete pCtx;199 196 return rc; 200 } 201 202 for (uint32_t uScreen = 0; uScreen < cScreens; uScreen++)203 { 204 VIDEORECSTREAM*pStream = NULL;197 198 settings::CaptureScreenMap::const_iterator itScreen = a_Settings.mapScreens.begin(); 199 while (itScreen != a_Settings.mapScreens.end()) 200 { 201 CaptureStream *pStream = NULL; 205 202 try 206 203 { 207 pStream = new VIDEORECSTREAM(); 204 pStream = new CaptureStream(itScreen->first /* Screen ID */, itScreen->second); 205 this->vecStreams.push_back(pStream); 208 206 } 209 207 catch (std::bad_alloc &) … … 212 210 break; 213 211 } 214 215 rc = RTCritSectInit(&pStream->CritSect);216 if (RT_FAILURE(rc))217 break;218 219 try220 {221 pStream->uScreenID = uScreen;222 223 pCtx->vecStreams.push_back(pStream);224 225 pStream->File.pWEBM = new WebMWriter();226 }227 catch (std::bad_alloc &)228 {229 rc = VERR_NO_MEMORY;230 break;231 }232 212 } 233 213 234 214 if (RT_SUCCESS(rc)) 235 215 { 236 pCtx->tsStartMs = RTTimeMilliTS();237 pCtx->enmState = VIDEORECSTS_UNINITIALIZED;238 pCtx->fStarted = false;239 pCtx->fShutdown = false;240 241 /* Copy the configurationto our context. */242 pCtx->Cfg = *pVideoRecCfg;243 244 rc = RTSemEventCreate(& pCtx->WaitEvent);216 this->tsStartMs = RTTimeMilliTS(); 217 this->enmState = VIDEORECSTS_UNINITIALIZED; 218 this->fStarted = false; 219 this->fShutdown = false; 220 221 /* Copy the settings to our context. */ 222 this->Settings = a_Settings; 223 224 rc = RTSemEventCreate(&this->WaitEvent); 245 225 AssertRCReturn(rc, rc); 246 226 247 rc = RTThreadCreate(& pCtx->Thread, videoRecThread, (void *)pCtx, 0,227 rc = RTThreadCreate(&this->Thread, CaptureContext::threadMain, (void *)this, 0, 248 228 RTTHREADTYPE_MAIN_WORKER, RTTHREADFLAGS_WAITABLE, "VideoRec"); 249 229 250 230 if (RT_SUCCESS(rc)) /* Wait for the thread to start. */ 251 rc = RTThreadUserWait( pCtx->Thread, 30 * RT_MS_1SEC /* 30s timeout */);231 rc = RTThreadUserWait(this->Thread, 30 * RT_MS_1SEC /* 30s timeout */); 252 232 253 233 if (RT_SUCCESS(rc)) 254 234 { 255 pCtx->enmState = VIDEORECSTS_INITIALIZED; 256 pCtx->fStarted = true; 257 258 if (ppCtx) 259 *ppCtx = pCtx; 235 this->enmState = VIDEORECSTS_INITIALIZED; 236 this->fStarted = true; 260 237 } 261 238 } … … 263 240 if (RT_FAILURE(rc)) 264 241 { 265 int rc2 = VideoRecContextDestroy(pCtx);242 int rc2 = destroyInternal(); 266 243 AssertRC(rc2); 267 244 } … … 272 249 /** 273 250 * Destroys a video recording context. 274 * 275 * @param pCtx Video recording context to destroy. 276 */ 277 int VideoRecContextDestroy(PVIDEORECCONTEXT pCtx) 278 { 279 if (!pCtx) 280 return VINF_SUCCESS; 281 251 */ 252 int CaptureContext::destroyInternal(void) 253 { 282 254 int rc = VINF_SUCCESS; 283 255 284 if ( pCtx->enmState == VIDEORECSTS_INITIALIZED)256 if (this->enmState == VIDEORECSTS_INITIALIZED) 285 257 { 286 258 LogFunc(("Shutting down thread ...\n")); 287 259 288 260 /* Set shutdown indicator. */ 289 ASMAtomicWriteBool(& pCtx->fShutdown, true);261 ASMAtomicWriteBool(&this->fShutdown, true); 290 262 291 263 /* Signal the thread and wait for it to shut down. */ 292 rc = videoRecThreadNotify(pCtx);264 rc = threadNotify(); 293 265 if (RT_SUCCESS(rc)) 294 rc = RTThreadWait( pCtx->Thread, 30 * 1000 /* 10s timeout */, NULL);266 rc = RTThreadWait(this->Thread, 30 * 1000 /* 10s timeout */, NULL); 295 267 296 268 if (RT_SUCCESS(rc)) 297 269 { 298 270 /* Disable the context. */ 299 ASMAtomicWriteBool(& pCtx->fStarted, false);300 301 int rc2 = RTSemEventDestroy( pCtx->WaitEvent);271 ASMAtomicWriteBool(&this->fStarted, false); 272 273 int rc2 = RTSemEventDestroy(this->WaitEvent); 302 274 AssertRC(rc2); 303 275 304 pCtx->WaitEvent = NIL_RTSEMEVENT;276 this->WaitEvent = NIL_RTSEMEVENT; 305 277 } 306 278 } … … 312 284 } 313 285 314 rc = RTCritSectEnter(& pCtx->CritSect);286 rc = RTCritSectEnter(&this->CritSect); 315 287 if (RT_SUCCESS(rc)) 316 288 { 317 VideoRecStreams::iterator it = pCtx->vecStreams.begin(); 318 while (it != pCtx->vecStreams.end()) 319 { 320 PVIDEORECSTREAM pStream = (*it); 321 322 VideoRecStreamLock(pStream); 323 324 int rc2 = VideoRecStreamClose(pStream); 289 VideoRecStreams::iterator it = this->vecStreams.begin(); 290 while (it != this->vecStreams.end()) 291 { 292 CaptureStream *pStream = (*it); 293 294 int rc2 = pStream->Uninit(); 325 295 if (RT_SUCCESS(rc)) 326 296 rc = rc2; 327 297 328 rc2 = VideoRecStreamUninit(pStream);329 if (RT_SUCCESS(rc))330 rc = rc2;331 332 pCtx->vecStreams.erase(it);333 it = pCtx->vecStreams.begin();334 335 VideoRecStreamUnlock(pStream);336 337 RTCritSectDelete(&pStream->CritSect);338 339 298 delete pStream; 340 299 pStream = NULL; 300 301 this->vecStreams.erase(it); 302 it = this->vecStreams.begin(); 303 304 delete pStream; 305 pStream = NULL; 341 306 } 342 307 343 308 /* Sanity. */ 344 Assert( pCtx->vecStreams.empty());345 Assert( pCtx->mapBlocksCommon.size() == 0);346 347 int rc2 = RTCritSectLeave(& pCtx->CritSect);309 Assert(this->vecStreams.empty()); 310 Assert(this->mapBlocksCommon.size() == 0); 311 312 int rc2 = RTCritSectLeave(&this->CritSect); 348 313 AssertRC(rc2); 349 314 350 RTCritSectDelete(&pCtx->CritSect); 351 352 delete pCtx; 353 pCtx = NULL; 315 RTCritSectDelete(&this->CritSect); 354 316 } 355 317 … … 357 319 } 358 320 359 /** 360 * Returns which recording features currently are enabled for a given configuration. 361 * 362 * @returns Enabled video recording features. 363 * @param pCfg Pointer to recording configuration. 364 */ 365 VIDEORECFEATURES VideoRecGetFeatures(PVIDEORECCFG pCfg) 366 { 367 if (!pCfg) 368 return VIDEORECFEATURE_NONE; 369 370 VIDEORECFEATURES fFeatures = VIDEORECFEATURE_NONE; 371 372 if (pCfg->Video.fEnabled) 373 fFeatures |= VIDEORECFEATURE_VIDEO; 374 375 #ifdef VBOX_WITH_AUDIO_VIDEOREC 376 if (pCfg->Audio.fEnabled) 377 fFeatures |= VIDEORECFEATURE_AUDIO; 378 #endif 379 380 return fFeatures; 321 const settings::CaptureSettings &CaptureContext::GetConfig(void) const 322 { 323 return this->Settings; 324 } 325 326 CaptureStream *CaptureContext::getStreamInternal(unsigned uScreen) const 327 { 328 CaptureStream *pStream; 329 330 try 331 { 332 pStream = this->vecStreams.at(uScreen); 333 } 334 catch (std::out_of_range &) 335 { 336 pStream = NULL; 337 } 338 339 return pStream; 381 340 } 382 341 … … 385 344 * 386 345 * @returns Pointer to recording stream if found, or NULL if not found. 387 * @param pCtx Recording context to look up stream for.388 346 * @param uScreen Screen number of recording stream to look up. 389 347 */ 390 PVIDEORECSTREAM VideoRecGetStream(PVIDEORECCONTEXT pCtx, uint32_t uScreen) 391 { 392 AssertPtrReturn(pCtx, NULL); 393 394 PVIDEORECSTREAM pStream; 395 396 try 397 { 398 pStream = pCtx->vecStreams.at(uScreen); 399 } 400 catch (std::out_of_range &) 401 { 402 pStream = NULL; 403 } 404 405 return pStream; 348 CaptureStream *CaptureContext::GetStream(unsigned uScreen) const 349 { 350 return getStreamInternal(uScreen); 351 } 352 353 size_t CaptureContext::GetStreamCount(void) const 354 { 355 return this->vecStreams.size(); 356 } 357 358 int CaptureContext::Create(const settings::CaptureSettings &a_Settings) 359 { 360 return createInternal(a_Settings); 361 } 362 363 int CaptureContext::Destroy(void) 364 { 365 return destroyInternal(); 366 } 367 368 bool CaptureContext::IsFeatureEnabled(CaptureFeature_T enmFeature) const 369 { 370 VideoRecStreams::const_iterator itStream = this->vecStreams.begin(); 371 while (itStream != this->vecStreams.end()) 372 { 373 if ((*itStream)->GetConfig().isFeatureEnabled(enmFeature)) 374 return true; 375 ++itStream; 376 } 377 378 return false; 379 } 380 381 bool CaptureContext::IsReady(void) const 382 { 383 return this->fStarted; 406 384 } 407 385 … … 410 388 * 411 389 * @returns true if recording engine is ready, false if not. 412 * @param pCtx Pointer to video recording context.413 390 * @param uScreen Screen ID. 414 391 * @param uTimeStampMs Current time stamp (in ms). Currently not being used. 415 392 */ 416 bool VideoRecIsReady(PVIDEORECCONTEXT pCtx, uint32_t uScreen, uint64_t uTimeStampMs) 417 { 418 AssertPtrReturn(pCtx, false); 393 bool CaptureContext::IsReady(uint32_t uScreen, uint64_t uTimeStampMs) const 394 { 419 395 RT_NOREF(uTimeStampMs); 420 396 421 if ( ASMAtomicReadU32(&pCtx->enmState)!= VIDEORECSTS_INITIALIZED)397 if (this->enmState != VIDEORECSTS_INITIALIZED) 422 398 return false; 423 399 424 400 bool fIsReady = false; 425 401 426 PVIDEORECSTREAM pStream = VideoRecGetStream(pCtx,uScreen);402 const CaptureStream *pStream = GetStream(uScreen); 427 403 if (pStream) 428 { 429 VideoRecStreamLock(pStream); 430 fIsReady = pStream->fEnabled; 431 VideoRecStreamUnlock(pStream); 432 } 404 fIsReady = pStream->IsReady(); 433 405 434 406 /* Note: Do not check for other constraints like the video FPS rate here, … … 443 415 * 444 416 * @returns true if active, false if not. 445 * @param pCtx Pointer to video recording context. 446 */ 447 bool VideoRecIsStarted(PVIDEORECCONTEXT pCtx) 448 { 449 if (!pCtx) 450 return false; 451 452 return ASMAtomicReadBool(&pCtx->fStarted); 417 */ 418 bool CaptureContext::IsStarted(void) const 419 { 420 return this->fStarted; 453 421 } 454 422 … … 457 425 * 458 426 * @returns true if any limit has been reached. 459 * @param pCtx Pointer to video recording context.460 427 * @param uScreen Screen ID. 461 428 * @param tsNowMs Current time stamp (in ms). 462 429 */ 463 bool VideoRecIsLimitReached(PVIDEORECCONTEXT pCtx, uint32_t uScreen, uint64_t tsNowMs)464 { 465 PVIDEORECSTREAM pStream = VideoRecGetStream(pCtx,uScreen);430 bool CaptureContext::IsLimitReached(uint32_t uScreen, uint64_t tsNowMs) const 431 { 432 const CaptureStream *pStream = GetStream(uScreen); 466 433 if ( !pStream 467 || !pStream->fEnabled) 468 { 469 return false; 470 } 471 472 const PVIDEORECCFG pCfg = &pCtx->Cfg; 473 474 if ( pCfg->uMaxTimeS 475 && tsNowMs >= pCtx->tsStartMs + (pCfg->uMaxTimeS * RT_MS_1SEC)) 434 || pStream->IsLimitReached(tsNowMs)) 476 435 { 477 436 return true; 478 437 } 479 438 480 if (pCfg->enmDst == VIDEORECDEST_FILE)481 {482 483 if (pCfg->File.uMaxSizeMB)484 {485 uint64_t sizeInMB = pStream->File.pWEBM->GetFileSize() / _1M;486 if(sizeInMB >= pCfg->File.uMaxSizeMB)487 return true;488 }489 490 /* Check for available free disk space */491 if ( pStream->File.pWEBM492 && pStream->File.pWEBM->GetAvailableSpace() < 0x100000) /** @todo r=andy WTF? Fix this. */493 {494 LogRel(("VideoRec: Not enough free storage space available, stopping video capture\n"));495 return true;496 }497 }498 499 439 return false; 500 440 } … … 506 446 * 507 447 * @returns IPRT status code. 508 * @param pCtx Pointer to the video recording context.509 448 * @param pvData Audio frame data to send. 510 449 * @param cbData Size (in bytes) of (encoded) audio frame data. 511 450 * @param uTimeStampMs Time stamp (in ms) of audio playback. 512 451 */ 513 int VideoRecSendAudioFrame(PVIDEORECCONTEXT pCtx,const void *pvData, size_t cbData, uint64_t uTimeStampMs)452 int CaptureContext::SendAudioFrame(const void *pvData, size_t cbData, uint64_t uTimeStampMs) 514 453 { 515 454 #ifdef VBOX_WITH_AUDIO_VIDEOREC … … 537 476 pBlock->pvData = pFrame; 538 477 pBlock->cbData = sizeof(VIDEORECAUDIOFRAME) + cbData; 539 pBlock->cRefs = (uint16_t) pCtx->vecStreams.size(); /* All streams need the same audio data. */478 pBlock->cRefs = (uint16_t)this->vecStreams.size(); /* All streams need the same audio data. */ 540 479 pBlock->uTimeStampMs = uTimeStampMs; 541 480 542 int rc = RTCritSectEnter(& pCtx->CritSect);481 int rc = RTCritSectEnter(&this->CritSect); 543 482 if (RT_FAILURE(rc)) 544 483 return rc; … … 546 485 try 547 486 { 548 VideoRecBlockMap::iterator itBlocks = pCtx->mapBlocksCommon.find(uTimeStampMs);549 if (itBlocks == pCtx->mapBlocksCommon.end())550 { 551 VideoRecBlocks *pVideoRecBlocks = new VideoRecBlocks();487 VideoRecBlockMap::iterator itBlocks = this->mapBlocksCommon.find(uTimeStampMs); 488 if (itBlocks == this->mapBlocksCommon.end()) 489 { 490 CaptureBlocks *pVideoRecBlocks = new CaptureBlocks(); 552 491 pVideoRecBlocks->List.push_back(pBlock); 553 492 554 pCtx->mapBlocksCommon.insert(std::make_pair(uTimeStampMs, pVideoRecBlocks));493 this->mapBlocksCommon.insert(std::make_pair(uTimeStampMs, pVideoRecBlocks)); 555 494 } 556 495 else … … 563 502 } 564 503 565 int rc2 = RTCritSectLeave(& pCtx->CritSect);504 int rc2 = RTCritSectLeave(&this->CritSect); 566 505 AssertRC(rc2); 567 506 568 507 if (RT_SUCCESS(rc)) 569 rc = videoRecThreadNotify(pCtx);508 rc = threadNotify(); 570 509 571 510 return rc; … … 583 522 * 584 523 * @returns IPRT status code. 585 * @param pCtx Pointer to the video recording context. 586 * @param uScreen Screen number. 524 * @param uScreen Screen number to send video frame to. 587 525 * @param x Starting x coordinate of the video frame. 588 526 * @param y Starting y coordinate of the video frame. … … 595 533 * @param uTimeStampMs Time stamp (in ms). 596 534 */ 597 int VideoRecSendVideoFrame(PVIDEORECCONTEXT pCtx, uint32_t uScreen, uint32_t x, uint32_t y, 598 uint32_t uPixelFormat, uint32_t uBPP, uint32_t uBytesPerLine, 599 uint32_t uSrcWidth, uint32_t uSrcHeight, uint8_t *puSrcData, 600 uint64_t uTimeStampMs) 601 { 602 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 535 int CaptureContext::SendVideoFrame(uint32_t uScreen, uint32_t x, uint32_t y, 536 uint32_t uPixelFormat, uint32_t uBPP, uint32_t uBytesPerLine, 537 uint32_t uSrcWidth, uint32_t uSrcHeight, uint8_t *puSrcData, 538 uint64_t uTimeStampMs) 539 { 603 540 AssertReturn(uSrcWidth, VERR_INVALID_PARAMETER); 604 541 AssertReturn(uSrcHeight, VERR_INVALID_PARAMETER); 605 542 AssertReturn(puSrcData, VERR_INVALID_POINTER); 606 543 607 int rc = RTCritSectEnter(& pCtx->CritSect);544 int rc = RTCritSectEnter(&this->CritSect); 608 545 AssertRC(rc); 609 546 610 PVIDEORECSTREAM pStream = VideoRecGetStream(pCtx,uScreen);547 CaptureStream *pStream = GetStream(uScreen); 611 548 if (!pStream) 612 549 { 613 rc = RTCritSectLeave(& pCtx->CritSect);550 rc = RTCritSectLeave(&this->CritSect); 614 551 AssertRC(rc); 615 552 … … 617 554 } 618 555 619 VideoRecStreamLock(pStream); 620 621 PVIDEORECVIDEOFRAME pFrame = NULL; 622 623 do 624 { 625 if (!pStream->fEnabled) 626 { 627 rc = VINF_TRY_AGAIN; /* Not (yet) enabled. */ 628 break; 629 } 630 631 if (uTimeStampMs < pStream->Video.uLastTimeStampMs + pStream->Video.uDelayMs) 632 { 633 rc = VINF_TRY_AGAIN; /* Respect maximum frames per second. */ 634 break; 635 } 636 637 pStream->Video.uLastTimeStampMs = uTimeStampMs; 638 639 int xDiff = ((int)pStream->Video.uWidth - (int)uSrcWidth) / 2; 640 uint32_t w = uSrcWidth; 641 if ((int)w + xDiff + (int)x <= 0) /* Nothing visible. */ 642 { 643 rc = VERR_INVALID_PARAMETER; 644 break; 645 } 646 647 uint32_t destX; 648 if ((int)x < -xDiff) 649 { 650 w += xDiff + x; 651 x = -xDiff; 652 destX = 0; 653 } 654 else 655 destX = x + xDiff; 656 657 uint32_t h = uSrcHeight; 658 int yDiff = ((int)pStream->Video.uHeight - (int)uSrcHeight) / 2; 659 if ((int)h + yDiff + (int)y <= 0) /* Nothing visible. */ 660 { 661 rc = VERR_INVALID_PARAMETER; 662 break; 663 } 664 665 uint32_t destY; 666 if ((int)y < -yDiff) 667 { 668 h += yDiff + (int)y; 669 y = -yDiff; 670 destY = 0; 671 } 672 else 673 destY = y + yDiff; 674 675 if ( destX > pStream->Video.uWidth 676 || destY > pStream->Video.uHeight) 677 { 678 rc = VERR_INVALID_PARAMETER; /* Nothing visible. */ 679 break; 680 } 681 682 if (destX + w > pStream->Video.uWidth) 683 w = pStream->Video.uWidth - destX; 684 685 if (destY + h > pStream->Video.uHeight) 686 h = pStream->Video.uHeight - destY; 687 688 pFrame = (PVIDEORECVIDEOFRAME)RTMemAllocZ(sizeof(VIDEORECVIDEOFRAME)); 689 AssertBreakStmt(pFrame, rc = VERR_NO_MEMORY); 690 691 /* Calculate bytes per pixel and set pixel format. */ 692 const unsigned uBytesPerPixel = uBPP / 8; 693 if (uPixelFormat == BitmapFormat_BGR) 694 { 695 switch (uBPP) 696 { 697 case 32: 698 pFrame->uPixelFormat = VIDEORECPIXELFMT_RGB32; 699 break; 700 case 24: 701 pFrame->uPixelFormat = VIDEORECPIXELFMT_RGB24; 702 break; 703 case 16: 704 pFrame->uPixelFormat = VIDEORECPIXELFMT_RGB565; 705 break; 706 default: 707 AssertMsgFailed(("Unknown color depth (%RU32)\n", uBPP)); 708 break; 709 } 710 } 711 else 712 AssertMsgFailed(("Unknown pixel format (%RU32)\n", uPixelFormat)); 713 714 const size_t cbRGBBuf = pStream->Video.uWidth 715 * pStream->Video.uHeight 716 * uBytesPerPixel; 717 AssertBreakStmt(cbRGBBuf, rc = VERR_INVALID_PARAMETER); 718 719 pFrame->pu8RGBBuf = (uint8_t *)RTMemAlloc(cbRGBBuf); 720 AssertBreakStmt(pFrame->pu8RGBBuf, rc = VERR_NO_MEMORY); 721 pFrame->cbRGBBuf = cbRGBBuf; 722 pFrame->uWidth = uSrcWidth; 723 pFrame->uHeight = uSrcHeight; 724 725 /* If the current video frame is smaller than video resolution we're going to encode, 726 * clear the frame beforehand to prevent artifacts. */ 727 if ( uSrcWidth < pStream->Video.uWidth 728 || uSrcHeight < pStream->Video.uHeight) 729 { 730 RT_BZERO(pFrame->pu8RGBBuf, pFrame->cbRGBBuf); 731 } 732 733 /* Calculate start offset in source and destination buffers. */ 734 uint32_t offSrc = y * uBytesPerLine + x * uBytesPerPixel; 735 uint32_t offDst = (destY * pStream->Video.uWidth + destX) * uBytesPerPixel; 736 737 #ifdef VBOX_VIDEOREC_DUMP 738 VIDEORECBMPHDR bmpHdr; 739 RT_ZERO(bmpHdr); 740 741 VIDEORECBMPDIBHDR bmpDIBHdr; 742 RT_ZERO(bmpDIBHdr); 743 744 bmpHdr.u16Magic = 0x4d42; /* Magic */ 745 bmpHdr.u32Size = (uint32_t)(sizeof(VIDEORECBMPHDR) + sizeof(VIDEORECBMPDIBHDR) + (w * h * uBytesPerPixel)); 746 bmpHdr.u32OffBits = (uint32_t)(sizeof(VIDEORECBMPHDR) + sizeof(VIDEORECBMPDIBHDR)); 747 748 bmpDIBHdr.u32Size = sizeof(VIDEORECBMPDIBHDR); 749 bmpDIBHdr.u32Width = w; 750 bmpDIBHdr.u32Height = h; 751 bmpDIBHdr.u16Planes = 1; 752 bmpDIBHdr.u16BitCount = uBPP; 753 bmpDIBHdr.u32XPelsPerMeter = 5000; 754 bmpDIBHdr.u32YPelsPerMeter = 5000; 755 756 char szFileName[RTPATH_MAX]; 757 RTStrPrintf2(szFileName, sizeof(szFileName), "/tmp/VideoRecFrame-%RU32.bmp", uScreen); 758 759 RTFILE fh; 760 int rc2 = RTFileOpen(&fh, szFileName, 761 RTFILE_O_CREATE_REPLACE | RTFILE_O_WRITE | RTFILE_O_DENY_NONE); 762 if (RT_SUCCESS(rc2)) 763 { 764 RTFileWrite(fh, &bmpHdr, sizeof(bmpHdr), NULL); 765 RTFileWrite(fh, &bmpDIBHdr, sizeof(bmpDIBHdr), NULL); 766 } 767 #endif 768 Assert(pFrame->cbRGBBuf >= w * h * uBytesPerPixel); 769 770 /* Do the copy. */ 771 for (unsigned int i = 0; i < h; i++) 772 { 773 /* Overflow check. */ 774 Assert(offSrc + w * uBytesPerPixel <= uSrcHeight * uBytesPerLine); 775 Assert(offDst + w * uBytesPerPixel <= pStream->Video.uHeight * pStream->Video.uWidth * uBytesPerPixel); 776 777 memcpy(pFrame->pu8RGBBuf + offDst, puSrcData + offSrc, w * uBytesPerPixel); 778 779 #ifdef VBOX_VIDEOREC_DUMP 780 if (RT_SUCCESS(rc2)) 781 RTFileWrite(fh, pFrame->pu8RGBBuf + offDst, w * uBytesPerPixel, NULL); 782 #endif 783 offSrc += uBytesPerLine; 784 offDst += pStream->Video.uWidth * uBytesPerPixel; 785 } 786 787 #ifdef VBOX_VIDEOREC_DUMP 788 if (RT_SUCCESS(rc2)) 789 RTFileClose(fh); 790 #endif 791 792 } while (0); 793 794 if (rc == VINF_SUCCESS) /* Note: Also could be VINF_TRY_AGAIN. */ 795 { 796 PVIDEORECBLOCK pBlock = (PVIDEORECBLOCK)RTMemAlloc(sizeof(VIDEORECBLOCK)); 797 if (pBlock) 798 { 799 AssertPtr(pFrame); 800 801 pBlock->enmType = VIDEORECBLOCKTYPE_VIDEO; 802 pBlock->pvData = pFrame; 803 pBlock->cbData = sizeof(VIDEORECVIDEOFRAME) + pFrame->cbRGBBuf; 804 805 try 806 { 807 VideoRecBlocks *pVideoRecBlocks = new VideoRecBlocks(); 808 pVideoRecBlocks->List.push_back(pBlock); 809 810 Assert(pStream->Blocks.Map.find(uTimeStampMs) == pStream->Blocks.Map.end()); 811 pStream->Blocks.Map.insert(std::make_pair(uTimeStampMs, pVideoRecBlocks)); 812 } 813 catch (const std::exception &ex) 814 { 815 RT_NOREF(ex); 816 817 RTMemFree(pBlock); 818 rc = VERR_NO_MEMORY; 819 } 820 } 821 else 822 rc = VERR_NO_MEMORY; 823 } 824 825 if (RT_FAILURE(rc)) 826 VideoRecVideoFrameFree(pFrame); 827 828 VideoRecStreamUnlock(pStream); 829 830 int rc2 = RTCritSectLeave(&pCtx->CritSect); 556 rc = pStream->SendVideoFrame(x, y, uPixelFormat, uBPP, uBytesPerLine, uSrcWidth, uSrcHeight, puSrcData, uTimeStampMs); 557 558 int rc2 = RTCritSectLeave(&this->CritSect); 831 559 AssertRC(rc2); 832 560 … … 834 562 && rc != VINF_TRY_AGAIN) /* Only signal the thread if operation was successful. */ 835 563 { 836 videoRecThreadNotify(pCtx);564 threadNotify(); 837 565 } 838 566 -
trunk/src/VBox/Main/src-client/VideoRecStream.cpp
r75069 r75251 42 42 43 43 44 /** 45 * Locks a recording stream. 46 * 47 * @param pStream Recording stream to lock. 48 */ 49 void VideoRecStreamLock(PVIDEORECSTREAM pStream) 50 { 51 int rc = RTCritSectEnter(&pStream->CritSect); 52 AssertRC(rc); 53 } 54 55 /** 56 * Unlocks a locked recording stream. 57 * 58 * @param pStream Recording stream to unlock. 59 */ 60 void VideoRecStreamUnlock(PVIDEORECSTREAM pStream) 61 { 62 int rc = RTCritSectLeave(&pStream->CritSect); 63 AssertRC(rc); 44 CaptureStream::CaptureStream(void) 45 : tsStartMs(0) 46 { 47 } 48 49 CaptureStream::CaptureStream(uint32_t a_uScreen, const settings::CaptureScreenSettings &a_Settings) 50 : tsStartMs(0) 51 { 52 int rc2 = initInternal(a_uScreen, a_Settings); 53 if (RT_FAILURE(rc2)) 54 throw rc2; 55 } 56 57 CaptureStream::~CaptureStream(void) 58 { 59 int rc2 = uninitInternal(); 60 AssertRC(rc2); 64 61 } 65 62 … … 68 65 * 69 66 * @returns IPRT status code. 70 * @param pStream Recording stream to open. 71 * @param pCfg Recording configuration to use. 72 */ 73 int VideoRecStreamOpen(PVIDEORECSTREAM pStream, PVIDEORECCFG pCfg) 74 { 75 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 76 AssertPtrReturn(pCfg, VERR_INVALID_POINTER); 77 78 Assert(pStream->enmDst == VIDEORECDEST_INVALID); 67 */ 68 int CaptureStream::open(void) 69 { 70 Assert(Settings.enmDest == CaptureDestination_None); 79 71 80 72 int rc; 81 73 82 switch ( pCfg->enmDst)83 { 84 case VIDEORECDEST_FILE:85 { 86 Assert( pCfg->File.strName.isNotEmpty());87 88 char *pszAbsPath = RTPathAbsDup( com::Utf8Str(pCfg->File.strName).c_str());74 switch (Settings.enmDest) 75 { 76 case CaptureDestination_File: 77 { 78 Assert(Settings.File.strName.isNotEmpty()); 79 80 char *pszAbsPath = RTPathAbsDup(Settings.File.strName.c_str()); 89 81 AssertPtrReturn(pszAbsPath, VERR_NO_MEMORY); 90 82 … … 101 93 char *pszFile = NULL; 102 94 103 if ( pCfg->aScreens.size() > 1)104 rc = RTStrAPrintf(&pszFile, "%s-%u%s", pszAbsPath, pStream->uScreenID + 1, pszSuff);95 if (this->uScreenID > 0) 96 rc = RTStrAPrintf(&pszFile, "%s-%u%s", pszAbsPath, this->uScreenID + 1, pszSuff); 105 97 else 106 98 rc = RTStrAPrintf(&pszFile, "%s%s", pszAbsPath, pszSuff); … … 127 119 RTTimeExplode(&time, &ts); 128 120 129 if ( pCfg->aScreens.size() > 1)121 if (this->uScreenID > 0) 130 122 rc = RTStrAPrintf(&pszFile, "%s-%04d-%02u-%02uT%02u-%02u-%02u-%09uZ-%u%s", 131 123 pszAbsPath, time.i32Year, time.u8Month, time.u8MonthDay, 132 124 time.u8Hour, time.u8Minute, time.u8Second, time.u32Nanosecond, 133 pStream->uScreenID + 1, pszSuff);125 this->uScreenID + 1, pszSuff); 134 126 else 135 127 rc = RTStrAPrintf(&pszFile, "%s-%04d-%02u-%02uT%02u-%02u-%02u-%09uZ%s", … … 144 136 if (RT_SUCCESS(rc)) 145 137 { 146 pStream->enmDst = VIDEORECDEST_FILE; 147 pStream->File.hFile = hFile; 148 pStream->File.pszFile = pszFile; /* Assign allocated string to our stream's config. */ 138 this->File.hFile = hFile; 139 this->File.strName = pszFile; 149 140 } 150 141 } … … 156 147 { 157 148 LogRel(("VideoRec: Failed to open file '%s' for screen %RU32, rc=%Rrc\n", 158 pszFile ? pszFile : "<Unnamed>", pStream->uScreenID, rc));159 RTStrFree(pszFile);160 } 161 149 pszFile ? pszFile : "<Unnamed>", this->uScreenID, rc)); 150 } 151 152 RTStrFree(pszFile); 162 153 break; 163 154 } … … 170 161 LogFlowFuncLeaveRC(rc); 171 162 return rc; 163 } 164 165 int CaptureStream::parseOptionsString(const com::Utf8Str &strOptions) 166 { 167 size_t pos = 0; 168 com::Utf8Str key, value; 169 while ((pos = strOptions.parseKeyValue(key, value, pos)) != com::Utf8Str::npos) 170 { 171 if (key.compare("vc_quality", Utf8Str::CaseInsensitive) == 0) 172 { 173 #ifdef VBOX_WITH_LIBVPX 174 Assert(this->Settings.Video.ulFPS); 175 if (value.compare("realtime", Utf8Str::CaseInsensitive) == 0) 176 this->Video.Codec.VPX.uEncoderDeadline = VPX_DL_REALTIME; 177 else if (value.compare("good", Utf8Str::CaseInsensitive) == 0) 178 this->Video.Codec.VPX.uEncoderDeadline = 1000000 / this->Settings.Video.ulFPS; 179 else if (value.compare("best", Utf8Str::CaseInsensitive) == 0) 180 this->Video.Codec.VPX.uEncoderDeadline = VPX_DL_BEST_QUALITY; 181 else 182 { 183 LogRel(("VideoRec: Setting encoder deadline to '%s'\n", value.c_str())); 184 this->Video.Codec.VPX.uEncoderDeadline = value.toUInt32(); 185 #endif 186 } 187 } 188 else if (key.compare("vc_enabled", Utf8Str::CaseInsensitive) == 0) 189 { 190 if (value.compare("false", Utf8Str::CaseInsensitive) == 0) 191 { 192 this->Settings.featureMap[CaptureFeature_Video] = false; 193 #ifdef VBOX_WITH_AUDIO_VIDEOREC 194 LogRel(("VideoRec: Only audio will be recorded\n")); 195 #endif 196 } 197 } 198 else if (key.compare("ac_enabled", Utf8Str::CaseInsensitive) == 0) 199 { 200 #ifdef VBOX_WITH_AUDIO_VIDEOREC 201 if (value.compare("true", Utf8Str::CaseInsensitive) == 0) 202 { 203 this->Settings.featureMap[CaptureFeature_Audio] = true; 204 } 205 else 206 LogRel(("VideoRec: Only video will be recorded\n")); 207 #endif 208 } 209 else if (key.compare("ac_profile", Utf8Str::CaseInsensitive) == 0) 210 { 211 #ifdef VBOX_WITH_AUDIO_VIDEOREC 212 if (value.compare("low", Utf8Str::CaseInsensitive) == 0) 213 { 214 this->Settings.Audio.uHz = 8000; 215 this->Settings.Audio.cBits = 16; 216 this->Settings.Audio.cChannels = 1; 217 } 218 else if (value.startsWith("med" /* "med[ium]" */, Utf8Str::CaseInsensitive) == 0) 219 { 220 /* Stay with the default set above. */ 221 } 222 else if (value.compare("high", Utf8Str::CaseInsensitive) == 0) 223 { 224 this->Settings.Audio.uHz = 48000; 225 this->Settings.Audio.cBits = 16; 226 this->Settings.Audio.cChannels = 2; 227 } 228 #endif 229 } 230 else 231 LogRel(("VideoRec: Unknown option '%s' (value '%s'), skipping\n", key.c_str(), value.c_str())); 232 233 } /* while */ 234 235 return VINF_SUCCESS; 236 } 237 238 const settings::CaptureScreenSettings &CaptureStream::GetConfig(void) const 239 { 240 return this->Settings; 241 } 242 243 /** 244 * Checks if a specified limit for recording has been reached. 245 * 246 * @returns true if any limit has been reached. 247 * @param tsNowMs Current time stamp (in ms). 248 */ 249 bool CaptureStream::IsLimitReached(uint64_t tsNowMs) const 250 { 251 if (!IsReady()) 252 return true; 253 254 if ( Settings.ulMaxTimeS 255 && tsNowMs >= this->tsStartMs + (Settings.ulMaxTimeS * RT_MS_1SEC)) 256 { 257 return true; 258 } 259 260 if (Settings.enmDest == CaptureDestination_File) 261 { 262 263 if (Settings.File.ulMaxSizeMB) 264 { 265 uint64_t sizeInMB = this->File.pWEBM->GetFileSize() / _1M; 266 if(sizeInMB >= Settings.File.ulMaxSizeMB) 267 return true; 268 } 269 270 /* Check for available free disk space */ 271 if ( this->File.pWEBM 272 && this->File.pWEBM->GetAvailableSpace() < 0x100000) /** @todo r=andy WTF? Fix this. */ 273 { 274 LogRel(("VideoRec: Not enough free storage space available, stopping video capture\n")); 275 return true; 276 } 277 } 278 279 return false; 280 } 281 282 bool CaptureStream::IsReady(void) const 283 { 284 return this->fEnabled; 172 285 } 173 286 … … 178 291 * 179 292 * @returns IPRT status code. 180 * @param pStream Recording stream to process. 181 */ 182 int VideoRecStreamProcess(PVIDEORECSTREAM pStream) 183 { 184 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 185 186 VideoRecStreamLock(pStream); 187 188 if (!pStream->fEnabled) 189 { 190 VideoRecStreamUnlock(pStream); 293 * @param mapBlocksCommon Map of common block to process for this stream. 294 */ 295 int CaptureStream::Process(VideoRecBlockMap &mapBlocksCommon) 296 { 297 lock(); 298 299 if (!Settings.fEnabled) 300 { 301 unlock(); 191 302 return VINF_SUCCESS; 192 303 } … … 194 305 int rc = VINF_SUCCESS; 195 306 196 const PVIDEORECCONTEXT pCtx = pStream->pCtx; 197 AssertPtr(pCtx); 198 199 VideoRecBlockMap::iterator itStreamBlocks = pStream->Blocks.Map.begin(); 200 while (itStreamBlocks != pStream->Blocks.Map.end()) 307 VideoRecBlockMap::iterator itStreamBlocks = Blocks.Map.begin(); 308 while (itStreamBlocks != Blocks.Map.end()) 201 309 { 202 310 const uint64_t uTimeStampMs = itStreamBlocks->first; 203 VideoRecBlocks *pBlocks= itStreamBlocks->second;311 CaptureBlocks *pBlocks = itStreamBlocks->second; 204 312 205 313 AssertPtr(pBlocks); … … 217 325 rc = videoRecRGBToYUV(pVideoFrame->uPixelFormat, 218 326 /* Destination */ 219 pStream->Video.Codec.VPX.pu8YuvBuf, pVideoFrame->uWidth, pVideoFrame->uHeight,327 this->Video.Codec.VPX.pu8YuvBuf, pVideoFrame->uWidth, pVideoFrame->uHeight, 220 328 /* Source */ 221 pVideoFrame->pu8RGBBuf, pStream->Video.uWidth, pStream->Video.uHeight);329 pVideoFrame->pu8RGBBuf, this->Settings.Video.ulWidth, this->Settings.Video.ulHeight); 222 330 if (RT_SUCCESS(rc)) 223 331 { 224 rc = VideoRecStreamWriteVideoVPX(pStream,uTimeStampMs, pVideoFrame);332 rc = writeVideoVPX(uTimeStampMs, pVideoFrame); 225 333 } 226 334 else … … 238 346 239 347 #ifdef VBOX_WITH_AUDIO_VIDEOREC 348 AssertPtr(pCtx); 349 240 350 /* As each (enabled) screen has to get the same audio data, look for common (audio) data which needs to be 241 351 * written to the screen's assigned recording stream. */ 242 VideoRecBlockMap::iterator itCommonBlocks = pCtx->mapBlocksCommon.begin();243 while (itCommonBlocks != pCtx->mapBlocksCommon.end())352 VideoRecBlockMap::iterator itCommonBlocks = mapBlocksCommon.begin(); 353 while (itCommonBlocks != mapBlocksCommon.end()) 244 354 { 245 355 VideoRecBlockList::iterator itBlock = itCommonBlocks->second->List.begin(); … … 258 368 WebMWriter::BlockData_Opus blockData = { pAudioFrame->pvBuf, pAudioFrame->cbBuf, 259 369 pBlockCommon->uTimeStampMs }; 260 AssertPtr( pStream->File.pWEBM);261 rc = pStream->File.pWEBM->WriteBlock(pStream->uTrackAudio, &blockData, sizeof(blockData));370 AssertPtr(this->File.pWEBM); 371 rc = this->File.pWEBM->WriteBlock(this->uTrackAudio, &blockData, sizeof(blockData)); 262 372 break; 263 373 } … … 287 397 { 288 398 delete itCommonBlocks->second; 289 pCtx->mapBlocksCommon.erase(itCommonBlocks);290 itCommonBlocks = pCtx->mapBlocksCommon.begin();399 mapBlocksCommon.erase(itCommonBlocks); 400 itCommonBlocks = mapBlocksCommon.begin(); 291 401 } 292 402 else 293 403 ++itCommonBlocks; 294 404 295 LogFunc(("Common blocks: %zu\n", pCtx->mapBlocksCommon.size()));405 LogFunc(("Common blocks: %zu\n", mapBlocksCommon.size())); 296 406 297 407 if (RT_FAILURE(rc)) … … 300 410 #endif 301 411 302 VideoRecStreamUnlock(pStream);412 unlock(); 303 413 304 414 return rc; 305 415 } 306 416 417 int CaptureStream::SendVideoFrame(uint32_t x, uint32_t y, uint32_t uPixelFormat, uint32_t uBPP, uint32_t uBytesPerLine, 418 uint32_t uSrcWidth, uint32_t uSrcHeight, uint8_t *puSrcData, uint64_t uTimeStampMs) 419 { 420 lock(); 421 422 PVIDEORECVIDEOFRAME pFrame = NULL; 423 424 int rc = VINF_SUCCESS; 425 426 do 427 { 428 if (!this->fEnabled) 429 { 430 rc = VINF_TRY_AGAIN; /* Not (yet) enabled. */ 431 break; 432 } 433 434 if (uTimeStampMs < this->Video.uLastTimeStampMs + this->Video.uDelayMs) 435 { 436 rc = VINF_TRY_AGAIN; /* Respect maximum frames per second. */ 437 break; 438 } 439 440 this->Video.uLastTimeStampMs = uTimeStampMs; 441 442 int xDiff = ((int)this->Settings.Video.ulWidth - (int)uSrcWidth) / 2; 443 uint32_t w = uSrcWidth; 444 if ((int)w + xDiff + (int)x <= 0) /* Nothing visible. */ 445 { 446 rc = VERR_INVALID_PARAMETER; 447 break; 448 } 449 450 uint32_t destX; 451 if ((int)x < -xDiff) 452 { 453 w += xDiff + x; 454 x = -xDiff; 455 destX = 0; 456 } 457 else 458 destX = x + xDiff; 459 460 uint32_t h = uSrcHeight; 461 int yDiff = ((int)this->Settings.Video.ulHeight - (int)uSrcHeight) / 2; 462 if ((int)h + yDiff + (int)y <= 0) /* Nothing visible. */ 463 { 464 rc = VERR_INVALID_PARAMETER; 465 break; 466 } 467 468 uint32_t destY; 469 if ((int)y < -yDiff) 470 { 471 h += yDiff + (int)y; 472 y = -yDiff; 473 destY = 0; 474 } 475 else 476 destY = y + yDiff; 477 478 if ( destX > this->Settings.Video.ulWidth 479 || destY > this->Settings.Video.ulHeight) 480 { 481 rc = VERR_INVALID_PARAMETER; /* Nothing visible. */ 482 break; 483 } 484 485 if (destX + w > this->Settings.Video.ulWidth) 486 w = this->Settings.Video.ulWidth - destX; 487 488 if (destY + h > this->Settings.Video.ulHeight) 489 h = this->Settings.Video.ulHeight - destY; 490 491 pFrame = (PVIDEORECVIDEOFRAME)RTMemAllocZ(sizeof(VIDEORECVIDEOFRAME)); 492 AssertBreakStmt(pFrame, rc = VERR_NO_MEMORY); 493 494 /* Calculate bytes per pixel and set pixel format. */ 495 const unsigned uBytesPerPixel = uBPP / 8; 496 if (uPixelFormat == BitmapFormat_BGR) 497 { 498 switch (uBPP) 499 { 500 case 32: 501 pFrame->uPixelFormat = VIDEORECPIXELFMT_RGB32; 502 break; 503 case 24: 504 pFrame->uPixelFormat = VIDEORECPIXELFMT_RGB24; 505 break; 506 case 16: 507 pFrame->uPixelFormat = VIDEORECPIXELFMT_RGB565; 508 break; 509 default: 510 AssertMsgFailedBreakStmt(("Unknown color depth (%RU32)\n", uBPP), rc = VERR_NOT_SUPPORTED); 511 break; 512 } 513 } 514 else 515 AssertMsgFailedBreakStmt(("Unknown pixel format (%RU32)\n", uPixelFormat), rc = VERR_NOT_SUPPORTED); 516 517 const size_t cbRGBBuf = this->Settings.Video.ulWidth 518 * this->Settings.Video.ulHeight 519 * uBytesPerPixel; 520 AssertBreakStmt(cbRGBBuf, rc = VERR_INVALID_PARAMETER); 521 522 pFrame->pu8RGBBuf = (uint8_t *)RTMemAlloc(cbRGBBuf); 523 AssertBreakStmt(pFrame->pu8RGBBuf, rc = VERR_NO_MEMORY); 524 pFrame->cbRGBBuf = cbRGBBuf; 525 pFrame->uWidth = uSrcWidth; 526 pFrame->uHeight = uSrcHeight; 527 528 /* If the current video frame is smaller than video resolution we're going to encode, 529 * clear the frame beforehand to prevent artifacts. */ 530 if ( uSrcWidth < this->Settings.Video.ulWidth 531 || uSrcHeight < this->Settings.Video.ulHeight) 532 { 533 RT_BZERO(pFrame->pu8RGBBuf, pFrame->cbRGBBuf); 534 } 535 536 /* Calculate start offset in source and destination buffers. */ 537 uint32_t offSrc = y * uBytesPerLine + x * uBytesPerPixel; 538 uint32_t offDst = (destY * this->Settings.Video.ulWidth + destX) * uBytesPerPixel; 539 540 #ifdef VBOX_VIDEOREC_DUMP 541 VIDEORECBMPHDR bmpHdr; 542 RT_ZERO(bmpHdr); 543 544 VIDEORECBMPDIBHDR bmpDIBHdr; 545 RT_ZERO(bmpDIBHdr); 546 547 bmpHdr.u16Magic = 0x4d42; /* Magic */ 548 bmpHdr.u32Size = (uint32_t)(sizeof(VIDEORECBMPHDR) + sizeof(VIDEORECBMPDIBHDR) + (w * h * uBytesPerPixel)); 549 bmpHdr.u32OffBits = (uint32_t)(sizeof(VIDEORECBMPHDR) + sizeof(VIDEORECBMPDIBHDR)); 550 551 bmpDIBHdr.u32Size = sizeof(VIDEORECBMPDIBHDR); 552 bmpDIBHdr.u32Width = w; 553 bmpDIBHdr.u32Height = h; 554 bmpDIBHdr.u16Planes = 1; 555 bmpDIBHdr.u16BitCount = uBPP; 556 bmpDIBHdr.u32XPelsPerMeter = 5000; 557 bmpDIBHdr.u32YPelsPerMeter = 5000; 558 559 char szFileName[RTPATH_MAX]; 560 RTStrPrintf2(szFileName, sizeof(szFileName), "/tmp/VideoRecFrame-%RU32.bmp", this->uScreenID); 561 562 RTFILE fh; 563 int rc2 = RTFileOpen(&fh, szFileName, 564 RTFILE_O_CREATE_REPLACE | RTFILE_O_WRITE | RTFILE_O_DENY_NONE); 565 if (RT_SUCCESS(rc2)) 566 { 567 RTFileWrite(fh, &bmpHdr, sizeof(bmpHdr), NULL); 568 RTFileWrite(fh, &bmpDIBHdr, sizeof(bmpDIBHdr), NULL); 569 } 570 #endif 571 Assert(pFrame->cbRGBBuf >= w * h * uBytesPerPixel); 572 573 /* Do the copy. */ 574 for (unsigned int i = 0; i < h; i++) 575 { 576 /* Overflow check. */ 577 Assert(offSrc + w * uBytesPerPixel <= uSrcHeight * uBytesPerLine); 578 Assert(offDst + w * uBytesPerPixel <= this->Settings.Video.ulHeight * this->Settings.Video.ulWidth * uBytesPerPixel); 579 580 memcpy(pFrame->pu8RGBBuf + offDst, puSrcData + offSrc, w * uBytesPerPixel); 581 582 #ifdef VBOX_VIDEOREC_DUMP 583 if (RT_SUCCESS(rc2)) 584 RTFileWrite(fh, pFrame->pu8RGBBuf + offDst, w * uBytesPerPixel, NULL); 585 #endif 586 offSrc += uBytesPerLine; 587 offDst += this->Settings.Video.ulWidth * uBytesPerPixel; 588 } 589 590 #ifdef VBOX_VIDEOREC_DUMP 591 if (RT_SUCCESS(rc2)) 592 RTFileClose(fh); 593 #endif 594 595 } while (0); 596 597 if (rc == VINF_SUCCESS) /* Note: Also could be VINF_TRY_AGAIN. */ 598 { 599 PVIDEORECBLOCK pBlock = (PVIDEORECBLOCK)RTMemAlloc(sizeof(VIDEORECBLOCK)); 600 if (pBlock) 601 { 602 AssertPtr(pFrame); 603 604 pBlock->enmType = VIDEORECBLOCKTYPE_VIDEO; 605 pBlock->pvData = pFrame; 606 pBlock->cbData = sizeof(VIDEORECVIDEOFRAME) + pFrame->cbRGBBuf; 607 608 try 609 { 610 CaptureBlocks *pVideoRecBlocks = new CaptureBlocks(); 611 pVideoRecBlocks->List.push_back(pBlock); 612 613 Assert(this->Blocks.Map.find(uTimeStampMs) == this->Blocks.Map.end()); 614 this->Blocks.Map.insert(std::make_pair(uTimeStampMs, pVideoRecBlocks)); 615 } 616 catch (const std::exception &ex) 617 { 618 RT_NOREF(ex); 619 620 RTMemFree(pBlock); 621 rc = VERR_NO_MEMORY; 622 } 623 } 624 else 625 rc = VERR_NO_MEMORY; 626 } 627 628 if (RT_FAILURE(rc)) 629 VideoRecVideoFrameFree(pFrame); 630 631 lock(); 632 633 return rc; 634 } 635 636 int CaptureStream::Init(uint32_t a_uScreen, const settings::CaptureScreenSettings &a_Settings) 637 { 638 return initInternal(a_uScreen, a_Settings); 639 } 640 307 641 /** 308 642 * Initializes a recording stream. 309 643 * 310 644 * @returns IPRT status code. 311 * @param pStream Recording stream to initialize. 312 * @param pCtx Recording context to use for initialization. 313 * @param uScreen Screen number to record. 314 */ 315 int VideoRecStreamInit(PVIDEORECSTREAM pStream, PVIDEORECCONTEXT pCtx, uint32_t uScreen) 316 { 317 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 318 AssertPtrReturn(pCtx, VERR_INVALID_POINTER); 319 320 PVIDEORECCFG pCfg = &pCtx->Cfg; 321 322 #ifdef VBOX_WITH_AUDIO_VIDEOREC 323 if (pCfg->Audio.fEnabled) 324 { 325 /* Sanity. */ 326 AssertReturn(pCfg->Audio.uHz, VERR_INVALID_PARAMETER); 327 AssertReturn(pCfg->Audio.cBits, VERR_INVALID_PARAMETER); 328 AssertReturn(pCfg->Audio.cChannels, VERR_INVALID_PARAMETER); 329 } 330 #endif 331 332 int rc = VideoRecStreamOpen(pStream, pCfg); 645 * @param uScreen Screen number to use for this recording stream. 646 * @param Cfg Recording screen configuration to use for initialization. 647 */ 648 int CaptureStream::initInternal(uint32_t a_uScreen, const settings::CaptureScreenSettings &a_Settings) 649 { 650 int rc = parseOptionsString(a_Settings.strOptions); 333 651 if (RT_FAILURE(rc)) 334 652 return rc; 335 653 336 if (pCfg->Video.fEnabled) 337 rc = VideoRecStreamInitVideo(pStream, pCfg); 338 339 switch (pStream->enmDst) 340 { 341 case VIDEORECDEST_FILE: 342 { 343 rc = pStream->File.pWEBM->OpenEx(pStream->File.pszFile, &pStream->File.hFile, 654 rc = RTCritSectInit(&this->CritSect); 655 if (RT_FAILURE(rc)) 656 return rc; 657 658 rc = open(); 659 if (RT_FAILURE(rc)) 660 return rc; 661 662 const bool fVideoEnabled = a_Settings.isFeatureEnabled(CaptureFeature_Video); 663 const bool fAudioEnabled = a_Settings.isFeatureEnabled(CaptureFeature_Audio); 664 665 if (fVideoEnabled) 666 rc = initVideo(); 667 668 if (fAudioEnabled) 669 rc = initAudio(); 670 671 switch (this->Settings.enmDest) 672 { 673 case CaptureDestination_File: 674 { 675 const char *pszFile = this->Settings.File.strName.c_str(); 676 677 rc = File.pWEBM->OpenEx(pszFile, &this->File.hFile, 344 678 #ifdef VBOX_WITH_AUDIO_VIDEOREC 345 pCfg->Audio.fEnabled ? WebMWriter::AudioCodec_Opus : WebMWriter::AudioCodec_None, 679 a_Settings.isFeatureEnabled(CaptureFeature_Audio) 680 ? WebMWriter::AudioCodec_Opus : WebMWriter::AudioCodec_None, 346 681 #else 347 WebMWriter::AudioCodec_None, 348 #endif 349 pCfg->Video.fEnabled ? WebMWriter::VideoCodec_VP8 : WebMWriter::VideoCodec_None); 682 WebMWriter::AudioCodec_None, 683 #endif 684 a_Settings.isFeatureEnabled(CaptureFeature_Video) 685 ? WebMWriter::VideoCodec_VP8 : WebMWriter::VideoCodec_None); 350 686 if (RT_FAILURE(rc)) 351 687 { 352 LogRel(("VideoRec: Failed to create the capture output file '%s' (%Rrc)\n", p Stream->File.pszFile, rc));688 LogRel(("VideoRec: Failed to create the capture output file '%s' (%Rrc)\n", pszFile, rc)); 353 689 break; 354 690 } 355 691 356 const char *pszFile = pStream->File.pszFile; 357 358 if (pCfg->Video.fEnabled) 359 { 360 rc = pStream->File.pWEBM->AddVideoTrack(pCfg->Video.uWidth, pCfg->Video.uHeight, pCfg->Video.uFPS, 361 &pStream->uTrackVideo); 692 if (fVideoEnabled) 693 { 694 rc = this->File.pWEBM->AddVideoTrack(a_Settings.Video.ulWidth, a_Settings.Video.ulHeight, 695 a_Settings.Video.ulFPS, &this->uTrackVideo); 362 696 if (RT_FAILURE(rc)) 363 697 { … … 367 701 368 702 LogRel(("VideoRec: Recording video of screen #%u with %RU32x%RU32 @ %RU32 kbps, %RU32 FPS (track #%RU8)\n", 369 uScreen, pCfg->Video.uWidth, pCfg->Video.uHeight, pCfg->Video.uRate, pCfg->Video.uFPS,370 pStream->uTrackVideo));703 this->uScreenID, a_Settings.Video.ulWidth, a_Settings.Video.ulHeight, a_Settings.Video.ulRate, 704 a_Settings.Video.ulFPS, this->uTrackVideo)); 371 705 } 372 706 373 707 #ifdef VBOX_WITH_AUDIO_VIDEOREC 374 if ( pCfg->Audio.fEnabled)375 { 376 rc = pStream->File.pWEBM->AddAudioTrack(pCfg->Audio.uHz, pCfg->Audio.cChannels, pCfg->Audio.cBits,377 &pStream->uTrackAudio);708 if (fAudioEnabled) 709 { 710 rc = this->File.pWEBM->AddAudioTrack(a_Settings.Audio.uHz, a_Settings.Audio.cChannels, a_Settings.Audio.cBits, 711 &this->uTrackAudio); 378 712 if (RT_FAILURE(rc)) 379 713 { … … 383 717 384 718 LogRel(("VideoRec: Recording audio in %RU16Hz, %RU8 bit, %RU8 %s (track #%RU8)\n", 385 pCfg->Audio.uHz, pCfg->Audio.cBits, pCfg->Audio.cChannels, pCfg->Audio.cChannels ? "channels" : "channel",386 pStream->uTrackAudio));387 } 388 #endif 389 390 if ( pCfg->Video.fEnabled719 a_Settings.Audio.uHz, a_Settings.Audio.cBits, a_Settings.Audio.cChannels, 720 a_Settings.Audio.cChannels ? "channels" : "channel", this->uTrackAudio)); 721 } 722 #endif 723 724 if ( fVideoEnabled 391 725 #ifdef VBOX_WITH_AUDIO_VIDEOREC 392 || pCfg->Audio.fEnabled726 || fAudioEnabled 393 727 #endif 394 728 ) 395 729 { 396 730 char szWhat[32] = { 0 }; 397 if ( pCfg->Video.fEnabled)731 if (fVideoEnabled) 398 732 RTStrCat(szWhat, sizeof(szWhat), "video"); 399 733 #ifdef VBOX_WITH_AUDIO_VIDEOREC 400 if ( pCfg->Audio.fEnabled)734 if (fAudioEnabled) 401 735 { 402 if ( pCfg->Video.fEnabled)736 if (fVideoEnabled) 403 737 RTStrCat(szWhat, sizeof(szWhat), " + "); 404 738 RTStrCat(szWhat, sizeof(szWhat), "audio"); … … 419 753 if (RT_SUCCESS(rc)) 420 754 { 421 pStream->pCtx = pCtx; 422 pStream->fEnabled = true; 755 this->pCtx = pCtx; 756 this->fEnabled = true; 757 this->uScreenID = a_uScreen; 758 this->tsStartMs = RTTimeMilliTS(); 759 this->Settings = a_Settings; 423 760 } 424 761 else 425 762 { 426 int rc2 = VideoRecStreamClose(pStream);763 int rc2 = uninitInternal(); 427 764 AssertRC(rc2); 428 765 return rc; … … 438 775 * 439 776 * @returns IPRT status code. 440 * @param pStream Recording stream to close. 441 * 442 */ 443 int VideoRecStreamClose(PVIDEORECSTREAM pStream) 777 */ 778 int CaptureStream::close(void) 444 779 { 445 780 int rc = VINF_SUCCESS; 446 781 447 if ( pStream->fEnabled)448 { 449 switch ( pStream->enmDst)450 { 451 case VIDEORECDEST_FILE:452 { 453 if ( pStream->File.pWEBM)454 rc = pStream->File.pWEBM->Close();782 if (this->fEnabled) 783 { 784 switch (this->Settings.enmDest) 785 { 786 case CaptureDestination_File: 787 { 788 if (this->File.pWEBM) 789 rc = this->File.pWEBM->Close(); 455 790 break; 456 791 } … … 461 796 } 462 797 463 pStream->Blocks.Clear();464 465 LogRel(("VideoRec: Recording screen #%u stopped\n", pStream->uScreenID));798 this->Blocks.Clear(); 799 800 LogRel(("VideoRec: Recording screen #%u stopped\n", this->uScreenID)); 466 801 } 467 802 468 803 if (RT_FAILURE(rc)) 469 804 { 470 LogRel(("VideoRec: Error stopping recording screen #%u, rc=%Rrc\n", pStream->uScreenID, rc));805 LogRel(("VideoRec: Error stopping recording screen #%u, rc=%Rrc\n", this->uScreenID, rc)); 471 806 return rc; 472 807 } 473 808 474 switch (pStream->enmDst) 475 { 476 case VIDEORECDEST_FILE: 477 { 478 AssertPtr(pStream->File.pszFile); 479 if (RTFileIsValid(pStream->File.hFile)) 480 { 481 rc = RTFileClose(pStream->File.hFile); 809 switch (this->Settings.enmDest) 810 { 811 case CaptureDestination_File: 812 { 813 if (RTFileIsValid(this->File.hFile)) 814 { 815 rc = RTFileClose(this->File.hFile); 482 816 if (RT_SUCCESS(rc)) 483 817 { 484 LogRel(("VideoRec: Closed file '%s'\n", pStream->File.pszFile));818 LogRel(("VideoRec: Closed file '%s'\n", this->Settings.File.strName.c_str())); 485 819 } 486 820 else 487 821 { 488 LogRel(("VideoRec: Error closing file '%s', rc=%Rrc\n", pStream->File.pszFile, rc));822 LogRel(("VideoRec: Error closing file '%s', rc=%Rrc\n", this->Settings.File.strName.c_str(), rc)); 489 823 break; 490 824 } 491 825 } 492 826 493 RTStrFree(pStream->File.pszFile); 494 pStream->File.pszFile = NULL; 495 496 if (pStream->File.pWEBM) 497 { 498 delete pStream->File.pWEBM; 499 pStream->File.pWEBM = NULL; 827 if (this->File.pWEBM) 828 { 829 delete this->File.pWEBM; 830 this->File.pWEBM = NULL; 500 831 } 501 832 break; … … 507 838 } 508 839 509 if (RT_SUCCESS(rc))510 {511 pStream->enmDst = VIDEORECDEST_INVALID;512 }513 514 840 LogFlowFuncLeaveRC(rc); 515 841 return rc; … … 520 846 * 521 847 * @returns IPRT status code. 522 * @param pStream Recording stream to uninitialize. 523 */ 524 int VideoRecStreamUninit(PVIDEORECSTREAM pStream) 525 { 526 int rc = VINF_SUCCESS; 527 528 if (pStream->pCtx->Cfg.Video.fEnabled) 529 { 530 int rc2 = VideoRecStreamUnitVideo(pStream); 848 */ 849 int CaptureStream::Uninit(void) 850 { 851 return uninitInternal(); 852 } 853 854 int CaptureStream::uninitInternal(void) 855 { 856 int rc = close(); 857 if (RT_FAILURE(rc)) 858 return rc; 859 860 if (this->Settings.isFeatureEnabled(CaptureFeature_Video)) 861 { 862 int rc2 = unitVideo(); 531 863 if (RT_SUCCESS(rc)) 532 864 rc = rc2; 533 865 } 534 866 867 RTCritSectDelete(&this->CritSect); 868 869 this->fEnabled = false; 870 535 871 return rc; 536 872 } … … 540 876 * 541 877 * @returns IPRT status code. 542 * @param pStream Recording stream to uninitialize video recording for. 543 */ 544 int VideoRecStreamUnitVideo(PVIDEORECSTREAM pStream) 878 */ 879 int CaptureStream::unitVideo(void) 545 880 { 546 881 #ifdef VBOX_WITH_LIBVPX 547 882 /* At the moment we only have VPX. */ 548 return VideoRecStreamUninitVideoVPX(pStream);883 return uninitVideoVPX(); 549 884 #else 550 885 return VERR_NOT_SUPPORTED; … … 557 892 * 558 893 * @returns IPRT status code. 559 * @param pStream Recording stream to uninitialize VPX codec for. 560 */ 561 int VideoRecStreamUninitVideoVPX(PVIDEORECSTREAM pStream) 562 { 563 vpx_img_free(&pStream->Video.Codec.VPX.RawImage); 564 vpx_codec_err_t rcv = vpx_codec_destroy(&pStream->Video.Codec.VPX.Ctx); 894 */ 895 int CaptureStream::uninitVideoVPX(void) 896 { 897 vpx_img_free(&this->Video.Codec.VPX.RawImage); 898 vpx_codec_err_t rcv = vpx_codec_destroy(&this->Video.Codec.VPX.Ctx); 565 899 Assert(rcv == VPX_CODEC_OK); RT_NOREF(rcv); 566 900 … … 573 907 * 574 908 * @returns IPRT status code. 575 * @param pStream Recording stream to initialize video recording for. 576 * @param pCfg Video recording configuration to use for initialization. 577 */ 578 int VideoRecStreamInitVideo(PVIDEORECSTREAM pStream, PVIDEORECCFG pCfg) 579 { 909 */ 910 int CaptureStream::initVideo(void) 911 { 912 /* Sanity. */ 913 AssertReturn(this->Settings.Video.ulRate, VERR_INVALID_PARAMETER); 914 AssertReturn(this->Settings.Video.ulWidth, VERR_INVALID_PARAMETER); 915 AssertReturn(this->Settings.Video.ulHeight, VERR_INVALID_PARAMETER); 916 AssertReturn(this->Settings.Video.ulFPS, VERR_INVALID_PARAMETER); 917 918 this->Video.cFailedEncodingFrames = 0; 919 this->Video.uDelayMs = RT_MS_1SEC / this->Settings.Video.ulFPS; 920 580 921 #ifdef VBOX_WITH_LIBVPX 581 922 /* At the moment we only have VPX. */ 582 return VideoRecStreamInitVideoVPX(pStream, pCfg);923 return initVideoVPX(); 583 924 #else 584 return V ERR_NOT_SUPPORTED;925 return VINF_SUCCESS; 585 926 #endif 586 927 } … … 591 932 * 592 933 * @returns IPRT status code. 593 * @param pStream Recording stream to initialize VPX codec for. 594 * @param pCfg Video recording configuration to use for initialization. 595 */ 596 int VideoRecStreamInitVideoVPX(PVIDEORECSTREAM pStream, PVIDEORECCFG pCfg) 597 { 598 pStream->Video.uWidth = pCfg->Video.uWidth; 599 pStream->Video.uHeight = pCfg->Video.uHeight; 600 pStream->Video.cFailedEncodingFrames = 0; 601 602 PVIDEORECVIDEOCODEC pVC = &pStream->Video.Codec; 603 604 pStream->Video.uDelayMs = RT_MS_1SEC / pCfg->Video.uFPS; 605 606 pVC->enmType = VIDEORECVIDEOCODECTYPE_VP8; /** @todo Make this configurable. */ 607 934 */ 935 int CaptureStream::initVideoVPX(void) 936 { 608 937 # ifdef VBOX_WITH_LIBVPX_VP9 609 938 vpx_codec_iface_t *pCodecIface = vpx_codec_vp9_cx(); … … 612 941 # endif 613 942 614 vpx_codec_err_t rcv = vpx_codec_enc_config_default(pCodecIface, &pVC->VPX.Cfg, 0 /* Reserved */); 943 PVIDEORECVIDEOCODEC pCodec = &this->Video.Codec; 944 945 vpx_codec_err_t rcv = vpx_codec_enc_config_default(pCodecIface, &pCodec->VPX.Cfg, 0 /* Reserved */); 615 946 if (rcv != VPX_CODEC_OK) 616 947 { … … 620 951 621 952 /* Target bitrate in kilobits per second. */ 622 p VC->VPX.Cfg.rc_target_bitrate = pCfg->Video.uRate;953 pCodec->VPX.Cfg.rc_target_bitrate = this->Settings.Video.ulRate; 623 954 /* Frame width. */ 624 p VC->VPX.Cfg.g_w = pCfg->Video.uWidth;955 pCodec->VPX.Cfg.g_w = this->Settings.Video.ulWidth; 625 956 /* Frame height. */ 626 p VC->VPX.Cfg.g_h = pCfg->Video.uHeight;957 pCodec->VPX.Cfg.g_h = this->Settings.Video.ulHeight; 627 958 /* 1ms per frame. */ 628 p VC->VPX.Cfg.g_timebase.num = 1;629 p VC->VPX.Cfg.g_timebase.den = 1000;959 pCodec->VPX.Cfg.g_timebase.num = 1; 960 pCodec->VPX.Cfg.g_timebase.den = 1000; 630 961 /* Disable multithreading. */ 631 p VC->VPX.Cfg.g_threads = 0;962 pCodec->VPX.Cfg.g_threads = 0; 632 963 633 964 /* Initialize codec. */ 634 rcv = vpx_codec_enc_init(&p VC->VPX.Ctx, pCodecIface, &pVC->VPX.Cfg, 0 /* Flags */);965 rcv = vpx_codec_enc_init(&pCodec->VPX.Ctx, pCodecIface, &pCodec->VPX.Cfg, 0 /* Flags */); 635 966 if (rcv != VPX_CODEC_OK) 636 967 { … … 639 970 } 640 971 641 if (!vpx_img_alloc(&pVC->VPX.RawImage, VPX_IMG_FMT_I420, pCfg->Video.uWidth, pCfg->Video.uHeight, 1)) 642 { 643 LogRel(("VideoRec: Failed to allocate image %RU32x%RU32\n", pCfg->Video.uWidth, pCfg->Video.uHeight)); 972 if (!vpx_img_alloc(&pCodec->VPX.RawImage, VPX_IMG_FMT_I420, 973 this->Settings.Video.ulWidth, this->Settings.Video.ulHeight, 1)) 974 { 975 LogRel(("VideoRec: Failed to allocate image %RU32x%RU32\n", 976 this->Settings.Video.ulWidth, this->Settings.Video.ulHeight)); 644 977 return VERR_NO_MEMORY; 645 978 } 646 979 647 980 /* Save a pointer to the first raw YUV plane. */ 648 p Stream->Video.Codec.VPX.pu8YuvBuf = pVC->VPX.RawImage.planes[0];981 pCodec->VPX.pu8YuvBuf = pCodec->VPX.RawImage.planes[0]; 649 982 650 983 return VINF_SUCCESS; … … 652 985 #endif 653 986 987 int CaptureStream::initAudio(void) 988 { 989 #ifdef VBOX_WITH_AUDIO_VIDEOREC 990 if (this->Settings.isFeatureEnabled(CaptureFeature_Audio)) 991 { 992 /* Sanity. */ 993 AssertReturn(this->Settings.Audio.uHz, VERR_INVALID_PARAMETER); 994 AssertReturn(this->Settings.Audio.cBits, VERR_INVALID_PARAMETER); 995 AssertReturn(this->Settings.Audio.cChannels, VERR_INVALID_PARAMETER); 996 } 997 #endif 998 999 return VINF_SUCCESS; 1000 } 1001 654 1002 #ifdef VBOX_WITH_LIBVPX 655 1003 /** … … 657 1005 * 658 1006 * @returns IPRT status code. 659 * @param pStream Stream to encode and submit to.660 1007 * @param uTimeStampMs Absolute timestamp (PTS) of frame (in ms) to encode. 661 1008 * @param pFrame Frame to encode and submit. 662 1009 */ 663 int VideoRecStreamWriteVideoVPX(PVIDEORECSTREAM pStream, uint64_t uTimeStampMs, PVIDEORECVIDEOFRAME pFrame) 664 { 665 AssertPtrReturn(pStream, VERR_INVALID_POINTER); 666 AssertPtrReturn(pFrame, VERR_INVALID_POINTER); 1010 int CaptureStream::writeVideoVPX(uint64_t uTimeStampMs, PVIDEORECVIDEOFRAME pFrame) 1011 { 1012 AssertPtrReturn(pFrame, VERR_INVALID_POINTER); 667 1013 668 1014 int rc; 669 1015 670 AssertPtr(pStream->pCtx); 671 PVIDEORECCFG pCfg = &pStream->pCtx->Cfg; 672 PVIDEORECVIDEOCODEC pVC = &pStream->Video.Codec; 1016 PVIDEORECVIDEOCODEC pCodec = &this->Video.Codec; 673 1017 674 1018 /* Presentation Time Stamp (PTS). */ 675 1019 vpx_codec_pts_t pts = uTimeStampMs; 676 vpx_codec_err_t rcv = vpx_codec_encode(&p VC->VPX.Ctx,677 &p VC->VPX.RawImage,678 pts 679 pStream->Video.uDelayMs/* How long to show this frame */,680 0 681 pC fg->Video.Codec.VPX.uEncoderDeadline /* Quality setting */);1020 vpx_codec_err_t rcv = vpx_codec_encode(&pCodec->VPX.Ctx, 1021 &pCodec->VPX.RawImage, 1022 pts /* Time stamp */, 1023 this->Video.uDelayMs /* How long to show this frame */, 1024 0 /* Flags */, 1025 pCodec->VPX.uEncoderDeadline /* Quality setting */); 682 1026 if (rcv != VPX_CODEC_OK) 683 1027 { 684 if ( pStream->Video.cFailedEncodingFrames++ < 64)1028 if (this->Video.cFailedEncodingFrames++ < 64) /** @todo Make this configurable. */ 685 1029 { 686 1030 LogRel(("VideoRec: Failed to encode video frame: %s\n", vpx_codec_err_to_string(rcv))); … … 689 1033 } 690 1034 691 pStream->Video.cFailedEncodingFrames = 0;1035 this->Video.cFailedEncodingFrames = 0; 692 1036 693 1037 vpx_codec_iter_t iter = NULL; … … 695 1039 for (;;) 696 1040 { 697 const vpx_codec_cx_pkt_t *pPacket = vpx_codec_get_cx_data(&p VC->VPX.Ctx, &iter);1041 const vpx_codec_cx_pkt_t *pPacket = vpx_codec_get_cx_data(&pCodec->VPX.Ctx, &iter); 698 1042 if (!pPacket) 699 1043 break; … … 703 1047 case VPX_CODEC_CX_FRAME_PKT: 704 1048 { 705 WebMWriter::BlockData_VP8 blockData = { &p VC->VPX.Cfg, pPacket };706 rc = pStream->File.pWEBM->WriteBlock(pStream->uTrackVideo, &blockData, sizeof(blockData));1049 WebMWriter::BlockData_VP8 blockData = { &pCodec->VPX.Cfg, pPacket }; 1050 rc = this->File.pWEBM->WriteBlock(this->uTrackVideo, &blockData, sizeof(blockData)); 707 1051 break; 708 1052 } … … 719 1063 #endif /* VBOX_WITH_LIBVPX */ 720 1064 1065 /** 1066 * Locks a recording stream. 1067 * 1068 * @param pStream Recording stream to lock. 1069 */ 1070 void CaptureStream::lock(void) 1071 { 1072 int rc = RTCritSectEnter(&CritSect); 1073 AssertRC(rc); 1074 } 1075 1076 /** 1077 * Unlocks a locked recording stream. 1078 * 1079 * @param pStream Recording stream to unlock. 1080 */ 1081 void CaptureStream::unlock(void) 1082 { 1083 int rc = RTCritSectLeave(&CritSect); 1084 AssertRC(rc); 1085 } 1086 -
trunk/src/VBox/Main/src-server/MachineImpl.cpp
r74804 r75251 5 5 6 6 /* 7 * Copyright (C) 2004-201 7Oracle Corporation7 * Copyright (C) 2004-2018 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 168 168 mAccelerate2DVideoEnabled = false; 169 169 mMonitorCount = 1; 170 mVideoCaptureWidth = 1024;171 mVideoCaptureHeight = 768;172 mVideoCaptureRate = 512;173 mVideoCaptureFPS = 25;174 mVideoCaptureMaxTime = 0;175 mVideoCaptureMaxFileSize = 0;176 mVideoCaptureEnabled = false;177 for (unsigned i = 0; i < RT_ELEMENTS(maVideoCaptureScreens); ++i)178 maVideoCaptureScreens[i] = true;179 180 170 mHWVirtExEnabled = true; 181 171 mHWVirtExNestedPagingEnabled = true; … … 365 355 } 366 356 367 /* Apply BIOS defaults */357 /* Apply BIOS defaults. */ 368 358 mBIOSSettings->i_applyDefaults(aOsType); 359 360 /* Apply capture defaults. */ 361 mCaptureSettings->i_applyDefaults(); 369 362 370 363 /* Apply network adapters defaults */ … … 1732 1725 } 1733 1726 1734 HRESULT Machine::getVideoCaptureEnabled(BOOL *aVideoCaptureEnabled)1735 {1736 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);1737 1738 *aVideoCaptureEnabled = mHWData->mVideoCaptureEnabled;1739 return S_OK;1740 }1741 1742 HRESULT Machine::setVideoCaptureEnabled(BOOL aVideoCaptureEnabled)1743 {1744 HRESULT rc = S_OK;1745 1746 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);1747 1748 i_setModified(IsModified_MachineData);1749 mHWData.backup();1750 mHWData->mVideoCaptureEnabled = aVideoCaptureEnabled;1751 1752 alock.release();1753 rc = i_onVideoCaptureChange();1754 alock.acquire();1755 if (FAILED(rc))1756 {1757 /*1758 * Normally we would do the actual change _after_ i_onVideoCaptureChange() succeeded.1759 * We cannot do this because that function uses Machine::GetVideoCaptureEnabled to1760 * determine if it should start or stop capturing. Therefore we need to manually1761 * undo change.1762 */1763 mHWData->mVideoCaptureEnabled = mHWData.backedUpData()->mVideoCaptureEnabled;1764 return rc;1765 }1766 1767 /** Save settings if online - @todo why is this required? -- @bugref{6818} */1768 if (Global::IsOnline(mData->mMachineState))1769 i_saveSettings(NULL);1770 1771 return rc;1772 }1773 1774 HRESULT Machine::getVideoCaptureScreens(std::vector<BOOL> &aVideoCaptureScreens)1775 {1776 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);1777 aVideoCaptureScreens.resize(mHWData->mMonitorCount);1778 for (unsigned i = 0; i < mHWData->mMonitorCount; ++i)1779 aVideoCaptureScreens[i] = mHWData->maVideoCaptureScreens[i];1780 return S_OK;1781 }1782 1783 HRESULT Machine::setVideoCaptureScreens(const std::vector<BOOL> &aVideoCaptureScreens)1784 {1785 AssertReturn(aVideoCaptureScreens.size() <= RT_ELEMENTS(mHWData->maVideoCaptureScreens), E_INVALIDARG);1786 bool fChanged = false;1787 1788 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);1789 1790 for (unsigned i = 0; i < aVideoCaptureScreens.size(); ++i)1791 {1792 if (mHWData->maVideoCaptureScreens[i] != RT_BOOL(aVideoCaptureScreens[i]))1793 {1794 mHWData->maVideoCaptureScreens[i] = RT_BOOL(aVideoCaptureScreens[i]);1795 fChanged = true;1796 }1797 }1798 if (fChanged)1799 {1800 alock.release();1801 HRESULT rc = i_onVideoCaptureChange();1802 alock.acquire();1803 if (FAILED(rc)) return rc;1804 i_setModified(IsModified_MachineData);1805 1806 /** Save settings if online - @todo why is this required? -- @bugref{6818} */1807 if (Global::IsOnline(mData->mMachineState))1808 i_saveSettings(NULL);1809 }1810 1811 return S_OK;1812 }1813 1814 HRESULT Machine::getVideoCaptureFile(com::Utf8Str &aVideoCaptureFile)1815 {1816 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);1817 if (mHWData->mVideoCaptureFile.isEmpty())1818 i_getDefaultVideoCaptureFile(aVideoCaptureFile);1819 else1820 aVideoCaptureFile = mHWData->mVideoCaptureFile;1821 return S_OK;1822 }1823 1824 HRESULT Machine::setVideoCaptureFile(const com::Utf8Str &aVideoCaptureFile)1825 {1826 Utf8Str strFile(aVideoCaptureFile);1827 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);1828 1829 if ( Global::IsOnline(mData->mMachineState)1830 && mHWData->mVideoCaptureEnabled)1831 return setError(E_INVALIDARG, tr("Cannot change parameters while capturing is enabled"));1832 1833 if (!RTPathStartsWithRoot(strFile.c_str()))1834 return setError(E_INVALIDARG, tr("Video capture file name '%s' is not absolute"), strFile.c_str());1835 1836 if (!strFile.isEmpty())1837 {1838 Utf8Str defaultFile;1839 i_getDefaultVideoCaptureFile(defaultFile);1840 if (!RTPathCompare(strFile.c_str(), defaultFile.c_str()))1841 strFile.setNull();1842 }1843 1844 i_setModified(IsModified_MachineData);1845 mHWData.backup();1846 mHWData->mVideoCaptureFile = strFile;1847 1848 return S_OK;1849 }1850 1851 HRESULT Machine::getVideoCaptureWidth(ULONG *aVideoCaptureWidth)1852 {1853 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);1854 *aVideoCaptureWidth = mHWData->mVideoCaptureWidth;1855 return S_OK;1856 }1857 1858 HRESULT Machine::setVideoCaptureWidth(ULONG aVideoCaptureWidth)1859 {1860 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);1861 1862 if ( Global::IsOnline(mData->mMachineState)1863 && mHWData->mVideoCaptureEnabled)1864 return setError(E_INVALIDARG, tr("Cannot change parameters while capturing is enabled"));1865 1866 i_setModified(IsModified_MachineData);1867 mHWData.backup();1868 mHWData->mVideoCaptureWidth = aVideoCaptureWidth;1869 1870 return S_OK;1871 }1872 1873 HRESULT Machine::getVideoCaptureHeight(ULONG *aVideoCaptureHeight)1874 {1875 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);1876 *aVideoCaptureHeight = mHWData->mVideoCaptureHeight;1877 return S_OK;1878 }1879 1880 HRESULT Machine::setVideoCaptureHeight(ULONG aVideoCaptureHeight)1881 {1882 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);1883 1884 if ( Global::IsOnline(mData->mMachineState)1885 && mHWData->mVideoCaptureEnabled)1886 return setError(E_INVALIDARG, tr("Cannot change parameters while capturing is enabled"));1887 1888 i_setModified(IsModified_MachineData);1889 mHWData.backup();1890 mHWData->mVideoCaptureHeight = aVideoCaptureHeight;1891 1892 return S_OK;1893 }1894 1895 HRESULT Machine::getVideoCaptureRate(ULONG *aVideoCaptureRate)1896 {1897 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);1898 *aVideoCaptureRate = mHWData->mVideoCaptureRate;1899 return S_OK;1900 }1901 1902 HRESULT Machine::setVideoCaptureRate(ULONG aVideoCaptureRate)1903 {1904 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);1905 1906 if ( Global::IsOnline(mData->mMachineState)1907 && mHWData->mVideoCaptureEnabled)1908 return setError(E_INVALIDARG, tr("Cannot change parameters while capturing is enabled"));1909 1910 i_setModified(IsModified_MachineData);1911 mHWData.backup();1912 mHWData->mVideoCaptureRate = aVideoCaptureRate;1913 1914 return S_OK;1915 }1916 1917 HRESULT Machine::getVideoCaptureFPS(ULONG *aVideoCaptureFPS)1918 {1919 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);1920 *aVideoCaptureFPS = mHWData->mVideoCaptureFPS;1921 return S_OK;1922 }1923 1924 HRESULT Machine::setVideoCaptureFPS(ULONG aVideoCaptureFPS)1925 {1926 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);1927 1928 if ( Global::IsOnline(mData->mMachineState)1929 && mHWData->mVideoCaptureEnabled)1930 return setError(E_INVALIDARG, tr("Cannot change parameters while capturing is enabled"));1931 1932 i_setModified(IsModified_MachineData);1933 mHWData.backup();1934 mHWData->mVideoCaptureFPS = aVideoCaptureFPS;1935 1936 return S_OK;1937 }1938 1939 HRESULT Machine::getVideoCaptureMaxTime(ULONG *aVideoCaptureMaxTime)1940 {1941 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);1942 *aVideoCaptureMaxTime = mHWData->mVideoCaptureMaxTime;1943 return S_OK;1944 }1945 1946 HRESULT Machine::setVideoCaptureMaxTime(ULONG aVideoCaptureMaxTime)1947 {1948 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);1949 1950 if ( Global::IsOnline(mData->mMachineState)1951 && mHWData->mVideoCaptureEnabled)1952 return setError(E_INVALIDARG, tr("Cannot change parameters while capturing is enabled"));1953 1954 i_setModified(IsModified_MachineData);1955 mHWData.backup();1956 mHWData->mVideoCaptureMaxTime = aVideoCaptureMaxTime;1957 1958 return S_OK;1959 }1960 1961 HRESULT Machine::getVideoCaptureMaxFileSize(ULONG *aVideoCaptureMaxFileSize)1962 {1963 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);1964 *aVideoCaptureMaxFileSize = mHWData->mVideoCaptureMaxFileSize;1965 return S_OK;1966 }1967 1968 HRESULT Machine::setVideoCaptureMaxFileSize(ULONG aVideoCaptureMaxFileSize)1969 {1970 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);1971 1972 if ( Global::IsOnline(mData->mMachineState)1973 && mHWData->mVideoCaptureEnabled)1974 return setError(E_INVALIDARG, tr("Cannot change parameters while capturing is enabled"));1975 1976 i_setModified(IsModified_MachineData);1977 mHWData.backup();1978 mHWData->mVideoCaptureMaxFileSize = aVideoCaptureMaxFileSize;1979 1980 return S_OK;1981 }1982 1983 HRESULT Machine::getVideoCaptureOptions(com::Utf8Str &aVideoCaptureOptions)1984 {1985 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);1986 1987 aVideoCaptureOptions = mHWData->mVideoCaptureOptions;1988 return S_OK;1989 }1990 1991 HRESULT Machine::setVideoCaptureOptions(const com::Utf8Str &aVideoCaptureOptions)1992 {1993 AutoWriteLock alock(this COMMA_LOCKVAL_SRC_POS);1994 1995 if ( Global::IsOnline(mData->mMachineState)1996 && mHWData->mVideoCaptureEnabled)1997 return setError(E_INVALIDARG, tr("Cannot change parameters while capturing is enabled"));1998 1999 i_setModified(IsModified_MachineData);2000 mHWData.backup();2001 mHWData->mVideoCaptureOptions = aVideoCaptureOptions;2002 2003 return S_OK;2004 }2005 2006 1727 HRESULT Machine::getGraphicsControllerType(GraphicsControllerType_T *aGraphicsControllerType) 2007 1728 { … … 2215 1936 /* mBIOSSettings is constant during life time, no need to lock */ 2216 1937 aBIOSSettings = mBIOSSettings; 1938 1939 return S_OK; 1940 } 1941 1942 HRESULT Machine::getCaptureSettings(ComPtr<ICaptureSettings> &aCaptureSettings) 1943 { 1944 /* mCaptureSettings is constant during life time, no need to lock */ 1945 aCaptureSettings = mCaptureSettings; 2217 1946 2218 1947 return S_OK; … … 7654 7383 7655 7384 /** 7656 * Returns the full path to the default video capture file.7657 */7658 void Machine::i_getDefaultVideoCaptureFile(Utf8Str &strFile)7659 {7660 AutoCaller autoCaller(this);7661 AssertComRCReturnVoid(autoCaller.rc());7662 7663 AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS);7664 7665 strFile = mData->m_strConfigFileFull; // path/to/machinesfolder/vmname/vmname.vbox7666 strFile.stripSuffix(); // path/to/machinesfolder/vmname/vmname7667 strFile.append(".webm"); // path/to/machinesfolder/vmname/vmname.webm7668 }7669 7670 /**7671 7385 * Returns whether at least one USB controller is present for the VM. 7672 7386 */ … … 8545 8259 mBIOSSettings->init(this); 8546 8260 8261 /* create associated capture settings object */ 8262 unconst(mCaptureSettings).createObject(); 8263 mCaptureSettings->init(this); 8264 8547 8265 /* create an associated VRDE object (default is disabled) */ 8548 8266 unconst(mVRDEServer).createObject(); … … 8658 8376 mBIOSSettings->uninit(); 8659 8377 unconst(mBIOSSettings).setNull(); 8378 } 8379 8380 if (mCaptureSettings) 8381 { 8382 mCaptureSettings->uninit(); 8383 unconst(mCaptureSettings).setNull(); 8660 8384 } 8661 8385 … … 9157 8881 mHWData->mAccelerate3DEnabled = data.fAccelerate3D; 9158 8882 mHWData->mAccelerate2DVideoEnabled = data.fAccelerate2DVideo; 9159 mHWData->mVideoCaptureWidth = data.ulVideoCaptureHorzRes;9160 mHWData->mVideoCaptureHeight = data.ulVideoCaptureVertRes;9161 mHWData->mVideoCaptureEnabled = data.fVideoCaptureEnabled;9162 for (unsigned i = 0; i < RT_ELEMENTS(mHWData->maVideoCaptureScreens); ++i)9163 mHWData->maVideoCaptureScreens[i] = ASMBitTest(&data.u64VideoCaptureScreens, i);9164 AssertCompile(RT_ELEMENTS(mHWData->maVideoCaptureScreens) == sizeof(data.u64VideoCaptureScreens) * 8);9165 mHWData->mVideoCaptureRate = data.ulVideoCaptureRate;9166 mHWData->mVideoCaptureFPS = data.ulVideoCaptureFPS;9167 if (!data.strVideoCaptureFile.isEmpty())9168 i_calculateFullPath(data.strVideoCaptureFile, mHWData->mVideoCaptureFile);9169 else9170 mHWData->mVideoCaptureFile.setNull();9171 mHWData->mVideoCaptureOptions = data.strVideoCaptureOptions;9172 8883 mHWData->mFirmwareType = data.firmwareType; 9173 8884 mHWData->mPointingHIDType = data.pointingHIDType; … … 9187 8898 if (FAILED(rc)) return rc; 9188 8899 8900 /* Capture settings */ 8901 rc = mCaptureSettings->i_loadSettings(data.captureSettings); 8902 if (FAILED(rc)) return rc; 8903 9189 8904 // Bandwidth control (must come before network adapters) 9190 8905 rc = mBandwidthControl->i_loadSettings(data.ioSettings); 9191 8906 if (FAILED(rc)) return rc; 9192 8907 9193 /* Shared folders */8908 /* USB controllers */ 9194 8909 for (settings::USBControllerList::const_iterator 9195 8910 it = data.usbSettings.llUSBControllers.begin(); … … 10493 10208 data.fAccelerate3D = !!mHWData->mAccelerate3DEnabled; 10494 10209 data.fAccelerate2DVideo = !!mHWData->mAccelerate2DVideoEnabled; 10495 data.ulVideoCaptureHorzRes = mHWData->mVideoCaptureWidth;10496 data.ulVideoCaptureVertRes = mHWData->mVideoCaptureHeight;10497 data.ulVideoCaptureRate = mHWData->mVideoCaptureRate;10498 data.ulVideoCaptureFPS = mHWData->mVideoCaptureFPS;10499 data.fVideoCaptureEnabled = !!mHWData->mVideoCaptureEnabled;10500 for (unsigned i = 0; i < sizeof(data.u64VideoCaptureScreens) * 8; ++i)10501 {10502 if (mHWData->maVideoCaptureScreens[i])10503 ASMBitSet(&data.u64VideoCaptureScreens, i);10504 else10505 ASMBitClear(&data.u64VideoCaptureScreens, i);10506 }10507 /* store relative video capture file if possible */10508 i_copyPathRelativeToMachine(mHWData->mVideoCaptureFile, data.strVideoCaptureFile);10509 data.strVideoCaptureOptions = mHWData->mVideoCaptureOptions;10510 10210 10511 10211 /* VRDEServer settings (optional) */ … … 10513 10213 if (FAILED(rc)) throw rc; 10514 10214 10515 /* BIOS (required) */10215 /* BIOS settings (required) */ 10516 10216 rc = mBIOSSettings->i_saveSettings(data.biosSettings); 10217 if (FAILED(rc)) throw rc; 10218 10219 /* Capture settings (required) */ 10220 rc = mCaptureSettings->i_saveSettings(data.captureSettings); 10517 10221 if (FAILED(rc)) throw rc; 10518 10222 … … 12019 11723 mBIOSSettings->i_rollback(); 12020 11724 11725 if (mCaptureSettings && (mData->flModifications & IsModified_Capture)) 11726 mCaptureSettings->i_rollback(); 11727 12021 11728 if (mVRDEServer && (mData->flModifications & IsModified_VRDEServer)) 12022 11729 mVRDEServer->i_rollback(); … … 12129 11836 12130 11837 mBIOSSettings->i_commit(); 11838 mCaptureSettings->i_commit(); 12131 11839 mVRDEServer->i_commit(); 12132 11840 mAudioAdapter->i_commit(); … … 12381 12089 12382 12090 mBIOSSettings->i_copyFrom(aThat->mBIOSSettings); 12091 mCaptureSettings->i_copyFrom(aThat->mCaptureSettings); 12383 12092 mVRDEServer->i_copyFrom(aThat->mVRDEServer); 12384 12093 mAudioAdapter->i_copyFrom(aThat->mAudioAdapter); … … 12754 12463 unconst(mBIOSSettings).createObject(); 12755 12464 mBIOSSettings->init(this, aMachine->mBIOSSettings); 12465 unconst(mCaptureSettings).createObject(); 12466 mCaptureSettings->init(this, aMachine->mCaptureSettings); 12756 12467 /* create another VRDEServer object that will be mutable */ 12757 12468 unconst(mVRDEServer).createObject(); … … 14387 14098 * @note Locks this object for reading. 14388 14099 */ 14389 HRESULT SessionMachine::i_on VideoCaptureChange()14100 HRESULT SessionMachine::i_onCaptureChange() 14390 14101 { 14391 14102 LogFlowThisFunc(("\n")); … … 14405 14116 return S_OK; 14406 14117 14407 return directControl->On VideoCaptureChange();14118 return directControl->OnCaptureChange(); 14408 14119 } 14409 14120 … … 15339 15050 mBIOSSettings->i_applyDefaults(osType); 15340 15051 15052 /* Initialize default capture settings. */ 15053 mCaptureSettings->i_applyDefaults(); 15054 15341 15055 /* Initialize default BIOS settings here */ 15342 15056 mHWData->mAPIC = osType->i_recommendedIOAPIC(); -
trunk/src/VBox/Main/xml/Settings.cpp
r74474 r75251 2371 2371 } 2372 2372 2373 CaptureScreenSettings::CaptureScreenSettings(void) 2374 { 2375 applyDefaults(); 2376 } 2377 2378 CaptureScreenSettings::~CaptureScreenSettings() 2379 { 2380 2381 } 2382 2383 void CaptureScreenSettings::applyDefaults(void) 2384 { 2385 /* 2386 * Set sensible defaults. 2387 */ 2388 2389 fEnabled = true; 2390 enmDest = CaptureDestination_File; 2391 ulMaxTimeS = 0; 2392 strOptions = ""; 2393 File.ulMaxSizeMB = 0; 2394 Video.enmCodec = CaptureVideoCodec_VP8; 2395 Video.ulWidth = 1024; 2396 Video.ulHeight = 768; 2397 Video.ulRate = 512; 2398 Video.ulFPS = 25; 2399 Audio.enmAudioCodec = CaptureAudioCodec_Opus; 2400 Audio.cBits = 16; 2401 Audio.cChannels = 2; 2402 Audio.uHz = 22050; 2403 2404 featureMap[CaptureFeature_Video] = true; 2405 featureMap[CaptureFeature_Audio] = false; 2406 2407 //i_calculateFullPath 2408 } 2409 2410 /** 2411 * Check if all settings have default values. 2412 */ 2413 bool CaptureScreenSettings::areDefaultSettings(void) const 2414 { 2415 const bool fDefault = fEnabled == true 2416 && enmDest == CaptureDestination_File 2417 && ulMaxTimeS == 0 2418 && strOptions == "" 2419 && File.ulMaxSizeMB == 0 2420 && Video.enmCodec == CaptureVideoCodec_VP8 2421 && Video.ulWidth == 1024 2422 && Video.ulHeight == 768 2423 && Video.ulRate == 512 2424 && Video.ulFPS == 25 2425 && Audio.enmAudioCodec == CaptureAudioCodec_Opus 2426 && Audio.cBits == 16 2427 && Audio.cChannels == 2 2428 && Audio.uHz == 22050; 2429 2430 return fDefault; 2431 } 2432 2433 bool CaptureScreenSettings::isFeatureEnabled(CaptureFeature_T enmFeature) const 2434 { 2435 CaptureFeatureMap::const_iterator itFeature = featureMap.find(enmFeature); 2436 if (itFeature != featureMap.end()) 2437 return itFeature->second; 2438 2439 return false; 2440 } 2441 2442 /** 2443 * Comparison operator. This gets called from MachineConfigFile::operator==, 2444 * which in turn gets called from Machine::saveSettings to figure out whether 2445 * machine settings have really changed and thus need to be written out to disk. 2446 */ 2447 bool CaptureScreenSettings::operator==(const CaptureScreenSettings &d) const 2448 { 2449 return fEnabled == d.fEnabled 2450 && enmDest == d.enmDest 2451 && featureMap == d.featureMap 2452 && ulMaxTimeS == d.ulMaxTimeS 2453 && strOptions == d.strOptions 2454 && File.ulMaxSizeMB == d.File.ulMaxSizeMB 2455 && Video.enmCodec == d.Video.enmCodec 2456 && Video.ulWidth == d.Video.ulWidth 2457 && Video.ulHeight == d.Video.ulHeight 2458 && Video.ulRate == d.Video.ulRate 2459 && Video.ulFPS == d.Video.ulFPS 2460 && Audio.enmAudioCodec == d.Audio.enmAudioCodec 2461 && Audio.cBits == d.Audio.cBits 2462 && Audio.cChannels == d.Audio.cChannels 2463 && Audio.uHz == d.Audio.uHz; 2464 } 2465 2466 /** 2467 * Constructor. Needs to set sane defaults which stand the test of time. 2468 */ 2469 CaptureSettings::CaptureSettings() 2470 { 2471 applyDefaults(); 2472 } 2473 2474 void CaptureSettings::applyDefaults(void) 2475 { 2476 fEnabled = false; 2477 2478 mapScreens.clear(); 2479 2480 CaptureScreenSettings screenSettings; /* Apply default settings. */ 2481 for (unsigned long l = 0; l < SchemaDefs::MaxGuestMonitors; l++) 2482 { 2483 mapScreens[l] = screenSettings; 2484 } 2485 } 2486 2487 /** 2488 * Check if all settings have default values. 2489 */ 2490 bool CaptureSettings::areDefaultSettings() const 2491 { 2492 CaptureScreenMap::const_iterator itScreen = mapScreens.begin(); 2493 while (itScreen != mapScreens.end()) 2494 { 2495 if (!itScreen->second.areDefaultSettings()) 2496 return false; 2497 2498 ++itScreen; 2499 } 2500 2501 return true; 2502 } 2503 2504 /** 2505 * Comparison operator. This gets called from MachineConfigFile::operator==, 2506 * which in turn gets called from Machine::saveSettings to figure out whether 2507 * machine settings have really changed and thus need to be written out to disk. 2508 */ 2509 bool CaptureSettings::operator==(const CaptureSettings &d) const 2510 { 2511 if (this == &d) 2512 return true; 2513 2514 if ( fEnabled != d.fEnabled 2515 || mapScreens.size() != d.mapScreens.size()) 2516 return false; 2517 2518 CaptureScreenMap::const_iterator itScreen = mapScreens.begin(); 2519 size_t i = 0; 2520 while (itScreen != mapScreens.end()) 2521 { 2522 CaptureScreenMap::const_iterator itScreenThat = d.mapScreens.find(i); 2523 if (itScreen->second == itScreenThat->second) 2524 { 2525 /* Nothing to do in here (yet). */ 2526 } 2527 else 2528 return false; 2529 2530 ++itScreen; 2531 ++i; 2532 } 2533 2534 return true; 2535 } 2536 2373 2537 /** 2374 2538 * Constructor. Needs to set sane defaults which stand the test of time. … … 2901 3065 fAccelerate3D(false), 2902 3066 fAccelerate2DVideo(false), 2903 ulVideoCaptureHorzRes(1024),2904 ulVideoCaptureVertRes(768),2905 ulVideoCaptureRate(512),2906 ulVideoCaptureFPS(25),2907 ulVideoCaptureMaxTime(0),2908 ulVideoCaptureMaxSize(0),2909 fVideoCaptureEnabled(false),2910 u64VideoCaptureScreens(UINT64_C(0xffffffffffffffff)),2911 strVideoCaptureFile(""),2912 3067 firmwareType(FirmwareType_BIOS), 2913 3068 pointingHIDType(PointingHIDType_PS2Mouse), … … 2986 3141 && !fAccelerate3D 2987 3142 && !fAccelerate2DVideo; 2988 }2989 2990 /**2991 * Check if all Video Capture settings have default values.2992 */2993 bool Hardware::areVideoCaptureDefaultSettings() const2994 {2995 return !fVideoCaptureEnabled2996 && u64VideoCaptureScreens == UINT64_C(0xffffffffffffffff)2997 && strVideoCaptureFile.isEmpty()2998 && ulVideoCaptureHorzRes == 10242999 && ulVideoCaptureVertRes == 7683000 && ulVideoCaptureRate == 5123001 && ulVideoCaptureFPS == 253002 && ulVideoCaptureMaxTime == 03003 && ulVideoCaptureMaxSize == 03004 && strVideoCaptureOptions.isEmpty();3005 3143 } 3006 3144 … … 3062 3200 && fAccelerate3D == h.fAccelerate3D 3063 3201 && fAccelerate2DVideo == h.fAccelerate2DVideo 3064 && fVideoCaptureEnabled == h.fVideoCaptureEnabled3065 && u64VideoCaptureScreens == h.u64VideoCaptureScreens3066 && strVideoCaptureFile == h.strVideoCaptureFile3067 && ulVideoCaptureHorzRes == h.ulVideoCaptureHorzRes3068 && ulVideoCaptureVertRes == h.ulVideoCaptureVertRes3069 && ulVideoCaptureRate == h.ulVideoCaptureRate3070 && ulVideoCaptureFPS == h.ulVideoCaptureFPS3071 && ulVideoCaptureMaxTime == h.ulVideoCaptureMaxTime3072 && ulVideoCaptureMaxSize == h.ulVideoCaptureMaxTime3073 && strVideoCaptureOptions == h.strVideoCaptureOptions3074 3202 && firmwareType == h.firmwareType 3075 3203 && pointingHIDType == h.pointingHIDType … … 4276 4404 else if (pelmHwChild->nameEquals("VideoCapture")) 4277 4405 { 4278 pelmHwChild->getAttributeValue("enabled", hw.fVideoCaptureEnabled); 4279 pelmHwChild->getAttributeValue("screens", hw.u64VideoCaptureScreens); 4280 pelmHwChild->getAttributeValuePath("file", hw.strVideoCaptureFile); 4281 pelmHwChild->getAttributeValue("horzRes", hw.ulVideoCaptureHorzRes); 4282 pelmHwChild->getAttributeValue("vertRes", hw.ulVideoCaptureVertRes); 4283 pelmHwChild->getAttributeValue("rate", hw.ulVideoCaptureRate); 4284 pelmHwChild->getAttributeValue("fps", hw.ulVideoCaptureFPS); 4285 pelmHwChild->getAttributeValue("maxTime", hw.ulVideoCaptureMaxTime); 4286 pelmHwChild->getAttributeValue("maxSize", hw.ulVideoCaptureMaxSize); 4287 pelmHwChild->getAttributeValue("options", hw.strVideoCaptureOptions); 4406 pelmHwChild->getAttributeValue("enabled", hw.captureSettings.fEnabled); 4407 4408 /* Right now I don't want to bump the settings version, so just convert the enabled 4409 * screens to the former uint6t_t bit array and vice versa. */ 4410 uint64_t u64VideoCaptureScreens; 4411 pelmHwChild->getAttributeValue("screens", u64VideoCaptureScreens); 4412 4413 /* At the moment we only support one capturing configuration, that is, all screens 4414 * have the same configuration. So load/save to/from screen 0. */ 4415 CaptureScreenSettings &screen0Settings = hw.captureSettings.mapScreens[0]; 4416 4417 pelmHwChild->getAttributeValue("maxTime", screen0Settings.ulMaxTimeS); 4418 pelmHwChild->getAttributeValue("options", screen0Settings.strOptions); 4419 pelmHwChild->getAttributeValuePath("file", screen0Settings.File.strName); 4420 pelmHwChild->getAttributeValue("maxSize", screen0Settings.File.ulMaxSizeMB); 4421 pelmHwChild->getAttributeValue("horzRes", screen0Settings.Video.ulWidth); 4422 pelmHwChild->getAttributeValue("vertRes", screen0Settings.Video.ulHeight); 4423 pelmHwChild->getAttributeValue("rate", screen0Settings.Video.ulRate); 4424 pelmHwChild->getAttributeValue("fps", screen0Settings.Video.ulFPS); 4425 4426 for (unsigned i = 0; i < 64; i++) 4427 { 4428 if (u64VideoCaptureScreens & RT_BIT(i)) /* Screen i enabled? */ 4429 { 4430 hw.captureSettings.mapScreens[i] = screen0Settings; 4431 hw.captureSettings.mapScreens[i].fEnabled = true; 4432 } 4433 } 4288 4434 } 4289 4435 else if (pelmHwChild->nameEquals("RemoteDisplay")) … … 5668 5814 } 5669 5815 5670 if (m->sv >= SettingsVersion_v1_14 && !hw. areVideoCaptureDefaultSettings())5816 if (m->sv >= SettingsVersion_v1_14 && !hw.captureSettings.areDefaultSettings()) 5671 5817 { 5672 5818 xml::ElementNode *pelmVideoCapture = pelmHardware->createChild("VideoCapture"); 5673 if (hw.fVideoCaptureEnabled) 5674 pelmVideoCapture->setAttribute("enabled", hw.fVideoCaptureEnabled); 5675 if (hw.u64VideoCaptureScreens != UINT64_C(0xffffffffffffffff)) 5676 pelmVideoCapture->setAttribute("screens", hw.u64VideoCaptureScreens); 5677 if (!hw.strVideoCaptureFile.isEmpty()) 5678 pelmVideoCapture->setAttributePath("file", hw.strVideoCaptureFile); 5679 if (hw.ulVideoCaptureHorzRes != 1024 || hw.ulVideoCaptureVertRes != 768) 5680 { 5681 pelmVideoCapture->setAttribute("horzRes", hw.ulVideoCaptureHorzRes); 5682 pelmVideoCapture->setAttribute("vertRes", hw.ulVideoCaptureVertRes); 5683 } 5684 if (hw.ulVideoCaptureRate != 512) 5685 pelmVideoCapture->setAttribute("rate", hw.ulVideoCaptureRate); 5686 if (hw.ulVideoCaptureFPS) 5687 pelmVideoCapture->setAttribute("fps", hw.ulVideoCaptureFPS); 5688 if (hw.ulVideoCaptureMaxTime) 5689 pelmVideoCapture->setAttribute("maxTime", hw.ulVideoCaptureMaxTime); 5690 if (hw.ulVideoCaptureMaxSize) 5691 pelmVideoCapture->setAttribute("maxSize", hw.ulVideoCaptureMaxSize); 5692 if (!hw.strVideoCaptureOptions.isEmpty()) 5693 pelmVideoCapture->setAttributePath("options", hw.strVideoCaptureOptions); 5819 5820 if (hw.captureSettings.fEnabled) 5821 pelmVideoCapture->setAttribute("enabled", hw.captureSettings.fEnabled); 5822 5823 /* Right now I don't want to bump the settings version, so just convert the enabled 5824 * screens to the former uint6t_t bit array and vice versa. */ 5825 uint64_t u64VideoCaptureScreens = 0; 5826 CaptureScreenMap::const_iterator itScreen = hw.captureSettings.mapScreens.begin(); 5827 while (itScreen != hw.captureSettings.mapScreens.end()) 5828 { 5829 if (itScreen->second.fEnabled) 5830 u64VideoCaptureScreens |= RT_BIT(itScreen->first); 5831 ++itScreen; 5832 } 5833 5834 if (u64VideoCaptureScreens) 5835 pelmVideoCapture->setAttribute("screens", u64VideoCaptureScreens); 5836 5837 /* At the moment we only support one capturing configuration, that is, all screens 5838 * have the same configuration. So load/save to/from screen 0. */ 5839 Assert(hw.captureSettings.mapScreens.size()); 5840 const CaptureScreenMap::const_iterator itScreen0Settings = hw.captureSettings.mapScreens.find(0); 5841 5842 if (itScreen0Settings->second.ulMaxTimeS) 5843 pelmVideoCapture->setAttribute("maxTime", itScreen0Settings->second.ulMaxTimeS); 5844 if (itScreen0Settings->second.strOptions.isNotEmpty()) 5845 pelmVideoCapture->setAttributePath("options", itScreen0Settings->second.strOptions); 5846 5847 if (!itScreen0Settings->second.File.strName.isEmpty()) 5848 pelmVideoCapture->setAttributePath("file", itScreen0Settings->second.File.strName); 5849 if (itScreen0Settings->second.File.ulMaxSizeMB) 5850 pelmVideoCapture->setAttribute("maxSize", itScreen0Settings->second.File.ulMaxSizeMB); 5851 5852 if ( itScreen0Settings->second.Video.ulWidth != 1024 5853 || itScreen0Settings->second.Video.ulHeight != 768) 5854 { 5855 pelmVideoCapture->setAttribute("horzRes", itScreen0Settings->second.Video.ulWidth); 5856 pelmVideoCapture->setAttribute("vertRes", itScreen0Settings->second.Video.ulHeight); 5857 } 5858 if (itScreen0Settings->second.Video.ulRate != 512) 5859 pelmVideoCapture->setAttribute("rate", itScreen0Settings->second.Video.ulRate); 5860 if (itScreen0Settings->second.Video.ulFPS) 5861 pelmVideoCapture->setAttribute("fps", itScreen0Settings->second.Video.ulFPS); 5694 5862 } 5695 5863 … … 7262 7430 { 7263 7431 // VirtualBox 4.3 adds default frontend setting, graphics controller 7264 // setting, explicit long mode setting, videocapturing and NAT networking.7432 // setting, explicit long mode setting, (video) capturing and NAT networking. 7265 7433 if ( !hardwareMachine.strDefaultFrontend.isEmpty() 7266 7434 || hardwareMachine.graphicsControllerType != GraphicsControllerType_VBoxVGA 7267 7435 || hardwareMachine.enmLongMode != Hardware::LongMode_Legacy 7268 7436 || machineUserData.ovIcon.size() > 0 7269 || hardwareMachine. fVideoCaptureEnabled)7437 || hardwareMachine.captureSettings.fEnabled) 7270 7438 { 7271 7439 m->sv = SettingsVersion_v1_14;
Note:
See TracChangeset
for help on using the changeset viewer.