Bug 1729455 - Inject RTCStatsTimestampMakerRealtimeClock into Call instances. r=bwc

This patch makes libwebrtc use our clock for timestamps.
It also makes sure there's no use of the libwebrtc realtime clock, other than
for relative time tracking (like timeouts), and that future libwebrtc updates
don't introduce unaudited use of it.

Differential Revision: https://phabricator.services.mozilla.com/D127714
This commit is contained in:
Andreas Pehrson 2021-11-02 14:35:57 +00:00
Родитель 6cc9a2ba1a
Коммит 1d84e22f11
20 изменённых файлов: 70 добавлений и 42 удалений

Просмотреть файл

@ -13,6 +13,7 @@
#include "VideoUtils.h"
#include "nsISupportsImpl.h"
#include "nsThreadUtils.h"
#include "jsapi/RTCStatsReport.h"
#include "mozilla/TaskQueue.h"
#include "mozilla/dom/ImageBitmapBinding.h"
#include "mozilla/dom/ImageUtils.h"
@ -20,7 +21,6 @@
#include "common_video/include/i420_buffer_pool.h"
#include "common_video/include/video_frame_buffer.h"
#include "rtc_base/keep_ref_until_done.h"
#include "system_wrappers/include/clock.h"
// The number of frame buffers VideoFrameConverter may create before returning
// errors.
@ -54,8 +54,10 @@ class VideoFrameConverter {
public:
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VideoFrameConverter)
VideoFrameConverter()
: mTaskQueue(
explicit VideoFrameConverter(
const dom::RTCStatsTimestampMaker& aTimestampMaker)
: mTimestampMaker(aTimestampMaker),
mTaskQueue(
new TaskQueue(GetMediaThreadPool(MediaThreadType::WEBRTC_WORKER),
"VideoFrameConverter")),
mPacingTimer(new MediaTimer()),
@ -231,7 +233,7 @@ class VideoFrameConverter {
}
self->mLastFrameConverted->set_timestamp_us(
webrtc::Clock::GetRealTimeClock()->TimeInMicroseconds());
self->mTimestampMaker.GetNowRealtime().us());
for (RefPtr<VideoConverterListener>& listener : self->mListeners) {
listener->OnVideoFrameConverted(*self->mLastFrameConverted);
}
@ -308,7 +310,7 @@ class VideoFrameConverter {
// See Bug 1529581 - Ideally we'd use the mTimestamp from the chunk
// passed into QueueVideoChunk rather than the webrtc.org clock here.
int64_t now = webrtc::Clock::GetRealTimeClock()->TimeInMilliseconds();
const webrtc::Timestamp now = mTimestampMaker.GetNowRealtime();
if (aFrame.mForceBlack) {
// Send a black image.
@ -328,7 +330,7 @@ class VideoFrameConverter {
webrtc::I420Buffer::SetBlack(buffer);
webrtc::VideoFrame frame(buffer, 0, // not setting rtp timestamp
now, webrtc::kVideoRotation_0);
now.ms(), webrtc::kVideoRotation_0);
VideoFrameConverted(frame);
return;
}
@ -354,7 +356,7 @@ class VideoFrameConverter {
webrtc::VideoFrame i420_frame(video_frame_buffer,
0, // not setting rtp timestamp
now, webrtc::kVideoRotation_0);
now.ms(), webrtc::kVideoRotation_0);
MOZ_LOG(gVideoFrameConverterLog, LogLevel::Verbose,
("Sending an I420 video frame"));
VideoFrameConverted(i420_frame);
@ -390,10 +392,12 @@ class VideoFrameConverter {
}
webrtc::VideoFrame frame(buffer, 0, // not setting rtp timestamp
now, webrtc::kVideoRotation_0);
now.ms(), webrtc::kVideoRotation_0);
VideoFrameConverted(frame);
}
const dom::RTCStatsTimestampMaker mTimestampMaker;
const RefPtr<TaskQueue> mTaskQueue;
// Used to pace future frames close to their rendering-time. Thread-safe.

Просмотреть файл

