зеркало из https://github.com/mozilla/gecko-dev.git
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:
Родитель
6cc9a2ba1a
Коммит
1d84e22f11
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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)
|
||||
|
|
Загрузка…
Ссылка в новой задаче