Source code

Revision control

Copy as Markdown

Other Tools

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
Bug 1376873 - Rollup conflict fixes for audio/video code; r=pehrsons
MozReview-Commit-ID: 1T8mgqdkzq3
Bug 1376873 - Rollup conflict fixes for rtp_rtcp module; r=ng
MozReview-Commit-ID: D09534DOVLj
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.
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.
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.
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.
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.
Bug 1512459 - Remove webrtc sndio audio device; r=padenot
This code is unused and can be removed.
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.
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.
Bug 1497573 - Remove DesktopCapturer::Stop; r=ng
Bug 1497619 - Restore thread check in process_thread_impl.cc; r=ng
Not not really needed.
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.
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.
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.
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.
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.
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.
Bug 1376873 - Updates to Android video capture; r=pehrsons
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.
Bug 1652552 - Remove remaining application capture code; r=jib
Bug 1846358 - revert mozilla-specific b2g related change in generic_decoder.cc kDecoderFrameMemoryLength. r=ng,webrtc-reviewers
Bug 1846875 - remove redundant divide by zero protection in libwebrtc's merge.cc r=ng,webrtc-reviewers
Bug 1846590 - move SetCaptureAndroidVM declaration from libwebrtc video_capture.h to our VideoEngine.cpp r=ng,webrtc-reviewers
Bug 1847466 - remove work-around for missing v4l2_capability::bus_info in v412loopback driver. r=jesup,pehrsons,webrtc-reviewers
Added in Bug 861280, but should no longer be necessary after fixes in upstream
v4l2loopback commits (fc4c173, fe03e4f, c3b1eaa).
Bug 1846636 - restore ScreenCapturerWinMagnifier destructor to upstream version. r=ng,webrtc-reviewers
Bug 1376873 - Fix up logging in WebrtcLog.cpp; r=ng
The webrtc::Trace code is removed by this update. We already had support for
LOG (now RTC_LOG) in WebrtcLog.cpp. This removes the trace code from
WebRtcLog.cpp and moves the aec logging code from webrtc::Trace to
rtc::LogMessage.
This also disables logging to stderr in rtc_base/logging.cc. We could disable
it using the API, but that happens through peerconnection resulting in some
logging occuring during getusermedia.
The aec logs were testing with --disable-e10s. Rather than trying to
work around sandboxing, I think it makes more sense to fix Bug 1404982 and
store the logs in memory for retrieval from about:webrtc.
Bug 1847818 - restore aec logging from about:webrtc. r=ng,webrtc-reviewers
Bug 1535584 - Restore UpdateCodecFrameSize to vp9_impl.cc; r=bwc
Bug 1846850 - remove mozilla-added IsGUIThread asserts from libwebrtc. r=ng,webrtc-reviewers
These were added in Bug 1060738 but no longer seem to add value based
on crash stats.
Bug 1846858 - revert changes to libwebrtc's deprecated/session_info.cc since we don't build it. r=ng,webrtc-reviewers
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.
Bug 1847984 - remove mozilla-specific null FILE* checks in apm_data_dumper.h r=ng,webrtc-reviewers
Since upstream commit 4bc60452f7 ApmDataDumper::GetRawFile does a release
assert if FILE* is null so our mozilla-specific mods to check for valid
FILE pointers are no longer needed.
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.
Bug 1847833 - remove aec log output size limiting code from libwebrtc's apm_data_dumper. r=ng,webrtc-reviewers
Bug 1847833 - aec_debug_size_, aec_debug_size(), set_aec_debug_size(uint32_t size) are no longer used. r=ng,webrtc-reviewers
Bug 1850146 - remove unnecessary libwebrtc changes in jvm_android.cc. r?dbaker!
After landing Bug 1826428 to remove jvm_android.cc from the build and
giving time for that to simmer for a while with no known effects, we
can remove our modifications.
---
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 | 5 +
test/vcm_capturer.cc | 2 +-
webrtc.gni | 2 +-
39 files changed, 566 insertions(+), 81 deletions(-)
diff --git a/api/rtp_headers.cc b/api/rtp_headers.cc
index 8813e0f4c2..b5e08cea2c 100644
--- a/api/rtp_headers.cc
+++ b/api/rtp_headers.cc
@@ -31,7 +31,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 129ab5f499..5a867bbd77 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 {
absl::optional<ColorSpace> color_space;
+ CsrcAudioLevelList csrcAudioLevels;
+
private:
absl::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 283d238e77..da06138ce8 100644
--- a/api/rtp_parameters.cc
+++ b/api/rtp_parameters.cc
@@ -164,7 +164,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 f57f9e0d3c..9f2833196d 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 59ffd39548..71b5f12982 100644
--- a/call/video_receive_stream.h
+++ b/call/video_receive_stream.h
@@ -216,6 +216,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 92305da0e6..3257f5fff0 100644
--- a/modules/audio_coding/acm2/acm_receiver.h
+++ b/modules/audio_coding/acm2/acm_receiver.h
@@ -19,6 +19,7 @@
#include <string>
#include <utility>
#include <vector>
+#include <atomic>
#include "absl/types/optional.h"
#include "api/array_view.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 7ec3b17929..cd516d3d6f 100644
--- a/modules/rtp_rtcp/source/rtcp_sender.cc
+++ b/modules/rtp_rtcp/source/rtcp_sender.cc
@@ -200,7 +200,7 @@ void RTCPSender::SetRTCPStatus(RtcpMode new_method) {
next_time_to_send_rtcp_ = absl::nullopt;
} else if (method_ == RtcpMode::kOff) {
// When switching on, reschedule the next packet
- SetNextRtcpSendEvaluationDuration(report_interval_ / 2);
+ SetNextRtcpSendEvaluationDuration(RTCP_INTERVAL_RAPID_SYNC_MS / 2);
}
method_ = new_method;
}
diff --git a/modules/rtp_rtcp/source/rtp_header_extensions.cc b/modules/rtp_rtcp/source/rtp_header_extensions.cc
index 43770a728a..bcdc9a036b 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 02a1543e00..05e771a56d 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 2a95a3a816..b152cdbd9e 100644
--- a/modules/rtp_rtcp/source/rtp_packet.cc
+++ b/modules/rtp_rtcp/source/rtp_packet.cc
@@ -205,6 +205,10 @@ void RtpPacket::ZeroMutableExtensions() {
// Non-mutable extension. Don't change it.
break;
}
+ case RTPExtensionType::kRtpExtensionCsrcAudioLevel: {
+ // TODO: This is a Mozilla addition, we need to add a handler for this.
+ RTC_CHECK(false);
+ }
}
}
}
diff --git a/modules/rtp_rtcp/source/rtp_packet_unittest.cc b/modules/rtp_rtcp/source/rtp_packet_unittest.cc
index ccdb5f8a75..da4abe0131 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>(), 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 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 ed805e7a2b..65a9d58314 100644
--- a/modules/rtp_rtcp/source/rtp_sender.cc
+++ b/modules/rtp_rtcp/source/rtp_sender.cc
@@ -128,6 +128,10 @@ bool IsNonVolatile(RTPExtensionType type) {
case kRtpExtensionNumberOfExtensions:
RTC_DCHECK_NOTREACHED();
return false;
+ case kRtpExtensionCsrcAudioLevel:
+ // TODO: Mozilla implement for CsrcAudioLevel
+ RTC_CHECK(false);
+ return false;
}
RTC_CHECK_NOTREACHED();
}
diff --git a/modules/video_capture/device_info_impl.cc b/modules/video_capture/device_info_impl.cc
index ff32a78580..7cccdb51a7 100644
--- a/modules/video_capture/device_info_impl.cc
+++ b/modules/video_capture/device_info_impl.cc
@@ -65,7 +65,7 @@ int32_t DeviceInfoImpl::GetCapability(const char* deviceUniqueIdUTF8,
// Make sure the number is valid
if (deviceCapabilityNumber >= (unsigned int)_captureCapabilities.size()) {
- RTC_LOG(LS_ERROR) << "Invalid deviceCapabilityNumber "
+ RTC_LOG(LS_ERROR) << deviceUniqueIdUTF8 << " Invalid deviceCapabilityNumber "
<< deviceCapabilityNumber << ">= number of capabilities ("
<< _captureCapabilities.size() << ").";
return -1;
diff --git a/modules/video_capture/device_info_impl.h b/modules/video_capture/device_info_impl.h
index 546265049c..8acbef6d69 100644
--- a/modules/video_capture/device_info_impl.h
+++ b/modules/video_capture/device_info_impl.h
@@ -42,6 +42,7 @@ class DeviceInfoImpl : public VideoCaptureModule::DeviceInfo {
/* Initialize this object*/
virtual int32_t Init() = 0;
+ int32_t Refresh() override { return 0; }
/*
* Fills the member variable _captureCapabilities with capabilities for the
* given device name.
diff --git a/modules/video_capture/linux/device_info_v4l2.cc b/modules/video_capture/linux/device_info_v4l2.cc
index a472e41a41..7397a10625 100644
--- a/modules/video_capture/linux/device_info_v4l2.cc
+++ b/modules/video_capture/linux/device_info_v4l2.cc
@@ -45,15 +45,187 @@
#define V4L2_PIX_FMT_RGBA32 v4l2_fourcc('A', 'B', '2', '4')
#endif
+#ifdef WEBRTC_LINUX
+#define EVENT_SIZE ( sizeof (struct inotify_event) )
+#define BUF_LEN ( 1024 * ( EVENT_SIZE + 16 ) )
+#endif
+
namespace webrtc {
namespace videocapturemodule {
-DeviceInfoV4l2::DeviceInfoV4l2() : DeviceInfoImpl() {}
+#ifdef WEBRTC_LINUX
+void DeviceInfoV4l2::HandleEvent(inotify_event* event, int fd)
+{
+ if (event->mask & IN_CREATE) {
+ if (fd == _fd_v4l || fd == _fd_snd) {
+ DeviceChange();
+ } else if ((event->mask & IN_ISDIR) && (fd == _fd_dev)) {
+ if (_wd_v4l < 0) {
+ // Sometimes inotify_add_watch failed if we call it immediately after receiving this event
+ // Adding 5ms delay to let file system settle down
+ usleep(5*1000);
+ _wd_v4l = inotify_add_watch(_fd_v4l, "/dev/v4l/by-path/", IN_CREATE | IN_DELETE | IN_DELETE_SELF);
+ if (_wd_v4l >= 0) {
+ DeviceChange();
+ }
+ }
+ if (_wd_snd < 0) {
+ usleep(5*1000);
+ _wd_snd = inotify_add_watch(_fd_snd, "/dev/snd/by-path/", IN_CREATE | IN_DELETE | IN_DELETE_SELF);
+ if (_wd_snd >= 0) {
+ DeviceChange();
+ }
+ }
+ }
+ } else if (event->mask & IN_DELETE) {
+ if (fd == _fd_v4l || fd == _fd_snd) {
+ DeviceChange();
+ }
+ } else if (event->mask & IN_DELETE_SELF) {
+ if (fd == _fd_v4l) {
+ inotify_rm_watch(_fd_v4l, _wd_v4l);
+ _wd_v4l = -1;
+ } else if (fd == _fd_snd) {
+ inotify_rm_watch(_fd_snd, _wd_snd);
+ _wd_snd = -1;
+ } else {
+ assert(false);
+ }
+ }
+}
+
+int DeviceInfoV4l2::EventCheck(int fd)
+{
+ struct timeval timeout;
+ fd_set rfds;
+
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 100000;
+
+ FD_ZERO(&rfds);
+ FD_SET(fd, &rfds);
+
+ return select(fd+1, &rfds, NULL, NULL, &timeout);
+}
+
+int DeviceInfoV4l2::HandleEvents(int fd)
+{
+ char buffer[BUF_LEN];
+
+ ssize_t r = read(fd, buffer, BUF_LEN);
+
+ if (r <= 0) {
+ return r;
+ }
+
+ ssize_t buffer_i = 0;
+ inotify_event* pevent;
+ size_t eventSize;
+ int count = 0;
+
+ while (buffer_i < r)
+ {
+ pevent = (inotify_event *) (&buffer[buffer_i]);
+ eventSize = sizeof(inotify_event) + pevent->len;
+ char event[sizeof(inotify_event) + FILENAME_MAX + 1] // null-terminated
+ __attribute__ ((aligned(__alignof__(struct inotify_event))));
+
+ memcpy(event, pevent, eventSize);
+
+ HandleEvent((inotify_event*)(event), fd);
+
+ buffer_i += eventSize;
+ count++;
+ }
+
+ return count;
+}
+
+int DeviceInfoV4l2::ProcessInotifyEvents()
+{
+ while (!_isShutdown) {
+ if (EventCheck(_fd_dev) > 0) {
+ if (HandleEvents(_fd_dev) < 0) {
+ break;
+ }
+ }
+ if (EventCheck(_fd_v4l) > 0) {
+ if (HandleEvents(_fd_v4l) < 0) {
+ break;
+ }
+ }
+ if (EventCheck(_fd_snd) > 0) {
+ if (HandleEvents(_fd_snd) < 0) {
+ break;
+ }
+ }
+ }
+ return 0;
+}
+
+void DeviceInfoV4l2::InotifyEventThread(void* obj)
+{
+ static_cast<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 fc3640cee0..b4508a224e 100644
--- a/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.cc
+++ b/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.cc
@@ -255,6 +255,7 @@ LibvpxVp9Encoder::LibvpxVp9Encoder(const Environment& env,
first_frame_in_picture_(true),
ss_info_needed_(false),
force_all_active_layers_(false),
+ num_cores_(0),
is_flexible_mode_(false),
variable_framerate_controller_(variable_framerate_screenshare::kMinFps),
quality_scaler_experiment_(ParseQualityScalerConfig(env.field_trials())),
@@ -528,6 +529,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()) {
@@ -1098,6 +1100,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);
@@ -1220,6 +1230,48 @@ int LibvpxVp9Encoder::Encode(const VideoFrame& input_image,
return WEBRTC_VIDEO_CODEC_OK;
}
+int LibvpxVp9Encoder::UpdateCodecFrameSize(
+ const VideoFrame& input_image) {
+ RTC_LOG(LS_INFO) << "Reconfiging VP from " <<
+ codec_.width << "x" << codec_.height << " to " <<
+ input_image.width() << "x" << input_image.height();
+ // Preserve latest bitrate/framerate setting
+ // TODO: Mozilla - see below, we need to save more state here.
+ //uint32_t old_bitrate_kbit = config_->rc_target_bitrate;
+ //uint32_t old_framerate = codec_.maxFramerate;
+
+ codec_.width = input_image.width();
+ codec_.height = input_image.height();
+
+ vpx_img_free(raw_);
+ raw_ = vpx_img_wrap(NULL, VPX_IMG_FMT_I420, codec_.width, codec_.height,
+ 1, NULL);
+ // Update encoder context for new frame size.
+ config_->g_w = codec_.width;
+ config_->g_h = codec_.height;
+
+ // Determine number of threads based on the image size and #cores.
+ config_->g_threads = NumberOfThreads(codec_.width, codec_.height,
+ num_cores_);
+
+ // NOTE: We would like to do this the same way vp8 does it
+ // (with vpx_codec_enc_config_set()), but that causes asserts
+ // in AQ 3 (cyclic); and in AQ 0 it works, but on a resize to smaller
+ // than 1/2 x 1/2 original it asserts in convolve(). Given these
+ // bugs in trying to do it the "right" way, we basically re-do
+ // the initialization.
+ vpx_codec_destroy(encoder_); // clean up old state
+ int result = InitAndSetControlSettings(&codec_);
+ if (result == WEBRTC_VIDEO_CODEC_OK) {
+ // TODO: Mozilla rates have become much more complicated, we need to store
+ // more state or find another way of doing this.
+ //return SetRates(old_bitrate_kbit, old_framerate);
+ RTC_CHECK(false);
+ return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
+ }
+ return result;
+}
+
bool LibvpxVp9Encoder::PopulateCodecSpecific(CodecSpecificInfo* codec_specific,
absl::optional<int>* spatial_idx,
absl::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 0134e3ea58..86d1bdda16 100644
--- a/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.h
+++ b/modules/video_coding/codecs/vp9/libvpx_vp9_encoder.h
@@ -68,6 +68,9 @@ class LibvpxVp9Encoder : public VideoEncoder {
// 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 VideoEncoder {
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/rtc_base/BUILD.gn b/rtc_base/BUILD.gn
index 4743a46d9d..2bdbb971ef 100644
--- a/rtc_base/BUILD.gn
+++ b/rtc_base/BUILD.gn
@@ -469,6 +469,12 @@ rtc_library("logging") {
"//third_party/abseil-cpp/absl/types:optional",
]
+ # Added to allow including apm_data_dumper.h in rtc_base/logging.cc
+ # for Mozilla controlling aec logging from about:webrtc.
+ if (build_with_mozilla) {
+ configs += [ "../modules/audio_processing:apm_debug_dump" ]
+ }
+
if (build_with_chromium) {
# Dependency on chromium's logging (in //base).
deps += [ "//base" ]
diff --git a/rtc_base/logging.cc b/rtc_base/logging.cc
index 61a3c667ba..ad2303735e 100644
--- a/rtc_base/logging.cc
+++ b/rtc_base/logging.cc
@@ -44,6 +44,7 @@ static const int kMaxLogLineSize = 1024 - 60;
#include "absl/base/attributes.h"
#include "absl/strings/string_view.h"
#include "api/units/timestamp.h"
+#include "modules/audio_processing/logging/apm_data_dumper.h"
#include "rtc_base/checks.h"
#include "rtc_base/platform_thread_types.h"
#include "rtc_base/string_encode.h"
@@ -54,6 +55,24 @@ static const int kMaxLogLineSize = 1024 - 60;
#include "rtc_base/time_utils.h"
namespace rtc {
+
+bool LogMessage::aec_debug_ = false;
+std::string LogMessage::aec_filename_base_;
+
+void LogMessage::set_aec_debug(bool enable) {
+ aec_debug_ = enable;
+ webrtc::ApmDataDumper::SetActivated(aec_debug_);
+}
+
+std::string LogMessage::aec_debug_filename() {
+ return aec_filename_base_;
+}
+
+void LogMessage::set_aec_debug_filename(const char* filename) {
+ aec_filename_base_ = filename;
+ webrtc::ApmDataDumper::SetOutputDirectory(aec_filename_base_);
+}
+
namespace {
// By default, release builds don't log, debug builds at info level
@@ -114,7 +133,7 @@ std::string LogLineRef::DefaultLogLine() const {
// LogMessage
/////////////////////////////////////////////////////////////////////////////
-bool LogMessage::log_to_stderr_ = true;
+bool LogMessage::log_to_stderr_ = false;
// The list of logging streams currently configured.
// Note: we explicitly do not clean this up, because of the uncertain ordering
diff --git a/rtc_base/logging.h b/rtc_base/logging.h
index b171cfe11e..df7f173f58 100644
--- a/rtc_base/logging.h
+++ b/rtc_base/logging.h
@@ -581,6 +581,12 @@ class LogMessage {
}
#endif // RTC_LOG_ENABLED()
+ // Enable dumping of AEC inputs and outputs. Can be changed in mid-call
+ static void set_aec_debug(bool enable);
+ static bool aec_debug() { return aec_debug_; }
+ static std::string aec_debug_filename();
+ static void set_aec_debug_filename(const char* filename);
+
private:
friend class LogMessageForTesting;
@@ -636,6 +642,9 @@ class LogMessage {
// The stringbuilder that buffers the formatted message before output
rtc::StringBuilder print_stream_;
+
+ static bool aec_debug_;
+ static std::string aec_filename_base_;
};
//////////////////////////////////////////////////////////////////////
diff --git a/test/fuzzers/rtp_packet_fuzzer.cc b/test/fuzzers/rtp_packet_fuzzer.cc
index be4e9a3e85..23a1828915 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 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