From: Dan Minor Date: Mon, 22 Jan 2018 13:31:00 -0500 Subject: Bug 1376873 - Rollup of local modifications; r=ng MozReview-Commit-ID: 2euYzBEvuNb Differential Revision: https://phabricator.services.mozilla.com/D7425 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/28b57e3ba51de982a4663801a3935580114b5477 Bug 1376873 - Rollup conflict fixes for audio/video code; r=pehrsons MozReview-Commit-ID: 1T8mgqdkzq3 Differential Revision: https://phabricator.services.mozilla.com/D7427 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/93eec571640ee0810da8475ee37e417b88045574 Bug 1376873 - Rollup conflict fixes for rtp_rtcp module; r=ng MozReview-Commit-ID: D09534DOVLj Differential Revision: https://phabricator.services.mozilla.com/D7428 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/50f89f4e45b0af87fd6aa45aed60f02f3e69b951 Bug 1497552 - Remove support for 44100 Hz in dtmf_tone_generator; r=padenot Assertions in NetEqImpl::SetSampleRateAndChannels prevent us from requesting tones at 44100 Hz, so this code can be safely removed. Differential Revision: https://phabricator.services.mozilla.com/D12982 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/8ea04ec01e9905d4714aa01ade891d552c56a3a6 Bug 1497577 - Remove code to detect zero size windows; r=ng This code was added by Bug 1196542 to fix a permanently failing test on our Windows test machines. After this landed, upstream added a check for empty windows in window_captuer_win.cc, so this should no longer be a problem on Windows. As far as I know, this was never a problem on the other platforms, so this code can be safely removed. Differential Revision: https://phabricator.services.mozilla.com/D13448 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/647ade4da0fba74a268aab079677cb47f20f036e Bug 1509994 - Move video_engine from webrtc to systemservices; r=pehrsons Historically this code was part of webrtc.org but has since been removed from upstream. Rather than maintaining it as a local diff against upstream, we should just move it to where it is used. Differential Revision: https://phabricator.services.mozilla.com/D13092 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/0fd399c6caabff60ac0fe53b920b7d26a9806750 Bug 1497606 - Remove disable_composition_ in screen_capturer_win_gdi; r=ng This removes disable_composition_ and instead uses the value of composition_func_ to determine whether or not composition is disabled. This is what is done by upstream webrtc.org. We call options.set_disable_effects(false) in desktop_capture_impl.cc. Differential Revision: https://phabricator.services.mozilla.com/D13839 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/b3f5cca4be44c01024b1ef7b5d4951c7297a112a Bug 1497974 - Remove local changes to jitter_buffer.cc; r=pehrsons These modifications are made to code which we do not use and so can be removed. Differential Revision: https://phabricator.services.mozilla.com/D13989 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/2fb1dd0d8344ef24e2e0fca94725bbfaf59aa257 Bug 1512459 - Remove webrtc sndio audio device; r=padenot This code is unused and can be removed. Differential Revision: https://phabricator.services.mozilla.com/D13929 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/fa0a179388e96b1a47eeef2fda9676812c244d3b Bug 1497650 - Remove 100 bytes added to CalcBufferSize in vp8_impl.cc; r=ng In Bug 919979 we added 100 bytes to the size returned by CalcBufferSize to work around an error with the calculated buffer size with small resolutions. I verified that this extra buffer is no longer required with a modified mochitest. Given the age of the bug this was working around, I don't think a permanent test is required to prevent regressions from upstream. Differential Revision: https://phabricator.services.mozilla.com/D14076 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/b20329b1ec0565b3b94db73e13a9c49e43c418c3 Bug 1368816 - Enable VideoCaptureExternalTest Rotation gtest; r=ng This test started failing after the 57 update and started passing again after the 64 update, so we might as well enable it. Differential Revision: https://phabricator.services.mozilla.com/D13803 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/65a44b43b7b69c066abcb864076003252abc475e Bug 1497573 - Remove DesktopCapturer::Stop; r=ng Differential Revision: https://phabricator.services.mozilla.com/D14066 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/0d9c607f26195b7f63cca847224bcd137f73720d Bug 1497619 - Restore thread check in process_thread_impl.cc; r=ng Not not really needed. Differential Revision: https://phabricator.services.mozilla.com/D14097 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/923373fdf5e50d44c895141dc1db74709d6610fe Bug 1497992 - Remove VideoReceiver::Reset; r=pehrsons This ends up calling VCMReceiver::Reset() which resets the state of the VCMJitterBuffer. We no longer use VCMJitterBuffer, which is the old jitter buffer implementation, so this code no longer has any effect and can be removed. Differential Revision: https://phabricator.services.mozilla.com/D14185 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/9e526b3093ee60791cf9c436ea06b6665eb5ef74 Bug 1497610 - Remove IsNewerOrSameTimestamp; r=bwc The affected functions are only used by VCMJitterBuffer, which is the older jitter buffer that is no longer in use. We can safely remove these modifications. Differential Revision: https://phabricator.services.mozilla.com/D14485 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/5ed0ed11b23d82ee026244a9a48e522fe38335e2 Bug 1498253 - Remove mozAvSyncDelay and mozJitterBufferDelay; r=ng The value for mozAvSyncDelay has been broken since the branch 57 update (Bug 1341285). We added SetCurrentSyncOffset() but never called it from anywhere. In the future we should be getting stats from AudioReceiveStream rather than modifying the channel code, the delay_estimate_ms field provides almost the same information. Since we're attempting to get rid of moz prefixed stats, it makes sense to just remove this code rather than fix it. The associated telemetry code has been broken since Bug 1341285 as well so I think it is safe to remove. Differential Revision: https://phabricator.services.mozilla.com/D14462 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/80e86c169d202e724cda74bbd9535b2d5236305b Bug 1498205 - Move PlatformUIThread from rtc_base to video_engine; r=pehrsons PlatformUIThread is only used by the video_engine code, so it makes sense to move it there rather than maintain it as a diff against upstream webrtc.org. Differential Revision: https://phabricator.services.mozilla.com/D13531 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/65bf3e37a4409f3ca0350366d7be19368adfa21b Bug 1497602 - Enable DirectX screen capturer on Windows; r=pehrsons This enables support for the DirectX screen capturer. We use the default DesktopCaptureOptions which do not set the option to use the DirectX screen capturer so this change will have no effect with the current code. For what it's worth, I tested enabling the DirectX option and it worked fine on my system, but I don't see any reason to not follow the defaults provided by webrtc.org in this case. Differential Revision: https://phabricator.services.mozilla.com/D13303 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/eb07312cfbe868780ebed84fc83e5a5470e81fb4 Bug 1439997 - Remove old mac video capture code; r=jib This code is no longer used and has been removed upstream. We can remove it as well. Differential Revision: https://phabricator.services.mozilla.com/D15196 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/e79251fa381cfc9f3425f6a746ac8d8c22046d6b Bug 1376873 - Updates to Android video capture; r=pehrsons Differential Revision: https://phabricator.services.mozilla.com/D7452 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/1e6d72de0587d24c20fefc142591d8b47c363f89 Bug 1578073 - Move android video capture code to dom/media/systemservices; r=jib Although originally part of webrtc.org, this code has subsequently been removed by upstream. Moving it to under dom/media should make it clearer that this is code that we are maintaining and simplify future upstream merges. Differential Revision: https://phabricator.services.mozilla.com/D61850 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/46c21affcbc14da30abb03b10573076aee6341c0 Bug 1652552 - Remove remaining application capture code; r=jib Differential Revision: https://phabricator.services.mozilla.com/D83491 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/26eee332d844bd3f9479d1db92d2f000255664c1 Bug 1846358 - revert mozilla-specific b2g related change in generic_decoder.cc kDecoderFrameMemoryLength. r=ng,webrtc-reviewers Differential Revision: https://phabricator.services.mozilla.com/D184983 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/478632b0cc4982639276a4a817165ac49ca8fb6e Bug 1846875 - remove redundant divide by zero protection in libwebrtc's merge.cc r=ng,webrtc-reviewers Differential Revision: https://phabricator.services.mozilla.com/D185236 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/a777f43c4d9cabe80f2fc3aea6bf95c7e3e9c4c1 Bug 1846590 - move SetCaptureAndroidVM declaration from libwebrtc video_capture.h to our VideoEngine.cpp r=ng,webrtc-reviewers Differential Revision: https://phabricator.services.mozilla.com/D185076 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/0b9ef0f6bf04851bcc8bbe9beb88362eb1659a50 Bug 1847466 - remove work-around for missing v4l2_capability::bus_info in v412loopback driver. r=jesup,pehrsons,webrtc-reviewers Added in Bug 861280, but should no longer be necessary after fixes in upstream v4l2loopback commits (fc4c173, fe03e4f, c3b1eaa). https://github.com/umlaeute/v4l2loopback/commit/fc4c173 https://github.com/umlaeute/v4l2loopback/commit/fe03e4f https://github.com/umlaeute/v4l2loopback/commit/c3b1eaa Differential Revision: https://phabricator.services.mozilla.com/D185518 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/d054dde5c370feb3ee9c9f9159b512333b3554ac Bug 1846636 - restore ScreenCapturerWinMagnifier destructor to upstream version. r=ng,webrtc-reviewers Differential Revision: https://phabricator.services.mozilla.com/D185109 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/b50be8861ca0a4f9e6777e9333a9e483bdb57bf9 Bug 1376873 - Fix up logging in WebrtcLog.cpp; r=ng The webrtc::Trace code is removed by this update. We already had support for LOG (now RTC_LOG) in WebrtcLog.cpp. This removes the trace code from WebRtcLog.cpp and moves the aec logging code from webrtc::Trace to rtc::LogMessage. This also disables logging to stderr in rtc_base/logging.cc. We could disable it using the API, but that happens through peerconnection resulting in some logging occuring during getusermedia. The aec logs were testing with --disable-e10s. Rather than trying to work around sandboxing, I think it makes more sense to fix Bug 1404982 and store the logs in memory for retrieval from about:webrtc. Differential Revision: https://phabricator.services.mozilla.com/D7429 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/e84c60e2c9373f4d2dc24e769375a92c17c2a0ad Bug 1847818 - restore aec logging from about:webrtc. r=ng,webrtc-reviewers Differential Revision: https://phabricator.services.mozilla.com/D185709 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/a67a9e51d8b8597caa1511e2f3b7795e92b07068 Bug 1535584 - Restore UpdateCodecFrameSize to vp9_impl.cc; r=bwc Differential Revision: https://phabricator.services.mozilla.com/D23713 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/0898f9cfe09273e1d86c38abdd576cdf273009f0 Bug 1846850 - remove mozilla-added IsGUIThread asserts from libwebrtc. r=ng,webrtc-reviewers These were added in Bug 1060738 but no longer seem to add value based on crash stats. Differential Revision: https://phabricator.services.mozilla.com/D185222 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/5e6f94c1b7c4491bdab454e24dfdb93eb75f80ca Bug 1846858 - revert changes to libwebrtc's deprecated/session_info.cc since we don't build it. r=ng,webrtc-reviewers Differential Revision: https://phabricator.services.mozilla.com/D185224 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/4836114af07e38525d319b0a2f59f2fd618b7a3b Bug 1847257 - revert an unneccesary change in libwebrtc's window_capturer_x11.cc r=karlt,webrtc-reviewers This small change we've been carrying to when ProcessPendingXEvents is called in WindowCapturerLinux::Capture should not be necessary. Differential Revision: https://phabricator.services.mozilla.com/D185449 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/9633cb1dde33ecbab435012c4ae1456a4ae79a42 Bug 1847984 - remove mozilla-specific null FILE* checks in apm_data_dumper.h r=ng,webrtc-reviewers Since upstream commit 4bc60452f7 ApmDataDumper::GetRawFile does a release assert if FILE* is null so our mozilla-specific mods to check for valid FILE pointers are no longer needed. Differential Revision: https://phabricator.services.mozilla.com/D185838 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/53ecaeda76c3613b90d3a1c3348f0d903a054821 Bug 1848045 - removing mozilla output directory handling code from apm_data_dumper. r=ng,webrtc-reviewers Upstream added the capability to set the output directory in commit 4bc60452f7 so we can revert to using upstream's version instead of ours. Differential Revision: https://phabricator.services.mozilla.com/D185863 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/48217906ac982e129b5eedf07e90904396c31ed4 Bug 1847833 - remove aec log output size limiting code from libwebrtc's apm_data_dumper. r=ng,webrtc-reviewers Differential Revision: https://phabricator.services.mozilla.com/D185930 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/7622e6dddeec583e5839b5432d436d85c356f6c3 Bug 1847833 - aec_debug_size_, aec_debug_size(), set_aec_debug_size(uint32_t size) are no longer used. r=ng,webrtc-reviewers Differential Revision: https://phabricator.services.mozilla.com/D185931 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/525d71640bb7be400040131a5b1a16652c881a0f Bug 1850146 - remove unnecessary libwebrtc changes in jvm_android.cc. r?dbaker! After landing Bug 1826428 to remove jvm_android.cc from the build and giving time for that to simmer for a while with no known effects, we can remove our modifications. Differential Revision: https://phabricator.services.mozilla.com/D186855 Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/fc01107426c3adebb169f19efba72a91be19f613 --- api/rtp_headers.cc | 3 +- api/rtp_headers.h | 17 +- api/rtp_parameters.cc | 3 +- call/BUILD.gn | 4 +- call/video_receive_stream.h | 2 + modules/audio_coding/acm2/acm_receiver.h | 12 +- modules/audio_coding/neteq/dtmf_buffer.cc | 6 +- modules/desktop_capture/desktop_capturer.h | 1 + .../desktop_capture/fake_desktop_capturer.cc | 4 +- .../linux/x11/mouse_cursor_monitor_x11.cc | 4 +- .../linux/x11/screen_capturer_x11.cc | 2 +- .../linux/x11/window_capturer_x11.cc | 9 + .../linux/x11/window_capturer_x11.h | 4 + .../desktop_capture/linux/x11/x_error_trap.cc | 68 ++++--- .../desktop_capture/linux/x11/x_error_trap.h | 29 ++- .../win/screen_capture_utils.cc | 2 +- modules/rtp_rtcp/source/rtcp_sender.cc | 2 +- .../rtp_rtcp/source/rtp_header_extensions.cc | 39 ++++ .../rtp_rtcp/source/rtp_header_extensions.h | 15 ++ modules/rtp_rtcp/source/rtp_packet.cc | 4 + .../rtp_rtcp/source/rtp_packet_unittest.cc | 30 +++ modules/rtp_rtcp/source/rtp_rtcp_config.h | 4 + modules/rtp_rtcp/source/rtp_sender.cc | 4 + modules/video_capture/device_info_impl.cc | 2 +- modules/video_capture/device_info_impl.h | 1 + .../video_capture/linux/device_info_v4l2.cc | 179 +++++++++++++++++- .../video_capture/linux/device_info_v4l2.h | 18 +- modules/video_capture/video_capture.h | 41 +++- .../video_capture/video_capture_factory.cc | 8 - modules/video_capture/video_capture_impl.cc | 34 +++- modules/video_capture/video_capture_impl.h | 6 +- .../codecs/vp9/libvpx_vp9_encoder.cc | 52 +++++ .../codecs/vp9/libvpx_vp9_encoder.h | 4 + rtc_base/BUILD.gn | 6 + rtc_base/logging.cc | 21 +- rtc_base/logging.h | 9 + test/fuzzers/rtp_packet_fuzzer.cc | 5 + test/vcm_capturer.cc | 2 +- webrtc.gni | 2 +- 39 files changed, 573 insertions(+), 85 deletions(-) diff --git a/api/rtp_headers.cc b/api/rtp_headers.cc index 0573e54684..40d4690397 100644 --- a/api/rtp_headers.cc +++ b/api/rtp_headers.cc @@ -26,7 +26,8 @@ RTPHeaderExtension::RTPHeaderExtension() videoRotation(kVideoRotation_0), hasVideoContentType(false), videoContentType(VideoContentType::UNSPECIFIED), - has_video_timing(false) {} + has_video_timing(false), + csrcAudioLevels() {} RTPHeaderExtension::RTPHeaderExtension(const RTPHeaderExtension& other) = default; diff --git a/api/rtp_headers.h b/api/rtp_headers.h index 5d4d4190d5..9868365f24 100644 --- a/api/rtp_headers.h +++ b/api/rtp_headers.h @@ -89,6 +89,19 @@ inline bool operator!=(const AbsoluteCaptureTime& lhs, return !(lhs == rhs); } +enum { kRtpCsrcSize = 15 }; // RFC 3550 page 13 + +// Audio level of CSRCs See: +// https://tools.ietf.org/html/rfc6465 +struct CsrcAudioLevelList { + CsrcAudioLevelList() : numAudioLevels(0) { } + CsrcAudioLevelList(const CsrcAudioLevelList&) = default; + CsrcAudioLevelList& operator=(const CsrcAudioLevelList&) = default; + uint8_t numAudioLevels; + // arrOfAudioLevels has the same ordering as RTPHeader.arrOfCSRCs + uint8_t arrOfAudioLevels[kRtpCsrcSize]; +}; + struct RTPHeaderExtension { RTPHeaderExtension(); RTPHeaderExtension(const RTPHeaderExtension& other); @@ -144,9 +157,9 @@ struct RTPHeaderExtension { std::string mid; absl::optional color_space; -}; -enum { kRtpCsrcSize = 15 }; // RFC 3550 page 13 + CsrcAudioLevelList csrcAudioLevels; +}; struct RTC_EXPORT RTPHeader { RTPHeader(); diff --git a/api/rtp_parameters.cc b/api/rtp_parameters.cc index 3ff4b58a2e..ad0f3c9396 100644 --- a/api/rtp_parameters.cc +++ b/api/rtp_parameters.cc @@ -160,7 +160,8 @@ bool RtpExtension::IsSupportedForAudio(absl::string_view uri) { uri == webrtc::RtpExtension::kTransportSequenceNumberV2Uri || uri == webrtc::RtpExtension::kMidUri || uri == webrtc::RtpExtension::kRidUri || - uri == webrtc::RtpExtension::kRepairedRidUri; + uri == webrtc::RtpExtension::kRepairedRidUri || + uri == webrtc::RtpExtension::kCsrcAudioLevelsUri; } bool RtpExtension::IsSupportedForVideo(absl::string_view uri) { diff --git a/call/BUILD.gn b/call/BUILD.gn index 613b2b94d2..7c24834f1d 100644 --- a/call/BUILD.gn +++ b/call/BUILD.gn @@ -20,6 +20,7 @@ rtc_library("call_interfaces") { sources = [ "audio_receive_stream.cc", "audio_receive_stream.h", + "audio_send_stream.cc", "audio_send_stream.h", "audio_state.cc", "audio_state.h", @@ -32,9 +33,6 @@ rtc_library("call_interfaces") { "syncable.cc", "syncable.h", ] - if (!build_with_mozilla) { - sources += [ "audio_send_stream.cc" ] - } deps = [ ":audio_sender_interface", diff --git a/call/video_receive_stream.h b/call/video_receive_stream.h index 12f6bf60c8..542067d30c 100644 --- a/call/video_receive_stream.h +++ b/call/video_receive_stream.h @@ -206,6 +206,8 @@ class VideoReceiveStreamInterface : public MediaReceiveStreamInterface { // disabled. KeyFrameReqMethod keyframe_method = KeyFrameReqMethod::kPliRtcp; + bool tmmbr = false; + // See LntfConfig for description. LntfConfig lntf; diff --git a/modules/audio_coding/acm2/acm_receiver.h b/modules/audio_coding/acm2/acm_receiver.h index 820150aede..39653be00b 100644 --- a/modules/audio_coding/acm2/acm_receiver.h +++ b/modules/audio_coding/acm2/acm_receiver.h @@ -18,6 +18,7 @@ #include #include #include +#include #include "absl/types/optional.h" #include "api/array_view.h" @@ -230,12 +231,15 @@ class AcmReceiver { mutable Mutex mutex_; absl::optional last_decoder_ RTC_GUARDED_BY(mutex_); - ACMResampler resampler_ RTC_GUARDED_BY(mutex_); - std::unique_ptr last_audio_buffer_ RTC_GUARDED_BY(mutex_); - CallStatistics call_stats_ RTC_GUARDED_BY(mutex_); + ACMResampler resampler_; + + // After construction, this is only ever touched on the thread that calls + // AcmReceiver::GetAudio, and only modified in this method. + std::unique_ptr last_audio_buffer_; + CallStatistics call_stats_; const std::unique_ptr neteq_; // NetEq is thread-safe; no lock needed. Clock& clock_; - bool resampled_last_output_frame_ RTC_GUARDED_BY(mutex_); + std::atomic resampled_last_output_frame_; }; } // namespace acm2 diff --git a/modules/audio_coding/neteq/dtmf_buffer.cc b/modules/audio_coding/neteq/dtmf_buffer.cc index 9f78aca6e2..115bfcf97b 100644 --- a/modules/audio_coding/neteq/dtmf_buffer.cc +++ b/modules/audio_coding/neteq/dtmf_buffer.cc @@ -193,7 +193,11 @@ bool DtmfBuffer::Empty() const { } int DtmfBuffer::SetSampleRate(int fs_hz) { - if (fs_hz != 8000 && fs_hz != 16000 && fs_hz != 32000 && fs_hz != 48000) { + if (fs_hz != 8000 && + fs_hz != 16000 && + fs_hz != 32000 && + fs_hz != 44100 && + fs_hz != 48000) { return kInvalidSampleRate; } max_extrapolation_samples_ = 7 * fs_hz / 100; diff --git a/modules/desktop_capture/desktop_capturer.h b/modules/desktop_capture/desktop_capturer.h index 9c7ecc78f4..2c9c419bcd 100644 --- a/modules/desktop_capture/desktop_capturer.h +++ b/modules/desktop_capture/desktop_capturer.h @@ -82,6 +82,7 @@ class RTC_EXPORT DesktopCapturer { struct Source { // The unique id to represent a Source of current DesktopCapturer. SourceId id; + pid_t pid; // Title of the window or screen in UTF-8 encoding, maybe empty. This field // should not be used to identify a source. diff --git a/modules/desktop_capture/fake_desktop_capturer.cc b/modules/desktop_capture/fake_desktop_capturer.cc index f9d9dbd2c4..67149bfcb9 100644 --- a/modules/desktop_capture/fake_desktop_capturer.cc +++ b/modules/desktop_capture/fake_desktop_capturer.cc @@ -72,8 +72,8 @@ void FakeDesktopCapturer::SetSharedMemoryFactory( } bool FakeDesktopCapturer::GetSourceList(DesktopCapturer::SourceList* sources) { - sources->push_back({kWindowId, "A-Fake-DesktopCapturer-Window"}); - sources->push_back({kScreenId}); + sources->push_back({kWindowId, 1, "A-Fake-DesktopCapturer-Window"}); + sources->push_back({kScreenId, 1}); return true; } diff --git a/modules/desktop_capture/linux/x11/mouse_cursor_monitor_x11.cc b/modules/desktop_capture/linux/x11/mouse_cursor_monitor_x11.cc index d9c7635c1d..d4b85af6bd 100644 --- a/modules/desktop_capture/linux/x11/mouse_cursor_monitor_x11.cc +++ b/modules/desktop_capture/linux/x11/mouse_cursor_monitor_x11.cc @@ -38,6 +38,7 @@ namespace { // searches up the list of the windows to find the root child that corresponds // to `window`. Window GetTopLevelWindow(Display* display, Window window) { + webrtc::XErrorTrap error_trap(display); while (true) { // If the window is in WithdrawnState then look at all of its children. ::Window root, parent; @@ -104,7 +105,7 @@ MouseCursorMonitorX11::~MouseCursorMonitorX11() { } void MouseCursorMonitorX11::Init(Callback* callback, Mode mode) { - // Init can be called only once per instance of MouseCursorMonitor. + // Init can be called only if not started RTC_DCHECK(!callback_); RTC_DCHECK(callback); @@ -116,6 +117,7 @@ void MouseCursorMonitorX11::Init(Callback* callback, Mode mode) { if (have_xfixes_) { // Register for changes to the cursor shape. + XErrorTrap error_trap(display()); XFixesSelectCursorInput(display(), window_, XFixesDisplayCursorNotifyMask); x_display_->AddEventHandler(xfixes_event_base_ + XFixesCursorNotify, this); diff --git a/modules/desktop_capture/linux/x11/screen_capturer_x11.cc b/modules/desktop_capture/linux/x11/screen_capturer_x11.cc index d5dcd7af86..fa6334e8ba 100644 --- a/modules/desktop_capture/linux/x11/screen_capturer_x11.cc +++ b/modules/desktop_capture/linux/x11/screen_capturer_x11.cc @@ -302,7 +302,7 @@ bool ScreenCapturerX11::GetSourceList(SourceList* sources) { char* monitor_title = XGetAtomName(display(), m.name); // Note name is an X11 Atom used to id the monitor. - sources->push_back({static_cast(m.name), monitor_title}); + sources->push_back({static_cast(m.name), 0, monitor_title}); XFree(monitor_title); } diff --git a/modules/desktop_capture/linux/x11/window_capturer_x11.cc b/modules/desktop_capture/linux/x11/window_capturer_x11.cc index b55f7e8fa9..2b1392ced0 100644 --- a/modules/desktop_capture/linux/x11/window_capturer_x11.cc +++ b/modules/desktop_capture/linux/x11/window_capturer_x11.cc @@ -57,6 +57,7 @@ bool WindowCapturerX11::GetSourceList(SourceList* sources) { return GetWindowList(&atom_cache_, [this, sources](::Window window) { Source w; w.id = window; + w.pid = (pid_t)GetWindowProcessID(window); if (this->GetWindowTitle(window, &w.title)) { sources->push_back(w); } @@ -237,6 +238,14 @@ bool WindowCapturerX11::GetWindowTitle(::Window window, std::string* title) { return result; } +int WindowCapturerX11::GetWindowProcessID(::Window window) { + // Get _NET_WM_PID property of the window. + Atom process_atom = XInternAtom(display(), "_NET_WM_PID", True); + XWindowProperty process_id(display(), window, process_atom); + + return process_id.is_valid() ? *process_id.data() : 0; +} + // static std::unique_ptr WindowCapturerX11::CreateRawWindowCapturer( const DesktopCaptureOptions& options) { diff --git a/modules/desktop_capture/linux/x11/window_capturer_x11.h b/modules/desktop_capture/linux/x11/window_capturer_x11.h index ac591c272e..cfd29eca66 100644 --- a/modules/desktop_capture/linux/x11/window_capturer_x11.h +++ b/modules/desktop_capture/linux/x11/window_capturer_x11.h @@ -22,6 +22,7 @@ #include "modules/desktop_capture/desktop_capturer.h" #include "modules/desktop_capture/desktop_geometry.h" #include "modules/desktop_capture/linux/x11/shared_x_display.h" +#include "modules/desktop_capture/linux/x11/x_window_property.h" #include "modules/desktop_capture/linux/x11/window_finder_x11.h" #include "modules/desktop_capture/linux/x11/x_atom_cache.h" #include "modules/desktop_capture/linux/x11/x_server_pixel_buffer.h" @@ -57,6 +58,9 @@ class WindowCapturerX11 : public DesktopCapturer, // Returns window title for the specified X `window`. bool GetWindowTitle(::Window window, std::string* title); + // Returns the id of the owning process. + int GetWindowProcessID(::Window window); + Callback* callback_ = nullptr; rtc::scoped_refptr x_display_; diff --git a/modules/desktop_capture/linux/x11/x_error_trap.cc b/modules/desktop_capture/linux/x11/x_error_trap.cc index 24c2065111..3314dd286c 100644 --- a/modules/desktop_capture/linux/x11/x_error_trap.cc +++ b/modules/desktop_capture/linux/x11/x_error_trap.cc @@ -12,48 +12,58 @@ #include -#include +#include #include "rtc_base/checks.h" -namespace webrtc { - -namespace { - -static int g_last_xserver_error_code = 0; -static std::atomic g_display_for_error_handler = nullptr; -Mutex* AcquireMutex() { - static Mutex* mutex = new Mutex(); - return mutex; -} +namespace webrtc { -int XServerErrorHandler(Display* display, XErrorEvent* error_event) { - RTC_DCHECK_EQ(display, g_display_for_error_handler.load()); - g_last_xserver_error_code = error_event->error_code; - return 0; +Bool XErrorTrap::XServerErrorHandler(Display* display, xReply* rep, + char* /* buf */, int /* len */, + XPointer data) { + XErrorTrap* self = reinterpret_cast(data); + if (rep->generic.type != X_Error || + // Overflow-safe last_request_read <= last_ignored_request_ for skipping + // async replies from requests before XErrorTrap was created. + self->last_ignored_request_ - display->last_request_read < + std::numeric_limits::max() >> 1) + return False; + self->last_xserver_error_code_ = rep->error.errorCode; + return True; } -} // namespace - -XErrorTrap::XErrorTrap(Display* display) : mutex_lock_(AcquireMutex()) { - // We don't expect this class to be used in a nested fashion so therefore - // g_display_for_error_handler should never be valid here. - RTC_DCHECK(!g_display_for_error_handler.load()); - RTC_DCHECK(display); - g_display_for_error_handler.store(display); - g_last_xserver_error_code = 0; - original_error_handler_ = XSetErrorHandler(&XServerErrorHandler); +XErrorTrap::XErrorTrap(Display* display) + : display_(display), + last_xserver_error_code_(0), + enabled_(true) { + // Use async_handlers instead of XSetErrorHandler(). async_handlers can + // remain in place and then be safely removed at the right time even if a + // handler change happens concurrently on another thread. async_handlers + // are processed first and so can prevent errors reaching the global + // XSetErrorHandler handler. They also will not see errors from or affect + // handling of errors on other Displays, which may be processed on other + // threads. + LockDisplay(display); + async_handler_.next = display->async_handlers; + async_handler_.handler = XServerErrorHandler; + async_handler_.data = reinterpret_cast(this); + display->async_handlers = &async_handler_; + last_ignored_request_ = display->request; + UnlockDisplay(display); } int XErrorTrap::GetLastErrorAndDisable() { - g_display_for_error_handler.store(nullptr); - XSetErrorHandler(original_error_handler_); - return g_last_xserver_error_code; + assert(enabled_); + enabled_ = false; + LockDisplay(display_); + DeqAsyncHandler(display_, &async_handler_); + UnlockDisplay(display_); + return last_xserver_error_code_; } XErrorTrap::~XErrorTrap() { - if (g_display_for_error_handler.load() != nullptr) + if (enabled_) GetLastErrorAndDisable(); } diff --git a/modules/desktop_capture/linux/x11/x_error_trap.h b/modules/desktop_capture/linux/x11/x_error_trap.h index 1f21ab969c..df7e86bf03 100644 --- a/modules/desktop_capture/linux/x11/x_error_trap.h +++ b/modules/desktop_capture/linux/x11/x_error_trap.h @@ -11,30 +11,39 @@ #ifndef MODULES_DESKTOP_CAPTURE_LINUX_X11_X_ERROR_TRAP_H_ #define MODULES_DESKTOP_CAPTURE_LINUX_X11_X_ERROR_TRAP_H_ -#include - -#include "rtc_base/synchronization/mutex.h" +#include +#undef max // Xlibint.h defines this and it breaks std::max +#undef min // Xlibint.h defines this and it breaks std::min namespace webrtc { -// Helper class that registers an X Window error handler. Caller can use +// Helper class that registers X Window error handler. Caller can use // GetLastErrorAndDisable() to get the last error that was caught, if any. +// An XErrorTrap may be constructed on any thread, but errors are collected +// from all threads and so |display| should be used only on one thread. +// Other Displays are unaffected. class XErrorTrap { public: explicit XErrorTrap(Display* display); + ~XErrorTrap(); XErrorTrap(const XErrorTrap&) = delete; XErrorTrap& operator=(const XErrorTrap&) = delete; - ~XErrorTrap(); - - // Returns the last error if one was caught, otherwise 0. Also unregisters the - // error handler and replaces it with `original_error_handler_`. + // Returns last error and removes unregisters the error handler. + // Must not be called more than once. int GetLastErrorAndDisable(); private: - MutexLock mutex_lock_; - XErrorHandler original_error_handler_ = nullptr; + static Bool XServerErrorHandler(Display* display, xReply* rep, + char* /* buf */, int /* len */, + XPointer data); + + _XAsyncHandler async_handler_; + Display* display_; + unsigned long last_ignored_request_; + int last_xserver_error_code_; + bool enabled_; }; } // namespace webrtc diff --git a/modules/desktop_capture/win/screen_capture_utils.cc b/modules/desktop_capture/win/screen_capture_utils.cc index 3745e9cba5..f68cfb94c1 100644 --- a/modules/desktop_capture/win/screen_capture_utils.cc +++ b/modules/desktop_capture/win/screen_capture_utils.cc @@ -52,7 +52,7 @@ bool GetScreenList(DesktopCapturer::SourceList* screens, continue; } - screens->push_back({device_index, std::string()}); + screens->push_back({device_index, 0, std::string()}); if (device_names) { device_names->push_back(rtc::ToUtf8(device.DeviceName)); } diff --git a/modules/rtp_rtcp/source/rtcp_sender.cc b/modules/rtp_rtcp/source/rtcp_sender.cc index de68885519..099b0be1a3 100644 --- a/modules/rtp_rtcp/source/rtcp_sender.cc +++ b/modules/rtp_rtcp/source/rtcp_sender.cc @@ -200,7 +200,7 @@ void RTCPSender::SetRTCPStatus(RtcpMode new_method) { next_time_to_send_rtcp_ = absl::nullopt; } else if (method_ == RtcpMode::kOff) { // When switching on, reschedule the next packet - SetNextRtcpSendEvaluationDuration(report_interval_ / 2); + SetNextRtcpSendEvaluationDuration(RTCP_INTERVAL_RAPID_SYNC_MS / 2); } method_ = new_method; } diff --git a/modules/rtp_rtcp/source/rtp_header_extensions.cc b/modules/rtp_rtcp/source/rtp_header_extensions.cc index e42a84bd06..b86a7d775c 100644 --- a/modules/rtp_rtcp/source/rtp_header_extensions.cc +++ b/modules/rtp_rtcp/source/rtp_header_extensions.cc @@ -423,6 +423,45 @@ bool PlayoutDelayLimits::Write(rtc::ArrayView data, return true; } +// CSRCAudioLevel +// Sample Audio Level Encoding Using the One-Byte Header Format +// Note that the range of len is 1 to 15 which is encoded as 0 to 14 +// 0 1 2 3 +// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ +// | ID | len=2 |0| level 1 |0| level 2 |0| level 3 | +// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ + + +constexpr RTPExtensionType CsrcAudioLevel::kId; +constexpr const char* CsrcAudioLevel::kUri; + +bool CsrcAudioLevel::Parse(rtc::ArrayView data, + CsrcAudioLevelList* csrcAudioLevels) { + if (data.size() < 1 || data.size() > kRtpCsrcSize) + return false; + csrcAudioLevels->numAudioLevels = data.size(); + for(uint8_t i = 0; i < csrcAudioLevels->numAudioLevels; i++) { + // Ensure range is 0 to 127 inclusive + csrcAudioLevels->arrOfAudioLevels[i] = 0x7f & data[i]; + } + return true; +} + +size_t CsrcAudioLevel::ValueSize(const CsrcAudioLevelList& csrcAudioLevels) { + return csrcAudioLevels.numAudioLevels; +} + +bool CsrcAudioLevel::Write(rtc::ArrayView data, + const CsrcAudioLevelList& csrcAudioLevels) { + RTC_DCHECK_GE(csrcAudioLevels.numAudioLevels, 0); + for(uint8_t i = 0; i < csrcAudioLevels.numAudioLevels; i++) { + data[i] = csrcAudioLevels.arrOfAudioLevels[i] & 0x7f; + } + // This extension if used must have at least one audio level + return csrcAudioLevels.numAudioLevels; +} + // Video Content Type. // // E.g. default video or screenshare. diff --git a/modules/rtp_rtcp/source/rtp_header_extensions.h b/modules/rtp_rtcp/source/rtp_header_extensions.h index 739d4765d0..fff7db0294 100644 --- a/modules/rtp_rtcp/source/rtp_header_extensions.h +++ b/modules/rtp_rtcp/source/rtp_header_extensions.h @@ -298,6 +298,21 @@ class ColorSpaceExtension { static size_t WriteLuminance(uint8_t* data, float f, int denominator); }; +class CsrcAudioLevel { + public: + static constexpr RTPExtensionType kId = kRtpExtensionCsrcAudioLevel; + static constexpr absl::string_view Uri() { + return RtpExtension::kCsrcAudioLevelsUri; + } + static constexpr const char* kUri = + "urn:ietf:params:rtp-hdrext:csrc-audio-level"; + + static bool Parse(rtc::ArrayView data, + CsrcAudioLevelList* csrcAudioLevels); + static size_t ValueSize(const CsrcAudioLevelList& csrcAudioLevels); + static bool Write(rtc::ArrayView data, const CsrcAudioLevelList& csrcAudioLevels); +}; + // Base extension class for RTP header extensions which are strings. // Subclasses must defined kId and kUri static constexpr members. class BaseRtpStringExtension { diff --git a/modules/rtp_rtcp/source/rtp_packet.cc b/modules/rtp_rtcp/source/rtp_packet.cc index 2a95a3a816..b152cdbd9e 100644 --- a/modules/rtp_rtcp/source/rtp_packet.cc +++ b/modules/rtp_rtcp/source/rtp_packet.cc @@ -205,6 +205,10 @@ void RtpPacket::ZeroMutableExtensions() { // Non-mutable extension. Don't change it. break; } + case RTPExtensionType::kRtpExtensionCsrcAudioLevel: { + // TODO: This is a Mozilla addition, we need to add a handler for this. + RTC_CHECK(false); + } } } } diff --git a/modules/rtp_rtcp/source/rtp_packet_unittest.cc b/modules/rtp_rtcp/source/rtp_packet_unittest.cc index ac464493b8..44f1a9e742 100644 --- a/modules/rtp_rtcp/source/rtp_packet_unittest.cc +++ b/modules/rtp_rtcp/source/rtp_packet_unittest.cc @@ -123,6 +123,18 @@ constexpr uint8_t kPacketWithMid[] = { 0xbe, 0xde, 0x00, 0x01, 0xb2, 'm', 'i', 'd'}; +constexpr uint8_t kCsrcAudioLevelExtensionId = 0xc; +constexpr uint8_t kCsrcAudioLevelsSize = 4; +constexpr uint8_t kCsrcAudioLevels[] = {0x7f, 0x00, 0x10, 0x08}; +constexpr uint8_t kPacketWithCsrcAudioLevels[] = { + 0x90, kPayloadType, kSeqNumFirstByte, kSeqNumSecondByte, + 0x65, 0x43, 0x12, 0x78, + 0x12, 0x34, 0x56, 0x78, + 0xbe, 0xde, 0x00, 0x02, + (kCsrcAudioLevelExtensionId << 4) | (kCsrcAudioLevelsSize - 1), + 0x7f, 0x00, 0x10, + 0x08, 0x00, 0x00, 0x00}; + constexpr uint32_t kCsrcs[] = {0x34567890, 0x32435465}; constexpr uint8_t kPayload[] = {'p', 'a', 'y', 'l', 'o', 'a', 'd'}; constexpr uint8_t kPacketPaddingSize = 8; @@ -397,6 +409,24 @@ TEST(RtpPacketTest, FailsToSetUnregisteredExtension) { EXPECT_EQ(packet.GetExtension(), absl::nullopt); } +TEST(RtpPacketTest, CreateWithDynamicSizedExtensionCsrcAudioLevel) { + RtpPacketToSend::ExtensionManager extensions; + extensions.Register(kCsrcAudioLevelExtensionId); + RtpPacketToSend packet(&extensions); + packet.SetPayloadType(kPayloadType); + packet.SetSequenceNumber(kSeqNum); + packet.SetTimestamp(kTimestamp); + packet.SetSsrc(kSsrc); + CsrcAudioLevelList levels; + levels.numAudioLevels = kCsrcAudioLevelsSize; + for (uint8_t i = 0; i < kCsrcAudioLevelsSize; i++) { + levels.arrOfAudioLevels[i] = kCsrcAudioLevels[i]; + } + packet.SetExtension(levels); + EXPECT_THAT(kPacketWithCsrcAudioLevels, + ElementsAreArray(packet.data(), packet.size())); +} + TEST(RtpPacketTest, SetReservedExtensionsAfterPayload) { const size_t kPayloadSize = 4; RtpPacketToSend::ExtensionManager extensions; diff --git a/modules/rtp_rtcp/source/rtp_rtcp_config.h b/modules/rtp_rtcp/source/rtp_rtcp_config.h index 0b87d6d065..d69ae9420b 100644 --- a/modules/rtp_rtcp/source/rtp_rtcp_config.h +++ b/modules/rtp_rtcp/source/rtp_rtcp_config.h @@ -11,11 +11,15 @@ #ifndef MODULES_RTP_RTCP_SOURCE_RTP_RTCP_CONFIG_H_ #define MODULES_RTP_RTCP_SOURCE_RTP_RTCP_CONFIG_H_ +#include "api/units/time_delta.h" + // Configuration file for RTP utilities (RTPSender, RTPReceiver ...) namespace webrtc { constexpr int kDefaultMaxReorderingThreshold = 50; // In sequence numbers. constexpr int kRtcpMaxNackFields = 253; +constexpr TimeDelta RTCP_INTERVAL_RAPID_SYNC_MS = + TimeDelta::Millis(100); // RFX 6051 constexpr int RTCP_MAX_REPORT_BLOCKS = 31; // RFC 3550 page 37 } // namespace webrtc diff --git a/modules/rtp_rtcp/source/rtp_sender.cc b/modules/rtp_rtcp/source/rtp_sender.cc index d899b4f44e..f4ba024444 100644 --- a/modules/rtp_rtcp/source/rtp_sender.cc +++ b/modules/rtp_rtcp/source/rtp_sender.cc @@ -128,6 +128,10 @@ bool IsNonVolatile(RTPExtensionType type) { case kRtpExtensionNumberOfExtensions: RTC_DCHECK_NOTREACHED(); return false; + case kRtpExtensionCsrcAudioLevel: + // TODO: Mozilla implement for CsrcAudioLevel + RTC_CHECK(false); + return false; } RTC_CHECK_NOTREACHED(); } diff --git a/modules/video_capture/device_info_impl.cc b/modules/video_capture/device_info_impl.cc index ff32a78580..7cccdb51a7 100644 --- a/modules/video_capture/device_info_impl.cc +++ b/modules/video_capture/device_info_impl.cc @@ -65,7 +65,7 @@ int32_t DeviceInfoImpl::GetCapability(const char* deviceUniqueIdUTF8, // Make sure the number is valid if (deviceCapabilityNumber >= (unsigned int)_captureCapabilities.size()) { - RTC_LOG(LS_ERROR) << "Invalid deviceCapabilityNumber " + RTC_LOG(LS_ERROR) << deviceUniqueIdUTF8 << " Invalid deviceCapabilityNumber " << deviceCapabilityNumber << ">= number of capabilities (" << _captureCapabilities.size() << ")."; return -1; diff --git a/modules/video_capture/device_info_impl.h b/modules/video_capture/device_info_impl.h index 546265049c..8acbef6d69 100644 --- a/modules/video_capture/device_info_impl.h +++ b/modules/video_capture/device_info_impl.h @@ -42,6 +42,7 @@ class DeviceInfoImpl : public VideoCaptureModule::DeviceInfo { /* Initialize this object*/ virtual int32_t Init() = 0; + int32_t Refresh() override { return 0; } /* * Fills the member variable _captureCapabilities with capabilities for the * given device name. diff --git a/modules/video_capture/linux/device_info_v4l2.cc b/modules/video_capture/linux/device_info_v4l2.cc index a472e41a41..7397a10625 100644 --- a/modules/video_capture/linux/device_info_v4l2.cc +++ b/modules/video_capture/linux/device_info_v4l2.cc @@ -45,15 +45,187 @@ #define V4L2_PIX_FMT_RGBA32 v4l2_fourcc('A', 'B', '2', '4') #endif +#ifdef WEBRTC_LINUX +#define EVENT_SIZE ( sizeof (struct inotify_event) ) +#define BUF_LEN ( 1024 * ( EVENT_SIZE + 16 ) ) +#endif + namespace webrtc { namespace videocapturemodule { -DeviceInfoV4l2::DeviceInfoV4l2() : DeviceInfoImpl() {} +#ifdef WEBRTC_LINUX +void DeviceInfoV4l2::HandleEvent(inotify_event* event, int fd) +{ + if (event->mask & IN_CREATE) { + if (fd == _fd_v4l || fd == _fd_snd) { + DeviceChange(); + } else if ((event->mask & IN_ISDIR) && (fd == _fd_dev)) { + if (_wd_v4l < 0) { + // Sometimes inotify_add_watch failed if we call it immediately after receiving this event + // Adding 5ms delay to let file system settle down + usleep(5*1000); + _wd_v4l = inotify_add_watch(_fd_v4l, "/dev/v4l/by-path/", IN_CREATE | IN_DELETE | IN_DELETE_SELF); + if (_wd_v4l >= 0) { + DeviceChange(); + } + } + if (_wd_snd < 0) { + usleep(5*1000); + _wd_snd = inotify_add_watch(_fd_snd, "/dev/snd/by-path/", IN_CREATE | IN_DELETE | IN_DELETE_SELF); + if (_wd_snd >= 0) { + DeviceChange(); + } + } + } + } else if (event->mask & IN_DELETE) { + if (fd == _fd_v4l || fd == _fd_snd) { + DeviceChange(); + } + } else if (event->mask & IN_DELETE_SELF) { + if (fd == _fd_v4l) { + inotify_rm_watch(_fd_v4l, _wd_v4l); + _wd_v4l = -1; + } else if (fd == _fd_snd) { + inotify_rm_watch(_fd_snd, _wd_snd); + _wd_snd = -1; + } else { + assert(false); + } + } +} + +int DeviceInfoV4l2::EventCheck(int fd) +{ + struct timeval timeout; + fd_set rfds; + + timeout.tv_sec = 0; + timeout.tv_usec = 100000; + + FD_ZERO(&rfds); + FD_SET(fd, &rfds); + + return select(fd+1, &rfds, NULL, NULL, &timeout); +} + +int DeviceInfoV4l2::HandleEvents(int fd) +{ + char buffer[BUF_LEN]; + + ssize_t r = read(fd, buffer, BUF_LEN); + + if (r <= 0) { + return r; + } + + ssize_t buffer_i = 0; + inotify_event* pevent; + size_t eventSize; + int count = 0; + + while (buffer_i < r) + { + pevent = (inotify_event *) (&buffer[buffer_i]); + eventSize = sizeof(inotify_event) + pevent->len; + char event[sizeof(inotify_event) + FILENAME_MAX + 1] // null-terminated + __attribute__ ((aligned(__alignof__(struct inotify_event)))); + + memcpy(event, pevent, eventSize); + + HandleEvent((inotify_event*)(event), fd); + + buffer_i += eventSize; + count++; + } + + return count; +} + +int DeviceInfoV4l2::ProcessInotifyEvents() +{ + while (!_isShutdown) { + if (EventCheck(_fd_dev) > 0) { + if (HandleEvents(_fd_dev) < 0) { + break; + } + } + if (EventCheck(_fd_v4l) > 0) { + if (HandleEvents(_fd_v4l) < 0) { + break; + } + } + if (EventCheck(_fd_snd) > 0) { + if (HandleEvents(_fd_snd) < 0) { + break; + } + } + } + return 0; +} + +void DeviceInfoV4l2::InotifyEventThread(void* obj) +{ + static_cast (obj)->InotifyProcess(); +} + +void DeviceInfoV4l2::InotifyProcess() +{ + _fd_v4l = inotify_init(); + _fd_snd = inotify_init(); + _fd_dev = inotify_init(); + if (_fd_v4l >= 0 && _fd_snd >= 0 && _fd_dev >= 0) { + _wd_v4l = inotify_add_watch(_fd_v4l, "/dev/v4l/by-path/", IN_CREATE | IN_DELETE | IN_DELETE_SELF); + _wd_snd = inotify_add_watch(_fd_snd, "/dev/snd/by-path/", IN_CREATE | IN_DELETE | IN_DELETE_SELF); + _wd_dev = inotify_add_watch(_fd_dev, "/dev/", IN_CREATE); + ProcessInotifyEvents(); + + if (_wd_v4l >= 0) { + inotify_rm_watch(_fd_v4l, _wd_v4l); + } + + if (_wd_snd >= 0) { + inotify_rm_watch(_fd_snd, _wd_snd); + } + + if (_wd_dev >= 0) { + inotify_rm_watch(_fd_dev, _wd_dev); + } + + close(_fd_v4l); + close(_fd_snd); + close(_fd_dev); + } +} +#endif + +DeviceInfoV4l2::DeviceInfoV4l2() : DeviceInfoImpl() +#ifdef WEBRTC_LINUX + , _inotifyEventThread(new rtc::PlatformThread( + InotifyEventThread, this, "InotifyEventThread")) + , _isShutdown(false) +#endif +{ +#ifdef WEBRTC_LINUX + if (_inotifyEventThread) + { + _inotifyEventThread->Start(); + } +} +#endif int32_t DeviceInfoV4l2::Init() { return 0; } -DeviceInfoV4l2::~DeviceInfoV4l2() {} +DeviceInfoV4l2::~DeviceInfoV4l2() { +#ifdef WEBRTC_LINUX + _isShutdown = true; + + if (_inotifyEventThread) { + _inotifyEventThread->Stop(); + _inotifyEventThread = nullptr; + } +#endif +} uint32_t DeviceInfoV4l2::NumberOfDevices() { uint32_t count = 0; @@ -86,7 +258,8 @@ int32_t DeviceInfoV4l2::GetDeviceName(uint32_t deviceNumber, char* deviceUniqueIdUTF8, uint32_t deviceUniqueIdUTF8Length, char* /*productUniqueIdUTF8*/, - uint32_t /*productUniqueIdUTF8Length*/) { + uint32_t /*productUniqueIdUTF8Length*/, + pid_t* /*pid*/) { // Travel through /dev/video [0-63] uint32_t count = 0; char device[20]; diff --git a/modules/video_capture/linux/device_info_v4l2.h b/modules/video_capture/linux/device_info_v4l2.h index fb95a6020d..95432a509d 100644 --- a/modules/video_capture/linux/device_info_v4l2.h +++ b/modules/video_capture/linux/device_info_v4l2.h @@ -15,6 +15,9 @@ #include "modules/video_capture/device_info_impl.h" +#include "rtc_base/platform_thread.h" +#include + namespace webrtc { namespace videocapturemodule { class DeviceInfoV4l2 : public DeviceInfoImpl { @@ -28,7 +31,8 @@ class DeviceInfoV4l2 : public DeviceInfoImpl { char* deviceUniqueIdUTF8, uint32_t deviceUniqueIdUTF8Length, char* productUniqueIdUTF8 = 0, - uint32_t productUniqueIdUTF8Length = 0) override; + uint32_t productUniqueIdUTF8Length = 0, + pid_t* pid=0) override; /* * Fills the membervariable _captureCapabilities with capabilites for the * given device name. @@ -45,6 +49,18 @@ class DeviceInfoV4l2 : public DeviceInfoImpl { private: bool IsDeviceNameMatches(const char* name, const char* deviceUniqueIdUTF8); + +#ifdef WEBRTC_LINUX + void HandleEvent(inotify_event* event, int fd); + int EventCheck(int fd); + int HandleEvents(int fd); + int ProcessInotifyEvents(); + std::unique_ptr _inotifyEventThread; + static void InotifyEventThread(void*); + void InotifyProcess(); + int _fd_v4l, _fd_dev, _wd_v4l, _wd_dev; /* accessed on InotifyEventThread thread */ + std::atomic _isShutdown; +#endif }; } // namespace videocapturemodule } // namespace webrtc diff --git a/modules/video_capture/video_capture.h b/modules/video_capture/video_capture.h index 48920b27c0..f31b239c71 100644 --- a/modules/video_capture/video_capture.h +++ b/modules/video_capture/video_capture.h @@ -15,15 +15,44 @@ #include "api/video/video_sink_interface.h" #include "modules/video_capture/raw_video_sink_interface.h" #include "modules/video_capture/video_capture_defines.h" +#include + +#if defined(ANDROID) +#include +#endif namespace webrtc { +class VideoInputFeedBack +{ +public: + virtual void OnDeviceChange() = 0; +protected: + virtual ~VideoInputFeedBack(){} +}; + class VideoCaptureModule : public RefCountInterface { public: // Interface for receiving information about available camera devices. class DeviceInfo { public: virtual uint32_t NumberOfDevices() = 0; + virtual int32_t Refresh() = 0; + virtual void DeviceChange() { + for (auto inputCallBack : _inputCallBacks) { + inputCallBack->OnDeviceChange(); + } + } + virtual void RegisterVideoInputFeedBack(VideoInputFeedBack* callBack) { + _inputCallBacks.insert(callBack); + } + + virtual void DeRegisterVideoInputFeedBack(VideoInputFeedBack* callBack) { + auto it = _inputCallBacks.find(callBack); + if (it != _inputCallBacks.end()) { + _inputCallBacks.erase(it); + } + } // Returns the available capture devices. // deviceNumber - Index of capture device. @@ -38,7 +67,8 @@ class VideoCaptureModule : public RefCountInterface { char* deviceUniqueIdUTF8, uint32_t deviceUniqueIdUTF8Length, char* productUniqueIdUTF8 = 0, - uint32_t productUniqueIdUTF8Length = 0) = 0; + uint32_t productUniqueIdUTF8Length = 0, + pid_t* pid = 0) = 0; // Returns the number of capabilities this device. virtual int32_t NumberOfCapabilities(const char* deviceUniqueIdUTF8) = 0; @@ -70,6 +100,8 @@ class VideoCaptureModule : public RefCountInterface { uint32_t positionY) = 0; virtual ~DeviceInfo() {} + private: + std::set _inputCallBacks; }; // Register capture data callback @@ -79,11 +111,16 @@ class VideoCaptureModule : public RefCountInterface { RawVideoSinkInterface* dataCallback) = 0; // Remove capture data callback - virtual void DeRegisterCaptureDataCallback() = 0; + virtual void DeRegisterCaptureDataCallback( + rtc::VideoSinkInterface *dataCallback) = 0; // Start capture device virtual int32_t StartCapture(const VideoCaptureCapability& capability) = 0; + virtual int32_t StopCaptureIfAllClientsClose() = 0; + + virtual bool FocusOnSelectedSource() { return false; } + virtual int32_t StopCapture() = 0; // Returns the name of the device used by this module. diff --git a/modules/video_capture/video_capture_factory.cc b/modules/video_capture/video_capture_factory.cc index 563ef5abd2..e085ac2df8 100644 --- a/modules/video_capture/video_capture_factory.cc +++ b/modules/video_capture/video_capture_factory.cc @@ -16,11 +16,7 @@ namespace webrtc { rtc::scoped_refptr VideoCaptureFactory::Create( const char* deviceUniqueIdUTF8) { -#if defined(WEBRTC_ANDROID) || defined(WEBRTC_MAC) - return nullptr; -#else return videocapturemodule::VideoCaptureImpl::Create(deviceUniqueIdUTF8); -#endif } rtc::scoped_refptr VideoCaptureFactory::Create( @@ -37,11 +33,7 @@ rtc::scoped_refptr VideoCaptureFactory::Create( } VideoCaptureModule::DeviceInfo* VideoCaptureFactory::CreateDeviceInfo() { -#if defined(WEBRTC_ANDROID) || defined(WEBRTC_MAC) - return nullptr; -#else return videocapturemodule::VideoCaptureImpl::CreateDeviceInfo(); -#endif } VideoCaptureModule::DeviceInfo* VideoCaptureFactory::CreateDeviceInfo( diff --git a/modules/video_capture/video_capture_impl.cc b/modules/video_capture/video_capture_impl.cc index 428253bf23..66fd0a0ebe 100644 --- a/modules/video_capture/video_capture_impl.cc +++ b/modules/video_capture/video_capture_impl.cc @@ -77,7 +77,6 @@ VideoCaptureImpl::VideoCaptureImpl() _requestedCapability(), _lastProcessTimeNanos(rtc::TimeNanos()), _lastFrameRateCallbackTimeNanos(rtc::TimeNanos()), - _dataCallBack(NULL), _rawDataCallBack(NULL), _lastProcessFrameTimeNanos(rtc::TimeNanos()), _rotateFrame(kVideoRotation_0), @@ -91,7 +90,6 @@ VideoCaptureImpl::VideoCaptureImpl() VideoCaptureImpl::~VideoCaptureImpl() { RTC_DCHECK_RUN_ON(&api_checker_); - DeRegisterCaptureDataCallback(); if (_deviceUniqueId) delete[] _deviceUniqueId; } @@ -100,28 +98,41 @@ void VideoCaptureImpl::RegisterCaptureDataCallback( rtc::VideoSinkInterface* dataCallBack) { MutexLock lock(&api_lock_); RTC_DCHECK(!_rawDataCallBack); - _dataCallBack = dataCallBack; + _dataCallBacks.insert(dataCallBack); } void VideoCaptureImpl::RegisterCaptureDataCallback( RawVideoSinkInterface* dataCallBack) { MutexLock lock(&api_lock_); - RTC_DCHECK(!_dataCallBack); + RTC_DCHECK(_dataCallBacks.empty()); _rawDataCallBack = dataCallBack; } -void VideoCaptureImpl::DeRegisterCaptureDataCallback() { +void VideoCaptureImpl::DeRegisterCaptureDataCallback( + rtc::VideoSinkInterface* dataCallBack) { MutexLock lock(&api_lock_); - _dataCallBack = NULL; + auto it = _dataCallBacks.find(dataCallBack); + if (it != _dataCallBacks.end()) { + _dataCallBacks.erase(it); + } _rawDataCallBack = NULL; } + +int32_t VideoCaptureImpl::StopCaptureIfAllClientsClose() { + if (_dataCallBacks.empty()) { + return StopCapture(); + } else { + return 0; + } +} + int32_t VideoCaptureImpl::DeliverCapturedFrame(VideoFrame& captureFrame) { RTC_CHECK_RUNS_SERIALIZED(&capture_checker_); UpdateFrameCount(); // frame count used for local frame rate callback. - if (_dataCallBack) { - _dataCallBack->OnFrame(captureFrame); + for (auto dataCallBack : _dataCallBacks) { + dataCallBack->OnFrame(captureFrame); } return 0; @@ -229,6 +240,13 @@ int32_t VideoCaptureImpl::IncomingFrame(uint8_t* videoFrame, .build(); captureFrame.set_ntp_time_ms(captureTime); + // This is one ugly hack to let CamerasParent know what rotation + // the frame was captured at. Note that this goes against the intended + // meaning of rotation of the frame (how to rotate it before rendering). + // We do this so CamerasChild can scale to the proper dimensions + // later on in the pipe. + captureFrame.set_rotation(_rotateFrame); + DeliverCapturedFrame(captureFrame); return 0; diff --git a/modules/video_capture/video_capture_impl.h b/modules/video_capture/video_capture_impl.h index 5ec1fd4a83..e46e050609 100644 --- a/modules/video_capture/video_capture_impl.h +++ b/modules/video_capture/video_capture_impl.h @@ -64,8 +64,10 @@ class RTC_EXPORT VideoCaptureImpl : public VideoCaptureModule { rtc::VideoSinkInterface* dataCallback) override; virtual void RegisterCaptureDataCallback( RawVideoSinkInterface* dataCallback) override; - void DeRegisterCaptureDataCallback() override; + void DeRegisterCaptureDataCallback( + rtc::VideoSinkInterface* dataCallback) override; + int32_t StopCaptureIfAllClientsClose() override; int32_t SetCaptureRotation(VideoRotation rotation) override; bool SetApplyRotation(bool enable) override; bool GetApplyRotation() override; @@ -115,7 +117,7 @@ class RTC_EXPORT VideoCaptureImpl : public VideoCaptureModule { // last time the frame rate callback function was called. int64_t _lastFrameRateCallbackTimeNanos RTC_GUARDED_BY(capture_checker_); - rtc::VideoSinkInterface* _dataCallBack RTC_GUARDED_BY(api_lock_); + std::set*> _dataCallBacks RTC_GUARDED_BY(api_lock_); RawVideoSinkInterface* _rawDataCallBack RTC_GUARDED_BY(api_lock_); int64_t _lastProcessFrameTimeNanos RTC_GUARDED_BY(capture_checker_); diff --git a/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.cc b/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.cc index 20c29abc7c..edbe781639 100644 --- a/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.cc +++ b/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.cc @@ -256,6 +256,7 @@ LibvpxVp9Encoder::LibvpxVp9Encoder(const cricket::VideoCodec& codec, first_frame_in_picture_(true), ss_info_needed_(false), force_all_active_layers_(false), + num_cores_(0), is_flexible_mode_(false), variable_framerate_experiment_(ParseVariableFramerateConfig(trials)), variable_framerate_controller_( @@ -580,6 +581,7 @@ int LibvpxVp9Encoder::InitEncode(const VideoCodec* inst, force_key_frame_ = true; pics_since_key_ = 0; + num_cores_ = settings.number_of_cores; scalability_mode_ = inst->GetScalabilityMode(); if (scalability_mode_.has_value()) { @@ -1167,6 +1169,14 @@ int LibvpxVp9Encoder::Encode(const VideoFrame& input_image, config_changed_ = false; } + if (input_image.width() != codec_.width || + input_image.height() != codec_.height) { + int ret = UpdateCodecFrameSize(input_image); + if (ret < 0) { + return ret; + } + } + RTC_DCHECK_EQ(input_image.width(), raw_->d_w); RTC_DCHECK_EQ(input_image.height(), raw_->d_h); @@ -1289,6 +1299,48 @@ int LibvpxVp9Encoder::Encode(const VideoFrame& input_image, return WEBRTC_VIDEO_CODEC_OK; } +int LibvpxVp9Encoder::UpdateCodecFrameSize( + const VideoFrame& input_image) { + RTC_LOG(LS_INFO) << "Reconfiging VP from " << + codec_.width << "x" << codec_.height << " to " << + input_image.width() << "x" << input_image.height(); + // Preserve latest bitrate/framerate setting + // TODO: Mozilla - see below, we need to save more state here. + //uint32_t old_bitrate_kbit = config_->rc_target_bitrate; + //uint32_t old_framerate = codec_.maxFramerate; + + codec_.width = input_image.width(); + codec_.height = input_image.height(); + + vpx_img_free(raw_); + raw_ = vpx_img_wrap(NULL, VPX_IMG_FMT_I420, codec_.width, codec_.height, + 1, NULL); + // Update encoder context for new frame size. + config_->g_w = codec_.width; + config_->g_h = codec_.height; + + // Determine number of threads based on the image size and #cores. + config_->g_threads = NumberOfThreads(codec_.width, codec_.height, + num_cores_); + + // NOTE: We would like to do this the same way vp8 does it + // (with vpx_codec_enc_config_set()), but that causes asserts + // in AQ 3 (cyclic); and in AQ 0 it works, but on a resize to smaller + // than 1/2 x 1/2 original it asserts in convolve(). Given these + // bugs in trying to do it the "right" way, we basically re-do + // the initialization. + vpx_codec_destroy(encoder_); // clean up old state + int result = InitAndSetControlSettings(&codec_); + if (result == WEBRTC_VIDEO_CODEC_OK) { + // TODO: Mozilla rates have become much more complicated, we need to store + // more state or find another way of doing this. + //return SetRates(old_bitrate_kbit, old_framerate); + RTC_CHECK(false); + return WEBRTC_VIDEO_CODEC_UNINITIALIZED; + } + return result; +} + bool LibvpxVp9Encoder::PopulateCodecSpecific(CodecSpecificInfo* codec_specific, absl::optional* spatial_idx, absl::optional* temporal_idx, diff --git a/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.h b/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.h index 3ccaa5fa52..ea4e5810ac 100644 --- a/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.h +++ b/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.h @@ -67,6 +67,9 @@ class LibvpxVp9Encoder : public VP9Encoder { // Call encoder initialize function and set control settings. int InitAndSetControlSettings(const VideoCodec* inst); + // Update frame size for codec. + int UpdateCodecFrameSize(const VideoFrame& input_image); + bool PopulateCodecSpecific(CodecSpecificInfo* codec_specific, absl::optional* spatial_idx, absl::optional* temporal_idx, @@ -148,6 +151,7 @@ class LibvpxVp9Encoder : public VP9Encoder { VideoBitrateAllocation current_bitrate_allocation_; bool ss_info_needed_; bool force_all_active_layers_; + uint8_t num_cores_; std::unique_ptr svc_controller_; absl::optional scalability_mode_; diff --git a/rtc_base/BUILD.gn b/rtc_base/BUILD.gn index 2cf9c11316..b5e15ac2da 100644 --- a/rtc_base/BUILD.gn +++ b/rtc_base/BUILD.gn @@ -463,6 +463,12 @@ rtc_library("logging") { "//third_party/abseil-cpp/absl/types:optional", ] + # Added to allow including apm_data_dumper.h in rtc_base/logging.cc + # for Mozilla controlling aec logging from about:webrtc. + if (build_with_mozilla) { + configs += [ "../modules/audio_processing:apm_debug_dump" ] + } + if (build_with_chromium) { # Dependency on chromium's logging (in //base). deps += [ "//base" ] diff --git a/rtc_base/logging.cc b/rtc_base/logging.cc index 61a3c667ba..ad2303735e 100644 --- a/rtc_base/logging.cc +++ b/rtc_base/logging.cc @@ -44,6 +44,7 @@ static const int kMaxLogLineSize = 1024 - 60; #include "absl/base/attributes.h" #include "absl/strings/string_view.h" #include "api/units/timestamp.h" +#include "modules/audio_processing/logging/apm_data_dumper.h" #include "rtc_base/checks.h" #include "rtc_base/platform_thread_types.h" #include "rtc_base/string_encode.h" @@ -54,6 +55,24 @@ static const int kMaxLogLineSize = 1024 - 60; #include "rtc_base/time_utils.h" namespace rtc { + +bool LogMessage::aec_debug_ = false; +std::string LogMessage::aec_filename_base_; + +void LogMessage::set_aec_debug(bool enable) { + aec_debug_ = enable; + webrtc::ApmDataDumper::SetActivated(aec_debug_); +} + +std::string LogMessage::aec_debug_filename() { + return aec_filename_base_; +} + +void LogMessage::set_aec_debug_filename(const char* filename) { + aec_filename_base_ = filename; + webrtc::ApmDataDumper::SetOutputDirectory(aec_filename_base_); +} + namespace { // By default, release builds don't log, debug builds at info level @@ -114,7 +133,7 @@ std::string LogLineRef::DefaultLogLine() const { // LogMessage ///////////////////////////////////////////////////////////////////////////// -bool LogMessage::log_to_stderr_ = true; +bool LogMessage::log_to_stderr_ = false; // The list of logging streams currently configured. // Note: we explicitly do not clean this up, because of the uncertain ordering diff --git a/rtc_base/logging.h b/rtc_base/logging.h index b171cfe11e..df7f173f58 100644 --- a/rtc_base/logging.h +++ b/rtc_base/logging.h @@ -581,6 +581,12 @@ class LogMessage { } #endif // RTC_LOG_ENABLED() + // Enable dumping of AEC inputs and outputs. Can be changed in mid-call + static void set_aec_debug(bool enable); + static bool aec_debug() { return aec_debug_; } + static std::string aec_debug_filename(); + static void set_aec_debug_filename(const char* filename); + private: friend class LogMessageForTesting; @@ -636,6 +642,9 @@ class LogMessage { // The stringbuilder that buffers the formatted message before output rtc::StringBuilder print_stream_; + + static bool aec_debug_; + static std::string aec_filename_base_; }; ////////////////////////////////////////////////////////////////////// diff --git a/test/fuzzers/rtp_packet_fuzzer.cc b/test/fuzzers/rtp_packet_fuzzer.cc index 60afb986de..0e10a8fa3a 100644 --- a/test/fuzzers/rtp_packet_fuzzer.cc +++ b/test/fuzzers/rtp_packet_fuzzer.cc @@ -164,6 +164,11 @@ void FuzzOneInput(const uint8_t* data, size_t size) { // This extension requires state to read and so complicated that // deserves own fuzzer. break; + case kRtpExtensionCsrcAudioLevel: { + CsrcAudioLevelList levels; + packet.GetExtension(&levels); + break; + } } } diff --git a/test/vcm_capturer.cc b/test/vcm_capturer.cc index 0a9226ef6f..620c1c02f3 100644 --- a/test/vcm_capturer.cc +++ b/test/vcm_capturer.cc @@ -83,7 +83,7 @@ void VcmCapturer::Destroy() { return; vcm_->StopCapture(); - vcm_->DeRegisterCaptureDataCallback(); + vcm_->DeRegisterCaptureDataCallback(this); // Release reference to VCM. vcm_ = nullptr; } diff --git a/webrtc.gni b/webrtc.gni index 447aae4096..277c12c054 100644 --- a/webrtc.gni +++ b/webrtc.gni @@ -126,7 +126,7 @@ declare_args() { # Selects whether debug dumps for the audio processing module # should be generated. - apm_debug_dump = false + apm_debug_dump = build_with_mozilla # Selects whether the audio processing module should be excluded. rtc_exclude_audio_processing_module = false