summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/moz-patch-stack/0001.patch
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
commit6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch)
treea68f146d7fa01f0134297619fbe7e33db084e0aa /third_party/libwebrtc/moz-patch-stack/0001.patch
parentInitial commit. (diff)
downloadthunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz
thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/libwebrtc/moz-patch-stack/0001.patch')
-rw-r--r--third_party/libwebrtc/moz-patch-stack/0001.patch1950
1 files changed, 1950 insertions, 0 deletions
diff --git a/third_party/libwebrtc/moz-patch-stack/0001.patch b/third_party/libwebrtc/moz-patch-stack/0001.patch
new file mode 100644
index 0000000000..19eea5558b
--- /dev/null
+++ b/third_party/libwebrtc/moz-patch-stack/0001.patch
@@ -0,0 +1,1950 @@
+From: Dan Minor <dminor@mozilla.com>
+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
+---
+ 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/audio_coding/neteq/merge.cc | 6 +
+ .../logging/apm_data_dumper.cc | 23 ++-
+ .../logging/apm_data_dumper.h | 67 ++++--
+ 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 | 12 +-
+ .../linux/x11/window_capturer_x11.h | 4 +
+ .../desktop_capture/linux/x11/x_error_trap.cc | 70 ++++---
+ .../desktop_capture/linux/x11/x_error_trap.h | 29 ++-
+ .../mouse_cursor_monitor_win.cc | 7 +-
+ .../win/screen_capture_utils.cc | 3 +-
+ .../win/screen_capturer_win_gdi.cc | 1 +
+ .../win/screen_capturer_win_magnifier.cc | 16 +-
+ 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 | 2 +
+ modules/rtp_rtcp/source/rtp_sender.cc | 4 +
+ modules/utility/source/jvm_android.cc | 28 ++-
+ modules/video_capture/device_info_impl.cc | 2 +-
+ modules/video_capture/device_info_impl.h | 1 +
+ .../video_capture/linux/device_info_v4l2.cc | 193 +++++++++++++++++-
+ .../video_capture/linux/device_info_v4l2.h | 18 +-
+ .../video_capture/linux/video_capture_v4l2.cc | 7 +
+ modules/video_capture/video_capture.h | 45 +++-
+ .../video_capture/video_capture_factory.cc | 8 -
+ modules/video_capture/video_capture_impl.cc | 36 +++-
+ modules/video_capture/video_capture_impl.h | 6 +-
+ .../codecs/vp9/libvpx_vp9_encoder.cc | 2 +
+ .../codecs/vp9/libvpx_vp9_encoder.h | 4 +
+ modules/video_coding/generic_decoder.cc | 5 +-
+ modules/video_coding/session_info.cc | 32 ++-
+ test/fuzzers/rtp_packet_fuzzer.cc | 5 +
+ test/vcm_capturer.cc | 2 +-
+ 45 files changed, 652 insertions(+), 134 deletions(-)
+
+diff --git a/api/rtp_headers.cc b/api/rtp_headers.cc
+index e0ad9eb26e..8e1efc7262 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 743fd6d1b6..261c984d05 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<ColorSpace> 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 c48b8da02c..c1d12e5d8d 100644
+--- a/api/rtp_parameters.cc
++++ b/api/rtp_parameters.cc
+@@ -148,7 +148,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 f4c3295ff5..0e52e8fb3f 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 0fa257e5ba..15b313a3b9 100644
+--- a/call/video_receive_stream.h
++++ b/call/video_receive_stream.h
+@@ -199,6 +199,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 18b662aed0..a61247627f 100644
+--- a/modules/audio_coding/acm2/acm_receiver.h
++++ b/modules/audio_coding/acm2/acm_receiver.h
+@@ -18,6 +18,7 @@
+ #include <string>
+ #include <utility>
+ #include <vector>
++#include <atomic>
+
+ #include "absl/types/optional.h"
+ #include "api/array_view.h"
+@@ -215,12 +216,15 @@ class AcmReceiver {
+
+ mutable Mutex mutex_;
+ absl::optional<DecoderInfo> last_decoder_ RTC_GUARDED_BY(mutex_);
+- ACMResampler resampler_ RTC_GUARDED_BY(mutex_);
+- std::unique_ptr<int16_t[]> 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<int16_t[]> last_audio_buffer_;
++ CallStatistics call_stats_;
+ const std::unique_ptr<NetEq> neteq_; // NetEq is thread-safe; no lock needed.
+ Clock* const clock_;
+- bool resampled_last_output_frame_ RTC_GUARDED_BY(mutex_);
++ std::atomic<bool> 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/audio_coding/neteq/merge.cc b/modules/audio_coding/neteq/merge.cc
+index 22cf6a7754..0aec6d2597 100644
+--- a/modules/audio_coding/neteq/merge.cc
++++ b/modules/audio_coding/neteq/merge.cc
+@@ -213,6 +213,12 @@ int16_t Merge::SignalScaling(const int16_t* input,
+ // Adjust muting factor if new vector is more or less of the BGN energy.
+ const auto mod_input_length = rtc::SafeMin<size_t>(
+ 64 * rtc::dchecked_cast<size_t>(fs_mult_), input_length);
++
++ // Missing input, do no muting
++ if (mod_input_length == 0) {
++ return 16384;
++ }
++
+ const int16_t expanded_max =
+ WebRtcSpl_MaxAbsValueW16(expanded_signal, mod_input_length);
+ int32_t factor =
+diff --git a/modules/audio_processing/logging/apm_data_dumper.cc b/modules/audio_processing/logging/apm_data_dumper.cc
+index 65d2167d37..f787b65604 100644
+--- a/modules/audio_processing/logging/apm_data_dumper.cc
++++ b/modules/audio_processing/logging/apm_data_dumper.cc
+@@ -35,14 +35,20 @@ std::string FormFileName(absl::string_view output_dir,
+ int instance_index,
+ int reinit_index,
+ absl::string_view suffix) {
+- char buf[1024];
+- rtc::SimpleStringBuilder ss(buf);
+- if (!output_dir.empty()) {
+- ss << output_dir;
+- if (output_dir.back() != kPathDelimiter) {
+- ss << kPathDelimiter;
+- }
++#ifdef WEBRTC_WIN
++ char sep = '\\';
++#else
++ char sep = '/';
++#endif
++
++ std::stringstream ss;
++ std::string base = webrtc::Trace::aec_debug_filename();
++ ss << base;
++
++ if (base.length() && base.back() != sep) {
++ ss << sep;
+ }
++
+ ss << name << "_" << instance_index << "-" << reinit_index << suffix;
+ return ss.str();
+ }
+@@ -52,7 +58,8 @@ std::string FormFileName(absl::string_view output_dir,
+
+ #if WEBRTC_APM_DEBUG_DUMP == 1
+ ApmDataDumper::ApmDataDumper(int instance_index)
+- : instance_index_(instance_index) {}
++ : instance_index_(instance_index)
++ , debug_written_(0) {}
+ #else
+ ApmDataDumper::ApmDataDumper(int instance_index) {}
+ #endif
+diff --git a/modules/audio_processing/logging/apm_data_dumper.h b/modules/audio_processing/logging/apm_data_dumper.h
+index 4ab6baad83..aa8496819b 100644
+--- a/modules/audio_processing/logging/apm_data_dumper.h
++++ b/modules/audio_processing/logging/apm_data_dumper.h
+@@ -41,7 +41,7 @@ namespace webrtc {
+ // Functor used to use as a custom deleter in the map of file pointers to raw
+ // files.
+ struct RawFileCloseFunctor {
+- void operator()(FILE* f) const { fclose(f); }
++ void operator()(FILE* f) const { if (f) fclose(f); }
+ };
+ #endif
+
+@@ -100,6 +100,7 @@ class ApmDataDumper {
+ void InitiateNewSetOfRecordings() {
+ #if WEBRTC_APM_DEBUG_DUMP == 1
+ ++recording_set_index_;
++ debug_written_ = 0;
+ #endif
+ }
+
+@@ -114,7 +115,9 @@ class ApmDataDumper {
+
+ if (recording_activated_) {
+ FILE* file = GetRawFile(name);
+- fwrite(&v, sizeof(v), 1, file);
++ if (file) {
++ fwrite(&v, sizeof(v), 1, file);
++ }
+ }
+ #endif
+ }
+@@ -129,7 +132,9 @@ class ApmDataDumper {
+
+ if (recording_activated_) {
+ FILE* file = GetRawFile(name);
+- fwrite(v, sizeof(v[0]), v_length, file);
++ if (file) {
++ fwrite(v, sizeof(v[0]), v_length, file);
++ }
+ }
+ #endif
+ }
+@@ -156,7 +161,9 @@ class ApmDataDumper {
+
+ if (recording_activated_) {
+ FILE* file = GetRawFile(name);
+- fwrite(&v, sizeof(v), 1, file);
++ if (file) {
++ fwrite(&v, sizeof(v), 1, file);
++ }
+ }
+ #endif
+ }
+@@ -171,7 +178,9 @@ class ApmDataDumper {
+
+ if (recording_activated_) {
+ FILE* file = GetRawFile(name);
+- fwrite(v, sizeof(v[0]), v_length, file);
++ if (file) {
++ fwrite(v, sizeof(v[0]), v_length, file);
++ }
+ }
+ #endif
+ }
+@@ -210,9 +219,11 @@ class ApmDataDumper {
+
+ if (recording_activated_) {
+ FILE* file = GetRawFile(name);
+- for (size_t k = 0; k < v_length; ++k) {
+- int16_t value = static_cast<int16_t>(v[k]);
+- fwrite(&value, sizeof(value), 1, file);
++ if (file) {
++ for (size_t k = 0; k < v_length; ++k) {
++ int16_t value = static_cast<int16_t>(v[k]);
++ fwrite(&value, sizeof(value), 1, file);
++ }
+ }
+ }
+ #endif
+@@ -240,7 +251,9 @@ class ApmDataDumper {
+
+ if (recording_activated_) {
+ FILE* file = GetRawFile(name);
+- fwrite(&v, sizeof(v), 1, file);
++ if (file) {
++ fwrite(&v, sizeof(v), 1, file);
++ }
+ }
+ #endif
+ }
+@@ -255,7 +268,9 @@ class ApmDataDumper {
+
+ if (recording_activated_) {
+ FILE* file = GetRawFile(name);
+- fwrite(v, sizeof(v[0]), v_length, file);
++ if (file) {
++ fwrite(v, sizeof(v[0]), v_length, file);
++ }
+ }
+ #endif
+ }
+@@ -282,7 +297,9 @@ class ApmDataDumper {
+
+ if (recording_activated_) {
+ FILE* file = GetRawFile(name);
+- fwrite(&v, sizeof(v), 1, file);
++ if (file) {
++ fwrite(&v, sizeof(v), 1, file);
++ }
+ }
+ #endif
+ }
+@@ -297,7 +314,9 @@ class ApmDataDumper {
+
+ if (recording_activated_) {
+ FILE* file = GetRawFile(name);
+- fwrite(v, sizeof(v[0]), v_length, file);
++ if (file) {
++ fwrite(v, sizeof(v[0]), v_length, file);
++ }
+ }
+ #endif
+ }
+@@ -311,7 +330,9 @@ class ApmDataDumper {
+
+ if (recording_activated_) {
+ FILE* file = GetRawFile(name);
+- fwrite(&v, sizeof(v), 1, file);
++ if (file) {
++ fwrite(&v, sizeof(v), 1, file);
++ }
+ }
+ #endif
+ }
+@@ -326,7 +347,9 @@ class ApmDataDumper {
+
+ if (recording_activated_) {
+ FILE* file = GetRawFile(name);
+- fwrite(v, sizeof(v[0]), v_length, file);
++ if (file) {
++ fwrite(v, sizeof(v[0]), v_length, file);
++ }
+ }
+ #endif
+ }
+@@ -369,6 +392,12 @@ class ApmDataDumper {
+ WavWriter* file = GetWavFile(name, sample_rate_hz, num_channels,
+ WavFile::SampleFormat::kFloat);
+ file->WriteSamples(v, v_length);
++ // Cheat and use aec_near as a stand-in for "size of the largest file"
++ // in the dump. We're looking to limit the total time, and that's a
++ // reasonable stand-in.
++ if (strcmp(name, "aec_near") == 0) {
++ updateDebugWritten(v_length * sizeof(float));
++ }
+ }
+ #endif
+ }
+@@ -405,6 +434,16 @@ class ApmDataDumper {
+ int sample_rate_hz,
+ int num_channels,
+ WavFile::SampleFormat format);
++
++ uint32_t debug_written_ = 0;
++
++ void updateDebugWritten(uint32_t amount) {
++ debug_written_ += amount;
++ if (debug_written_ >= webrtc::Trace::aec_debug_size()) {
++ SetActivated(false);
++ }
++ }
++
+ #endif
+ };
+
+diff --git a/modules/desktop_capture/desktop_capturer.h b/modules/desktop_capture/desktop_capturer.h
+index d336723f18..6909a57891 100644
+--- a/modules/desktop_capture/desktop_capturer.h
++++ b/modules/desktop_capture/desktop_capturer.h
+@@ -79,6 +79,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<SourceId>(m.name), monitor_title});
++ sources->push_back({static_cast<SourceId>(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..2e17d44c0a 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);
+ }
+@@ -140,6 +141,7 @@ void WindowCapturerX11::Start(Callback* callback) {
+
+ void WindowCapturerX11::CaptureFrame() {
+ TRACE_EVENT0("webrtc", "WindowCapturerX11::CaptureFrame");
++ x_display_->ProcessPendingXEvents();
+
+ if (!x_server_pixel_buffer_.IsWindowValid()) {
+ RTC_LOG(LS_ERROR) << "The window is no longer valid.";
+@@ -147,8 +149,6 @@ void WindowCapturerX11::CaptureFrame() {
+ return;
+ }
+
+- x_display_->ProcessPendingXEvents();
+-
+ if (!has_composite_extension_) {
+ // Without the Xcomposite extension we capture when the whole window is
+ // visible on screen and not covered by any other window. This is not
+@@ -237,6 +237,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<uint32_t> process_id(display(), window, process_atom);
++
++ return process_id.is_valid() ? *process_id.data() : 0;
++}
++
+ // static
+ std::unique_ptr<DesktopCapturer> 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<SharedXDisplay> 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 94e3a03c73..3314dd286c 100644
+--- a/modules/desktop_capture/linux/x11/x_error_trap.cc
++++ b/modules/desktop_capture/linux/x11/x_error_trap.cc
+@@ -10,50 +10,60 @@
+
+ #include "modules/desktop_capture/linux/x11/x_error_trap.h"
+
+-#include <atomic>
+-
+ #include <stddef.h>
+
+-#include "rtc_base/checks.h"
+-
+-namespace webrtc {
++#include <limits>
+
+-namespace {
++#include "rtc_base/checks.h"
+
+-static int g_last_xserver_error_code = 0;
+-static std::atomic<Display*> 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<XErrorTrap*>(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<unsigned long>::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<XPointer>(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 <X11/Xlib.h>
+-
+-#include "rtc_base/synchronization/mutex.h"
++#include <X11/Xlibint.h>
++#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/mouse_cursor_monitor_win.cc b/modules/desktop_capture/mouse_cursor_monitor_win.cc
+index c892d59955..18ef43eeb4 100644
+--- a/modules/desktop_capture/mouse_cursor_monitor_win.cc
++++ b/modules/desktop_capture/mouse_cursor_monitor_win.cc
+@@ -88,6 +88,7 @@ MouseCursorMonitorWin::~MouseCursorMonitorWin() {
+ void MouseCursorMonitorWin::Init(Callback* callback, Mode mode) {
+ RTC_DCHECK(!callback_);
+ RTC_DCHECK(callback);
++ RTC_DCHECK(IsGUIThread(false));
+
+ callback_ = callback;
+ mode_ = mode;
+@@ -96,6 +97,8 @@ void MouseCursorMonitorWin::Init(Callback* callback, Mode mode) {
+ }
+
+ void MouseCursorMonitorWin::Capture() {
++// TODO: Bug 1666266. Commented out to pass new tests added in bug 1634044.
++// RTC_DCHECK(IsGUIThread(false));
+ RTC_DCHECK(callback_);
+
+ CURSORINFO cursor_info;
+@@ -107,7 +110,8 @@ void MouseCursorMonitorWin::Capture() {
+ }
+
+ if (!IsSameCursorShape(cursor_info, last_cursor_)) {
+- if (cursor_info.flags == CURSOR_SUPPRESSED) {
++ // Mozilla - CURSOR_SUPPRESSED is win8 and above; so we seem not to be able to see the symbol
++ if (cursor_info.flags != CURSOR_SHOWING) {
+ // The cursor is intentionally hidden now, send an empty bitmap.
+ last_cursor_ = cursor_info;
+ callback_->OnMouseCursor(new MouseCursor(
+@@ -168,6 +172,7 @@ void MouseCursorMonitorWin::Capture() {
+ }
+
+ DesktopRect MouseCursorMonitorWin::GetScreenRect() {
++ RTC_DCHECK(IsGUIThread(false));
+ RTC_DCHECK_NE(screen_, kInvalidScreenId);
+ if (screen_ == kFullDesktopScreenId) {
+ return DesktopRect::MakeXYWH(GetSystemMetrics(SM_XVIRTUALSCREEN),
+diff --git a/modules/desktop_capture/win/screen_capture_utils.cc b/modules/desktop_capture/win/screen_capture_utils.cc
+index 3d4aecf14d..1dc2918d08 100644
+--- a/modules/desktop_capture/win/screen_capture_utils.cc
++++ b/modules/desktop_capture/win/screen_capture_utils.cc
+@@ -51,7 +51,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));
+ }
+@@ -147,6 +147,7 @@ DesktopRect GetFullscreenRect() {
+
+ DesktopRect GetScreenRect(const DesktopCapturer::SourceId screen,
+ const std::wstring& device_key) {
++ RTC_DCHECK(IsGUIThread(false));
+ if (screen == kFullDesktopScreenId) {
+ return GetFullscreenRect();
+ }
+diff --git a/modules/desktop_capture/win/screen_capturer_win_gdi.cc b/modules/desktop_capture/win/screen_capturer_win_gdi.cc
+index 57b1f71b0d..c6d4a75931 100644
+--- a/modules/desktop_capture/win/screen_capturer_win_gdi.cc
++++ b/modules/desktop_capture/win/screen_capturer_win_gdi.cc
+@@ -186,6 +186,7 @@ void ScreenCapturerWinGdi::PrepareCaptureResources() {
+ }
+
+ bool ScreenCapturerWinGdi::CaptureImage() {
++ RTC_DCHECK(IsGUIThread(false));
+ DesktopRect screen_rect =
+ GetScreenRect(current_screen_id_, current_device_key_);
+ if (screen_rect.is_empty()) {
+diff --git a/modules/desktop_capture/win/screen_capturer_win_magnifier.cc b/modules/desktop_capture/win/screen_capturer_win_magnifier.cc
+index 214eb0e463..ce747e0141 100644
+--- a/modules/desktop_capture/win/screen_capturer_win_magnifier.cc
++++ b/modules/desktop_capture/win/screen_capturer_win_magnifier.cc
+@@ -49,17 +49,25 @@ ScreenCapturerWinMagnifier::ScreenCapturerWinMagnifier() = default;
+ ScreenCapturerWinMagnifier::~ScreenCapturerWinMagnifier() {
+ // DestroyWindow must be called before MagUninitialize. magnifier_window_ is
+ // destroyed automatically when host_window_ is destroyed.
+- if (host_window_)
++ if (host_window_) {
+ DestroyWindow(host_window_);
++ host_window_ = NULL;
++ }
+
+- if (magnifier_initialized_)
++ if (magnifier_initialized_) {
+ mag_uninitialize_func_();
++ magnifier_initialized_ = false;
++ }
+
+- if (mag_lib_handle_)
++ if (mag_lib_handle_) {
+ FreeLibrary(mag_lib_handle_);
++ mag_lib_handle_ = NULL;
++ }
+
+- if (desktop_dc_)
++ if (desktop_dc_) {
+ ReleaseDC(NULL, desktop_dc_);
++ desktop_dc_ = NULL;
++ }
+ }
+
+ void ScreenCapturerWinMagnifier::Start(Callback* callback) {
+diff --git a/modules/rtp_rtcp/source/rtcp_sender.cc b/modules/rtp_rtcp/source/rtcp_sender.cc
+index 7983371097..983851a55b 100644
+--- a/modules/rtp_rtcp/source/rtcp_sender.cc
++++ b/modules/rtp_rtcp/source/rtcp_sender.cc
+@@ -201,7 +201,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 81961c69aa..a57d9e7f62 100644
+--- a/modules/rtp_rtcp/source/rtp_header_extensions.cc
++++ b/modules/rtp_rtcp/source/rtp_header_extensions.cc
+@@ -446,6 +446,45 @@ bool PlayoutDelayLimits::Write(rtc::ArrayView<uint8_t> 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<const uint8_t> 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<uint8_t> 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 d80e0da4f8..89c73955a2 100644
+--- a/modules/rtp_rtcp/source/rtp_header_extensions.h
++++ b/modules/rtp_rtcp/source/rtp_header_extensions.h
+@@ -292,6 +292,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<const uint8_t> data,
++ CsrcAudioLevelList* csrcAudioLevels);
++ static size_t ValueSize(const CsrcAudioLevelList& csrcAudioLevels);
++ static bool Write(rtc::ArrayView<uint8_t> 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 6c7dff322b..9495841984 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 1d51d75662..41bc114efb 100644
+--- a/modules/rtp_rtcp/source/rtp_packet_unittest.cc
++++ b/modules/rtp_rtcp/source/rtp_packet_unittest.cc
+@@ -121,6 +121,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;
+@@ -385,6 +397,24 @@ TEST(RtpPacketTest, FailsToSetUnregisteredExtension) {
+ EXPECT_EQ(packet.GetExtension<TransportSequenceNumber>(), absl::nullopt);
+ }
+
++TEST(RtpPacketTest, CreateWithDynamicSizedExtensionCsrcAudioLevel) {
++ RtpPacketToSend::ExtensionManager extensions;
++ extensions.Register<CsrcAudioLevel>(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<CsrcAudioLevel>(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 3e6aa3baae..9ac7696ce9 100644
+--- a/modules/rtp_rtcp/source/rtp_rtcp_config.h
++++ b/modules/rtp_rtcp/source/rtp_rtcp_config.h
+@@ -18,6 +18,8 @@ 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 TimeDelta RTCP_SEND_BEFORE_KEY_FRAME = TimeDelta::Millis(100);
+ 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 ac3bd55e05..0ed7243d0a 100644
+--- a/modules/rtp_rtcp/source/rtp_sender.cc
++++ b/modules/rtp_rtcp/source/rtp_sender.cc
+@@ -132,6 +132,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/utility/source/jvm_android.cc b/modules/utility/source/jvm_android.cc
+index ee9930bcaa..39ef12f428 100644
+--- a/modules/utility/source/jvm_android.cc
++++ b/modules/utility/source/jvm_android.cc
+@@ -18,6 +18,16 @@
+ #include "rtc_base/logging.h"
+ #include "rtc_base/platform_thread.h"
+
++namespace mozilla {
++namespace jni {
++jclass GetClassRef(JNIEnv* aEnv, const char* aClassName);
++}
++}
++
++#define TAG "JVM"
++#define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)
++#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__)
++
+ namespace webrtc {
+
+ JVM* g_jvm;
+@@ -40,14 +50,11 @@ struct {
+ void LoadClasses(JNIEnv* jni) {
+ RTC_LOG(LS_INFO) << "LoadClasses:";
+ for (auto& c : loaded_classes) {
+- jclass localRef = FindClass(jni, c.name);
+- RTC_LOG(LS_INFO) << "name: " << c.name;
+- CHECK_EXCEPTION(jni) << "Error during FindClass: " << c.name;
+- RTC_CHECK(localRef) << c.name;
+- jclass globalRef = reinterpret_cast<jclass>(jni->NewGlobalRef(localRef));
+- CHECK_EXCEPTION(jni) << "Error during NewGlobalRef: " << c.name;
+- RTC_CHECK(globalRef) << c.name;
+- c.clazz = globalRef;
++ ALOGD("name: %s", c.name);
++ jclass clsRef = mozilla::jni::GetClassRef(jni, c.name);
++ RTC_CHECK(clsRef) << c.name;
++ c.clazz = static_cast<jclass>(jni->NewGlobalRef(clsRef));
++ jni->DeleteLocalRef(clsRef);
+ }
+ }
+
+@@ -216,8 +223,9 @@ std::string JNIEnvironment::JavaToStdString(const jstring& j_string) {
+
+ // static
+ void JVM::Initialize(JavaVM* jvm) {
+- RTC_LOG(LS_INFO) << "JVM::Initialize";
+- RTC_CHECK(!g_jvm);
++ if (g_jvm) {
++ return;
++ }
+ g_jvm = new JVM(jvm);
+ }
+
+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 5af58015a7..28395a5a05 100644
+--- a/modules/video_capture/linux/device_info_v4l2.cc
++++ b/modules/video_capture/linux/device_info_v4l2.cc
+@@ -27,15 +27,187 @@
+ #include "modules/video_capture/video_capture_impl.h"
+ #include "rtc_base/logging.h"
+
++#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<DeviceInfoLinux*> (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;
+@@ -68,15 +240,17 @@ 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];
+ int fd = -1;
+ bool found = false;
+ struct v4l2_capability cap;
+- for (int n = 0; n < 64; n++) {
+- snprintf(device, sizeof(device), "/dev/video%d", n);
++ int device_index;
++ for (device_index = 0; device_index < 64; device_index++) {
++ sprintf(device, "/dev/video%d", device_index);
+ if ((fd = open(device, O_RDONLY)) != -1) {
+ // query device capabilities and make sure this is a video capture device
+ if (ioctl(fd, VIDIOC_QUERYCAP, &cap) < 0 ||
+@@ -129,8 +303,15 @@ int32_t DeviceInfoV4l2::GetDeviceName(uint32_t deviceNumber,
+ RTC_LOG(LS_INFO) << "buffer passed is too small";
+ return -1;
+ }
++ } else {
++ // if there's no bus info to use for uniqueId, invent one - and it has to be repeatable
++ if (snprintf(deviceUniqueIdUTF8,
++ deviceUniqueIdUTF8Length, "fake_%u", device_index) >=
++ (int) deviceUniqueIdUTF8Length)
++ {
++ return -1;
++ }
+ }
+-
+ return 0;
+ }
+
+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 <sys/inotify.h>
++
+ 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<rtc::PlatformThread> _inotifyEventThread;
++ static void InotifyEventThread(void*);
++ void InotifyProcess();
++ int _fd_v4l, _fd_dev, _wd_v4l, _wd_dev; /* accessed on InotifyEventThread thread */
++ std::atomic<bool> _isShutdown;
++#endif
+ };
+ } // namespace videocapturemodule
+ } // namespace webrtc
+diff --git a/modules/video_capture/linux/video_capture_v4l2.cc b/modules/video_capture/linux/video_capture_v4l2.cc
+index 5101a67e0c..1dc13b01aa 100644
+--- a/modules/video_capture/linux/video_capture_v4l2.cc
++++ b/modules/video_capture/linux/video_capture_v4l2.cc
+@@ -50,6 +50,13 @@ int32_t VideoCaptureModuleV4L2::Init(const char* deviceUniqueIdUTF8) {
+ memcpy(_deviceUniqueId, deviceUniqueIdUTF8, len + 1);
+ }
+
++ int device_index;
++ if (sscanf(deviceUniqueIdUTF8,"fake_%d", &device_index) == 1)
++ {
++ _deviceId = device_index;
++ return 0;
++ }
++
+ int fd;
+ char device[32];
+ bool found = false;
+diff --git a/modules/video_capture/video_capture.h b/modules/video_capture/video_capture.h
+index eddc31414a..187eba76a0 100644
+--- a/modules/video_capture/video_capture.h
++++ b/modules/video_capture/video_capture.h
+@@ -15,15 +15,48 @@
+ #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 <set>
++
++#if defined(ANDROID)
++#include <jni.h>
++#endif
+
+ namespace webrtc {
+
++class VideoInputFeedBack
++{
++public:
++ virtual void OnDeviceChange() = 0;
++protected:
++ virtual ~VideoInputFeedBack(){}
++};
++
++#if defined(ANDROID) && !defined(WEBRTC_CHROMIUM_BUILD)
++ int32_t SetCaptureAndroidVM(JavaVM* javaVM);
++#endif
++
+ class VideoCaptureModule : public rtc::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 +71,8 @@ class VideoCaptureModule : public rtc::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 +104,8 @@ class VideoCaptureModule : public rtc::RefCountInterface {
+ uint32_t positionY) = 0;
+
+ virtual ~DeviceInfo() {}
++ private:
++ std::set<VideoInputFeedBack*> _inputCallBacks;
+ };
+
+ // Register capture data callback
+@@ -79,11 +115,16 @@ class VideoCaptureModule : public rtc::RefCountInterface {
+ RawVideoSinkInterface* dataCallback) = 0;
+
+ // Remove capture data callback
+- virtual void DeRegisterCaptureDataCallback() = 0;
++ virtual void DeRegisterCaptureDataCallback(
++ rtc::VideoSinkInterface<VideoFrame> *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 c0e1479caf..e4a46902e0 100644
+--- a/modules/video_capture/video_capture_factory.cc
++++ b/modules/video_capture/video_capture_factory.cc
+@@ -16,19 +16,11 @@ namespace webrtc {
+
+ rtc::scoped_refptr<VideoCaptureModule> VideoCaptureFactory::Create(
+ const char* deviceUniqueIdUTF8) {
+-#if defined(WEBRTC_ANDROID) || defined(WEBRTC_MAC)
+- return nullptr;
+-#else
+ return videocapturemodule::VideoCaptureImpl::Create(deviceUniqueIdUTF8);
+-#endif
+ }
+
+ VideoCaptureModule::DeviceInfo* VideoCaptureFactory::CreateDeviceInfo() {
+-#if defined(WEBRTC_ANDROID) || defined(WEBRTC_MAC)
+- return nullptr;
+-#else
+ return videocapturemodule::VideoCaptureImpl::CreateDeviceInfo();
+-#endif
+ }
+
+ } // namespace webrtc
+diff --git a/modules/video_capture/video_capture_impl.cc b/modules/video_capture/video_capture_impl.cc
+index d539b38264..d5ec4daae1 100644
+--- a/modules/video_capture/video_capture_impl.cc
++++ b/modules/video_capture/video_capture_impl.cc
+@@ -76,7 +76,6 @@ VideoCaptureImpl::VideoCaptureImpl()
+ _requestedCapability(),
+ _lastProcessTimeNanos(rtc::TimeNanos()),
+ _lastFrameRateCallbackTimeNanos(rtc::TimeNanos()),
+- _dataCallBack(NULL),
+ _rawDataCallBack(NULL),
+ _lastProcessFrameTimeNanos(rtc::TimeNanos()),
+ _rotateFrame(kVideoRotation_0),
+@@ -89,7 +88,6 @@ VideoCaptureImpl::VideoCaptureImpl()
+ }
+
+ VideoCaptureImpl::~VideoCaptureImpl() {
+- DeRegisterCaptureDataCallback();
+ if (_deviceUniqueId)
+ delete[] _deviceUniqueId;
+ }
+@@ -98,26 +96,39 @@ void VideoCaptureImpl::RegisterCaptureDataCallback(
+ rtc::VideoSinkInterface<VideoFrame>* 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<VideoFrame>* 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) {
+ UpdateFrameCount(); // frame count used for local frame rate callback.
+
+- if (_dataCallBack) {
+- _dataCallBack->OnFrame(captureFrame);
++ for (auto dataCallBack : _dataCallBacks) {
++ dataCallBack->OnFrame(captureFrame);
+ }
+
+ return 0;
+@@ -204,7 +215,7 @@ int32_t VideoCaptureImpl::IncomingFrame(uint8_t* videoFrame,
+ buffer.get()->StrideV(), 0, 0, // No Cropping
+ width, height, target_width, target_height, rotation_mode,
+ ConvertVideoType(frameInfo.videoType));
+- if (conversionResult < 0) {
++ if (conversionResult != 0) {
+ RTC_LOG(LS_ERROR) << "Failed to convert capture frame from type "
+ << static_cast<int>(frameInfo.videoType) << "to I420.";
+ return -1;
+@@ -219,6 +230,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 fee93396d3..f874580471 100644
+--- a/modules/video_capture/video_capture_impl.h
++++ b/modules/video_capture/video_capture_impl.h
+@@ -55,8 +55,10 @@ class VideoCaptureImpl : public VideoCaptureModule {
+ rtc::VideoSinkInterface<VideoFrame>* dataCallback) override;
+ virtual void RegisterCaptureDataCallback(
+ RawVideoSinkInterface* dataCallback) override;
+- void DeRegisterCaptureDataCallback() override;
++ void DeRegisterCaptureDataCallback(
++ rtc::VideoSinkInterface<VideoFrame>* dataCallback) override;
+
++ int32_t StopCaptureIfAllClientsClose() override;
+ int32_t SetCaptureRotation(VideoRotation rotation) override;
+ bool SetApplyRotation(bool enable) override;
+ bool GetApplyRotation() override;
+@@ -98,7 +100,7 @@ class VideoCaptureImpl : public VideoCaptureModule {
+ // last time the frame rate callback function was called.
+ int64_t _lastFrameRateCallbackTimeNanos;
+
+- rtc::VideoSinkInterface<VideoFrame>* _dataCallBack;
++ std::set<rtc::VideoSinkInterface<VideoFrame>*> _dataCallBacks;
+ RawVideoSinkInterface* _rawDataCallBack;
+
+ int64_t _lastProcessFrameTimeNanos;
+diff --git a/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.cc b/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.cc
+index c2884c0395..35b13058a2 100644
+--- a/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.cc
++++ b/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.cc
+@@ -254,6 +254,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_(
+@@ -577,6 +578,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()) {
+diff --git a/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.h b/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.h
+index 6b662ae8f9..bb871f8498 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<int>* spatial_idx,
+ absl::optional<int>* temporal_idx,
+@@ -150,6 +153,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<ScalableVideoController> svc_controller_;
+ absl::optional<ScalabilityMode> scalability_mode_;
+diff --git a/modules/video_coding/generic_decoder.cc b/modules/video_coding/generic_decoder.cc
+index b660e02b72..54467d1477 100644
+--- a/modules/video_coding/generic_decoder.cc
++++ b/modules/video_coding/generic_decoder.cc
+@@ -32,7 +32,10 @@ namespace webrtc {
+
+ namespace {
+
+-constexpr size_t kDecoderFrameMemoryLength = 10;
++// Changed from 10 to 30 in Mozilla Bug 989944: Increase decode
++// timestamp map to handle delayed decode on 8x10. The map is
++// now a deque (as of libwebrtc upstream commit 1c51ec4d74).
++constexpr size_t kDecoderFrameMemoryLength = 30;
+
+ }
+
+diff --git a/modules/video_coding/session_info.cc b/modules/video_coding/session_info.cc
+index 854230ae0a..e31b8b1d25 100644
+--- a/modules/video_coding/session_info.cc
++++ b/modules/video_coding/session_info.cc
+@@ -210,16 +210,26 @@ size_t VCMSessionInfo::InsertBuffer(uint8_t* frame_buffer,
+ if (h264 && h264->packetization_type == kH264StapA) {
+ size_t required_length = 0;
+ const uint8_t* nalu_ptr = packet_buffer + kH264NALHeaderLengthInBytes;
+- while (nalu_ptr < packet_buffer + packet.sizeBytes) {
++ // Must check that incoming data length doesn't extend past end of buffer.
++ // We allow for 100 bytes of expansion due to startcodes being longer than
++ // length fields.
++ while (nalu_ptr + kLengthFieldLength <= packet_buffer + packet.sizeBytes) {
+ size_t length = BufferToUWord16(nalu_ptr);
+- required_length +=
++ if (nalu_ptr + kLengthFieldLength + length <= packet_buffer + packet.sizeBytes) {
++ required_length +=
+ length + (packet.insertStartCode ? kH264StartCodeLengthBytes : 0);
+- nalu_ptr += kLengthFieldLength + length;
++ nalu_ptr += kLengthFieldLength + length;
++ } else {
++ // Something is very wrong!
++ RTC_LOG(LS_ERROR) << "Failed to insert packet due to corrupt H264 STAP-A";
++ return 0;
++ }
+ }
+ ShiftSubsequentPackets(packet_it, required_length);
+ nalu_ptr = packet_buffer + kH264NALHeaderLengthInBytes;
+ uint8_t* frame_buffer_ptr = frame_buffer + offset;
+- while (nalu_ptr < packet_buffer + packet.sizeBytes) {
++ // we already know we won't go past end-of-buffer
++ while (nalu_ptr + kLengthFieldLength <= packet_buffer + packet.sizeBytes) {
+ size_t length = BufferToUWord16(nalu_ptr);
+ nalu_ptr += kLengthFieldLength;
+ frame_buffer_ptr += Insert(nalu_ptr, length, packet.insertStartCode,
+@@ -447,12 +457,23 @@ int VCMSessionInfo::InsertPacket(const VCMPacket& packet,
+ return -2;
+
+ if (packet.codec() == kVideoCodecH264) {
+- frame_type_ = packet.video_header.frame_type;
++ // H.264 can have leading or trailing non-VCL (Video Coding Layer)
++ // NALUs, such as SPS/PPS/SEI and others. Also, the RTP marker bit is
++ // not reliable for the last packet of a frame (RFC 6184 5.1 - "Decoders
++ // [] MUST NOT rely on this property"), so allow out-of-order packets to
++ // update the first and last seq# range. Also mark as a key frame if
++ // any packet is of that type.
++ if (frame_type_ != VideoFrameType::kVideoFrameKey) {
++ frame_type_ = packet.video_header.frame_type;
++ }
+ if (packet.is_first_packet_in_frame() &&
+ (first_packet_seq_num_ == -1 ||
+ IsNewerSequenceNumber(first_packet_seq_num_, packet.seqNum))) {
+ first_packet_seq_num_ = packet.seqNum;
+ }
++ // Note: the code does *not* currently handle the Marker bit being totally
++ // absent from a frame. It does not, however, depend on it being on the last
++ // packet of the 'frame'/'session'.
+ if (packet.markerBit &&
+ (last_packet_seq_num_ == -1 ||
+ IsNewerSequenceNumber(packet.seqNum, last_packet_seq_num_))) {
+@@ -499,7 +520,6 @@ int VCMSessionInfo::InsertPacket(const VCMPacket& packet,
+
+ size_t returnLength = InsertBuffer(frame_buffer, packet_list_it);
+ UpdateCompleteSession();
+-
+ return static_cast<int>(returnLength);
+ }
+
+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<CsrcAudioLevel>(&levels);
++ break;
++ }
+ }
+ }
+
+diff --git a/test/vcm_capturer.cc b/test/vcm_capturer.cc
+index a037f9eff6..e02fc722b2 100644
+--- a/test/vcm_capturer.cc
++++ b/test/vcm_capturer.cc
+@@ -81,7 +81,7 @@ void VcmCapturer::Destroy() {
+ return;
+
+ vcm_->StopCapture();
+- vcm_->DeRegisterCaptureDataCallback();
++ vcm_->DeRegisterCaptureDataCallback(this);
+ // Release reference to VCM.
+ vcm_ = nullptr;
+ }
+--
+2.34.1
+