@ -35,7 +35,8 @@ class VideoFrameConverterTest : public ::testing::Test {
RefPtr<FrameListener> mListener;
VideoFrameConverterTest()
: mConverter(MakeAndAddRef<VideoFrameConverter>()),
: mConverter(
MakeAndAddRef<VideoFrameConverter>(dom::RTCStatsTimestampMaker())),
mListener(MakeAndAddRef<FrameListener>()) {
mConverter->AddListener(mListener);
}

Просмотреть файл

@ -5,6 +5,7 @@
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "VideoEngine.h"
#include "libwebrtcglue/SystemTime.h"
#include "video_engine/desktop_capture_impl.h"
#include "system_wrappers/include/clock.h"
#ifdef WEBRTC_ANDROID
@ -138,7 +139,7 @@ int VideoEngine::ReleaseVideoCapture(const int32_t id) {
std::shared_ptr<webrtc::VideoCaptureModule::DeviceInfo>
VideoEngine::GetOrCreateVideoCaptureDeviceInfo() {
LOG(("%s", __PRETTY_FUNCTION__));
int64_t currentTime = 0;
webrtc::Timestamp currentTime = webrtc::Timestamp::Micros(0);
const char* capDevTypeName =
webrtc::CaptureDeviceInfo(mCaptureDevInfo.type).TypeName();
@ -151,21 +152,22 @@ VideoEngine::GetOrCreateVideoCaptureDeviceInfo() {
return mDeviceInfo;
}
// Screen sharing cache is invalidated after the expiration time
currentTime = webrtc::Clock::GetRealTimeClock()->TimeInMilliseconds();
LOG(("Checking expiry, fetched current time of: %" PRId64, currentTime));
LOG(("device cache expiration is %" PRId64, mExpiryTimeInMs));
if (currentTime <= mExpiryTimeInMs) {
currentTime = WebrtcSystemTime();
LOG(("Checking expiry, fetched current time of: %" PRId64,
currentTime.ms()));
LOG(("device cache expiration is %" PRId64, mExpiryTime.ms()));
if (currentTime <= mExpiryTime) {
LOG(("returning cached CaptureDeviceInfo of type %s", capDevTypeName));
return mDeviceInfo;
}
}
if (currentTime == 0) {
currentTime = webrtc::Clock::GetRealTimeClock()->TimeInMilliseconds();
LOG(("Fetched current time of: %" PRId64, currentTime));
if (currentTime.IsZero()) {
currentTime = WebrtcSystemTime();
LOG(("Fetched current time of: %" PRId64, currentTime.ms()));
}
mExpiryTimeInMs = currentTime + kCacheExpiryPeriodMs;
LOG(("new device cache expiration is %" PRId64, mExpiryTimeInMs));
mExpiryTime = currentTime + webrtc::TimeDelta::Millis(kCacheExpiryPeriodMs);
LOG(("new device cache expiration is %" PRId64, mExpiryTime.ms()));
LOG(("creating a new VideoCaptureDeviceInfo of type %s", capDevTypeName));
switch (mCaptureDevInfo.type) {

Просмотреть файл

@ -87,7 +87,7 @@ class VideoEngine {
std::map<int32_t, CaptureEntry> mCaps;
std::map<int32_t, int32_t> mIdMap;
// The validity period for non-camera capture device infos`
int64_t mExpiryTimeInMs = 0;
webrtc::Timestamp mExpiryTime = webrtc::Timestamp::Micros(0);
int32_t GenerateId();
};
} // namespace camera

Просмотреть файл

@ -7,6 +7,7 @@
#include "nsTArray.h"
#include "mozilla/Assertions.h"
#include "MainThreadUtils.h"
#include "SystemTime.h"
#include "system_wrappers/include/clock.h"
@ -133,13 +134,13 @@ void MediaSessionConduit::InsertAudioLevelForContributingSource(
domEntry.mAudioLevel.Construct(rtpToDomAudioLevel(aAudioLevel));
}
int64_t libwebrtcNow =
webrtc::Clock::GetRealTimeClock()->TimeInMilliseconds();
double jsNow = GetTimestampMaker().GetNow();
webrtc::Timestamp libwebrtcNow = GetTimestampMaker().GetNowRealtime();
double jsNow = GetTimestampMaker().ReduceRealtimePrecision(libwebrtcNow);
double ago = jsNow - aTimestamp;
uint64_t convertedTimestamp = libwebrtcNow - ago;
webrtc::Timestamp convertedTimestamp =
libwebrtcNow - webrtc::TimeDelta::Millis(ago);
SourceKey key(convertedTimestamp, aCsrcSource);
SourceKey key(convertedTimestamp.ms<uint32_t>(), aCsrcSource);
mSourcesCache[key] = domEntry;
}

Просмотреть файл

@ -196,25 +196,25 @@ class MediaSessionConduit {
// not necessarily yield exactly the same result if performed again later, we
// need to avoid performing it more than once for each entry, which means we
// need to remember both the JS timestamp (in dom::RTCRtpSourceEntry) and the
// libwebrtc timestamp (in SourceKey::mLibwebrtcTimestamp).
// libwebrtc timestamp (in SourceKey::mLibwebrtcTimestampMs).
class SourceKey {
public:
explicit SourceKey(const webrtc::RtpSource& aSource)
: SourceKey(aSource.timestamp_ms(), aSource.source_id()) {}
SourceKey(uint32_t aTimestamp, uint32_t aSrc)
: mLibwebrtcTimestamp(aTimestamp), mSrc(aSrc) {}
: mLibwebrtcTimestampMs(aTimestamp), mSrc(aSrc) {}
// TODO: Once we support = default for this in our toolchain, do so
auto operator>(const SourceKey& aRhs) const {
if (mLibwebrtcTimestamp == aRhs.mLibwebrtcTimestamp) {
if (mLibwebrtcTimestampMs == aRhs.mLibwebrtcTimestampMs) {
return mSrc > aRhs.mSrc;
}
return mLibwebrtcTimestamp > aRhs.mLibwebrtcTimestamp;
return mLibwebrtcTimestampMs > aRhs.mLibwebrtcTimestampMs;
}
private:
uint32_t mLibwebrtcTimestamp;
uint32_t mLibwebrtcTimestampMs;
uint32_t mSrc;
};
mutable std::map<SourceKey, dom::RTCRtpSourceEntry, std::greater<SourceKey>>

Просмотреть файл

@ -32,8 +32,9 @@ namespace mozilla {
webrtc::AudioState::Create(aSharedState->mAudioStateConfig);
config.task_queue_factory = wrapper->mTaskQueueFactory.get();
config.trials = aSharedState->mTrials.get();
wrapper->SetCall(WrapUnique(
webrtc::Call::Create(config, aSharedState->GetModuleThread())));
wrapper->SetCall(WrapUnique(webrtc::Call::Create(
config, &wrapper->mClock, aSharedState->GetModuleThread(),
webrtc::ProcessThread::Create("PacerThread"))));
}));
return wrapper;
@ -75,7 +76,7 @@ void WebrtcCallWrapper::Destroy() {
const dom::RTCStatsTimestampMaker& WebrtcCallWrapper::GetTimestampMaker()
const {
return mTimestampMaker;
return mClock.mTimestampMaker;
}
WebrtcCallWrapper::~WebrtcCallWrapper() { MOZ_ASSERT(!mCall); }
@ -89,7 +90,7 @@ WebrtcCallWrapper::WebrtcCallWrapper(
const dom::RTCStatsTimestampMaker& aTimestampMaker,
UniquePtr<media::ShutdownBlockingTicket> aShutdownTicket)
: mSharedState(std::move(aSharedState)),
mTimestampMaker(aTimestampMaker),
mClock(aTimestampMaker),
mShutdownTicket(std::move(aShutdownTicket)),
mCallThread(mSharedState->mCallWorkerThread),
mAudioDecoderFactory(mSharedState->mAudioDecoderFactory),

Просмотреть файл

@ -12,6 +12,7 @@
#include "domstubs.h"
#include "jsapi/RTCStatsReport.h"
#include "nsISupportsImpl.h"
#include "SystemTime.h"
// libwebrtc includes
#include "api/video/builtin_video_bitrate_allocator_factory.h"
@ -91,7 +92,7 @@ class WebrtcCallWrapper {
// Allows conduits to know about one another, to avoid remote SSRC
// collisions.
std::set<MediaSessionConduit*> mConduits;
dom::RTCStatsTimestampMaker mTimestampMaker;
RTCStatsTimestampMakerRealtimeClock mClock;
UniquePtr<media::ShutdownBlockingTicket> mShutdownTicket;
public:

Просмотреть файл

@ -827,7 +827,7 @@ MediaPipelineTransmit::MediaPipelineTransmit(
MakeAndAddRef<AudioProxyThread>(*mConduit->AsAudioSessionConduit());
mListener->SetAudioProxy(mAudioProcessing);
} else { // Video
mConverter = MakeAndAddRef<VideoFrameConverter>();
mConverter = MakeAndAddRef<VideoFrameConverter>(GetTimestampMaker());
mConverter->AddListener(mFeeder);
mListener->SetVideoFrameConverter(mConverter);
}

2
third_party/libwebrtc/audio/channel_send.cc поставляемый
Просмотреть файл

@ -508,7 +508,7 @@ ChannelSend::ChannelSend(
RtpRtcpInterface::Configuration configuration;
configuration.bandwidth_callback = rtcp_observer_.get();
configuration.transport_feedback_callback = feedback_observer_;
configuration.clock = (clock ? clock : Clock::GetRealTimeClock());
configuration.clock = clock;
configuration.audio = true;
configuration.outgoing_transport = rtp_transport;

2
third_party/libwebrtc/call/call.cc поставляемый
Просмотреть файл

@ -454,6 +454,7 @@ std::string Call::Stats::ToString(int64_t time_ms) const {
return ss.str();
}
/* Mozilla: Avoid this since it could use GetRealTimeClock().
Call* Call::Create(const Call::Config& config) {
rtc::scoped_refptr<SharedModuleThread> call_thread =
SharedModuleThread::Create(ProcessThread::Create("ModuleProcessThread"),
@ -466,6 +467,7 @@ Call* Call::Create(const Call::Config& config,
return Create(config, Clock::GetRealTimeClock(), std::move(call_thread),
ProcessThread::Create("PacerThread"));
}
*/
Call* Call::Create(const Call::Config& config,
Clock* clock,

2
third_party/libwebrtc/call/call.h поставляемый
Просмотреть файл

@ -81,9 +81,11 @@ class Call {
int64_t rtt_ms = -1;
};
/* Mozilla: Avoid this since it could use GetRealTimeClock().
static Call* Create(const Call::Config& config);
static Call* Create(const Call::Config& config,
rtc::scoped_refptr<SharedModuleThread> call_thread);
*/
static Call* Create(const Call::Config& config,
Clock* clock,
rtc::scoped_refptr<SharedModuleThread> call_thread,

8
third_party/libwebrtc/call/call_factory.cc поставляемый
Просмотреть файл

@ -82,9 +82,13 @@ Call* CallFactory::CreateCall(const Call::Config& config) {
receive_degradation_config = ParseDegradationConfig(false);
if (send_degradation_config || receive_degradation_config) {
RTC_CHECK(false);
return nullptr;
/* Mozilla: Avoid this since it could use GetRealTimeClock().
return new DegradedCall(std::unique_ptr<Call>(Call::Create(config)),
send_degradation_config, receive_degradation_config,
config.task_queue_factory);
*/
}
if (!module_thread_) {
@ -95,7 +99,11 @@ Call* CallFactory::CreateCall(const Call::Config& config) {
});
}
RTC_CHECK(false);
return nullptr;
/* Mozilla: Avoid this since it could use GetRealTimeClock().
return Call::Create(config, module_thread_);
*/
}
std::unique_ptr<CallFactoryInterface> CreateCallFactory() {

2
third_party/libwebrtc/call/degraded_call.cc поставляемый
Просмотреть файл

@ -125,6 +125,7 @@ bool DegradedCall::FakeNetworkPipeTransportAdapter::SendRtcp(
return true;
}
/* Mozilla: Avoid this since it could use GetRealTimeClock().
DegradedCall::DegradedCall(
std::unique_ptr<Call> call,
absl::optional<BuiltInNetworkBehaviorConfig> send_config,
@ -150,6 +151,7 @@ DegradedCall::DegradedCall(
task_queue_factory_, clock_, std::move(network));
}
}
*/
DegradedCall::~DegradedCall() = default;

Просмотреть файл

@ -615,7 +615,7 @@ ANAStats AudioCodingModuleImpl::GetANAStats() const {
AudioCodingModule::Config::Config(
rtc::scoped_refptr<AudioDecoderFactory> decoder_factory)
: neteq_config(),
clock(Clock::GetRealTimeClock()),
clock(Clock::GetRealTimeClockRaw()),
decoder_factory(decoder_factory) {
// Post-decode VAD is disabled by default in NetEq, however, Audio
// Conference Mixer relies on VAD decisions and fails without them.

Просмотреть файл

@ -28,9 +28,11 @@ class Clock;
class FlexfecReceiver {
public:
/* Mozilla: Avoid this since it could use GetRealTimeClock().
FlexfecReceiver(uint32_t ssrc,
uint32_t protected_media_ssrc,
RecoveredPacketReceiver* recovered_packet_receiver);
*/
FlexfecReceiver(Clock* clock,
uint32_t ssrc,
uint32_t protected_media_ssrc,

Просмотреть файл

@ -29,6 +29,7 @@ constexpr int kPacketLogIntervalMs = 10000;
} // namespace
/* Mozilla: Avoid this since it could use GetRealTimeClock().
FlexfecReceiver::FlexfecReceiver(
uint32_t ssrc,
uint32_t protected_media_ssrc,
@ -37,6 +38,7 @@ FlexfecReceiver::FlexfecReceiver(
ssrc,
protected_media_ssrc,
recovered_packet_receiver) {}
*/
FlexfecReceiver::FlexfecReceiver(
Clock* clock,

Просмотреть файл

@ -96,7 +96,7 @@ class RepeatingTaskHandle {
template <class Closure>
static RepeatingTaskHandle Start(TaskQueueBase* task_queue,
Closure&& closure,
Clock* clock = Clock::GetRealTimeClock()) {
Clock* clock = Clock::GetRealTimeClockRaw()) {
auto repeating_task = std::make_unique<
webrtc_repeating_task_impl::RepeatingTaskImpl<Closure>>(
task_queue, TimeDelta::Zero(), std::forward<Closure>(closure), clock);
@ -112,7 +112,7 @@ class RepeatingTaskHandle {
TaskQueueBase* task_queue,
TimeDelta first_delay,
Closure&& closure,
Clock* clock = Clock::GetRealTimeClock()) {
Clock* clock = Clock::GetRealTimeClockRaw()) {
auto repeating_task = std::make_unique<
webrtc_repeating_task_impl::RepeatingTaskImpl<Closure>>(
task_queue, first_delay, std::forward<Closure>(closure), clock);

Просмотреть файл

@ -53,7 +53,7 @@ class RTC_EXPORT Clock {
}
// Returns an instance of the real-time system clock implementation.
static Clock* GetRealTimeClock();
static Clock* GetRealTimeClockRaw();
};
class SimulatedClock : public Clock {

Просмотреть файл

@ -258,7 +258,7 @@ class UnixRealTimeClock : public RealTimeClock {
};
#endif // defined(WEBRTC_POSIX)
Clock* Clock::GetRealTimeClock() {
Clock* Clock::GetRealTimeClockRaw() {
#if defined(WINUWP)
static Clock* const clock = new WinUwpRealTimeClock();
#elif defined(WEBRTC_WIN)