1*d9f75844SAndroid Build Coastguard Worker<?% config.freshness.reviewed = '2021-04-12' %?> 2*d9f75844SAndroid Build Coastguard Worker 3*d9f75844SAndroid Build Coastguard Worker# PeerConnection level framework fixture architecture 4*d9f75844SAndroid Build Coastguard Worker 5*d9f75844SAndroid Build Coastguard Worker## Overview 6*d9f75844SAndroid Build Coastguard Worker 7*d9f75844SAndroid Build Coastguard WorkerThe main implementation of 8*d9f75844SAndroid Build Coastguard Worker[`webrtc::webrtc_pc_e2e::PeerConnectionE2EQualityTestFixture`][1] is 9*d9f75844SAndroid Build Coastguard Worker[`webrtc::webrtc_pc_e2e::PeerConnectionE2EQualityTest`][2]. Internally it owns 10*d9f75844SAndroid Build Coastguard Workerthe next main pieces: 11*d9f75844SAndroid Build Coastguard Worker 12*d9f75844SAndroid Build Coastguard Worker* [`MediaHelper`][3] - responsible for adding audio and video tracks to the 13*d9f75844SAndroid Build Coastguard Worker peers. 14*d9f75844SAndroid Build Coastguard Worker* [`VideoQualityAnalyzerInjectionHelper`][4] and 15*d9f75844SAndroid Build Coastguard Worker [`SingleProcessEncodedImageDataInjector`][5] - used to inject video quality 16*d9f75844SAndroid Build Coastguard Worker analysis and properly match captured and rendered video frames. You can read 17*d9f75844SAndroid Build Coastguard Worker more about it in 18*d9f75844SAndroid Build Coastguard Worker [DefaultVideoQualityAnalyzer](default_video_quality_analyzer.md) section. 19*d9f75844SAndroid Build Coastguard Worker* [`AudioQualityAnalyzerInterface`][6] - used to measure audio quality metrics 20*d9f75844SAndroid Build Coastguard Worker* [`TestActivitiesExecutor`][7] - used to support [`ExecuteAt(...)`][8] and 21*d9f75844SAndroid Build Coastguard Worker [`ExecuteEvery(...)`][9] API of `PeerConnectionE2EQualityTestFixture` to run 22*d9f75844SAndroid Build Coastguard Worker any arbitrary action during test execution timely synchronized with a test 23*d9f75844SAndroid Build Coastguard Worker call. 24*d9f75844SAndroid Build Coastguard Worker* A vector of [`QualityMetricsReporter`][10] added by the 25*d9f75844SAndroid Build Coastguard Worker `PeerConnectionE2EQualityTestFixture` user. 26*d9f75844SAndroid Build Coastguard Worker* Two peers: Alice and Bob represented by instances of [`TestPeer`][11] 27*d9f75844SAndroid Build Coastguard Worker object. 28*d9f75844SAndroid Build Coastguard Worker 29*d9f75844SAndroid Build Coastguard WorkerAlso it keeps a reference to [`webrtc::TimeController`][12], which is used to 30*d9f75844SAndroid Build Coastguard Workercreate all required threads, task queues, task queue factories and time related 31*d9f75844SAndroid Build Coastguard Workerobjects. 32*d9f75844SAndroid Build Coastguard Worker 33*d9f75844SAndroid Build Coastguard Worker## TestPeer 34*d9f75844SAndroid Build Coastguard Worker 35*d9f75844SAndroid Build Coastguard WorkerCall participants are represented by instances of `TestPeer` object. 36*d9f75844SAndroid Build Coastguard Worker[`TestPeerFactory`][13] is used to create them. `TestPeer` owns all instances 37*d9f75844SAndroid Build Coastguard Workerrelated to the `webrtc::PeerConnection`, including required listeners and 38*d9f75844SAndroid Build Coastguard Workercallbacks. Also it provides an API to do offer/answer exchange and ICE candidate 39*d9f75844SAndroid Build Coastguard Workerexchange. For this purposes internally it uses an instance of 40*d9f75844SAndroid Build Coastguard Worker[`webrtc::PeerConnectionWrapper`][14]. 41*d9f75844SAndroid Build Coastguard Worker 42*d9f75844SAndroid Build Coastguard WorkerThe `TestPeer` also owns the `PeerConnection` worker thread. The signaling 43*d9f75844SAndroid Build Coastguard Workerthread for all `PeerConnection`'s is owned by 44*d9f75844SAndroid Build Coastguard Worker`PeerConnectionE2EQualityTestFixture` and shared between all participants in the 45*d9f75844SAndroid Build Coastguard Workercall. The network thread is owned by the network layer (it maybe either emulated 46*d9f75844SAndroid Build Coastguard Workernetwork provided by [Network Emulation Framework][24] or network thread and 47*d9f75844SAndroid Build Coastguard Worker`rtc::NetworkManager` provided by user) and provided when peer is added to the 48*d9f75844SAndroid Build Coastguard Workerfixture via [`AddPeer(...)`][15] API. 49*d9f75844SAndroid Build Coastguard Worker 50*d9f75844SAndroid Build Coastguard Worker## GetStats API based metrics reporters 51*d9f75844SAndroid Build Coastguard Worker 52*d9f75844SAndroid Build Coastguard Worker`PeerConnectionE2EQualityTestFixture` gives the user ability to provide 53*d9f75844SAndroid Build Coastguard Workerdifferent `QualityMetricsReporter`s which will listen for `PeerConnection` 54*d9f75844SAndroid Build Coastguard Worker[`GetStats`][16] API. Then such reporters will be able to report various metrics 55*d9f75844SAndroid Build Coastguard Workerthat user wants to measure. 56*d9f75844SAndroid Build Coastguard Worker 57*d9f75844SAndroid Build Coastguard Worker`PeerConnectionE2EQualityTestFixture` itself also uses this mechanism to 58*d9f75844SAndroid Build Coastguard Workermeasure: 59*d9f75844SAndroid Build Coastguard Worker 60*d9f75844SAndroid Build Coastguard Worker* Audio quality metrics 61*d9f75844SAndroid Build Coastguard Worker* Audio/Video sync metrics (with help of [`CrossMediaMetricsReporter`][17]) 62*d9f75844SAndroid Build Coastguard Worker 63*d9f75844SAndroid Build Coastguard WorkerAlso framework provides a [`StatsBasedNetworkQualityMetricsReporter`][18] to 64*d9f75844SAndroid Build Coastguard Workermeasure network related WebRTC metrics and print debug raw emulated network 65*d9f75844SAndroid Build Coastguard Workerstatistic. This reporter should be added by user via 66*d9f75844SAndroid Build Coastguard Worker[`AddQualityMetricsReporter(...)`][19] API if requried. 67*d9f75844SAndroid Build Coastguard Worker 68*d9f75844SAndroid Build Coastguard WorkerInternally stats gathering is done by [`StatsPoller`][20]. Stats are requested 69*d9f75844SAndroid Build Coastguard Workeronce per second for each `PeerConnection` and then resulted object is provided 70*d9f75844SAndroid Build Coastguard Workerinto each stats listener. 71*d9f75844SAndroid Build Coastguard Worker 72*d9f75844SAndroid Build Coastguard Worker## Offer/Answer exchange 73*d9f75844SAndroid Build Coastguard Worker 74*d9f75844SAndroid Build Coastguard Worker`PeerConnectionE2EQualityTest` provides ability to test Simulcast and SVC for 75*d9f75844SAndroid Build Coastguard Workervideo. These features aren't supported by P2P call and in general requires a 76*d9f75844SAndroid Build Coastguard WorkerSelective Forwarding Unit (SFU). So special logic is applied to mimic SFU 77*d9f75844SAndroid Build Coastguard Workerbehavior in P2P call. This logic is located inside [`SignalingInterceptor`][21], 78*d9f75844SAndroid Build Coastguard Worker[`QualityAnalyzingVideoEncoder`][22] and [`QualityAnalyzingVideoDecoder`][23] 79*d9f75844SAndroid Build Coastguard Workerand consist of SDP modification during offer/answer exchange and special 80*d9f75844SAndroid Build Coastguard Workerhandling of video frames from unrelated Simulcast/SVC streams during decoding. 81*d9f75844SAndroid Build Coastguard Worker 82*d9f75844SAndroid Build Coastguard Worker### Simulcast 83*d9f75844SAndroid Build Coastguard Worker 84*d9f75844SAndroid Build Coastguard WorkerIn case of Simulcast we have a video track, which internally contains multiple 85*d9f75844SAndroid Build Coastguard Workervideo streams, for example low resolution, medium resolution and high 86*d9f75844SAndroid Build Coastguard Workerresolution. WebRTC client doesn't support receiving an offer with multiple 87*d9f75844SAndroid Build Coastguard Workerstreams in it, because usually SFU will keep only single stream for the client. 88*d9f75844SAndroid Build Coastguard WorkerTo bypass it framework will modify offer by converting a single track with three 89*d9f75844SAndroid Build Coastguard Workervideo streams into three independent video tracks. Then sender will think that 90*d9f75844SAndroid Build Coastguard Workerit send simulcast, but receiver will think that it receives 3 independent 91*d9f75844SAndroid Build Coastguard Workertracks. 92*d9f75844SAndroid Build Coastguard Worker 93*d9f75844SAndroid Build Coastguard WorkerTo achieve such behavior some extra tweaks are required: 94*d9f75844SAndroid Build Coastguard Worker 95*d9f75844SAndroid Build Coastguard Worker* MID RTP header extension from original offer have to be removed 96*d9f75844SAndroid Build Coastguard Worker* RID RTP header extension from original offer is replaced with MID RTP header 97*d9f75844SAndroid Build Coastguard Worker extension, so the ID that sender uses for RID on receiver will be parsed as 98*d9f75844SAndroid Build Coastguard Worker MID. 99*d9f75844SAndroid Build Coastguard Worker* Answer have to be modified in the opposite way. 100*d9f75844SAndroid Build Coastguard Worker 101*d9f75844SAndroid Build Coastguard WorkerDescribed modifications are illustrated on the picture below. 102*d9f75844SAndroid Build Coastguard Worker 103*d9f75844SAndroid Build Coastguard Worker 104*d9f75844SAndroid Build Coastguard Worker 105*d9f75844SAndroid Build Coastguard WorkerThe exchange will look like this: 106*d9f75844SAndroid Build Coastguard Worker 107*d9f75844SAndroid Build Coastguard Worker1. Alice creates an offer 108*d9f75844SAndroid Build Coastguard Worker2. Alice sets offer as local description 109*d9f75844SAndroid Build Coastguard Worker3. Do described offer modification 110*d9f75844SAndroid Build Coastguard Worker4. Alice sends modified offer to Bob 111*d9f75844SAndroid Build Coastguard Worker5. Bob sets modified offer as remote description 112*d9f75844SAndroid Build Coastguard Worker6. Bob creates answer 113*d9f75844SAndroid Build Coastguard Worker7. Bob sets answer as local description 114*d9f75844SAndroid Build Coastguard Worker8. Do reverse modifications on answer 115*d9f75844SAndroid Build Coastguard Worker9. Bob sends modified answer to Alice 116*d9f75844SAndroid Build Coastguard Worker10. Alice sets modified answer as remote description 117*d9f75844SAndroid Build Coastguard Worker 118*d9f75844SAndroid Build Coastguard WorkerSuch mechanism put a constraint that RTX streams are not supported, because they 119*d9f75844SAndroid Build Coastguard Workerdon't have RID RTP header extension in their packets. 120*d9f75844SAndroid Build Coastguard Worker 121*d9f75844SAndroid Build Coastguard Worker### SVC 122*d9f75844SAndroid Build Coastguard Worker 123*d9f75844SAndroid Build Coastguard WorkerIn case of SVC the framework will update the sender's offer before even setting 124*d9f75844SAndroid Build Coastguard Workerit as local description on the sender side. Then no changes to answer will be 125*d9f75844SAndroid Build Coastguard Workerrequired. 126*d9f75844SAndroid Build Coastguard Worker 127*d9f75844SAndroid Build Coastguard Worker`ssrc` is a 32 bit random value that is generated in RTP to denote a specific 128*d9f75844SAndroid Build Coastguard Workersource used to send media in an RTP connection. In original offer video track 129*d9f75844SAndroid Build Coastguard Workersection will look like this: 130*d9f75844SAndroid Build Coastguard Worker 131*d9f75844SAndroid Build Coastguard Worker``` 132*d9f75844SAndroid Build Coastguard Workerm=video 9 UDP/TLS/RTP/SAVPF 98 100 99 101 133*d9f75844SAndroid Build Coastguard Worker... 134*d9f75844SAndroid Build Coastguard Workera=ssrc-group:FID <primary ssrc> <retransmission ssrc> 135*d9f75844SAndroid Build Coastguard Workera=ssrc:<primary ssrc> cname:... 136*d9f75844SAndroid Build Coastguard Worker.... 137*d9f75844SAndroid Build Coastguard Workera=ssrc:<retransmission ssrc> cname:... 138*d9f75844SAndroid Build Coastguard Worker.... 139*d9f75844SAndroid Build Coastguard Worker``` 140*d9f75844SAndroid Build Coastguard Worker 141*d9f75844SAndroid Build Coastguard WorkerTo enable SVC for such video track framework will add extra `ssrc`s for each SVC 142*d9f75844SAndroid Build Coastguard Workerstream that is required like this: 143*d9f75844SAndroid Build Coastguard Worker 144*d9f75844SAndroid Build Coastguard Worker``` 145*d9f75844SAndroid Build Coastguard Workera=ssrc-group:FID <Low resolution primary ssrc> <Low resolution retransmission ssrc> 146*d9f75844SAndroid Build Coastguard Workera=ssrc:<Low resolution primary ssrc> cname:... 147*d9f75844SAndroid Build Coastguard Worker.... 148*d9f75844SAndroid Build Coastguard Workera=ssrc:<Low resolution retransmission ssrc> cname:.... 149*d9f75844SAndroid Build Coastguard Worker... 150*d9f75844SAndroid Build Coastguard Workera=ssrc-group:FID <Medium resolution primary ssrc> <Medium resolution retransmission ssrc> 151*d9f75844SAndroid Build Coastguard Workera=ssrc:<Medium resolution primary ssrc> cname:... 152*d9f75844SAndroid Build Coastguard Worker.... 153*d9f75844SAndroid Build Coastguard Workera=ssrc:<Medium resolution retransmission ssrc> cname:.... 154*d9f75844SAndroid Build Coastguard Worker... 155*d9f75844SAndroid Build Coastguard Workera=ssrc-group:FID <High resolution primary ssrc> <High resolution retransmission ssrc> 156*d9f75844SAndroid Build Coastguard Workera=ssrc:<High resolution primary ssrc> cname:... 157*d9f75844SAndroid Build Coastguard Worker.... 158*d9f75844SAndroid Build Coastguard Workera=ssrc:<High resolution retransmission ssrc> cname:.... 159*d9f75844SAndroid Build Coastguard Worker... 160*d9f75844SAndroid Build Coastguard Worker``` 161*d9f75844SAndroid Build Coastguard Worker 162*d9f75844SAndroid Build Coastguard WorkerThe next line will also be added to the video track section of the offer: 163*d9f75844SAndroid Build Coastguard Worker 164*d9f75844SAndroid Build Coastguard Worker``` 165*d9f75844SAndroid Build Coastguard Workera=ssrc-group:SIM <Low resolution primary ssrc> <Medium resolution primary ssrc> <High resolution primary ssrc> 166*d9f75844SAndroid Build Coastguard Worker``` 167*d9f75844SAndroid Build Coastguard Worker 168*d9f75844SAndroid Build Coastguard WorkerIt will tell PeerConnection that this track should be configured as SVC. It 169*d9f75844SAndroid Build Coastguard Workerutilize WebRTC Plan B offer structure to achieve SVC behavior, also it modifies 170*d9f75844SAndroid Build Coastguard Workeroffer before setting it as local description which violates WebRTC standard. 171*d9f75844SAndroid Build Coastguard WorkerAlso it adds limitations that on lossy networks only top resolution streams can 172*d9f75844SAndroid Build Coastguard Workerbe analyzed, because WebRTC won't try to restore low resolution streams in case 173*d9f75844SAndroid Build Coastguard Workerof loss, because it still receives higher stream. 174*d9f75844SAndroid Build Coastguard Worker 175*d9f75844SAndroid Build Coastguard Worker### Handling in encoder/decoder 176*d9f75844SAndroid Build Coastguard Worker 177*d9f75844SAndroid Build Coastguard WorkerIn the encoder, the framework for each encoded video frame will propagate 178*d9f75844SAndroid Build Coastguard Workerinformation requried for the fake SFU to know if it belongs to an interesting 179*d9f75844SAndroid Build Coastguard Workersimulcast stream/spatial layer of if it should be "discarded". 180*d9f75844SAndroid Build Coastguard Worker 181*d9f75844SAndroid Build Coastguard WorkerOn the decoder side frames that should be "discarded" by fake SFU will be auto 182*d9f75844SAndroid Build Coastguard Workerdecoded into single pixel images and only the interesting simulcast 183*d9f75844SAndroid Build Coastguard Workerstream/spatial layer will go into real decoder and then will be analyzed. 184*d9f75844SAndroid Build Coastguard Worker 185*d9f75844SAndroid Build Coastguard Worker[1]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/api/test/peerconnection_quality_test_fixture.h;l=55;drc=484acf27231d931dbc99aedce85bc27e06486b96 186*d9f75844SAndroid Build Coastguard Worker[2]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/test/pc/e2e/peer_connection_quality_test.h;l=44;drc=6cc893ad778a0965e2b7a8e614f3c98aa81bee5b 187*d9f75844SAndroid Build Coastguard Worker[3]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/test/pc/e2e/media/media_helper.h;l=27;drc=d46db9f1523ae45909b4a6fdc90a140443068bc6 188*d9f75844SAndroid Build Coastguard Worker[4]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/test/pc/e2e/analyzer/video/video_quality_analyzer_injection_helper.h;l=38;drc=79020414fd5c71f9ec1f25445ea5f1c8001e1a49 189*d9f75844SAndroid Build Coastguard Worker[5]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/test/pc/e2e/analyzer/video/single_process_encoded_image_data_injector.h;l=40;drc=79020414fd5c71f9ec1f25445ea5f1c8001e1a49 190*d9f75844SAndroid Build Coastguard Worker[6]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/api/test/audio_quality_analyzer_interface.h;l=23;drc=20f45823e37fd7272aa841831c029c21f29742c2 191*d9f75844SAndroid Build Coastguard Worker[7]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/test/pc/e2e/test_activities_executor.h;l=28;drc=6cc893ad778a0965e2b7a8e614f3c98aa81bee5b 192*d9f75844SAndroid Build Coastguard Worker[8]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/api/test/peerconnection_quality_test_fixture.h;l=439;drc=484acf27231d931dbc99aedce85bc27e06486b96 193*d9f75844SAndroid Build Coastguard Worker[9]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/api/test/peerconnection_quality_test_fixture.h;l=445;drc=484acf27231d931dbc99aedce85bc27e06486b96 194*d9f75844SAndroid Build Coastguard Worker[10]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/api/test/peerconnection_quality_test_fixture.h;l=413;drc=9438fb3fff97c803d1ead34c0e4f223db168526f 195*d9f75844SAndroid Build Coastguard Worker[11]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/test/pc/e2e/test_activities_executor.h;l=28;drc=6cc893ad778a0965e2b7a8e614f3c98aa81bee5b 196*d9f75844SAndroid Build Coastguard Worker[12]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/test/pc/e2e/test_activities_executor.h;l=28;drc=6cc893ad778a0965e2b7a8e614f3c98aa81bee5b 197*d9f75844SAndroid Build Coastguard Worker[13]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/test/pc/e2e/test_peer_factory.h;l=46;drc=0ef4a2488a466a24ab97b31fdddde55440d451f9 198*d9f75844SAndroid Build Coastguard Worker[14]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/pc/peer_connection_wrapper.h;l=47;drc=5ab79e62f691875a237ea28ca3975ea1f0ed62ec 199*d9f75844SAndroid Build Coastguard Worker[15]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/api/test/peerconnection_quality_test_fixture.h;l=459;drc=484acf27231d931dbc99aedce85bc27e06486b96 200*d9f75844SAndroid Build Coastguard Worker[16]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/api/peer_connection_interface.h;l=886;drc=9438fb3fff97c803d1ead34c0e4f223db168526f 201*d9f75844SAndroid Build Coastguard Worker[17]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/test/pc/e2e/cross_media_metrics_reporter.h;l=29;drc=9d777620236ec76754cfce19f6e82dd18e52d22c 202*d9f75844SAndroid Build Coastguard Worker[18]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/test/pc/e2e/cross_media_metrics_reporter.h;l=29;drc=9d777620236ec76754cfce19f6e82dd18e52d22c 203*d9f75844SAndroid Build Coastguard Worker[19]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/api/test/peerconnection_quality_test_fixture.h;l=450;drc=484acf27231d931dbc99aedce85bc27e06486b96 204*d9f75844SAndroid Build Coastguard Worker[20]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/test/pc/e2e/stats_poller.h;l=52;drc=9b526180c9e9722d3fc7f8689da6ec094fc7fc0a 205*d9f75844SAndroid Build Coastguard Worker[21]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/test/pc/e2e/sdp/sdp_changer.h;l=79;drc=ee558dcca89fd8b105114ededf9e74d948da85e8 206*d9f75844SAndroid Build Coastguard Worker[22]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/test/pc/e2e/analyzer/video/quality_analyzing_video_encoder.h;l=54;drc=79020414fd5c71f9ec1f25445ea5f1c8001e1a49 207*d9f75844SAndroid Build Coastguard Worker[23]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/webrtc/test/pc/e2e/analyzer/video/quality_analyzing_video_decoder.h;l=50;drc=79020414fd5c71f9ec1f25445ea5f1c8001e1a49 208*d9f75844SAndroid Build Coastguard Worker[24]: /test/network/g3doc/index.md 209