Source code
Revision control
Copy as Markdown
Other Tools
From: Dan Minor <dminor@mozilla.com>
Date: Mon, 22 Jan 2018 13:31:00 -0500
MozReview-Commit-ID: 2euYzBEvuNb
Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/28b57e3ba51de982a4663801a3935580114b5477
MozReview-Commit-ID: 1T8mgqdkzq3
Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/93eec571640ee0810da8475ee37e417b88045574
MozReview-Commit-ID: D09534DOVLj
Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/50f89f4e45b0af87fd6aa45aed60f02f3e69b951
Assertions in NetEqImpl::SetSampleRateAndChannels prevent us from requesting
tones at 44100 Hz, so this code can be safely removed.
Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/8ea04ec01e9905d4714aa01ade891d552c56a3a6
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.
Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/647ade4da0fba74a268aab079677cb47f20f036e
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.
Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/0fd399c6caabff60ac0fe53b920b7d26a9806750
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.
Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/b3f5cca4be44c01024b1ef7b5d4951c7297a112a
These modifications are made to code which we do not use and so
can be removed.
Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/2fb1dd0d8344ef24e2e0fca94725bbfaf59aa257
This code is unused and can be removed.
Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/fa0a179388e96b1a47eeef2fda9676812c244d3b
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.
Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/b20329b1ec0565b3b94db73e13a9c49e43c418c3
This test started failing after the 57 update and started passing
again after the 64 update, so we might as well enable it.
Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/65a44b43b7b69c066abcb864076003252abc475e
Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/0d9c607f26195b7f63cca847224bcd137f73720d
Not not really needed.
Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/923373fdf5e50d44c895141dc1db74709d6610fe
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.
Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/9e526b3093ee60791cf9c436ea06b6665eb5ef74
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.
Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/5ed0ed11b23d82ee026244a9a48e522fe38335e2
The value for mozAvSyncDelay has been broken since the branch 57 update
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
Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/80e86c169d202e724cda74bbd9535b2d5236305b
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.
Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/65bf3e37a4409f3ca0350366d7be19368adfa21b
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.
Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/eb07312cfbe868780ebed84fc83e5a5470e81fb4
This code is no longer used and has been removed upstream. We can remove
it as well.
Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/e79251fa381cfc9f3425f6a746ac8d8c22046d6b
Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/1e6d72de0587d24c20fefc142591d8b47c363f89
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.
Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/46c21affcbc14da30abb03b10573076aee6341c0
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
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
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
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
v4l2loopback commits (fc4c173, fe03e4f, c3b1eaa).
Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/d054dde5c370feb3ee9c9f9159b512333b3554ac
Bug 1846636 - restore ScreenCapturerWinMagnifier destructor to upstream version. r=ng,webrtc-reviewers
Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/b50be8861ca0a4f9e6777e9333a9e483bdb57bf9
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
store the logs in memory for retrieval from about:webrtc.
Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/e84c60e2c9373f4d2dc24e769375a92c17c2a0ad
Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/a67a9e51d8b8597caa1511e2f3b7795e92b07068
Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/0898f9cfe09273e1d86c38abdd576cdf273009f0
on crash stats.
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
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.
Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/9633cb1dde33ecbab435012c4ae1456a4ae79a42
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.
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.
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
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
Mercurial Revision: https://hg.mozilla.org/mozilla-central/rev/525d71640bb7be400040131a5b1a16652c881a0f
giving time for that to simmer for a while with no known effects, we
can remove our modifications.
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 | 1 +
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 | 4 +
test/vcm_capturer.cc | 2 +-
webrtc.gni | 2 +-
39 files changed, 565 insertions(+), 81 deletions(-)
diff --git a/api/rtp_headers.cc b/api/rtp_headers.cc
index c272ccae06..0271714c44 100644
--- a/api/rtp_headers.cc
+++ b/api/rtp_headers.cc
@@ -35,7 +35,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 6ba3292fca..5d3a731864 100644
--- a/api/rtp_headers.h
+++ b/api/rtp_headers.h
@@ -113,6 +113,19 @@ inline bool operator!=(const AbsoluteCaptureTime& lhs,
return !(lhs == rhs);
}
+enum { kRtpCsrcSize = 15 }; // RFC 3550 page 13
+
+// Audio level of CSRCs See:
+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);
@@ -171,12 +184,12 @@ struct RTPHeaderExtension {
std::optional<ColorSpace> color_space;
+ CsrcAudioLevelList csrcAudioLevels;
+
private:
std::optional<AudioLevel> audio_level_;
};
-enum { kRtpCsrcSize = 15 }; // RFC 3550 page 13
-
struct RTC_EXPORT RTPHeader {
RTPHeader();
RTPHeader(const RTPHeader& other);
diff --git a/api/rtp_parameters.cc b/api/rtp_parameters.cc
index c919f7c1dd..117aba6a0f 100644
--- a/api/rtp_parameters.cc
+++ b/api/rtp_parameters.cc
@@ -165,7 +165,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 f53d0bdbf6..8f706f8ce3 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 08ac664edc..3b09c2d78c 100644
--- a/call/video_receive_stream.h
+++ b/call/video_receive_stream.h
@@ -232,6 +232,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 47de3bc9fd..26d09c23ee 100644
--- a/modules/audio_coding/acm2/acm_receiver.h
+++ b/modules/audio_coding/acm2/acm_receiver.h
@@ -20,6 +20,7 @@
#include <string>
#include <utility>
#include <vector>
+#include <atomic>
#include "api/array_view.h"
#include "api/audio/audio_frame.h"
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<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..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<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 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 <stddef.h>
-#include <atomic>
+#include <limits>
#include "rtc_base/checks.h"
-namespace webrtc {
-
-namespace {
-
-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/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 51ace1cf75..051d77c4f7 100644
--- a/modules/rtp_rtcp/source/rtcp_sender.cc
+++ b/modules/rtp_rtcp/source/rtcp_sender.cc
@@ -211,7 +211,7 @@ void RTCPSender::SetRTCPStatus(RtcpMode new_method) {
next_time_to_send_rtcp_ = std::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 46c82180eb..bb035729f8 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<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 b8495f4ba6..ed816caa10 100644
--- a/modules/rtp_rtcp/source/rtp_header_extensions.h
+++ b/modules/rtp_rtcp/source/rtp_header_extensions.h
@@ -308,6 +308,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 19372880b2..3192c27a49 100644
--- a/modules/rtp_rtcp/source/rtp_packet.cc
+++ b/modules/rtp_rtcp/source/rtp_packet.cc
@@ -212,6 +212,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 5f9544dcab..7c2b93e219 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;
@@ -402,6 +414,24 @@ TEST(RtpPacketTest, FailsToSetUnregisteredExtension) {
EXPECT_EQ(packet.GetExtension<TransportSequenceNumber>(), std::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 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 9d1f423ae4..258bfa1885 100644
--- a/modules/rtp_rtcp/source/rtp_sender.cc
+++ b/modules/rtp_rtcp/source/rtp_sender.cc
@@ -140,6 +140,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<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;
@@ -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 <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/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 <set>
+
+#if defined(ANDROID)
+#include <jni.h>
+#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<VideoInputFeedBack*> _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<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 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<VideoCaptureModule> VideoCaptureFactory::Create(
const char* deviceUniqueIdUTF8) {
-#if defined(WEBRTC_ANDROID) || defined(WEBRTC_MAC)
- return nullptr;
-#else
return videocapturemodule::VideoCaptureImpl::Create(deviceUniqueIdUTF8);
-#endif
}
rtc::scoped_refptr<VideoCaptureModule> VideoCaptureFactory::Create(
@@ -37,11 +33,7 @@ rtc::scoped_refptr<VideoCaptureModule> 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 5588fae161..51282183f5 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<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) {
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<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;
@@ -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<VideoFrame>* _dataCallBack RTC_GUARDED_BY(api_lock_);
+ std::set<rtc::VideoSinkInterface<VideoFrame>*> _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 a82d33ab36..ea7cb5767e 100644
--- a/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.cc
+++ b/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.cc
@@ -258,6 +258,7 @@ LibvpxVp9Encoder::LibvpxVp9Encoder(const Environment& env,
force_all_active_layers_(false),
enable_svc_for_simulcast_(
!env.field_trials().IsDisabled("WebRTC-VP9-SvcForSimulcast")),
+ num_cores_(0),
is_flexible_mode_(false),
variable_framerate_controller_(variable_framerate_screenshare::kMinFps),
quality_scaler_experiment_(ParseQualityScalerConfig(env.field_trials())),
@@ -543,6 +544,7 @@ int LibvpxVp9Encoder::InitEncode(const VideoCodec* inst,
force_key_frame_ = true;
pics_since_key_ = 0;
+ num_cores_ = settings.number_of_cores;
scalability_mode_ = codec_.GetScalabilityMode();
if (scalability_mode_.has_value()) {
@@ -1110,6 +1112,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);
@@ -1232,6 +1242,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,
std::optional<int>* spatial_idx,
std::optional<int>* 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 f08d452346..b4342125a7 100644
--- a/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.h
+++ b/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.h
@@ -71,6 +71,9 @@ class LibvpxVp9Encoder : public VideoEncoder {
// Call encoder initialize function and set control settings.
int InitAndSetControlSettings();
+ // Update frame size for codec.
+ int UpdateCodecFrameSize(const VideoFrame& input_image);
+
bool PopulateCodecSpecific(CodecSpecificInfo* codec_specific,
std::optional<int>* spatial_idx,
std::optional<int>* temporal_idx,
@@ -153,6 +156,7 @@ class LibvpxVp9Encoder : public VideoEncoder {
VideoBitrateAllocation current_bitrate_allocation_;
bool ss_info_needed_;
bool force_all_active_layers_;
+ uint8_t num_cores_;
const bool enable_svc_for_simulcast_;
std::optional<SimulcastToSvcConverter> simulcast_to_svc_converter_;
diff --git a/rtc_base/BUILD.gn b/rtc_base/BUILD.gn
index e1282d7293..ef2a93fbb8 100644
--- a/rtc_base/BUILD.gn
+++ b/rtc_base/BUILD.gn
@@ -444,6 +444,12 @@ rtc_library("logging") {
"//third_party/abseil-cpp/absl/strings:string_view",
]
+ # 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 165a83b467..4280f32125 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 eaa423e855..6a7b233e29 100644
--- a/test/fuzzers/rtp_packet_fuzzer.cc
+++ b/test/fuzzers/rtp_packet_fuzzer.cc
@@ -170,6 +170,10 @@ void FuzzOneInput(const uint8_t* data, size_t size) {
CorruptionDetectionMessage message;
packet.GetExtension<CorruptionDetectionExtension>(&message);
break;
+ case kRtpExtensionCsrcAudioLevel: {
+ CsrcAudioLevelList levels;
+ packet.GetExtension<CsrcAudioLevel>(&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 66ed8434ff..45293063a9 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