VideoConduit.h (19871B)
1 /* This Source Code Form is subject to the terms of the Mozilla Public 2 * License, v. 2.0. If a copy of the MPL was not distributed with this file, 3 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 4 5 #ifndef VIDEO_SESSION_H_ 6 #define VIDEO_SESSION_H_ 7 8 #include "MediaConduitInterface.h" 9 #include "RtpRtcpConfig.h" 10 #include "RunningStat.h" 11 #include "mozilla/Atomics.h" 12 #include "mozilla/Attributes.h" 13 #include "mozilla/DataMutex.h" 14 #include "mozilla/ReentrantMonitor.h" 15 #include "mozilla/StateMirroring.h" 16 #include "mozilla/UniquePtr.h" 17 18 // conflicts with #include of scoped_ptr.h 19 #undef FF 20 // Video Engine Includes 21 #include "api/media_stream_interface.h" 22 #include "api/video_codecs/video_decoder.h" 23 #include "api/video_codecs/video_encoder.h" 24 #include "call/call_basic_stats.h" 25 /** This file hosts several structures identifying different aspects 26 * of a RTP Session. 27 */ 28 29 namespace mozilla { 30 31 // Convert (SI) kilobits/sec to (SI) bits/sec 32 #define KBPS(kbps) ((kbps) * 1000) 33 34 const int kViEMinCodecBitrate_bps = KBPS(30); 35 const unsigned int kVideoMtu = 1200; 36 const int kQpMax = 56; 37 38 template <typename T> 39 T MinIgnoreZero(const T& a, const T& b) { 40 return std::min(a ? a : b, b ? b : a); 41 } 42 43 class VideoStreamFactory; 44 class WebrtcAudioConduit; 45 class WebrtcVideoConduit; 46 47 // Interface of external video encoder for WebRTC. 48 class WebrtcVideoEncoder : public VideoEncoder, public webrtc::VideoEncoder {}; 49 50 // Interface of external video decoder for WebRTC. 51 class WebrtcVideoDecoder : public VideoDecoder, public webrtc::VideoDecoder {}; 52 53 class RecvSinkProxy : public webrtc::VideoSinkInterface<webrtc::VideoFrame> { 54 public: 55 explicit RecvSinkProxy(WebrtcVideoConduit* aOwner) : mOwner(aOwner) {} 56 57 private: 58 void OnFrame(const webrtc::VideoFrame& aFrame) override; 59 60 WebrtcVideoConduit* const mOwner; 61 }; 62 63 class SendSinkProxy : public webrtc::VideoSinkInterface<webrtc::VideoFrame> { 64 public: 65 explicit SendSinkProxy(WebrtcVideoConduit* aOwner) : mOwner(aOwner) {} 66 67 private: 68 void OnFrame(const webrtc::VideoFrame& aFrame) override; 69 70 WebrtcVideoConduit* const mOwner; 71 }; 72 73 /** 74 * Concrete class for Video session. Hooks up 75 * - media-source and target to external transport 76 */ 77 class WebrtcVideoConduit : public VideoSessionConduit, 78 public webrtc::RtcpEventObserver { 79 friend class RecvSinkProxy; 80 friend class SendSinkProxy; 81 82 public: 83 // Returns true when both encoder and decoder are HW accelerated. 84 static bool HasH264Hardware(); 85 // Returns true when AV1 is supported in the build. 86 static bool HasAv1(); 87 88 Maybe<int> ActiveSendPayloadType() const override; 89 Maybe<int> ActiveRecvPayloadType() const override; 90 91 /** 92 * Function to attach Renderer end-point for the Media-Video conduit. 93 * @param aRenderer : Reference to the concrete mozilla Video renderer 94 * implementation Note: Multiple invocations of this API shall remove an 95 * existing renderer and attaches the new to the Conduit. 96 */ 97 MediaConduitErrorCode AttachRenderer( 98 RefPtr<mozilla::VideoRenderer> aVideoRenderer) override; 99 void DetachRenderer() override; 100 101 Maybe<uint16_t> RtpSendBaseSeqFor(uint32_t aSsrc) const override; 102 103 const dom::RTCStatsTimestampMaker& GetTimestampMaker() const override; 104 105 void StopTransmitting(); 106 void StartTransmitting(); 107 void StopReceiving(); 108 void StartReceiving(); 109 110 void SetTrackSource(webrtc::VideoTrackSourceInterface* aSource) override; 111 112 bool LockScaling() const override { return mLockScaling; } 113 114 bool SendRtp(const uint8_t* aData, size_t aLength, 115 const webrtc::PacketOptions& aOptions) override; 116 bool SendSenderRtcp(const uint8_t* aData, size_t aLength) override; 117 bool SendReceiverRtcp(const uint8_t* aData, size_t aLength) override; 118 119 void OnRecvFrame(const webrtc::VideoFrame& aFrame); 120 121 /** 122 * Function to observe a video frame that was just passed to libwebrtc for 123 * encoding and transport. 124 * 125 * Note that this is called async while the call to libwebrtc is sync, to 126 * avoid a deadlock because webrtc::VideoBroadcaster holds its lock while 127 * calling mSendSinkProxy, and this function locks mMutex. DeleteSendStream 128 * locks those locks in reverse order. 129 */ 130 void OnSendFrame(const webrtc::VideoFrame& aFrame); 131 132 bool HasCodecPluginID(uint64_t aPluginID) const override; 133 134 RefPtr<GenericPromise> Shutdown() override; 135 136 // Call thread only. 137 bool IsShutdown() const override; 138 139 bool Denoising() const { return mDenoising; } 140 141 uint8_t SpatialLayers() const { return mSpatialLayers; } 142 143 uint8_t TemporalLayers() const { return mTemporalLayers; } 144 145 webrtc::VideoCodecMode CodecMode() const; 146 147 webrtc::DegradationPreference DegradationPreference() const; 148 149 WebrtcVideoConduit(RefPtr<WebrtcCallWrapper> aCall, 150 nsCOMPtr<nsISerialEventTarget> aStsThread, 151 Options aOptions, std::string aPCHandle, 152 const TrackingId& aRecvTrackingId); 153 virtual ~WebrtcVideoConduit(); 154 155 // Call thread. 156 void InitControl(VideoConduitControlInterface* aControl) override; 157 158 // Called when a parameter in mControl has changed. Call thread. 159 void OnControlConfigChange(); 160 161 // Necessary Init steps on main thread. 162 MediaConduitErrorCode Init(); 163 164 Ssrcs GetLocalSSRCs() const override; 165 Maybe<Ssrc> GetAssociatedLocalRtxSSRC(Ssrc aSsrc) const override; 166 Maybe<Ssrc> GetRemoteSSRC() const override; 167 168 Maybe<gfx::IntSize> GetLastResolution() const override; 169 170 // Call thread. 171 void UnsetRemoteSSRC(uint32_t aSsrc) override; 172 173 static unsigned ToLibwebrtcMaxFramerate(const Maybe<double>& aMaxFramerate); 174 175 private: 176 void NotifyUnsetCurrentRemoteSSRC(); 177 void SetRemoteSSRCConfig(uint32_t aSsrc, uint32_t aRtxSsrc); 178 void SetRemoteSSRCAndRestartAsNeeded(uint32_t aSsrc, uint32_t aRtxSsrc); 179 webrtc::RefCountedObject<mozilla::VideoStreamFactory>* 180 CreateVideoStreamFactory(); 181 182 public: 183 // Creating a recv stream or a send stream requires a local ssrc to be 184 // configured. This method will generate one if needed. 185 void EnsureLocalSSRC(); 186 // Creating a recv stream requires a remote ssrc to be configured. This method 187 // will generate one if needed. 188 void EnsureRemoteSSRC(); 189 190 Maybe<webrtc::VideoReceiveStreamInterface::Stats> GetReceiverStats() 191 const override; 192 Maybe<webrtc::VideoSendStream::Stats> GetSenderStats() const override; 193 Maybe<webrtc::CallBasicStats> GetCallStats() const override; 194 195 bool AddFrameHistory(dom::Sequence<dom::RTCVideoFrameHistoryInternal>* 196 outHistories) const override; 197 198 void SetJitterBufferTarget(DOMHighResTimeStamp aTargetMs) override; 199 200 uint64_t MozVideoLatencyAvg(); 201 202 void DisableSsrcChanges() override { 203 MOZ_ASSERT(mCallThread->IsOnCurrentThread()); 204 mAllowSsrcChange = false; 205 } 206 207 void CollectTelemetryData() override; 208 209 void OnRtpReceived(webrtc::RtpPacketReceived&& aPacket, 210 webrtc::RTPHeader&& aHeader); 211 void OnRtcpReceived(webrtc::CopyOnWriteBuffer&& aPacket); 212 213 void OnRtcpBye() override; 214 void OnRtcpTimeout() override; 215 216 void SetTransportActive(bool aActive) override; 217 218 MediaEventSourceExc<MediaPacket>& SenderRtpSendEvent() override { 219 return mSenderRtpSendEvent; 220 } 221 MediaEventSourceExc<MediaPacket>& SenderRtcpSendEvent() override { 222 return mSenderRtcpSendEvent; 223 } 224 MediaEventSourceExc<MediaPacket>& ReceiverRtcpSendEvent() override { 225 return mReceiverRtcpSendEvent; 226 } 227 void ConnectReceiverRtpEvent( 228 MediaEventSourceExc<webrtc::RtpPacketReceived, webrtc::RTPHeader>& aEvent) 229 override { 230 mReceiverRtpEventListener = 231 aEvent.Connect(mCallThread, this, &WebrtcVideoConduit::OnRtpReceived); 232 } 233 void ConnectReceiverRtcpEvent( 234 MediaEventSourceExc<webrtc::CopyOnWriteBuffer>& aEvent) override { 235 mReceiverRtcpEventListener = 236 aEvent.Connect(mCallThread, this, &WebrtcVideoConduit::OnRtcpReceived); 237 } 238 void ConnectSenderRtcpEvent( 239 MediaEventSourceExc<webrtc::CopyOnWriteBuffer>& aEvent) override { 240 mSenderRtcpEventListener = 241 aEvent.Connect(mCallThread, this, &WebrtcVideoConduit::OnRtcpReceived); 242 } 243 244 AbstractCanonical<Maybe<gfx::IntSize>>* CanonicalReceivingSize() override { 245 return &mReceivingSize; 246 } 247 248 const std::vector<webrtc::RtpSource>& GetUpstreamRtpSources() const override; 249 250 void RequestKeyFrame(FrameTransformerProxy* aProxy) override; 251 void GenerateKeyFrame(const Maybe<std::string>& aRid, 252 FrameTransformerProxy* aProxy) override; 253 254 private: 255 // Don't allow copying/assigning. 256 WebrtcVideoConduit(const WebrtcVideoConduit&) = delete; 257 void operator=(const WebrtcVideoConduit&) = delete; 258 259 // Utility function to dump recv codec database 260 void DumpCodecDB() const; 261 262 // Video Latency Test averaging filter 263 void VideoLatencyUpdate(uint64_t aNewSample); 264 265 // Call thread only, called before DeleteSendStream if streams need recreation 266 void MemoSendStreamStats(); 267 268 void CreateSendStream(); 269 void DeleteSendStream(); 270 void CreateRecvStream(); 271 void DeleteRecvStream(); 272 273 // Call thread only. 274 // Should only be called from Shutdown() 275 void SetIsShutdown(); 276 277 void DeliverPacket(webrtc::CopyOnWriteBuffer packet, 278 PacketType type) override; 279 280 MediaEventSource<void>& RtcpByeEvent() override { return mRtcpByeEvent; } 281 MediaEventSource<void>& RtcpTimeoutEvent() override { 282 return mRtcpTimeoutEvent; 283 } 284 MediaEventSource<void>& RtpPacketEvent() override { return mRtpPacketEvent; } 285 286 bool RequiresNewSendStream(const VideoCodecConfig& newConfig) const; 287 288 mutable mozilla::ReentrantMonitor mRendererMonitor MOZ_UNANNOTATED; 289 290 // Accessed on any thread under mRendererMonitor. 291 RefPtr<mozilla::VideoRenderer> mRenderer; 292 293 // WEBRTC.ORG Call API 294 // Const so can be accessed on any thread. All methods are called on the Call 295 // thread. 296 const RefPtr<WebrtcCallWrapper> mCall; 297 298 // Call worker thread. All access to mCall->Call() happens here. 299 const nsCOMPtr<nsISerialEventTarget> mCallThread; 300 301 // Socket transport service thread that runs stats queries against us. Any 302 // thread. 303 const nsCOMPtr<nsISerialEventTarget> mStsThread; 304 305 // XXX 306 const RefPtr<AbstractThread> mFrameRecvThread; 307 308 // Thread on which we are fed video frames. Set lazily on first call to 309 // SendVideoFrame(). 310 nsCOMPtr<nsISerialEventTarget> mFrameSendingThread; 311 312 struct Control { 313 // Mirrors that map to VideoConduitControlInterface for control. Call thread 314 // only. 315 Mirror<bool> mReceiving; 316 Mirror<bool> mTransmitting; 317 Mirror<Ssrcs> mLocalSsrcs; 318 Mirror<Ssrcs> mLocalRtxSsrcs; 319 Mirror<std::string> mLocalCname; 320 Mirror<std::string> mMid; 321 Mirror<Ssrc> mRemoteSsrc; 322 Mirror<Ssrc> mRemoteRtxSsrc; 323 Mirror<std::string> mSyncGroup; 324 Mirror<RtpExtList> mLocalRecvRtpExtensions; 325 Mirror<RtpExtList> mLocalSendRtpExtensions; 326 Mirror<Maybe<VideoCodecConfig>> mSendCodec; 327 Mirror<Maybe<RtpRtcpConfig>> mSendRtpRtcpConfig; 328 Mirror<std::vector<VideoCodecConfig>> mRecvCodecs; 329 Mirror<Maybe<RtpRtcpConfig>> mRecvRtpRtcpConfig; 330 Mirror<webrtc::VideoCodecMode> mCodecMode; 331 Mirror<RefPtr<FrameTransformerProxy>> mFrameTransformerProxySend; 332 Mirror<RefPtr<FrameTransformerProxy>> mFrameTransformerProxyRecv; 333 Mirror<webrtc::DegradationPreference> mVideoDegradationPreference; 334 335 // For caching mRemoteSsrc and mRemoteRtxSsrc, since another caller may 336 // change the remote ssrc in the stream config directly. 337 Ssrc mConfiguredRemoteSsrc = 0; 338 Ssrc mConfiguredRemoteRtxSsrc = 0; 339 // For tracking changes to mSendCodec and mSendRtpRtcpConfig. 340 Maybe<VideoCodecConfig> mConfiguredSendCodec; 341 Maybe<RtpRtcpConfig> mConfiguredSendRtpRtcpConfig; 342 // For tracking changes to mRecvCodecs and mRecvRtpRtcpConfig. 343 std::vector<VideoCodecConfig> mConfiguredRecvCodecs; 344 Maybe<RtpRtcpConfig> mConfiguredRecvRtpRtcpConfig; 345 // For tracking changes to mVideoDegradationPreference 346 webrtc::DegradationPreference mConfiguredDegradationPreference = 347 webrtc::DegradationPreference::DISABLED; 348 349 // For change tracking. Callthread only. 350 RefPtr<FrameTransformerProxy> mConfiguredFrameTransformerProxySend; 351 RefPtr<FrameTransformerProxy> mConfiguredFrameTransformerProxyRecv; 352 353 Control() = delete; 354 explicit Control(const RefPtr<AbstractThread>& aCallThread); 355 } mControl; 356 357 // Canonical for mirroring mReceivingWidth and mReceivingHeight. Call thread 358 // only. 359 Canonical<Maybe<gfx::IntSize>> mReceivingSize; 360 361 // WatchManager allowing Mirrors and other watch targets to trigger functions 362 // that will update the webrtc.org configuration. 363 WatchManager<WebrtcVideoConduit> mWatchManager; 364 365 mutable Mutex mMutex MOZ_UNANNOTATED; 366 367 // Decoder factory used by mRecvStream when it needs new decoders. This is 368 // not shared broader like some state in the WebrtcCallWrapper because it 369 // handles CodecPluginID plumbing tied to this VideoConduit. 370 const UniquePtr<WebrtcVideoDecoderFactory> mDecoderFactory; 371 372 // Encoder factory used by mSendStream when it needs new encoders. This is 373 // not shared broader like some state in the WebrtcCallWrapper because it 374 // handles CodecPluginID plumbing tied to this VideoConduit. 375 const UniquePtr<WebrtcVideoEncoderFactory> mEncoderFactory; 376 377 // These sink proxies are needed because both the recv and send sides of the 378 // conduit need to implement webrtc::VideoSinkInterface<webrtc::VideoFrame>. 379 RecvSinkProxy mRecvSinkProxy; 380 SendSinkProxy mSendSinkProxy; 381 382 // The track source that passes video frames to the libwebrtc send stream, and 383 // to mSendSinkProxy. 384 RefPtr<webrtc::VideoTrackSourceInterface> mTrackSource; 385 386 // Engine state we are concerned with. Written on the Call thread and read 387 // anywhere. 388 mozilla::Atomic<bool> 389 mEngineTransmitting; // If true ==> Transmit Subsystem is up and running 390 mozilla::Atomic<bool> 391 mEngineReceiving; // if true ==> Receive Subsystem up and running 392 393 // Written only on the Call thread. Guarded by mMutex, except for reads on the 394 // Call thread. 395 Maybe<VideoCodecConfig> mCurSendCodecConfig; 396 397 // Bookkeeping of stats for telemetry. Call thread only. 398 RunningStat mSendFramerate; 399 RunningStat mSendBitrate; 400 RunningStat mRecvFramerate; 401 RunningStat mRecvBitrate; 402 403 // Must call webrtc::Call::DestroyVideoReceive/SendStream to delete this. 404 // Written only on the Call thread. Guarded by mMutex, except for reads on the 405 // Call thread. 406 webrtc::VideoReceiveStreamInterface* mRecvStream = nullptr; 407 408 // Must call webrtc::Call::DestroyVideoReceive/SendStream to delete this. 409 webrtc::VideoSendStream* mSendStream = nullptr; 410 411 // Size of the most recently sent video frame. Call thread only. 412 Maybe<gfx::IntSize> mLastSize; 413 414 // Written on the frame feeding thread, the timestamp of the last frame on the 415 // send side. This is a local timestamp using the system clock with an 416 // unspecified epoch (Like mozilla::TimeStamp). Guarded by mMutex. 417 Maybe<webrtc::Timestamp> mLastTimestampSend; 418 419 // Written on the frame receive thread, the rtp timestamp of the last frame 420 // on the receive side, in 90kHz base. This comes from the RTP packet. 421 // Guarded by mMutex. 422 Maybe<uint32_t> mLastRTPTimestampReceive; 423 424 // Accessed from any thread under mRendererMonitor. 425 uint64_t mVideoLatencyAvg = 0; 426 427 const bool mVideoLatencyTestEnable; 428 429 // All in bps. 430 const int mMinBitrate; 431 const int mStartBitrate; 432 const int mPrefMaxBitrate; 433 const int mMinBitrateEstimate; 434 435 // Max bitrate in bps as provided by negotiation. Call thread only. 436 int mNegotiatedMaxBitrate = 0; 437 438 // Set to true to force denoising on. 439 const bool mDenoising; 440 441 // Set to true to ignore sink wants (scaling due to bwe and cpu usage) and 442 // degradation preference (always use MAINTAIN_RESOLUTION). 443 const bool mLockScaling; 444 445 const uint8_t mSpatialLayers; 446 const uint8_t mTemporalLayers; 447 448 static const unsigned int sAlphaNum = 7; 449 static const unsigned int sAlphaDen = 8; 450 static const unsigned int sRoundingPadding = 1024; 451 452 // Target jitter buffer to be applied to the receive stream in milliseconds. 453 uint16_t mJitterBufferTargetMs = 0; 454 455 // Set up in the ctor and then not touched. Called through by the streams on 456 // any thread. Safe since we own and control the lifetime of the streams. 457 WebrtcSendTransport mSendTransport; 458 WebrtcReceiveTransport mRecvTransport; 459 460 // Written only on the Call thread. Guarded by mMutex, except for reads on the 461 // Call thread. Typical non-Call thread access is on the frame delivery 462 // thread. 463 webrtc::VideoSendStream::Config mSendStreamConfig; 464 465 // Call thread only. 466 webrtc::VideoEncoderConfig mEncoderConfig; 467 468 // Written only on the Call thread. Guarded by mMutex, except for reads on the 469 // Call thread. Calls can happen under mMutex on any thread. 470 DataMutex<RefPtr<webrtc::RefCountedObject<VideoStreamFactory>>> 471 mVideoStreamFactory; 472 473 // Call thread only. 474 webrtc::VideoReceiveStreamInterface::Config mRecvStreamConfig; 475 476 // Are SSRC changes without signaling allowed or not. 477 // Call thread only. 478 bool mAllowSsrcChange = true; 479 480 // Accessed during configuration/signaling (Call thread), and on the frame 481 // delivery thread for frame history tracking. Set only on the Call thread. 482 Atomic<uint32_t> mRecvSSRC = 483 Atomic<uint32_t>(0); // this can change during a stream! 484 485 // Accessed from both the STS and frame delivery thread for frame history 486 // tracking. Set when receiving packets. 487 Atomic<uint32_t> mRemoteSendSSRC = 488 Atomic<uint32_t>(0); // this can change during a stream! 489 490 // Main thread only 491 nsTArray<uint64_t> mSendCodecPluginIDs; 492 // Main thread only 493 nsTArray<uint64_t> mRecvCodecPluginIDs; 494 495 // Main thread only 496 MediaEventListener mSendPluginCreated; 497 MediaEventListener mSendPluginReleased; 498 MediaEventListener mRecvPluginCreated; 499 MediaEventListener mRecvPluginReleased; 500 501 // Call thread only. ssrc -> base_seq 502 std::map<uint32_t, uint16_t> mRtpSendBaseSeqs; 503 // libwebrtc network thread only. ssrc -> base_seq. 504 // To track changes needed to mRtpSendBaseSeqs. 505 std::map<uint32_t, uint16_t> mRtpSendBaseSeqs_n; 506 507 // Tracking the attributes of received frames over time 508 // Protected by mRendererMonitor 509 dom::RTCVideoFrameHistoryInternal mReceivedFrameHistory; 510 511 // Call thread only. 512 Canonical<std::vector<webrtc::RtpSource>> mCanonicalRtpSources; 513 514 // Main thread only mirror of mCanonicalRtpSources. 515 Mirror<std::vector<webrtc::RtpSource>> mRtpSources; 516 517 // Cache of stats that holds the send stream stats during the stream 518 // recreation process. After DeleteSendStream() then CreateSendStream() and 519 // before the codecs are initialized there is a gap where the send stream 520 // stats have no substreams. This holds onto the stats until the codecs are 521 // initialized and the send stream is recreated. 522 // It is mutable because we want to be able to invalidate the cache when a 523 // GetStats call is made. 524 // Call thread only. 525 mutable Maybe<webrtc::VideoSendStream::Stats> mTransitionalSendStreamStats; 526 527 // Thread safe 528 Atomic<bool> mTransportActive = Atomic<bool>(false); 529 MediaEventProducer<void> mRtcpByeEvent; 530 MediaEventProducer<void> mRtcpTimeoutEvent; 531 MediaEventProducer<void> mRtpPacketEvent; 532 MediaEventProducerExc<MediaPacket> mSenderRtpSendEvent; 533 MediaEventProducerExc<MediaPacket> mSenderRtcpSendEvent; 534 MediaEventProducerExc<MediaPacket> mReceiverRtcpSendEvent; 535 536 // Assigned and revoked on mStsThread. Listeners for receiving packets. 537 MediaEventListener mReceiverRtpEventListener; // Rtp-receiving pipeline 538 MediaEventListener mReceiverRtcpEventListener; // Rctp-receiving pipeline 539 MediaEventListener mSenderRtcpEventListener; // Rctp-sending pipeline 540 541 // Whether the conduit is shutdown or not. 542 // Call thread only. 543 bool mIsShutdown = false; 544 }; 545 } // namespace mozilla 546 547 #endif