summaryrefslogtreecommitdiffstats
path: root/third_party/libwebrtc/webrtc/test
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/libwebrtc/webrtc/test')
-rw-r--r--third_party/libwebrtc/webrtc/test/BUILD.gn729
-rw-r--r--third_party/libwebrtc/webrtc/test/DEPS43
-rw-r--r--third_party/libwebrtc/webrtc/test/OWNERS2
-rw-r--r--third_party/libwebrtc/webrtc/test/android/AndroidManifest.xml46
-rw-r--r--third_party/libwebrtc/webrtc/test/android/org/webrtc/native_test/RTCNativeUnitTest.java26
-rw-r--r--third_party/libwebrtc/webrtc/test/android/org/webrtc/native_test/RTCNativeUnitTestActivity.java34
-rw-r--r--third_party/libwebrtc/webrtc/test/call_test.cc619
-rw-r--r--third_party/libwebrtc/webrtc/test/call_test.h249
-rw-r--r--third_party/libwebrtc/webrtc/test/configurable_frame_size_encoder.cc93
-rw-r--r--third_party/libwebrtc/webrtc/test/configurable_frame_size_encoder.h59
-rw-r--r--third_party/libwebrtc/webrtc/test/constants.cc25
-rw-r--r--third_party/libwebrtc/webrtc/test/constants.h22
-rw-r--r--third_party/libwebrtc/webrtc/test/direct_transport.cc126
-rw-r--r--third_party/libwebrtc/webrtc/test/direct_transport.h86
-rw-r--r--third_party/libwebrtc/webrtc/test/drifting_clock.cc56
-rw-r--r--third_party/libwebrtc/webrtc/test/drifting_clock.h45
-rw-r--r--third_party/libwebrtc/webrtc/test/encoder_settings.cc102
-rw-r--r--third_party/libwebrtc/webrtc/test/encoder_settings.h56
-rw-r--r--third_party/libwebrtc/webrtc/test/fake_audio_device.cc380
-rw-r--r--third_party/libwebrtc/webrtc/test/fake_audio_device.h144
-rw-r--r--third_party/libwebrtc/webrtc/test/fake_audio_device_unittest.cc131
-rw-r--r--third_party/libwebrtc/webrtc/test/fake_decoder.cc86
-rw-r--r--third_party/libwebrtc/webrtc/test/fake_decoder.h76
-rw-r--r--third_party/libwebrtc/webrtc/test/fake_encoder.cc377
-rw-r--r--third_party/libwebrtc/webrtc/test/fake_encoder.h137
-rw-r--r--third_party/libwebrtc/webrtc/test/fake_network_pipe.cc255
-rw-r--r--third_party/libwebrtc/webrtc/test/fake_network_pipe.h185
-rw-r--r--third_party/libwebrtc/webrtc/test/fake_network_pipe_unittest.cc445
-rw-r--r--third_party/libwebrtc/webrtc/test/fake_texture_frame.cc25
-rw-r--r--third_party/libwebrtc/webrtc/test/fake_texture_frame.h48
-rw-r--r--third_party/libwebrtc/webrtc/test/fake_videorenderer.h28
-rw-r--r--third_party/libwebrtc/webrtc/test/field_trial.cc93
-rw-r--r--third_party/libwebrtc/webrtc/test/field_trial.h49
-rw-r--r--third_party/libwebrtc/webrtc/test/frame_generator.cc457
-rw-r--r--third_party/libwebrtc/webrtc/test/frame_generator.h104
-rw-r--r--third_party/libwebrtc/webrtc/test/frame_generator_capturer.cc273
-rw-r--r--third_party/libwebrtc/webrtc/test/frame_generator_capturer.h114
-rw-r--r--third_party/libwebrtc/webrtc/test/frame_generator_unittest.cc189
-rw-r--r--third_party/libwebrtc/webrtc/test/frame_utils.cc91
-rw-r--r--third_party/libwebrtc/webrtc/test/frame_utils.h48
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/BUILD.gn411
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/DEPS3
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/OWNERS1
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/audio_decoder_fuzzer.cc99
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/audio_decoder_fuzzer.h40
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/audio_decoder_ilbc_fuzzer.cc23
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/audio_decoder_isac_fuzzer.cc23
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/audio_decoder_isac_incoming_packet_fuzzer.cc19
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/audio_decoder_isacfix_fuzzer.cc23
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/audio_decoder_opus_fuzzer.cc24
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/audio_decoder_opus_redundant_fuzzer.cc24
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/audio_processing_fuzzer.cc156
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/audio_processing_fuzzer.h27
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/audio_processing_fuzzer_configs.cc99
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/congestion_controller_feedback_fuzzer.cc49
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/README34
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/pseudotcp-corpus/785b96587d0eb44dd5d75b7a886f37e2ac504511bin0 -> 24 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/0.rtcpbin0 -> 72 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/1.rtcpbin0 -> 24 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/10.rtcpbin0 -> 76 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/11.rtcpbin0 -> 12 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/12.rtcpbin0 -> 16 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/13.rtcpbin0 -> 12 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/14.rtcpbin0 -> 40 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/15.rtcpbin0 -> 20 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/16.rtcpbin0 -> 16 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/17.rtcpbin0 -> 12 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/18.rtcpbin0 -> 28 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/19.rtcpbin0 -> 12 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/2.rtcpbin0 -> 12 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/20.rtcpbin0 -> 8 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/21.rtcpbin0 -> 8 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/22.rtcpbin0 -> 8 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/23.rtcpbin0 -> 20 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/24.rtcpbin0 -> 8 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/25.rtcpbin0 -> 20 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/26.rtcpbin0 -> 12 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/27.rtcpbin0 -> 8 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/28.rtcpbin0 -> 12 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/29.rtcpbin0 -> 56 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/3.rtcpbin0 -> 12 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/30.rtcpbin0 -> 28 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/31.rtcpbin0 -> 28 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/32.rtcpbin0 -> 8 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/33.rtcpbin0 -> 32 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/34.rtcpbin0 -> 32 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/35.rtcpbin0 -> 16 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/36.rtcpbin0 -> 52 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/37.rtcpbin0 -> 12 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/38.rtcpbin0 -> 20 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/39.rtcpbin0 -> 12 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/4.rtcpbin0 -> 20 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/40.rtcpbin0 -> 24 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/41.rtcpbin0 -> 20 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/42.rtcpbin0 -> 11 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/43.rtcpbin0 -> 36 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/44.rtcpbin0 -> 32 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/45.rtcpbin0 -> 32 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/46.rtcpbin0 -> 32 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/47.rtcp1
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/48.rtcpbin0 -> 16 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/49.rtcpbin0 -> 24 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/5.rtcpbin0 -> 20 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/50.rtcpbin0 -> 4 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/51.rtcpbin0 -> 20 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/52.rtcpbin0 -> 32 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/53.rtcpbin0 -> 4 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/54.rtcpbin0 -> 12 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/55.rtcp0
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/56.rtcpbin0 -> 8 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/57.rtcpbin0 -> 20 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/58.rtcpbin0 -> 20 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/59.rtcpbin0 -> 4 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/6.rtcpbin0 -> 16 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/60.rtcpbin0 -> 28 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/61.rtcpbin0 -> 44 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/62.rtcpbin0 -> 4 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/63.rtcpbin0 -> 40 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/64.rtcpbin0 -> 20 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/65.rtcpbin0 -> 16 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/66.rtcpbin0 -> 4 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/7.rtcpbin0 -> 16 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/8.rtcpbin0 -> 4 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/9.rtcpbin0 -> 16 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtp-corpus/rtp-0bin0 -> 12 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtp-corpus/rtp-1bin0 -> 20 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtp-corpus/rtp-2bin0 -> 24 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtp-corpus/rtp-3bin0 -> 43 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtp-corpus/rtp-4bin0 -> 20 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/10.sdp11
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/11.sdp10
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/12.sdp9
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/13.sdp9
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/14.sdp9
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/15.sdp9
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/16.sdp10
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/17.sdp10
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/18.sdp9
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/19.sdp9
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/2.sdp12
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/20.sdp10
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/21.sdp10
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/22.sdp12
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/23.sdp10
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/24.sdp8
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/25.sdp8
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/26.sdp7
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/27.sdp7
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/28.sdp11
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/29.sdp10
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/3.sdp9
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/30.sdp11
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/31.sdp11
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/32.sdp8
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/33.sdp7
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/34.sdp11
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/35.sdp11
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/36.sdp7
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/37.sdp7
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/38.sdp9
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/39.sdp9
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/4.sdp12
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/40.sdp9
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/41.sdp9
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/42.sdp9
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/43.sdp9
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/44.sdp5
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/45.sdp5
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/46.sdp7
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/47.sdp7
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/48.sdp7
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/49.sdp7
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/5.sdp10
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/50.sdp7
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/51.sdp7
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/52.sdp7
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/53.sdp7
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/54.sdp7
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/55.sdp8
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/6.sdp9
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/7.sdp9
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/8.sdp12
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/9.sdp9
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/firefox-1.sdp58
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/firefox-2.sdp43
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/opera-1.sdp85
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/opera-2.sdp73
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/unittest-1.sdp52
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/unittest-2.sdp40
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/unittest-3.sdp13
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/unittest-4.sdp11
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/unittest-5.sdp5
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/unittest-6.sdp12
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/unittest-7.sdp12
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/unittest-8.sdp64
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/unittest-9.sdp66
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp.tokens56
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/0.stunbin0 -> 32 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/1.stunbin0 -> 32 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/10.stunbin0 -> 44 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/11.stunbin0 -> 32 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/12.stunbin0 -> 32 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/13.stunbin0 -> 28 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/14.stunbin0 -> 40 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/15.stunbin0 -> 32 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/16.stunbin0 -> 40 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/17.stunbin0 -> 44 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/2.stunbin0 -> 44 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/3.stunbin0 -> 44 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/4.stunbin0 -> 44 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/5.stunbin0 -> 108 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/6.stunbin0 -> 80 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/7.stunbin0 -> 92 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/8.stunbin0 -> 116 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/9.stunbin0 -> 32 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/validator-crash-1.stunbin0 -> 80 bytes
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun.tokens2
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/flexfec_header_reader_fuzzer.cc35
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/flexfec_receiver_fuzzer.cc72
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/flexfec_sender_fuzzer.cc70
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/h264_bitstream_parser_fuzzer.cc21
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/h264_depacketizer_fuzzer.cc18
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/neteq_rtp_fuzzer.cc168
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/neteq_signal_fuzzer.cc262
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/packet_buffer_fuzzer.cc46
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/pseudotcp_parser_fuzzer.cc48
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/residual_echo_detector_fuzzer.cc66
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/rtcp_receiver_fuzzer.cc37
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/rtp_header_fuzzer.cc50
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/rtp_packet_fuzzer.cc120
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/sdp_parser_fuzzer.cc25
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/stun_parser_fuzzer.cc28
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/stun_validator_fuzzer.cc23
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/transport_feedback_packet_loss_tracker_fuzzer.cc279
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/turn_unwrap_fuzzer.cc22
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/ulpfec_generator_fuzzer.cc60
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/ulpfec_header_reader_fuzzer.cc35
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/ulpfec_receiver_fuzzer.cc79
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/vp8_depacketizer_fuzzer.cc18
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/vp8_qp_parser_fuzzer.cc17
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/vp9_depacketizer_fuzzer.cc18
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/vp9_qp_parser_fuzzer.cc18
-rw-r--r--third_party/libwebrtc/webrtc/test/fuzzers/webrtc_fuzzer_main.cc41
-rw-r--r--third_party/libwebrtc/webrtc/test/gl/gl_renderer.cc112
-rw-r--r--third_party/libwebrtc/webrtc/test/gl/gl_renderer.h50
-rw-r--r--third_party/libwebrtc/webrtc/test/gmock.h20
-rw-r--r--third_party/libwebrtc/webrtc/test/gtest.h27
-rw-r--r--third_party/libwebrtc/webrtc/test/ios/Info.plist45
-rw-r--r--third_party/libwebrtc/webrtc/test/ios/test_support.h25
-rw-r--r--third_party/libwebrtc/webrtc/test/ios/test_support.mm108
-rw-r--r--third_party/libwebrtc/webrtc/test/layer_filtering_transport.cc124
-rw-r--r--third_party/libwebrtc/webrtc/test/layer_filtering_transport.h60
-rw-r--r--third_party/libwebrtc/webrtc/test/linux/glx_renderer.cc178
-rw-r--r--third_party/libwebrtc/webrtc/test/linux/glx_renderer.h47
-rw-r--r--third_party/libwebrtc/webrtc/test/linux/video_renderer_linux.cc27
-rw-r--r--third_party/libwebrtc/webrtc/test/mac/run_test.mm73
-rw-r--r--third_party/libwebrtc/webrtc/test/mac/video_renderer_mac.h40
-rw-r--r--third_party/libwebrtc/webrtc/test/mac/video_renderer_mac.mm127
-rw-r--r--third_party/libwebrtc/webrtc/test/mock_audio_decoder.cc20
-rw-r--r--third_party/libwebrtc/webrtc/test/mock_audio_decoder.h38
-rw-r--r--third_party/libwebrtc/webrtc/test/mock_audio_decoder_factory.h84
-rw-r--r--third_party/libwebrtc/webrtc/test/mock_audio_encoder.cc59
-rw-r--r--third_party/libwebrtc/webrtc/test/mock_audio_encoder.h107
-rw-r--r--third_party/libwebrtc/webrtc/test/mock_audio_encoder_factory.h91
-rw-r--r--third_party/libwebrtc/webrtc/test/mock_transport.h28
-rw-r--r--third_party/libwebrtc/webrtc/test/mock_voe_channel_proxy.h99
-rw-r--r--third_party/libwebrtc/webrtc/test/mock_voice_engine.h124
-rw-r--r--third_party/libwebrtc/webrtc/test/null_platform_renderer.cc22
-rw-r--r--third_party/libwebrtc/webrtc/test/null_transport.cc26
-rw-r--r--third_party/libwebrtc/webrtc/test/null_transport.h30
-rw-r--r--third_party/libwebrtc/webrtc/test/rtcp_packet_parser.cc106
-rw-r--r--third_party/libwebrtc/webrtc/test/rtcp_packet_parser.h121
-rw-r--r--third_party/libwebrtc/webrtc/test/rtp_file_reader.cc667
-rw-r--r--third_party/libwebrtc/webrtc/test/rtp_file_reader.h49
-rw-r--r--third_party/libwebrtc/webrtc/test/rtp_file_reader_unittest.cc126
-rw-r--r--third_party/libwebrtc/webrtc/test/rtp_file_writer.cc108
-rw-r--r--third_party/libwebrtc/webrtc/test/rtp_file_writer.h33
-rw-r--r--third_party/libwebrtc/webrtc/test/rtp_file_writer_unittest.cc76
-rw-r--r--third_party/libwebrtc/webrtc/test/rtp_rtcp_observer.h165
-rw-r--r--third_party/libwebrtc/webrtc/test/run_loop.cc22
-rw-r--r--third_party/libwebrtc/webrtc/test/run_loop.h22
-rw-r--r--third_party/libwebrtc/webrtc/test/run_test.cc23
-rw-r--r--third_party/libwebrtc/webrtc/test/run_test.h22
-rw-r--r--third_party/libwebrtc/webrtc/test/single_threaded_task_queue.cc144
-rw-r--r--third_party/libwebrtc/webrtc/test/single_threaded_task_queue.h97
-rw-r--r--third_party/libwebrtc/webrtc/test/single_threaded_task_queue_unittest.cc364
-rw-r--r--third_party/libwebrtc/webrtc/test/statistics.cc41
-rw-r--r--third_party/libwebrtc/webrtc/test/statistics.h36
-rw-r--r--third_party/libwebrtc/webrtc/test/test_main.cc65
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/always_passing_unittest.cc19
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/fileutils.cc363
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/fileutils.h110
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/fileutils_unittest.cc240
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/frame_reader.h75
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/frame_writer.h105
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/iosfileutils.mm63
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/jpeg_frame_writer.cc90
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/jpeg_frame_writer_ios.cc31
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/metrics/video_metrics.cc193
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/metrics/video_metrics.h121
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/metrics/video_metrics_unittest.cc147
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/mock/mock_frame_reader.h33
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/packet_reader.cc49
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/packet_reader.h54
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/packet_reader_unittest.cc125
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/perf_test.cc92
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/perf_test.h71
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/perf_test_unittest.cc39
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/test_artifacts.cc70
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/test_artifacts.h39
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/test_artifacts_unittest.cc61
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/unittest_utils.h56
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/y4m_frame_writer.cc56
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/y4m_frame_writer_unittest.cc77
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/yuv_frame_reader.cc91
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/yuv_frame_reader_unittest.cc82
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/yuv_frame_writer.cc77
-rw-r--r--third_party/libwebrtc/webrtc/test/testsupport/yuv_frame_writer_unittest.cc68
-rw-r--r--third_party/libwebrtc/webrtc/test/vcm_capturer.cc118
-rw-r--r--third_party/libwebrtc/webrtc/test/vcm_capturer.h61
-rw-r--r--third_party/libwebrtc/webrtc/test/video_capturer.cc58
-rw-r--r--third_party/libwebrtc/webrtc/test/video_capturer.h53
-rw-r--r--third_party/libwebrtc/webrtc/test/video_codec_settings.h111
-rw-r--r--third_party/libwebrtc/webrtc/test/video_renderer.cc33
-rw-r--r--third_party/libwebrtc/webrtc/test/video_renderer.h41
-rw-r--r--third_party/libwebrtc/webrtc/test/win/d3d_renderer.cc220
-rw-r--r--third_party/libwebrtc/webrtc/test/win/d3d_renderer.h53
-rw-r--r--third_party/libwebrtc/webrtc/test/win/run_loop_win.cc33
328 files changed, 17511 insertions, 0 deletions
diff --git a/third_party/libwebrtc/webrtc/test/BUILD.gn b/third_party/libwebrtc/webrtc/test/BUILD.gn
new file mode 100644
index 0000000000..f7bd8144be
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/BUILD.gn
@@ -0,0 +1,729 @@
+# Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+#
+# Use of this source code is governed by a BSD-style license
+# that can be found in the LICENSE file in the root of the source
+# tree. An additional intellectual property rights grant can be found
+# in the file PATENTS. All contributing project authors may
+# be found in the AUTHORS file in the root of the source tree.
+
+import("../webrtc.gni")
+import("//build/config/ui.gni")
+if (is_android) {
+ import("//build/config/android/rules.gni")
+}
+if (rtc_use_memcheck) {
+ import("//tools_webrtc/valgrind/valgrind-webrtc.gni")
+}
+
+group("test") {
+ testonly = true
+
+ deps = [
+ ":field_trial",
+ ":rtp_test_utils",
+ ":test_common",
+ ":test_renderer",
+ ":test_support",
+ ":video_test_common",
+ ]
+
+ if (rtc_include_tests) {
+ deps += [
+ ":test_main",
+ ":test_support_unittests",
+ ]
+ }
+}
+
+rtc_source_set("video_test_common") {
+ testonly = true
+ sources = [
+ "fake_texture_frame.cc",
+ "fake_texture_frame.h",
+ "frame_generator.cc",
+ "frame_generator.h",
+ "frame_generator_capturer.cc",
+ "frame_generator_capturer.h",
+ "frame_utils.cc",
+ "frame_utils.h",
+ "vcm_capturer.cc",
+ "vcm_capturer.h",
+ "video_capturer.cc",
+ "video_capturer.h",
+ "video_codec_settings.h",
+ ]
+
+ if (!build_with_chromium && is_clang) {
+ # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
+ suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
+ }
+
+ deps = [
+ "..:webrtc_common",
+ "../api:optional",
+ "../api:video_frame_api_i420",
+ "../api/video_codecs:video_codecs_api",
+ "../call:video_stream_api",
+ "../common_video",
+ "../media:rtc_media_base",
+ "../modules/video_capture:video_capture_module",
+ "../rtc_base:rtc_base_approved",
+ "../rtc_base:rtc_task_queue",
+ "../system_wrappers",
+ ]
+}
+
+rtc_source_set("rtp_test_utils") {
+ testonly = true
+ sources = [
+ "rtcp_packet_parser.cc",
+ "rtcp_packet_parser.h",
+ "rtp_file_reader.cc",
+ "rtp_file_reader.h",
+ "rtp_file_writer.cc",
+ "rtp_file_writer.h",
+ ]
+
+ if (!build_with_chromium && is_clang) {
+ # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
+ suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
+ }
+
+ deps = [
+ "..:webrtc_common",
+ "../api:array_view",
+ "../modules/rtp_rtcp",
+ "../rtc_base:rtc_base_approved",
+ "//testing/gtest",
+ ]
+}
+
+rtc_source_set("field_trial") {
+ testonly = true
+ sources = [
+ "field_trial.cc",
+ "field_trial.h",
+ ]
+
+ deps = [
+ "..:webrtc_common",
+ "../system_wrappers",
+ "../system_wrappers:field_trial_default",
+ ]
+}
+
+if (is_ios) {
+ rtc_source_set("test_support_objc") {
+ testonly = true
+ visibility = [ ":test_support" ]
+ sources = [
+ "ios/test_support.h",
+ "ios/test_support.mm",
+ ]
+ deps = [
+ "../sdk:common_objc",
+ ]
+ }
+}
+
+rtc_source_set("test_support") {
+ testonly = true
+
+ sources = [
+ "gmock.h",
+ "gtest.h",
+ "testsupport/packet_reader.cc",
+ "testsupport/packet_reader.h",
+ "testsupport/perf_test.cc",
+ "testsupport/perf_test.h",
+ "testsupport/unittest_utils.h",
+ ]
+
+ public_deps = [
+ ":fileutils",
+ ]
+ if (is_ios) {
+ public_deps += [ ":test_support_objc" ]
+ }
+
+ deps = [
+ "..:webrtc_common",
+ "../common_video",
+ "../rtc_base:gtest_prod",
+ "../rtc_base:rtc_base_approved",
+ "../system_wrappers",
+ "//testing/gmock",
+ "//testing/gtest",
+ ]
+
+ if (!build_with_chromium && is_clang) {
+ # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
+ suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
+ }
+
+ if (!build_with_mozilla && is_android) {
+ deps += [ "//base:base" ]
+ }
+
+ if (is_ios && !build_with_chromium) {
+ deps += [ "../sdk:common_objc" ]
+ }
+
+ if (rtc_use_memcheck) {
+ data = valgrind_webrtc_dependencies
+ }
+}
+
+if (rtc_include_tests) {
+ rtc_source_set("test_main") {
+ testonly = true
+ sources = [
+ "test_main.cc",
+ ]
+
+ public_deps = [
+ ":test_support",
+ ]
+ deps = [
+ ":field_trial",
+ "../rtc_base:rtc_base_approved",
+ "../system_wrappers:metrics_default",
+ "//testing/gmock",
+ "//testing/gtest",
+ ]
+ }
+
+ rtc_source_set("video_test_support") {
+ testonly = true
+
+ sources = [
+ "testsupport/frame_reader.h",
+ "testsupport/frame_writer.h",
+ "testsupport/metrics/video_metrics.cc",
+ "testsupport/metrics/video_metrics.h",
+ "testsupport/mock/mock_frame_reader.h",
+ "testsupport/y4m_frame_writer.cc",
+ "testsupport/yuv_frame_reader.cc",
+ "testsupport/yuv_frame_writer.cc",
+ ]
+
+ deps = [
+ ":test_support",
+ ":video_test_common",
+ "..:webrtc_common",
+ "../api:video_frame_api",
+ "../api:video_frame_api_i420",
+ "../common_video",
+ "../rtc_base:rtc_base_approved",
+ "../system_wrappers",
+ "//testing/gmock",
+ "//testing/gtest",
+ ]
+
+ if (!is_ios) {
+ deps += [ "//third_party:jpeg" ]
+ sources += [ "testsupport/jpeg_frame_writer.cc" ]
+ } else {
+ sources += [ "testsupport/jpeg_frame_writer_ios.cc" ]
+ }
+
+ public_deps = [
+ ":fileutils",
+ ]
+
+ if (!build_with_chromium && is_clang) {
+ # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
+ suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
+ }
+
+ if (is_android) {
+ deps += [ "//base:base" ]
+ }
+
+ if (is_ios) {
+ deps += [ "../sdk:common_objc" ]
+ }
+
+ if (rtc_use_memcheck) {
+ data = valgrind_webrtc_dependencies
+ }
+ }
+
+ rtc_source_set("test_support_test_artifacts") {
+ testonly = true
+ sources = [
+ "testsupport/test_artifacts.cc",
+ "testsupport/test_artifacts.h",
+ ]
+ deps = [
+ ":fileutils",
+ "../rtc_base:rtc_base_approved",
+ ]
+ }
+
+ test_support_unittests_resources = [
+ "../resources/foreman_cif_short.yuv",
+ "../resources/video_coding/frame-ethernet-ii.pcap",
+ "../resources/video_coding/frame-loopback.pcap",
+ "../resources/video_coding/pltype103.rtp",
+ "../resources/video_coding/pltype103_header_only.rtp",
+ "../resources/video_coding/ssrcs-2.pcap",
+ "../resources/video_coding/ssrcs-3.pcap",
+ ]
+
+ if (is_ios) {
+ bundle_data("test_support_unittests_bundle_data") {
+ testonly = true
+ sources = test_support_unittests_resources
+ outputs = [
+ "{{bundle_resources_dir}}/{{source_file_part}}",
+ ]
+ }
+ }
+
+ rtc_test("test_support_unittests") {
+ deps = [
+ ":fake_audio_device",
+ ":rtp_test_utils",
+ "../api:video_frame_api",
+ "../api:video_frame_api_i420",
+ "../call:call_interfaces",
+ "../common_audio",
+ "../modules/rtp_rtcp",
+ "../rtc_base:rtc_base_approved",
+ "../system_wrappers",
+ ]
+ sources = [
+ "fake_audio_device_unittest.cc",
+ "fake_network_pipe_unittest.cc",
+ "frame_generator_unittest.cc",
+ "rtp_file_reader_unittest.cc",
+ "rtp_file_writer_unittest.cc",
+ "single_threaded_task_queue_unittest.cc",
+ "testsupport/always_passing_unittest.cc",
+ "testsupport/metrics/video_metrics_unittest.cc",
+ "testsupport/packet_reader_unittest.cc",
+ "testsupport/perf_test_unittest.cc",
+ "testsupport/test_artifacts_unittest.cc",
+ "testsupport/y4m_frame_writer_unittest.cc",
+ "testsupport/yuv_frame_reader_unittest.cc",
+ "testsupport/yuv_frame_writer_unittest.cc",
+ ]
+
+ # TODO(jschuh): Bug 1348: fix this warning.
+ configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
+
+ if (is_win) {
+ # virtual override w/different const/volatile signature.
+ cflags = [ "/wd4373" ]
+ }
+
+ if (!build_with_chromium && is_clang) {
+ # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
+ suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
+ }
+
+ data = test_support_unittests_resources
+ if (is_android) {
+ deps += [ "//testing/android/native_test:native_test_support" ]
+ shard_timeout = 900
+ }
+
+ if (is_ios) {
+ deps += [ ":test_support_unittests_bundle_data" ]
+ }
+
+ deps += [
+ ":direct_transport",
+ ":fileutils_unittests",
+ ":test_common",
+ ":test_main",
+ ":test_support_test_artifacts",
+ ":video_test_common",
+ ":video_test_support",
+ "../modules/video_capture",
+ "../rtc_base:rtc_base_approved",
+ "//testing/gmock",
+ "//testing/gtest",
+ ]
+ }
+}
+
+if (is_ios) {
+ rtc_source_set("fileutils_objc") {
+ visibility = [ ":fileutils" ]
+ sources = [
+ "testsupport/iosfileutils.mm",
+ ]
+ deps = [
+ "..:webrtc_common",
+ "../rtc_base:rtc_base_approved",
+ "../sdk:common_objc",
+ ]
+ }
+}
+
+rtc_source_set("fileutils") {
+ testonly = true
+ visibility = [
+ ":fileutils_unittests",
+ ":test_support_test_artifacts",
+ ":test_support",
+ ":video_test_support",
+ ]
+ sources = [
+ "testsupport/fileutils.cc",
+ "testsupport/fileutils.h",
+ ]
+ deps = [
+ "..:webrtc_common",
+ "../api:optional",
+ "../rtc_base:rtc_base_approved",
+ ]
+ if (is_ios) {
+ deps += [ ":fileutils_objc" ]
+ }
+ if (is_win) {
+ deps += [ "../rtc_base:rtc_base" ]
+ }
+}
+
+rtc_source_set("run_test") {
+ testonly = true
+ if (is_mac) {
+ public_deps = [
+ ":run_test_objc",
+ ]
+ } else {
+ public_deps = [
+ ":run_test_generic",
+ ]
+ }
+}
+
+rtc_source_set("run_test_interface") {
+ sources = [
+ "run_test.h",
+ ]
+}
+
+if (is_mac) {
+ rtc_source_set("run_test_objc") {
+ testonly = true
+ visibility = [ ":run_test" ]
+ sources = [
+ "mac/run_test.mm",
+ ]
+ deps = [
+ ":run_test_interface",
+ ]
+ }
+}
+
+rtc_source_set("run_test_generic") {
+ testonly = true
+ visibility = [ ":run_test" ]
+ sources = [
+ "run_test.cc",
+ ]
+ deps = [
+ ":run_test_interface",
+ ]
+}
+
+rtc_source_set("fileutils_unittests") {
+ testonly = true
+ visibility = [ ":*" ] # Only targets in this file can depend on this.
+ sources = [
+ "testsupport/fileutils_unittest.cc",
+ ]
+ deps = [
+ ":fileutils",
+ ":test_support",
+ "../api:optional",
+ "../rtc_base:rtc_base_approved",
+ "//testing/gmock",
+ "//testing/gtest",
+ ]
+}
+
+rtc_source_set("direct_transport") {
+ testonly = true
+ sources = [
+ "direct_transport.cc",
+ "direct_transport.h",
+ "fake_network_pipe.cc",
+ "fake_network_pipe.h",
+ ]
+ if (!build_with_chromium && is_clang) {
+ # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
+ suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
+ }
+ deps = [
+ "..:webrtc_common",
+ "../api:transport_api",
+ "../call",
+ "../modules/rtp_rtcp",
+ "../rtc_base:rtc_base_approved",
+ "../rtc_base:sequenced_task_checker",
+ "../system_wrappers",
+ ]
+ public_deps = [
+ ":single_threaded_task_queue",
+ ]
+}
+
+rtc_source_set("single_threaded_task_queue") {
+ testonly = true
+ sources = [
+ "single_threaded_task_queue.cc",
+ "single_threaded_task_queue.h",
+ ]
+ deps = [
+ "../rtc_base:rtc_base_approved",
+ ]
+}
+
+rtc_source_set("fake_audio_device") {
+ testonly = true
+ sources = [
+ "fake_audio_device.cc",
+ "fake_audio_device.h",
+ ]
+ if (!build_with_chromium && is_clang) {
+ # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
+ suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
+ }
+ deps = [
+ "..:webrtc_common",
+ "../api:array_view",
+ "../common_audio:common_audio",
+ "../modules/audio_device:audio_device",
+ "../rtc_base:rtc_base_approved",
+ "../system_wrappers:system_wrappers",
+ ]
+}
+
+rtc_source_set("test_common") {
+ testonly = true
+ sources = [
+ "call_test.cc",
+ "call_test.h",
+ "configurable_frame_size_encoder.cc",
+ "configurable_frame_size_encoder.h",
+ "constants.cc",
+ "constants.h",
+ "drifting_clock.cc",
+ "drifting_clock.h",
+ "encoder_settings.cc",
+ "encoder_settings.h",
+ "fake_decoder.cc",
+ "fake_decoder.h",
+ "fake_encoder.cc",
+ "fake_encoder.h",
+ "fake_videorenderer.h",
+ "layer_filtering_transport.cc",
+ "layer_filtering_transport.h",
+ "mock_transport.h",
+ "mock_voe_channel_proxy.h",
+ "mock_voice_engine.h",
+ "null_transport.cc",
+ "null_transport.h",
+ "rtp_rtcp_observer.h",
+ "statistics.cc",
+ "statistics.h",
+ "win/run_loop_win.cc",
+ ]
+ if (!is_win) {
+ sources += [
+ "run_loop.cc",
+ "run_loop.h",
+ ]
+ }
+
+ if (!build_with_chromium && is_clang) {
+ # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
+ suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
+ }
+
+ deps = [
+ ":direct_transport",
+ ":fake_audio_device",
+ ":rtp_test_utils",
+ ":test_support",
+ ":video_test_common",
+ "..:webrtc_common",
+ "../api:transport_api",
+ "../api:video_frame_api",
+ "../api:video_frame_api_i420",
+ "../api/audio_codecs:builtin_audio_decoder_factory",
+ "../api/audio_codecs:builtin_audio_encoder_factory",
+ "../api/video_codecs:video_codecs_api",
+ "../audio",
+ "../call",
+ "../call:rtp_sender",
+ "../call:video_stream_api",
+ "../common_video",
+ "../logging:rtc_event_log_api",
+ "../modules/audio_device:mock_audio_device",
+ "../modules/audio_mixer:audio_mixer_impl",
+ "../modules/audio_processing",
+ "../modules/rtp_rtcp",
+ "../modules/rtp_rtcp:mock_rtp_rtcp",
+ "../modules/video_coding:video_coding_utility",
+ "../modules/video_coding:webrtc_h264",
+ "../modules/video_coding:webrtc_vp8",
+ "../modules/video_coding:webrtc_vp9",
+ "../rtc_base:rtc_base_approved",
+ "../rtc_base:rtc_task_queue",
+ "../rtc_base:sequenced_task_checker",
+ "../system_wrappers",
+ "../video",
+ "../voice_engine",
+ "//testing/gmock",
+ "//testing/gtest",
+ ]
+ if (!is_android && !build_with_chromium) {
+ deps += [ "../modules/video_capture:video_capture_internal_impl" ]
+ }
+}
+
+config("test_renderer_exported_config") {
+ if (is_win && is_clang) {
+ # GN orders flags on a target before flags from configs. The default config
+ # adds -Wall, and this flag have to be after -Wall -- so they need to
+ # come from a config and cannot be on the target directly.
+ cflags = [
+ "-Wno-bool-conversion",
+ "-Wno-comment",
+ "-Wno-delete-non-virtual-dtor",
+ ]
+ }
+}
+
+rtc_source_set("test_renderer") {
+ public_deps = [
+ ":test_renderer_generic",
+ ]
+ testonly = true
+ if (is_mac) {
+ public_deps += [ ":test_renderer_objc" ]
+ }
+}
+
+if (is_mac) {
+ rtc_source_set("test_renderer_objc") {
+ testonly = true
+ visibility = [ ":test_renderer" ]
+ sources = [
+ "mac/video_renderer_mac.h",
+ "mac/video_renderer_mac.mm",
+ ]
+ deps = [
+ ":test_renderer_generic",
+ "../rtc_base:rtc_base_approved",
+ ]
+ libs = [
+ "Cocoa.framework",
+ "OpenGL.framework",
+ "CoreVideo.framework",
+ ]
+ if (!build_with_chromium && is_clang) {
+ # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
+ suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
+ }
+ }
+}
+
+rtc_source_set("test_renderer_generic") {
+ testonly = true
+ visibility = [
+ ":test_renderer",
+ ":test_renderer_objc",
+ ]
+ libs = []
+ sources = [
+ "video_renderer.cc",
+ "video_renderer.h",
+ "win/d3d_renderer.cc",
+ "win/d3d_renderer.h",
+ ]
+ deps = [
+ ":test_support",
+ "..:webrtc_common",
+ "../common_video",
+ "../modules/media_file",
+ "../rtc_base:rtc_base_approved",
+ "//testing/gtest",
+ ]
+ if (!(is_linux && use_x11) && !is_mac && !is_win) {
+ sources += [ "null_platform_renderer.cc" ]
+ }
+ if ((is_linux && use_x11) || is_mac) {
+ sources += [
+ "gl/gl_renderer.cc",
+ "gl/gl_renderer.h",
+ ]
+ }
+
+ if (is_linux && use_x11) {
+ sources += [
+ "linux/glx_renderer.cc",
+ "linux/glx_renderer.h",
+ "linux/video_renderer_linux.cc",
+ ]
+ libs += [
+ "Xext",
+ "X11",
+ "GL",
+ ]
+ }
+ if (is_android) {
+ libs += [
+ "GLESv2",
+ "log",
+ ]
+ }
+
+ public_configs = [ ":test_renderer_exported_config" ]
+
+ if (!build_with_chromium && is_clang) {
+ # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
+ suppressed_configs += [ "//build/config/clang:find_bad_constructs" ]
+ }
+}
+
+rtc_source_set("audio_codec_mocks") {
+ testonly = true
+ sources = [
+ "mock_audio_decoder.cc",
+ "mock_audio_decoder.h",
+ "mock_audio_decoder_factory.h",
+ "mock_audio_encoder.cc",
+ "mock_audio_encoder.h",
+ "mock_audio_encoder_factory.h",
+ ]
+
+ deps = [
+ ":test_support",
+ "../api:array_view",
+ "../api/audio_codecs:audio_codecs_api",
+ "../api/audio_codecs:builtin_audio_decoder_factory",
+ "../rtc_base:rtc_base_approved",
+ "//testing/gmock",
+ ]
+}
+
+if (!build_with_chromium && !build_with_mozilla && is_android) {
+ rtc_android_library("native_test_java") {
+ testonly = true
+ java_files = [
+ "android/org/webrtc/native_test/RTCNativeUnitTest.java",
+ "android/org/webrtc/native_test/RTCNativeUnitTestActivity.java",
+ ]
+ deps = [
+ "../rtc_base:base_java",
+ "//testing/android/native_test:native_test_java",
+ ]
+ }
+}
diff --git a/third_party/libwebrtc/webrtc/test/DEPS b/third_party/libwebrtc/webrtc/test/DEPS
new file mode 100644
index 0000000000..39f107b9b2
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/DEPS
@@ -0,0 +1,43 @@
+include_rules = [
+ "+third_party/libjpeg",
+ "+third_party/libjpeg_turbo",
+ "+call",
+ "+common_audio",
+ "+common_video",
+ "+logging/rtc_event_log",
+ "+media/base",
+ "+modules/audio_coding",
+ "+modules/audio_device",
+ "+modules/audio_mixer",
+ "+modules/audio_processing",
+ "+modules/media_file",
+ "+modules/rtp_rtcp",
+ "+modules/video_capture",
+ "+modules/video_coding",
+ "+sdk",
+ "+system_wrappers",
+ "+voice_engine",
+]
+
+specific_include_rules = {
+ "gmock\.h": [
+ "+testing/gmock/include/gmock",
+ ],
+ "gtest\.h": [
+ "+testing/gtest/include/gtest",
+ ],
+ ".*congestion_controller_feedback_fuzzer\.cc": [
+ "+modules/congestion_controller/include/receive_side_congestion_controller.h",
+ "+modules/pacing/packet_router.h",
+ "+modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h",
+ ],
+ ".*pseudotcp_parser_fuzzer\.cc": [
+ "+p2p/base/pseudotcp.h",
+ ],
+ ".*stun_parser_fuzzer\.cc": [
+ "+p2p/base/stun.h",
+ ],
+ ".*stun_validator_fuzzer\.cc": [
+ "+p2p/base/stun.h",
+ ],
+}
diff --git a/third_party/libwebrtc/webrtc/test/OWNERS b/third_party/libwebrtc/webrtc/test/OWNERS
new file mode 100644
index 0000000000..c58c863e16
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/OWNERS
@@ -0,0 +1,2 @@
+phoglund@webrtc.org
+stefan@webrtc.org
diff --git a/third_party/libwebrtc/webrtc/test/android/AndroidManifest.xml b/third_party/libwebrtc/webrtc/test/android/AndroidManifest.xml
new file mode 100644
index 0000000000..b5157a75df
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/android/AndroidManifest.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright 2017 The WebRTC project authors. All Rights Reserved.
+
+Use of this source code is governed by a BSD-style license
+that can be found in the LICENSE file in the root of the source
+tree. An additional intellectual property rights grant can be found
+in the file PATENTS. All contributing project authors may
+be found in the AUTHORS file in the root of the source tree.
+-->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="org.webrtc.native_test"
+ android:versionCode="1"
+ android:versionName="1.0">
+
+ <uses-sdk android:minSdkVersion="16" android:targetSdkVersion="23" />
+ <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
+ <uses-permission android:name="android.permission.BLUETOOTH"/>
+ <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
+ <uses-permission android:name="android.permission.CAMERA" />
+ <uses-permission android:name="android.permission.INTERNET"/>
+ <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
+ <uses-permission android:name="android.permission.RECORD_AUDIO"/>
+ <uses-permission android:name="android.permission.WAKE_LOCK"/>
+ <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
+
+ <application android:label="NativeTests"
+ android:name="org.chromium.base.BaseChromiumApplication">
+ <uses-library android:name="android.test.runner"/>
+ <activity android:name=".RTCNativeUnitTestActivity"
+ android:label="NativeTest"
+ android:configChanges="orientation|keyboardHidden"
+ android:process=":test_process">
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+ <instrumentation android:name="org.chromium.native_test.NativeTestInstrumentationTestRunner"
+ android:targetPackage="org.webrtc.native_test"
+ android:label="Instrumentation entry point for org.webrtc.native_test"/>
+
+</manifest>
diff --git a/third_party/libwebrtc/webrtc/test/android/org/webrtc/native_test/RTCNativeUnitTest.java b/third_party/libwebrtc/webrtc/test/android/org/webrtc/native_test/RTCNativeUnitTest.java
new file mode 100644
index 0000000000..dede7edd1f
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/android/org/webrtc/native_test/RTCNativeUnitTest.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+package org.webrtc.native_test;
+
+import android.app.Activity;
+import org.chromium.native_test.NativeUnitTest;
+import org.webrtc.ContextUtils;
+
+/**
+ * Native unit test that calls ContextUtils.initialize for WebRTC.
+ */
+public class RTCNativeUnitTest extends NativeUnitTest {
+ @Override
+ public void preCreate(Activity activity) {
+ super.preCreate(activity);
+ ContextUtils.initialize(activity.getApplicationContext());
+ }
+}
diff --git a/third_party/libwebrtc/webrtc/test/android/org/webrtc/native_test/RTCNativeUnitTestActivity.java b/third_party/libwebrtc/webrtc/test/android/org/webrtc/native_test/RTCNativeUnitTestActivity.java
new file mode 100644
index 0000000000..2a413682fe
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/android/org/webrtc/native_test/RTCNativeUnitTestActivity.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+package org.webrtc.native_test;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * Activity that uses RTCNativeUnitTest to run the tests.
+ */
+public class RTCNativeUnitTestActivity extends Activity {
+ private RTCNativeUnitTest mTest = new RTCNativeUnitTest();
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ mTest.preCreate(this);
+ super.onCreate(savedInstanceState);
+ mTest.postCreate(this);
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ mTest.postStart(this, false);
+ }
+}
diff --git a/third_party/libwebrtc/webrtc/test/call_test.cc b/third_party/libwebrtc/webrtc/test/call_test.cc
new file mode 100644
index 0000000000..3210e6460d
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/call_test.cc
@@ -0,0 +1,619 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/call_test.h"
+
+#include <algorithm>
+
+#include "api/audio_codecs/builtin_audio_decoder_factory.h"
+#include "api/audio_codecs/builtin_audio_encoder_factory.h"
+#include "call/rtp_transport_controller_send.h"
+#include "call/video_config.h"
+#include "modules/audio_mixer/audio_mixer_impl.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/event.h"
+#include "rtc_base/ptr_util.h"
+#include "test/testsupport/fileutils.h"
+#include "voice_engine/include/voe_base.h"
+
+namespace webrtc {
+namespace test {
+
+namespace {
+const int kVideoRotationRtpExtensionId = 4;
+}
+
+CallTest::CallTest()
+ : clock_(Clock::GetRealTimeClock()),
+ event_log_(RtcEventLog::CreateNull()),
+ sender_call_transport_controller_(nullptr),
+ video_send_config_(nullptr),
+ video_send_stream_(nullptr),
+ audio_send_config_(nullptr),
+ audio_send_stream_(nullptr),
+ fake_encoder_(clock_),
+ num_video_streams_(1),
+ num_audio_streams_(0),
+ num_flexfec_streams_(0),
+ decoder_factory_(CreateBuiltinAudioDecoderFactory()),
+ encoder_factory_(CreateBuiltinAudioEncoderFactory()),
+ task_queue_("CallTestTaskQueue"),
+ fake_send_audio_device_(nullptr),
+ fake_recv_audio_device_(nullptr) {}
+
+CallTest::~CallTest() {
+ task_queue_.SendTask([this]() {
+ fake_send_audio_device_.reset();
+ fake_recv_audio_device_.reset();
+ frame_generator_capturer_.reset();
+ });
+}
+
+void CallTest::RunBaseTest(BaseTest* test) {
+ task_queue_.SendTask([this, test]() {
+ num_video_streams_ = test->GetNumVideoStreams();
+ num_audio_streams_ = test->GetNumAudioStreams();
+ num_flexfec_streams_ = test->GetNumFlexfecStreams();
+ RTC_DCHECK(num_video_streams_ > 0 || num_audio_streams_ > 0);
+ Call::Config send_config(test->GetSenderCallConfig());
+ if (num_audio_streams_ > 0) {
+ CreateFakeAudioDevices(test->CreateCapturer(), test->CreateRenderer());
+ test->OnFakeAudioDevicesCreated(fake_send_audio_device_.get(),
+ fake_recv_audio_device_.get());
+ apm_send_ = AudioProcessing::Create();
+ apm_recv_ = AudioProcessing::Create();
+ CreateVoiceEngines();
+ AudioState::Config audio_state_config;
+ audio_state_config.voice_engine = voe_send_.voice_engine;
+ audio_state_config.audio_mixer = AudioMixerImpl::Create();
+ audio_state_config.audio_processing = apm_send_;
+ send_config.audio_state = AudioState::Create(audio_state_config);
+ fake_send_audio_device_->RegisterAudioCallback(
+ send_config.audio_state->audio_transport());
+ }
+ CreateSenderCall(send_config);
+ if (sender_call_transport_controller_ != nullptr) {
+ test->OnRtpTransportControllerSendCreated(
+ sender_call_transport_controller_);
+ }
+ if (test->ShouldCreateReceivers()) {
+ Call::Config recv_config(test->GetReceiverCallConfig());
+ if (num_audio_streams_ > 0) {
+ AudioState::Config audio_state_config;
+ audio_state_config.voice_engine = voe_recv_.voice_engine;
+ audio_state_config.audio_mixer = AudioMixerImpl::Create();
+ audio_state_config.audio_processing = apm_recv_;
+ recv_config.audio_state = AudioState::Create(audio_state_config);
+ fake_recv_audio_device_->RegisterAudioCallback(
+ recv_config.audio_state->audio_transport()); }
+ CreateReceiverCall(recv_config);
+ }
+ test->OnCallsCreated(sender_call_.get(), receiver_call_.get());
+ receive_transport_.reset(test->CreateReceiveTransport(&task_queue_));
+ send_transport_.reset(
+ test->CreateSendTransport(&task_queue_, sender_call_.get()));
+
+ if (test->ShouldCreateReceivers()) {
+ send_transport_->SetReceiver(receiver_call_->Receiver());
+ receive_transport_->SetReceiver(sender_call_->Receiver());
+ if (num_video_streams_ > 0)
+ receiver_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
+ if (num_audio_streams_ > 0)
+ receiver_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
+ } else {
+ // Sender-only call delivers to itself.
+ send_transport_->SetReceiver(sender_call_->Receiver());
+ receive_transport_->SetReceiver(nullptr);
+ }
+
+ CreateSendConfig(num_video_streams_, num_audio_streams_,
+ num_flexfec_streams_, send_transport_.get());
+ if (test->ShouldCreateReceivers()) {
+ CreateMatchingReceiveConfigs(receive_transport_.get());
+ }
+ if (num_video_streams_ > 0) {
+ test->ModifyVideoConfigs(&video_send_config_, &video_receive_configs_,
+ &video_encoder_config_);
+ }
+ if (num_audio_streams_ > 0) {
+ test->ModifyAudioConfigs(&audio_send_config_, &audio_receive_configs_);
+ }
+ if (num_flexfec_streams_ > 0) {
+ test->ModifyFlexfecConfigs(&flexfec_receive_configs_);
+ }
+
+ if (num_flexfec_streams_ > 0) {
+ CreateFlexfecStreams();
+ test->OnFlexfecStreamsCreated(flexfec_receive_streams_);
+ }
+ if (num_video_streams_ > 0) {
+ CreateVideoStreams();
+ test->OnVideoStreamsCreated(video_send_stream_, video_receive_streams_);
+ }
+ if (num_audio_streams_ > 0) {
+ CreateAudioStreams();
+ test->OnAudioStreamsCreated(audio_send_stream_, audio_receive_streams_);
+ }
+
+ if (num_video_streams_ > 0) {
+ int width = kDefaultWidth;
+ int height = kDefaultHeight;
+ int frame_rate = kDefaultFramerate;
+ test->ModifyVideoCaptureStartResolution(&width, &height, &frame_rate);
+ CreateFrameGeneratorCapturer(frame_rate, width, height);
+ test->OnFrameGeneratorCapturerCreated(frame_generator_capturer_.get());
+ }
+
+ Start();
+ });
+
+ test->PerformTest();
+
+ task_queue_.SendTask([this, test]() {
+ Stop();
+ test->OnStreamsStopped();
+ DestroyStreams();
+ send_transport_.reset();
+ receive_transport_.reset();
+ DestroyCalls();
+ if (num_audio_streams_ > 0)
+ DestroyVoiceEngines();
+ });
+}
+
+void CallTest::CreateCalls(const Call::Config& sender_config,
+ const Call::Config& receiver_config) {
+ CreateSenderCall(sender_config);
+ CreateReceiverCall(receiver_config);
+}
+
+void CallTest::CreateSenderCall(const Call::Config& config) {
+ sender_call_transport_controller_ = new RtpTransportControllerSend(
+ Clock::GetRealTimeClock(), config.event_log);
+
+ sender_call_.reset(
+ Call::Create(config, std::unique_ptr<RtpTransportControllerSend>(
+ sender_call_transport_controller_)));
+}
+
+void CallTest::CreateReceiverCall(const Call::Config& config) {
+ receiver_call_.reset(Call::Create(config));
+}
+
+void CallTest::DestroyCalls() {
+ sender_call_.reset();
+ receiver_call_.reset();
+}
+
+void CallTest::CreateSendConfig(size_t num_video_streams,
+ size_t num_audio_streams,
+ size_t num_flexfec_streams,
+ Transport* send_transport) {
+ RTC_DCHECK(num_video_streams <= kNumSsrcs);
+ RTC_DCHECK_LE(num_audio_streams, 1);
+ RTC_DCHECK_LE(num_flexfec_streams, 1);
+ RTC_DCHECK(num_audio_streams == 0 || voe_send_.channel_id >= 0);
+ if (num_video_streams > 0) {
+ video_send_config_ = VideoSendStream::Config(send_transport);
+ video_send_config_.encoder_settings.encoder = &fake_encoder_;
+ video_send_config_.encoder_settings.payload_name = "FAKE";
+ video_send_config_.encoder_settings.payload_type =
+ kFakeVideoSendPayloadType;
+ video_send_config_.rtp.extensions.push_back(
+ RtpExtension(RtpExtension::kTransportSequenceNumberUri,
+ kTransportSequenceNumberExtensionId));
+ video_send_config_.rtp.extensions.push_back(RtpExtension(
+ RtpExtension::kVideoContentTypeUri, kVideoContentTypeExtensionId));
+ FillEncoderConfiguration(num_video_streams, &video_encoder_config_);
+
+ for (size_t i = 0; i < num_video_streams; ++i)
+ video_send_config_.rtp.ssrcs.push_back(kVideoSendSsrcs[i]);
+ video_send_config_.rtp.extensions.push_back(RtpExtension(
+ RtpExtension::kVideoRotationUri, kVideoRotationRtpExtensionId));
+ }
+
+ if (num_audio_streams > 0) {
+ audio_send_config_ = AudioSendStream::Config(send_transport);
+ audio_send_config_.voe_channel_id = voe_send_.channel_id;
+ audio_send_config_.rtp.ssrc = kAudioSendSsrc;
+ audio_send_config_.send_codec_spec =
+ rtc::Optional<AudioSendStream::Config::SendCodecSpec>(
+ {kAudioSendPayloadType, {"opus", 48000, 2, {{"stereo", "1"}}}});
+ audio_send_config_.encoder_factory = encoder_factory_;
+ }
+
+ // TODO(brandtr): Update this when we support multistream protection.
+ if (num_flexfec_streams > 0) {
+ video_send_config_.rtp.flexfec.payload_type = kFlexfecPayloadType;
+ video_send_config_.rtp.flexfec.ssrc = kFlexfecSendSsrc;
+ video_send_config_.rtp.flexfec.protected_media_ssrcs = {kVideoSendSsrcs[0]};
+ }
+}
+
+void CallTest::CreateMatchingReceiveConfigs(Transport* rtcp_send_transport) {
+ video_receive_configs_.clear();
+ allocated_decoders_.clear();
+ if (num_video_streams_ > 0) {
+ RTC_DCHECK(!video_send_config_.rtp.ssrcs.empty());
+ VideoReceiveStream::Config video_config(rtcp_send_transport);
+ video_config.rtp.remb = false;
+ video_config.rtp.transport_cc = true;
+ video_config.rtp.local_ssrc = kReceiverLocalVideoSsrc;
+ for (const RtpExtension& extension : video_send_config_.rtp.extensions)
+ video_config.rtp.extensions.push_back(extension);
+ video_config.renderer = &fake_renderer_;
+ for (size_t i = 0; i < video_send_config_.rtp.ssrcs.size(); ++i) {
+ VideoReceiveStream::Decoder decoder =
+ test::CreateMatchingDecoder(video_send_config_.encoder_settings);
+ allocated_decoders_.push_back(
+ std::unique_ptr<VideoDecoder>(decoder.decoder));
+ video_config.decoders.clear();
+ video_config.decoders.push_back(decoder);
+ video_config.rtp.remote_ssrc = video_send_config_.rtp.ssrcs[i];
+ video_receive_configs_.push_back(video_config.Copy());
+ }
+ video_receive_configs_[0].rtp.protected_by_flexfec =
+ (num_flexfec_streams_ == 1);
+ }
+
+ RTC_DCHECK_GE(1, num_audio_streams_);
+ if (num_audio_streams_ == 1) {
+ RTC_DCHECK_LE(0, voe_send_.channel_id);
+ AudioReceiveStream::Config audio_config;
+ audio_config.rtp.local_ssrc = kReceiverLocalAudioSsrc;
+ audio_config.rtcp_send_transport = rtcp_send_transport;
+ audio_config.voe_channel_id = voe_recv_.channel_id;
+ audio_config.rtp.remote_ssrc = audio_send_config_.rtp.ssrc;
+ audio_config.decoder_factory = decoder_factory_;
+ audio_config.decoder_map = {{kAudioSendPayloadType, {"opus", 48000, 2}}};
+ audio_receive_configs_.push_back(audio_config);
+ }
+
+ // TODO(brandtr): Update this when we support multistream protection.
+ RTC_DCHECK(num_flexfec_streams_ <= 1);
+ if (num_flexfec_streams_ == 1) {
+ FlexfecReceiveStream::Config config(rtcp_send_transport);
+ config.payload_type = kFlexfecPayloadType;
+ config.remote_ssrc = kFlexfecSendSsrc;
+ config.protected_media_ssrcs = {kVideoSendSsrcs[0]};
+ config.local_ssrc = kReceiverLocalVideoSsrc;
+ for (const RtpExtension& extension : video_send_config_.rtp.extensions)
+ config.rtp_header_extensions.push_back(extension);
+ flexfec_receive_configs_.push_back(config);
+ }
+}
+
+void CallTest::CreateFrameGeneratorCapturerWithDrift(Clock* clock,
+ float speed,
+ int framerate,
+ int width,
+ int height) {
+ frame_generator_capturer_.reset(test::FrameGeneratorCapturer::Create(
+ width, height, framerate * speed, clock));
+ video_send_stream_->SetSource(
+ frame_generator_capturer_.get(),
+ VideoSendStream::DegradationPreference::kMaintainFramerate);
+}
+
+void CallTest::CreateFrameGeneratorCapturer(int framerate,
+ int width,
+ int height) {
+ frame_generator_capturer_.reset(
+ test::FrameGeneratorCapturer::Create(width, height, framerate, clock_));
+ video_send_stream_->SetSource(
+ frame_generator_capturer_.get(),
+ VideoSendStream::DegradationPreference::kMaintainFramerate);
+}
+
+void CallTest::CreateFakeAudioDevices(
+ std::unique_ptr<FakeAudioDevice::Capturer> capturer,
+ std::unique_ptr<FakeAudioDevice::Renderer> renderer) {
+ fake_send_audio_device_.reset(new FakeAudioDevice(
+ std::move(capturer), nullptr, 1.f));
+ fake_recv_audio_device_.reset(new FakeAudioDevice(
+ nullptr, std::move(renderer), 1.f));
+}
+
+void CallTest::CreateVideoStreams() {
+ RTC_DCHECK(video_send_stream_ == nullptr);
+ RTC_DCHECK(video_receive_streams_.empty());
+ RTC_DCHECK(audio_send_stream_ == nullptr);
+ RTC_DCHECK(audio_receive_streams_.empty());
+
+ video_send_stream_ = sender_call_->CreateVideoSendStream(
+ video_send_config_.Copy(), video_encoder_config_.Copy());
+ for (size_t i = 0; i < video_receive_configs_.size(); ++i) {
+ video_receive_streams_.push_back(receiver_call_->CreateVideoReceiveStream(
+ video_receive_configs_[i].Copy()));
+ }
+
+ AssociateFlexfecStreamsWithVideoStreams();
+}
+
+void CallTest::CreateAudioStreams() {
+ audio_send_stream_ = sender_call_->CreateAudioSendStream(audio_send_config_);
+ for (size_t i = 0; i < audio_receive_configs_.size(); ++i) {
+ audio_receive_streams_.push_back(
+ receiver_call_->CreateAudioReceiveStream(audio_receive_configs_[i]));
+ }
+}
+
+void CallTest::CreateFlexfecStreams() {
+ for (size_t i = 0; i < flexfec_receive_configs_.size(); ++i) {
+ flexfec_receive_streams_.push_back(
+ receiver_call_->CreateFlexfecReceiveStream(
+ flexfec_receive_configs_[i]));
+ }
+
+ AssociateFlexfecStreamsWithVideoStreams();
+}
+
+void CallTest::AssociateFlexfecStreamsWithVideoStreams() {
+ // All FlexFEC streams protect all of the video streams.
+ for (FlexfecReceiveStream* flexfec_recv_stream : flexfec_receive_streams_) {
+ for (VideoReceiveStream* video_recv_stream : video_receive_streams_) {
+ video_recv_stream->AddSecondarySink(flexfec_recv_stream);
+ }
+ }
+}
+
+void CallTest::DissociateFlexfecStreamsFromVideoStreams() {
+ for (FlexfecReceiveStream* flexfec_recv_stream : flexfec_receive_streams_) {
+ for (VideoReceiveStream* video_recv_stream : video_receive_streams_) {
+ video_recv_stream->RemoveSecondarySink(flexfec_recv_stream);
+ }
+ }
+}
+
+void CallTest::Start() {
+ if (video_send_stream_)
+ video_send_stream_->Start();
+ for (VideoReceiveStream* video_recv_stream : video_receive_streams_)
+ video_recv_stream->Start();
+ if (audio_send_stream_) {
+ audio_send_stream_->Start();
+ }
+ for (AudioReceiveStream* audio_recv_stream : audio_receive_streams_)
+ audio_recv_stream->Start();
+ if (frame_generator_capturer_.get() != NULL)
+ frame_generator_capturer_->Start();
+}
+
+void CallTest::Stop() {
+ if (frame_generator_capturer_.get() != NULL)
+ frame_generator_capturer_->Stop();
+ for (AudioReceiveStream* audio_recv_stream : audio_receive_streams_)
+ audio_recv_stream->Stop();
+ if (audio_send_stream_) {
+ audio_send_stream_->Stop();
+ }
+ for (VideoReceiveStream* video_recv_stream : video_receive_streams_)
+ video_recv_stream->Stop();
+ if (video_send_stream_)
+ video_send_stream_->Stop();
+}
+
+void CallTest::DestroyStreams() {
+ DissociateFlexfecStreamsFromVideoStreams();
+
+ if (audio_send_stream_)
+ sender_call_->DestroyAudioSendStream(audio_send_stream_);
+ audio_send_stream_ = nullptr;
+ for (AudioReceiveStream* audio_recv_stream : audio_receive_streams_)
+ receiver_call_->DestroyAudioReceiveStream(audio_recv_stream);
+
+ if (video_send_stream_)
+ sender_call_->DestroyVideoSendStream(video_send_stream_);
+ video_send_stream_ = nullptr;
+
+ for (VideoReceiveStream* video_recv_stream : video_receive_streams_)
+ receiver_call_->DestroyVideoReceiveStream(video_recv_stream);
+
+ for (FlexfecReceiveStream* flexfec_recv_stream : flexfec_receive_streams_)
+ receiver_call_->DestroyFlexfecReceiveStream(flexfec_recv_stream);
+
+ video_receive_streams_.clear();
+ allocated_decoders_.clear();
+}
+
+void CallTest::SetFakeVideoCaptureRotation(VideoRotation rotation) {
+ frame_generator_capturer_->SetFakeRotation(rotation);
+}
+
+void CallTest::CreateVoiceEngines() {
+ voe_send_.voice_engine = VoiceEngine::Create();
+ voe_send_.base = VoEBase::GetInterface(voe_send_.voice_engine);
+ EXPECT_EQ(0, fake_send_audio_device_->Init());
+ EXPECT_EQ(0, voe_send_.base->Init(fake_send_audio_device_.get(),
+ apm_send_.get(), decoder_factory_));
+ VoEBase::ChannelConfig config;
+ config.enable_voice_pacing = true;
+ voe_send_.channel_id = voe_send_.base->CreateChannel(config);
+ EXPECT_GE(voe_send_.channel_id, 0);
+
+ voe_recv_.voice_engine = VoiceEngine::Create();
+ voe_recv_.base = VoEBase::GetInterface(voe_recv_.voice_engine);
+ EXPECT_EQ(0, fake_recv_audio_device_->Init());
+ EXPECT_EQ(0, voe_recv_.base->Init(fake_recv_audio_device_.get(),
+ apm_recv_.get(), decoder_factory_));
+ voe_recv_.channel_id = voe_recv_.base->CreateChannel();
+ EXPECT_GE(voe_recv_.channel_id, 0);
+}
+
+void CallTest::DestroyVoiceEngines() {
+ voe_recv_.base->DeleteChannel(voe_recv_.channel_id);
+ voe_recv_.channel_id = -1;
+ voe_recv_.base->Release();
+ voe_recv_.base = nullptr;
+
+ voe_send_.base->DeleteChannel(voe_send_.channel_id);
+ voe_send_.channel_id = -1;
+ voe_send_.base->Release();
+ voe_send_.base = nullptr;
+
+ VoiceEngine::Delete(voe_send_.voice_engine);
+ voe_send_.voice_engine = nullptr;
+ VoiceEngine::Delete(voe_recv_.voice_engine);
+ voe_recv_.voice_engine = nullptr;
+}
+
+const int CallTest::kDefaultWidth;
+const int CallTest::kDefaultHeight;
+const int CallTest::kDefaultFramerate;
+const int CallTest::kDefaultTimeoutMs = 30 * 1000;
+const int CallTest::kLongTimeoutMs = 120 * 1000;
+const uint8_t CallTest::kVideoSendPayloadType = 100;
+const uint8_t CallTest::kFakeVideoSendPayloadType = 125;
+const uint8_t CallTest::kSendRtxPayloadType = 98;
+const uint8_t CallTest::kRedPayloadType = 118;
+const uint8_t CallTest::kRtxRedPayloadType = 99;
+const uint8_t CallTest::kUlpfecPayloadType = 119;
+const uint8_t CallTest::kFlexfecPayloadType = 120;
+const uint8_t CallTest::kAudioSendPayloadType = 103;
+const uint8_t CallTest::kPayloadTypeH264 = 122;
+const uint8_t CallTest::kPayloadTypeVP8 = 123;
+const uint8_t CallTest::kPayloadTypeVP9 = 124;
+const uint32_t CallTest::kSendRtxSsrcs[kNumSsrcs] = {0xBADCAFD, 0xBADCAFE,
+ 0xBADCAFF};
+const uint32_t CallTest::kVideoSendSsrcs[kNumSsrcs] = {0xC0FFED, 0xC0FFEE,
+ 0xC0FFEF};
+const uint32_t CallTest::kAudioSendSsrc = 0xDEADBEEF;
+const uint32_t CallTest::kFlexfecSendSsrc = 0xBADBEEF;
+const uint32_t CallTest::kReceiverLocalVideoSsrc = 0x123456;
+const uint32_t CallTest::kReceiverLocalAudioSsrc = 0x1234567;
+const int CallTest::kNackRtpHistoryMs = 1000;
+
+const uint8_t CallTest::kDefaultKeepalivePayloadType =
+ RtpKeepAliveConfig().payload_type;
+
+const std::map<uint8_t, MediaType> CallTest::payload_type_map_ = {
+ {CallTest::kVideoSendPayloadType, MediaType::VIDEO},
+ {CallTest::kFakeVideoSendPayloadType, MediaType::VIDEO},
+ {CallTest::kSendRtxPayloadType, MediaType::VIDEO},
+ {CallTest::kRedPayloadType, MediaType::VIDEO},
+ {CallTest::kRtxRedPayloadType, MediaType::VIDEO},
+ {CallTest::kUlpfecPayloadType, MediaType::VIDEO},
+ {CallTest::kFlexfecPayloadType, MediaType::VIDEO},
+ {CallTest::kAudioSendPayloadType, MediaType::AUDIO},
+ {CallTest::kDefaultKeepalivePayloadType, MediaType::ANY}};
+
+BaseTest::BaseTest() : event_log_(RtcEventLog::CreateNull()) {}
+
+BaseTest::BaseTest(unsigned int timeout_ms)
+ : RtpRtcpObserver(timeout_ms), event_log_(RtcEventLog::CreateNull()) {}
+
+BaseTest::~BaseTest() {
+}
+
+std::unique_ptr<FakeAudioDevice::Capturer> BaseTest::CreateCapturer() {
+ return FakeAudioDevice::CreatePulsedNoiseCapturer(256, 48000);
+}
+
+std::unique_ptr<FakeAudioDevice::Renderer> BaseTest::CreateRenderer() {
+ return FakeAudioDevice::CreateDiscardRenderer(48000);
+}
+
+void BaseTest::OnFakeAudioDevicesCreated(FakeAudioDevice* send_audio_device,
+ FakeAudioDevice* recv_audio_device) {
+}
+
+Call::Config BaseTest::GetSenderCallConfig() {
+ return Call::Config(event_log_.get());
+}
+
+Call::Config BaseTest::GetReceiverCallConfig() {
+ return Call::Config(event_log_.get());
+}
+
+void BaseTest::OnRtpTransportControllerSendCreated(
+ RtpTransportControllerSend* controller) {}
+
+void BaseTest::OnCallsCreated(Call* sender_call, Call* receiver_call) {
+}
+
+test::PacketTransport* BaseTest::CreateSendTransport(
+ SingleThreadedTaskQueueForTesting* task_queue,
+ Call* sender_call) {
+ return new PacketTransport(
+ task_queue, sender_call, this, test::PacketTransport::kSender,
+ CallTest::payload_type_map_, FakeNetworkPipe::Config());
+}
+
+test::PacketTransport* BaseTest::CreateReceiveTransport(
+ SingleThreadedTaskQueueForTesting* task_queue) {
+ return new PacketTransport(
+ task_queue, nullptr, this, test::PacketTransport::kReceiver,
+ CallTest::payload_type_map_, FakeNetworkPipe::Config());
+}
+
+size_t BaseTest::GetNumVideoStreams() const {
+ return 1;
+}
+
+size_t BaseTest::GetNumAudioStreams() const {
+ return 0;
+}
+
+size_t BaseTest::GetNumFlexfecStreams() const {
+ return 0;
+}
+
+void BaseTest::ModifyVideoConfigs(
+ VideoSendStream::Config* send_config,
+ std::vector<VideoReceiveStream::Config>* receive_configs,
+ VideoEncoderConfig* encoder_config) {}
+
+void BaseTest::ModifyVideoCaptureStartResolution(int* width,
+ int* heigt,
+ int* frame_rate) {}
+
+void BaseTest::OnVideoStreamsCreated(
+ VideoSendStream* send_stream,
+ const std::vector<VideoReceiveStream*>& receive_streams) {}
+
+void BaseTest::ModifyAudioConfigs(
+ AudioSendStream::Config* send_config,
+ std::vector<AudioReceiveStream::Config>* receive_configs) {}
+
+void BaseTest::OnAudioStreamsCreated(
+ AudioSendStream* send_stream,
+ const std::vector<AudioReceiveStream*>& receive_streams) {}
+
+void BaseTest::ModifyFlexfecConfigs(
+ std::vector<FlexfecReceiveStream::Config>* receive_configs) {}
+
+void BaseTest::OnFlexfecStreamsCreated(
+ const std::vector<FlexfecReceiveStream*>& receive_streams) {}
+
+void BaseTest::OnFrameGeneratorCapturerCreated(
+ FrameGeneratorCapturer* frame_generator_capturer) {
+}
+
+void BaseTest::OnStreamsStopped() {
+}
+
+SendTest::SendTest(unsigned int timeout_ms) : BaseTest(timeout_ms) {
+}
+
+bool SendTest::ShouldCreateReceivers() const {
+ return false;
+}
+
+EndToEndTest::EndToEndTest() {}
+
+EndToEndTest::EndToEndTest(unsigned int timeout_ms) : BaseTest(timeout_ms) {
+}
+
+bool EndToEndTest::ShouldCreateReceivers() const {
+ return true;
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/call_test.h b/third_party/libwebrtc/webrtc/test/call_test.h
new file mode 100644
index 0000000000..cf15aacf11
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/call_test.h
@@ -0,0 +1,249 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef TEST_CALL_TEST_H_
+#define TEST_CALL_TEST_H_
+
+#include <memory>
+#include <vector>
+
+#include "call/call.h"
+#include "call/rtp_transport_controller_send.h"
+#include "logging/rtc_event_log/rtc_event_log.h"
+#include "test/encoder_settings.h"
+#include "test/fake_audio_device.h"
+#include "test/fake_decoder.h"
+#include "test/fake_encoder.h"
+#include "test/fake_videorenderer.h"
+#include "test/frame_generator_capturer.h"
+#include "test/rtp_rtcp_observer.h"
+#include "test/single_threaded_task_queue.h"
+
+namespace webrtc {
+
+class VoEBase;
+
+namespace test {
+
+class BaseTest;
+
+class CallTest : public ::testing::Test {
+ public:
+ CallTest();
+ virtual ~CallTest();
+
+ static const size_t kNumSsrcs = 3;
+ static const int kDefaultWidth = 320;
+ static const int kDefaultHeight = 180;
+ static const int kDefaultFramerate = 30;
+ static const int kDefaultTimeoutMs;
+ static const int kLongTimeoutMs;
+ static const uint8_t kVideoSendPayloadType;
+ static const uint8_t kSendRtxPayloadType;
+ static const uint8_t kFakeVideoSendPayloadType;
+ static const uint8_t kRedPayloadType;
+ static const uint8_t kRtxRedPayloadType;
+ static const uint8_t kUlpfecPayloadType;
+ static const uint8_t kFlexfecPayloadType;
+ static const uint8_t kAudioSendPayloadType;
+ static const uint8_t kPayloadTypeH264;
+ static const uint8_t kPayloadTypeVP8;
+ static const uint8_t kPayloadTypeVP9;
+ static const uint32_t kSendRtxSsrcs[kNumSsrcs];
+ static const uint32_t kVideoSendSsrcs[kNumSsrcs];
+ static const uint32_t kAudioSendSsrc;
+ static const uint32_t kFlexfecSendSsrc;
+ static const uint32_t kReceiverLocalVideoSsrc;
+ static const uint32_t kReceiverLocalAudioSsrc;
+ static const int kNackRtpHistoryMs;
+ static const uint8_t kDefaultKeepalivePayloadType;
+ static const std::map<uint8_t, MediaType> payload_type_map_;
+
+ protected:
+ // RunBaseTest overwrites the audio_state and the voice_engine of the send and
+ // receive Call configs to simplify test code and avoid having old VoiceEngine
+ // APIs in the tests.
+ void RunBaseTest(BaseTest* test);
+
+ void CreateCalls(const Call::Config& sender_config,
+ const Call::Config& receiver_config);
+ void CreateSenderCall(const Call::Config& config);
+ void CreateReceiverCall(const Call::Config& config);
+ void DestroyCalls();
+
+ void CreateSendConfig(size_t num_video_streams,
+ size_t num_audio_streams,
+ size_t num_flexfec_streams,
+ Transport* send_transport);
+
+ void CreateMatchingReceiveConfigs(Transport* rtcp_send_transport);
+
+ void CreateFrameGeneratorCapturerWithDrift(Clock* drift_clock,
+ float speed,
+ int framerate,
+ int width,
+ int height);
+ void CreateFrameGeneratorCapturer(int framerate, int width, int height);
+ void CreateFakeAudioDevices(
+ std::unique_ptr<FakeAudioDevice::Capturer> capturer,
+ std::unique_ptr<FakeAudioDevice::Renderer> renderer);
+
+ void CreateVideoStreams();
+ void CreateAudioStreams();
+ void CreateFlexfecStreams();
+
+ void AssociateFlexfecStreamsWithVideoStreams();
+ void DissociateFlexfecStreamsFromVideoStreams();
+
+ void Start();
+ void Stop();
+ void DestroyStreams();
+ void SetFakeVideoCaptureRotation(VideoRotation rotation);
+
+ Clock* const clock_;
+
+ std::unique_ptr<webrtc::RtcEventLog> event_log_;
+ std::unique_ptr<Call> sender_call_;
+ RtpTransportControllerSend* sender_call_transport_controller_;
+ std::unique_ptr<PacketTransport> send_transport_;
+ VideoSendStream::Config video_send_config_;
+ VideoEncoderConfig video_encoder_config_;
+ VideoSendStream* video_send_stream_;
+ AudioSendStream::Config audio_send_config_;
+ AudioSendStream* audio_send_stream_;
+
+ std::unique_ptr<Call> receiver_call_;
+ std::unique_ptr<PacketTransport> receive_transport_;
+ std::vector<VideoReceiveStream::Config> video_receive_configs_;
+ std::vector<VideoReceiveStream*> video_receive_streams_;
+ std::vector<AudioReceiveStream::Config> audio_receive_configs_;
+ std::vector<AudioReceiveStream*> audio_receive_streams_;
+ std::vector<FlexfecReceiveStream::Config> flexfec_receive_configs_;
+ std::vector<FlexfecReceiveStream*> flexfec_receive_streams_;
+
+ std::unique_ptr<test::FrameGeneratorCapturer> frame_generator_capturer_;
+ test::FakeEncoder fake_encoder_;
+ std::vector<std::unique_ptr<VideoDecoder>> allocated_decoders_;
+ size_t num_video_streams_;
+ size_t num_audio_streams_;
+ size_t num_flexfec_streams_;
+ rtc::scoped_refptr<AudioDecoderFactory> decoder_factory_;
+ rtc::scoped_refptr<AudioEncoderFactory> encoder_factory_;
+ test::FakeVideoRenderer fake_renderer_;
+
+ SingleThreadedTaskQueueForTesting task_queue_;
+
+ private:
+ // TODO(holmer): Remove once VoiceEngine is fully refactored to the new API.
+ // These methods are used to set up legacy voice engines and channels which is
+ // necessary while voice engine is being refactored to the new stream API.
+ struct VoiceEngineState {
+ VoiceEngineState()
+ : voice_engine(nullptr),
+ base(nullptr),
+ channel_id(-1) {}
+
+ VoiceEngine* voice_engine;
+ VoEBase* base;
+ int channel_id;
+ };
+
+ void CreateVoiceEngines();
+ void DestroyVoiceEngines();
+
+ VoiceEngineState voe_send_;
+ VoiceEngineState voe_recv_;
+ rtc::scoped_refptr<AudioProcessing> apm_send_;
+ rtc::scoped_refptr<AudioProcessing> apm_recv_;
+
+ // The audio devices must outlive the voice engines.
+ std::unique_ptr<test::FakeAudioDevice> fake_send_audio_device_;
+ std::unique_ptr<test::FakeAudioDevice> fake_recv_audio_device_;
+};
+
+class BaseTest : public RtpRtcpObserver {
+ public:
+ BaseTest();
+ explicit BaseTest(unsigned int timeout_ms);
+ virtual ~BaseTest();
+
+ virtual void PerformTest() = 0;
+ virtual bool ShouldCreateReceivers() const = 0;
+
+ virtual size_t GetNumVideoStreams() const;
+ virtual size_t GetNumAudioStreams() const;
+ virtual size_t GetNumFlexfecStreams() const;
+
+ virtual std::unique_ptr<FakeAudioDevice::Capturer> CreateCapturer();
+ virtual std::unique_ptr<FakeAudioDevice::Renderer> CreateRenderer();
+ virtual void OnFakeAudioDevicesCreated(FakeAudioDevice* send_audio_device,
+ FakeAudioDevice* recv_audio_device);
+
+ virtual Call::Config GetSenderCallConfig();
+ virtual Call::Config GetReceiverCallConfig();
+ virtual void OnRtpTransportControllerSendCreated(
+ RtpTransportControllerSend* controller);
+ virtual void OnCallsCreated(Call* sender_call, Call* receiver_call);
+
+ virtual test::PacketTransport* CreateSendTransport(
+ SingleThreadedTaskQueueForTesting* task_queue,
+ Call* sender_call);
+ virtual test::PacketTransport* CreateReceiveTransport(
+ SingleThreadedTaskQueueForTesting* task_queue);
+
+ virtual void ModifyVideoConfigs(
+ VideoSendStream::Config* send_config,
+ std::vector<VideoReceiveStream::Config>* receive_configs,
+ VideoEncoderConfig* encoder_config);
+ virtual void ModifyVideoCaptureStartResolution(int* width,
+ int* heigt,
+ int* frame_rate);
+ virtual void OnVideoStreamsCreated(
+ VideoSendStream* send_stream,
+ const std::vector<VideoReceiveStream*>& receive_streams);
+
+ virtual void ModifyAudioConfigs(
+ AudioSendStream::Config* send_config,
+ std::vector<AudioReceiveStream::Config>* receive_configs);
+ virtual void OnAudioStreamsCreated(
+ AudioSendStream* send_stream,
+ const std::vector<AudioReceiveStream*>& receive_streams);
+
+ virtual void ModifyFlexfecConfigs(
+ std::vector<FlexfecReceiveStream::Config>* receive_configs);
+ virtual void OnFlexfecStreamsCreated(
+ const std::vector<FlexfecReceiveStream*>& receive_streams);
+
+ virtual void OnFrameGeneratorCapturerCreated(
+ FrameGeneratorCapturer* frame_generator_capturer);
+
+ virtual void OnStreamsStopped();
+
+ std::unique_ptr<webrtc::RtcEventLog> event_log_;
+};
+
+class SendTest : public BaseTest {
+ public:
+ explicit SendTest(unsigned int timeout_ms);
+
+ bool ShouldCreateReceivers() const override;
+};
+
+class EndToEndTest : public BaseTest {
+ public:
+ EndToEndTest();
+ explicit EndToEndTest(unsigned int timeout_ms);
+
+ bool ShouldCreateReceivers() const override;
+};
+
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_CALL_TEST_H_
diff --git a/third_party/libwebrtc/webrtc/test/configurable_frame_size_encoder.cc b/third_party/libwebrtc/webrtc/test/configurable_frame_size_encoder.cc
new file mode 100644
index 0000000000..cbfb35bf33
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/configurable_frame_size_encoder.cc
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/configurable_frame_size_encoder.h"
+
+#include <string.h>
+
+#include "common_video/include/video_frame.h"
+#include "modules/video_coding/include/video_codec_interface.h"
+#include "rtc_base/checks.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+namespace test {
+
+ConfigurableFrameSizeEncoder::ConfigurableFrameSizeEncoder(
+ size_t max_frame_size)
+ : callback_(NULL),
+ max_frame_size_(max_frame_size),
+ current_frame_size_(max_frame_size),
+ buffer_(new uint8_t[max_frame_size]) {
+ memset(buffer_.get(), 0, max_frame_size);
+}
+
+ConfigurableFrameSizeEncoder::~ConfigurableFrameSizeEncoder() {}
+
+int32_t ConfigurableFrameSizeEncoder::InitEncode(
+ const VideoCodec* codec_settings,
+ int32_t number_of_cores,
+ size_t max_payload_size) {
+ return WEBRTC_VIDEO_CODEC_OK;
+}
+
+int32_t ConfigurableFrameSizeEncoder::Encode(
+ const VideoFrame& inputImage,
+ const CodecSpecificInfo* codecSpecificInfo,
+ const std::vector<FrameType>* frame_types) {
+ EncodedImage encodedImage(
+ buffer_.get(), current_frame_size_, max_frame_size_);
+ encodedImage._completeFrame = true;
+ encodedImage._encodedHeight = inputImage.height();
+ encodedImage._encodedWidth = inputImage.width();
+ encodedImage._frameType = kVideoFrameKey;
+ encodedImage._timeStamp = inputImage.timestamp();
+ encodedImage.capture_time_ms_ = inputImage.render_time_ms();
+ RTPFragmentationHeader* fragmentation = NULL;
+ CodecSpecificInfo specific;
+ memset(&specific, 0, sizeof(specific));
+ callback_->OnEncodedImage(encodedImage, &specific, fragmentation);
+
+ return WEBRTC_VIDEO_CODEC_OK;
+}
+
+int32_t ConfigurableFrameSizeEncoder::RegisterEncodeCompleteCallback(
+ EncodedImageCallback* callback) {
+ callback_ = callback;
+ return WEBRTC_VIDEO_CODEC_OK;
+}
+
+int32_t ConfigurableFrameSizeEncoder::Release() {
+ return WEBRTC_VIDEO_CODEC_OK;
+}
+
+int32_t ConfigurableFrameSizeEncoder::SetChannelParameters(uint32_t packet_loss,
+ int64_t rtt) {
+ return WEBRTC_VIDEO_CODEC_OK;
+}
+
+int32_t ConfigurableFrameSizeEncoder::SetRateAllocation(
+ const BitrateAllocation& allocation,
+ uint32_t framerate) {
+ return WEBRTC_VIDEO_CODEC_OK;
+}
+
+int32_t ConfigurableFrameSizeEncoder::SetPeriodicKeyFrames(bool enable) {
+ return WEBRTC_VIDEO_CODEC_OK;
+}
+
+int32_t ConfigurableFrameSizeEncoder::SetFrameSize(size_t size) {
+ RTC_DCHECK_LE(size, max_frame_size_);
+ current_frame_size_ = size;
+ return WEBRTC_VIDEO_CODEC_OK;
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/configurable_frame_size_encoder.h b/third_party/libwebrtc/webrtc/test/configurable_frame_size_encoder.h
new file mode 100644
index 0000000000..8d3cbc65af
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/configurable_frame_size_encoder.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef TEST_CONFIGURABLE_FRAME_SIZE_ENCODER_H_
+#define TEST_CONFIGURABLE_FRAME_SIZE_ENCODER_H_
+
+#include <memory>
+#include <vector>
+
+#include "api/video_codecs/video_encoder.h"
+
+namespace webrtc {
+namespace test {
+
+class ConfigurableFrameSizeEncoder : public VideoEncoder {
+ public:
+ explicit ConfigurableFrameSizeEncoder(size_t max_frame_size);
+ virtual ~ConfigurableFrameSizeEncoder();
+
+ int32_t InitEncode(const VideoCodec* codec_settings,
+ int32_t number_of_cores,
+ size_t max_payload_size) override;
+
+ int32_t Encode(const VideoFrame& input_image,
+ const CodecSpecificInfo* codec_specific_info,
+ const std::vector<FrameType>* frame_types) override;
+
+ int32_t RegisterEncodeCompleteCallback(
+ EncodedImageCallback* callback) override;
+
+ int32_t Release() override;
+
+ int32_t SetChannelParameters(uint32_t packet_loss, int64_t rtt) override;
+
+ int32_t SetRateAllocation(const BitrateAllocation& allocation,
+ uint32_t framerate) override;
+
+ int32_t SetPeriodicKeyFrames(bool enable) override;
+
+ int32_t SetFrameSize(size_t size);
+
+ private:
+ EncodedImageCallback* callback_;
+ const size_t max_frame_size_;
+ size_t current_frame_size_;
+ std::unique_ptr<uint8_t[]> buffer_;
+};
+
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_CONFIGURABLE_FRAME_SIZE_ENCODER_H_
diff --git a/third_party/libwebrtc/webrtc/test/constants.cc b/third_party/libwebrtc/webrtc/test/constants.cc
new file mode 100644
index 0000000000..0835777570
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/constants.cc
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/constants.h"
+
+namespace webrtc {
+namespace test {
+
+const int kAudioLevelExtensionId = 5;
+const int kTOffsetExtensionId = 6;
+const int kAbsSendTimeExtensionId = 7;
+const int kTransportSequenceNumberExtensionId = 8;
+const int kVideoRotationExtensionId = 9;
+const int kVideoContentTypeExtensionId = 10;
+const int kVideoTimingExtensionId = 11;
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/constants.h b/third_party/libwebrtc/webrtc/test/constants.h
new file mode 100644
index 0000000000..85e8c18d53
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/constants.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+namespace webrtc {
+namespace test {
+
+extern const int kAudioLevelExtensionId;
+extern const int kTOffsetExtensionId;
+extern const int kAbsSendTimeExtensionId;
+extern const int kTransportSequenceNumberExtensionId;
+extern const int kVideoRotationExtensionId;
+extern const int kVideoContentTypeExtensionId;
+extern const int kVideoTimingExtensionId;
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/direct_transport.cc b/third_party/libwebrtc/webrtc/test/direct_transport.cc
new file mode 100644
index 0000000000..dddbe58909
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/direct_transport.cc
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "test/direct_transport.h"
+
+#include "call/call.h"
+#include "rtc_base/ptr_util.h"
+#include "system_wrappers/include/clock.h"
+#include "test/single_threaded_task_queue.h"
+
+namespace webrtc {
+namespace test {
+
+DirectTransport::DirectTransport(
+ SingleThreadedTaskQueueForTesting* task_queue,
+ Call* send_call,
+ const std::map<uint8_t, MediaType>& payload_type_map)
+ : DirectTransport(task_queue,
+ FakeNetworkPipe::Config(),
+ send_call,
+ payload_type_map) {
+}
+
+DirectTransport::DirectTransport(
+ SingleThreadedTaskQueueForTesting* task_queue,
+ const FakeNetworkPipe::Config& config,
+ Call* send_call,
+ const std::map<uint8_t, MediaType>& payload_type_map)
+ : DirectTransport(
+ task_queue,
+ config,
+ send_call,
+ std::unique_ptr<Demuxer>(new DemuxerImpl(payload_type_map))) {
+}
+
+DirectTransport::DirectTransport(SingleThreadedTaskQueueForTesting* task_queue,
+ const FakeNetworkPipe::Config& config,
+ Call* send_call,
+ std::unique_ptr<Demuxer> demuxer)
+ : send_call_(send_call),
+ clock_(Clock::GetRealTimeClock()),
+ task_queue_(task_queue),
+ fake_network_(rtc::MakeUnique<FakeNetworkPipe>(clock_, config,
+ std::move(demuxer))) {
+ Start();
+}
+
+DirectTransport::DirectTransport(SingleThreadedTaskQueueForTesting* task_queue,
+ std::unique_ptr<FakeNetworkPipe> pipe,
+ Call* send_call)
+ : send_call_(send_call),
+ clock_(Clock::GetRealTimeClock()),
+ task_queue_(task_queue),
+ fake_network_(std::move(pipe)) {
+ Start();
+}
+
+DirectTransport::~DirectTransport() {
+ RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
+ // Constructor updates |next_scheduled_task_|, so it's guaranteed to
+ // be initialized.
+ task_queue_->CancelTask(next_scheduled_task_);
+}
+
+void DirectTransport::SetConfig(const FakeNetworkPipe::Config& config) {
+ fake_network_->SetConfig(config);
+}
+
+void DirectTransport::StopSending() {
+ RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
+ task_queue_->CancelTask(next_scheduled_task_);
+}
+
+void DirectTransport::SetReceiver(PacketReceiver* receiver) {
+ RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
+ fake_network_->SetReceiver(receiver);
+}
+
+bool DirectTransport::SendRtp(const uint8_t* data,
+ size_t length,
+ const PacketOptions& options) {
+ if (send_call_) {
+ rtc::SentPacket sent_packet(options.packet_id,
+ clock_->TimeInMilliseconds());
+ send_call_->OnSentPacket(sent_packet);
+ }
+ fake_network_->SendPacket(data, length);
+ return true;
+}
+
+bool DirectTransport::SendRtcp(const uint8_t* data, size_t length) {
+ fake_network_->SendPacket(data, length);
+ return true;
+}
+
+int DirectTransport::GetAverageDelayMs() {
+ return fake_network_->AverageDelay();
+}
+
+void DirectTransport::Start() {
+ RTC_DCHECK(task_queue_);
+ if (send_call_) {
+ send_call_->SignalChannelNetworkState(MediaType::AUDIO, kNetworkUp);
+ send_call_->SignalChannelNetworkState(MediaType::VIDEO, kNetworkUp);
+ }
+ SendPackets();
+}
+
+void DirectTransport::SendPackets() {
+ RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
+
+ fake_network_->Process();
+
+ int64_t delay_ms = fake_network_->TimeUntilNextProcess();
+ next_scheduled_task_ = task_queue_->PostDelayedTask([this]() {
+ SendPackets();
+ }, delay_ms);
+}
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/direct_transport.h b/third_party/libwebrtc/webrtc/test/direct_transport.h
new file mode 100644
index 0000000000..85cd892ec2
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/direct_transport.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef TEST_DIRECT_TRANSPORT_H_
+#define TEST_DIRECT_TRANSPORT_H_
+
+#include <assert.h>
+
+#include <memory>
+
+#include "api/call/transport.h"
+#include "call/call.h"
+#include "rtc_base/sequenced_task_checker.h"
+#include "rtc_base/thread_annotations.h"
+#include "test/fake_network_pipe.h"
+#include "test/single_threaded_task_queue.h"
+
+namespace webrtc {
+
+class Clock;
+class PacketReceiver;
+
+namespace test {
+
+// Objects of this class are expected to be allocated and destroyed on the
+// same task-queue - the one that's passed in via the constructor.
+class DirectTransport : public Transport {
+ public:
+ DirectTransport(SingleThreadedTaskQueueForTesting* task_queue,
+ Call* send_call,
+ const std::map<uint8_t, MediaType>& payload_type_map);
+
+ DirectTransport(SingleThreadedTaskQueueForTesting* task_queue,
+ const FakeNetworkPipe::Config& config,
+ Call* send_call,
+ const std::map<uint8_t, MediaType>& payload_type_map);
+
+ DirectTransport(SingleThreadedTaskQueueForTesting* task_queue,
+ const FakeNetworkPipe::Config& config,
+ Call* send_call,
+ std::unique_ptr<Demuxer> demuxer);
+
+ DirectTransport(SingleThreadedTaskQueueForTesting* task_queue,
+ std::unique_ptr<FakeNetworkPipe> pipe, Call* send_call);
+
+ ~DirectTransport() override;
+
+ void SetConfig(const FakeNetworkPipe::Config& config);
+
+ RTC_DEPRECATED void StopSending();
+
+ // TODO(holmer): Look into moving this to the constructor.
+ virtual void SetReceiver(PacketReceiver* receiver);
+
+ bool SendRtp(const uint8_t* data,
+ size_t length,
+ const PacketOptions& options) override;
+ bool SendRtcp(const uint8_t* data, size_t length) override;
+
+ int GetAverageDelayMs();
+
+ private:
+ void SendPackets();
+ void Start();
+
+ Call* const send_call_;
+ Clock* const clock_;
+
+ SingleThreadedTaskQueueForTesting* const task_queue_;
+ SingleThreadedTaskQueueForTesting::TaskId next_scheduled_task_
+ RTC_GUARDED_BY(&sequence_checker_);
+
+ std::unique_ptr<FakeNetworkPipe> fake_network_;
+
+ rtc::SequencedTaskChecker sequence_checker_;
+};
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_DIRECT_TRANSPORT_H_
diff --git a/third_party/libwebrtc/webrtc/test/drifting_clock.cc b/third_party/libwebrtc/webrtc/test/drifting_clock.cc
new file mode 100644
index 0000000000..5333e1de15
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/drifting_clock.cc
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/drifting_clock.h"
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+namespace test {
+const float DriftingClock::kDoubleSpeed = 2.0f;
+const float DriftingClock::kNoDrift = 1.0f;
+const float DriftingClock::kHalfSpeed = 0.5f;
+
+DriftingClock::DriftingClock(Clock* clock, float speed)
+ : clock_(clock),
+ drift_(speed - 1.0f),
+ start_time_(clock_->TimeInMicroseconds()) {
+ RTC_CHECK(clock);
+ RTC_CHECK_GT(speed, 0.0f);
+}
+
+float DriftingClock::Drift() const {
+ int64_t now = clock_->TimeInMicroseconds();
+ RTC_DCHECK_GE(now, start_time_);
+ return (now - start_time_) * drift_;
+}
+
+int64_t DriftingClock::TimeInMilliseconds() const {
+ return clock_->TimeInMilliseconds() + Drift() / 1000.;
+}
+
+int64_t DriftingClock::TimeInMicroseconds() const {
+ return clock_->TimeInMicroseconds() + Drift();
+}
+
+NtpTime DriftingClock::CurrentNtpTime() const {
+ // NTP precision is 1/2^32 seconds, i.e. 2^32 ntp fractions = 1 second.
+ const double kNtpFracPerMicroSecond = 4294.967296; // = 2^32 / 10^6
+
+ NtpTime ntp = clock_->CurrentNtpTime();
+ uint64_t total_fractions = static_cast<uint64_t>(ntp);
+ total_fractions += Drift() * kNtpFracPerMicroSecond;
+ return NtpTime(total_fractions);
+}
+
+int64_t DriftingClock::CurrentNtpInMilliseconds() const {
+ return clock_->CurrentNtpInMilliseconds() + Drift() / 1000.;
+}
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/drifting_clock.h b/third_party/libwebrtc/webrtc/test/drifting_clock.h
new file mode 100644
index 0000000000..a0ba93edf0
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/drifting_clock.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef TEST_DRIFTING_CLOCK_H_
+#define TEST_DRIFTING_CLOCK_H_
+
+#include "system_wrappers/include/clock.h"
+
+namespace webrtc {
+namespace test {
+class DriftingClock : public Clock {
+ public:
+ // TODO(danilchap): Make this constants constexpr when it would be supported.
+ static const float kDoubleSpeed; // 2.0f;
+ static const float kNoDrift; // 1.0f;
+ static const float kHalfSpeed; // 0.5f;
+
+ DriftingClock(Clock* clock, float speed);
+
+ // TODO(danilchap): Make this functions constexpr when it would be supported.
+ static float PercentsFaster(float percent) { return 1.0f + percent / 100.0f; }
+ static float PercentsSlower(float percent) { return 1.0f - percent / 100.0f; }
+
+ int64_t TimeInMilliseconds() const override;
+ int64_t TimeInMicroseconds() const override;
+ NtpTime CurrentNtpTime() const override;
+ int64_t CurrentNtpInMilliseconds() const override;
+
+ private:
+ float Drift() const;
+
+ Clock* const clock_;
+ const float drift_;
+ const int64_t start_time_;
+};
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_DRIFTING_CLOCK_H_
diff --git a/third_party/libwebrtc/webrtc/test/encoder_settings.cc b/third_party/libwebrtc/webrtc/test/encoder_settings.cc
new file mode 100644
index 0000000000..bd700cf6d2
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/encoder_settings.cc
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "test/encoder_settings.h"
+
+#include <algorithm>
+#include <string>
+
+#include "modules/video_coding/codecs/h264/include/h264.h"
+#include "modules/video_coding/codecs/vp8/include/vp8.h"
+#include "modules/video_coding/codecs/vp9/include/vp9.h"
+#include "rtc_base/refcountedobject.h"
+#include "test/fake_decoder.h"
+
+namespace webrtc {
+namespace test {
+
+const size_t DefaultVideoStreamFactory::kMaxNumberOfStreams;
+const int DefaultVideoStreamFactory::kMaxBitratePerStream[] = {150000, 450000,
+ 1500000};
+const int DefaultVideoStreamFactory::kDefaultMinBitratePerStream[] = {
+ 30000, 200000, 700000};
+
+// static
+std::vector<VideoStream> CreateVideoStreams(
+ int width,
+ int height,
+ const webrtc::VideoEncoderConfig& encoder_config) {
+ RTC_DCHECK(encoder_config.number_of_streams <=
+ DefaultVideoStreamFactory::kMaxNumberOfStreams);
+
+ std::vector<VideoStream> stream_settings(encoder_config.number_of_streams);
+ int bitrate_left_bps = encoder_config.max_bitrate_bps;
+
+ for (size_t i = 0; i < encoder_config.number_of_streams; ++i) {
+ stream_settings[i].width =
+ (i + 1) * width / encoder_config.number_of_streams;
+ stream_settings[i].height =
+ (i + 1) * height / encoder_config.number_of_streams;
+ stream_settings[i].max_framerate = 30;
+ stream_settings[i].min_bitrate_bps =
+ DefaultVideoStreamFactory::kDefaultMinBitratePerStream[i];
+ stream_settings[i].target_bitrate_bps = stream_settings[i].max_bitrate_bps =
+ std::min(bitrate_left_bps,
+ DefaultVideoStreamFactory::kMaxBitratePerStream[i]);
+ stream_settings[i].max_qp = 56;
+ bitrate_left_bps -= stream_settings[i].target_bitrate_bps;
+ }
+
+ stream_settings[encoder_config.number_of_streams - 1].max_bitrate_bps +=
+ bitrate_left_bps;
+
+ return stream_settings;
+}
+
+DefaultVideoStreamFactory::DefaultVideoStreamFactory() {}
+
+std::vector<VideoStream> DefaultVideoStreamFactory::CreateEncoderStreams(
+ int width,
+ int height,
+ const webrtc::VideoEncoderConfig& encoder_config) {
+ return CreateVideoStreams(width, height, encoder_config);
+}
+
+void FillEncoderConfiguration(size_t num_streams,
+ VideoEncoderConfig* configuration) {
+ RTC_DCHECK_LE(num_streams, DefaultVideoStreamFactory::kMaxNumberOfStreams);
+
+ configuration->number_of_streams = num_streams;
+ configuration->video_stream_factory =
+ new rtc::RefCountedObject<DefaultVideoStreamFactory>();
+ configuration->max_bitrate_bps = 0;
+ for (size_t i = 0; i < num_streams; ++i) {
+ configuration->max_bitrate_bps +=
+ DefaultVideoStreamFactory::kMaxBitratePerStream[i];
+ }
+}
+
+VideoReceiveStream::Decoder CreateMatchingDecoder(
+ const VideoSendStream::Config::EncoderSettings& encoder_settings) {
+ VideoReceiveStream::Decoder decoder;
+ decoder.payload_type = encoder_settings.payload_type;
+ decoder.payload_name = encoder_settings.payload_name;
+ if (encoder_settings.payload_name == "H264") {
+ decoder.decoder = H264Decoder::Create().release();
+ } else if (encoder_settings.payload_name == "VP8") {
+ decoder.decoder = VP8Decoder::Create().release();
+ } else if (encoder_settings.payload_name == "VP9") {
+ decoder.decoder = VP9Decoder::Create().release();
+ } else {
+ decoder.decoder = new FakeDecoder();
+ }
+ return decoder;
+}
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/encoder_settings.h b/third_party/libwebrtc/webrtc/test/encoder_settings.h
new file mode 100644
index 0000000000..25cfa29897
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/encoder_settings.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef TEST_ENCODER_SETTINGS_H_
+#define TEST_ENCODER_SETTINGS_H_
+
+#include <vector>
+
+#include "call/video_receive_stream.h"
+#include "call/video_send_stream.h"
+
+namespace webrtc {
+namespace test {
+
+class DefaultVideoStreamFactory
+ : public VideoEncoderConfig::VideoStreamFactoryInterface {
+ public:
+ DefaultVideoStreamFactory();
+
+ static const size_t kMaxNumberOfStreams = 3;
+ // Defined as {150000, 450000, 1500000};
+ static const int kMaxBitratePerStream[];
+ // Defined as {50000, 200000, 700000};
+ static const int kDefaultMinBitratePerStream[];
+
+ private:
+ std::vector<VideoStream> CreateEncoderStreams(
+ int width,
+ int height,
+ const VideoEncoderConfig& encoder_config) override;
+};
+
+// Creates |encoder_config.number_of_streams| VideoStreams where index
+// |encoder_config.number_of_streams -1| have width = |width|, height =
+// |height|. The total max bitrate of all VideoStreams is
+// |encoder_config.max_bitrate_bps|.
+std::vector<VideoStream> CreateVideoStreams(
+ int width,
+ int height,
+ const webrtc::VideoEncoderConfig& encoder_config);
+
+void FillEncoderConfiguration(size_t num_streams,
+ VideoEncoderConfig* configuration);
+
+VideoReceiveStream::Decoder CreateMatchingDecoder(
+ const VideoSendStream::Config::EncoderSettings& encoder_settings);
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_ENCODER_SETTINGS_H_
diff --git a/third_party/libwebrtc/webrtc/test/fake_audio_device.cc b/third_party/libwebrtc/webrtc/test/fake_audio_device.cc
new file mode 100644
index 0000000000..eef8bfd015
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fake_audio_device.cc
@@ -0,0 +1,380 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/fake_audio_device.h"
+
+#include <algorithm>
+#include <utility>
+
+#include "common_audio/wav_file.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/random.h"
+#include "system_wrappers/include/event_wrapper.h"
+
+namespace webrtc {
+
+namespace {
+
+constexpr int kFrameLengthMs = 10;
+constexpr int kFramesPerSecond = 1000 / kFrameLengthMs;
+
+// Assuming 10ms audio packets..
+class PulsedNoiseCapturer final : public test::FakeAudioDevice::Capturer {
+ public:
+ PulsedNoiseCapturer(int16_t max_amplitude, int sampling_frequency_in_hz)
+ : sampling_frequency_in_hz_(sampling_frequency_in_hz),
+ fill_with_zero_(false),
+ random_generator_(1),
+ max_amplitude_(max_amplitude) {
+ RTC_DCHECK_GT(max_amplitude, 0);
+ }
+
+ int SamplingFrequency() const override {
+ return sampling_frequency_in_hz_;
+ }
+
+ bool Capture(rtc::BufferT<int16_t>* buffer) override {
+ fill_with_zero_ = !fill_with_zero_;
+ buffer->SetData(
+ test::FakeAudioDevice::SamplesPerFrame(sampling_frequency_in_hz_),
+ [&](rtc::ArrayView<int16_t> data) {
+ if (fill_with_zero_) {
+ std::fill(data.begin(), data.end(), 0);
+ } else {
+ std::generate(data.begin(), data.end(), [&]() {
+ return random_generator_.Rand(-max_amplitude_, max_amplitude_);
+ });
+ }
+ return data.size();
+ });
+ return true;
+ }
+
+ private:
+ int sampling_frequency_in_hz_;
+ bool fill_with_zero_;
+ Random random_generator_;
+ const int16_t max_amplitude_;
+};
+
+class WavFileReader final : public test::FakeAudioDevice::Capturer {
+ public:
+ WavFileReader(std::string filename, int sampling_frequency_in_hz)
+ : sampling_frequency_in_hz_(sampling_frequency_in_hz),
+ wav_reader_(filename) {
+ RTC_CHECK_EQ(wav_reader_.sample_rate(), sampling_frequency_in_hz);
+ RTC_CHECK_EQ(wav_reader_.num_channels(), 1);
+ }
+
+ int SamplingFrequency() const override {
+ return sampling_frequency_in_hz_;
+ }
+
+ bool Capture(rtc::BufferT<int16_t>* buffer) override {
+ buffer->SetData(
+ test::FakeAudioDevice::SamplesPerFrame(sampling_frequency_in_hz_),
+ [&](rtc::ArrayView<int16_t> data) {
+ return wav_reader_.ReadSamples(data.size(), data.data());
+ });
+ return buffer->size() > 0;
+ }
+
+ private:
+ int sampling_frequency_in_hz_;
+ WavReader wav_reader_;
+};
+
+class WavFileWriter final : public test::FakeAudioDevice::Renderer {
+ public:
+ WavFileWriter(std::string filename, int sampling_frequency_in_hz)
+ : sampling_frequency_in_hz_(sampling_frequency_in_hz),
+ wav_writer_(filename, sampling_frequency_in_hz, 1) {}
+
+ int SamplingFrequency() const override {
+ return sampling_frequency_in_hz_;
+ }
+
+ bool Render(rtc::ArrayView<const int16_t> data) override {
+ wav_writer_.WriteSamples(data.data(), data.size());
+ return true;
+ }
+
+ private:
+ int sampling_frequency_in_hz_;
+ WavWriter wav_writer_;
+};
+
+class BoundedWavFileWriter : public test::FakeAudioDevice::Renderer {
+ public:
+ BoundedWavFileWriter(std::string filename, int sampling_frequency_in_hz)
+ : sampling_frequency_in_hz_(sampling_frequency_in_hz),
+ wav_writer_(filename, sampling_frequency_in_hz, 1),
+ silent_audio_(test::FakeAudioDevice::SamplesPerFrame(
+ sampling_frequency_in_hz), 0),
+ started_writing_(false),
+ trailing_zeros_(0) {}
+
+ int SamplingFrequency() const override {
+ return sampling_frequency_in_hz_;
+ }
+
+ bool Render(rtc::ArrayView<const int16_t> data) override {
+ const int16_t kAmplitudeThreshold = 5;
+
+ const int16_t* begin = data.begin();
+ const int16_t* end = data.end();
+ if (!started_writing_) {
+ // Cut off silence at the beginning.
+ while (begin < end) {
+ if (std::abs(*begin) > kAmplitudeThreshold) {
+ started_writing_ = true;
+ break;
+ }
+ ++begin;
+ }
+ }
+ if (started_writing_) {
+ // Cut off silence at the end.
+ while (begin < end) {
+ if (*(end - 1) != 0) {
+ break;
+ }
+ --end;
+ }
+ if (begin < end) {
+ // If it turns out that the silence was not final, need to write all the
+ // skipped zeros and continue writing audio.
+ while (trailing_zeros_ > 0) {
+ const size_t zeros_to_write = std::min(trailing_zeros_,
+ silent_audio_.size());
+ wav_writer_.WriteSamples(silent_audio_.data(), zeros_to_write);
+ trailing_zeros_ -= zeros_to_write;
+ }
+ wav_writer_.WriteSamples(begin, end - begin);
+ }
+ // Save the number of zeros we skipped in case this needs to be restored.
+ trailing_zeros_ += data.end() - end;
+ }
+ return true;
+ }
+
+ private:
+ int sampling_frequency_in_hz_;
+ WavWriter wav_writer_;
+ std::vector<int16_t> silent_audio_;
+ bool started_writing_;
+ size_t trailing_zeros_;
+};
+
+
+class DiscardRenderer final : public test::FakeAudioDevice::Renderer {
+ public:
+ explicit DiscardRenderer(int sampling_frequency_in_hz)
+ : sampling_frequency_in_hz_(sampling_frequency_in_hz) {}
+
+ int SamplingFrequency() const override {
+ return sampling_frequency_in_hz_;
+ }
+
+ bool Render(rtc::ArrayView<const int16_t> data) override {
+ return true;
+ }
+
+ private:
+ int sampling_frequency_in_hz_;
+};
+
+} // namespace
+namespace test {
+
+size_t FakeAudioDevice::SamplesPerFrame(int sampling_frequency_in_hz) {
+ return rtc::CheckedDivExact(sampling_frequency_in_hz, kFramesPerSecond);
+}
+
+std::unique_ptr<FakeAudioDevice::Capturer>
+ FakeAudioDevice::CreatePulsedNoiseCapturer(
+ int16_t max_amplitude, int sampling_frequency_in_hz) {
+ return std::unique_ptr<FakeAudioDevice::Capturer>(
+ new PulsedNoiseCapturer(max_amplitude, sampling_frequency_in_hz));
+}
+
+std::unique_ptr<FakeAudioDevice::Capturer> FakeAudioDevice::CreateWavFileReader(
+ std::string filename, int sampling_frequency_in_hz) {
+ return std::unique_ptr<FakeAudioDevice::Capturer>(
+ new WavFileReader(filename, sampling_frequency_in_hz));
+}
+
+std::unique_ptr<FakeAudioDevice::Capturer> FakeAudioDevice::CreateWavFileReader(
+ std::string filename) {
+ int sampling_frequency_in_hz = WavReader(filename).sample_rate();
+ return std::unique_ptr<FakeAudioDevice::Capturer>(
+ new WavFileReader(filename, sampling_frequency_in_hz));
+}
+
+std::unique_ptr<FakeAudioDevice::Renderer> FakeAudioDevice::CreateWavFileWriter(
+ std::string filename, int sampling_frequency_in_hz) {
+ return std::unique_ptr<FakeAudioDevice::Renderer>(
+ new WavFileWriter(filename, sampling_frequency_in_hz));
+}
+
+std::unique_ptr<FakeAudioDevice::Renderer>
+ FakeAudioDevice::CreateBoundedWavFileWriter(
+ std::string filename, int sampling_frequency_in_hz) {
+ return std::unique_ptr<FakeAudioDevice::Renderer>(
+ new BoundedWavFileWriter(filename, sampling_frequency_in_hz));
+}
+
+std::unique_ptr<FakeAudioDevice::Renderer>
+ FakeAudioDevice::CreateDiscardRenderer(int sampling_frequency_in_hz) {
+ return std::unique_ptr<FakeAudioDevice::Renderer>(
+ new DiscardRenderer(sampling_frequency_in_hz));
+}
+
+
+FakeAudioDevice::FakeAudioDevice(std::unique_ptr<Capturer> capturer,
+ std::unique_ptr<Renderer> renderer,
+ float speed)
+ : capturer_(std::move(capturer)),
+ renderer_(std::move(renderer)),
+ speed_(speed),
+ audio_callback_(nullptr),
+ rendering_(false),
+ capturing_(false),
+ done_rendering_(true, true),
+ done_capturing_(true, true),
+ tick_(EventTimerWrapper::Create()),
+ thread_(FakeAudioDevice::Run, this, "FakeAudioDevice") {
+ auto good_sample_rate = [](int sr) {
+ return sr == 8000 || sr == 16000 || sr == 32000
+ || sr == 44100 || sr == 48000;
+ };
+
+ if (renderer_) {
+ const int sample_rate = renderer_->SamplingFrequency();
+ playout_buffer_.resize(SamplesPerFrame(sample_rate), 0);
+ RTC_CHECK(good_sample_rate(sample_rate));
+ }
+ if (capturer_) {
+ RTC_CHECK(good_sample_rate(capturer_->SamplingFrequency()));
+ }
+}
+
+FakeAudioDevice::~FakeAudioDevice() {
+ StopPlayout();
+ StopRecording();
+ thread_.Stop();
+}
+
+int32_t FakeAudioDevice::StartPlayout() {
+ rtc::CritScope cs(&lock_);
+ RTC_CHECK(renderer_);
+ rendering_ = true;
+ done_rendering_.Reset();
+ return 0;
+}
+
+int32_t FakeAudioDevice::StopPlayout() {
+ rtc::CritScope cs(&lock_);
+ rendering_ = false;
+ done_rendering_.Set();
+ return 0;
+}
+
+int32_t FakeAudioDevice::StartRecording() {
+ rtc::CritScope cs(&lock_);
+ RTC_CHECK(capturer_);
+ capturing_ = true;
+ done_capturing_.Reset();
+ return 0;
+}
+
+int32_t FakeAudioDevice::StopRecording() {
+ rtc::CritScope cs(&lock_);
+ capturing_ = false;
+ done_capturing_.Set();
+ return 0;
+}
+
+int32_t FakeAudioDevice::Init() {
+ RTC_CHECK(tick_->StartTimer(true, kFrameLengthMs / speed_));
+ thread_.Start();
+ thread_.SetPriority(rtc::kHighPriority);
+ return 0;
+}
+
+int32_t FakeAudioDevice::RegisterAudioCallback(AudioTransport* callback) {
+ rtc::CritScope cs(&lock_);
+ RTC_DCHECK(callback || audio_callback_);
+ audio_callback_ = callback;
+ return 0;
+}
+
+bool FakeAudioDevice::Playing() const {
+ rtc::CritScope cs(&lock_);
+ return rendering_;
+}
+
+bool FakeAudioDevice::Recording() const {
+ rtc::CritScope cs(&lock_);
+ return capturing_;
+}
+
+bool FakeAudioDevice::WaitForPlayoutEnd(int timeout_ms) {
+ return done_rendering_.Wait(timeout_ms);
+}
+
+bool FakeAudioDevice::WaitForRecordingEnd(int timeout_ms) {
+ return done_capturing_.Wait(timeout_ms);
+}
+
+bool FakeAudioDevice::Run(void* obj) {
+ static_cast<FakeAudioDevice*>(obj)->ProcessAudio();
+ return true;
+}
+
+void FakeAudioDevice::ProcessAudio() {
+ {
+ rtc::CritScope cs(&lock_);
+ if (capturing_) {
+ // Capture 10ms of audio. 2 bytes per sample.
+ const bool keep_capturing = capturer_->Capture(&recording_buffer_);
+ uint32_t new_mic_level;
+ if (recording_buffer_.size() > 0) {
+ audio_callback_->RecordedDataIsAvailable(
+ recording_buffer_.data(), recording_buffer_.size(), 2, 1,
+ capturer_->SamplingFrequency(), 0, 0, 0, false, new_mic_level);
+ }
+ if (!keep_capturing) {
+ capturing_ = false;
+ done_capturing_.Set();
+ }
+ }
+ if (rendering_) {
+ size_t samples_out;
+ int64_t elapsed_time_ms;
+ int64_t ntp_time_ms;
+ const int sampling_frequency = renderer_->SamplingFrequency();
+ audio_callback_->NeedMorePlayData(
+ SamplesPerFrame(sampling_frequency), 2, 1, sampling_frequency,
+ playout_buffer_.data(), samples_out, &elapsed_time_ms, &ntp_time_ms);
+ const bool keep_rendering = renderer_->Render(
+ rtc::ArrayView<const int16_t>(playout_buffer_.data(), samples_out));
+ if (!keep_rendering) {
+ rendering_ = false;
+ done_rendering_.Set();
+ }
+ }
+ }
+ tick_->Wait(WEBRTC_EVENT_INFINITE);
+}
+
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fake_audio_device.h b/third_party/libwebrtc/webrtc/test/fake_audio_device.h
new file mode 100644
index 0000000000..f71fd016d9
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fake_audio_device.h
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef TEST_FAKE_AUDIO_DEVICE_H_
+#define TEST_FAKE_AUDIO_DEVICE_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "api/array_view.h"
+#include "modules/audio_device/include/fake_audio_device.h"
+#include "rtc_base/buffer.h"
+#include "rtc_base/criticalsection.h"
+#include "rtc_base/event.h"
+#include "rtc_base/platform_thread.h"
+#include "typedefs.h" // NOLINT(build/include)
+
+namespace webrtc {
+
+class EventTimerWrapper;
+
+namespace test {
+
+// FakeAudioDevice implements an AudioDevice module that can act both as a
+// capturer and a renderer. It will use 10ms audio frames.
+class FakeAudioDevice : public FakeAudioDeviceModule {
+ public:
+ // Returns the number of samples that Capturers and Renderers with this
+ // sampling frequency will work with every time Capture or Render is called.
+ static size_t SamplesPerFrame(int sampling_frequency_in_hz);
+
+ class Capturer {
+ public:
+ virtual ~Capturer() {}
+ // Returns the sampling frequency in Hz of the audio data that this
+ // capturer produces.
+ virtual int SamplingFrequency() const = 0;
+ // Replaces the contents of |buffer| with 10ms of captured audio data
+ // (see FakeAudioDevice::SamplesPerFrame). Returns true if the capturer can
+ // keep producing data, or false when the capture finishes.
+ virtual bool Capture(rtc::BufferT<int16_t>* buffer) = 0;
+ };
+
+ class Renderer {
+ public:
+ virtual ~Renderer() {}
+ // Returns the sampling frequency in Hz of the audio data that this
+ // renderer receives.
+ virtual int SamplingFrequency() const = 0;
+ // Renders the passed audio data and returns true if the renderer wants
+ // to keep receiving data, or false otherwise.
+ virtual bool Render(rtc::ArrayView<const int16_t> data) = 0;
+ };
+
+ // Creates a new FakeAudioDevice. When capturing or playing, 10 ms audio
+ // frames will be processed every 10ms / |speed|.
+ // |capturer| is an object that produces audio data. Can be nullptr if this
+ // device is never used for recording.
+ // |renderer| is an object that receives audio data that would have been
+ // played out. Can be nullptr if this device is never used for playing.
+ // Use one of the Create... functions to get these instances.
+ FakeAudioDevice(std::unique_ptr<Capturer> capturer,
+ std::unique_ptr<Renderer> renderer,
+ float speed = 1);
+ ~FakeAudioDevice() override;
+
+ // Returns a Capturer instance that generates a signal where every second
+ // frame is zero and every second frame is evenly distributed random noise
+ // with max amplitude |max_amplitude|.
+ static std::unique_ptr<Capturer> CreatePulsedNoiseCapturer(
+ int16_t max_amplitude, int sampling_frequency_in_hz);
+
+ // Returns a Capturer instance that gets its data from a file.
+ static std::unique_ptr<Capturer> CreateWavFileReader(
+ std::string filename, int sampling_frequency_in_hz);
+
+ // Returns a Capturer instance that gets its data from a file.
+ // Automatically detects sample rate.
+ static std::unique_ptr<Capturer> CreateWavFileReader(std::string filename);
+
+ // Returns a Renderer instance that writes its data to a file.
+ static std::unique_ptr<Renderer> CreateWavFileWriter(
+ std::string filename, int sampling_frequency_in_hz);
+
+ // Returns a Renderer instance that writes its data to a WAV file, cutting
+ // off silence at the beginning (not necessarily perfect silence, see
+ // kAmplitudeThreshold) and at the end (only actual 0 samples in this case).
+ static std::unique_ptr<Renderer> CreateBoundedWavFileWriter(
+ std::string filename, int sampling_frequency_in_hz);
+
+ // Returns a Renderer instance that does nothing with the audio data.
+ static std::unique_ptr<Renderer> CreateDiscardRenderer(
+ int sampling_frequency_in_hz);
+
+ int32_t Init() override;
+ int32_t RegisterAudioCallback(AudioTransport* callback) override;
+
+ int32_t StartPlayout() override;
+ int32_t StopPlayout() override;
+ int32_t StartRecording() override;
+ int32_t StopRecording() override;
+
+ bool Playing() const override;
+ bool Recording() const override;
+
+ // Blocks until the Renderer refuses to receive data.
+ // Returns false if |timeout_ms| passes before that happens.
+ bool WaitForPlayoutEnd(int timeout_ms = rtc::Event::kForever);
+ // Blocks until the Recorder stops producing data.
+ // Returns false if |timeout_ms| passes before that happens.
+ bool WaitForRecordingEnd(int timeout_ms = rtc::Event::kForever);
+
+ private:
+ static bool Run(void* obj);
+ void ProcessAudio();
+
+ const std::unique_ptr<Capturer> capturer_ RTC_GUARDED_BY(lock_);
+ const std::unique_ptr<Renderer> renderer_ RTC_GUARDED_BY(lock_);
+ const float speed_;
+
+ rtc::CriticalSection lock_;
+ AudioTransport* audio_callback_ RTC_GUARDED_BY(lock_);
+ bool rendering_ RTC_GUARDED_BY(lock_);
+ bool capturing_ RTC_GUARDED_BY(lock_);
+ rtc::Event done_rendering_;
+ rtc::Event done_capturing_;
+
+ std::vector<int16_t> playout_buffer_ RTC_GUARDED_BY(lock_);
+ rtc::BufferT<int16_t> recording_buffer_ RTC_GUARDED_BY(lock_);
+
+ std::unique_ptr<EventTimerWrapper> tick_;
+ rtc::PlatformThread thread_;
+};
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_FAKE_AUDIO_DEVICE_H_
diff --git a/third_party/libwebrtc/webrtc/test/fake_audio_device_unittest.cc b/third_party/libwebrtc/webrtc/test/fake_audio_device_unittest.cc
new file mode 100644
index 0000000000..02ece3cd85
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fake_audio_device_unittest.cc
@@ -0,0 +1,131 @@
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <algorithm>
+#include <array>
+
+#include "common_audio/wav_file.h"
+#include "common_audio/wav_header.h"
+#include "test/fake_audio_device.h"
+#include "test/gtest.h"
+#include "test/testsupport/fileutils.h"
+
+namespace webrtc {
+namespace test {
+
+namespace {
+void RunTest(const std::vector<int16_t>& input_samples,
+ const std::vector<int16_t>& expected_samples,
+ size_t samples_per_frame) {
+ const ::testing::TestInfo* const test_info =
+ ::testing::UnitTest::GetInstance()->current_test_info();
+
+ const std::string output_filename = test::OutputPath() +
+ "BoundedWavFileWriterTest_" + test_info->name() + ".wav";
+
+ static const size_t kSamplesPerFrame = 8;
+ static const int kSampleRate = kSamplesPerFrame * 100;
+ EXPECT_EQ(FakeAudioDevice::SamplesPerFrame(kSampleRate), kSamplesPerFrame);
+
+ {
+ std::unique_ptr<FakeAudioDevice::Renderer> writer =
+ FakeAudioDevice::CreateBoundedWavFileWriter(output_filename, 800);
+
+ for (size_t i = 0; i < input_samples.size(); i += kSamplesPerFrame) {
+ EXPECT_TRUE(writer->Render(rtc::ArrayView<const int16_t>(
+ &input_samples[i],
+ std::min(kSamplesPerFrame, input_samples.size() - i))));
+ }
+ }
+
+ {
+ WavReader reader(output_filename);
+ std::vector<int16_t> read_samples(expected_samples.size());
+ EXPECT_EQ(expected_samples.size(),
+ reader.ReadSamples(read_samples.size(), read_samples.data()));
+ EXPECT_EQ(expected_samples, read_samples);
+
+ EXPECT_EQ(0u, reader.ReadSamples(read_samples.size(), read_samples.data()));
+ }
+
+ remove(output_filename.c_str());
+}
+} // namespace
+
+TEST(BoundedWavFileWriterTest, NoSilence) {
+ static const std::vector<int16_t> kInputSamples = {
+ 75, 1234, 243, -1231, -22222, 0, 3, 88,
+ 1222, -1213, -13222, -7, -3525, 5787, -25247, 8
+ };
+ static const std::vector<int16_t> kExpectedSamples = kInputSamples;
+ RunTest(kInputSamples, kExpectedSamples, 8);
+}
+
+TEST(BoundedWavFileWriterTest, SomeStartSilence) {
+ static const std::vector<int16_t> kInputSamples = {
+ 0, 0, 0, 0, 3, 0, 0, 0,
+ 0, 3, -13222, -7, -3525, 5787, -25247, 8
+ };
+ static const std::vector<int16_t> kExpectedSamples(kInputSamples.begin() + 10,
+ kInputSamples.end());
+ RunTest(kInputSamples, kExpectedSamples, 8);
+}
+
+TEST(BoundedWavFileWriterTest, NegativeStartSilence) {
+ static const std::vector<int16_t> kInputSamples = {
+ 0, -4, -6, 0, 3, 0, 0, 0,
+ 0, 3, -13222, -7, -3525, 5787, -25247, 8
+ };
+ static const std::vector<int16_t> kExpectedSamples(kInputSamples.begin() + 2,
+ kInputSamples.end());
+ RunTest(kInputSamples, kExpectedSamples, 8);
+}
+
+TEST(BoundedWavFileWriterTest, SomeEndSilence) {
+ static const std::vector<int16_t> kInputSamples = {
+ 75, 1234, 243, -1231, -22222, 0, 1, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ static const std::vector<int16_t> kExpectedSamples(kInputSamples.begin(),
+ kInputSamples.end() - 9);
+ RunTest(kInputSamples, kExpectedSamples, 8);
+}
+
+TEST(BoundedWavFileWriterTest, DoubleEndSilence) {
+ static const std::vector<int16_t> kInputSamples = {
+ 75, 1234, 243, -1231, -22222, 0, 0, 0,
+ 0, -1213, -13222, -7, -3525, 5787, 0, 0
+ };
+ static const std::vector<int16_t> kExpectedSamples(kInputSamples.begin(),
+ kInputSamples.end() - 2);
+ RunTest(kInputSamples, kExpectedSamples, 8);
+}
+
+TEST(BoundedWavFileWriterTest, DoubleSilence) {
+ static const std::vector<int16_t> kInputSamples = {
+ 0, -1213, -13222, -7, -3525, 5787, 0, 0
+ };
+ static const std::vector<int16_t> kExpectedSamples(kInputSamples.begin() + 1,
+ kInputSamples.end() - 2);
+ RunTest(kInputSamples, kExpectedSamples, 8);
+}
+
+TEST(BoundedWavFileWriterTest, EndSilenceCutoff) {
+ static const std::vector<int16_t> kInputSamples = {
+ 75, 1234, 243, -1231, -22222, 0, 1, 0,
+ 0, 0, 0
+ };
+ static const std::vector<int16_t> kExpectedSamples(kInputSamples.begin(),
+ kInputSamples.end() - 4);
+ RunTest(kInputSamples, kExpectedSamples, 8);
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fake_decoder.cc b/third_party/libwebrtc/webrtc/test/fake_decoder.cc
new file mode 100644
index 0000000000..fe8aef7167
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fake_decoder.cc
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/fake_decoder.h"
+
+#include "api/video/i420_buffer.h"
+#include "rtc_base/timeutils.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+namespace test {
+
+FakeDecoder::FakeDecoder() : callback_(NULL) {}
+
+int32_t FakeDecoder::InitDecode(const VideoCodec* config,
+ int32_t number_of_cores) {
+ config_ = *config;
+ return WEBRTC_VIDEO_CODEC_OK;
+}
+
+int32_t FakeDecoder::Decode(const EncodedImage& input,
+ bool missing_frames,
+ const RTPFragmentationHeader* fragmentation,
+ const CodecSpecificInfo* codec_specific_info,
+ int64_t render_time_ms) {
+ VideoFrame frame(I420Buffer::Create(config_.width, config_.height),
+ webrtc::kVideoRotation_0,
+ render_time_ms * rtc::kNumMicrosecsPerMillisec);
+ frame.set_timestamp(input._timeStamp);
+ frame.set_ntp_time_ms(input.ntp_time_ms_);
+
+ callback_->Decoded(frame);
+
+ return WEBRTC_VIDEO_CODEC_OK;
+}
+
+int32_t FakeDecoder::RegisterDecodeCompleteCallback(
+ DecodedImageCallback* callback) {
+ callback_ = callback;
+ return WEBRTC_VIDEO_CODEC_OK;
+}
+
+int32_t FakeDecoder::Release() {
+ return WEBRTC_VIDEO_CODEC_OK;
+}
+
+const char* FakeDecoder::kImplementationName = "fake_decoder";
+const char* FakeDecoder::ImplementationName() const {
+ return kImplementationName;
+}
+
+int32_t FakeH264Decoder::Decode(const EncodedImage& input,
+ bool missing_frames,
+ const RTPFragmentationHeader* fragmentation,
+ const CodecSpecificInfo* codec_specific_info,
+ int64_t render_time_ms) {
+ uint8_t value = 0;
+ for (size_t i = 0; i < input._length; ++i) {
+ uint8_t kStartCode[] = {0, 0, 0, 1};
+ if (i < input._length - sizeof(kStartCode) &&
+ !memcmp(&input._buffer[i], kStartCode, sizeof(kStartCode))) {
+ i += sizeof(kStartCode) + 1; // Skip start code and NAL header.
+ }
+ if (input._buffer[i] != value) {
+ EXPECT_EQ(value, input._buffer[i])
+ << "Bitstream mismatch between sender and receiver.";
+ return -1;
+ }
+ ++value;
+ }
+ return FakeDecoder::Decode(input,
+ missing_frames,
+ fragmentation,
+ codec_specific_info,
+ render_time_ms);
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fake_decoder.h b/third_party/libwebrtc/webrtc/test/fake_decoder.h
new file mode 100644
index 0000000000..61dacf065f
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fake_decoder.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef TEST_FAKE_DECODER_H_
+#define TEST_FAKE_DECODER_H_
+
+#include <vector>
+
+#include "modules/video_coding/include/video_codec_interface.h"
+#include "system_wrappers/include/clock.h"
+
+namespace webrtc {
+namespace test {
+
+class FakeDecoder : public VideoDecoder {
+ public:
+ FakeDecoder();
+ virtual ~FakeDecoder() {}
+
+ int32_t InitDecode(const VideoCodec* config,
+ int32_t number_of_cores) override;
+
+ int32_t Decode(const EncodedImage& input,
+ bool missing_frames,
+ const RTPFragmentationHeader* fragmentation,
+ const CodecSpecificInfo* codec_specific_info,
+ int64_t render_time_ms) override;
+
+ int32_t RegisterDecodeCompleteCallback(
+ DecodedImageCallback* callback) override;
+
+ int32_t Release() override;
+
+ const char* ImplementationName() const override;
+
+ static const char* kImplementationName;
+
+ private:
+ VideoCodec config_;
+ DecodedImageCallback* callback_;
+};
+
+class FakeH264Decoder : public FakeDecoder {
+ public:
+ virtual ~FakeH264Decoder() {}
+
+ int32_t Decode(const EncodedImage& input,
+ bool missing_frames,
+ const RTPFragmentationHeader* fragmentation,
+ const CodecSpecificInfo* codec_specific_info,
+ int64_t render_time_ms) override;
+};
+
+class FakeNullDecoder : public FakeDecoder {
+ public:
+ virtual ~FakeNullDecoder() {}
+
+ int32_t Decode(const EncodedImage& input,
+ bool missing_frames,
+ const RTPFragmentationHeader* fragmentation,
+ const CodecSpecificInfo* codec_specific_info,
+ int64_t render_time_ms) override {
+ return 0;
+ }
+};
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_FAKE_DECODER_H_
diff --git a/third_party/libwebrtc/webrtc/test/fake_encoder.cc b/third_party/libwebrtc/webrtc/test/fake_encoder.cc
new file mode 100644
index 0000000000..a7dbbd9048
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fake_encoder.cc
@@ -0,0 +1,377 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/fake_encoder.h"
+
+#include <string.h>
+
+#include <algorithm>
+#include <memory>
+
+#include "common_types.h" // NOLINT(build/include)
+#include "modules/video_coding/include/video_codec_interface.h"
+#include "rtc_base/checks.h"
+#include "system_wrappers/include/sleep.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+namespace test {
+
+const int kKeyframeSizeFactor = 10;
+
+FakeEncoder::FakeEncoder(Clock* clock)
+ : clock_(clock),
+ callback_(nullptr),
+ configured_input_framerate_(-1),
+ max_target_bitrate_kbps_(-1),
+ pending_keyframe_(true),
+ debt_bytes_(0) {
+ // Generate some arbitrary not-all-zero data
+ for (size_t i = 0; i < sizeof(encoded_buffer_); ++i) {
+ encoded_buffer_[i] = static_cast<uint8_t>(i);
+ }
+}
+
+void FakeEncoder::SetMaxBitrate(int max_kbps) {
+ RTC_DCHECK_GE(max_kbps, -1); // max_kbps == -1 disables it.
+ rtc::CritScope cs(&crit_sect_);
+ max_target_bitrate_kbps_ = max_kbps;
+}
+
+int32_t FakeEncoder::InitEncode(const VideoCodec* config,
+ int32_t number_of_cores,
+ size_t max_payload_size) {
+ rtc::CritScope cs(&crit_sect_);
+ config_ = *config;
+ target_bitrate_.SetBitrate(0, 0, config_.startBitrate * 1000);
+ configured_input_framerate_ = config_.maxFramerate;
+ pending_keyframe_ = true;
+ return 0;
+}
+
+int32_t FakeEncoder::Encode(const VideoFrame& input_image,
+ const CodecSpecificInfo* codec_specific_info,
+ const std::vector<FrameType>* frame_types) {
+ unsigned char max_framerate;
+ unsigned char num_simulcast_streams;
+ SimulcastStream simulcast_streams[kMaxSimulcastStreams];
+ EncodedImageCallback* callback;
+ uint32_t target_bitrate_sum_kbps;
+ int max_target_bitrate_kbps;
+ size_t num_encoded_bytes;
+ int framerate;
+ VideoCodecMode mode;
+ bool keyframe;
+ {
+ rtc::CritScope cs(&crit_sect_);
+ max_framerate = config_.maxFramerate;
+ num_simulcast_streams = config_.numberOfSimulcastStreams;
+ for (int i = 0; i < num_simulcast_streams; ++i) {
+ simulcast_streams[i] = config_.simulcastStream[i];
+ }
+ callback = callback_;
+ target_bitrate_sum_kbps = target_bitrate_.get_sum_kbps();
+ max_target_bitrate_kbps = max_target_bitrate_kbps_;
+ num_encoded_bytes = sizeof(encoded_buffer_);
+ mode = config_.mode;
+ if (configured_input_framerate_ > 0) {
+ framerate = configured_input_framerate_;
+ } else {
+ framerate = max_framerate;
+ }
+ keyframe = pending_keyframe_;
+ pending_keyframe_ = false;
+ }
+
+ for (FrameType frame_type : *frame_types) {
+ if (frame_type == kVideoFrameKey) {
+ keyframe = true;
+ break;
+ }
+ }
+
+ RTC_DCHECK_GT(max_framerate, 0);
+
+ size_t bitrate =
+ std::max(target_bitrate_sum_kbps, simulcast_streams[0].minBitrate);
+ if (max_target_bitrate_kbps > 0)
+ bitrate = std::min(bitrate, static_cast<size_t>(max_target_bitrate_kbps));
+
+ size_t bits_available = bitrate * 1000 / framerate;
+
+ RTC_DCHECK_GT(num_simulcast_streams, 0);
+ for (unsigned char i = 0; i < num_simulcast_streams; ++i) {
+ CodecSpecificInfo specifics;
+ memset(&specifics, 0, sizeof(specifics));
+ specifics.codecType = kVideoCodecGeneric;
+ specifics.codecSpecific.generic.simulcast_idx = i;
+ size_t min_stream_bits = static_cast<size_t>(
+ (simulcast_streams[i].minBitrate * 1000) / framerate);
+ size_t max_stream_bits = static_cast<size_t>(
+ (simulcast_streams[i].maxBitrate * 1000) / framerate);
+ size_t stream_bits = (bits_available > max_stream_bits) ? max_stream_bits :
+ bits_available;
+ size_t stream_bytes = (stream_bits + 7) / 8;
+ if (keyframe) {
+ // The first frame is a key frame and should be larger.
+ // Store the overshoot bytes and distribute them over the coming frames,
+ // so that we on average meet the bitrate target.
+ debt_bytes_ += (kKeyframeSizeFactor - 1) * stream_bytes;
+ stream_bytes *= kKeyframeSizeFactor;
+ } else {
+ if (debt_bytes_ > 0) {
+ // Pay at most half of the frame size for old debts.
+ size_t payment_size = std::min(stream_bytes / 2, debt_bytes_);
+ debt_bytes_ -= payment_size;
+ stream_bytes -= payment_size;
+ }
+ }
+
+ if (stream_bytes > num_encoded_bytes)
+ stream_bytes = num_encoded_bytes;
+
+ // Always encode something on the first frame.
+ if (min_stream_bits > bits_available && i > 0)
+ continue;
+
+ std::unique_ptr<uint8_t[]> encoded_buffer(new uint8_t[num_encoded_bytes]);
+ memcpy(encoded_buffer.get(), encoded_buffer_, num_encoded_bytes);
+ EncodedImage encoded(encoded_buffer.get(), stream_bytes, num_encoded_bytes);
+ encoded._timeStamp = input_image.timestamp();
+ encoded.capture_time_ms_ = input_image.render_time_ms();
+ encoded._frameType = (*frame_types)[i];
+ encoded._encodedWidth = simulcast_streams[i].width;
+ encoded._encodedHeight = simulcast_streams[i].height;
+ encoded.rotation_ = input_image.rotation();
+ encoded.content_type_ = (mode == kScreensharing)
+ ? VideoContentType::SCREENSHARE
+ : VideoContentType::UNSPECIFIED;
+ specifics.codec_name = ImplementationName();
+ specifics.codecSpecific.generic.simulcast_idx = i;
+ RTC_DCHECK(callback);
+ if (callback->OnEncodedImage(encoded, &specifics, nullptr).error !=
+ EncodedImageCallback::Result::OK) {
+ return -1;
+ }
+ bits_available -= std::min(encoded._length * 8, bits_available);
+ }
+ return 0;
+}
+
+int32_t FakeEncoder::RegisterEncodeCompleteCallback(
+ EncodedImageCallback* callback) {
+ rtc::CritScope cs(&crit_sect_);
+ callback_ = callback;
+ return 0;
+}
+
+int32_t FakeEncoder::Release() { return 0; }
+
+int32_t FakeEncoder::SetChannelParameters(uint32_t packet_loss, int64_t rtt) {
+ return 0;
+}
+
+int32_t FakeEncoder::SetRateAllocation(const BitrateAllocation& rate_allocation,
+ uint32_t framerate) {
+ rtc::CritScope cs(&crit_sect_);
+ target_bitrate_ = rate_allocation;
+ configured_input_framerate_ = framerate;
+ return 0;
+}
+
+const char* FakeEncoder::kImplementationName = "fake_encoder";
+const char* FakeEncoder::ImplementationName() const {
+ return kImplementationName;
+}
+
+int FakeEncoder::GetConfiguredInputFramerate() const {
+ rtc::CritScope cs(&crit_sect_);
+ return configured_input_framerate_;
+}
+
+FakeH264Encoder::FakeH264Encoder(Clock* clock)
+ : FakeEncoder(clock), callback_(nullptr), idr_counter_(0) {
+ FakeEncoder::RegisterEncodeCompleteCallback(this);
+}
+
+int32_t FakeH264Encoder::RegisterEncodeCompleteCallback(
+ EncodedImageCallback* callback) {
+ rtc::CritScope cs(&local_crit_sect_);
+ callback_ = callback;
+ return 0;
+}
+
+EncodedImageCallback::Result FakeH264Encoder::OnEncodedImage(
+ const EncodedImage& encoded_image,
+ const CodecSpecificInfo* codec_specific_info,
+ const RTPFragmentationHeader* fragments) {
+ const size_t kSpsSize = 8;
+ const size_t kPpsSize = 11;
+ const int kIdrFrequency = 10;
+ EncodedImageCallback* callback;
+ int current_idr_counter;
+ {
+ rtc::CritScope cs(&local_crit_sect_);
+ callback = callback_;
+ current_idr_counter = idr_counter_;
+ ++idr_counter_;
+ }
+ RTPFragmentationHeader fragmentation;
+ if (current_idr_counter % kIdrFrequency == 0 &&
+ encoded_image._length > kSpsSize + kPpsSize + 1) {
+ const size_t kNumSlices = 3;
+ fragmentation.VerifyAndAllocateFragmentationHeader(kNumSlices);
+ fragmentation.fragmentationOffset[0] = 0;
+ fragmentation.fragmentationLength[0] = kSpsSize;
+ fragmentation.fragmentationOffset[1] = kSpsSize;
+ fragmentation.fragmentationLength[1] = kPpsSize;
+ fragmentation.fragmentationOffset[2] = kSpsSize + kPpsSize;
+ fragmentation.fragmentationLength[2] =
+ encoded_image._length - (kSpsSize + kPpsSize);
+ const size_t kSpsNalHeader = 0x67;
+ const size_t kPpsNalHeader = 0x68;
+ const size_t kIdrNalHeader = 0x65;
+ encoded_image._buffer[fragmentation.fragmentationOffset[0]] = kSpsNalHeader;
+ encoded_image._buffer[fragmentation.fragmentationOffset[1]] = kPpsNalHeader;
+ encoded_image._buffer[fragmentation.fragmentationOffset[2]] = kIdrNalHeader;
+ } else {
+ const size_t kNumSlices = 1;
+ fragmentation.VerifyAndAllocateFragmentationHeader(kNumSlices);
+ fragmentation.fragmentationOffset[0] = 0;
+ fragmentation.fragmentationLength[0] = encoded_image._length;
+ const size_t kNalHeader = 0x41;
+ encoded_image._buffer[fragmentation.fragmentationOffset[0]] = kNalHeader;
+ }
+ uint8_t value = 0;
+ int fragment_counter = 0;
+ for (size_t i = 0; i < encoded_image._length; ++i) {
+ if (fragment_counter == fragmentation.fragmentationVectorSize ||
+ i != fragmentation.fragmentationOffset[fragment_counter]) {
+ encoded_image._buffer[i] = value++;
+ } else {
+ ++fragment_counter;
+ }
+ }
+ CodecSpecificInfo specifics;
+ memset(&specifics, 0, sizeof(specifics));
+ specifics.codecType = kVideoCodecH264;
+ specifics.codecSpecific.H264.packetization_mode =
+ H264PacketizationMode::NonInterleaved;
+ RTC_DCHECK(callback);
+ return callback->OnEncodedImage(encoded_image, &specifics, &fragmentation);
+}
+
+DelayedEncoder::DelayedEncoder(Clock* clock, int delay_ms)
+ : test::FakeEncoder(clock), delay_ms_(delay_ms) {
+ // The encoder could be created on a different thread than
+ // it is being used on.
+ sequence_checker_.Detach();
+}
+
+void DelayedEncoder::SetDelay(int delay_ms) {
+ RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
+ delay_ms_ = delay_ms;
+}
+
+int32_t DelayedEncoder::Encode(const VideoFrame& input_image,
+ const CodecSpecificInfo* codec_specific_info,
+ const std::vector<FrameType>* frame_types) {
+ RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
+
+ SleepMs(delay_ms_);
+
+ return FakeEncoder::Encode(input_image, codec_specific_info, frame_types);
+}
+
+MultithreadedFakeH264Encoder::MultithreadedFakeH264Encoder(Clock* clock)
+ : test::FakeH264Encoder(clock),
+ current_queue_(0),
+ queue1_(nullptr),
+ queue2_(nullptr) {
+ // The encoder could be created on a different thread than
+ // it is being used on.
+ sequence_checker_.Detach();
+}
+
+int32_t MultithreadedFakeH264Encoder::InitEncode(const VideoCodec* config,
+ int32_t number_of_cores,
+ size_t max_payload_size) {
+ RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
+
+ queue1_.reset(new rtc::TaskQueue("Queue 1"));
+ queue2_.reset(new rtc::TaskQueue("Queue 2"));
+
+ return FakeH264Encoder::InitEncode(config, number_of_cores, max_payload_size);
+}
+
+class MultithreadedFakeH264Encoder::EncodeTask : public rtc::QueuedTask {
+ public:
+ EncodeTask(MultithreadedFakeH264Encoder* encoder,
+ const VideoFrame& input_image,
+ const CodecSpecificInfo* codec_specific_info,
+ const std::vector<FrameType>* frame_types)
+ : encoder_(encoder),
+ input_image_(input_image),
+ codec_specific_info_(),
+ frame_types_(*frame_types) {
+ if (codec_specific_info)
+ codec_specific_info_ = *codec_specific_info;
+ }
+
+ private:
+ bool Run() override {
+ encoder_->EncodeCallback(input_image_, &codec_specific_info_,
+ &frame_types_);
+ return true;
+ }
+
+ MultithreadedFakeH264Encoder* const encoder_;
+ VideoFrame input_image_;
+ CodecSpecificInfo codec_specific_info_;
+ std::vector<FrameType> frame_types_;
+};
+
+int32_t MultithreadedFakeH264Encoder::Encode(
+ const VideoFrame& input_image,
+ const CodecSpecificInfo* codec_specific_info,
+ const std::vector<FrameType>* frame_types) {
+ RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
+
+ std::unique_ptr<rtc::TaskQueue>& queue =
+ (current_queue_++ % 2 == 0) ? queue1_ : queue2_;
+
+ if (!queue) {
+ return WEBRTC_VIDEO_CODEC_UNINITIALIZED;
+ }
+
+ queue->PostTask(std::unique_ptr<rtc::QueuedTask>(
+ new EncodeTask(this, input_image, codec_specific_info, frame_types)));
+
+ return WEBRTC_VIDEO_CODEC_OK;
+}
+
+int32_t MultithreadedFakeH264Encoder::EncodeCallback(
+ const VideoFrame& input_image,
+ const CodecSpecificInfo* codec_specific_info,
+ const std::vector<FrameType>* frame_types) {
+ return FakeH264Encoder::Encode(input_image, codec_specific_info, frame_types);
+}
+
+int32_t MultithreadedFakeH264Encoder::Release() {
+ RTC_DCHECK_CALLED_SEQUENTIALLY(&sequence_checker_);
+
+ queue1_.reset();
+ queue2_.reset();
+
+ return FakeH264Encoder::Release();
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fake_encoder.h b/third_party/libwebrtc/webrtc/test/fake_encoder.h
new file mode 100644
index 0000000000..06c0e0392d
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fake_encoder.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef TEST_FAKE_ENCODER_H_
+#define TEST_FAKE_ENCODER_H_
+
+#include <vector>
+#include <memory>
+
+#include "api/video_codecs/video_encoder.h"
+#include "common_types.h" // NOLINT(build/include)
+#include "rtc_base/criticalsection.h"
+#include "rtc_base/sequenced_task_checker.h"
+#include "rtc_base/task_queue.h"
+#include "system_wrappers/include/clock.h"
+
+namespace webrtc {
+namespace test {
+
+class FakeEncoder : public VideoEncoder {
+ public:
+ explicit FakeEncoder(Clock* clock);
+ virtual ~FakeEncoder() = default;
+
+ // Sets max bitrate. Not thread-safe, call before registering the encoder.
+ void SetMaxBitrate(int max_kbps);
+
+ int32_t InitEncode(const VideoCodec* config,
+ int32_t number_of_cores,
+ size_t max_payload_size) override;
+ int32_t Encode(const VideoFrame& input_image,
+ const CodecSpecificInfo* codec_specific_info,
+ const std::vector<FrameType>* frame_types) override;
+ int32_t RegisterEncodeCompleteCallback(
+ EncodedImageCallback* callback) override;
+ int32_t Release() override;
+ int32_t SetChannelParameters(uint32_t packet_loss, int64_t rtt) override;
+ int32_t SetRateAllocation(const BitrateAllocation& rate_allocation,
+ uint32_t framerate) override;
+ const char* ImplementationName() const override;
+ int GetConfiguredInputFramerate() const;
+
+ static const char* kImplementationName;
+
+ protected:
+ Clock* const clock_;
+ VideoCodec config_ RTC_GUARDED_BY(crit_sect_);
+ EncodedImageCallback* callback_ RTC_GUARDED_BY(crit_sect_);
+ BitrateAllocation target_bitrate_ RTC_GUARDED_BY(crit_sect_);
+ int configured_input_framerate_ RTC_GUARDED_BY(crit_sect_);
+ int max_target_bitrate_kbps_ RTC_GUARDED_BY(crit_sect_);
+ bool pending_keyframe_ RTC_GUARDED_BY(crit_sect_);
+ rtc::CriticalSection crit_sect_;
+
+ uint8_t encoded_buffer_[100000];
+
+ // Current byte debt to be payed over a number of frames.
+ // The debt is acquired by keyframes overshooting the bitrate target.
+ size_t debt_bytes_;
+};
+
+class FakeH264Encoder : public FakeEncoder, public EncodedImageCallback {
+ public:
+ explicit FakeH264Encoder(Clock* clock);
+ virtual ~FakeH264Encoder() = default;
+
+ int32_t RegisterEncodeCompleteCallback(
+ EncodedImageCallback* callback) override;
+
+ Result OnEncodedImage(const EncodedImage& encodedImage,
+ const CodecSpecificInfo* codecSpecificInfo,
+ const RTPFragmentationHeader* fragments) override;
+
+ private:
+ EncodedImageCallback* callback_ RTC_GUARDED_BY(local_crit_sect_);
+ int idr_counter_ RTC_GUARDED_BY(local_crit_sect_);
+ rtc::CriticalSection local_crit_sect_;
+};
+
+class DelayedEncoder : public test::FakeEncoder {
+ public:
+ DelayedEncoder(Clock* clock, int delay_ms);
+ virtual ~DelayedEncoder() = default;
+
+ void SetDelay(int delay_ms);
+ int32_t Encode(const VideoFrame& input_image,
+ const CodecSpecificInfo* codec_specific_info,
+ const std::vector<FrameType>* frame_types) override;
+
+ private:
+ int delay_ms_ RTC_ACCESS_ON(sequence_checker_);
+ rtc::SequencedTaskChecker sequence_checker_;
+};
+
+// This class implements a multi-threaded fake encoder by posting
+// FakeH264Encoder::Encode(.) tasks to |queue1_| and |queue2_|, in an
+// alternating fashion. The class itself does not need to be thread safe,
+// as it is called from the task queue in VideoStreamEncoder.
+class MultithreadedFakeH264Encoder : public test::FakeH264Encoder {
+ public:
+ explicit MultithreadedFakeH264Encoder(Clock* clock);
+ virtual ~MultithreadedFakeH264Encoder() = default;
+
+ int32_t InitEncode(const VideoCodec* config,
+ int32_t number_of_cores,
+ size_t max_payload_size) override;
+
+ int32_t Encode(const VideoFrame& input_image,
+ const CodecSpecificInfo* codec_specific_info,
+ const std::vector<FrameType>* frame_types) override;
+
+ int32_t EncodeCallback(const VideoFrame& input_image,
+ const CodecSpecificInfo* codec_specific_info,
+ const std::vector<FrameType>* frame_types);
+
+ int32_t Release() override;
+
+ protected:
+ class EncodeTask;
+
+ int current_queue_ RTC_ACCESS_ON(sequence_checker_);
+ std::unique_ptr<rtc::TaskQueue> queue1_ RTC_ACCESS_ON(sequence_checker_);
+ std::unique_ptr<rtc::TaskQueue> queue2_ RTC_ACCESS_ON(sequence_checker_);
+ rtc::SequencedTaskChecker sequence_checker_;
+};
+
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_FAKE_ENCODER_H_
diff --git a/third_party/libwebrtc/webrtc/test/fake_network_pipe.cc b/third_party/libwebrtc/webrtc/test/fake_network_pipe.cc
new file mode 100644
index 0000000000..6678f1c374
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fake_network_pipe.cc
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/fake_network_pipe.h"
+
+#include <assert.h>
+#include <math.h>
+#include <string.h>
+
+#include <algorithm>
+#include <cmath>
+
+#include "call/call.h"
+#include "modules/rtp_rtcp/include/rtp_header_parser.h"
+#include "rtc_base/logging.h"
+#include "system_wrappers/include/clock.h"
+
+namespace webrtc {
+
+namespace {
+constexpr int64_t kDefaultProcessIntervalMs = 5;
+}
+
+DemuxerImpl::DemuxerImpl(const std::map<uint8_t, MediaType>& payload_type_map)
+ : packet_receiver_(nullptr), payload_type_map_(payload_type_map) {}
+
+void DemuxerImpl::SetReceiver(PacketReceiver* receiver) {
+ packet_receiver_ = receiver;
+}
+
+void DemuxerImpl::DeliverPacket(const NetworkPacket* packet,
+ const PacketTime& packet_time) {
+ // No packet receiver means that this demuxer will terminate the flow of
+ // packets.
+ if (!packet_receiver_)
+ return;
+ const uint8_t* const packet_data = packet->data();
+ const size_t packet_length = packet->data_length();
+ MediaType media_type = MediaType::ANY;
+ if (!RtpHeaderParser::IsRtcp(packet_data, packet_length)) {
+ RTC_CHECK_GE(packet_length, 2);
+ const uint8_t payload_type = packet_data[1] & 0x7f;
+ std::map<uint8_t, MediaType>::const_iterator it =
+ payload_type_map_.find(payload_type);
+ RTC_CHECK(it != payload_type_map_.end())
+ << "payload type " << static_cast<int>(payload_type) << " unknown.";
+ media_type = it->second;
+ }
+ packet_receiver_->DeliverPacket(media_type, packet_data, packet_length,
+ packet_time);
+}
+
+FakeNetworkPipe::FakeNetworkPipe(Clock* clock,
+ const FakeNetworkPipe::Config& config,
+ std::unique_ptr<Demuxer> demuxer)
+ : FakeNetworkPipe(clock, config, std::move(demuxer), 1) {}
+
+FakeNetworkPipe::FakeNetworkPipe(Clock* clock,
+ const FakeNetworkPipe::Config& config,
+ std::unique_ptr<Demuxer> demuxer,
+ uint64_t seed)
+ : clock_(clock),
+ demuxer_(std::move(demuxer)),
+ random_(seed),
+ config_(),
+ dropped_packets_(0),
+ sent_packets_(0),
+ total_packet_delay_(0),
+ bursting_(false),
+ next_process_time_(clock_->TimeInMilliseconds()),
+ last_log_time_(clock_->TimeInMilliseconds()) {
+ SetConfig(config);
+}
+
+FakeNetworkPipe::~FakeNetworkPipe() {
+ while (!capacity_link_.empty()) {
+ delete capacity_link_.front();
+ capacity_link_.pop();
+ }
+ while (!delay_link_.empty()) {
+ delete *delay_link_.begin();
+ delay_link_.erase(delay_link_.begin());
+ }
+}
+
+void FakeNetworkPipe::SetReceiver(PacketReceiver* receiver) {
+ RTC_CHECK(demuxer_);
+ demuxer_->SetReceiver(receiver);
+}
+
+void FakeNetworkPipe::SetConfig(const FakeNetworkPipe::Config& config) {
+ rtc::CritScope crit(&lock_);
+ config_ = config; // Shallow copy of the struct.
+ double prob_loss = config.loss_percent / 100.0;
+ if (config_.avg_burst_loss_length == -1) {
+ // Uniform loss
+ prob_loss_bursting_ = prob_loss;
+ prob_start_bursting_ = prob_loss;
+ } else {
+ // Lose packets according to a gilbert-elliot model.
+ int avg_burst_loss_length = config.avg_burst_loss_length;
+ int min_avg_burst_loss_length = std::ceil(prob_loss / (1 - prob_loss));
+
+ RTC_CHECK_GT(avg_burst_loss_length, min_avg_burst_loss_length)
+ << "For a total packet loss of " << config.loss_percent << "%% then"
+ << " avg_burst_loss_length must be " << min_avg_burst_loss_length + 1
+ << " or higher.";
+
+ prob_loss_bursting_ = (1.0 - 1.0 / avg_burst_loss_length);
+ prob_start_bursting_ = prob_loss / (1 - prob_loss) / avg_burst_loss_length;
+ }
+}
+
+void FakeNetworkPipe::SendPacket(const uint8_t* data, size_t data_length) {
+ RTC_CHECK(demuxer_);
+ rtc::CritScope crit(&lock_);
+ if (config_.queue_length_packets > 0 &&
+ capacity_link_.size() >= config_.queue_length_packets) {
+ // Too many packet on the link, drop this one.
+ ++dropped_packets_;
+ return;
+ }
+
+ int64_t time_now = clock_->TimeInMilliseconds();
+
+ // Delay introduced by the link capacity.
+ int64_t capacity_delay_ms = 0;
+ if (config_.link_capacity_kbps > 0) {
+ const int bytes_per_millisecond = config_.link_capacity_kbps / 8;
+ // To round to the closest millisecond we add half a milliseconds worth of
+ // bytes to the delay calculation.
+ capacity_delay_ms = (data_length + capacity_delay_error_bytes_ +
+ bytes_per_millisecond / 2) /
+ bytes_per_millisecond;
+ capacity_delay_error_bytes_ +=
+ data_length - capacity_delay_ms * bytes_per_millisecond;
+ }
+ int64_t network_start_time = time_now;
+
+ // Check if there already are packets on the link and change network start
+ // time forward if there is.
+ if (!capacity_link_.empty() &&
+ network_start_time < capacity_link_.back()->arrival_time())
+ network_start_time = capacity_link_.back()->arrival_time();
+
+ int64_t arrival_time = network_start_time + capacity_delay_ms;
+ NetworkPacket* packet = new NetworkPacket(data, data_length, time_now,
+ arrival_time);
+ capacity_link_.push(packet);
+}
+
+float FakeNetworkPipe::PercentageLoss() {
+ rtc::CritScope crit(&lock_);
+ if (sent_packets_ == 0)
+ return 0;
+
+ return static_cast<float>(dropped_packets_) /
+ (sent_packets_ + dropped_packets_);
+}
+
+int FakeNetworkPipe::AverageDelay() {
+ rtc::CritScope crit(&lock_);
+ if (sent_packets_ == 0)
+ return 0;
+
+ return static_cast<int>(total_packet_delay_ /
+ static_cast<int64_t>(sent_packets_));
+}
+
+void FakeNetworkPipe::Process() {
+ int64_t time_now = clock_->TimeInMilliseconds();
+ std::queue<NetworkPacket*> packets_to_deliver;
+ {
+ rtc::CritScope crit(&lock_);
+ if (time_now - last_log_time_ > 5000) {
+ int64_t queueing_delay_ms = 0;
+ if (!capacity_link_.empty()) {
+ queueing_delay_ms = time_now - capacity_link_.front()->send_time();
+ }
+ RTC_LOG(LS_INFO) << "Network queue: " << queueing_delay_ms << " ms.";
+ last_log_time_ = time_now;
+ }
+ // Check the capacity link first.
+ while (!capacity_link_.empty() &&
+ time_now >= capacity_link_.front()->arrival_time()) {
+ // Time to get this packet.
+ NetworkPacket* packet = capacity_link_.front();
+ capacity_link_.pop();
+
+ // Drop packets at an average rate of |config_.loss_percent| with
+ // and average loss burst length of |config_.avg_burst_loss_length|.
+ if ((bursting_ && random_.Rand<double>() < prob_loss_bursting_) ||
+ (!bursting_ && random_.Rand<double>() < prob_start_bursting_)) {
+ bursting_ = true;
+ delete packet;
+ continue;
+ } else {
+ bursting_ = false;
+ }
+
+ int arrival_time_jitter = random_.Gaussian(
+ config_.queue_delay_ms, config_.delay_standard_deviation_ms);
+
+ // If reordering is not allowed then adjust arrival_time_jitter
+ // to make sure all packets are sent in order.
+ if (!config_.allow_reordering && !delay_link_.empty() &&
+ packet->arrival_time() + arrival_time_jitter <
+ (*delay_link_.rbegin())->arrival_time()) {
+ arrival_time_jitter =
+ (*delay_link_.rbegin())->arrival_time() - packet->arrival_time();
+ }
+ packet->IncrementArrivalTime(arrival_time_jitter);
+ delay_link_.insert(packet);
+ }
+
+ // Check the extra delay queue.
+ while (!delay_link_.empty() &&
+ time_now >= (*delay_link_.begin())->arrival_time()) {
+ // Deliver this packet.
+ NetworkPacket* packet = *delay_link_.begin();
+ packets_to_deliver.push(packet);
+ delay_link_.erase(delay_link_.begin());
+ // |time_now| might be later than when the packet should have arrived, due
+ // to NetworkProcess being called too late. For stats, use the time it
+ // should have been on the link.
+ total_packet_delay_ += packet->arrival_time() - packet->send_time();
+ }
+ sent_packets_ += packets_to_deliver.size();
+ }
+ while (!packets_to_deliver.empty()) {
+ NetworkPacket* packet = packets_to_deliver.front();
+ packets_to_deliver.pop();
+ demuxer_->DeliverPacket(packet, PacketTime());
+ delete packet;
+ }
+
+ next_process_time_ = !delay_link_.empty()
+ ? (*delay_link_.begin())->arrival_time()
+ : time_now + kDefaultProcessIntervalMs;
+}
+
+int64_t FakeNetworkPipe::TimeUntilNextProcess() const {
+ rtc::CritScope crit(&lock_);
+ return std::max<int64_t>(next_process_time_ - clock_->TimeInMilliseconds(),
+ 0);
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fake_network_pipe.h b/third_party/libwebrtc/webrtc/test/fake_network_pipe.h
new file mode 100644
index 0000000000..1cfaa382f4
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fake_network_pipe.h
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef TEST_FAKE_NETWORK_PIPE_H_
+#define TEST_FAKE_NETWORK_PIPE_H_
+
+#include <string.h>
+#include <map>
+#include <memory>
+#include <queue>
+#include <set>
+
+#include "common_types.h" // NOLINT(build/include)
+#include "rtc_base/constructormagic.h"
+#include "rtc_base/criticalsection.h"
+#include "rtc_base/random.h"
+#include "typedefs.h" // NOLINT(build/include)
+
+namespace webrtc {
+
+class Clock;
+class PacketReceiver;
+enum class MediaType;
+
+class NetworkPacket {
+ public:
+ NetworkPacket(const uint8_t* data,
+ size_t length,
+ int64_t send_time,
+ int64_t arrival_time)
+ : data_(new uint8_t[length]),
+ data_length_(length),
+ send_time_(send_time),
+ arrival_time_(arrival_time) {
+ memcpy(data_.get(), data, length);
+ }
+
+ uint8_t* data() const { return data_.get(); }
+ size_t data_length() const { return data_length_; }
+ int64_t send_time() const { return send_time_; }
+ int64_t arrival_time() const { return arrival_time_; }
+ void IncrementArrivalTime(int64_t extra_delay) {
+ arrival_time_ += extra_delay;
+ }
+
+ private:
+ // The packet data.
+ std::unique_ptr<uint8_t[]> data_;
+ // Length of data_.
+ size_t data_length_;
+ // The time the packet was sent out on the network.
+ const int64_t send_time_;
+ // The time the packet should arrive at the receiver.
+ int64_t arrival_time_;
+};
+
+class Demuxer {
+ public:
+ virtual ~Demuxer() = default;
+ virtual void SetReceiver(PacketReceiver* receiver) = 0;
+ virtual void DeliverPacket(const NetworkPacket* packet,
+ const PacketTime& packet_time) = 0;
+};
+
+class DemuxerImpl final : public Demuxer {
+ public:
+ explicit DemuxerImpl(const std::map<uint8_t, MediaType>& payload_type_map);
+
+ void SetReceiver(PacketReceiver* receiver) override;
+ void DeliverPacket(const NetworkPacket* packet,
+ const PacketTime& packet_time) override;
+
+ private:
+ PacketReceiver* packet_receiver_;
+ const std::map<uint8_t, MediaType> payload_type_map_;
+ RTC_DISALLOW_COPY_AND_ASSIGN(DemuxerImpl);
+};
+
+// Class faking a network link. This is a simple and naive solution just faking
+// capacity and adding an extra transport delay in addition to the capacity
+// introduced delay.
+
+class FakeNetworkPipe {
+ public:
+ struct Config {
+ Config() {}
+ // Queue length in number of packets.
+ size_t queue_length_packets = 0;
+ // Delay in addition to capacity induced delay.
+ int queue_delay_ms = 0;
+ // Standard deviation of the extra delay.
+ int delay_standard_deviation_ms = 0;
+ // Link capacity in kbps.
+ int link_capacity_kbps = 0;
+ // Random packet loss.
+ int loss_percent = 0;
+ // If packets are allowed to be reordered.
+ bool allow_reordering = false;
+ // The average length of a burst of lost packets.
+ int avg_burst_loss_length = -1;
+ };
+
+ FakeNetworkPipe(Clock* clock,
+ const FakeNetworkPipe::Config& config,
+ std::unique_ptr<Demuxer> demuxer);
+ FakeNetworkPipe(Clock* clock,
+ const FakeNetworkPipe::Config& config,
+ std::unique_ptr<Demuxer> demuxer,
+ uint64_t seed);
+ virtual ~FakeNetworkPipe();
+
+ // Sets a new configuration. This won't affect packets already in the pipe.
+ void SetConfig(const FakeNetworkPipe::Config& config);
+
+ // Sends a new packet to the link.
+ virtual void SendPacket(const uint8_t* packet, size_t packet_length);
+
+ // Must not be called in parallel with SendPacket or Process.
+ void SetReceiver(PacketReceiver* receiver);
+
+ // Processes the network queues and trigger PacketReceiver::IncomingPacket for
+ // packets ready to be delivered.
+ virtual void Process();
+ int64_t TimeUntilNextProcess() const;
+
+ // Get statistics.
+ float PercentageLoss();
+ int AverageDelay();
+ size_t dropped_packets() { return dropped_packets_; }
+ size_t sent_packets() { return sent_packets_; }
+
+ protected:
+ Clock* const clock_;
+ rtc::CriticalSection lock_;
+ const std::unique_ptr<Demuxer> demuxer_;
+ std::queue<NetworkPacket*> capacity_link_;
+ Random random_;
+
+ // Since we need to access both the packet with the earliest and latest
+ // arrival time we need to use a multiset to keep all packets sorted,
+ // hence, we cannot use a priority queue.
+ struct PacketArrivalTimeComparator {
+ bool operator()(const NetworkPacket* p1, const NetworkPacket* p2) {
+ return p1->arrival_time() < p2->arrival_time();
+ }
+ };
+ std::multiset<NetworkPacket*, PacketArrivalTimeComparator> delay_link_;
+
+ // Link configuration.
+ Config config_;
+
+ // Statistics.
+ size_t dropped_packets_;
+ size_t sent_packets_;
+ int64_t total_packet_delay_;
+
+ // Are we currently dropping a burst of packets?
+ bool bursting_;
+
+ // The probability to drop the packet if we are currently dropping a
+ // burst of packet
+ double prob_loss_bursting_;
+
+ // The probability to drop a burst of packets.
+ double prob_start_bursting_;
+
+ int64_t next_process_time_;
+
+ int64_t last_log_time_;
+
+ int64_t capacity_delay_error_bytes_ = 0;
+
+ RTC_DISALLOW_COPY_AND_ASSIGN(FakeNetworkPipe);
+};
+
+} // namespace webrtc
+
+#endif // TEST_FAKE_NETWORK_PIPE_H_
diff --git a/third_party/libwebrtc/webrtc/test/fake_network_pipe_unittest.cc b/third_party/libwebrtc/webrtc/test/fake_network_pipe_unittest.cc
new file mode 100644
index 0000000000..759003b294
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fake_network_pipe_unittest.cc
@@ -0,0 +1,445 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <memory>
+
+#include "call/call.h"
+#include "modules/rtp_rtcp/include/rtp_header_parser.h"
+#include "system_wrappers/include/clock.h"
+#include "test/fake_network_pipe.h"
+#include "test/gmock.h"
+#include "test/gtest.h"
+
+using ::testing::_;
+using ::testing::AnyNumber;
+using ::testing::Return;
+using ::testing::Invoke;
+
+namespace webrtc {
+
+class TestDemuxer : public Demuxer {
+ public:
+ void IncomingPacket(NetworkPacket* packet) {
+ DeliverPacket(packet, PacketTime());
+ }
+
+ MOCK_METHOD1(SetReceiver, void(PacketReceiver* receiver));
+ MOCK_METHOD2(DeliverPacket,
+ void(const NetworkPacket* packet,
+ const PacketTime& packet_time));
+};
+
+class ReorderTestDemuxer : public TestDemuxer {
+ public:
+ void DeliverPacket(const NetworkPacket* packet,
+ const PacketTime& packet_time) override {
+ RTC_DCHECK_GE(packet->data_length(), sizeof(int));
+ int seq_num;
+ memcpy(&seq_num, packet->data(), sizeof(int));
+ delivered_sequence_numbers_.push_back(seq_num);
+ }
+ std::vector<int> delivered_sequence_numbers_;
+};
+
+class MockReceiver : public PacketReceiver {
+ public:
+ MOCK_METHOD4(
+ DeliverPacket,
+ DeliveryStatus(MediaType, const uint8_t*, size_t, const PacketTime&));
+};
+
+class FakeNetworkPipeTest : public ::testing::Test {
+ public:
+ FakeNetworkPipeTest() : fake_clock_(12345) {}
+
+ protected:
+ void SendPackets(FakeNetworkPipe* pipe, int number_packets, int packet_size) {
+ RTC_DCHECK_GE(packet_size, sizeof(int));
+ std::unique_ptr<uint8_t[]> packet(new uint8_t[packet_size]);
+ for (int i = 0; i < number_packets; ++i) {
+ // Set a sequence number for the packets by
+ // using the first bytes in the packet.
+ memcpy(packet.get(), &i, sizeof(int));
+ pipe->SendPacket(packet.get(), packet_size);
+ }
+ }
+
+ int PacketTimeMs(int capacity_kbps, int packet_size) const {
+ return 8 * packet_size / capacity_kbps;
+ }
+
+ SimulatedClock fake_clock_;
+};
+
+// Test the capacity link and verify we get as many packets as we expect.
+TEST_F(FakeNetworkPipeTest, CapacityTest) {
+ FakeNetworkPipe::Config config;
+ config.queue_length_packets = 20;
+ config.link_capacity_kbps = 80;
+ TestDemuxer* demuxer = new TestDemuxer();
+ std::unique_ptr<FakeNetworkPipe> pipe(new FakeNetworkPipe(
+ &fake_clock_, config, std::unique_ptr<Demuxer>(demuxer)));
+
+ // Add 10 packets of 1000 bytes, = 80 kb, and verify it takes one second to
+ // get through the pipe.
+ const int kNumPackets = 10;
+ const int kPacketSize = 1000;
+ SendPackets(pipe.get(), kNumPackets, kPacketSize);
+
+ // Time to get one packet through the link.
+ const int kPacketTimeMs = PacketTimeMs(config.link_capacity_kbps,
+ kPacketSize);
+
+ // Time haven't increased yet, so we souldn't get any packets.
+ EXPECT_CALL(*demuxer, DeliverPacket(_, _)).Times(0);
+ pipe->Process();
+
+ // Advance enough time to release one packet.
+ fake_clock_.AdvanceTimeMilliseconds(kPacketTimeMs);
+ EXPECT_CALL(*demuxer, DeliverPacket(_, _)).Times(1);
+ pipe->Process();
+
+ // Release all but one packet
+ fake_clock_.AdvanceTimeMilliseconds(9 * kPacketTimeMs - 1);
+ EXPECT_CALL(*demuxer, DeliverPacket(_, _)).Times(8);
+ pipe->Process();
+
+ // And the last one.
+ fake_clock_.AdvanceTimeMilliseconds(1);
+ EXPECT_CALL(*demuxer, DeliverPacket(_, _)).Times(1);
+ pipe->Process();
+}
+
+// Test the extra network delay.
+TEST_F(FakeNetworkPipeTest, ExtraDelayTest) {
+ FakeNetworkPipe::Config config;
+ config.queue_length_packets = 20;
+ config.queue_delay_ms = 100;
+ config.link_capacity_kbps = 80;
+ TestDemuxer* demuxer = new TestDemuxer();
+ std::unique_ptr<FakeNetworkPipe> pipe(new FakeNetworkPipe(
+ &fake_clock_, config, std::unique_ptr<Demuxer>(demuxer)));
+
+ const int kNumPackets = 2;
+ const int kPacketSize = 1000;
+ SendPackets(pipe.get(), kNumPackets, kPacketSize);
+
+ // Time to get one packet through the link.
+ const int kPacketTimeMs = PacketTimeMs(config.link_capacity_kbps,
+ kPacketSize);
+
+ // Increase more than kPacketTimeMs, but not more than the extra delay.
+ fake_clock_.AdvanceTimeMilliseconds(kPacketTimeMs);
+ EXPECT_CALL(*demuxer, DeliverPacket(_, _)).Times(0);
+ pipe->Process();
+
+ // Advance the network delay to get the first packet.
+ fake_clock_.AdvanceTimeMilliseconds(config.queue_delay_ms);
+ EXPECT_CALL(*demuxer, DeliverPacket(_, _)).Times(1);
+ pipe->Process();
+
+ // Advance one more kPacketTimeMs to get the last packet.
+ fake_clock_.AdvanceTimeMilliseconds(kPacketTimeMs);
+ EXPECT_CALL(*demuxer, DeliverPacket(_, _)).Times(1);
+ pipe->Process();
+}
+
+// Test the number of buffers and packets are dropped when sending too many
+// packets too quickly.
+TEST_F(FakeNetworkPipeTest, QueueLengthTest) {
+ FakeNetworkPipe::Config config;
+ config.queue_length_packets = 2;
+ config.link_capacity_kbps = 80;
+ TestDemuxer* demuxer = new TestDemuxer();
+ std::unique_ptr<FakeNetworkPipe> pipe(new FakeNetworkPipe(
+ &fake_clock_, config, std::unique_ptr<Demuxer>(demuxer)));
+
+ const int kPacketSize = 1000;
+ const int kPacketTimeMs = PacketTimeMs(config.link_capacity_kbps,
+ kPacketSize);
+
+ // Send three packets and verify only 2 are delivered.
+ SendPackets(pipe.get(), 3, kPacketSize);
+
+ // Increase time enough to deliver all three packets, verify only two are
+ // delivered.
+ fake_clock_.AdvanceTimeMilliseconds(3 * kPacketTimeMs);
+ EXPECT_CALL(*demuxer, DeliverPacket(_, _)).Times(2);
+ pipe->Process();
+}
+
+// Test we get statistics as expected.
+TEST_F(FakeNetworkPipeTest, StatisticsTest) {
+ FakeNetworkPipe::Config config;
+ config.queue_length_packets = 2;
+ config.queue_delay_ms = 20;
+ config.link_capacity_kbps = 80;
+ TestDemuxer* demuxer = new TestDemuxer();
+ std::unique_ptr<FakeNetworkPipe> pipe(new FakeNetworkPipe(
+ &fake_clock_, config, std::unique_ptr<Demuxer>(demuxer)));
+
+ const int kPacketSize = 1000;
+ const int kPacketTimeMs = PacketTimeMs(config.link_capacity_kbps,
+ kPacketSize);
+
+ // Send three packets and verify only 2 are delivered.
+ SendPackets(pipe.get(), 3, kPacketSize);
+ fake_clock_.AdvanceTimeMilliseconds(3 * kPacketTimeMs +
+ config.queue_delay_ms);
+
+ EXPECT_CALL(*demuxer, DeliverPacket(_, _)).Times(2);
+ pipe->Process();
+
+ // Packet 1: kPacketTimeMs + config.queue_delay_ms,
+ // packet 2: 2 * kPacketTimeMs + config.queue_delay_ms => 170 ms average.
+ EXPECT_EQ(pipe->AverageDelay(), 170);
+ EXPECT_EQ(pipe->sent_packets(), 2u);
+ EXPECT_EQ(pipe->dropped_packets(), 1u);
+ EXPECT_EQ(pipe->PercentageLoss(), 1/3.f);
+}
+
+// Change the link capacity half-way through the test and verify that the
+// delivery times change accordingly.
+TEST_F(FakeNetworkPipeTest, ChangingCapacityWithEmptyPipeTest) {
+ FakeNetworkPipe::Config config;
+ config.queue_length_packets = 20;
+ config.link_capacity_kbps = 80;
+ TestDemuxer* demuxer = new TestDemuxer();
+ std::unique_ptr<FakeNetworkPipe> pipe(new FakeNetworkPipe(
+ &fake_clock_, config, std::unique_ptr<Demuxer>(demuxer)));
+
+ // Add 10 packets of 1000 bytes, = 80 kb, and verify it takes one second to
+ // get through the pipe.
+ const int kNumPackets = 10;
+ const int kPacketSize = 1000;
+ SendPackets(pipe.get(), kNumPackets, kPacketSize);
+
+ // Time to get one packet through the link.
+ int packet_time_ms = PacketTimeMs(config.link_capacity_kbps, kPacketSize);
+
+ // Time hasn't increased yet, so we souldn't get any packets.
+ EXPECT_CALL(*demuxer, DeliverPacket(_, _)).Times(0);
+ pipe->Process();
+
+ // Advance time in steps to release one packet at a time.
+ for (int i = 0; i < kNumPackets; ++i) {
+ fake_clock_.AdvanceTimeMilliseconds(packet_time_ms);
+ EXPECT_CALL(*demuxer, DeliverPacket(_, _)).Times(1);
+ pipe->Process();
+ }
+
+ // Change the capacity.
+ config.link_capacity_kbps /= 2; // Reduce to 50%.
+ pipe->SetConfig(config);
+
+ // Add another 10 packets of 1000 bytes, = 80 kb, and verify it takes two
+ // seconds to get them through the pipe.
+ SendPackets(pipe.get(), kNumPackets, kPacketSize);
+
+ // Time to get one packet through the link.
+ packet_time_ms = PacketTimeMs(config.link_capacity_kbps, kPacketSize);
+
+ // Time hasn't increased yet, so we souldn't get any packets.
+ EXPECT_CALL(*demuxer, DeliverPacket(_, _)).Times(0);
+ pipe->Process();
+
+ // Advance time in steps to release one packet at a time.
+ for (int i = 0; i < kNumPackets; ++i) {
+ fake_clock_.AdvanceTimeMilliseconds(packet_time_ms);
+ EXPECT_CALL(*demuxer, DeliverPacket(_, _)).Times(1);
+ pipe->Process();
+ }
+
+ // Check that all the packets were sent.
+ EXPECT_EQ(static_cast<size_t>(2 * kNumPackets), pipe->sent_packets());
+ fake_clock_.AdvanceTimeMilliseconds(pipe->TimeUntilNextProcess());
+ EXPECT_CALL(*demuxer, DeliverPacket(_, _)).Times(0);
+ pipe->Process();
+}
+
+// Change the link capacity half-way through the test and verify that the
+// delivery times change accordingly.
+TEST_F(FakeNetworkPipeTest, ChangingCapacityWithPacketsInPipeTest) {
+ FakeNetworkPipe::Config config;
+ config.queue_length_packets = 20;
+ config.link_capacity_kbps = 80;
+ TestDemuxer* demuxer = new TestDemuxer();
+ std::unique_ptr<FakeNetworkPipe> pipe(new FakeNetworkPipe(
+ &fake_clock_, config, std::unique_ptr<Demuxer>(demuxer)));
+
+ // Add 10 packets of 1000 bytes, = 80 kb.
+ const int kNumPackets = 10;
+ const int kPacketSize = 1000;
+ SendPackets(pipe.get(), kNumPackets, kPacketSize);
+
+ // Time to get one packet through the link at the initial speed.
+ int packet_time_1_ms = PacketTimeMs(config.link_capacity_kbps, kPacketSize);
+
+ // Change the capacity.
+ config.link_capacity_kbps *= 2; // Double the capacity.
+ pipe->SetConfig(config);
+
+ // Add another 10 packets of 1000 bytes, = 80 kb, and verify it takes two
+ // seconds to get them through the pipe.
+ SendPackets(pipe.get(), kNumPackets, kPacketSize);
+
+ // Time to get one packet through the link at the new capacity.
+ int packet_time_2_ms = PacketTimeMs(config.link_capacity_kbps, kPacketSize);
+
+ // Time hasn't increased yet, so we souldn't get any packets.
+ EXPECT_CALL(*demuxer, DeliverPacket(_, _)).Times(0);
+ pipe->Process();
+
+ // Advance time in steps to release one packet at a time.
+ for (int i = 0; i < kNumPackets; ++i) {
+ fake_clock_.AdvanceTimeMilliseconds(packet_time_1_ms);
+ EXPECT_CALL(*demuxer, DeliverPacket(_, _)).Times(1);
+ pipe->Process();
+ }
+
+ // Advance time in steps to release one packet at a time.
+ for (int i = 0; i < kNumPackets; ++i) {
+ fake_clock_.AdvanceTimeMilliseconds(packet_time_2_ms);
+ EXPECT_CALL(*demuxer, DeliverPacket(_, _)).Times(1);
+ pipe->Process();
+ }
+
+ // Check that all the packets were sent.
+ EXPECT_EQ(static_cast<size_t>(2 * kNumPackets), pipe->sent_packets());
+ fake_clock_.AdvanceTimeMilliseconds(pipe->TimeUntilNextProcess());
+ EXPECT_CALL(*demuxer, DeliverPacket(_, _)).Times(0);
+ pipe->Process();
+}
+
+// At first disallow reordering and then allow reordering.
+TEST_F(FakeNetworkPipeTest, DisallowReorderingThenAllowReordering) {
+ FakeNetworkPipe::Config config;
+ config.queue_length_packets = 1000;
+ config.link_capacity_kbps = 800;
+ config.queue_delay_ms = 100;
+ config.delay_standard_deviation_ms = 10;
+ ReorderTestDemuxer* demuxer = new ReorderTestDemuxer();
+ std::unique_ptr<FakeNetworkPipe> pipe(new FakeNetworkPipe(
+ &fake_clock_, config, std::unique_ptr<Demuxer>(demuxer)));
+
+ const uint32_t kNumPackets = 100;
+ const int kPacketSize = 10;
+ SendPackets(pipe.get(), kNumPackets, kPacketSize);
+ fake_clock_.AdvanceTimeMilliseconds(1000);
+ pipe->Process();
+
+ // Confirm that all packets have been delivered in order.
+ EXPECT_EQ(kNumPackets, demuxer->delivered_sequence_numbers_.size());
+ int last_seq_num = -1;
+ for (int seq_num : demuxer->delivered_sequence_numbers_) {
+ EXPECT_GT(seq_num, last_seq_num);
+ last_seq_num = seq_num;
+ }
+
+ config.allow_reordering = true;
+ pipe->SetConfig(config);
+ SendPackets(pipe.get(), kNumPackets, kPacketSize);
+ fake_clock_.AdvanceTimeMilliseconds(1000);
+ demuxer->delivered_sequence_numbers_.clear();
+ pipe->Process();
+
+ // Confirm that all packets have been delivered
+ // and that reordering has occured.
+ EXPECT_EQ(kNumPackets, demuxer->delivered_sequence_numbers_.size());
+ bool reordering_has_occured = false;
+ last_seq_num = -1;
+ for (int seq_num : demuxer->delivered_sequence_numbers_) {
+ if (last_seq_num > seq_num) {
+ reordering_has_occured = true;
+ break;
+ }
+ last_seq_num = seq_num;
+ }
+ EXPECT_TRUE(reordering_has_occured);
+}
+
+TEST_F(FakeNetworkPipeTest, BurstLoss) {
+ const int kLossPercent = 5;
+ const int kAvgBurstLength = 3;
+ const int kNumPackets = 10000;
+ const int kPacketSize = 10;
+
+ FakeNetworkPipe::Config config;
+ config.queue_length_packets = kNumPackets;
+ config.loss_percent = kLossPercent;
+ config.avg_burst_loss_length = kAvgBurstLength;
+ ReorderTestDemuxer* demuxer = new ReorderTestDemuxer();
+ std::unique_ptr<FakeNetworkPipe> pipe(new FakeNetworkPipe(
+ &fake_clock_, config, std::unique_ptr<Demuxer>(demuxer)));
+
+ SendPackets(pipe.get(), kNumPackets, kPacketSize);
+ fake_clock_.AdvanceTimeMilliseconds(1000);
+ pipe->Process();
+
+ // Check that the average loss is |kLossPercent| percent.
+ int lost_packets = kNumPackets - demuxer->delivered_sequence_numbers_.size();
+ double loss_fraction = lost_packets / static_cast<double>(kNumPackets);
+
+ EXPECT_NEAR(kLossPercent / 100.0, loss_fraction, 0.05);
+
+ // Find the number of bursts that has occurred.
+ size_t received_packets = demuxer->delivered_sequence_numbers_.size();
+ int num_bursts = 0;
+ for (size_t i = 0; i < received_packets - 1; ++i) {
+ int diff = demuxer->delivered_sequence_numbers_[i + 1] -
+ demuxer->delivered_sequence_numbers_[i];
+ if (diff > 1)
+ ++num_bursts;
+ }
+
+ double average_burst_length = static_cast<double>(lost_packets) / num_bursts;
+
+ EXPECT_NEAR(kAvgBurstLength, average_burst_length, 0.3);
+}
+
+TEST_F(FakeNetworkPipeTest, SetReceiver) {
+ FakeNetworkPipe::Config config;
+ TestDemuxer* demuxer = new TestDemuxer();
+ std::unique_ptr<FakeNetworkPipe> pipe(new FakeNetworkPipe(
+ &fake_clock_, config, std::unique_ptr<Demuxer>(demuxer)));
+ MockReceiver packet_receiver;
+ EXPECT_CALL(*demuxer, SetReceiver(&packet_receiver)).Times(1);
+ pipe->SetReceiver(&packet_receiver);
+}
+
+TEST(DemuxerImplTest, Demuxing) {
+ constexpr uint8_t kVideoPayloadType = 100;
+ constexpr uint8_t kAudioPayloadType = 101;
+ constexpr int64_t kTimeNow = 12345;
+ constexpr int64_t kArrivalTime = kTimeNow - 1;
+ constexpr size_t kPacketSize = 10;
+ DemuxerImpl demuxer({{kVideoPayloadType, MediaType::VIDEO},
+ {kAudioPayloadType, MediaType::AUDIO}});
+
+ MockReceiver mock_receiver;
+ demuxer.SetReceiver(&mock_receiver);
+
+ std::vector<uint8_t> data(kPacketSize);
+ data[1] = kVideoPayloadType;
+ std::unique_ptr<NetworkPacket> packet(
+ new NetworkPacket(&data[0], kPacketSize, kTimeNow, kArrivalTime));
+ EXPECT_CALL(mock_receiver, DeliverPacket(MediaType::VIDEO, _, _, _))
+ .WillOnce(Return(PacketReceiver::DELIVERY_OK));
+ demuxer.DeliverPacket(packet.get(), PacketTime());
+
+ data[1] = kAudioPayloadType;
+ packet.reset(
+ new NetworkPacket(&data[0], kPacketSize, kTimeNow, kArrivalTime));
+ EXPECT_CALL(mock_receiver, DeliverPacket(MediaType::AUDIO, _, _, _))
+ .WillOnce(Return(PacketReceiver::DELIVERY_OK));
+ demuxer.DeliverPacket(packet.get(), PacketTime());
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fake_texture_frame.cc b/third_party/libwebrtc/webrtc/test/fake_texture_frame.cc
new file mode 100644
index 0000000000..4c4ea94fd2
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fake_texture_frame.cc
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/fake_texture_frame.h"
+
+namespace webrtc {
+namespace test {
+
+VideoFrame FakeNativeBuffer::CreateFrame(int width,
+ int height,
+ uint32_t timestamp,
+ int64_t render_time_ms,
+ VideoRotation rotation) {
+ return VideoFrame(new rtc::RefCountedObject<FakeNativeBuffer>(width, height),
+ timestamp, render_time_ms, rotation);
+}
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fake_texture_frame.h b/third_party/libwebrtc/webrtc/test/fake_texture_frame.h
new file mode 100644
index 0000000000..17261ff8ae
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fake_texture_frame.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef TEST_FAKE_TEXTURE_FRAME_H_
+#define TEST_FAKE_TEXTURE_FRAME_H_
+
+#include "api/video/i420_buffer.h"
+#include "api/video/video_frame.h"
+#include "common_video/include/video_frame_buffer.h"
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+namespace test {
+
+class FakeNativeBuffer : public VideoFrameBuffer {
+ public:
+ static VideoFrame CreateFrame(int width,
+ int height,
+ uint32_t timestamp,
+ int64_t render_time_ms,
+ VideoRotation rotation);
+
+ FakeNativeBuffer(int width, int height) : width_(width), height_(height) {}
+
+ Type type() const override { return Type::kNative; }
+ int width() const override { return width_; }
+ int height() const override { return height_; }
+
+ private:
+ rtc::scoped_refptr<I420BufferInterface> ToI420() override {
+ rtc::scoped_refptr<I420Buffer> buffer = I420Buffer::Create(width_, height_);
+ I420Buffer::SetBlack(buffer);
+ return buffer;
+ }
+
+ const int width_;
+ const int height_;
+};
+
+} // namespace test
+} // namespace webrtc
+#endif // TEST_FAKE_TEXTURE_FRAME_H_
diff --git a/third_party/libwebrtc/webrtc/test/fake_videorenderer.h b/third_party/libwebrtc/webrtc/test/fake_videorenderer.h
new file mode 100644
index 0000000000..bc9c1db710
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fake_videorenderer.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef TEST_FAKE_VIDEORENDERER_H_
+#define TEST_FAKE_VIDEORENDERER_H_
+
+#include "api/video/video_frame.h"
+#include "media/base/videosinkinterface.h"
+
+namespace webrtc {
+namespace test {
+
+class FakeVideoRenderer : public rtc::VideoSinkInterface<webrtc::VideoFrame> {
+ public:
+ void OnFrame(const webrtc::VideoFrame& frame) override {}
+};
+
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_FAKE_VIDEORENDERER_H_
diff --git a/third_party/libwebrtc/webrtc/test/field_trial.cc b/third_party/libwebrtc/webrtc/test/field_trial.cc
new file mode 100644
index 0000000000..00e5b69041
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/field_trial.cc
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/field_trial.h"
+
+#include <algorithm>
+#include <cassert>
+#include <cstdio>
+#include <cstdlib>
+#include <map>
+#include <string>
+
+#include "system_wrappers/include/field_trial.h"
+#include "system_wrappers/include/field_trial_default.h"
+
+namespace webrtc {
+namespace {
+bool field_trials_initiated_ = false;
+} // namespace
+
+namespace test {
+// Note: this code is copied from src/base/metrics/field_trial.cc since the aim
+// is to mimic chromium --force-fieldtrials.
+void InitFieldTrialsFromString(const std::string& trials_string) {
+ static const char kPersistentStringSeparator = '/';
+
+ // Catch an error if this is called more than once.
+ assert(!field_trials_initiated_);
+ field_trials_initiated_ = true;
+
+ if (trials_string.empty())
+ return;
+
+ size_t next_item = 0;
+ std::map<std::string, std::string> field_trials;
+ while (next_item < trials_string.length()) {
+ size_t name_end = trials_string.find(kPersistentStringSeparator, next_item);
+ if (name_end == trials_string.npos || next_item == name_end)
+ break;
+ size_t group_name_end = trials_string.find(kPersistentStringSeparator,
+ name_end + 1);
+ if (group_name_end == trials_string.npos || name_end + 1 == group_name_end)
+ break;
+ std::string name(trials_string, next_item, name_end - next_item);
+ std::string group_name(trials_string, name_end + 1,
+ group_name_end - name_end - 1);
+ next_item = group_name_end + 1;
+
+ // Fail if duplicate with different group name.
+ if (field_trials.find(name) != field_trials.end() &&
+ field_trials.find(name)->second != group_name) {
+ break;
+ }
+
+ field_trials[name] = group_name;
+
+ // Successfully parsed all field trials from the string.
+ if (next_item == trials_string.length()) {
+ webrtc::field_trial::InitFieldTrialsFromString(trials_string.c_str());
+ return;
+ }
+ }
+ // Using fprintf as RTC_LOG does not print when this is called early in main.
+ fprintf(stderr, "Invalid field trials string.\n");
+
+ // Using abort so it crashes in both debug and release mode.
+ abort();
+}
+
+ScopedFieldTrials::ScopedFieldTrials(const std::string& config)
+ : previous_field_trials_(webrtc::field_trial::GetFieldTrialString()) {
+ assert(field_trials_initiated_);
+ field_trials_initiated_ = false;
+ current_field_trials_ = config;
+ InitFieldTrialsFromString(current_field_trials_);
+}
+
+ScopedFieldTrials::~ScopedFieldTrials() {
+ // Should still be initialized, since InitFieldTrials is called from ctor.
+ // That's why we don't restore the flag.
+ assert(field_trials_initiated_);
+ webrtc::field_trial::InitFieldTrialsFromString(previous_field_trials_);
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/field_trial.h b/third_party/libwebrtc/webrtc/test/field_trial.h
new file mode 100644
index 0000000000..99ace4e864
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/field_trial.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef TEST_FIELD_TRIAL_H_
+#define TEST_FIELD_TRIAL_H_
+
+#include <string>
+#include <map>
+
+namespace webrtc {
+namespace test {
+
+// Parses enabled field trials from a string config, such as the one passed
+// to chrome's argument --force-fieldtrials and initializes webrtc::field_trial
+// with such a config.
+// E.g.:
+// "WebRTC-experimentFoo/Enabled/WebRTC-experimentBar/Enabled100kbps/"
+// Assigns the process to group "Enabled" on WebRTCExperimentFoo trial
+// and to group "Enabled100kbps" on WebRTCExperimentBar.
+//
+// E.g. invalid config:
+// "WebRTC-experiment1/Enabled" (note missing / separator at the end).
+//
+// Note: This method crashes with an error message if an invalid config is
+// passed to it. That can be used to find out if a binary is parsing the flags.
+void InitFieldTrialsFromString(const std::string& config);
+
+// This class is used to override field-trial configs within specific tests.
+// After this class goes out of scope previous field trials will be restored.
+class ScopedFieldTrials {
+ public:
+ explicit ScopedFieldTrials(const std::string& config);
+ ~ScopedFieldTrials();
+ private:
+ std::string current_field_trials_;
+ const char* previous_field_trials_;
+};
+
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_FIELD_TRIAL_H_
diff --git a/third_party/libwebrtc/webrtc/test/frame_generator.cc b/third_party/libwebrtc/webrtc/test/frame_generator.cc
new file mode 100644
index 0000000000..e5d9950301
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/frame_generator.cc
@@ -0,0 +1,457 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "test/frame_generator.h"
+
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <memory>
+
+#include "api/video/i420_buffer.h"
+#include "common_video/include/video_frame_buffer.h"
+#include "common_video/libyuv/include/webrtc_libyuv.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/keep_ref_until_done.h"
+#include "rtc_base/random.h"
+#include "system_wrappers/include/clock.h"
+#include "test/frame_utils.h"
+
+namespace webrtc {
+namespace test {
+namespace {
+
+// SquareGenerator is a FrameGenerator that draws a given amount of randomly
+// sized and colored squares. Between each new generated frame, the squares
+// are moved slightly towards the lower right corner.
+class SquareGenerator : public FrameGenerator {
+ public:
+ SquareGenerator(int width, int height, int num_squares) {
+ ChangeResolution(width, height);
+ for (int i = 0; i < num_squares; ++i) {
+ squares_.emplace_back(new Square(width, height, i + 1));
+ }
+ }
+
+ void ChangeResolution(size_t width, size_t height) override {
+ rtc::CritScope lock(&crit_);
+ width_ = static_cast<int>(width);
+ height_ = static_cast<int>(height);
+ RTC_CHECK(width_ > 0);
+ RTC_CHECK(height_ > 0);
+ }
+
+ VideoFrame* NextFrame() override {
+ rtc::CritScope lock(&crit_);
+
+ rtc::scoped_refptr<I420Buffer> buffer(I420Buffer::Create(width_, height_));
+
+ memset(buffer->MutableDataY(), 127, height_ * buffer->StrideY());
+ memset(buffer->MutableDataU(), 127,
+ buffer->ChromaHeight() * buffer->StrideU());
+ memset(buffer->MutableDataV(), 127,
+ buffer->ChromaHeight() * buffer->StrideV());
+
+ for (const auto& square : squares_)
+ square->Draw(buffer);
+
+ frame_.reset(new VideoFrame(buffer, 0, 0, webrtc::kVideoRotation_0));
+ return frame_.get();
+ }
+
+ private:
+ class Square {
+ public:
+ Square(int width, int height, int seed)
+ : random_generator_(seed),
+ x_(random_generator_.Rand(0, width)),
+ y_(random_generator_.Rand(0, height)),
+ length_(random_generator_.Rand(1, width > 4 ? width / 4 : 1)),
+ yuv_y_(random_generator_.Rand(0, 255)),
+ yuv_u_(random_generator_.Rand(0, 255)),
+ yuv_v_(random_generator_.Rand(0, 255)) {}
+
+ void Draw(const rtc::scoped_refptr<I420Buffer>& buffer) {
+ x_ = (x_ + random_generator_.Rand(0, 4)) % (buffer->width() - length_);
+ y_ = (y_ + random_generator_.Rand(0, 4)) % (buffer->height() - length_);
+ for (int y = y_; y < y_ + length_; ++y) {
+ uint8_t* pos_y =
+ (buffer->MutableDataY() + x_ + y * buffer->StrideY());
+ memset(pos_y, yuv_y_, length_);
+ }
+
+ for (int y = y_; y < y_ + length_; y = y + 2) {
+ uint8_t* pos_u =
+ (buffer->MutableDataU() + x_ / 2 + y / 2 * buffer->StrideU());
+ memset(pos_u, yuv_u_, length_ / 2);
+ uint8_t* pos_v =
+ (buffer->MutableDataV() + x_ / 2 + y / 2 * buffer->StrideV());
+ memset(pos_v, yuv_v_, length_ / 2);
+ }
+ }
+
+ private:
+ Random random_generator_;
+ int x_;
+ int y_;
+ const int length_;
+ const uint8_t yuv_y_;
+ const uint8_t yuv_u_;
+ const uint8_t yuv_v_;
+ };
+
+ rtc::CriticalSection crit_;
+ int width_ RTC_GUARDED_BY(&crit_);
+ int height_ RTC_GUARDED_BY(&crit_);
+ std::vector<std::unique_ptr<Square>> squares_ RTC_GUARDED_BY(&crit_);
+ std::unique_ptr<VideoFrame> frame_ RTC_GUARDED_BY(&crit_);
+};
+
+class YuvFileGenerator : public FrameGenerator {
+ public:
+ YuvFileGenerator(std::vector<FILE*> files,
+ size_t width,
+ size_t height,
+ int frame_repeat_count)
+ : file_index_(0),
+ files_(files),
+ width_(width),
+ height_(height),
+ frame_size_(CalcBufferSize(VideoType::kI420,
+ static_cast<int>(width_),
+ static_cast<int>(height_))),
+ frame_buffer_(new uint8_t[frame_size_]),
+ frame_display_count_(frame_repeat_count),
+ current_display_count_(0) {
+ RTC_DCHECK_GT(width, 0);
+ RTC_DCHECK_GT(height, 0);
+ RTC_DCHECK_GT(frame_repeat_count, 0);
+ }
+
+ virtual ~YuvFileGenerator() {
+ for (FILE* file : files_)
+ fclose(file);
+ }
+
+ VideoFrame* NextFrame() override {
+ if (current_display_count_ == 0)
+ ReadNextFrame();
+ if (++current_display_count_ >= frame_display_count_)
+ current_display_count_ = 0;
+
+ temp_frame_.reset(
+ new VideoFrame(last_read_buffer_, 0, 0, webrtc::kVideoRotation_0));
+ return temp_frame_.get();
+ }
+
+ void ReadNextFrame() {
+ last_read_buffer_ =
+ test::ReadI420Buffer(static_cast<int>(width_),
+ static_cast<int>(height_),
+ files_[file_index_]);
+ if (!last_read_buffer_) {
+ // No more frames to read in this file, rewind and move to next file.
+ rewind(files_[file_index_]);
+ file_index_ = (file_index_ + 1) % files_.size();
+ last_read_buffer_ =
+ test::ReadI420Buffer(static_cast<int>(width_),
+ static_cast<int>(height_),
+ files_[file_index_]);
+ RTC_CHECK(last_read_buffer_);
+ }
+ }
+
+ private:
+ size_t file_index_;
+ const std::vector<FILE*> files_;
+ const size_t width_;
+ const size_t height_;
+ const size_t frame_size_;
+ const std::unique_ptr<uint8_t[]> frame_buffer_;
+ const int frame_display_count_;
+ int current_display_count_;
+ rtc::scoped_refptr<I420Buffer> last_read_buffer_;
+ std::unique_ptr<VideoFrame> temp_frame_;
+};
+
+// SlideGenerator works similarly to YuvFileGenerator but it fills the frames
+// with randomly sized and colored squares instead of reading their content
+// from files.
+class SlideGenerator : public FrameGenerator {
+ public:
+ SlideGenerator(int width, int height, int frame_repeat_count)
+ : width_(width),
+ height_(height),
+ frame_display_count_(frame_repeat_count),
+ current_display_count_(0),
+ random_generator_(1234) {
+ RTC_DCHECK_GT(width, 0);
+ RTC_DCHECK_GT(height, 0);
+ RTC_DCHECK_GT(frame_repeat_count, 0);
+ }
+
+ VideoFrame* NextFrame() override {
+ if (current_display_count_ == 0)
+ GenerateNewFrame();
+ if (++current_display_count_ >= frame_display_count_)
+ current_display_count_ = 0;
+
+ frame_.reset(
+ new VideoFrame(buffer_, 0, 0, webrtc::kVideoRotation_0));
+ return frame_.get();
+ }
+
+ // Generates some randomly sized and colored squares scattered
+ // over the frame.
+ void GenerateNewFrame() {
+ // The squares should have a varying order of magnitude in order
+ // to simulate variation in the slides' complexity.
+ const int kSquareNum = 1 << (4 + (random_generator_.Rand(0, 3) * 2));
+
+ buffer_ = I420Buffer::Create(width_, height_);
+ memset(buffer_->MutableDataY(), 127, height_ * buffer_->StrideY());
+ memset(buffer_->MutableDataU(), 127,
+ buffer_->ChromaHeight() * buffer_->StrideU());
+ memset(buffer_->MutableDataV(), 127,
+ buffer_->ChromaHeight() * buffer_->StrideV());
+
+ for (int i = 0; i < kSquareNum; ++i) {
+ int length = random_generator_.Rand(1, width_ > 4 ? width_ / 4 : 1);
+ // Limit the length of later squares so that they don't overwrite the
+ // previous ones too much.
+ length = (length * (kSquareNum - i)) / kSquareNum;
+
+ int x = random_generator_.Rand(0, width_ - length);
+ int y = random_generator_.Rand(0, height_ - length);
+ uint8_t yuv_y = random_generator_.Rand(0, 255);
+ uint8_t yuv_u = random_generator_.Rand(0, 255);
+ uint8_t yuv_v = random_generator_.Rand(0, 255);
+
+ for (int yy = y; yy < y + length; ++yy) {
+ uint8_t* pos_y =
+ (buffer_->MutableDataY() + x + yy * buffer_->StrideY());
+ memset(pos_y, yuv_y, length);
+ }
+ for (int yy = y; yy < y + length; yy += 2) {
+ uint8_t* pos_u =
+ (buffer_->MutableDataU() + x / 2 + yy / 2 * buffer_->StrideU());
+ memset(pos_u, yuv_u, length / 2);
+ uint8_t* pos_v =
+ (buffer_->MutableDataV() + x / 2 + yy / 2 * buffer_->StrideV());
+ memset(pos_v, yuv_v, length / 2);
+ }
+ }
+ }
+
+ private:
+ const int width_;
+ const int height_;
+ const int frame_display_count_;
+ int current_display_count_;
+ Random random_generator_;
+ rtc::scoped_refptr<I420Buffer> buffer_;
+ std::unique_ptr<VideoFrame> frame_;
+};
+
+class ScrollingImageFrameGenerator : public FrameGenerator {
+ public:
+ ScrollingImageFrameGenerator(Clock* clock,
+ const std::vector<FILE*>& files,
+ size_t source_width,
+ size_t source_height,
+ size_t target_width,
+ size_t target_height,
+ int64_t scroll_time_ms,
+ int64_t pause_time_ms)
+ : clock_(clock),
+ start_time_(clock->TimeInMilliseconds()),
+ scroll_time_(scroll_time_ms),
+ pause_time_(pause_time_ms),
+ num_frames_(files.size()),
+ target_width_(static_cast<int>(target_width)),
+ target_height_(static_cast<int>(target_height)),
+ current_frame_num_(num_frames_ - 1),
+ current_source_frame_(nullptr),
+ file_generator_(files, source_width, source_height, 1) {
+ RTC_DCHECK(clock_ != nullptr);
+ RTC_DCHECK_GT(num_frames_, 0);
+ RTC_DCHECK_GE(source_height, target_height);
+ RTC_DCHECK_GE(source_width, target_width);
+ RTC_DCHECK_GE(scroll_time_ms, 0);
+ RTC_DCHECK_GE(pause_time_ms, 0);
+ RTC_DCHECK_GT(scroll_time_ms + pause_time_ms, 0);
+ }
+
+ virtual ~ScrollingImageFrameGenerator() {}
+
+ VideoFrame* NextFrame() override {
+ const int64_t kFrameDisplayTime = scroll_time_ + pause_time_;
+ const int64_t now = clock_->TimeInMilliseconds();
+ int64_t ms_since_start = now - start_time_;
+
+ size_t frame_num = (ms_since_start / kFrameDisplayTime) % num_frames_;
+ UpdateSourceFrame(frame_num);
+
+ double scroll_factor;
+ int64_t time_into_frame = ms_since_start % kFrameDisplayTime;
+ if (time_into_frame < scroll_time_) {
+ scroll_factor = static_cast<double>(time_into_frame) / scroll_time_;
+ } else {
+ scroll_factor = 1.0;
+ }
+ CropSourceToScrolledImage(scroll_factor);
+
+ return current_frame_ ? &*current_frame_ : nullptr;
+ }
+
+ void UpdateSourceFrame(size_t frame_num) {
+ while (current_frame_num_ != frame_num) {
+ current_source_frame_ = file_generator_.NextFrame();
+ current_frame_num_ = (current_frame_num_ + 1) % num_frames_;
+ }
+ RTC_DCHECK(current_source_frame_ != nullptr);
+ }
+
+ void CropSourceToScrolledImage(double scroll_factor) {
+ int scroll_margin_x = current_source_frame_->width() - target_width_;
+ int pixels_scrolled_x =
+ static_cast<int>(scroll_margin_x * scroll_factor + 0.5);
+ int scroll_margin_y = current_source_frame_->height() - target_height_;
+ int pixels_scrolled_y =
+ static_cast<int>(scroll_margin_y * scroll_factor + 0.5);
+
+ rtc::scoped_refptr<I420BufferInterface> i420_buffer =
+ current_source_frame_->video_frame_buffer()->ToI420();
+ int offset_y =
+ (i420_buffer->StrideY() * pixels_scrolled_y) + pixels_scrolled_x;
+ int offset_u = (i420_buffer->StrideU() * (pixels_scrolled_y / 2)) +
+ (pixels_scrolled_x / 2);
+ int offset_v = (i420_buffer->StrideV() * (pixels_scrolled_y / 2)) +
+ (pixels_scrolled_x / 2);
+
+ current_frame_ = rtc::Optional<webrtc::VideoFrame>(webrtc::VideoFrame(
+ new rtc::RefCountedObject<webrtc::WrappedI420Buffer>(
+ target_width_, target_height_, &i420_buffer->DataY()[offset_y],
+ i420_buffer->StrideY(), &i420_buffer->DataU()[offset_u],
+ i420_buffer->StrideU(), &i420_buffer->DataV()[offset_v],
+ i420_buffer->StrideV(), KeepRefUntilDone(i420_buffer)),
+ kVideoRotation_0, 0));
+ }
+
+ Clock* const clock_;
+ const int64_t start_time_;
+ const int64_t scroll_time_;
+ const int64_t pause_time_;
+ const size_t num_frames_;
+ const int target_width_;
+ const int target_height_;
+
+ size_t current_frame_num_;
+ VideoFrame* current_source_frame_;
+ rtc::Optional<VideoFrame> current_frame_;
+ YuvFileGenerator file_generator_;
+};
+
+} // namespace
+
+FrameForwarder::FrameForwarder() : sink_(nullptr) {}
+FrameForwarder::~FrameForwarder() {}
+
+void FrameForwarder::IncomingCapturedFrame(const VideoFrame& video_frame) {
+ rtc::CritScope lock(&crit_);
+ if (sink_)
+ sink_->OnFrame(video_frame);
+}
+
+void FrameForwarder::AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink,
+ const rtc::VideoSinkWants& wants) {
+ rtc::CritScope lock(&crit_);
+ RTC_DCHECK(!sink_ || sink_ == sink);
+ sink_ = sink;
+ sink_wants_ = wants;
+}
+
+void FrameForwarder::RemoveSink(rtc::VideoSinkInterface<VideoFrame>* sink) {
+ rtc::CritScope lock(&crit_);
+ RTC_DCHECK_EQ(sink, sink_);
+ sink_ = nullptr;
+}
+
+rtc::VideoSinkWants FrameForwarder::sink_wants() const {
+ rtc::CritScope lock(&crit_);
+ return sink_wants_;
+}
+
+bool FrameForwarder::has_sinks() const {
+ rtc::CritScope lock(&crit_);
+ return sink_ != nullptr;
+}
+
+std::unique_ptr<FrameGenerator> FrameGenerator::CreateSquareGenerator(
+ int width,
+ int height) {
+ return std::unique_ptr<FrameGenerator>(
+ new SquareGenerator(width, height, 10));
+}
+
+std::unique_ptr<FrameGenerator>
+FrameGenerator::CreateSquareGenerator(int width, int height, int num_squares) {
+ return std::unique_ptr<FrameGenerator>(
+ new SquareGenerator(width, height, num_squares));
+}
+
+std::unique_ptr<FrameGenerator> FrameGenerator::CreateSlideGenerator(
+ int width, int height, int frame_repeat_count) {
+ return std::unique_ptr<FrameGenerator>(new SlideGenerator(
+ width, height, frame_repeat_count));
+}
+
+std::unique_ptr<FrameGenerator> FrameGenerator::CreateFromYuvFile(
+ std::vector<std::string> filenames,
+ size_t width,
+ size_t height,
+ int frame_repeat_count) {
+ RTC_DCHECK(!filenames.empty());
+ std::vector<FILE*> files;
+ for (const std::string& filename : filenames) {
+ FILE* file = fopen(filename.c_str(), "rb");
+ RTC_DCHECK(file != nullptr);
+ files.push_back(file);
+ }
+
+ return std::unique_ptr<FrameGenerator>(
+ new YuvFileGenerator(files, width, height, frame_repeat_count));
+}
+
+std::unique_ptr<FrameGenerator>
+FrameGenerator::CreateScrollingInputFromYuvFiles(
+ Clock* clock,
+ std::vector<std::string> filenames,
+ size_t source_width,
+ size_t source_height,
+ size_t target_width,
+ size_t target_height,
+ int64_t scroll_time_ms,
+ int64_t pause_time_ms) {
+ RTC_DCHECK(!filenames.empty());
+ std::vector<FILE*> files;
+ for (const std::string& filename : filenames) {
+ FILE* file = fopen(filename.c_str(), "rb");
+ RTC_DCHECK(file != nullptr);
+ files.push_back(file);
+ }
+
+ return std::unique_ptr<FrameGenerator>(new ScrollingImageFrameGenerator(
+ clock, files, source_width, source_height, target_width, target_height,
+ scroll_time_ms, pause_time_ms));
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/frame_generator.h b/third_party/libwebrtc/webrtc/test/frame_generator.h
new file mode 100644
index 0000000000..d37166f2fa
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/frame_generator.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef TEST_FRAME_GENERATOR_H_
+#define TEST_FRAME_GENERATOR_H_
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "api/video/video_frame.h"
+#include "media/base/videosourceinterface.h"
+#include "rtc_base/criticalsection.h"
+#include "typedefs.h" // NOLINT(build/include)
+
+namespace webrtc {
+class Clock;
+namespace test {
+
+// FrameForwarder can be used as an implementation
+// of rtc::VideoSourceInterface<VideoFrame> where the caller controls when
+// a frame should be forwarded to its sink.
+// Currently this implementation only support one sink.
+class FrameForwarder : public rtc::VideoSourceInterface<VideoFrame> {
+ public:
+ FrameForwarder();
+ virtual ~FrameForwarder();
+ // Forwards |video_frame| to the registered |sink_|.
+ virtual void IncomingCapturedFrame(const VideoFrame& video_frame);
+ rtc::VideoSinkWants sink_wants() const;
+ bool has_sinks() const;
+
+ protected:
+ void AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink,
+ const rtc::VideoSinkWants& wants) override;
+ void RemoveSink(rtc::VideoSinkInterface<VideoFrame>* sink) override;
+
+ rtc::CriticalSection crit_;
+ rtc::VideoSinkInterface<VideoFrame>* sink_ RTC_GUARDED_BY(crit_);
+ rtc::VideoSinkWants sink_wants_ RTC_GUARDED_BY(crit_);
+};
+
+class FrameGenerator {
+ public:
+ virtual ~FrameGenerator() = default;
+
+ // Returns video frame that remains valid until next call.
+ virtual VideoFrame* NextFrame() = 0;
+
+ // Change the capture resolution.
+ virtual void ChangeResolution(size_t width, size_t height) {
+ RTC_NOTREACHED();
+ }
+
+ // Creates a frame generator that produces frames with small squares that
+ // move randomly towards the lower right corner.
+ static std::unique_ptr<FrameGenerator> CreateSquareGenerator(int width,
+ int height);
+ static std::unique_ptr<FrameGenerator> CreateSquareGenerator(int width,
+ int height,
+ int num_squares);
+
+ // Creates a frame generator that repeatedly plays a set of yuv files.
+ // The frame_repeat_count determines how many times each frame is shown,
+ // with 1 = show each frame once, etc.
+ static std::unique_ptr<FrameGenerator> CreateFromYuvFile(
+ std::vector<std::string> files,
+ size_t width,
+ size_t height,
+ int frame_repeat_count);
+
+ // Creates a frame generator which takes a set of yuv files (wrapping a
+ // frame generator created by CreateFromYuvFile() above), but outputs frames
+ // that have been cropped to specified resolution: source_width/source_height
+ // is the size of the source images, target_width/target_height is the size of
+ // the cropped output. For each source image read, the cropped viewport will
+ // be scrolled top to bottom/left to right for scroll_tim_ms milliseconds.
+ // After that the image will stay in place for pause_time_ms milliseconds,
+ // and then this will be repeated with the next file from the input set.
+ static std::unique_ptr<FrameGenerator> CreateScrollingInputFromYuvFiles(
+ Clock* clock,
+ std::vector<std::string> filenames,
+ size_t source_width,
+ size_t source_height,
+ size_t target_width,
+ size_t target_height,
+ int64_t scroll_time_ms,
+ int64_t pause_time_ms);
+
+ // Creates a frame generator that produces randomly generated slides.
+ // frame_repeat_count determines how many times each slide is shown.
+ static std::unique_ptr<FrameGenerator> CreateSlideGenerator(
+ int width, int height, int frame_repeat_count);
+};
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_FRAME_GENERATOR_H_
diff --git a/third_party/libwebrtc/webrtc/test/frame_generator_capturer.cc b/third_party/libwebrtc/webrtc/test/frame_generator_capturer.cc
new file mode 100644
index 0000000000..a8983b7ba2
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/frame_generator_capturer.cc
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/frame_generator_capturer.h"
+
+#include <utility>
+#include <vector>
+
+#include "rtc_base/criticalsection.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/platform_thread.h"
+#include "rtc_base/task_queue.h"
+#include "rtc_base/timeutils.h"
+#include "system_wrappers/include/clock.h"
+#include "test/frame_generator.h"
+#include "call/video_send_stream.h"
+
+namespace webrtc {
+namespace test {
+
+class FrameGeneratorCapturer::InsertFrameTask : public rtc::QueuedTask {
+ public:
+ // Repeats in |repeat_interval_ms|. One-time if |repeat_interval_ms| == 0.
+ InsertFrameTask(
+ webrtc::test::FrameGeneratorCapturer* frame_generator_capturer,
+ uint32_t repeat_interval_ms)
+ : frame_generator_capturer_(frame_generator_capturer),
+ repeat_interval_ms_(repeat_interval_ms),
+ intended_run_time_ms_(-1) {}
+
+ private:
+ bool Run() override {
+ bool task_completed = true;
+ if (repeat_interval_ms_ > 0) {
+ // This is not a one-off frame. Check if the frame interval for this
+ // task queue is the same same as the current configured frame rate.
+ uint32_t current_interval_ms =
+ 1000 / frame_generator_capturer_->GetCurrentConfiguredFramerate();
+ if (repeat_interval_ms_ != current_interval_ms) {
+ // Frame rate has changed since task was started, create a new instance.
+ rtc::TaskQueue::Current()->PostDelayedTask(
+ std::unique_ptr<rtc::QueuedTask>(new InsertFrameTask(
+ frame_generator_capturer_, current_interval_ms)),
+ current_interval_ms);
+ } else {
+ // Schedule the next frame capture event to happen at approximately the
+ // correct absolute time point.
+ int64_t delay_ms;
+ int64_t time_now_ms = rtc::TimeMillis();
+ if (intended_run_time_ms_ > 0) {
+ delay_ms = time_now_ms - intended_run_time_ms_;
+ } else {
+ delay_ms = 0;
+ intended_run_time_ms_ = time_now_ms;
+ }
+ intended_run_time_ms_ += repeat_interval_ms_;
+ if (delay_ms < repeat_interval_ms_) {
+ rtc::TaskQueue::Current()->PostDelayedTask(
+ std::unique_ptr<rtc::QueuedTask>(this),
+ repeat_interval_ms_ - delay_ms);
+ } else {
+ rtc::TaskQueue::Current()->PostDelayedTask(
+ std::unique_ptr<rtc::QueuedTask>(this), 0);
+ RTC_LOG(LS_ERROR)
+ << "Frame Generator Capturer can't keep up with requested fps";
+ }
+ // Repost of this instance, make sure it is not deleted.
+ task_completed = false;
+ }
+ }
+ frame_generator_capturer_->InsertFrame();
+ // Task should be deleted only if it's not repeating.
+ return task_completed;
+ }
+
+ webrtc::test::FrameGeneratorCapturer* const frame_generator_capturer_;
+ const uint32_t repeat_interval_ms_;
+ int64_t intended_run_time_ms_;
+};
+
+FrameGeneratorCapturer* FrameGeneratorCapturer::Create(int width,
+ int height,
+ int target_fps,
+ Clock* clock) {
+ std::unique_ptr<FrameGeneratorCapturer> capturer(new FrameGeneratorCapturer(
+ clock, FrameGenerator::CreateSquareGenerator(width, height), target_fps));
+ if (!capturer->Init())
+ return nullptr;
+
+ return capturer.release();
+}
+
+FrameGeneratorCapturer* FrameGeneratorCapturer::Create(int width,
+ int height,
+ int num_squares,
+ int target_fps,
+ Clock* clock) {
+ std::unique_ptr<FrameGeneratorCapturer> capturer(new FrameGeneratorCapturer(
+ clock, FrameGenerator::CreateSquareGenerator(width, height, num_squares),
+ target_fps));
+ if (!capturer->Init())
+ return nullptr;
+
+ return capturer.release();
+}
+
+FrameGeneratorCapturer* FrameGeneratorCapturer::CreateFromYuvFile(
+ const std::string& file_name,
+ size_t width,
+ size_t height,
+ int target_fps,
+ Clock* clock) {
+ std::unique_ptr<FrameGeneratorCapturer> capturer(new FrameGeneratorCapturer(
+ clock,
+ FrameGenerator::CreateFromYuvFile(std::vector<std::string>(1, file_name),
+ width, height, 1),
+ target_fps));
+ if (!capturer->Init())
+ return nullptr;
+
+ return capturer.release();
+}
+
+FrameGeneratorCapturer* FrameGeneratorCapturer::CreateSlideGenerator(
+ int width,
+ int height,
+ int frame_repeat_count,
+ int target_fps,
+ Clock* clock) {
+ std::unique_ptr<FrameGeneratorCapturer> capturer(new FrameGeneratorCapturer(
+ clock, FrameGenerator::CreateSlideGenerator(width, height,
+ frame_repeat_count),
+ target_fps));
+ if (!capturer->Init())
+ return nullptr;
+
+ return capturer.release();
+}
+
+FrameGeneratorCapturer::FrameGeneratorCapturer(
+ Clock* clock,
+ std::unique_ptr<FrameGenerator> frame_generator,
+ int target_fps)
+ : clock_(clock),
+ sending_(false),
+ sink_(nullptr),
+ sink_wants_observer_(nullptr),
+ frame_generator_(std::move(frame_generator)),
+ target_fps_(target_fps),
+ first_frame_capture_time_(-1),
+ task_queue_("FrameGenCapQ",
+ rtc::TaskQueue::Priority::HIGH) {
+ RTC_DCHECK(frame_generator_);
+ RTC_DCHECK_GT(target_fps, 0);
+}
+
+FrameGeneratorCapturer::~FrameGeneratorCapturer() {
+ Stop();
+}
+
+void FrameGeneratorCapturer::SetFakeRotation(VideoRotation rotation) {
+ rtc::CritScope cs(&lock_);
+ fake_rotation_ = rotation;
+}
+
+bool FrameGeneratorCapturer::Init() {
+ // This check is added because frame_generator_ might be file based and should
+ // not crash because a file moved.
+ if (frame_generator_.get() == nullptr)
+ return false;
+
+ int framerate_fps = GetCurrentConfiguredFramerate();
+ task_queue_.PostDelayedTask(
+ std::unique_ptr<rtc::QueuedTask>(
+ new InsertFrameTask(this, 1000 / framerate_fps)),
+ 1000 / framerate_fps);
+
+ return true;
+}
+
+void FrameGeneratorCapturer::InsertFrame() {
+ rtc::CritScope cs(&lock_);
+ if (sending_) {
+ VideoFrame* frame = frame_generator_->NextFrame();
+ frame->set_timestamp_us(clock_->TimeInMicroseconds());
+ frame->set_ntp_time_ms(clock_->CurrentNtpInMilliseconds());
+ frame->set_rotation(fake_rotation_);
+ if (first_frame_capture_time_ == -1) {
+ first_frame_capture_time_ = frame->ntp_time_ms();
+ }
+
+ if (sink_) {
+ rtc::Optional<VideoFrame> out_frame = AdaptFrame(*frame);
+ if (out_frame)
+ sink_->OnFrame(*out_frame);
+ }
+ }
+}
+
+void FrameGeneratorCapturer::Start() {
+ rtc::CritScope cs(&lock_);
+ sending_ = true;
+}
+
+void FrameGeneratorCapturer::Stop() {
+ rtc::CritScope cs(&lock_);
+ sending_ = false;
+}
+
+void FrameGeneratorCapturer::ChangeResolution(size_t width, size_t height) {
+ rtc::CritScope cs(&lock_);
+ frame_generator_->ChangeResolution(width, height);
+}
+
+void FrameGeneratorCapturer::SetSinkWantsObserver(SinkWantsObserver* observer) {
+ rtc::CritScope cs(&lock_);
+ RTC_DCHECK(!sink_wants_observer_);
+ sink_wants_observer_ = observer;
+}
+
+void FrameGeneratorCapturer::AddOrUpdateSink(
+ rtc::VideoSinkInterface<VideoFrame>* sink,
+ const rtc::VideoSinkWants& wants) {
+ rtc::CritScope cs(&lock_);
+ RTC_CHECK(!sink_ || sink_ == sink);
+ sink_ = sink;
+ if (sink_wants_observer_)
+ sink_wants_observer_->OnSinkWantsChanged(sink, wants);
+
+ // Handle framerate within this class, just pass on resolution for possible
+ // adaptation.
+ rtc::VideoSinkWants resolution_wants = wants;
+ resolution_wants.max_framerate_fps = std::numeric_limits<int>::max();
+ VideoCapturer::AddOrUpdateSink(sink, resolution_wants);
+
+ // Ignore any requests for framerate higher than initially configured.
+ if (wants.max_framerate_fps < target_fps_) {
+ wanted_fps_.emplace(wants.max_framerate_fps);
+ } else {
+ wanted_fps_.reset();
+ }
+}
+
+void FrameGeneratorCapturer::RemoveSink(
+ rtc::VideoSinkInterface<VideoFrame>* sink) {
+ rtc::CritScope cs(&lock_);
+ RTC_CHECK(sink_ == sink);
+ sink_ = nullptr;
+}
+
+void FrameGeneratorCapturer::ForceFrame() {
+ // One-time non-repeating task,
+ // therefore repeat_interval_ms is 0 in InsertFrameTask()
+ task_queue_.PostTask(
+ std::unique_ptr<rtc::QueuedTask>(new InsertFrameTask(this, 0)));
+}
+
+int FrameGeneratorCapturer::GetCurrentConfiguredFramerate() {
+ rtc::CritScope cs(&lock_);
+ if (wanted_fps_ && *wanted_fps_ < target_fps_)
+ return *wanted_fps_;
+ return target_fps_;
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/frame_generator_capturer.h b/third_party/libwebrtc/webrtc/test/frame_generator_capturer.h
new file mode 100644
index 0000000000..3a3fe82431
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/frame_generator_capturer.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef TEST_FRAME_GENERATOR_CAPTURER_H_
+#define TEST_FRAME_GENERATOR_CAPTURER_H_
+
+#include <memory>
+#include <string>
+
+#include "api/video/video_frame.h"
+#include "rtc_base/criticalsection.h"
+#include "rtc_base/task_queue.h"
+#include "test/video_capturer.h"
+#include "typedefs.h" // NOLINT(build/include)
+
+namespace webrtc {
+
+class EventTimerWrapper;
+
+namespace test {
+
+class FrameGenerator;
+
+class FrameGeneratorCapturer : public VideoCapturer {
+ public:
+ class SinkWantsObserver {
+ public:
+ // OnSinkWantsChanged is called when FrameGeneratorCapturer::AddOrUpdateSink
+ // is called.
+ virtual void OnSinkWantsChanged(rtc::VideoSinkInterface<VideoFrame>* sink,
+ const rtc::VideoSinkWants& wants) = 0;
+
+ protected:
+ virtual ~SinkWantsObserver() {}
+ };
+
+ static FrameGeneratorCapturer* Create(int width,
+ int height,
+ int target_fps,
+ Clock* clock);
+
+ static FrameGeneratorCapturer* Create(int width,
+ int height,
+ int num_squares,
+ int target_fps,
+ Clock* clock);
+
+ static FrameGeneratorCapturer* CreateFromYuvFile(const std::string& file_name,
+ size_t width,
+ size_t height,
+ int target_fps,
+ Clock* clock);
+
+ static FrameGeneratorCapturer* CreateSlideGenerator(int width,
+ int height,
+ int frame_repeat_count,
+ int target_fps,
+ Clock* clock);
+ virtual ~FrameGeneratorCapturer();
+
+ void Start() override;
+ void Stop() override;
+ void ChangeResolution(size_t width, size_t height);
+
+ void SetSinkWantsObserver(SinkWantsObserver* observer);
+
+ void AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink,
+ const rtc::VideoSinkWants& wants) override;
+ void RemoveSink(rtc::VideoSinkInterface<VideoFrame>* sink) override;
+
+ void ForceFrame();
+ void SetFakeRotation(VideoRotation rotation);
+
+ int64_t first_frame_capture_time() const { return first_frame_capture_time_; }
+
+ FrameGeneratorCapturer(Clock* clock,
+ std::unique_ptr<FrameGenerator> frame_generator,
+ int target_fps);
+ bool Init();
+
+ private:
+ class InsertFrameTask;
+
+ void InsertFrame();
+ static bool Run(void* obj);
+ int GetCurrentConfiguredFramerate();
+
+ Clock* const clock_;
+ bool sending_;
+ rtc::VideoSinkInterface<VideoFrame>* sink_ RTC_GUARDED_BY(&lock_);
+ SinkWantsObserver* sink_wants_observer_ RTC_GUARDED_BY(&lock_);
+
+ rtc::CriticalSection lock_;
+ std::unique_ptr<FrameGenerator> frame_generator_;
+
+ int target_fps_ RTC_GUARDED_BY(&lock_);
+ rtc::Optional<int> wanted_fps_ RTC_GUARDED_BY(&lock_);
+ VideoRotation fake_rotation_ = kVideoRotation_0;
+
+ int64_t first_frame_capture_time_;
+ // Must be the last field, so it will be deconstructed first as tasks
+ // in the TaskQueue access other fields of the instance of this class.
+ rtc::TaskQueue task_queue_;
+};
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_FRAME_GENERATOR_CAPTURER_H_
diff --git a/third_party/libwebrtc/webrtc/test/frame_generator_unittest.cc b/third_party/libwebrtc/webrtc/test/frame_generator_unittest.cc
new file mode 100644
index 0000000000..ba4627dc3b
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/frame_generator_unittest.cc
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <stdio.h>
+
+#include <memory>
+#include <string>
+
+#include "test/frame_generator.h"
+#include "test/gtest.h"
+#include "test/testsupport/fileutils.h"
+
+namespace webrtc {
+namespace test {
+
+static const int kFrameWidth = 4;
+static const int kFrameHeight = 4;
+
+class FrameGeneratorTest : public ::testing::Test {
+ public:
+ void SetUp() override {
+ two_frame_filename_ =
+ test::TempFilename(test::OutputPath(), "2_frame_yuv_file");
+ one_frame_filename_ =
+ test::TempFilename(test::OutputPath(), "1_frame_yuv_file");
+
+ FILE* file = fopen(two_frame_filename_.c_str(), "wb");
+ WriteYuvFile(file, 0, 0, 0);
+ WriteYuvFile(file, 127, 127, 127);
+ fclose(file);
+ file = fopen(one_frame_filename_.c_str(), "wb");
+ WriteYuvFile(file, 255, 255, 255);
+ fclose(file);
+ }
+ void TearDown() override {
+ remove(one_frame_filename_.c_str());
+ remove(two_frame_filename_.c_str());
+ }
+
+ protected:
+ void WriteYuvFile(FILE* file, uint8_t y, uint8_t u, uint8_t v) {
+ assert(file);
+ std::unique_ptr<uint8_t[]> plane_buffer(new uint8_t[y_size]);
+ memset(plane_buffer.get(), y, y_size);
+ fwrite(plane_buffer.get(), 1, y_size, file);
+ memset(plane_buffer.get(), u, uv_size);
+ fwrite(plane_buffer.get(), 1, uv_size, file);
+ memset(plane_buffer.get(), v, uv_size);
+ fwrite(plane_buffer.get(), 1, uv_size, file);
+ }
+
+ void CheckFrameAndMutate(VideoFrame* frame, uint8_t y, uint8_t u, uint8_t v) {
+ // Check that frame is valid, has the correct color and timestamp are clean.
+ ASSERT_NE(nullptr, frame);
+ rtc::scoped_refptr<I420BufferInterface> i420_buffer =
+ frame->video_frame_buffer()->ToI420();
+ const uint8_t* buffer;
+ buffer = i420_buffer->DataY();
+ for (int i = 0; i < y_size; ++i)
+ ASSERT_EQ(y, buffer[i]);
+ buffer = i420_buffer->DataU();
+ for (int i = 0; i < uv_size; ++i)
+ ASSERT_EQ(u, buffer[i]);
+ buffer = i420_buffer->DataV();
+ for (int i = 0; i < uv_size; ++i)
+ ASSERT_EQ(v, buffer[i]);
+ EXPECT_EQ(0, frame->ntp_time_ms());
+ EXPECT_EQ(0, frame->render_time_ms());
+ EXPECT_EQ(0u, frame->timestamp());
+
+ // Mutate to something arbitrary non-zero.
+ frame->set_ntp_time_ms(11);
+ frame->set_timestamp_us(12);
+ frame->set_timestamp(13);
+ }
+
+ uint64_t Hash(VideoFrame* frame) {
+ // Generate a 64-bit hash from the frame's buffer.
+ uint64_t hash = 19;
+ rtc::scoped_refptr<I420BufferInterface> i420_buffer =
+ frame->video_frame_buffer()->ToI420();
+ const uint8_t* buffer = i420_buffer->DataY();
+ for (int i = 0; i < y_size; ++i) {
+ hash = (37 * hash) + buffer[i];
+ }
+ buffer = i420_buffer->DataU();
+ for (int i = 0; i < uv_size; ++i) {
+ hash = (37 * hash) + buffer[i];
+ }
+ buffer = i420_buffer->DataV();
+ for (int i = 0; i < uv_size; ++i) {
+ hash = (37 * hash) + buffer[i];
+ }
+ return hash;
+ }
+
+ std::string two_frame_filename_;
+ std::string one_frame_filename_;
+ const int y_size = kFrameWidth * kFrameHeight;
+ const int uv_size = ((kFrameHeight + 1) / 2) * ((kFrameWidth + 1) / 2);
+};
+
+TEST_F(FrameGeneratorTest, SingleFrameFile) {
+ std::unique_ptr<FrameGenerator> generator(FrameGenerator::CreateFromYuvFile(
+ std::vector<std::string>(1, one_frame_filename_), kFrameWidth,
+ kFrameHeight, 1));
+ CheckFrameAndMutate(generator->NextFrame(), 255, 255, 255);
+ CheckFrameAndMutate(generator->NextFrame(), 255, 255, 255);
+}
+
+TEST_F(FrameGeneratorTest, TwoFrameFile) {
+ std::unique_ptr<FrameGenerator> generator(FrameGenerator::CreateFromYuvFile(
+ std::vector<std::string>(1, two_frame_filename_), kFrameWidth,
+ kFrameHeight, 1));
+ CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
+ CheckFrameAndMutate(generator->NextFrame(), 127, 127, 127);
+ CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
+}
+
+TEST_F(FrameGeneratorTest, MultipleFrameFiles) {
+ std::vector<std::string> files;
+ files.push_back(two_frame_filename_);
+ files.push_back(one_frame_filename_);
+
+ std::unique_ptr<FrameGenerator> generator(
+ FrameGenerator::CreateFromYuvFile(files, kFrameWidth, kFrameHeight, 1));
+ CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
+ CheckFrameAndMutate(generator->NextFrame(), 127, 127, 127);
+ CheckFrameAndMutate(generator->NextFrame(), 255, 255, 255);
+ CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
+}
+
+TEST_F(FrameGeneratorTest, TwoFrameFileWithRepeat) {
+ const int kRepeatCount = 3;
+ std::unique_ptr<FrameGenerator> generator(FrameGenerator::CreateFromYuvFile(
+ std::vector<std::string>(1, two_frame_filename_), kFrameWidth,
+ kFrameHeight, kRepeatCount));
+ for (int i = 0; i < kRepeatCount; ++i)
+ CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
+ for (int i = 0; i < kRepeatCount; ++i)
+ CheckFrameAndMutate(generator->NextFrame(), 127, 127, 127);
+ CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
+}
+
+TEST_F(FrameGeneratorTest, MultipleFrameFilesWithRepeat) {
+ const int kRepeatCount = 3;
+ std::vector<std::string> files;
+ files.push_back(two_frame_filename_);
+ files.push_back(one_frame_filename_);
+ std::unique_ptr<FrameGenerator> generator(FrameGenerator::CreateFromYuvFile(
+ files, kFrameWidth, kFrameHeight, kRepeatCount));
+ for (int i = 0; i < kRepeatCount; ++i)
+ CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
+ for (int i = 0; i < kRepeatCount; ++i)
+ CheckFrameAndMutate(generator->NextFrame(), 127, 127, 127);
+ for (int i = 0; i < kRepeatCount; ++i)
+ CheckFrameAndMutate(generator->NextFrame(), 255, 255, 255);
+ CheckFrameAndMutate(generator->NextFrame(), 0, 0, 0);
+}
+
+TEST_F(FrameGeneratorTest, SlideGenerator) {
+ const int kGenCount = 9;
+ const int kRepeatCount = 3;
+ std::unique_ptr<FrameGenerator> generator(
+ FrameGenerator::CreateSlideGenerator(
+ kFrameWidth, kFrameHeight, kRepeatCount));
+ uint64_t hashes[kGenCount];
+ for (int i = 0; i < kGenCount; ++i) {
+ hashes[i] = Hash(generator->NextFrame());
+ }
+ // Check that the buffer changes only every |kRepeatCount| frames.
+ for (int i = 1; i < kGenCount; ++i) {
+ if (i % kRepeatCount == 0) {
+ EXPECT_NE(hashes[i-1], hashes[i]);
+ } else {
+ EXPECT_EQ(hashes[i-1], hashes[i]);
+ }
+ }
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/frame_utils.cc b/third_party/libwebrtc/webrtc/test/frame_utils.cc
new file mode 100644
index 0000000000..1d5fe7c8f4
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/frame_utils.cc
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+#include "api/video/i420_buffer.h"
+#include "api/video/video_frame.h"
+#include "test/frame_utils.h"
+
+namespace webrtc {
+namespace test {
+
+bool EqualPlane(const uint8_t* data1,
+ const uint8_t* data2,
+ int stride1,
+ int stride2,
+ int width,
+ int height) {
+ for (int y = 0; y < height; ++y) {
+ if (memcmp(data1, data2, width) != 0)
+ return false;
+ data1 += stride1;
+ data2 += stride2;
+ }
+ return true;
+}
+
+bool FramesEqual(const webrtc::VideoFrame& f1, const webrtc::VideoFrame& f2) {
+ if (f1.timestamp() != f2.timestamp() ||
+ f1.ntp_time_ms() != f2.ntp_time_ms() ||
+ f1.render_time_ms() != f2.render_time_ms()) {
+ return false;
+ }
+ return FrameBufsEqual(f1.video_frame_buffer(), f2.video_frame_buffer());
+}
+
+bool FrameBufsEqual(const rtc::scoped_refptr<webrtc::VideoFrameBuffer>& f1,
+ const rtc::scoped_refptr<webrtc::VideoFrameBuffer>& f2) {
+ if (f1 == f2) {
+ return true;
+ }
+ // Exlude nullptr (except if both are nullptr, as above)
+ if (!f1 || !f2) {
+ return false;
+ }
+
+ if (f1->width() != f2->width() || f1->height() != f2->height() ||
+ f1->type() != f2->type()) {
+ return false;
+ }
+
+ rtc::scoped_refptr<webrtc::I420BufferInterface> f1_i420 = f1->ToI420();
+ rtc::scoped_refptr<webrtc::I420BufferInterface> f2_i420 = f2->ToI420();
+ return EqualPlane(f1_i420->DataY(), f2_i420->DataY(),
+ f1_i420->StrideY(), f2_i420->StrideY(),
+ f1_i420->width(), f1_i420->height()) &&
+ EqualPlane(f1_i420->DataU(), f2_i420->DataU(),
+ f1_i420->StrideU(), f2_i420->StrideU(),
+ f1_i420->ChromaWidth(), f1_i420->ChromaHeight()) &&
+ EqualPlane(f1_i420->DataV(), f2_i420->DataV(),
+ f1_i420->StrideV(), f2_i420->StrideV(),
+ f1_i420->ChromaWidth(), f1_i420->ChromaHeight());
+}
+
+rtc::scoped_refptr<I420Buffer> ReadI420Buffer(int width, int height, FILE *f) {
+ int half_width = (width + 1) / 2;
+ rtc::scoped_refptr<I420Buffer> buffer(
+ // Explicit stride, no padding between rows.
+ I420Buffer::Create(width, height, width, half_width, half_width));
+ size_t size_y = static_cast<size_t>(width) * height;
+ size_t size_uv = static_cast<size_t>(half_width) * ((height + 1) / 2);
+
+ if (fread(buffer->MutableDataY(), 1, size_y, f) < size_y)
+ return nullptr;
+ if (fread(buffer->MutableDataU(), 1, size_uv, f) < size_uv)
+ return nullptr;
+ if (fread(buffer->MutableDataV(), 1, size_uv, f) < size_uv)
+ return nullptr;
+ return buffer;
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/frame_utils.h b/third_party/libwebrtc/webrtc/test/frame_utils.h
new file mode 100644
index 0000000000..80466e1c29
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/frame_utils.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef TEST_FRAME_UTILS_H_
+#define TEST_FRAME_UTILS_H_
+
+#include <stdint.h>
+
+#include "rtc_base/scoped_ref_ptr.h"
+
+namespace webrtc {
+class I420Buffer;
+class VideoFrame;
+class VideoFrameBuffer;
+namespace test {
+
+bool EqualPlane(const uint8_t* data1,
+ const uint8_t* data2,
+ int stride1,
+ int stride2,
+ int width,
+ int height);
+
+static inline bool EqualPlane(const uint8_t* data1,
+ const uint8_t* data2,
+ int stride,
+ int width,
+ int height) {
+ return EqualPlane(data1, data2, stride, stride, width, height);
+}
+
+bool FramesEqual(const webrtc::VideoFrame& f1, const webrtc::VideoFrame& f2);
+
+bool FrameBufsEqual(const rtc::scoped_refptr<webrtc::VideoFrameBuffer>& f1,
+ const rtc::scoped_refptr<webrtc::VideoFrameBuffer>& f2);
+
+rtc::scoped_refptr<I420Buffer> ReadI420Buffer(int width, int height, FILE *);
+
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_FRAME_UTILS_H_
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/BUILD.gn b/third_party/libwebrtc/webrtc/test/fuzzers/BUILD.gn
new file mode 100644
index 0000000000..8a1cb97df2
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/BUILD.gn
@@ -0,0 +1,411 @@
+# Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+#
+# Use of this source code is governed by a BSD-style license
+# that can be found in the LICENSE file in the root of the source
+# tree. An additional intellectual property rights grant can be found
+# in the file PATENTS. All contributing project authors may
+# be found in the AUTHORS file in the root of the source tree.
+
+import("../../webrtc.gni")
+import("//build/config/features.gni")
+import("//testing/libfuzzer/fuzzer_test.gni")
+
+rtc_static_library("webrtc_fuzzer_main") {
+ sources = [
+ "webrtc_fuzzer_main.cc",
+ ]
+ deps = [
+ "../../rtc_base:rtc_base_approved",
+ "../../system_wrappers:field_trial_default",
+ "../../system_wrappers:metrics_default",
+ "//testing/libfuzzer:libfuzzer_main",
+ ]
+}
+
+template("webrtc_fuzzer_test") {
+ fuzzer_test(target_name) {
+ forward_variables_from(invoker, "*")
+ deps += [
+ ":webrtc_fuzzer_main",
+
+ # Link unconditionally with webrtc's TaskQueue, regardless of
+ # rtc_link_task_queue_impl flag.
+ "../../rtc_base:rtc_task_queue_impl",
+ ]
+ if (!build_with_chromium && is_clang) {
+ # Suppress warnings from the Chromium Clang plugin (bugs.webrtc.org/163).
+ suppressed_configs = [ "//build/config/clang:find_bad_constructs" ]
+ }
+ }
+}
+
+webrtc_fuzzer_test("h264_depacketizer_fuzzer") {
+ sources = [
+ "h264_depacketizer_fuzzer.cc",
+ ]
+ deps = [
+ "../../modules/rtp_rtcp",
+ ]
+}
+
+webrtc_fuzzer_test("vp8_depacketizer_fuzzer") {
+ sources = [
+ "vp8_depacketizer_fuzzer.cc",
+ ]
+ deps = [
+ "../../modules/rtp_rtcp",
+ ]
+}
+
+webrtc_fuzzer_test("vp9_depacketizer_fuzzer") {
+ sources = [
+ "vp9_depacketizer_fuzzer.cc",
+ ]
+ deps = [
+ "../../modules/rtp_rtcp",
+ ]
+}
+
+webrtc_fuzzer_test("vp8_qp_parser_fuzzer") {
+ sources = [
+ "vp8_qp_parser_fuzzer.cc",
+ ]
+ deps = [
+ "../../modules/video_coding:video_coding_utility",
+ "../../modules/video_coding/",
+ ]
+}
+
+webrtc_fuzzer_test("vp9_qp_parser_fuzzer") {
+ sources = [
+ "vp9_qp_parser_fuzzer.cc",
+ ]
+ deps = [
+ "../../modules/video_coding:video_coding_utility",
+ "../../modules/video_coding/",
+ ]
+}
+
+webrtc_fuzzer_test("h264_bitstream_parser_fuzzer") {
+ sources = [
+ "h264_bitstream_parser_fuzzer.cc",
+ ]
+ deps = [
+ "../../common_video",
+ "../../modules/video_coding/",
+ ]
+}
+
+webrtc_fuzzer_test("flexfec_header_reader_fuzzer") {
+ sources = [
+ "flexfec_header_reader_fuzzer.cc",
+ ]
+ deps = [
+ "../../modules/rtp_rtcp",
+ "../../rtc_base:rtc_base_approved",
+ ]
+}
+
+webrtc_fuzzer_test("flexfec_sender_fuzzer") {
+ sources = [
+ "flexfec_sender_fuzzer.cc",
+ ]
+ deps = [
+ "../../modules/rtp_rtcp",
+ "../../system_wrappers",
+ ]
+ libfuzzer_options = [ "max_len=200" ]
+}
+
+webrtc_fuzzer_test("ulpfec_header_reader_fuzzer") {
+ sources = [
+ "ulpfec_header_reader_fuzzer.cc",
+ ]
+ deps = [
+ "../../modules/rtp_rtcp",
+ "../../modules/rtp_rtcp:fec_test_helper",
+ "../../rtc_base:rtc_base_approved",
+ ]
+}
+
+webrtc_fuzzer_test("ulpfec_generator_fuzzer") {
+ sources = [
+ "ulpfec_generator_fuzzer.cc",
+ ]
+ deps = [
+ "../../modules/rtp_rtcp",
+ "../../modules/rtp_rtcp:fec_test_helper",
+ "../../rtc_base:rtc_base_approved",
+ ]
+}
+
+webrtc_fuzzer_test("ulpfec_receiver_fuzzer") {
+ sources = [
+ "ulpfec_receiver_fuzzer.cc",
+ ]
+ deps = [
+ "../../modules/rtp_rtcp",
+ "../../rtc_base:rtc_base_approved",
+ ]
+ libfuzzer_options = [ "max_len=2000" ]
+}
+
+webrtc_fuzzer_test("flexfec_receiver_fuzzer") {
+ sources = [
+ "flexfec_receiver_fuzzer.cc",
+ ]
+ deps = [
+ "../../modules/rtp_rtcp",
+ "../../rtc_base:rtc_base_approved",
+ ]
+ libfuzzer_options = [ "max_len=2000" ]
+}
+
+webrtc_fuzzer_test("packet_buffer_fuzzer") {
+ sources = [
+ "packet_buffer_fuzzer.cc",
+ ]
+ deps = [
+ "../../modules/video_coding/",
+ "../../system_wrappers",
+ ]
+ libfuzzer_options = [ "max_len=2000" ]
+}
+
+webrtc_fuzzer_test("rtcp_receiver_fuzzer") {
+ sources = [
+ "rtcp_receiver_fuzzer.cc",
+ ]
+ deps = [
+ "../../modules/rtp_rtcp",
+ "../../rtc_base:rtc_base_approved",
+ "../../system_wrappers:system_wrappers",
+ ]
+ seed_corpus = "corpora/rtcp-corpus"
+}
+
+webrtc_fuzzer_test("rtp_packet_fuzzer") {
+ sources = [
+ "rtp_packet_fuzzer.cc",
+ ]
+ deps = [
+ "../../modules/rtp_rtcp",
+ ]
+ seed_corpus = "corpora/rtp-corpus"
+}
+
+webrtc_fuzzer_test("rtp_header_fuzzer") {
+ sources = [
+ "rtp_header_fuzzer.cc",
+ ]
+ deps = [
+ "../../modules/rtp_rtcp",
+ ]
+}
+
+webrtc_fuzzer_test("congestion_controller_feedback_fuzzer") {
+ sources = [
+ "congestion_controller_feedback_fuzzer.cc",
+ ]
+ deps = [
+ "../../logging:rtc_event_log_api",
+ "../../logging:rtc_event_log_impl",
+ "../../modules/congestion_controller",
+ "../../modules/pacing",
+ "../../modules/remote_bitrate_estimator:remote_bitrate_estimator",
+ "../../modules/rtp_rtcp",
+ ]
+}
+
+rtc_static_library("audio_decoder_fuzzer") {
+ sources = [
+ "audio_decoder_fuzzer.cc",
+ "audio_decoder_fuzzer.h",
+ ]
+ deps = [
+ "../..:webrtc_common",
+ "../../api:optional",
+ "../../api/audio_codecs:audio_codecs_api",
+ "../../modules/rtp_rtcp",
+ "../../rtc_base:rtc_base_approved",
+ ]
+}
+
+webrtc_fuzzer_test("audio_decoder_ilbc_fuzzer") {
+ sources = [
+ "audio_decoder_ilbc_fuzzer.cc",
+ ]
+ deps = [
+ ":audio_decoder_fuzzer",
+ "../../modules/audio_coding:ilbc",
+ ]
+}
+
+webrtc_fuzzer_test("audio_decoder_isac_fuzzer") {
+ sources = [
+ "audio_decoder_isac_fuzzer.cc",
+ ]
+ deps = [
+ ":audio_decoder_fuzzer",
+ "../../modules/audio_coding:isac",
+ ]
+}
+
+webrtc_fuzzer_test("audio_decoder_isac_incoming_packet_fuzzer") {
+ sources = [
+ "audio_decoder_isac_incoming_packet_fuzzer.cc",
+ ]
+ deps = [
+ ":audio_decoder_fuzzer",
+ "../../modules/audio_coding:isac",
+ ]
+}
+
+webrtc_fuzzer_test("audio_decoder_isacfix_fuzzer") {
+ sources = [
+ "audio_decoder_isacfix_fuzzer.cc",
+ ]
+ deps = [
+ ":audio_decoder_fuzzer",
+ "../../modules/audio_coding:isac_fix",
+ ]
+}
+
+webrtc_fuzzer_test("audio_decoder_opus_fuzzer") {
+ sources = [
+ "audio_decoder_opus_fuzzer.cc",
+ ]
+ deps = [
+ ":audio_decoder_fuzzer",
+ "../../modules/audio_coding:webrtc_opus",
+ ]
+}
+
+webrtc_fuzzer_test("audio_decoder_opus_redundant_fuzzer") {
+ sources = [
+ "audio_decoder_opus_redundant_fuzzer.cc",
+ ]
+ deps = [
+ ":audio_decoder_fuzzer",
+ "../../modules/audio_coding:webrtc_opus",
+ ]
+}
+
+webrtc_fuzzer_test("turn_unwrap_fuzzer") {
+ sources = [
+ "turn_unwrap_fuzzer.cc",
+ ]
+ deps = [
+ "../../media:media",
+ ]
+}
+
+webrtc_fuzzer_test("neteq_rtp_fuzzer") {
+ sources = [
+ "neteq_rtp_fuzzer.cc",
+ ]
+ deps = [
+ "../../api:array_view",
+ "../../modules/audio_coding:neteq",
+ "../../modules/audio_coding:neteq_test_tools",
+ "../../modules/audio_coding:neteq_tools_minimal",
+ "../../modules/audio_coding:pcm16b",
+ "../../modules/rtp_rtcp",
+ "../../rtc_base:rtc_base_approved",
+ "../../rtc_base:rtc_base_tests_utils",
+ ]
+}
+
+webrtc_fuzzer_test("neteq_signal_fuzzer") {
+ sources = [
+ "neteq_signal_fuzzer.cc",
+ ]
+ deps = [
+ "../../api:array_view",
+ "../../modules/audio_coding:neteq",
+ "../../modules/audio_coding:neteq_test_tools",
+ "../../modules/audio_coding:neteq_tools_minimal",
+ "../../modules/audio_coding:pcm16b",
+ "../../modules/rtp_rtcp",
+ "../../rtc_base:rtc_base_approved",
+ "../../rtc_base:rtc_base_tests_utils",
+ ]
+}
+
+webrtc_fuzzer_test("residual_echo_detector_fuzzer") {
+ sources = [
+ "residual_echo_detector_fuzzer.cc",
+ ]
+ deps = [
+ "../../modules/audio_processing:audio_processing",
+ "../../rtc_base:rtc_base_approved",
+ ]
+}
+
+webrtc_fuzzer_test("sdp_parser_fuzzer") {
+ sources = [
+ "sdp_parser_fuzzer.cc",
+ ]
+ deps = [
+ "../../pc:libjingle_peerconnection",
+ ]
+ seed_corpus = "corpora/sdp-corpus"
+}
+
+webrtc_fuzzer_test("stun_parser_fuzzer") {
+ sources = [
+ "stun_parser_fuzzer.cc",
+ ]
+ deps = [
+ "../../p2p:rtc_p2p",
+ ]
+ seed_corpus = "corpora/stun-corpus"
+ dict = "corpora/stun.tokens"
+}
+
+webrtc_fuzzer_test("stun_validator_fuzzer") {
+ sources = [
+ "stun_validator_fuzzer.cc",
+ ]
+ deps = [
+ "../../p2p:rtc_p2p",
+ ]
+ seed_corpus = "corpora/stun-corpus"
+ dict = "corpora/stun.tokens"
+}
+
+webrtc_fuzzer_test("pseudotcp_parser_fuzzer") {
+ sources = [
+ "pseudotcp_parser_fuzzer.cc",
+ ]
+ deps = [
+ "../../p2p:rtc_p2p",
+ "../../rtc_base:rtc_base",
+ ]
+}
+
+webrtc_fuzzer_test("transport_feedback_packet_loss_tracker_fuzzer") {
+ sources = [
+ "transport_feedback_packet_loss_tracker_fuzzer.cc",
+ ]
+ deps = [
+ "../../api:array_view",
+ "../../modules/rtp_rtcp",
+ "../../rtc_base:rtc_base_approved",
+ "../../voice_engine",
+ ]
+}
+
+webrtc_fuzzer_test("audio_processing_fuzzer") {
+ sources = [
+ "audio_processing_fuzzer.cc",
+ "audio_processing_fuzzer.h",
+ "audio_processing_fuzzer_configs.cc",
+ ]
+ deps = [
+ "../../api:optional",
+ "../../modules:module_api",
+ "../../modules/audio_processing",
+ "../../rtc_base:rtc_base_approved",
+ ]
+}
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/DEPS b/third_party/libwebrtc/webrtc/test/fuzzers/DEPS
new file mode 100644
index 0000000000..cdbb5660e9
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/DEPS
@@ -0,0 +1,3 @@
+include_rules = [
+ "+webrtc",
+]
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/OWNERS b/third_party/libwebrtc/webrtc/test/fuzzers/OWNERS
new file mode 100644
index 0000000000..6e7454380e
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/OWNERS
@@ -0,0 +1 @@
+henrik.lundin@webrtc.org
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/audio_decoder_fuzzer.cc b/third_party/libwebrtc/webrtc/test/fuzzers/audio_decoder_fuzzer.cc
new file mode 100644
index 0000000000..f6ac4cb0bb
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/audio_decoder_fuzzer.cc
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/fuzzers/audio_decoder_fuzzer.h"
+
+#include <limits>
+
+#include "api/audio_codecs/audio_decoder.h"
+#include "api/optional.h"
+#include "modules/rtp_rtcp/source/byte_io.h"
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+namespace {
+template <typename T, unsigned int B = sizeof(T)>
+bool ParseInt(const uint8_t** data, size_t* remaining_size, T* value) {
+ static_assert(std::numeric_limits<T>::is_integer, "Type must be an integer.");
+ static_assert(sizeof(T) <= sizeof(uint64_t),
+ "Cannot read wider than uint64_t.");
+ static_assert(B <= sizeof(T), "T must be at least B bytes wide.");
+ if (B > *remaining_size)
+ return false;
+ uint64_t val = ByteReader<uint64_t, B>::ReadBigEndian(*data);
+ *data += B;
+ *remaining_size -= B;
+ *value = static_cast<T>(val);
+ return true;
+}
+} // namespace
+
+// This function reads two bytes from the beginning of |data|, interprets them
+// as the first packet length, and reads this many bytes if available. The
+// payload is inserted into the decoder, and the process continues until no more
+// data is available. Either AudioDecoder::Decode or
+// AudioDecoder::DecodeRedundant is used, depending on the value of
+// |decode_type|.
+void FuzzAudioDecoder(DecoderFunctionType decode_type,
+ const uint8_t* data,
+ size_t size,
+ AudioDecoder* decoder,
+ int sample_rate_hz,
+ size_t max_decoded_bytes,
+ int16_t* decoded) {
+ const uint8_t* data_ptr = data;
+ size_t remaining_size = size;
+ size_t packet_len;
+ while (ParseInt<size_t, 2>(&data_ptr, &remaining_size, &packet_len) &&
+ packet_len <= remaining_size) {
+ AudioDecoder::SpeechType speech_type;
+ switch (decode_type) {
+ case DecoderFunctionType::kNormalDecode:
+ decoder->Decode(data_ptr, packet_len, sample_rate_hz, max_decoded_bytes,
+ decoded, &speech_type);
+ break;
+ case DecoderFunctionType::kRedundantDecode:
+ decoder->DecodeRedundant(data_ptr, packet_len, sample_rate_hz,
+ max_decoded_bytes, decoded, &speech_type);
+ break;
+ }
+ data_ptr += packet_len;
+ remaining_size -= packet_len;
+ }
+}
+
+// This function is similar to FuzzAudioDecoder, but also reads fuzzed data into
+// RTP header values. The fuzzed data and values are sent to the decoder's
+// IncomingPacket method.
+void FuzzAudioDecoderIncomingPacket(const uint8_t* data,
+ size_t size,
+ AudioDecoder* decoder) {
+ const uint8_t* data_ptr = data;
+ size_t remaining_size = size;
+ size_t packet_len;
+ while (ParseInt<size_t, 2>(&data_ptr, &remaining_size, &packet_len)) {
+ uint16_t rtp_sequence_number;
+ if (!ParseInt(&data_ptr, &remaining_size, &rtp_sequence_number))
+ break;
+ uint32_t rtp_timestamp;
+ if (!ParseInt(&data_ptr, &remaining_size, &rtp_timestamp))
+ break;
+ uint32_t arrival_timestamp;
+ if (!ParseInt(&data_ptr, &remaining_size, &arrival_timestamp))
+ break;
+ if (remaining_size < packet_len)
+ break;
+ decoder->IncomingPacket(data_ptr, packet_len, rtp_sequence_number,
+ rtp_timestamp, arrival_timestamp);
+ data_ptr += packet_len;
+ remaining_size -= packet_len;
+ }
+}
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/audio_decoder_fuzzer.h b/third_party/libwebrtc/webrtc/test/fuzzers/audio_decoder_fuzzer.h
new file mode 100644
index 0000000000..504ecf6c02
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/audio_decoder_fuzzer.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef TEST_FUZZERS_AUDIO_DECODER_FUZZER_H_
+#define TEST_FUZZERS_AUDIO_DECODER_FUZZER_H_
+
+#include <stddef.h>
+
+#include "typedefs.h" // NOLINT(build/include)
+
+namespace webrtc {
+
+class AudioDecoder;
+
+enum class DecoderFunctionType {
+ kNormalDecode,
+ kRedundantDecode,
+};
+
+void FuzzAudioDecoder(DecoderFunctionType decode_type,
+ const uint8_t* data,
+ size_t size,
+ AudioDecoder* decoder,
+ int sample_rate_hz,
+ size_t max_decoded_bytes,
+ int16_t* decoded);
+
+void FuzzAudioDecoderIncomingPacket(const uint8_t* data,
+ size_t size,
+ AudioDecoder* decoder);
+} // namespace webrtc
+
+#endif // TEST_FUZZERS_AUDIO_DECODER_FUZZER_H_
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/audio_decoder_ilbc_fuzzer.cc b/third_party/libwebrtc/webrtc/test/fuzzers/audio_decoder_ilbc_fuzzer.cc
new file mode 100644
index 0000000000..a68725d6aa
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/audio_decoder_ilbc_fuzzer.cc
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/ilbc/audio_decoder_ilbc.h"
+#include "test/fuzzers/audio_decoder_fuzzer.h"
+
+namespace webrtc {
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ AudioDecoderIlbcImpl dec;
+ static const int kSampleRateHz = 8000;
+ static const size_t kAllocatedOuputSizeSamples = kSampleRateHz / 10;
+ int16_t output[kAllocatedOuputSizeSamples];
+ FuzzAudioDecoder(DecoderFunctionType::kNormalDecode, data, size, &dec,
+ kSampleRateHz, sizeof(output), output);
+}
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/audio_decoder_isac_fuzzer.cc b/third_party/libwebrtc/webrtc/test/fuzzers/audio_decoder_isac_fuzzer.cc
new file mode 100644
index 0000000000..e79996e05b
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/audio_decoder_isac_fuzzer.cc
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/main/include/audio_decoder_isac.h"
+#include "test/fuzzers/audio_decoder_fuzzer.h"
+
+namespace webrtc {
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ const int sample_rate_hz = size % 2 == 0 ? 16000 : 32000; // 16 or 32 kHz.
+ static const size_t kAllocatedOuputSizeSamples = 32000 / 10; // 100 ms.
+ int16_t output[kAllocatedOuputSizeSamples];
+ AudioDecoderIsacFloatImpl dec(sample_rate_hz);
+ FuzzAudioDecoder(DecoderFunctionType::kNormalDecode, data, size, &dec,
+ sample_rate_hz, sizeof(output), output);
+}
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/audio_decoder_isac_incoming_packet_fuzzer.cc b/third_party/libwebrtc/webrtc/test/fuzzers/audio_decoder_isac_incoming_packet_fuzzer.cc
new file mode 100644
index 0000000000..5645142a03
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/audio_decoder_isac_incoming_packet_fuzzer.cc
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/main/include/audio_decoder_isac.h"
+#include "test/fuzzers/audio_decoder_fuzzer.h"
+
+namespace webrtc {
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ AudioDecoderIsacFloatImpl dec(16000);
+ FuzzAudioDecoderIncomingPacket(data, size, &dec);
+}
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/audio_decoder_isacfix_fuzzer.cc b/third_party/libwebrtc/webrtc/test/fuzzers/audio_decoder_isacfix_fuzzer.cc
new file mode 100644
index 0000000000..444395b17d
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/audio_decoder_isacfix_fuzzer.cc
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/isac/fix/include/audio_decoder_isacfix.h"
+#include "test/fuzzers/audio_decoder_fuzzer.h"
+
+namespace webrtc {
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ static const int kSampleRateHz = 16000;
+ static const size_t kAllocatedOuputSizeSamples = 16000 / 10; // 100 ms.
+ int16_t output[kAllocatedOuputSizeSamples];
+ AudioDecoderIsacFixImpl dec(kSampleRateHz);
+ FuzzAudioDecoder(DecoderFunctionType::kNormalDecode, data, size, &dec,
+ kSampleRateHz, sizeof(output), output);
+}
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/audio_decoder_opus_fuzzer.cc b/third_party/libwebrtc/webrtc/test/fuzzers/audio_decoder_opus_fuzzer.cc
new file mode 100644
index 0000000000..a015f98b5b
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/audio_decoder_opus_fuzzer.cc
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/opus/audio_decoder_opus.h"
+#include "test/fuzzers/audio_decoder_fuzzer.h"
+
+namespace webrtc {
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ const size_t channels = (size % 2) + 1; // 1 or 2 channels.
+ AudioDecoderOpusImpl dec(channels);
+ const int kSampleRateHz = 48000;
+ const size_t kAllocatedOuputSizeSamples = kSampleRateHz / 10; // 100 ms.
+ int16_t output[kAllocatedOuputSizeSamples];
+ FuzzAudioDecoder(DecoderFunctionType::kNormalDecode, data, size, &dec,
+ kSampleRateHz, sizeof(output), output);
+}
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/audio_decoder_opus_redundant_fuzzer.cc b/third_party/libwebrtc/webrtc/test/fuzzers/audio_decoder_opus_redundant_fuzzer.cc
new file mode 100644
index 0000000000..efcba0f35d
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/audio_decoder_opus_redundant_fuzzer.cc
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_coding/codecs/opus/audio_decoder_opus.h"
+#include "test/fuzzers/audio_decoder_fuzzer.h"
+
+namespace webrtc {
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ const size_t channels = (size % 2) + 1; // 1 or 2 channels.
+ AudioDecoderOpusImpl dec(channels);
+ const int kSampleRateHz = 48000;
+ const size_t kAllocatedOuputSizeSamples = kSampleRateHz / 10; // 100 ms.
+ int16_t output[kAllocatedOuputSizeSamples];
+ FuzzAudioDecoder(DecoderFunctionType::kRedundantDecode, data, size, &dec,
+ kSampleRateHz, sizeof(output), output);
+}
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/audio_processing_fuzzer.cc b/third_party/libwebrtc/webrtc/test/fuzzers/audio_processing_fuzzer.cc
new file mode 100644
index 0000000000..a44d446096
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/audio_processing_fuzzer.cc
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/fuzzers/audio_processing_fuzzer.h"
+
+#include <algorithm>
+#include <array>
+#include <cmath>
+
+#include "modules/audio_processing/include/audio_processing.h"
+#include "modules/include/module_common_types.h"
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+namespace {
+size_t ByteToNativeRate(uint8_t data) {
+ using Rate = AudioProcessing::NativeRate;
+ switch (data % 4) {
+ case 0:
+ return static_cast<size_t>(Rate::kSampleRate8kHz);
+ case 1:
+ return static_cast<size_t>(Rate::kSampleRate16kHz);
+ case 2:
+ return static_cast<size_t>(Rate::kSampleRate32kHz);
+ default:
+ return static_cast<size_t>(Rate::kSampleRate48kHz);
+ }
+}
+
+template <class T>
+bool ParseSequence(size_t size,
+ const uint8_t** data,
+ size_t* remaining_size,
+ T* result_data) {
+ const size_t data_size_bytes = sizeof(T) * size;
+ if (data_size_bytes > *remaining_size) {
+ return false;
+ }
+
+ std::copy(*data, *data + data_size_bytes,
+ reinterpret_cast<uint8_t*>(result_data));
+
+ *data += data_size_bytes;
+ *remaining_size -= data_size_bytes;
+ return true;
+}
+
+void FuzzAudioProcessing(const uint8_t* data,
+ size_t size,
+ bool is_float,
+ AudioProcessing* apm) {
+ AudioFrame fixed_frame;
+ std::array<float, 480> float_frame{};
+ float* const first_channel = &float_frame[0];
+
+ while (size > 0) {
+ // Decide input/output rate for this iteration.
+ const auto input_rate_byte = ParseByte(&data, &size);
+ const auto output_rate_byte = ParseByte(&data, &size);
+ if (!input_rate_byte || !output_rate_byte) {
+ return;
+ }
+ const auto input_rate_hz = ByteToNativeRate(*input_rate_byte);
+ const auto output_rate_hz = ByteToNativeRate(*output_rate_byte);
+
+ const size_t samples_per_input_channel =
+ rtc::CheckedDivExact(input_rate_hz, 100ul);
+ fixed_frame.samples_per_channel_ = samples_per_input_channel;
+ fixed_frame.sample_rate_hz_ = input_rate_hz;
+
+ // Two channels breaks AEC3.
+ fixed_frame.num_channels_ = 1;
+
+ // Fill the arrays with audio samples from the data.
+ if (is_float) {
+ if (!ParseSequence(samples_per_input_channel, &data, &size,
+ &float_frame[0])) {
+ return;
+ }
+ } else if (!ParseSequence(samples_per_input_channel, &data, &size,
+ fixed_frame.mutable_data())) {
+ return;
+ }
+
+ // Filter obviously wrong values like inf/nan and values that will
+ // lead to inf/nan in calculations. 1e6 leads to DCHECKS failing.
+ for (auto& x : float_frame) {
+ if (!std::isnormal(x) || std::abs(x) > 1e5) {
+ x = 0;
+ }
+ }
+
+ // Make the APM call depending on capture/render mode and float /
+ // fix interface.
+ const auto is_capture = ParseBool(&data, &size);
+ if (!is_capture) {
+ return;
+ }
+ if (*is_capture) {
+ auto apm_return_code =
+ is_float ? (apm->ProcessStream(
+ &first_channel, StreamConfig(input_rate_hz, 1),
+ StreamConfig(output_rate_hz, 1), &first_channel))
+ : (apm->ProcessStream(&fixed_frame));
+ RTC_DCHECK_NE(apm_return_code, AudioProcessing::kBadDataLengthError);
+ } else {
+ auto apm_return_code =
+ is_float ? (apm->ProcessReverseStream(
+ &first_channel, StreamConfig(input_rate_hz, 1),
+ StreamConfig(output_rate_hz, 1), &first_channel))
+ : (apm->ProcessReverseStream(&fixed_frame));
+ RTC_DCHECK_NE(apm_return_code, AudioProcessing::kBadDataLengthError);
+ }
+ }
+}
+
+} // namespace
+
+rtc::Optional<bool> ParseBool(const uint8_t** data, size_t* remaining_size) {
+ if (1 > *remaining_size) {
+ return rtc::nullopt;
+ }
+ auto res = (**data) % 2;
+ *data += 1;
+ *remaining_size -= 1;
+ return res;
+}
+
+rtc::Optional<uint8_t> ParseByte(const uint8_t** data, size_t* remaining_size) {
+ if (1 > *remaining_size) {
+ return rtc::nullopt;
+ }
+ auto res = **data;
+ *data += 1;
+ *remaining_size -= 1;
+ return res;
+}
+
+void FuzzAudioProcessing(const uint8_t* data,
+ size_t size,
+ std::unique_ptr<AudioProcessing> apm) {
+ const auto is_float = ParseBool(&data, &size);
+ if (!is_float) {
+ return;
+ }
+
+ FuzzAudioProcessing(data, size, *is_float, apm.get());
+}
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/audio_processing_fuzzer.h b/third_party/libwebrtc/webrtc/test/fuzzers/audio_processing_fuzzer.h
new file mode 100644
index 0000000000..337d9b215d
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/audio_processing_fuzzer.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef TEST_FUZZERS_AUDIO_PROCESSING_FUZZER_H_
+#define TEST_FUZZERS_AUDIO_PROCESSING_FUZZER_H_
+
+#include <memory>
+
+#include "modules/audio_processing/include/audio_processing.h"
+namespace webrtc {
+
+rtc::Optional<bool> ParseBool(const uint8_t** data, size_t* remaining_size);
+rtc::Optional<uint8_t> ParseByte(const uint8_t** data, size_t* remaining_size);
+
+void FuzzAudioProcessing(const uint8_t* data,
+ size_t size,
+ std::unique_ptr<AudioProcessing> apm);
+} // namespace webrtc
+
+#endif // TEST_FUZZERS_AUDIO_PROCESSING_FUZZER_H_
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/audio_processing_fuzzer_configs.cc b/third_party/libwebrtc/webrtc/test/fuzzers/audio_processing_fuzzer_configs.cc
new file mode 100644
index 0000000000..15e0beeba9
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/audio_processing_fuzzer_configs.cc
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/audio_processing/include/audio_processing.h"
+#include "test/fuzzers/audio_processing_fuzzer.h"
+
+#include "api/optional.h"
+
+namespace webrtc {
+
+std::unique_ptr<AudioProcessing> CreateAPM(const uint8_t** data,
+ size_t* remaining_size) {
+ // Parse boolean values for optionally enabling different
+ // configurable public components of APM.
+ auto exp_agc = ParseBool(data, remaining_size);
+ auto exp_ns = ParseBool(data, remaining_size);
+ auto bf = ParseBool(data, remaining_size);
+ auto ef = ParseBool(data, remaining_size);
+ auto raf = ParseBool(data, remaining_size);
+ auto da = ParseBool(data, remaining_size);
+ auto ie = ParseBool(data, remaining_size);
+ auto red = ParseBool(data, remaining_size);
+ auto lc = ParseBool(data, remaining_size);
+ auto hpf = ParseBool(data, remaining_size);
+ auto aec3 = ParseBool(data, remaining_size);
+
+ auto use_aec = ParseBool(data, remaining_size);
+ auto use_aecm = ParseBool(data, remaining_size);
+ auto use_agc = ParseBool(data, remaining_size);
+ auto use_ns = ParseBool(data, remaining_size);
+ auto use_le = ParseBool(data, remaining_size);
+ auto use_vad = ParseBool(data, remaining_size);
+ auto use_agc_limiter = ParseBool(data, remaining_size);
+
+ if (!(exp_agc && exp_ns && bf && ef && raf && da && ie && red && lc && hpf &&
+ aec3 && use_aec && use_aecm && use_agc && use_ns && use_le && use_vad &&
+ use_agc_limiter)) {
+ return nullptr;
+ }
+
+ // Filter out incompatible settings that lead to CHECK failures.
+ if (*use_aecm && *use_aec) {
+ return nullptr;
+ }
+
+ // Components can be enabled through webrtc::Config and
+ // webrtc::AudioProcessingConfig.
+ Config config;
+
+ std::unique_ptr<EchoControlFactory> echo_control_factory;
+ if (*aec3) {
+ echo_control_factory.reset(new EchoCanceller3Factory());
+ }
+
+ config.Set<ExperimentalAgc>(new ExperimentalAgc(*exp_agc));
+ config.Set<ExperimentalNs>(new ExperimentalNs(*exp_ns));
+ if (*bf) {
+ config.Set<Beamforming>(new Beamforming());
+ }
+ config.Set<ExtendedFilter>(new ExtendedFilter(*ef));
+ config.Set<RefinedAdaptiveFilter>(new RefinedAdaptiveFilter(*raf));
+ config.Set<DelayAgnostic>(new DelayAgnostic(*da));
+ config.Set<Intelligibility>(new Intelligibility(*ie));
+
+ std::unique_ptr<AudioProcessing> apm(AudioProcessing::Create(
+ config, nullptr, std::move(echo_control_factory), nullptr));
+
+ webrtc::AudioProcessing::Config apm_config;
+ apm_config.residual_echo_detector.enabled = *red;
+ apm_config.level_controller.enabled = *lc;
+ apm_config.high_pass_filter.enabled = *hpf;
+
+ apm->ApplyConfig(apm_config);
+
+ apm->echo_cancellation()->Enable(*use_aec);
+ apm->echo_control_mobile()->Enable(*use_aecm);
+ apm->gain_control()->Enable(*use_agc);
+ apm->noise_suppression()->Enable(*use_ns);
+ apm->level_estimator()->Enable(*use_le);
+ apm->voice_detection()->Enable(*use_vad);
+ apm->gain_control()->enable_limiter(*use_agc_limiter);
+
+ return apm;
+}
+
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ auto apm = CreateAPM(&data, &size);
+ if (apm) {
+ FuzzAudioProcessing(data, size, std::move(apm));
+ }
+}
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/congestion_controller_feedback_fuzzer.cc b/third_party/libwebrtc/webrtc/test/fuzzers/congestion_controller_feedback_fuzzer.cc
new file mode 100644
index 0000000000..084c8c300a
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/congestion_controller_feedback_fuzzer.cc
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/congestion_controller/include/receive_side_congestion_controller.h"
+#include "modules/pacing/packet_router.h"
+#include "modules/remote_bitrate_estimator/include/remote_bitrate_estimator.h"
+#include "modules/rtp_rtcp/source/byte_io.h"
+
+namespace webrtc {
+
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ size_t i = 0;
+ if (size < sizeof(int64_t) + sizeof(uint8_t) + sizeof(uint32_t))
+ return;
+ SimulatedClock clock(data[i++]);
+ PacketRouter packet_router;
+ ReceiveSideCongestionController cc(&clock, &packet_router);
+ RemoteBitrateEstimator* rbe = cc.GetRemoteBitrateEstimator(true);
+ RTPHeader header;
+ header.ssrc = ByteReader<uint32_t>::ReadBigEndian(&data[i]);
+ i += sizeof(uint32_t);
+ header.extension.hasTransportSequenceNumber = true;
+ int64_t arrival_time_ms = std::min<int64_t>(
+ std::max<int64_t>(ByteReader<int64_t>::ReadBigEndian(&data[i]), 0),
+ std::numeric_limits<int64_t>::max() / 2);
+ i += sizeof(int64_t);
+ const size_t kMinPacketSize =
+ sizeof(size_t) + sizeof(uint16_t) + sizeof(uint8_t);
+ while (i + kMinPacketSize < size) {
+ size_t payload_size = ByteReader<size_t>::ReadBigEndian(&data[i]) % 1500;
+ i += sizeof(size_t);
+ header.extension.transportSequenceNumber =
+ ByteReader<uint16_t>::ReadBigEndian(&data[i]);
+ i += sizeof(uint16_t);
+ rbe->IncomingPacket(arrival_time_ms, payload_size, header);
+ clock.AdvanceTimeMilliseconds(5);
+ arrival_time_ms += ByteReader<uint8_t>::ReadBigEndian(&data[i]);
+ i += sizeof(uint8_t);
+ }
+ rbe->Process();
+}
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/README b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/README
new file mode 100644
index 0000000000..d29e169417
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/README
@@ -0,0 +1,34 @@
+This is a collection of corpora for various WebRTC fuzzers. To use
+them, the gn targets define seed_corpus=$corpus_dir, which causes the
+ClusterFuzz upload bot to bundle $corpus_dir and upload it.
+
+The format is simple: one file per test case. Specific notes are
+included below.
+
+### SDP ###
+This corpus was initially assembled manually from the following
+sources:
+
+ - curl --silent https://www.ietf.org/rfc/rfc4317.txt | grep '^[ a-z]*=[^=]*$' | sed 's/^[[:space:]]*//' | awk -v RS='(^|\n)v=' '/./ {print "v="$0 > NR".sdp"}'
+ - all the SDPs used in the parser unit tests
+ - some manually gathered SDPs from Firefox and Opera
+
+The SDP tokens come from:
+
+ - grep "^static const " webrtc/api/webrtcsdp.cc | cut -d'=' -f2 | cut -d ';' -f1 | tr -d '"' | tr -d "'" | tr -d ' ' | sort -u | grep -v '^(\n|\r|\r\n)$|^$' | sed -e 's/^/"/' -e 's/$/"/' | tail -n +2
+
+### STUN ###
+This corpus was initially assembled from the STUN unit tests, together
+with a crash that it found relatively quickly.
+
+### RT(C)P ###
+This corpus was initially assembled from the unittests. RTCP was
+minimised first.
+
+There is also rt(c?)p-corpus-with-extra-byte, in which each sample is
+prefixed by the byte 0xff. Some of the rtp fuzzers need to decide
+which header extensions to enable, and the first byte of the fuzz data
+is used for this.
+
+### PseudoTCP ###
+Very small corpus minimised from the unit tests. \ No newline at end of file
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/pseudotcp-corpus/785b96587d0eb44dd5d75b7a886f37e2ac504511 b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/pseudotcp-corpus/785b96587d0eb44dd5d75b7a886f37e2ac504511
new file mode 100644
index 0000000000..21f5cffa12
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/pseudotcp-corpus/785b96587d0eb44dd5d75b7a886f37e2ac504511
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/0.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/0.rtcp
new file mode 100644
index 0000000000..802eecf052
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/0.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/1.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/1.rtcp
new file mode 100644
index 0000000000..c062793b3c
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/1.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/10.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/10.rtcp
new file mode 100644
index 0000000000..fdc7780218
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/10.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/11.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/11.rtcp
new file mode 100644
index 0000000000..994f721dca
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/11.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/12.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/12.rtcp
new file mode 100644
index 0000000000..557fe9c23a
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/12.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/13.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/13.rtcp
new file mode 100644
index 0000000000..0f1b1809a7
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/13.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/14.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/14.rtcp
new file mode 100644
index 0000000000..df6bfed86c
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/14.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/15.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/15.rtcp
new file mode 100644
index 0000000000..3b31b3079d
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/15.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/16.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/16.rtcp
new file mode 100644
index 0000000000..0496ddf910
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/16.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/17.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/17.rtcp
new file mode 100644
index 0000000000..755b7198ba
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/17.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/18.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/18.rtcp
new file mode 100644
index 0000000000..04fd1e3417
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/18.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/19.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/19.rtcp
new file mode 100644
index 0000000000..8ae9812f10
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/19.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/2.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/2.rtcp
new file mode 100644
index 0000000000..ba38a0a599
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/2.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/20.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/20.rtcp
new file mode 100644
index 0000000000..debb7de940
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/20.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/21.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/21.rtcp
new file mode 100644
index 0000000000..3fcbd405e2
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/21.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/22.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/22.rtcp
new file mode 100644
index 0000000000..3defd8c253
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/22.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/23.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/23.rtcp
new file mode 100644
index 0000000000..211ccbd5be
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/23.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/24.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/24.rtcp
new file mode 100644
index 0000000000..8ded9be7fd
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/24.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/25.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/25.rtcp
new file mode 100644
index 0000000000..b5c8146cef
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/25.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/26.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/26.rtcp
new file mode 100644
index 0000000000..0fd4f25511
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/26.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/27.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/27.rtcp
new file mode 100644
index 0000000000..2c8bb63c9c
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/27.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/28.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/28.rtcp
new file mode 100644
index 0000000000..6a20bc27d8
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/28.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/29.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/29.rtcp
new file mode 100644
index 0000000000..76fd214197
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/29.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/3.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/3.rtcp
new file mode 100644
index 0000000000..72307e08bd
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/3.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/30.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/30.rtcp
new file mode 100644
index 0000000000..cfa38faa67
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/30.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/31.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/31.rtcp
new file mode 100644
index 0000000000..8abf725057
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/31.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/32.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/32.rtcp
new file mode 100644
index 0000000000..76518c88dd
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/32.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/33.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/33.rtcp
new file mode 100644
index 0000000000..92964965a6
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/33.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/34.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/34.rtcp
new file mode 100644
index 0000000000..9045c158b5
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/34.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/35.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/35.rtcp
new file mode 100644
index 0000000000..f86df02448
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/35.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/36.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/36.rtcp
new file mode 100644
index 0000000000..d274d416a2
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/36.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/37.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/37.rtcp
new file mode 100644
index 0000000000..b4f04f4069
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/37.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/38.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/38.rtcp
new file mode 100644
index 0000000000..8d65e0ff35
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/38.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/39.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/39.rtcp
new file mode 100644
index 0000000000..fb969f85f0
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/39.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/4.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/4.rtcp
new file mode 100644
index 0000000000..5170185122
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/4.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/40.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/40.rtcp
new file mode 100644
index 0000000000..279047c6b2
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/40.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/41.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/41.rtcp
new file mode 100644
index 0000000000..09a8a589bd
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/41.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/42.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/42.rtcp
new file mode 100644
index 0000000000..f727b190a7
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/42.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/43.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/43.rtcp
new file mode 100644
index 0000000000..9aab33a48a
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/43.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/44.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/44.rtcp
new file mode 100644
index 0000000000..2eba529c3a
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/44.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/45.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/45.rtcp
new file mode 100644
index 0000000000..50c0beabed
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/45.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/46.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/46.rtcp
new file mode 100644
index 0000000000..2de424a5d1
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/46.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/47.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/47.rtcp
new file mode 100644
index 0000000000..71d530b41f
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/47.rtcp
@@ -0,0 +1 @@
+€ \ No newline at end of file
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/48.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/48.rtcp
new file mode 100644
index 0000000000..665695029a
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/48.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/49.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/49.rtcp
new file mode 100644
index 0000000000..33b0f3d873
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/49.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/5.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/5.rtcp
new file mode 100644
index 0000000000..46bef3242a
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/5.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/50.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/50.rtcp
new file mode 100644
index 0000000000..5bec125397
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/50.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/51.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/51.rtcp
new file mode 100644
index 0000000000..ff94fb84b7
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/51.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/52.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/52.rtcp
new file mode 100644
index 0000000000..55cc76cd81
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/52.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/53.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/53.rtcp
new file mode 100644
index 0000000000..ac11523c94
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/53.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/54.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/54.rtcp
new file mode 100644
index 0000000000..f3f0bb8fa1
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/54.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/55.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/55.rtcp
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/55.rtcp
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/56.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/56.rtcp
new file mode 100644
index 0000000000..f0012f1efa
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/56.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/57.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/57.rtcp
new file mode 100644
index 0000000000..61517f01d8
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/57.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/58.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/58.rtcp
new file mode 100644
index 0000000000..3688310a05
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/58.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/59.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/59.rtcp
new file mode 100644
index 0000000000..e914f83b16
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/59.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/6.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/6.rtcp
new file mode 100644
index 0000000000..dcad8f6b40
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/6.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/60.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/60.rtcp
new file mode 100644
index 0000000000..8e999e7832
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/60.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/61.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/61.rtcp
new file mode 100644
index 0000000000..eb38d237aa
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/61.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/62.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/62.rtcp
new file mode 100644
index 0000000000..6df94b715f
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/62.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/63.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/63.rtcp
new file mode 100644
index 0000000000..a3b2acb3a8
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/63.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/64.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/64.rtcp
new file mode 100644
index 0000000000..4d50c0f4ae
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/64.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/65.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/65.rtcp
new file mode 100644
index 0000000000..537d10c6ce
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/65.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/66.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/66.rtcp
new file mode 100644
index 0000000000..f280f3ca09
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/66.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/7.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/7.rtcp
new file mode 100644
index 0000000000..f8f74e12c6
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/7.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/8.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/8.rtcp
new file mode 100644
index 0000000000..f0ceba83f4
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/8.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/9.rtcp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/9.rtcp
new file mode 100644
index 0000000000..7cc07893c3
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtcp-corpus/9.rtcp
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtp-corpus/rtp-0 b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtp-corpus/rtp-0
new file mode 100644
index 0000000000..c93ce82ec0
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtp-corpus/rtp-0
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtp-corpus/rtp-1 b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtp-corpus/rtp-1
new file mode 100644
index 0000000000..84834aefea
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtp-corpus/rtp-1
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtp-corpus/rtp-2 b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtp-corpus/rtp-2
new file mode 100644
index 0000000000..3a5aedba9b
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtp-corpus/rtp-2
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtp-corpus/rtp-3 b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtp-corpus/rtp-3
new file mode 100644
index 0000000000..300309ff37
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtp-corpus/rtp-3
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtp-corpus/rtp-4 b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtp-corpus/rtp-4
new file mode 100644
index 0000000000..84834aefea
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/rtp-corpus/rtp-4
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/10.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/10.sdp
new file mode 100644
index 0000000000..36319c4476
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/10.sdp
@@ -0,0 +1,11 @@
+v=0
+o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com
+s=
+c=IN IP4 host.atlanta.example.com
+t=0 0
+m=audio 49170 RTP/AVP 0 97
+a=rtpmap:0 PCMU/8000
+a=rtpmap:97 iLBC/8000
+m=audio 49172 RTP/AVP 98
+a=rtpmap:98 telephone-event/8000
+a=sendonly
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/11.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/11.sdp
new file mode 100644
index 0000000000..c3dbce401f
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/11.sdp
@@ -0,0 +1,10 @@
+v=0
+o=bob 2808844564 2808844564 IN IP4 host.biloxi.example.com
+s=
+c=IN IP4 host.biloxi.example.com
+t=0 0
+m=audio 49172 RTP/AVP 97
+a=rtpmap:97 iLBC/8000
+m=audio 49174 RTP/AVP 98
+a=rtpmap:98 telephone-event/8000
+a=recvonly
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/12.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/12.sdp
new file mode 100644
index 0000000000..26d4ff6266
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/12.sdp
@@ -0,0 +1,9 @@
+v=0
+o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com
+s=
+c=IN IP4 host.atlanta.example.com
+t=0 0
+m=audio 49170 RTP/AVP 97
+a=rtpmap:97 iLBC/8000
+m=video 51372 RTP/AVP 31
+a=rtpmap:31 H261/90000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/13.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/13.sdp
new file mode 100644
index 0000000000..f625e3890c
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/13.sdp
@@ -0,0 +1,9 @@
+v=0
+o=bob 2808844564 2808844564 IN IP4 host.biloxi.example.com
+s=
+c=IN IP4 host.biloxi.example.com
+t=0 0
+m=audio 49174 RTP/AVP 97
+a=rtpmap:97 iLBC/8000
+m=video 49170 RTP/AVP 31
+a=rtpmap:31 H261/90000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/14.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/14.sdp
new file mode 100644
index 0000000000..c36b9fe6cb
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/14.sdp
@@ -0,0 +1,9 @@
+v=0
+o=bob 2808844564 2808844565 IN IP4 host.biloxi.example.com
+s=
+c=IN IP4 newhost.biloxi.example.com
+t=0 0
+m=audio 49178 RTP/AVP 97
+a=rtpmap:97 iLBC/8000
+m=video 49188 RTP/AVP 31
+a=rtpmap:31 H261/90000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/15.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/15.sdp
new file mode 100644
index 0000000000..26d4ff6266
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/15.sdp
@@ -0,0 +1,9 @@
+v=0
+o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com
+s=
+c=IN IP4 host.atlanta.example.com
+t=0 0
+m=audio 49170 RTP/AVP 97
+a=rtpmap:97 iLBC/8000
+m=video 51372 RTP/AVP 31
+a=rtpmap:31 H261/90000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/16.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/16.sdp
new file mode 100644
index 0000000000..1d187a0dc5
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/16.sdp
@@ -0,0 +1,10 @@
+v=0
+o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com
+s=
+c=IN IP4 host.atlanta.example.com
+t=0 0
+m=audio 49170 RTP/AVP 0
+a=rtpmap:0 PCMU/8000
+m=audio 51372 RTP/AVP 97 101
+a=rtpmap:97 iLBC/8000
+a=rtpmap:101 telephone-event/8000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/17.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/17.sdp
new file mode 100644
index 0000000000..a328d16a16
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/17.sdp
@@ -0,0 +1,10 @@
+v=0
+o=bob 2808844564 2808844564 IN IP4 host.biloxi.example.com
+s=
+c=IN IP4 host.biloxi.example.com
+t=0 0
+m=audio 0 RTP/AVP 0
+a=rtpmap:0 PCMU/8000
+m=audio 49170 RTP/AVP 97 101
+a=rtpmap:97 iLBC/8000
+a=rtpmap:101 telephone-event/8000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/18.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/18.sdp
new file mode 100644
index 0000000000..1e0d3f5705
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/18.sdp
@@ -0,0 +1,9 @@
+v=0
+o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com
+s=
+c=IN IP4 host.atlanta.example.com
+t=0 0
+m=audio 49170 RTP/AVP 99
+a=rtpmap:99 iLBC/8000
+m=video 51372 RTP/AVP 31
+a=rtpmap:31 H261/90000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/19.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/19.sdp
new file mode 100644
index 0000000000..a9a5e12138
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/19.sdp
@@ -0,0 +1,9 @@
+v=0
+o=bob 2808844564 2808844564 IN IP4 host.biloxi.example.com
+s=
+c=IN IP4 host.biloxi.example.com
+t=0 0
+m=audio 49172 RTP/AVP 99
+a=rtpmap:99 iLBC/8000
+m=video 51374 RTP/AVP 31
+a=rtpmap:31 H261/90000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/2.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/2.sdp
new file mode 100644
index 0000000000..96c4975ec0
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/2.sdp
@@ -0,0 +1,12 @@
+v=0
+o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com
+s=
+c=IN IP4 host.atlanta.example.com
+t=0 0
+m=audio 49170 RTP/AVP 0 8 97
+a=rtpmap:0 PCMU/8000
+a=rtpmap:8 PCMA/8000
+a=rtpmap:97 iLBC/8000
+m=video 51372 RTP/AVP 31 32
+a=rtpmap:31 H261/90000
+a=rtpmap:32 MPV/90000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/20.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/20.sdp
new file mode 100644
index 0000000000..b2c072af1d
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/20.sdp
@@ -0,0 +1,10 @@
+v=0
+o=alice 2890844526 2890844527 IN IP4 host.atlanta.example.com
+s=
+c=IN IP4 host.atlanta.example.com
+t=0 0
+m=audio 49170 RTP/AVP 99
+a=rtpmap:99 iLBC/8000
+m=video 51372 RTP/AVP 31 32
+a=rtpmap:31 H261/90000
+a=rtpmap:32 MPV/90000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/21.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/21.sdp
new file mode 100644
index 0000000000..28e949133e
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/21.sdp
@@ -0,0 +1,10 @@
+v=0
+o=bob 2808844564 2808844565 IN IP4 host.biloxi.example.com
+s=
+c=IN IP4 host.biloxi.example.com
+t=0 0
+m=audio 49172 RTP/AVP 99
+a=rtpmap:99 iLBC/8000
+m=video 51374 RTP/AVP 31 32
+a=rtpmap:31 H261/90000
+a=rtpmap:32 MPV/90000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/22.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/22.sdp
new file mode 100644
index 0000000000..96c4975ec0
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/22.sdp
@@ -0,0 +1,12 @@
+v=0
+o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com
+s=
+c=IN IP4 host.atlanta.example.com
+t=0 0
+m=audio 49170 RTP/AVP 0 8 97
+a=rtpmap:0 PCMU/8000
+a=rtpmap:8 PCMA/8000
+a=rtpmap:97 iLBC/8000
+m=video 51372 RTP/AVP 31 32
+a=rtpmap:31 H261/90000
+a=rtpmap:32 MPV/90000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/23.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/23.sdp
new file mode 100644
index 0000000000..36c7d70148
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/23.sdp
@@ -0,0 +1,10 @@
+v=0
+o=bob 2808844564 2808844564 IN IP4 host.biloxi.example.com
+s=
+c=IN IP4 host.biloxi.example.com
+t=0 0
+m=audio 49174 RTP/AVP 0
+a=rtpmap:0 PCMU/8000
+m=video 49172 RTP/AVP 32
+c=IN IP4 otherhost.biloxi.example.com
+a=rtpmap:32 MPV/90000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/24.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/24.sdp
new file mode 100644
index 0000000000..6cf5dc5894
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/24.sdp
@@ -0,0 +1,8 @@
+v=0
+o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com
+s=
+c=IN IP4 host.atlanta.example.com
+t=0 0
+m=audio 49170 RTP/AVP 0 97
+a=rtpmap:0 PCMU/8000
+a=rtpmap:97 iLBC/8000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/25.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/25.sdp
new file mode 100644
index 0000000000..ac1ec85b29
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/25.sdp
@@ -0,0 +1,8 @@
+v=0
+o=bob 2808844564 2808844564 IN IP4 host.biloxi.example.com
+s=
+c=IN IP4 placeholder.biloxi.example.com
+t=0 0
+m=audio 49172 RTP/AVP 97
+a=rtpmap:97 iLBC/8000
+a=sendonly
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/26.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/26.sdp
new file mode 100644
index 0000000000..f0eb0d62a7
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/26.sdp
@@ -0,0 +1,7 @@
+v=0
+o=bob 2808844564 2808844565 IN IP4 host.biloxi.example.com
+s=
+c=IN IP4 host.biloxi.example.com
+t=0 0
+m=audio 49170 RTP/AVP 97
+a=rtpmap:97 iLBC/8000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/27.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/27.sdp
new file mode 100644
index 0000000000..1e4f3b3e19
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/27.sdp
@@ -0,0 +1,7 @@
+v=0
+o=alice 2890844526 2890844527 IN IP4 host.atlanta.example.com
+s=
+c=IN IP4 host.atlanta.example.com
+t=0 0
+m=audio 49178 RTP/AVP 97
+a=rtpmap:97 iLBC/8000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/28.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/28.sdp
new file mode 100644
index 0000000000..36319c4476
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/28.sdp
@@ -0,0 +1,11 @@
+v=0
+o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com
+s=
+c=IN IP4 host.atlanta.example.com
+t=0 0
+m=audio 49170 RTP/AVP 0 97
+a=rtpmap:0 PCMU/8000
+a=rtpmap:97 iLBC/8000
+m=audio 49172 RTP/AVP 98
+a=rtpmap:98 telephone-event/8000
+a=sendonly
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/29.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/29.sdp
new file mode 100644
index 0000000000..c3dbce401f
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/29.sdp
@@ -0,0 +1,10 @@
+v=0
+o=bob 2808844564 2808844564 IN IP4 host.biloxi.example.com
+s=
+c=IN IP4 host.biloxi.example.com
+t=0 0
+m=audio 49172 RTP/AVP 97
+a=rtpmap:97 iLBC/8000
+m=audio 49174 RTP/AVP 98
+a=rtpmap:98 telephone-event/8000
+a=recvonly
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/3.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/3.sdp
new file mode 100644
index 0000000000..b0142f5dcf
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/3.sdp
@@ -0,0 +1,9 @@
+v=0
+o=bob 2808844564 2808844564 IN IP4 host.biloxi.example.com
+s=
+c=IN IP4 host.biloxi.example.com
+t=0 0
+m=audio 49174 RTP/AVP 0
+a=rtpmap:0 PCMU/8000
+m=video 49170 RTP/AVP 32
+a=rtpmap:32 MPV/90000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/30.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/30.sdp
new file mode 100644
index 0000000000..0798631d2e
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/30.sdp
@@ -0,0 +1,11 @@
+v=0
+o=bob 2808844564 2808844565 IN IP4 host.biloxi.example.com
+s=
+c=IN IP4 host.biloxi.example.com
+t=0 0
+m=audio 49172 RTP/AVP 97
+a=rtpmap:97 iLBC/8000
+a=sendonly
+m=audio 49174 RTP/AVP 98
+a=rtpmap:98 telephone-event/8000
+a=recvonly
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/31.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/31.sdp
new file mode 100644
index 0000000000..78efdd8fcb
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/31.sdp
@@ -0,0 +1,11 @@
+v=0
+o=alice 2890844526 2890844527 IN IP4 host.atlanta.example.com
+s=
+c=IN IP4 host.atlanta.example.com
+t=0 0
+m=audio 49170 RTP/AVP 0 97
+a=rtpmap:0 PCMU/8000
+a=rtpmap:97 iLBC/8000
+m=audio 49172 RTP/AVP 98
+a=rtpmap:98 telephone-event/8000
+a=sendonly
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/32.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/32.sdp
new file mode 100644
index 0000000000..6cf5dc5894
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/32.sdp
@@ -0,0 +1,8 @@
+v=0
+o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com
+s=
+c=IN IP4 host.atlanta.example.com
+t=0 0
+m=audio 49170 RTP/AVP 0 97
+a=rtpmap:0 PCMU/8000
+a=rtpmap:97 iLBC/8000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/33.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/33.sdp
new file mode 100644
index 0000000000..23f462f5a6
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/33.sdp
@@ -0,0 +1,7 @@
+v=0
+o=bob 2808844564 2808844564 IN IP4 host.biloxi.example.com
+s=
+c=IN IP4 host.biloxi.example.com
+t=0 0
+m=audio 49170 RTP/AVP 97
+a=rtpmap:97 iLBC/8000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/34.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/34.sdp
new file mode 100644
index 0000000000..b52b947486
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/34.sdp
@@ -0,0 +1,11 @@
+v=0
+o=bob 2808844564 2808844565 IN IP4 host.biloxi.example.com
+s=
+c=IN IP4 host.biloxi.example.com
+t=0 0
+m=audio 49170 RTP/AVP 97
+a=rtpmap:97 iLBC/8000
+m=audio 48282 RTP/AVP 98
+c=IN IP4 mediaserver.biloxi.example.com
+a=rtpmap:98 telephone-event/8000
+a=recvonly
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/35.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/35.sdp
new file mode 100644
index 0000000000..07ad4f8758
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/35.sdp
@@ -0,0 +1,11 @@
+v=0
+o=alice 2890844526 2890844527 IN IP4 host.atlanta.example.com
+s=
+c=IN IP4 host.atlanta.example.com
+t=0 0
+m=audio 49170 RTP/AVP 97
+a=rtpmap:97 iLBC/8000
+m=audio 49172 RTP/AVP 98
+c=IN IP4 host.atlanta.example.com
+a=rtpmap:98 telephone-event/8000
+a=sendonly
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/36.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/36.sdp
new file mode 100644
index 0000000000..c75c6977bb
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/36.sdp
@@ -0,0 +1,7 @@
+v=0
+o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com
+s=
+c=IN IP4 host.atlanta.example.com
+t=0 0
+m=audio 49170 RTP/AVP 0
+a=rtpmap:0 PCMU/8000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/37.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/37.sdp
new file mode 100644
index 0000000000..d05dbd61fd
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/37.sdp
@@ -0,0 +1,7 @@
+v=0
+o=bob 2808844564 2808844564 IN IP4 host.biloxi.example.com
+s=
+c=IN IP4 host.biloxi.example.com
+t=0 0
+m=audio 49172 RTP/AVP 0
+a=rtpmap:0 PCMU/8000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/38.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/38.sdp
new file mode 100644
index 0000000000..253ac0705a
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/38.sdp
@@ -0,0 +1,9 @@
+v=0
+o=alice 2890844526 2890844527 IN IP4 host.atlanta.example.com
+s=
+c=IN IP4 host.atlanta.example.com
+t=0 0
+m=audio 49170 RTP/AVP 0
+a=rtpmap:0 PCMU/8000
+m=video 49172 RTP/AVP 31
+a=rtpmap:31 H261/90000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/39.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/39.sdp
new file mode 100644
index 0000000000..57d3203c74
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/39.sdp
@@ -0,0 +1,9 @@
+v=0
+o=bob 2808844564 2808844565 IN IP4 host.biloxi.example.com
+s=
+c=IN IP4 host.biloxi.example.com
+t=0 0
+m=audio 49172 RTP/AVP 0
+a=rtpmap:0 PCMU/8000
+m=video 49168 RTP/AVP 31
+a=rtpmap:31 H261/90000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/4.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/4.sdp
new file mode 100644
index 0000000000..96c4975ec0
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/4.sdp
@@ -0,0 +1,12 @@
+v=0
+o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com
+s=
+c=IN IP4 host.atlanta.example.com
+t=0 0
+m=audio 49170 RTP/AVP 0 8 97
+a=rtpmap:0 PCMU/8000
+a=rtpmap:8 PCMA/8000
+a=rtpmap:97 iLBC/8000
+m=video 51372 RTP/AVP 31 32
+a=rtpmap:31 H261/90000
+a=rtpmap:32 MPV/90000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/40.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/40.sdp
new file mode 100644
index 0000000000..26d4ff6266
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/40.sdp
@@ -0,0 +1,9 @@
+v=0
+o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com
+s=
+c=IN IP4 host.atlanta.example.com
+t=0 0
+m=audio 49170 RTP/AVP 97
+a=rtpmap:97 iLBC/8000
+m=video 51372 RTP/AVP 31
+a=rtpmap:31 H261/90000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/41.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/41.sdp
new file mode 100644
index 0000000000..f625e3890c
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/41.sdp
@@ -0,0 +1,9 @@
+v=0
+o=bob 2808844564 2808844564 IN IP4 host.biloxi.example.com
+s=
+c=IN IP4 host.biloxi.example.com
+t=0 0
+m=audio 49174 RTP/AVP 97
+a=rtpmap:97 iLBC/8000
+m=video 49170 RTP/AVP 31
+a=rtpmap:31 H261/90000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/42.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/42.sdp
new file mode 100644
index 0000000000..2dda9bb252
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/42.sdp
@@ -0,0 +1,9 @@
+v=0
+o=bob 2808844564 2808844565 IN IP4 host.biloxi.example.com
+s=
+c=IN IP4 host.biloxi.example.com
+t=0 0
+m=audio 49174 RTP/AVP 97
+a=rtpmap:97 iLBC/8000
+m=video 0 RTP/AVP 31
+a=rtpmap:31 H261/90000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/43.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/43.sdp
new file mode 100644
index 0000000000..83a2bf9e66
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/43.sdp
@@ -0,0 +1,9 @@
+v=0
+o=alice 2890844526 2890844527 IN IP4 host.atlanta.example.com
+s=
+c=IN IP4 host.atlanta.example.com
+t=0 0
+m=audio 49170 RTP/AVP 97
+a=rtpmap:97 iLBC/8000
+m=video 0 RTP/AVP 31
+a=rtpmap:31 H261/90000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/44.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/44.sdp
new file mode 100644
index 0000000000..e187d7df7d
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/44.sdp
@@ -0,0 +1,5 @@
+v=0
+o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com
+s=
+c=IN IP4 host.atlanta.example.com
+t=0 0
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/45.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/45.sdp
new file mode 100644
index 0000000000..9e344f035a
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/45.sdp
@@ -0,0 +1,5 @@
+v=0
+o=bob 2808844564 2808844564 IN IP4 host.biloxi.example.com
+s=
+c=IN IP4 host.biloxi.example.com
+t=0 0
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/46.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/46.sdp
new file mode 100644
index 0000000000..8a63ca0992
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/46.sdp
@@ -0,0 +1,7 @@
+v=0
+o=alice 2890844526 2890844527 IN IP4 host.atlanta.example.com
+s=
+c=IN IP4 host.atlanta.example.com
+t=0 0
+m=audio 49170 RTP/AVP 97
+a=rtpmap:97 iLBC/8000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/47.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/47.sdp
new file mode 100644
index 0000000000..66dadbb93f
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/47.sdp
@@ -0,0 +1,7 @@
+v=0
+o=bob 2808844564 2808844565 IN IP4 host.biloxi.example.com
+s=
+c=IN IP4 host.biloxi.example.com
+t=0 0
+m=audio 49172 RTP/AVP 97
+a=rtpmap:97 iLBC/8000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/48.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/48.sdp
new file mode 100644
index 0000000000..6df76ab942
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/48.sdp
@@ -0,0 +1,7 @@
+v=0
+o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com
+s=
+c=IN IP4 0.0.0.0
+t=0 0
+m=audio 23442 RTP/AVP 97
+a=rtpmap:97 iLBC/8000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/49.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/49.sdp
new file mode 100644
index 0000000000..23f462f5a6
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/49.sdp
@@ -0,0 +1,7 @@
+v=0
+o=bob 2808844564 2808844564 IN IP4 host.biloxi.example.com
+s=
+c=IN IP4 host.biloxi.example.com
+t=0 0
+m=audio 49170 RTP/AVP 97
+a=rtpmap:97 iLBC/8000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/5.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/5.sdp
new file mode 100644
index 0000000000..264ab8024f
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/5.sdp
@@ -0,0 +1,10 @@
+v=0
+o=bob 2808844564 2808844564 IN IP4 host.biloxi.example.com
+s=
+c=IN IP4 host.biloxi.example.com
+t=0 0
+m=audio 49172 RTP/AVP 0 8
+a=rtpmap:0 PCMU/8000
+a=rtpmap:8 PCMA/8000
+m=video 0 RTP/AVP 31
+a=rtpmap:31 H261/90000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/50.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/50.sdp
new file mode 100644
index 0000000000..8a63ca0992
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/50.sdp
@@ -0,0 +1,7 @@
+v=0
+o=alice 2890844526 2890844527 IN IP4 host.atlanta.example.com
+s=
+c=IN IP4 host.atlanta.example.com
+t=0 0
+m=audio 49170 RTP/AVP 97
+a=rtpmap:97 iLBC/8000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/51.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/51.sdp
new file mode 100644
index 0000000000..23f462f5a6
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/51.sdp
@@ -0,0 +1,7 @@
+v=0
+o=bob 2808844564 2808844564 IN IP4 host.biloxi.example.com
+s=
+c=IN IP4 host.biloxi.example.com
+t=0 0
+m=audio 49170 RTP/AVP 97
+a=rtpmap:97 iLBC/8000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/52.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/52.sdp
new file mode 100644
index 0000000000..7c1730eb1e
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/52.sdp
@@ -0,0 +1,7 @@
+v=0
+o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com
+s=
+c=IN IP4 host.atlanta.example.com
+t=0 0
+m=audio 49170 RTP/AVP 97
+a=rtpmap:97 iLBC/8000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/53.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/53.sdp
new file mode 100644
index 0000000000..599157691a
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/53.sdp
@@ -0,0 +1,7 @@
+v=0
+o=bob 2808844564 2808844564 IN IP4 host.biloxi.example.com
+s=
+c=IN IP4 0.0.0.0
+t=0 0
+m=audio 9322 RTP/AVP 97
+a=rtpmap:97 iLBC/8000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/54.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/54.sdp
new file mode 100644
index 0000000000..66dadbb93f
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/54.sdp
@@ -0,0 +1,7 @@
+v=0
+o=bob 2808844564 2808844565 IN IP4 host.biloxi.example.com
+s=
+c=IN IP4 host.biloxi.example.com
+t=0 0
+m=audio 49172 RTP/AVP 97
+a=rtpmap:97 iLBC/8000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/55.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/55.sdp
new file mode 100644
index 0000000000..bd724c471b
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/55.sdp
@@ -0,0 +1,8 @@
+v=0
+o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com
+s=
+c=IN IP4 host.atlanta.example.com
+t=0 0
+m=audio 49170 RTP/AVP 97
+a=rtpmap:97 iLBC/8000
+
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/6.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/6.sdp
new file mode 100644
index 0000000000..3f80345e30
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/6.sdp
@@ -0,0 +1,9 @@
+v=0
+o=alice 2890844526 2890844527 IN IP4 host.atlanta.example.com
+s=
+c=IN IP4 host.atlanta.example.com
+t=0 0
+m=audio 51372 RTP/AVP 0
+a=rtpmap:0 PCMU/8000
+m=video 0 RTP/AVP 31
+a=rtpmap:31 H261/90000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/7.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/7.sdp
new file mode 100644
index 0000000000..920ad8229e
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/7.sdp
@@ -0,0 +1,9 @@
+v=0
+o=bob 2808844564 2808844565 IN IP4 host.biloxi.example.com
+s=
+c=IN IP4 host.biloxi.example.com
+t=0 0
+m=audio 49172 RTP/AVP 0
+a=rtpmap:0 PCMU/8000
+m=video 0 RTP/AVP 31
+a=rtpmap:31 H261/90000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/8.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/8.sdp
new file mode 100644
index 0000000000..96c4975ec0
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/8.sdp
@@ -0,0 +1,12 @@
+v=0
+o=alice 2890844526 2890844526 IN IP4 host.atlanta.example.com
+s=
+c=IN IP4 host.atlanta.example.com
+t=0 0
+m=audio 49170 RTP/AVP 0 8 97
+a=rtpmap:0 PCMU/8000
+a=rtpmap:8 PCMA/8000
+a=rtpmap:97 iLBC/8000
+m=video 51372 RTP/AVP 31 32
+a=rtpmap:31 H261/90000
+a=rtpmap:32 MPV/90000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/9.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/9.sdp
new file mode 100644
index 0000000000..a9a5e12138
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/9.sdp
@@ -0,0 +1,9 @@
+v=0
+o=bob 2808844564 2808844564 IN IP4 host.biloxi.example.com
+s=
+c=IN IP4 host.biloxi.example.com
+t=0 0
+m=audio 49172 RTP/AVP 99
+a=rtpmap:99 iLBC/8000
+m=video 51374 RTP/AVP 31
+a=rtpmap:31 H261/90000
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/firefox-1.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/firefox-1.sdp
new file mode 100644
index 0000000000..6d664bc051
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/firefox-1.sdp
@@ -0,0 +1,58 @@
+v=0
+o=mozilla...THIS_IS_SDPARTA-46.0.1 5115930144083302970 0 IN IP4 0.0.0.0
+s=-
+t=0 0
+a=fingerprint:sha-256 24:67:5E:1B:9A:B9:CF:36:C5:30:8F:35:F7:B1:50:66:88:81:92:CB:29:BA:53:A5:02:C8:0A:A5:4E:9C:AE:D9
+a=group:BUNDLE sdparta_0 sdparta_1 sdparta_2
+a=ice-options:trickle
+a=msid-semantic:WMS *
+m=audio 9 UDP/TLS/RTP/SAVPF 109 9 0 8
+c=IN IP4 0.0.0.0
+a=sendrecv
+a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
+a=fmtp:109 maxplaybackrate=48000;stereo=1
+a=ice-pwd:b9f3911b591ae61e2d7f6af0531fd2a3
+a=ice-ufrag:3edc9012
+a=mid:sdparta_0
+a=msid:{258e92fb-547c-40ca-92e9-efe0cedb4cba} {bd1fafff-bfd0-40d4-b0a3-2a87cff307ee}
+a=rtcp-mux
+a=rtpmap:109 opus/48000/2
+a=rtpmap:9 G722/8000/1
+a=rtpmap:0 PCMU/8000
+a=rtpmap:8 PCMA/8000
+a=setup:actpass
+a=ssrc:2121669360 cname:{387b0735-bde2-43a4-8484-7f5663b60f24}
+m=video 9 UDP/TLS/RTP/SAVPF 120 126 97
+c=IN IP4 0.0.0.0
+a=sendrecv
+a=fmtp:126 profile-level-id=42e01f;level-asymmetry-allowed=1;packetization-mode=1
+a=fmtp:97 profile-level-id=42e01f;level-asymmetry-allowed=1
+a=fmtp:120 max-fs=12288;max-fr=60
+a=ice-pwd:b9f3911b591ae61e2d7f6af0531fd2a3
+a=ice-ufrag:3edc9012
+a=mid:sdparta_1
+a=msid:{258e92fb-547c-40ca-92e9-efe0cedb4cba} {9e8f5867-a9aa-4489-8bd4-3a8a57a5e592}
+a=rtcp-fb:120 nack
+a=rtcp-fb:120 nack pli
+a=rtcp-fb:120 ccm fir
+a=rtcp-fb:126 nack
+a=rtcp-fb:126 nack pli
+a=rtcp-fb:126 ccm fir
+a=rtcp-fb:97 nack
+a=rtcp-fb:97 nack pli
+a=rtcp-fb:97 ccm fir
+a=rtcp-mux
+a=rtpmap:120 VP8/90000
+a=rtpmap:126 H264/90000
+a=rtpmap:97 H264/90000
+a=setup:actpass
+a=ssrc:2158832026 cname:{387b0735-bde2-43a4-8484-7f5663b60f24}
+m=application 9 DTLS/SCTP 5000
+c=IN IP4 0.0.0.0
+a=sendrecv
+a=ice-pwd:b9f3911b591ae61e2d7f6af0531fd2a3
+a=ice-ufrag:3edc9012
+a=mid:sdparta_2
+a=sctpmap:5000 webrtc-datachannel 256
+a=setup:actpass
+a=ssrc:2670959794 cname:{387b0735-bde2-43a4-8484-7f5663b60f24}
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/firefox-2.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/firefox-2.sdp
new file mode 100644
index 0000000000..07806eb225
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/firefox-2.sdp
@@ -0,0 +1,43 @@
+v=0
+o=mozilla...THIS_IS_SDPARTA-46.0.1 3068771576687940834 0 IN IP4 0.0.0.0
+s=-
+t=0 0
+a=fingerprint:sha-256 AD:87:B3:11:E4:E2:BA:EF:D2:3F:2E:AC:24:57:8E:DC:1F:67:41:29:44:C4:96:E3:62:90:CC:90:59:CA:2C:84
+a=group:BUNDLE sdparta_0 sdparta_1 sdparta_2
+a=ice-options:trickle
+a=msid-semantic:WMS *
+m=audio 9 UDP/TLS/RTP/SAVPF 109
+c=IN IP4 0.0.0.0
+a=recvonly
+a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
+a=fmtp:109 maxplaybackrate=48000;stereo=1
+a=ice-pwd:ff4c4dc6fe92e1f22d2c10352d8967d5
+a=ice-ufrag:a539544b
+a=mid:sdparta_0
+a=rtcp-mux
+a=rtpmap:109 opus/48000/2
+a=setup:active
+a=ssrc:600995474 cname:{5b598a29-a81b-4ffe-a2c5-507778057e7a}
+m=video 9 UDP/TLS/RTP/SAVPF 120
+c=IN IP4 0.0.0.0
+a=recvonly
+a=fmtp:120 max-fs=12288;max-fr=60
+a=ice-pwd:ff4c4dc6fe92e1f22d2c10352d8967d5
+a=ice-ufrag:a539544b
+a=mid:sdparta_1
+a=rtcp-fb:120 nack
+a=rtcp-fb:120 nack pli
+a=rtcp-fb:120 ccm fir
+a=rtcp-mux
+a=rtpmap:120 VP8/90000
+a=setup:active
+a=ssrc:3480150809 cname:{5b598a29-a81b-4ffe-a2c5-507778057e7a}
+m=application 9 DTLS/SCTP 5000
+c=IN IP4 0.0.0.0
+a=sendrecv
+a=ice-pwd:ff4c4dc6fe92e1f22d2c10352d8967d5
+a=ice-ufrag:a539544b
+a=mid:sdparta_2
+a=sctpmap:5000 webrtc-datachannel 256
+a=setup:active
+a=ssrc:3021788991 cname:{5b598a29-a81b-4ffe-a2c5-507778057e7a}
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/opera-1.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/opera-1.sdp
new file mode 100644
index 0000000000..42d15e81f4
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/opera-1.sdp
@@ -0,0 +1,85 @@
+v=0
+o=- 1656229333038673902 2 IN IP4 127.0.0.1
+s=-
+t=0 0
+a=group:BUNDLE audio video data
+a=msid-semantic: WMS Ppsa09YmDLBombOh5e8HqfqxEIPF69a46Hd4
+m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 126
+c=IN IP4 0.0.0.0
+a=rtcp:9 IN IP4 0.0.0.0
+a=ice-ufrag:1Jyk4q3nLIL5NiMx
+a=ice-pwd:GL8/iarMqPIhImfnsG2dyXlH
+a=fingerprint:sha-256 5A:16:96:94:B2:AC:60:27:64:C5:FE:46:6C:02:C0:CD:49:E3:E2:0B:5B:C9:D4:86:C4:B3:A4:F2:23:80:7A:DA
+a=setup:actpass
+a=mid:audio
+a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
+a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
+a=sendrecv
+a=rtcp-mux
+a=rtpmap:111 opus/48000/2
+a=rtcp-fb:111 transport-cc
+a=fmtp:111 minptime=10; useinbandfec=1
+a=rtpmap:103 ISAC/16000
+a=rtpmap:104 ISAC/32000
+a=rtpmap:9 G722/8000
+a=rtpmap:0 PCMU/8000
+a=rtpmap:8 PCMA/8000
+a=rtpmap:106 CN/32000
+a=rtpmap:105 CN/16000
+a=rtpmap:13 CN/8000
+a=rtpmap:126 telephone-event/8000
+a=maxptime:60
+a=ssrc:2233075910 cname:VhHMGYCjn4alR9zP
+a=ssrc:2233075910 msid:Ppsa09YmDLBombOh5e8HqfqxEIPF69a46Hd4 689d3496-0896-4d52-bce6-8e90512a368b
+a=ssrc:2233075910 mslabel:Ppsa09YmDLBombOh5e8HqfqxEIPF69a46Hd4
+a=ssrc:2233075910 label:689d3496-0896-4d52-bce6-8e90512a368b
+m=video 9 UDP/TLS/RTP/SAVPF 100 101 116 117 96 97 98
+c=IN IP4 0.0.0.0
+a=rtcp:9 IN IP4 0.0.0.0
+a=ice-ufrag:1Jyk4q3nLIL5NiMx
+a=ice-pwd:GL8/iarMqPIhImfnsG2dyXlH
+a=fingerprint:sha-256 5A:16:96:94:B2:AC:60:27:64:C5:FE:46:6C:02:C0:CD:49:E3:E2:0B:5B:C9:D4:86:C4:B3:A4:F2:23:80:7A:DA
+a=setup:actpass
+a=mid:video
+a=extmap:2 urn:ietf:params:rtp-hdrext:toffset
+a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
+a=extmap:4 urn:3gpp:video-orientation
+a=sendrecv
+a=rtcp-mux
+a=rtpmap:100 VP8/90000
+a=rtcp-fb:100 ccm fir
+a=rtcp-fb:100 nack
+a=rtcp-fb:100 nack pli
+a=rtcp-fb:100 goog-remb
+a=rtcp-fb:100 transport-cc
+a=rtpmap:101 VP9/90000
+a=rtcp-fb:101 ccm fir
+a=rtcp-fb:101 nack
+a=rtcp-fb:101 nack pli
+a=rtcp-fb:101 goog-remb
+a=rtcp-fb:101 transport-cc
+a=rtpmap:116 red/90000
+a=rtpmap:117 ulpfec/90000
+a=rtpmap:96 rtx/90000
+a=fmtp:96 apt=100
+a=rtpmap:97 rtx/90000
+a=fmtp:97 apt=101
+a=rtpmap:98 rtx/90000
+a=fmtp:98 apt=116
+a=ssrc-group:FID 50498894 2399294607
+a=ssrc:50498894 cname:VhHMGYCjn4alR9zP
+a=ssrc:50498894 msid:Ppsa09YmDLBombOh5e8HqfqxEIPF69a46Hd4 1aef96f4-fc4c-4f86-98f3-0fbf4f625f70
+a=ssrc:50498894 mslabel:Ppsa09YmDLBombOh5e8HqfqxEIPF69a46Hd4
+a=ssrc:50498894 label:1aef96f4-fc4c-4f86-98f3-0fbf4f625f70
+a=ssrc:2399294607 cname:VhHMGYCjn4alR9zP
+a=ssrc:2399294607 msid:Ppsa09YmDLBombOh5e8HqfqxEIPF69a46Hd4 1aef96f4-fc4c-4f86-98f3-0fbf4f625f70
+a=ssrc:2399294607 mslabel:Ppsa09YmDLBombOh5e8HqfqxEIPF69a46Hd4
+a=ssrc:2399294607 label:1aef96f4-fc4c-4f86-98f3-0fbf4f625f70
+m=application 9 DTLS/SCTP 5000
+c=IN IP4 0.0.0.0
+a=ice-ufrag:1Jyk4q3nLIL5NiMx
+a=ice-pwd:GL8/iarMqPIhImfnsG2dyXlH
+a=fingerprint:sha-256 5A:16:96:94:B2:AC:60:27:64:C5:FE:46:6C:02:C0:CD:49:E3:E2:0B:5B:C9:D4:86:C4:B3:A4:F2:23:80:7A:DA
+a=setup:actpass
+a=mid:data
+a=sctpmap:5000 webrtc-datachannel 1024
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/opera-2.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/opera-2.sdp
new file mode 100644
index 0000000000..6ed4e3b4a8
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/opera-2.sdp
@@ -0,0 +1,73 @@
+v=0
+o=- 2013283641453412290 2 IN IP4 127.0.0.1
+s=-
+t=0 0
+a=group:BUNDLE audio video data
+a=msid-semantic: WMS
+m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 126
+c=IN IP4 0.0.0.0
+a=rtcp:9 IN IP4 0.0.0.0
+a=ice-ufrag:YVa3KTlFDCwsfPOQ
+a=ice-pwd:ByUn1Od88VokVM0rtQ/bbeZa
+a=fingerprint:sha-256 5A:16:96:94:B2:AC:60:27:64:C5:FE:46:6C:02:C0:CD:49:E3:E2:0B:5B:C9:D4:86:C4:B3:A4:F2:23:80:7A:DA
+a=setup:active
+a=mid:audio
+a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
+a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
+a=recvonly
+a=rtcp-mux
+a=rtpmap:111 opus/48000/2
+a=rtcp-fb:111 transport-cc
+a=fmtp:111 minptime=10; useinbandfec=1
+a=rtpmap:103 ISAC/16000
+a=rtpmap:104 ISAC/32000
+a=rtpmap:9 G722/8000
+a=rtpmap:0 PCMU/8000
+a=rtpmap:8 PCMA/8000
+a=rtpmap:106 CN/32000
+a=rtpmap:105 CN/16000
+a=rtpmap:13 CN/8000
+a=rtpmap:126 telephone-event/8000
+a=maxptime:60
+m=video 9 UDP/TLS/RTP/SAVPF 100 101 116 117 96 97 98
+c=IN IP4 0.0.0.0
+a=rtcp:9 IN IP4 0.0.0.0
+a=ice-ufrag:YVa3KTlFDCwsfPOQ
+a=ice-pwd:ByUn1Od88VokVM0rtQ/bbeZa
+a=fingerprint:sha-256 5A:16:96:94:B2:AC:60:27:64:C5:FE:46:6C:02:C0:CD:49:E3:E2:0B:5B:C9:D4:86:C4:B3:A4:F2:23:80:7A:DA
+a=setup:active
+a=mid:video
+a=extmap:2 urn:ietf:params:rtp-hdrext:toffset
+a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
+a=extmap:4 urn:3gpp:video-orientation
+a=recvonly
+a=rtcp-mux
+a=rtpmap:100 VP8/90000
+a=rtcp-fb:100 ccm fir
+a=rtcp-fb:100 nack
+a=rtcp-fb:100 nack pli
+a=rtcp-fb:100 goog-remb
+a=rtcp-fb:100 transport-cc
+a=rtpmap:101 VP9/90000
+a=rtcp-fb:101 ccm fir
+a=rtcp-fb:101 nack
+a=rtcp-fb:101 nack pli
+a=rtcp-fb:101 goog-remb
+a=rtcp-fb:101 transport-cc
+a=rtpmap:116 red/90000
+a=rtpmap:117 ulpfec/90000
+a=rtpmap:96 rtx/90000
+a=fmtp:96 apt=100
+a=rtpmap:97 rtx/90000
+a=fmtp:97 apt=101
+a=rtpmap:98 rtx/90000
+a=fmtp:98 apt=116
+m=application 9 DTLS/SCTP 5000
+c=IN IP4 0.0.0.0
+b=AS:30
+a=ice-ufrag:YVa3KTlFDCwsfPOQ
+a=ice-pwd:ByUn1Od88VokVM0rtQ/bbeZa
+a=fingerprint:sha-256 5A:16:96:94:B2:AC:60:27:64:C5:FE:46:6C:02:C0:CD:49:E3:E2:0B:5B:C9:D4:86:C4:B3:A4:F2:23:80:7A:DA
+a=setup:active
+a=mid:data
+a=sctpmap:5000 webrtc-datachannel 1024
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/unittest-1.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/unittest-1.sdp
new file mode 100644
index 0000000000..ce349ac30f
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/unittest-1.sdp
@@ -0,0 +1,52 @@
+v=0
+o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1
+s=-
+t=0 0
+a=msid-semantic: WMS local_stream_1
+m=audio 2345 RTP/SAVPF 111 103 104
+c=IN IP4 74.125.127.126
+a=rtcp:2347 IN IP4 74.125.127.126
+a=candidate:a0+B/1 1 udp 2130706432 192.168.1.5 1234 typ host generation 2
+a=candidate:a0+B/1 2 udp 2130706432 192.168.1.5 1235 typ host generation 2
+a=candidate:a0+B/2 1 udp 2130706432 ::1 1238 typ host generation 2
+a=candidate:a0+B/2 2 udp 2130706432 ::1 1239 typ host generation 2
+a=candidate:a0+B/3 1 udp 2130706432 74.125.127.126 2345 typ srflx raddr 192.168.1.5 rport 2346 generation 2
+a=candidate:a0+B/3 2 udp 2130706432 74.125.127.126 2347 typ srflx raddr 192.168.1.5 rport 2348 generation 2
+a=ice-ufrag:ufrag_voice
+a=ice-pwd:pwd_voice
+a=mid:audio_content_name
+a=sendrecv
+a=rtcp-mux
+a=rtcp-rsize
+a=crypto:1 AES_CM_128_HMAC_SHA1_32 inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj|2^20|1:32 dummy_session_params
+a=rtpmap:111 opus/48000/2
+a=rtpmap:103 ISAC/16000
+a=rtpmap:104 ISAC/32000
+a=ssrc:1 cname:stream_1_cname
+a=ssrc:1 msid:local_stream_1 audio_track_id_1
+a=ssrc:1 mslabel:local_stream_1
+a=ssrc:1 label:audio_track_id_1
+m=video 3457 RTP/SAVPF 120
+c=IN IP4 74.125.224.39
+a=rtcp:3456 IN IP4 74.125.224.39
+a=candidate:a0+B/1 2 udp 2130706432 192.168.1.5 1236 typ host generation 2
+a=candidate:a0+B/1 1 udp 2130706432 192.168.1.5 1237 typ host generation 2
+a=candidate:a0+B/2 2 udp 2130706432 ::1 1240 typ host generation 2
+a=candidate:a0+B/2 1 udp 2130706432 ::1 1241 typ host generation 2
+a=candidate:a0+B/4 2 udp 2130706432 74.125.224.39 3456 typ relay generation 2
+a=candidate:a0+B/4 1 udp 2130706432 74.125.224.39 3457 typ relay generation 2
+a=ice-ufrag:ufrag_video
+a=ice-pwd:pwd_video
+a=mid:video_content_name
+a=sendrecv
+a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj|2^20|1:32
+a=rtpmap:120 VP8/90000
+a=ssrc-group:FEC 2 3
+a=ssrc:2 cname:stream_1_cname
+a=ssrc:2 msid:local_stream_1 video_track_id_1
+a=ssrc:2 mslabel:local_stream_1
+a=ssrc:2 label:video_track_id_1
+a=ssrc:3 cname:stream_1_cname
+a=ssrc:3 msid:local_stream_1 video_track_id_1
+a=ssrc:3 mslabel:local_stream_1
+a=ssrc:3 label:video_track_id_1
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/unittest-2.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/unittest-2.sdp
new file mode 100644
index 0000000000..a35392513f
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/unittest-2.sdp
@@ -0,0 +1,40 @@
+v=0
+o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1
+s=-
+t=0 0
+a=msid-semantic: WMS local_stream_1
+m=audio 9 RTP/SAVPF 111 103 104
+c=IN IP4 0.0.0.0
+a=rtcp:9 IN IP4 0.0.0.0
+a=ice-ufrag:ufrag_voice
+a=ice-pwd:pwd_voice
+a=mid:audio_content_name
+a=sendrecv
+a=rtcp-mux
+a=rtcp-rsize
+a=crypto:1 AES_CM_128_HMAC_SHA1_32 inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj|2^20|1:32 dummy_session_params
+a=rtpmap:111 opus/48000/2
+a=rtpmap:103 ISAC/16000
+a=rtpmap:104 ISAC/32000
+a=ssrc:1 cname:stream_1_cname
+a=ssrc:1 msid:local_stream_1 audio_track_id_1
+a=ssrc:1 mslabel:local_stream_1
+a=ssrc:1 label:audio_track_id_1
+m=video 9 RTP/SAVPF 120
+c=IN IP4 0.0.0.0
+a=rtcp:9 IN IP4 0.0.0.0
+a=ice-ufrag:ufrag_video
+a=ice-pwd:pwd_video
+a=mid:video_content_name
+a=sendrecv
+a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj|2^20|1:32
+a=rtpmap:120 VP8/90000
+a=ssrc-group:FEC 2 3
+a=ssrc:2 cname:stream_1_cname
+a=ssrc:2 msid:local_stream_1 video_track_id_1
+a=ssrc:2 mslabel:local_stream_1
+a=ssrc:2 label:video_track_id_1
+a=ssrc:3 cname:stream_1_cname
+a=ssrc:3 msid:local_stream_1 video_track_id_1
+a=ssrc:3 mslabel:local_stream_1
+a=ssrc:3 label:video_track_id_1
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/unittest-3.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/unittest-3.sdp
new file mode 100644
index 0000000000..50f8e55ef7
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/unittest-3.sdp
@@ -0,0 +1,13 @@
+m=application 9 RTP/SAVPF 101
+c=IN IP4 0.0.0.0
+a=rtcp:9 IN IP4 0.0.0.0
+a=ice-ufrag:ufrag_data
+a=ice-pwd:pwd_data
+a=mid:data_content_name
+a=sendrecv
+a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:FvLcvU2P3ZWmQxgPAgcDu7Zl9vftYElFOjEzhWs5
+a=rtpmap:101 google-data/90000
+a=ssrc:10 cname:data_channel_cname
+a=ssrc:10 msid:data_channel data_channeld0
+a=ssrc:10 mslabel:data_channel
+a=ssrc:10 label:data_channeld0
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/unittest-4.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/unittest-4.sdp
new file mode 100644
index 0000000000..709db42c00
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/unittest-4.sdp
@@ -0,0 +1,11 @@
+v=0
+o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1
+s=-
+t=0 0
+a=msid-semantic: WMS
+m=audio 9 RTP/SAVPF 111 103 104
+c=IN IP4 0.0.0.0
+a=x-google-flag:conference
+m=video 9 RTP/SAVPF 120
+c=IN IP4 0.0.0.0
+a=x-google-flag:conference
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/unittest-5.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/unittest-5.sdp
new file mode 100644
index 0000000000..c440386062
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/unittest-5.sdp
@@ -0,0 +1,5 @@
+v=0
+o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1
+s=-
+t=0 0
+a=msid-semantic: WMS local_stream
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/unittest-6.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/unittest-6.sdp
new file mode 100644
index 0000000000..e07b5647bf
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/unittest-6.sdp
@@ -0,0 +1,12 @@
+m=audio 9 RTP/SAVPF 111
+c=IN IP4 0.0.0.0
+a=rtcp:9 IN IP4 0.0.0.0
+a=ice-ufrag:ufrag_voice
+a=ice-pwd:pwd_voice
+a=mid:audio_content_name
+a=sendrecv
+a=rtpmap:111 opus/48000/2
+a=ssrc:1 cname:stream_1_cname
+a=ssrc:1 msid:local_stream audio_track_id_1
+a=ssrc:1 mslabel:local_stream
+a=ssrc:1 label:audio_track_id_1
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/unittest-7.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/unittest-7.sdp
new file mode 100644
index 0000000000..8bdacc2baa
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/unittest-7.sdp
@@ -0,0 +1,12 @@
+m=video 9 RTP/SAVPF 120
+c=IN IP4 0.0.0.0
+a=rtcp:9 IN IP4 0.0.0.0
+a=ice-ufrag:ufrag_video
+a=ice-pwd:pwd_video
+a=mid:video_content_name
+a=sendrecv
+a=rtpmap:120 VP8/90000
+a=ssrc:2 cname:stream_1_cname
+a=ssrc:2 msid:local_stream video_track_id_1
+a=ssrc:2 mslabel:local_stream
+a=ssrc:2 label:video_track_id_1
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/unittest-8.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/unittest-8.sdp
new file mode 100644
index 0000000000..9688fc46a2
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/unittest-8.sdp
@@ -0,0 +1,64 @@
+v=0
+o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1
+s=-
+t=0 0
+a=msid-semantic: WMS local_stream_1 local_stream_2
+m=audio 2345 RTP/SAVPF 111 103 104
+c=IN IP4 74.125.127.126
+a=rtcp:2347 IN IP4 74.125.127.126
+a=candidate:a0+B/1 1 udp 2130706432 192.168.1.5 1234 typ host generation 2
+a=candidate:a0+B/1 2 udp 2130706432 192.168.1.5 1235 typ host generation 2
+a=candidate:a0+B/2 1 udp 2130706432 ::1 1238 typ host generation 2
+a=candidate:a0+B/2 2 udp 2130706432 ::1 1239 typ host generation 2
+a=candidate:a0+B/3 1 udp 2130706432 74.125.127.126 2345 typ srflx raddr 192.168.1.5 rport 2346 generation 2
+a=candidate:a0+B/3 2 udp 2130706432 74.125.127.126 2347 typ srflx raddr 192.168.1.5 rport 2348 generation 2
+a=ice-ufrag:ufrag_voice
+a=ice-pwd:pwd_voice
+a=mid:audio_content_name
+a=sendrecv
+a=rtcp-mux
+a=rtcp-rsize
+a=crypto:1 AES_CM_128_HMAC_SHA1_32 inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj|2^20|1:32 dummy_session_params
+a=rtpmap:111 opus/48000/2
+a=rtpmap:103 ISAC/16000
+a=rtpmap:104 ISAC/32000
+a=ssrc:1 cname:stream_1_cname
+a=ssrc:1 msid:local_stream_1 audio_track_id_1
+a=ssrc:1 mslabel:local_stream_1
+a=ssrc:1 label:audio_track_id_1
+a=ssrc:4 cname:stream_2_cname
+a=ssrc:4 msid:local_stream_2 audio_track_id_2
+a=ssrc:4 mslabel:local_stream_2
+a=ssrc:4 label:audio_track_id_2
+m=video 3457 RTP/SAVPF 120
+c=IN IP4 74.125.224.39
+a=rtcp:3456 IN IP4 74.125.224.39
+a=candidate:a0+B/1 2 udp 2130706432 192.168.1.5 1236 typ host generation 2
+a=candidate:a0+B/1 1 udp 2130706432 192.168.1.5 1237 typ host generation 2
+a=candidate:a0+B/2 2 udp 2130706432 ::1 1240 typ host generation 2
+a=candidate:a0+B/2 1 udp 2130706432 ::1 1241 typ host generation 2
+a=candidate:a0+B/4 2 udp 2130706432 74.125.224.39 3456 typ relay generation 2
+a=candidate:a0+B/4 1 udp 2130706432 74.125.224.39 3457 typ relay generation 2
+a=ice-ufrag:ufrag_video
+a=ice-pwd:pwd_video
+a=mid:video_content_name
+a=sendrecv
+a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj|2^20|1:32
+a=rtpmap:120 VP8/90000
+a=ssrc-group:FEC 2 3
+a=ssrc:2 cname:stream_1_cname
+a=ssrc:2 msid:local_stream_1 video_track_id_1
+a=ssrc:2 mslabel:local_stream_1
+a=ssrc:2 label:video_track_id_1
+a=ssrc:3 cname:stream_1_cname
+a=ssrc:3 msid:local_stream_1 video_track_id_1
+a=ssrc:3 mslabel:local_stream_1
+a=ssrc:3 label:video_track_id_1
+a=ssrc:5 cname:stream_2_cname
+a=ssrc:5 msid:local_stream_2 video_track_id_2
+a=ssrc:5 mslabel:local_stream_2
+a=ssrc:5 label:video_track_id_2
+a=ssrc:6 cname:stream_2_cname
+a=ssrc:6 msid:local_stream_2 video_track_id_3
+a=ssrc:6 mslabel:local_stream_2
+a=ssrc:6 label:video_track_id_3
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/unittest-9.sdp b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/unittest-9.sdp
new file mode 100644
index 0000000000..8c7c4c7c3d
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp-corpus/unittest-9.sdp
@@ -0,0 +1,66 @@
+v=0
+o=- 18446744069414584320 18446462598732840960 IN IP4 127.0.0.1
+s=-
+t=0 0
+a=msid-semantic: WMS local_stream_1 local_stream_2
+m=audio 2345 RTP/SAVPF 111 103 104
+c=IN IP4 74.125.127.126
+a=rtcp:2347 IN IP4 74.125.127.126
+a=candidate:a0+B/1 1 udp 2130706432 192.168.1.5 1234 typ host generation 2
+a=candidate:a0+B/1 2 udp 2130706432 192.168.1.5 1235 typ host generation 2
+a=candidate:a0+B/2 1 udp 2130706432 ::1 1238 typ host generation 2
+a=candidate:a0+B/2 2 udp 2130706432 ::1 1239 typ host generation 2
+a=candidate:a0+B/3 1 udp 2130706432 74.125.127.126 2345 typ srflx raddr 192.168.1.5 rport 2346 generation 2
+a=candidate:a0+B/3 2 udp 2130706432 74.125.127.126 2347 typ srflx raddr 192.168.1.5 rport 2348 generation 2
+a=ice-ufrag:ufrag_voice
+a=ice-pwd:pwd_voice
+a=mid:audio_content_name
+a=msid:local_stream_1 audio_track_id_1
+a=sendrecv
+a=rtcp-mux
+a=rtcp-rsize
+a=crypto:1 AES_CM_128_HMAC_SHA1_32 inline:NzB4d1BINUAvLEw6UzF3WSJ+PSdFcGdUJShpX1Zj|2^20|1:32 dummy_session_params
+a=rtpmap:111 opus/48000/2
+a=rtpmap:103 ISAC/16000
+a=rtpmap:104 ISAC/32000
+a=ssrc:1 cname:stream_1_cname
+a=ssrc:1 msid:local_stream_1 audio_track_id_1
+a=ssrc:1 mslabel:local_stream_1
+a=ssrc:1 label:audio_track_id_1
+a=ssrc:4 cname:stream_2_cname
+a=ssrc:4 msid:local_stream_2 audio_track_id_2
+a=ssrc:4 mslabel:local_stream_2
+a=ssrc:4 label:audio_track_id_2
+m=video 3457 RTP/SAVPF 120
+c=IN IP4 74.125.224.39
+a=rtcp:3456 IN IP4 74.125.224.39
+a=candidate:a0+B/1 2 udp 2130706432 192.168.1.5 1236 typ host generation 2
+a=candidate:a0+B/1 1 udp 2130706432 192.168.1.5 1237 typ host generation 2
+a=candidate:a0+B/2 2 udp 2130706432 ::1 1240 typ host generation 2
+a=candidate:a0+B/2 1 udp 2130706432 ::1 1241 typ host generation 2
+a=candidate:a0+B/4 2 udp 2130706432 74.125.224.39 3456 typ relay generation 2
+a=candidate:a0+B/4 1 udp 2130706432 74.125.224.39 3457 typ relay generation 2
+a=ice-ufrag:ufrag_video
+a=ice-pwd:pwd_video
+a=mid:video_content_name
+a=msid:local_stream_1 video_track_id_1
+a=sendrecv
+a=crypto:1 AES_CM_128_HMAC_SHA1_80 inline:d0RmdmcmVCspeEc3QGZiNWpVLFJhQX1cfHAwJSoj|2^20|1:32
+a=rtpmap:120 VP8/90000
+a=ssrc-group:FEC 2 3
+a=ssrc:2 cname:stream_1_cname
+a=ssrc:2 msid:local_stream_1 video_track_id_1
+a=ssrc:2 mslabel:local_stream_1
+a=ssrc:2 label:video_track_id_1
+a=ssrc:3 cname:stream_1_cname
+a=ssrc:3 msid:local_stream_1 video_track_id_1
+a=ssrc:3 mslabel:local_stream_1
+a=ssrc:3 label:video_track_id_1
+a=ssrc:5 cname:stream_2_cname
+a=ssrc:5 msid:local_stream_2 video_track_id_2
+a=ssrc:5 mslabel:local_stream_2
+a=ssrc:5 label:video_track_id_2
+a=ssrc:6 cname:stream_2_cname
+a=ssrc:6 msid:local_stream_2 video_track_id_3
+a=ssrc:6 mslabel:local_stream_2
+a=ssrc:6 label:video_track_id_3
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp.tokens b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp.tokens
new file mode 100644
index 0000000000..ddfdad5811
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/sdp.tokens
@@ -0,0 +1,56 @@
+"0.0.0.0"
+"127.0.0.1"
+"application"
+"audio"
+"candidate"
+"cname"
+"conference"
+"crypto"
+"default"
+"extmap"
+"fingerprint"
+"fmtp"
+"generation"
+"group"
+"host"
+"ice-lite"
+"ice-options"
+"ice-pwd"
+"ice-ufrag"
+"inactive"
+"IP4"
+"IP6"
+"ISAC"
+"label"
+"mid"
+"msid"
+"msid-semantic"
+"mslabel"
+"network-cost"
+"network-id"
+"prflx"
+"pwd"
+"raddr"
+"recvonly"
+"relay"
+"rport"
+"rtcp"
+"rtcp-fb"
+"rtcp-mux"
+"rtcp-rsize"
+"rtpmap"
+"sctpmap"
+"sctp-port"
+"sendonly"
+"sendrecv"
+"setup"
+"srflx"
+"ssrc"
+"ssrc-group"
+"tcptype"
+"typ"
+"ufrag"
+"video"
+"webrtc-datachannel"
+"WMS"
+"x-google-flag" \ No newline at end of file
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/0.stun b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/0.stun
new file mode 100644
index 0000000000..205997706f
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/0.stun
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/1.stun b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/1.stun
new file mode 100644
index 0000000000..1f82c03ffa
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/1.stun
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/10.stun b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/10.stun
new file mode 100644
index 0000000000..a6b06b2be8
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/10.stun
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/11.stun b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/11.stun
new file mode 100644
index 0000000000..1f82c03ffa
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/11.stun
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/12.stun b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/12.stun
new file mode 100644
index 0000000000..cb91baa250
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/12.stun
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/13.stun b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/13.stun
new file mode 100644
index 0000000000..63298fce7d
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/13.stun
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/14.stun b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/14.stun
new file mode 100644
index 0000000000..31f9f732d4
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/14.stun
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/15.stun b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/15.stun
new file mode 100644
index 0000000000..3d15a67193
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/15.stun
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/16.stun b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/16.stun
new file mode 100644
index 0000000000..8ccf0af26d
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/16.stun
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/17.stun b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/17.stun
new file mode 100644
index 0000000000..9c3efa0b80
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/17.stun
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/2.stun b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/2.stun
new file mode 100644
index 0000000000..50fe614adb
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/2.stun
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/3.stun b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/3.stun
new file mode 100644
index 0000000000..50fe614adb
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/3.stun
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/4.stun b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/4.stun
new file mode 100644
index 0000000000..a6b06b2be8
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/4.stun
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/5.stun b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/5.stun
new file mode 100644
index 0000000000..c0a79fa7ab
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/5.stun
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/6.stun b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/6.stun
new file mode 100644
index 0000000000..1f43a4787d
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/6.stun
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/7.stun b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/7.stun
new file mode 100644
index 0000000000..f5e824a68d
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/7.stun
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/8.stun b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/8.stun
new file mode 100644
index 0000000000..99f4e3bcf8
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/8.stun
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/9.stun b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/9.stun
new file mode 100644
index 0000000000..cbbcab4e74
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/9.stun
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/validator-crash-1.stun b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/validator-crash-1.stun
new file mode 100644
index 0000000000..5428c38d75
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun-corpus/validator-crash-1.stun
Binary files differ
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun.tokens b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun.tokens
new file mode 100644
index 0000000000..e01130f12e
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/corpora/stun.tokens
@@ -0,0 +1,2 @@
+"2112A442"
+"12214A24"
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/flexfec_header_reader_fuzzer.cc b/third_party/libwebrtc/webrtc/test/fuzzers/flexfec_header_reader_fuzzer.cc
new file mode 100644
index 0000000000..a5694ea300
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/flexfec_header_reader_fuzzer.cc
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <algorithm>
+
+#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
+#include "modules/rtp_rtcp/source/flexfec_header_reader_writer.h"
+#include "modules/rtp_rtcp/source/forward_error_correction.h"
+#include "rtc_base/scoped_ref_ptr.h"
+
+namespace webrtc {
+
+using Packet = ForwardErrorCorrection::Packet;
+using ReceivedFecPacket = ForwardErrorCorrection::ReceivedFecPacket;
+
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ ReceivedFecPacket packet;
+ packet.pkt = rtc::scoped_refptr<Packet>(new Packet());
+ const size_t packet_size =
+ std::min(size, static_cast<size_t>(IP_PACKET_SIZE));
+ memcpy(packet.pkt->data, data, packet_size);
+ packet.pkt->length = packet_size;
+
+ FlexfecHeaderReader flexfec_reader;
+ flexfec_reader.ReadFecHeader(&packet);
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/flexfec_receiver_fuzzer.cc b/third_party/libwebrtc/webrtc/test/fuzzers/flexfec_receiver_fuzzer.cc
new file mode 100644
index 0000000000..14208bd7ec
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/flexfec_receiver_fuzzer.cc
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <algorithm>
+
+#include "modules/rtp_rtcp/include/flexfec_receiver.h"
+#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
+#include "modules/rtp_rtcp/source/byte_io.h"
+#include "modules/rtp_rtcp/source/rtp_packet_received.h"
+#include "rtc_base/basictypes.h"
+
+namespace webrtc {
+
+namespace {
+class DummyCallback : public RecoveredPacketReceiver {
+ void OnRecoveredPacket(const uint8_t* packet, size_t length) override {}
+};
+} // namespace
+
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ constexpr size_t kMinDataNeeded = 12;
+ if (size < kMinDataNeeded) {
+ return;
+ }
+
+ uint32_t flexfec_ssrc;
+ memcpy(&flexfec_ssrc, data + 0, 4);
+ uint16_t flexfec_seq_num;
+ memcpy(&flexfec_seq_num, data + 4, 2);
+ uint32_t media_ssrc;
+ memcpy(&media_ssrc, data + 6, 4);
+ uint16_t media_seq_num;
+ memcpy(&media_seq_num, data + 10, 2);
+
+ DummyCallback callback;
+ FlexfecReceiver receiver(flexfec_ssrc, media_ssrc, &callback);
+
+ std::unique_ptr<uint8_t[]> packet;
+ size_t packet_length;
+ size_t i = kMinDataNeeded;
+ while (i < size) {
+ packet_length = kRtpHeaderSize + data[i++];
+ packet = std::unique_ptr<uint8_t[]>(new uint8_t[packet_length]);
+ if (i + packet_length >= size) {
+ break;
+ }
+ memcpy(packet.get(), data + i, packet_length);
+ i += packet_length;
+ if (i < size && data[i++] % 2 == 0) {
+ // Simulate FlexFEC packet.
+ ByteWriter<uint16_t>::WriteBigEndian(packet.get() + 2, flexfec_seq_num++);
+ ByteWriter<uint32_t>::WriteBigEndian(packet.get() + 8, flexfec_ssrc);
+ } else {
+ // Simulate media packet.
+ ByteWriter<uint16_t>::WriteBigEndian(packet.get() + 2, media_seq_num++);
+ ByteWriter<uint32_t>::WriteBigEndian(packet.get() + 8, media_ssrc);
+ }
+ RtpPacketReceived parsed_packet;
+ if (parsed_packet.Parse(packet.get(), packet_length)) {
+ receiver.OnRtpPacket(parsed_packet);
+ }
+ }
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/flexfec_sender_fuzzer.cc b/third_party/libwebrtc/webrtc/test/fuzzers/flexfec_sender_fuzzer.cc
new file mode 100644
index 0000000000..64bc3ed247
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/flexfec_sender_fuzzer.cc
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <memory>
+
+#include "modules/rtp_rtcp/include/flexfec_sender.h"
+#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
+#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
+#include "modules/rtp_rtcp/source/byte_io.h"
+#include "system_wrappers/include/clock.h"
+
+namespace webrtc {
+
+namespace {
+
+constexpr int kFlexfecPayloadType = 123;
+constexpr uint32_t kMediaSsrc = 1234;
+constexpr uint32_t kFlexfecSsrc = 5678;
+const std::vector<RtpExtension> kNoRtpHeaderExtensions;
+const std::vector<RtpExtensionSize> kNoRtpHeaderExtensionSizes;
+
+} // namespace
+
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ size_t i = 0;
+ if (size < 5) {
+ return;
+ }
+
+ SimulatedClock clock(1 + data[i++]);
+ FlexfecSender sender(kFlexfecPayloadType, kFlexfecSsrc, kMediaSsrc,
+ kNoRtpHeaderExtensions, kNoRtpHeaderExtensionSizes,
+ nullptr /* rtp_state */, &clock);
+ FecProtectionParams params = {
+ data[i++], static_cast<int>(data[i++] % 100),
+ data[i++] <= 127 ? kFecMaskRandom : kFecMaskBursty};
+ sender.SetFecParameters(params);
+ uint16_t seq_num = data[i++];
+
+ while (i + 1 < size) {
+ // Everything past the base RTP header (12 bytes) is payload,
+ // from the perspective of FlexFEC.
+ size_t payload_size = data[i++];
+ if (i + kRtpHeaderSize + payload_size >= size)
+ break;
+ std::unique_ptr<uint8_t[]> packet(
+ new uint8_t[kRtpHeaderSize + payload_size]);
+ memcpy(packet.get(), &data[i], kRtpHeaderSize + payload_size);
+ i += kRtpHeaderSize + payload_size;
+ ByteWriter<uint16_t>::WriteBigEndian(&packet[2], seq_num++);
+ ByteWriter<uint32_t>::WriteBigEndian(&packet[8], kMediaSsrc);
+ RtpPacketToSend rtp_packet(nullptr);
+ if (!rtp_packet.Parse(packet.get(), kRtpHeaderSize + payload_size))
+ break;
+ sender.AddRtpPacketAndGenerateFec(rtp_packet);
+ if (sender.FecAvailable()) {
+ std::vector<std::unique_ptr<RtpPacketToSend>> fec_packets =
+ sender.GetFecPackets();
+ }
+ }
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/h264_bitstream_parser_fuzzer.cc b/third_party/libwebrtc/webrtc/test/fuzzers/h264_bitstream_parser_fuzzer.cc
new file mode 100644
index 0000000000..a9384d73f3
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/h264_bitstream_parser_fuzzer.cc
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include <stdint.h>
+
+#include "common_video/h264/h264_bitstream_parser.h"
+
+namespace webrtc {
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ H264BitstreamParser h264_bitstream_parser;
+ h264_bitstream_parser.ParseBitstream(data, size);
+ int qp;
+ h264_bitstream_parser.GetLastSliceQp(&qp);
+}
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/h264_depacketizer_fuzzer.cc b/third_party/libwebrtc/webrtc/test/fuzzers/h264_depacketizer_fuzzer.cc
new file mode 100644
index 0000000000..2cefb1e1b3
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/h264_depacketizer_fuzzer.cc
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "modules/rtp_rtcp/source/rtp_format_h264.h"
+
+namespace webrtc {
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ RtpDepacketizerH264 depacketizer;
+ RtpDepacketizer::ParsedPayload parsed_payload;
+ depacketizer.Parse(&parsed_payload, data, size);
+}
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/neteq_rtp_fuzzer.cc b/third_party/libwebrtc/webrtc/test/fuzzers/neteq_rtp_fuzzer.cc
new file mode 100644
index 0000000000..0f26367b68
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/neteq_rtp_fuzzer.cc
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <cmath>
+#include <memory>
+#include <vector>
+
+#include "api/array_view.h"
+#include "modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.h"
+#include "modules/audio_coding/neteq/tools/audio_checksum.h"
+#include "modules/audio_coding/neteq/tools/encode_neteq_input.h"
+#include "modules/audio_coding/neteq/tools/neteq_test.h"
+#include "modules/rtp_rtcp/source/byte_io.h"
+
+namespace webrtc {
+namespace test {
+namespace {
+constexpr int kPayloadType = 95;
+
+class SineGenerator : public EncodeNetEqInput::Generator {
+ public:
+ explicit SineGenerator(int sample_rate_hz)
+ : sample_rate_hz_(sample_rate_hz) {}
+
+ rtc::ArrayView<const int16_t> Generate(size_t num_samples) override {
+ if (samples_.size() < num_samples) {
+ samples_.resize(num_samples);
+ }
+
+ rtc::ArrayView<int16_t> output(samples_.data(), num_samples);
+ for (auto& x : output) {
+ x = static_cast<int16_t>(2000.0 * std::sin(phase_));
+ phase_ += 2 * kPi * kFreqHz / sample_rate_hz_;
+ }
+ return output;
+ }
+
+ private:
+ static constexpr int kFreqHz = 300; // The sinewave frequency.
+ const int sample_rate_hz_;
+ const double kPi = std::acos(-1);
+ std::vector<int16_t> samples_;
+ double phase_ = 0.0;
+};
+
+class FuzzRtpInput : public NetEqInput {
+ public:
+ explicit FuzzRtpInput(rtc::ArrayView<const uint8_t> data) : data_(data) {
+ AudioEncoderPcm16B::Config config;
+ config.payload_type = kPayloadType;
+ config.sample_rate_hz = 32000;
+ std::unique_ptr<AudioEncoder> encoder(new AudioEncoderPcm16B(config));
+ std::unique_ptr<EncodeNetEqInput::Generator> generator(
+ new SineGenerator(config.sample_rate_hz));
+ input_.reset(new EncodeNetEqInput(std::move(generator), std::move(encoder),
+ std::numeric_limits<int64_t>::max()));
+ packet_ = input_->PopPacket();
+ FuzzHeader();
+ }
+
+ rtc::Optional<int64_t> NextPacketTime() const override {
+ return packet_->time_ms;
+ }
+
+ rtc::Optional<int64_t> NextOutputEventTime() const override {
+ return input_->NextOutputEventTime();
+ }
+
+ std::unique_ptr<PacketData> PopPacket() override {
+ RTC_DCHECK(packet_);
+ std::unique_ptr<PacketData> packet_to_return = std::move(packet_);
+ packet_ = input_->PopPacket();
+ FuzzHeader();
+ return packet_to_return;
+ }
+
+ void AdvanceOutputEvent() override { return input_->AdvanceOutputEvent(); }
+
+ bool ended() const override { return ended_; }
+
+ rtc::Optional<RTPHeader> NextHeader() const override {
+ RTC_DCHECK(packet_);
+ return packet_->header;
+ }
+
+ private:
+ void FuzzHeader() {
+ constexpr size_t kNumBytesToFuzz = 11;
+ if (data_ix_ + kNumBytesToFuzz > data_.size()) {
+ ended_ = true;
+ return;
+ }
+ RTC_DCHECK(packet_);
+ const size_t start_ix = data_ix_;
+ packet_->header.payloadType =
+ ByteReader<uint8_t>::ReadLittleEndian(&data_[data_ix_]);
+ packet_->header.payloadType &= 0x7F;
+ data_ix_ += sizeof(uint8_t);
+ packet_->header.sequenceNumber =
+ ByteReader<uint16_t>::ReadLittleEndian(&data_[data_ix_]);
+ data_ix_ += sizeof(uint16_t);
+ packet_->header.timestamp =
+ ByteReader<uint32_t>::ReadLittleEndian(&data_[data_ix_]);
+ data_ix_ += sizeof(uint32_t);
+ packet_->header.ssrc =
+ ByteReader<uint32_t>::ReadLittleEndian(&data_[data_ix_]);
+ data_ix_ += sizeof(uint32_t);
+ RTC_CHECK_EQ(data_ix_ - start_ix, kNumBytesToFuzz);
+ }
+
+ bool ended_ = false;
+ rtc::ArrayView<const uint8_t> data_;
+ size_t data_ix_ = 0;
+ std::unique_ptr<EncodeNetEqInput> input_;
+ std::unique_ptr<PacketData> packet_;
+};
+} // namespace
+
+void FuzzOneInputTest(const uint8_t* data, size_t size) {
+ std::unique_ptr<FuzzRtpInput> input(
+ new FuzzRtpInput(rtc::ArrayView<const uint8_t>(data, size)));
+ std::unique_ptr<AudioChecksum> output(new AudioChecksum);
+ NetEqTest::Callbacks callbacks;
+ NetEq::Config config;
+ NetEqTest::DecoderMap codecs;
+ codecs[0] = std::make_pair(NetEqDecoder::kDecoderPCMu, "pcmu");
+ codecs[8] = std::make_pair(NetEqDecoder::kDecoderPCMa, "pcma");
+ codecs[103] = std::make_pair(NetEqDecoder::kDecoderISAC, "isac");
+ codecs[104] = std::make_pair(NetEqDecoder::kDecoderISACswb, "isac-swb");
+ codecs[111] = std::make_pair(NetEqDecoder::kDecoderOpus, "opus");
+ codecs[93] = std::make_pair(NetEqDecoder::kDecoderPCM16B, "pcm16-nb");
+ codecs[94] = std::make_pair(NetEqDecoder::kDecoderPCM16Bwb, "pcm16-wb");
+ codecs[96] =
+ std::make_pair(NetEqDecoder::kDecoderPCM16Bswb48kHz, "pcm16-swb48");
+ codecs[9] = std::make_pair(NetEqDecoder::kDecoderG722, "g722");
+ codecs[106] = std::make_pair(NetEqDecoder::kDecoderAVT, "avt");
+ codecs[114] = std::make_pair(NetEqDecoder::kDecoderAVT16kHz, "avt-16");
+ codecs[115] = std::make_pair(NetEqDecoder::kDecoderAVT32kHz, "avt-32");
+ codecs[116] = std::make_pair(NetEqDecoder::kDecoderAVT48kHz, "avt-48");
+ codecs[117] = std::make_pair(NetEqDecoder::kDecoderRED, "red");
+ codecs[13] = std::make_pair(NetEqDecoder::kDecoderCNGnb, "cng-nb");
+ codecs[98] = std::make_pair(NetEqDecoder::kDecoderCNGwb, "cng-wb");
+ codecs[99] = std::make_pair(NetEqDecoder::kDecoderCNGswb32kHz, "cng-swb32");
+ codecs[100] = std::make_pair(NetEqDecoder::kDecoderCNGswb48kHz, "cng-swb48");
+ // This is the payload type that will be used for encoding.
+ codecs[kPayloadType] =
+ std::make_pair(NetEqDecoder::kDecoderPCM16Bswb32kHz, "pcm16-swb32");
+ NetEqTest::ExtDecoderMap ext_codecs;
+
+ NetEqTest test(config, codecs, ext_codecs, std::move(input),
+ std::move(output), callbacks);
+ test.Run();
+}
+
+} // namespace test
+
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ test::FuzzOneInputTest(data, size);
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/neteq_signal_fuzzer.cc b/third_party/libwebrtc/webrtc/test/fuzzers/neteq_signal_fuzzer.cc
new file mode 100644
index 0000000000..f0b79113ae
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/neteq_signal_fuzzer.cc
@@ -0,0 +1,262 @@
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <cmath>
+#include <limits>
+#include <memory>
+#include <vector>
+
+#include "api/array_view.h"
+#include "modules/audio_coding/codecs/pcm16b/audio_encoder_pcm16b.h"
+#include "modules/audio_coding/neteq/tools/audio_checksum.h"
+#include "modules/audio_coding/neteq/tools/encode_neteq_input.h"
+#include "modules/audio_coding/neteq/tools/neteq_test.h"
+#include "modules/rtp_rtcp/source/byte_io.h"
+#include "rtc_base/numerics/safe_conversions.h"
+#include "rtc_base/random.h"
+
+namespace webrtc {
+namespace test {
+namespace {
+// Helper class to take care of the fuzzer input, read from it, and keep track
+// of when the end of the data has been reached.
+class FuzzData {
+ public:
+ explicit FuzzData(rtc::ArrayView<const uint8_t> data) : data_(data) {}
+
+ // Returns true if n bytes can be read.
+ bool CanReadBytes(size_t n) const { return data_ix_ + n <= data_.size(); }
+
+ // Reads and returns data of type T.
+ template <typename T>
+ T Read() {
+ RTC_CHECK(CanReadBytes(sizeof(T)));
+ T x = ByteReader<T>::ReadLittleEndian(&data_[data_ix_]);
+ data_ix_ += sizeof(T);
+ return x;
+ }
+
+ // Reads and returns data of type T. Returns default_value if not enough
+ // fuzzer input remains to read a T.
+ template <typename T>
+ T ReadOrDefaultValue(T default_value) {
+ if (!CanReadBytes(sizeof(T))) {
+ return default_value;
+ }
+ return Read<T>();
+ }
+
+ // Like ReadOrDefaultValue, but replaces the value 0 with default_value.
+ template <typename T>
+ T ReadOrDefaultValueNotZero(T default_value) {
+ static_assert(std::is_integral<T>::value, "");
+ T x = ReadOrDefaultValue(default_value);
+ return x == 0 ? default_value : x;
+ }
+
+ // Returns one of the elements from the provided input array. The selection
+ // is based on the fuzzer input data. If not enough fuzzer data is available,
+ // the method will return the first element in the input array. The reason for
+ // not flaggin this as an error is that the method is called from the
+ // FuzzSignalInput constructor, and in constructors we typically do not handle
+ // errors. The code will work anyway, and the fuzzer will likely see that
+ // providing more data will actually make this method return something else.
+ template <typename T>
+ T SelectOneOf(rtc::ArrayView<const T> select_from) {
+ RTC_CHECK_LE(select_from.size(), std::numeric_limits<uint8_t>::max());
+ // Read an index between 0 and select_from.size() - 1 from the fuzzer data.
+ uint8_t index = ReadOrDefaultValue<uint8_t>(0) % select_from.size();
+ return select_from[index];
+ }
+
+ private:
+ rtc::ArrayView<const uint8_t> data_;
+ size_t data_ix_ = 0;
+};
+
+// Generate a mixture of sine wave and gaussian noise.
+class SineAndNoiseGenerator : public EncodeNetEqInput::Generator {
+ public:
+ // The noise generator is seeded with a value from the fuzzer data, but 0 is
+ // avoided (since it is not allowed by the Random class).
+ SineAndNoiseGenerator(int sample_rate_hz, FuzzData* fuzz_data)
+ : sample_rate_hz_(sample_rate_hz),
+ fuzz_data_(*fuzz_data),
+ noise_generator_(fuzz_data_.ReadOrDefaultValueNotZero<uint64_t>(1)) {}
+
+ // Generates num_samples of the sine-gaussian mixture.
+ rtc::ArrayView<const int16_t> Generate(size_t num_samples) override {
+ if (samples_.size() < num_samples) {
+ samples_.resize(num_samples);
+ }
+
+ rtc::ArrayView<int16_t> output(samples_.data(), num_samples);
+ // Randomize an amplitude between 0 and 32768; use 65000/2 if we are out of
+ // fuzzer data.
+ const float amplitude = fuzz_data_.ReadOrDefaultValue<uint16_t>(65000) / 2;
+ // Randomize a noise standard deviation between 0 and 1999.
+ const float noise_std = fuzz_data_.ReadOrDefaultValue<uint16_t>(0) % 2000;
+ for (auto& x : output) {
+ x = rtc::saturated_cast<int16_t>(amplitude * std::sin(phase_) +
+ noise_generator_.Gaussian(0, noise_std));
+ phase_ += 2 * kPi * kFreqHz / sample_rate_hz_;
+ }
+ return output;
+ }
+
+ private:
+ static constexpr int kFreqHz = 300; // The sinewave frequency.
+ const int sample_rate_hz_;
+ const double kPi = std::acos(-1);
+ std::vector<int16_t> samples_;
+ double phase_ = 0.0;
+ FuzzData& fuzz_data_;
+ Random noise_generator_;
+};
+
+class FuzzSignalInput : public NetEqInput {
+ public:
+ explicit FuzzSignalInput(FuzzData* fuzz_data,
+ int sample_rate,
+ uint8_t payload_type)
+ : fuzz_data_(*fuzz_data) {
+ AudioEncoderPcm16B::Config config;
+ config.payload_type = payload_type;
+ config.sample_rate_hz = sample_rate;
+ std::unique_ptr<AudioEncoder> encoder(new AudioEncoderPcm16B(config));
+ std::unique_ptr<EncodeNetEqInput::Generator> generator(
+ new SineAndNoiseGenerator(config.sample_rate_hz, fuzz_data));
+ input_.reset(new EncodeNetEqInput(std::move(generator), std::move(encoder),
+ std::numeric_limits<int64_t>::max()));
+ packet_ = input_->PopPacket();
+
+ // Select an output event period. This is how long time we wait between each
+ // call to NetEq::GetAudio. 10 ms is nominal, 9 and 11 ms will both lead to
+ // clock drift (in different directions).
+ constexpr int output_event_periods[] = {9, 10, 11};
+ output_event_period_ms_ =
+ fuzz_data_.SelectOneOf(rtc::ArrayView<const int>(output_event_periods));
+ }
+
+ rtc::Optional<int64_t> NextPacketTime() const override {
+ return packet_->time_ms;
+ }
+
+ rtc::Optional<int64_t> NextOutputEventTime() const override {
+ return next_output_event_ms_;
+ }
+
+ std::unique_ptr<PacketData> PopPacket() override {
+ RTC_DCHECK(packet_);
+ std::unique_ptr<PacketData> packet_to_return = std::move(packet_);
+ do {
+ packet_ = input_->PopPacket();
+ // If the next value from the fuzzer input is 0, the packet is discarded
+ // and the next one is pulled from the source.
+ } while (fuzz_data_.CanReadBytes(1) && fuzz_data_.Read<uint8_t>() == 0);
+ if (fuzz_data_.CanReadBytes(1)) {
+ // Generate jitter by setting an offset for the arrival time.
+ const int8_t arrival_time_offset_ms = fuzz_data_.Read<int8_t>();
+ // The arrival time can not be before the previous packets.
+ packet_->time_ms = std::max(packet_to_return->time_ms,
+ packet_->time_ms + arrival_time_offset_ms);
+ } else {
+ // Mark that we are at the end of the test. However, the current packet is
+ // still valid (but it may not have been fuzzed as expected).
+ ended_ = true;
+ }
+ return packet_to_return;
+ }
+
+ void AdvanceOutputEvent() override {
+ next_output_event_ms_ += output_event_period_ms_;
+ }
+
+ bool ended() const override { return ended_; }
+
+ rtc::Optional<RTPHeader> NextHeader() const override {
+ RTC_DCHECK(packet_);
+ return packet_->header;
+ }
+
+ private:
+ bool ended_ = false;
+ FuzzData& fuzz_data_;
+ std::unique_ptr<EncodeNetEqInput> input_;
+ std::unique_ptr<PacketData> packet_;
+ int64_t next_output_event_ms_ = 0;
+ int64_t output_event_period_ms_ = 10;
+};
+} // namespace
+
+void FuzzOneInputTest(const uint8_t* data, size_t size) {
+ if (size < 1)
+ return;
+ FuzzData fuzz_data(rtc::ArrayView<const uint8_t>(data, size));
+
+ // Allowed sample rates and payload types used in the test.
+ std::pair<int, uint8_t> rate_types[] = {
+ {8000, 93}, {16000, 94}, {32000, 95}, {48000, 96}};
+ const auto rate_type = fuzz_data.SelectOneOf(
+ rtc::ArrayView<const std::pair<int, uint8_t>>(rate_types));
+ const int sample_rate = rate_type.first;
+ const uint8_t payload_type = rate_type.second;
+
+ // Set up the input signal generator.
+ std::unique_ptr<FuzzSignalInput> input(
+ new FuzzSignalInput(&fuzz_data, sample_rate, payload_type));
+
+ // Output sink for the test.
+ std::unique_ptr<AudioChecksum> output(new AudioChecksum);
+
+ // Configure NetEq and the NetEqTest object.
+ NetEqTest::Callbacks callbacks;
+ NetEq::Config config;
+ config.enable_post_decode_vad = true;
+ config.enable_fast_accelerate = true;
+ NetEqTest::DecoderMap codecs;
+ codecs[0] = std::make_pair(NetEqDecoder::kDecoderPCMu, "pcmu");
+ codecs[8] = std::make_pair(NetEqDecoder::kDecoderPCMa, "pcma");
+ codecs[103] = std::make_pair(NetEqDecoder::kDecoderISAC, "isac");
+ codecs[104] = std::make_pair(NetEqDecoder::kDecoderISACswb, "isac-swb");
+ codecs[111] = std::make_pair(NetEqDecoder::kDecoderOpus, "opus");
+ codecs[9] = std::make_pair(NetEqDecoder::kDecoderG722, "g722");
+ codecs[106] = std::make_pair(NetEqDecoder::kDecoderAVT, "avt");
+ codecs[114] = std::make_pair(NetEqDecoder::kDecoderAVT16kHz, "avt-16");
+ codecs[115] = std::make_pair(NetEqDecoder::kDecoderAVT32kHz, "avt-32");
+ codecs[116] = std::make_pair(NetEqDecoder::kDecoderAVT48kHz, "avt-48");
+ codecs[117] = std::make_pair(NetEqDecoder::kDecoderRED, "red");
+ codecs[13] = std::make_pair(NetEqDecoder::kDecoderCNGnb, "cng-nb");
+ codecs[98] = std::make_pair(NetEqDecoder::kDecoderCNGwb, "cng-wb");
+ codecs[99] = std::make_pair(NetEqDecoder::kDecoderCNGswb32kHz, "cng-swb32");
+ codecs[100] = std::make_pair(NetEqDecoder::kDecoderCNGswb48kHz, "cng-swb48");
+ // One of these payload types will be used for encoding.
+ codecs[rate_types[0].second] =
+ std::make_pair(NetEqDecoder::kDecoderPCM16B, "pcm16-nb");
+ codecs[rate_types[1].second] =
+ std::make_pair(NetEqDecoder::kDecoderPCM16Bwb, "pcm16-wb");
+ codecs[rate_types[2].second] =
+ std::make_pair(NetEqDecoder::kDecoderPCM16Bswb32kHz, "pcm16-swb32");
+ codecs[rate_types[3].second] =
+ std::make_pair(NetEqDecoder::kDecoderPCM16Bswb48kHz, "pcm16-swb48");
+ NetEqTest::ExtDecoderMap ext_codecs;
+
+ NetEqTest test(config, codecs, ext_codecs, std::move(input),
+ std::move(output), callbacks);
+ test.Run();
+}
+
+} // namespace test
+
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ test::FuzzOneInputTest(data, size);
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/packet_buffer_fuzzer.cc b/third_party/libwebrtc/webrtc/test/fuzzers/packet_buffer_fuzzer.cc
new file mode 100644
index 0000000000..df6baf48e5
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/packet_buffer_fuzzer.cc
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/video_coding/packet_buffer.h"
+#include "system_wrappers/include/clock.h"
+
+namespace webrtc {
+
+namespace {
+class NullCallback : public video_coding::OnReceivedFrameCallback {
+ void OnReceivedFrame(std::unique_ptr<video_coding::RtpFrameObject> frame) {}
+};
+} // namespace
+
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ // Two bytes for the sequence number,
+ // one byte for |is_first_packet_in_frame| and |markerBit|.
+ constexpr size_t kMinDataNeeded = 3;
+ if (size < kMinDataNeeded) {
+ return;
+ }
+
+ VCMPacket packet;
+ NullCallback callback;
+ SimulatedClock clock(0);
+ rtc::scoped_refptr<video_coding::PacketBuffer> packet_buffer(
+ video_coding::PacketBuffer::Create(&clock, 8, 1024, &callback));
+
+ size_t i = kMinDataNeeded;
+ while (i < size) {
+ memcpy(&packet.seqNum, &data[i - kMinDataNeeded], 2);
+ packet.is_first_packet_in_frame = data[i] & 1;
+ packet.markerBit = data[i] & 2;
+ packet_buffer->InsertPacket(&packet);
+ i += kMinDataNeeded;
+ }
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/pseudotcp_parser_fuzzer.cc b/third_party/libwebrtc/webrtc/test/fuzzers/pseudotcp_parser_fuzzer.cc
new file mode 100644
index 0000000000..90123c3206
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/pseudotcp_parser_fuzzer.cc
@@ -0,0 +1,48 @@
+/*
+* Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+*
+* Use of this source code is governed by a BSD-style license
+* that can be found in the LICENSE file in the root of the source
+* tree. An additional intellectual property rights grant can be found
+* in the file PATENTS. All contributing project authors may
+* be found in the AUTHORS file in the root of the source tree.
+*/
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "p2p/base/pseudotcp.h"
+#include "rtc_base/thread.h"
+
+namespace webrtc {
+class FakeIPseudoTcpNotify : public cricket::IPseudoTcpNotify {
+ public:
+ void OnTcpOpen(cricket::PseudoTcp* tcp) {}
+ void OnTcpReadable(cricket::PseudoTcp* tcp) {}
+ void OnTcpWriteable(cricket::PseudoTcp* tcp) {}
+ void OnTcpClosed(cricket::PseudoTcp* tcp, uint32_t error) {}
+
+ cricket::IPseudoTcpNotify::WriteResult TcpWritePacket(cricket::PseudoTcp* tcp,
+ const char* buffer,
+ size_t len) {
+ return cricket::IPseudoTcpNotify::WriteResult::WR_SUCCESS;
+ }
+};
+
+struct Environment {
+ explicit Environment(cricket::IPseudoTcpNotify* notifier):
+ ptcp(notifier, 0) {
+ }
+
+ // We need the thread to avoid some uninteresting crashes, since the
+ // production code expects there to be a thread object available.
+ rtc::AutoThread thread;
+ cricket::PseudoTcp ptcp;
+};
+
+Environment* env = new Environment(new FakeIPseudoTcpNotify());
+
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ env->ptcp.NotifyPacket(reinterpret_cast<const char*>(data), size);
+}
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/residual_echo_detector_fuzzer.cc b/third_party/libwebrtc/webrtc/test/fuzzers/residual_echo_detector_fuzzer.cc
new file mode 100644
index 0000000000..c3c81237c8
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/residual_echo_detector_fuzzer.cc
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <math.h>
+#include <string.h>
+
+#include <algorithm>
+#include <bitset>
+#include <vector>
+
+#include "modules/audio_processing/residual_echo_detector.h"
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ // Number of times to update the echo detector.
+ constexpr size_t kNrOfUpdates = 7;
+ // Each round of updates requires a call to both AnalyzeRender and
+ // AnalyzeCapture, so the amount of needed input bytes doubles. Also, two
+ // bytes are used to set the call order.
+ constexpr size_t kNrOfNeededInputBytes = 2 * kNrOfUpdates * sizeof(float) + 2;
+ // The maximum audio energy that an audio frame can have is equal to the
+ // number of samples in the frame multiplied by 2^30. We use a single sample
+ // to represent an audio frame in this test, so it should have a maximum value
+ // equal to the square root of that value.
+ const float maxFuzzedValue = sqrtf(20 * 48) * 32768;
+ if (size < kNrOfNeededInputBytes) {
+ return;
+ }
+ size_t read_idx = 0;
+ // Use the first two bytes to choose the call order.
+ uint16_t call_order_int;
+ memcpy(&call_order_int, &data[read_idx], 2);
+ read_idx += 2;
+ std::bitset<16> call_order(call_order_int);
+
+ ResidualEchoDetector echo_detector;
+ std::vector<float> input(1);
+ // Call AnalyzeCaptureAudio once to prevent the flushing of the buffer.
+ echo_detector.AnalyzeCaptureAudio(input);
+ for (size_t i = 0; i < 2 * kNrOfUpdates; ++i) {
+ // Convert 4 input bytes to a float.
+ RTC_DCHECK_LE(read_idx + sizeof(float), size);
+ memcpy(input.data(), &data[read_idx], sizeof(float));
+ read_idx += sizeof(float);
+ if (!isfinite(input[0]) || fabs(input[0]) > maxFuzzedValue) {
+ // Ignore infinity, nan values and values that are unrealistically large.
+ continue;
+ }
+ if (call_order[i]) {
+ echo_detector.AnalyzeRenderAudio(input);
+ } else {
+ echo_detector.AnalyzeCaptureAudio(input);
+ }
+ }
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/rtcp_receiver_fuzzer.cc b/third_party/libwebrtc/webrtc/test/fuzzers/rtcp_receiver_fuzzer.cc
new file mode 100644
index 0000000000..8782f0c0a8
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/rtcp_receiver_fuzzer.cc
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "modules/rtp_rtcp/source/rtcp_receiver.h"
+#include "rtc_base/checks.h"
+#include "system_wrappers/include/clock.h"
+
+namespace webrtc {
+namespace {
+
+class NullModuleRtpRtcp : public RTCPReceiver::ModuleRtpRtcp {
+ public:
+ void SetTmmbn(std::vector<rtcp::TmmbItem>) override {}
+ void OnRequestSendReport() override {}
+ void OnReceivedNack(const std::vector<uint16_t>&) override {};
+ void OnReceivedRtcpReportBlocks(const ReportBlockList&) override {};
+};
+
+}
+
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ NullModuleRtpRtcp rtp_rtcp_module;
+ SimulatedClock clock(1234);
+
+ RTCPReceiver receiver(&clock, false, nullptr, nullptr, nullptr, nullptr,
+ nullptr, &rtp_rtcp_module);
+
+ receiver.IncomingPacket(data, size);
+}
+} // namespace webrtc
+
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/rtp_header_fuzzer.cc b/third_party/libwebrtc/webrtc/test/fuzzers/rtp_header_fuzzer.cc
new file mode 100644
index 0000000000..09bf81197e
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/rtp_header_fuzzer.cc
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <bitset>
+
+#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
+#include "modules/rtp_rtcp/source/rtp_packet_received.h"
+#include "modules/rtp_rtcp/source/rtp_utility.h"
+
+namespace webrtc {
+// We decide which header extensions to register by reading two bytes
+// from the beginning of |data| and interpreting it as a bitmask over
+// the RTPExtensionType enum. This assert ensures two bytes are enough.
+static_assert(kRtpExtensionNumberOfExtensions <= 16,
+ "Insufficient bits read to configure all header extensions. Add "
+ "an extra byte and update the switches.");
+
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ if (size <= 2)
+ return;
+
+ // Don't use the configuration byte as part of the packet.
+ std::bitset<16> extensionMask(*reinterpret_cast<const uint16_t*>(data));
+ data += 2;
+ size -= 2;
+
+ RtpPacketReceived::ExtensionManager extensions;
+ // Skip i = 0 since it maps to ExtensionNone and extension id = 0 is invalid.
+ for (int i = 0; i < kRtpExtensionNumberOfExtensions; i++) {
+ RTPExtensionType extension_type = static_cast<RTPExtensionType>(i);
+ if (extensionMask[i] && extension_type != kRtpExtensionNone) {
+ // Extensions are registered with an ID, which you signal to the
+ // peer so they know what to expect. This code only cares about
+ // parsing so the value of the ID isn't relevant; we use i.
+ extensions.RegisterByType(i, extension_type);
+ }
+ }
+
+ RTPHeader rtp_header;
+ RtpUtility::RtpHeaderParser rtp_parser(data, size);
+ rtp_parser.Parse(&rtp_header, &extensions);
+}
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/rtp_packet_fuzzer.cc b/third_party/libwebrtc/webrtc/test/fuzzers/rtp_packet_fuzzer.cc
new file mode 100644
index 0000000000..9a30c88eaa
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/rtp_packet_fuzzer.cc
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/rtp_rtcp/include/rtp_header_extension_map.h"
+#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
+#include "modules/rtp_rtcp/source/rtp_packet_received.h"
+
+namespace webrtc {
+
+// We decide which header extensions to register by reading two bytes
+// from the beginning of |data| and interpreting it as a bitmask over
+// the RTPExtensionType enum. This assert ensures two bytes are enough.
+static_assert(kRtpExtensionNumberOfExtensions <= 16,
+ "Insufficient bits read to configure all header extensions. Add "
+ "an extra byte and update the switches.");
+
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ if (size <= 2)
+ return;
+
+ // Don't use the configuration bytes as part of the packet.
+ std::bitset<16> extensionMask(*reinterpret_cast<const uint16_t*>(data));
+ data += 2;
+ size -= 2;
+
+ RtpPacketReceived::ExtensionManager extensions;
+ // Skip i = 0 since it maps to ExtensionNone and extension id = 0 is invalid.
+ for (int i = 1; i < kRtpExtensionNumberOfExtensions; i++) {
+ RTPExtensionType extension_type = static_cast<RTPExtensionType>(i);
+ if (extensionMask[i] && extension_type != kRtpExtensionNone) {
+ // Extensions are registered with an ID, which you signal to the
+ // peer so they know what to expect. This code only cares about
+ // parsing so the value of the ID isn't relevant; we use i.
+ extensions.RegisterByType(i, extension_type);
+ }
+ }
+
+ RtpPacketReceived packet(&extensions);
+ packet.Parse(data, size);
+
+ // Call packet accessors because they have extra checks.
+ packet.Marker();
+ packet.PayloadType();
+ packet.SequenceNumber();
+ packet.Timestamp();
+ packet.Ssrc();
+ packet.Csrcs();
+
+ // Each extension has its own getter. It is supported behaviour to
+ // call GetExtension on an extension which was not registered, so we
+ // don't check the bitmask here.
+ for (int i = 0; i < kRtpExtensionNumberOfExtensions; i++) {
+ switch (static_cast<RTPExtensionType>(i)) {
+ case kRtpExtensionNone:
+ case kRtpExtensionNumberOfExtensions:
+ break;
+ case kRtpExtensionTransmissionTimeOffset:
+ int32_t offset;
+ packet.GetExtension<TransmissionOffset>(&offset);
+ break;
+ case kRtpExtensionAudioLevel:
+ bool voice_activity;
+ uint8_t audio_level;
+ packet.GetExtension<AudioLevel>(&voice_activity, &audio_level);
+ break;
+ case kRtpExtensionAbsoluteSendTime:
+ uint32_t sendtime;
+ packet.GetExtension<AbsoluteSendTime>(&sendtime);
+ break;
+ case kRtpExtensionVideoRotation:
+ uint8_t rotation;
+ packet.GetExtension<VideoOrientation>(&rotation);
+ break;
+ case kRtpExtensionTransportSequenceNumber:
+ uint16_t seqnum;
+ packet.GetExtension<TransportSequenceNumber>(&seqnum);
+ break;
+ case kRtpExtensionPlayoutDelay:
+ PlayoutDelay playout;
+ packet.GetExtension<PlayoutDelayLimits>(&playout);
+ break;
+ case kRtpExtensionVideoContentType:
+ VideoContentType content_type;
+ packet.GetExtension<VideoContentTypeExtension>(&content_type);
+ break;
+ case kRtpExtensionVideoTiming:
+ VideoSendTiming timing;
+ packet.GetExtension<VideoTimingExtension>(&timing);
+ break;
+ case kRtpExtensionRtpStreamId: {
+ std::string rsid;
+ packet.GetExtension<RtpStreamId>(&rsid);
+ break;
+ }
+ case kRtpExtensionRepairedRtpStreamId: {
+ std::string rsid;
+ packet.GetExtension<RepairedRtpStreamId>(&rsid);
+ break;
+ }
+ case kRtpExtensionMid: {
+ std::string mid;
+ packet.GetExtension<RtpMid>(&mid);
+ break;
+ }
+ case kRtpExtensionCsrcAudioLevel: {
+ CsrcAudioLevelList levels;
+ packet.GetExtension<CsrcAudioLevel>(&levels);
+ break;
+ }
+ }
+ }
+}
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/sdp_parser_fuzzer.cc b/third_party/libwebrtc/webrtc/test/fuzzers/sdp_parser_fuzzer.cc
new file mode 100644
index 0000000000..e47156c571
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/sdp_parser_fuzzer.cc
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "api/jsepsessiondescription.h"
+
+namespace webrtc {
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ std::string message(reinterpret_cast<const char*>(data), size);
+ webrtc::SdpParseError error;
+
+ std::unique_ptr<webrtc::SessionDescriptionInterface> sdp(
+ CreateSessionDescription("offer", message, &error));
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/stun_parser_fuzzer.cc b/third_party/libwebrtc/webrtc/test/fuzzers/stun_parser_fuzzer.cc
new file mode 100644
index 0000000000..02e42bcbc8
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/stun_parser_fuzzer.cc
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "p2p/base/stun.h"
+
+namespace webrtc {
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ const char* message = reinterpret_cast<const char*>(data);
+
+ // Normally we'd check the integrity first, but those checks are
+ // fuzzed separately in stun_validator_fuzzer.cc. We still want to
+ // fuzz this target since the integrity checks could be forged by a
+ // malicious adversary who receives a call.
+ std::unique_ptr<cricket::IceMessage> stun_msg(new cricket::IceMessage());
+ rtc::ByteBufferReader buf(message, size);
+ stun_msg->Read(&buf);
+}
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/stun_validator_fuzzer.cc b/third_party/libwebrtc/webrtc/test/fuzzers/stun_validator_fuzzer.cc
new file mode 100644
index 0000000000..9873ff40fb
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/stun_validator_fuzzer.cc
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "p2p/base/stun.h"
+
+namespace webrtc {
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ const char* message = reinterpret_cast<const char*>(data);
+
+ cricket::StunMessage::ValidateFingerprint(message, size);
+ cricket::StunMessage::ValidateMessageIntegrity(message, size, "");
+}
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/transport_feedback_packet_loss_tracker_fuzzer.cc b/third_party/libwebrtc/webrtc/test/fuzzers/transport_feedback_packet_loss_tracker_fuzzer.cc
new file mode 100644
index 0000000000..31bc1639e2
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/transport_feedback_packet_loss_tracker_fuzzer.cc
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <algorithm>
+
+#include "api/array_view.h"
+#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
+#include "modules/rtp_rtcp/source/byte_io.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
+#include "voice_engine/transport_feedback_packet_loss_tracker.h"
+
+namespace webrtc {
+
+namespace {
+
+template <typename T>
+T FuzzInput(const uint8_t** data, size_t* size) {
+ RTC_CHECK_GE(*size, sizeof(T));
+ T rc = ByteReader<T>::ReadBigEndian(*data);
+ *data += sizeof(T);
+ *size -= sizeof(T);
+ return rc;
+}
+
+size_t FuzzInRange(const uint8_t** data,
+ size_t* size,
+ size_t lower,
+ size_t upper) {
+ // Achieve a close-to-uniform distribution.
+ RTC_CHECK_LE(lower, upper);
+ RTC_CHECK_LT(upper - lower, 1 << (8 * sizeof(uint16_t)));
+ const size_t range = upper - lower;
+ const uint16_t fuzzed = FuzzInput<uint16_t>(data, size);
+ const size_t offset = (static_cast<float>(fuzzed) / 0x10000) * (range + 1);
+ RTC_CHECK_LE(offset, range); // (fuzzed <= 0xffff) -> (offset < range + 1)
+ return lower + offset;
+}
+
+class TransportFeedbackGenerator {
+ public:
+ explicit TransportFeedbackGenerator(const uint8_t** data, size_t* size)
+ : data_(data), size_(size) {}
+
+ bool GetNextTransportFeedbackVector(
+ std::vector<PacketFeedback>* feedback_vector) {
+ RTC_CHECK(feedback_vector->empty());
+
+ uint16_t remaining_packets = 0;
+ if (!ReadData<uint16_t>(&remaining_packets)) {
+ return false;
+ }
+
+ if (remaining_packets == 0) {
+ return true;
+ }
+
+ uint16_t seq_num;
+ if (!ReadData<uint16_t>(&seq_num)) { // Fuzz base sequence number.
+ return false;
+ }
+
+ while (remaining_packets > 0) {
+ uint8_t status_byte = 0;
+ if (!ReadData<uint8_t>(&status_byte)) {
+ return false;
+ }
+ // Each status byte contains 8 statuses.
+ for (size_t i = 0; i < 8 && remaining_packets > 0; ++i) {
+ // Any positive integer signals reception. kNotReceived signals loss.
+ // Other values are just illegal.
+ constexpr int64_t kArrivalTimeMs = 1234;
+
+ const bool received = (status_byte & (0x01 << i));
+ feedback_vector->emplace_back(PacketFeedback(
+ received ? kArrivalTimeMs : PacketFeedback::kNotReceived,
+ seq_num++));
+ --remaining_packets;
+ }
+ }
+
+ return true;
+ }
+
+ private:
+ template <typename T>
+ bool ReadData(T* value) {
+ if (*size_ < sizeof(T)) {
+ return false;
+ } else {
+ *value = FuzzInput<T>(data_, size_);
+ return true;
+ }
+ }
+
+ const uint8_t** data_;
+ size_t* size_;
+};
+
+bool Setup(const uint8_t** data,
+ size_t* size,
+ std::unique_ptr<TransportFeedbackPacketLossTracker>* tracker) {
+ if (*size < 3 * sizeof(uint16_t)) {
+ return false;
+ }
+
+ constexpr size_t kSeqNumHalf = 0x8000u;
+
+ const int64_t max_window_size_ms = FuzzInRange(data, size, 1, 1 << 16);
+ const size_t plr_min_num_packets = FuzzInRange(data, size, 1, kSeqNumHalf);
+ const size_t rplr_min_num_pairs = FuzzInRange(data, size, 1, kSeqNumHalf - 1);
+
+ tracker->reset(new TransportFeedbackPacketLossTracker(
+ max_window_size_ms, plr_min_num_packets, rplr_min_num_pairs));
+
+ return true;
+}
+
+bool FuzzSequenceNumberDelta(const uint8_t** data,
+ size_t* size,
+ uint16_t* delta) {
+ // Fuzz with a higher likelihood for immediately consecutive pairs
+ // than you would by just fuzzing 1-256.
+ // Note: Values higher than 256 still possible, but that would be in a new
+ // packet-sending block.
+ // * Fuzzed value in [0 : 127] (50% chance) -> delta is 1.
+ // * Fuzzed value in [128 : 255] (50% chance) -> delta in range [2 : 129].
+ if (*size < sizeof(uint8_t)) {
+ return false;
+ }
+ uint8_t fuzzed = FuzzInput<uint8_t>(data, size);
+ *delta = (fuzzed < 128) ? 1 : (fuzzed - 128 + 2);
+ return true;
+}
+
+bool FuzzClockAdvancement(const uint8_t** data,
+ size_t* size,
+ int64_t* time_ms) {
+ // Fuzzing 64-bit worth of delta would be extreme overkill, as 32-bit is
+ // already ~49 days long. We'll fuzz deltas up to a smaller value, and this
+ // way also guarantee that wrap-around is impossible, as in real life.
+
+ // Higher likelihood for more likely cases:
+ // 5% chance of delta = 0.
+ // 20% chance of delta in range [1 : 10] (uniformly distributed)
+ // 55% chance of delta in range [11 : 500] (uniformly distributed)
+ // 20% chance of delta in range [501 : 10000] (uniformly distributed)
+ struct ProbabilityDistribution {
+ float probability;
+ size_t lower;
+ size_t higher;
+ };
+ constexpr ProbabilityDistribution clock_probability_distribution[] = {
+ {0.05, 0, 0}, {0.20, 1, 10}, {0.55, 11, 500}, {0.20, 501, 10000}};
+
+ if (*size < sizeof(uint8_t)) {
+ return false;
+ }
+ const float fuzzed = FuzzInput<uint8_t>(data, size) / 256.0f;
+
+ float cumulative_probability = 0;
+ for (const auto& dist : clock_probability_distribution) {
+ cumulative_probability += dist.probability;
+ if (fuzzed < cumulative_probability) {
+ if (dist.lower == dist.higher) {
+ *time_ms += dist.lower;
+ return true;
+ } else if (*size < sizeof(uint16_t)) {
+ return false;
+ } else {
+ *time_ms += FuzzInRange(data, size, dist.lower, dist.higher);
+ return true;
+ }
+ }
+ }
+
+ RTC_NOTREACHED();
+ return false;
+}
+
+bool FuzzPacketSendBlock(
+ std::unique_ptr<TransportFeedbackPacketLossTracker>& tracker,
+ const uint8_t** data,
+ size_t* size,
+ int64_t* time_ms) {
+ // We want to test with block lengths between 1 and 2^16, inclusive.
+ if (*size < sizeof(uint8_t)) {
+ return false;
+ }
+ size_t packet_block_len = 1 + FuzzInput<uint8_t>(data, size);
+
+ // First sent sequence number uniformly selected.
+ if (*size < sizeof(uint16_t)) {
+ return false;
+ }
+ uint16_t seq_num = FuzzInput<uint16_t>(data, size);
+ tracker->OnPacketAdded(seq_num, *time_ms);
+ tracker->Validate();
+
+ bool may_continue = FuzzClockAdvancement(data, size, time_ms);
+ if (!may_continue) {
+ return false;
+ }
+
+ for (size_t i = 1; i < packet_block_len; i++) {
+ uint16_t delta;
+ may_continue = FuzzSequenceNumberDelta(data, size, &delta);
+ if (!may_continue)
+ return false;
+ may_continue = FuzzClockAdvancement(data, size, time_ms);
+ if (!may_continue)
+ return false;
+ seq_num += delta;
+ tracker->OnPacketAdded(seq_num, *time_ms);
+ tracker->Validate();
+ }
+
+ return true;
+}
+
+bool FuzzTransportFeedbackBlock(
+ std::unique_ptr<TransportFeedbackPacketLossTracker>& tracker,
+ const uint8_t** data,
+ size_t* size) {
+ // Fuzz the number of back-to-back feedbacks. At least one, or this would
+ // be meaningless - we'd go straight back to fuzzing another packet
+ // transmission block.
+ if (*size < sizeof(uint8_t)) {
+ return false;
+ }
+
+ size_t feedbacks_num = 1 + (FuzzInput<uint8_t>(data, size) & 0x3f);
+ TransportFeedbackGenerator feedback_generator(data, size);
+
+ for (size_t i = 0; i < feedbacks_num; i++) {
+ std::vector<PacketFeedback> feedback_vector;
+ bool may_continue =
+ feedback_generator.GetNextTransportFeedbackVector(&feedback_vector);
+ if (!may_continue) {
+ return false;
+ }
+ tracker->OnPacketFeedbackVector(feedback_vector);
+ tracker->Validate();
+ }
+
+ return true;
+}
+
+} // namespace
+
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ std::unique_ptr<TransportFeedbackPacketLossTracker> tracker;
+ bool may_continue;
+
+ may_continue = Setup(&data, &size, &tracker);
+
+ // We never expect this to wrap around, so it makes sense to just start with
+ // a sane value, and keep on incrementing by a fuzzed delta.
+ if (size < sizeof(uint32_t)) {
+ return;
+ }
+ int64_t time_ms = FuzzInput<uint32_t>(&data, &size);
+
+ while (may_continue) {
+ may_continue = FuzzPacketSendBlock(tracker, &data, &size, &time_ms);
+ if (!may_continue) {
+ return;
+ }
+ may_continue = FuzzTransportFeedbackBlock(tracker, &data, &size);
+ }
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/turn_unwrap_fuzzer.cc b/third_party/libwebrtc/webrtc/test/fuzzers/turn_unwrap_fuzzer.cc
new file mode 100644
index 0000000000..ed9f34d711
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/turn_unwrap_fuzzer.cc
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+
+#include "media/base/turnutils.h"
+
+namespace webrtc {
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ size_t content_position;
+ size_t content_size;
+ cricket::UnwrapTurnPacket(data, size, &content_position, &content_size);
+}
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/ulpfec_generator_fuzzer.cc b/third_party/libwebrtc/webrtc/test/fuzzers/ulpfec_generator_fuzzer.cc
new file mode 100644
index 0000000000..03728f6bac
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/ulpfec_generator_fuzzer.cc
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <memory>
+
+#include "modules/rtp_rtcp/source/byte_io.h"
+#include "modules/rtp_rtcp/source/fec_test_helper.h"
+#include "modules/rtp_rtcp/source/ulpfec_generator.h"
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+
+namespace {
+constexpr uint8_t kFecPayloadType = 96;
+constexpr uint8_t kRedPayloadType = 97;
+} // namespace
+
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ UlpfecGenerator generator;
+ size_t i = 0;
+ if (size < 4)
+ return;
+ FecProtectionParams params = {
+ data[i++] % 128, static_cast<int>(data[i++] % 10), kFecMaskBursty};
+ generator.SetFecParameters(params);
+ uint16_t seq_num = data[i++];
+
+ while (i + 3 < size) {
+ size_t rtp_header_length = data[i++] % 10 + 12;
+ size_t payload_size = data[i++] % 10;
+ if (i + payload_size + rtp_header_length + 2 > size)
+ break;
+ std::unique_ptr<uint8_t[]> packet(
+ new uint8_t[payload_size + rtp_header_length]);
+ memcpy(packet.get(), &data[i], payload_size + rtp_header_length);
+ ByteWriter<uint16_t>::WriteBigEndian(&packet[2], seq_num++);
+ i += payload_size + rtp_header_length;
+ // Make sure sequence numbers are increasing.
+ const bool protect = data[i++] % 2 == 1;
+ if (protect) {
+ generator.AddRtpPacketAndGenerateFec(packet.get(), payload_size,
+ rtp_header_length);
+ }
+ const size_t num_fec_packets = generator.NumAvailableFecPackets();
+ if (num_fec_packets > 0) {
+ std::vector<std::unique_ptr<RedPacket>> fec_packets =
+ generator.GetUlpfecPacketsAsRed(kRedPayloadType, kFecPayloadType, 100,
+ rtp_header_length);
+ RTC_CHECK_EQ(num_fec_packets, fec_packets.size());
+ }
+ }
+}
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/ulpfec_header_reader_fuzzer.cc b/third_party/libwebrtc/webrtc/test/fuzzers/ulpfec_header_reader_fuzzer.cc
new file mode 100644
index 0000000000..6a6394f763
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/ulpfec_header_reader_fuzzer.cc
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <algorithm>
+
+#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
+#include "modules/rtp_rtcp/source/forward_error_correction.h"
+#include "modules/rtp_rtcp/source/ulpfec_header_reader_writer.h"
+#include "rtc_base/scoped_ref_ptr.h"
+
+namespace webrtc {
+
+using Packet = ForwardErrorCorrection::Packet;
+using ReceivedFecPacket = ForwardErrorCorrection::ReceivedFecPacket;
+
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ ReceivedFecPacket packet;
+ packet.pkt = rtc::scoped_refptr<Packet>(new Packet());
+ const size_t packet_size =
+ std::min(size, static_cast<size_t>(IP_PACKET_SIZE));
+ memcpy(packet.pkt->data, data, packet_size);
+ packet.pkt->length = packet_size;
+
+ UlpfecHeaderReader ulpfec_reader;
+ ulpfec_reader.ReadFecHeader(&packet);
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/ulpfec_receiver_fuzzer.cc b/third_party/libwebrtc/webrtc/test/fuzzers/ulpfec_receiver_fuzzer.cc
new file mode 100644
index 0000000000..c850fec996
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/ulpfec_receiver_fuzzer.cc
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <algorithm>
+
+#include "modules/rtp_rtcp/include/ulpfec_receiver.h"
+#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
+#include "modules/rtp_rtcp/source/byte_io.h"
+#include "modules/rtp_rtcp/source/rtp_packet_received.h"
+#include "rtc_base/basictypes.h"
+
+namespace webrtc {
+
+namespace {
+class DummyCallback : public RecoveredPacketReceiver {
+ void OnRecoveredPacket(const uint8_t* packet, size_t length) override {}
+};
+} // namespace
+
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ constexpr size_t kMinDataNeeded = 12;
+ if (size < kMinDataNeeded) {
+ return;
+ }
+
+ uint32_t ulpfec_ssrc = ByteReader<uint32_t>::ReadLittleEndian(data + 0);
+ uint16_t ulpfec_seq_num = ByteReader<uint16_t>::ReadLittleEndian(data + 4);
+ uint32_t media_ssrc = ByteReader<uint32_t>::ReadLittleEndian(data + 6);
+ uint16_t media_seq_num = ByteReader<uint16_t>::ReadLittleEndian(data + 10);
+
+ DummyCallback callback;
+ std::unique_ptr<UlpfecReceiver> receiver(
+ UlpfecReceiver::Create(ulpfec_ssrc, &callback));
+
+ std::unique_ptr<uint8_t[]> packet;
+ size_t packet_length;
+ size_t i = kMinDataNeeded;
+ while (i < size) {
+ packet_length = kRtpHeaderSize + data[i++];
+ packet = std::unique_ptr<uint8_t[]>(new uint8_t[packet_length]);
+ if (i + packet_length >= size) {
+ break;
+ }
+ memcpy(packet.get(), data + i, packet_length);
+ i += packet_length;
+ // Overwrite the RTPHeader fields for the sequence number and SSRC with
+ // consistent values for either a received UlpFEC packet or received media
+ // packet. (We're still relying on libfuzzer to manage to generate packet
+ // headers that interact together; this just ensures that we have two
+ // consistent streams).
+ if (i < size && data[i++] % 2 == 0) {
+ // Simulate UlpFEC packet.
+ ByteWriter<uint16_t>::WriteBigEndian(packet.get() + 2, ulpfec_seq_num++);
+ ByteWriter<uint32_t>::WriteBigEndian(packet.get() + 8, ulpfec_ssrc);
+ } else {
+ // Simulate media packet.
+ ByteWriter<uint16_t>::WriteBigEndian(packet.get() + 2, media_seq_num++);
+ ByteWriter<uint32_t>::WriteBigEndian(packet.get() + 8, media_ssrc);
+ }
+ RtpPacketReceived parsed_packet;
+ RTPHeader parsed_header;
+ if (parsed_packet.Parse(packet.get(), packet_length)) {
+ parsed_packet.GetHeader(&parsed_header);
+ receiver->AddReceivedRedPacket(parsed_header, packet.get(),
+ packet_length, 0);
+ }
+ }
+
+ receiver->ProcessReceivedFec();
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/vp8_depacketizer_fuzzer.cc b/third_party/libwebrtc/webrtc/test/fuzzers/vp8_depacketizer_fuzzer.cc
new file mode 100644
index 0000000000..bd9ac8ffb2
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/vp8_depacketizer_fuzzer.cc
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "modules/rtp_rtcp/source/rtp_format_vp8.h"
+
+namespace webrtc {
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ RtpDepacketizerVp8 depacketizer;
+ RtpDepacketizer::ParsedPayload parsed_payload;
+ depacketizer.Parse(&parsed_payload, data, size);
+}
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/vp8_qp_parser_fuzzer.cc b/third_party/libwebrtc/webrtc/test/fuzzers/vp8_qp_parser_fuzzer.cc
new file mode 100644
index 0000000000..2ecfd820c8
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/vp8_qp_parser_fuzzer.cc
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "modules/video_coding/utility/vp8_header_parser.h"
+
+namespace webrtc {
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ int qp;
+ vp8::GetQp(data, size, &qp);
+}
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/vp9_depacketizer_fuzzer.cc b/third_party/libwebrtc/webrtc/test/fuzzers/vp9_depacketizer_fuzzer.cc
new file mode 100644
index 0000000000..8f62b429ff
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/vp9_depacketizer_fuzzer.cc
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "modules/rtp_rtcp/source/rtp_format_vp9.h"
+
+namespace webrtc {
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ RtpDepacketizerVp9 depacketizer;
+ RtpDepacketizer::ParsedPayload parsed_payload;
+ depacketizer.Parse(&parsed_payload, data, size);
+}
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/vp9_qp_parser_fuzzer.cc b/third_party/libwebrtc/webrtc/test/fuzzers/vp9_qp_parser_fuzzer.cc
new file mode 100644
index 0000000000..3cff95f5b7
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/vp9_qp_parser_fuzzer.cc
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "modules/video_coding/utility/vp9_uncompressed_header_parser.h"
+
+namespace webrtc {
+void FuzzOneInput(const uint8_t* data, size_t size) {
+ int qp;
+ vp9::GetQp(data, size, &qp);
+}
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/fuzzers/webrtc_fuzzer_main.cc b/third_party/libwebrtc/webrtc/test/fuzzers/webrtc_fuzzer_main.cc
new file mode 100644
index 0000000000..ca4bc15c71
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/fuzzers/webrtc_fuzzer_main.cc
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+// This file is intended to provide a common interface for fuzzing functions.
+// It's intended to set sane defaults, such as removing logging for further
+// fuzzing efficiency.
+
+#include "rtc_base/logging.h"
+
+namespace {
+bool g_initialized = false;
+void InitializeWebRtcFuzzDefaults() {
+ if (g_initialized)
+ return;
+
+ // Remove default logging to prevent huge slowdowns.
+ // TODO(pbos): Disable in Chromium: http://crbug.com/561667
+#if !defined(WEBRTC_CHROMIUM_BUILD)
+ rtc::LogMessage::LogToDebug(rtc::LS_NONE);
+#endif // !defined(WEBRTC_CHROMIUM_BUILD)
+
+ g_initialized = true;
+}
+}
+
+namespace webrtc {
+extern void FuzzOneInput(const uint8_t* data, size_t size);
+} // namespace webrtc
+
+extern "C" int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size) {
+ InitializeWebRtcFuzzDefaults();
+ webrtc::FuzzOneInput(data, size);
+ return 0;
+}
diff --git a/third_party/libwebrtc/webrtc/test/gl/gl_renderer.cc b/third_party/libwebrtc/webrtc/test/gl/gl_renderer.cc
new file mode 100644
index 0000000000..ef7ab9c126
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/gl/gl_renderer.cc
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/gl/gl_renderer.h"
+
+#include <string.h>
+
+#include "common_video/libyuv/include/webrtc_libyuv.h"
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+namespace test {
+
+GlRenderer::GlRenderer()
+ : is_init_(false), buffer_(NULL), width_(0), height_(0) {}
+
+void GlRenderer::Init() {
+ RTC_DCHECK(!is_init_);
+ is_init_ = true;
+
+ glGenTextures(1, &texture_);
+}
+
+void GlRenderer::Destroy() {
+ if (!is_init_) {
+ return;
+ }
+
+ is_init_ = false;
+
+ delete[] buffer_;
+ buffer_ = NULL;
+
+ glDeleteTextures(1, &texture_);
+}
+
+void GlRenderer::ResizeViewport(size_t width, size_t height) {
+ // TODO(pbos): Aspect ratio, letterbox the video.
+ glViewport(0, 0, width, height);
+
+ glMatrixMode(GL_PROJECTION);
+ glLoadIdentity();
+ glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
+ glOrtho(0.0f, 1.0f, 1.0f, 0.0f, -1.0f, 1.0f);
+ glMatrixMode(GL_MODELVIEW);
+}
+
+void GlRenderer::ResizeVideo(size_t width, size_t height) {
+ RTC_DCHECK(is_init_);
+ width_ = width;
+ height_ = height;
+
+ buffer_size_ = width * height * 4; // BGRA
+
+ delete[] buffer_;
+ buffer_ = new uint8_t[buffer_size_];
+ RTC_DCHECK(buffer_);
+ memset(buffer_, 0, buffer_size_);
+ glBindTexture(GL_TEXTURE_2D, texture_);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_BGRA,
+ GL_UNSIGNED_INT_8_8_8_8, static_cast<GLvoid*>(buffer_));
+}
+
+void GlRenderer::OnFrame(const webrtc::VideoFrame& frame) {
+ RTC_DCHECK(is_init_);
+
+ if (static_cast<size_t>(frame.width()) != width_ ||
+ static_cast<size_t>(frame.height()) != height_) {
+ ResizeVideo(frame.width(), frame.height());
+ }
+
+ webrtc::ConvertFromI420(frame, VideoType::kBGRA, 0, buffer_);
+
+ glEnable(GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, texture_);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width_, height_, GL_BGRA,
+ GL_UNSIGNED_INT_8_8_8_8, buffer_);
+
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+
+ glLoadIdentity();
+
+ glBegin(GL_QUADS);
+ {
+ glTexCoord2f(0.0f, 0.0f);
+ glVertex3f(0.0f, 0.0f, 0.0f);
+
+ glTexCoord2f(0.0f, 1.0f);
+ glVertex3f(0.0f, 1.0f, 0.0f);
+
+ glTexCoord2f(1.0f, 1.0f);
+ glVertex3f(1.0f, 1.0f, 0.0f);
+
+ glTexCoord2f(1.0f, 0.0f);
+ glVertex3f(1.0f, 0.0f, 0.0f);
+ }
+ glEnd();
+
+ glBindTexture(GL_TEXTURE_2D, 0);
+ glFlush();
+}
+} // test
+} // webrtc
diff --git a/third_party/libwebrtc/webrtc/test/gl/gl_renderer.h b/third_party/libwebrtc/webrtc/test/gl/gl_renderer.h
new file mode 100644
index 0000000000..382739d307
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/gl/gl_renderer.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef TEST_GL_GL_RENDERER_H_
+#define TEST_GL_GL_RENDERER_H_
+
+#ifdef WEBRTC_MAC
+#include <OpenGL/gl.h>
+#else
+#include <GL/gl.h>
+#endif
+
+#include "test/video_renderer.h"
+#include "typedefs.h" // NOLINT(build/include)
+
+
+namespace webrtc {
+namespace test {
+
+class GlRenderer : public VideoRenderer {
+ public:
+ void OnFrame(const webrtc::VideoFrame& frame) override;
+
+ protected:
+ GlRenderer();
+
+ void Init();
+ void Destroy();
+
+ void ResizeViewport(size_t width, size_t height);
+
+ private:
+ bool is_init_;
+ uint8_t* buffer_;
+ GLuint texture_;
+ size_t width_, height_, buffer_size_;
+
+ void ResizeVideo(size_t width, size_t height);
+};
+} // test
+} // webrtc
+
+#endif // TEST_GL_GL_RENDERER_H_
diff --git a/third_party/libwebrtc/webrtc/test/gmock.h b/third_party/libwebrtc/webrtc/test/gmock.h
new file mode 100644
index 0000000000..f137d080a4
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/gmock.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef TEST_GMOCK_H_
+#define TEST_GMOCK_H_
+
+#include "rtc_base/ignore_wundef.h"
+
+RTC_PUSH_IGNORING_WUNDEF()
+#include "testing/gmock/include/gmock/gmock.h"
+RTC_POP_IGNORING_WUNDEF()
+
+#endif // TEST_GMOCK_H_
diff --git a/third_party/libwebrtc/webrtc/test/gtest.h b/third_party/libwebrtc/webrtc/test/gtest.h
new file mode 100644
index 0000000000..928ec496f0
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/gtest.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef TEST_GTEST_H_
+#define TEST_GTEST_H_
+
+#include "rtc_base/ignore_wundef.h"
+
+RTC_PUSH_IGNORING_WUNDEF()
+#include "testing/gtest/include/gtest/gtest.h"
+RTC_POP_IGNORING_WUNDEF()
+
+// GTEST_HAS_DEATH_TEST is set to 1 when death tests are supported, but appears
+// to be left unset if they're not supported. Rather than depend on this, we
+// set it to 0 ourselves here.
+#ifndef GTEST_HAS_DEATH_TEST
+#define GTEST_HAS_DEATH_TEST 0
+#endif
+
+#endif // TEST_GTEST_H_
diff --git a/third_party/libwebrtc/webrtc/test/ios/Info.plist b/third_party/libwebrtc/webrtc/test/ios/Info.plist
new file mode 100644
index 0000000000..e02ce91165
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/ios/Info.plist
@@ -0,0 +1,45 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleDisplayName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIdentifier</key>
+ <string>${IOS_BUNDLE_ID_PREFIX}.gtest.${GTEST_BUNDLE_ID_SUFFIX:rfc1034identifier}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>LSRequiresIPhoneOS</key>
+ <true/>
+ <key>NSAppTransportSecurity</key>
+ <dict>
+ <key>NSAllowsArbitraryLoads</key>
+ <true/>
+ </dict>
+ <key>UIFileSharingEnabled</key>
+ <true/>
+ <key>UISupportedInterfaceOrientation</key>
+ <array>
+ <string>UIInterfaceOrientationPortrait</string>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ </array>
+ <key>UIBackgroundModes</key>
+ <array>
+ <string>fetch</string>
+ </array>
+ <key>NSMicrophoneUsageDescription</key>
+ <string>For testing purposes</string>
+</dict>
+</plist>
diff --git a/third_party/libwebrtc/webrtc/test/ios/test_support.h b/third_party/libwebrtc/webrtc/test/ios/test_support.h
new file mode 100644
index 0000000000..7bc2993b9e
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/ios/test_support.h
@@ -0,0 +1,25 @@
+/*
+ * Copyright 2017 The WebRTC Project Authors. All rights reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef TEST_IOS_TEST_SUPPORT_H_
+#define TEST_IOS_TEST_SUPPORT_H_
+
+namespace rtc {
+namespace test {
+// Launches an iOS app that serves as a host for a test suite.
+// This is necessary as iOS doesn't like processes without a gui
+// running for longer than a few seconds.
+void RunTestsFromIOSApp();
+void InitTestSuite(int (*test_suite)(void), int argc, char* argv[]);
+
+} // namespace test
+} // namespace rtc
+
+#endif // TEST_IOS_TEST_SUPPORT_H_
diff --git a/third_party/libwebrtc/webrtc/test/ios/test_support.mm b/third_party/libwebrtc/webrtc/test/ios/test_support.mm
new file mode 100644
index 0000000000..603bc8c19c
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/ios/test_support.mm
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2017 The WebRTC Project Authors. All rights reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#import <UIKit/UIKit.h>
+
+#include "test/ios/test_support.h"
+
+#import "sdk/objc/Framework/Classes/Common/RTCUIApplicationStatusObserver.h"
+
+// Springboard will kill any iOS app that fails to check in after launch within
+// a given time. Starting a UIApplication before invoking TestSuite::Run
+// prevents this from happening.
+
+// InitIOSRunHook saves the TestSuite and argc/argv, then invoking
+// RunTestsFromIOSApp calls UIApplicationMain(), providing an application
+// delegate class: WebRtcUnitTestDelegate. The delegate implements
+// application:didFinishLaunchingWithOptions: to invoke the TestSuite's Run
+// method.
+
+// Since the executable isn't likely to be a real iOS UI, the delegate puts up a
+// window displaying the app name. If a bunch of apps using MainHook are being
+// run in a row, this provides an indication of which one is currently running.
+
+static int (*g_test_suite)(void) = NULL;
+static int g_argc;
+static char **g_argv;
+
+@interface UIApplication (Testing)
+- (void)_terminateWithStatus:(int)status;
+@end
+
+@interface WebRtcUnitTestDelegate : NSObject {
+ UIWindow *_window;
+}
+- (void)runTests;
+@end
+
+@implementation WebRtcUnitTestDelegate
+
+- (BOOL)application:(UIApplication *)application
+ didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+ CGRect bounds = [[UIScreen mainScreen] bounds];
+
+ _window = [[UIWindow alloc] initWithFrame:bounds];
+ [_window setBackgroundColor:[UIColor whiteColor]];
+ [_window makeKeyAndVisible];
+
+ // Add a label with the app name.
+ UILabel *label = [[UILabel alloc] initWithFrame:bounds];
+ label.text = [[NSProcessInfo processInfo] processName];
+ label.textAlignment = NSTextAlignmentCenter;
+ [_window addSubview:label];
+
+ // An NSInternalInconsistencyException is thrown if the app doesn't have a
+ // root view controller. Set an empty one here.
+ [_window setRootViewController:[[UIViewController alloc] init]];
+
+ // We want to call `RTCUIApplicationStatusObserver sharedInstance` as early as
+ // possible in the application lifecycle to set observation properly.
+ __unused RTCUIApplicationStatusObserver *observer =
+ [RTCUIApplicationStatusObserver sharedInstance];
+
+ // Queue up the test run.
+ [self performSelector:@selector(runTests) withObject:nil afterDelay:0.1];
+ return YES;
+}
+
+- (void)runTests {
+ int exitStatus = g_test_suite();
+
+ // If a test app is too fast, it will exit before Instruments has has a
+ // a chance to initialize and no test results will be seen.
+ // TODO(crbug.com/137010): Figure out how much time is actually needed, and
+ // sleep only to make sure that much time has elapsed since launch.
+ [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:2.0]];
+
+ // Use the hidden selector to try and cleanly take down the app (otherwise
+ // things can think the app crashed even on a zero exit status).
+ UIApplication *application = [UIApplication sharedApplication];
+ [application _terminateWithStatus:exitStatus];
+
+ exit(exitStatus);
+}
+
+@end
+namespace rtc {
+namespace test {
+
+void InitTestSuite(int (*test_suite)(void), int argc, char *argv[]) {
+ g_test_suite = test_suite;
+ g_argc = argc;
+ g_argv = argv;
+}
+
+void RunTestsFromIOSApp() {
+ @autoreleasepool {
+ exit(UIApplicationMain(g_argc, g_argv, nil, @"WebRtcUnitTestDelegate"));
+ }
+}
+} // namespace test
+} // namespace rtc
diff --git a/third_party/libwebrtc/webrtc/test/layer_filtering_transport.cc b/third_party/libwebrtc/webrtc/test/layer_filtering_transport.cc
new file mode 100644
index 0000000000..a8a337da65
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/layer_filtering_transport.cc
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <memory>
+
+#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
+#include "modules/rtp_rtcp/source/byte_io.h"
+#include "modules/rtp_rtcp/source/rtp_format.h"
+#include "modules/rtp_rtcp/source/rtp_utility.h"
+#include "rtc_base/checks.h"
+#include "test/layer_filtering_transport.h"
+
+namespace webrtc {
+namespace test {
+
+LayerFilteringTransport::LayerFilteringTransport(
+ SingleThreadedTaskQueueForTesting* task_queue,
+ const FakeNetworkPipe::Config& config,
+ Call* send_call,
+ uint8_t vp8_video_payload_type,
+ uint8_t vp9_video_payload_type,
+ int selected_tl,
+ int selected_sl,
+ const std::map<uint8_t, MediaType>& payload_type_map)
+ : DirectTransport(task_queue, config, send_call, payload_type_map),
+ vp8_video_payload_type_(vp8_video_payload_type),
+ vp9_video_payload_type_(vp9_video_payload_type),
+ selected_tl_(selected_tl),
+ selected_sl_(selected_sl),
+ discarded_last_packet_(false) {}
+
+LayerFilteringTransport::LayerFilteringTransport(
+ SingleThreadedTaskQueueForTesting* task_queue,
+ std::unique_ptr<FakeNetworkPipe> pipe,
+ Call* send_call,
+ uint8_t vp8_video_payload_type,
+ uint8_t vp9_video_payload_type,
+ int selected_tl,
+ int selected_sl)
+ : DirectTransport(task_queue, std::move(pipe), send_call),
+ vp8_video_payload_type_(vp8_video_payload_type),
+ vp9_video_payload_type_(vp9_video_payload_type),
+ selected_tl_(selected_tl),
+ selected_sl_(selected_sl),
+ discarded_last_packet_(false) {}
+
+bool LayerFilteringTransport::DiscardedLastPacket() const {
+ return discarded_last_packet_;
+}
+
+bool LayerFilteringTransport::SendRtp(const uint8_t* packet,
+ size_t length,
+ const PacketOptions& options) {
+ if (selected_tl_ == -1 && selected_sl_ == -1) {
+ // Nothing to change, forward the packet immediately.
+ return test::DirectTransport::SendRtp(packet, length, options);
+ }
+
+ bool set_marker_bit = false;
+ RtpUtility::RtpHeaderParser parser(packet, length);
+ RTPHeader header;
+ parser.Parse(&header);
+
+ RTC_DCHECK_LE(length, IP_PACKET_SIZE);
+ uint8_t temp_buffer[IP_PACKET_SIZE];
+ memcpy(temp_buffer, packet, length);
+
+ if (header.payloadType == vp8_video_payload_type_ ||
+ header.payloadType == vp9_video_payload_type_) {
+ const uint8_t* payload = packet + header.headerLength;
+ RTC_DCHECK_GT(length, header.headerLength);
+ const size_t payload_length = length - header.headerLength;
+ RTC_DCHECK_GT(payload_length, header.paddingLength);
+ const size_t payload_data_length = payload_length - header.paddingLength;
+
+ const bool is_vp8 = header.payloadType == vp8_video_payload_type_;
+ std::unique_ptr<RtpDepacketizer> depacketizer(
+ RtpDepacketizer::Create(is_vp8 ? kRtpVideoVp8 : kRtpVideoVp9));
+ RtpDepacketizer::ParsedPayload parsed_payload;
+ if (depacketizer->Parse(&parsed_payload, payload, payload_data_length)) {
+ const int temporal_idx = static_cast<int>(
+ is_vp8 ? parsed_payload.type.Video.codecHeader.VP8.temporalIdx
+ : parsed_payload.type.Video.codecHeader.VP9.temporal_idx);
+ const int spatial_idx = static_cast<int>(
+ is_vp8 ? kNoSpatialIdx
+ : parsed_payload.type.Video.codecHeader.VP9.spatial_idx);
+ if (selected_sl_ >= 0 && spatial_idx == selected_sl_ &&
+ parsed_payload.type.Video.codecHeader.VP9.end_of_frame) {
+ // This layer is now the last in the superframe.
+ set_marker_bit = true;
+ } else if ((selected_tl_ >= 0 && temporal_idx != kNoTemporalIdx &&
+ temporal_idx > selected_tl_) ||
+ (selected_sl_ >= 0 && spatial_idx != kNoSpatialIdx &&
+ spatial_idx > selected_sl_)) {
+ // Truncate packet to a padding packet.
+ length = header.headerLength + 1;
+ temp_buffer[0] |= (1 << 5); // P = 1.
+ temp_buffer[1] &= 0x7F; // M = 0.
+ discarded_last_packet_ = true;
+ temp_buffer[header.headerLength] = 1; // One byte of padding.
+ }
+ } else {
+ RTC_NOTREACHED() << "Parse error";
+ }
+ }
+
+ // We are discarding some of the packets (specifically, whole layers), so
+ // make sure the marker bit is set properly, and that sequence numbers are
+ // continuous.
+ if (set_marker_bit)
+ temp_buffer[1] |= kRtpMarkerBitMask;
+
+ return test::DirectTransport::SendRtp(temp_buffer, length, options);
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/layer_filtering_transport.h b/third_party/libwebrtc/webrtc/test/layer_filtering_transport.h
new file mode 100644
index 0000000000..fe3b3d6d70
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/layer_filtering_transport.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef TEST_LAYER_FILTERING_TRANSPORT_H_
+#define TEST_LAYER_FILTERING_TRANSPORT_H_
+
+#include "call/call.h"
+#include "test/direct_transport.h"
+#include "test/fake_network_pipe.h"
+#include "test/single_threaded_task_queue.h"
+
+#include <map>
+
+namespace webrtc {
+
+namespace test {
+
+class LayerFilteringTransport : public test::DirectTransport {
+ public:
+ LayerFilteringTransport(SingleThreadedTaskQueueForTesting* task_queue,
+ const FakeNetworkPipe::Config& config,
+ Call* send_call,
+ uint8_t vp8_video_payload_type,
+ uint8_t vp9_video_payload_type,
+ int selected_tl,
+ int selected_sl,
+ const std::map<uint8_t, MediaType>& payload_type_map);
+ LayerFilteringTransport(SingleThreadedTaskQueueForTesting* task_queue,
+ std::unique_ptr<FakeNetworkPipe> pipe,
+ Call* send_call,
+ uint8_t vp8_video_payload_type,
+ uint8_t vp9_video_payload_type,
+ int selected_tl,
+ int selected_sl);
+ bool DiscardedLastPacket() const;
+ bool SendRtp(const uint8_t* data,
+ size_t length,
+ const PacketOptions& options) override;
+
+ private:
+ // Used to distinguish between VP8 and VP9.
+ const uint8_t vp8_video_payload_type_;
+ const uint8_t vp9_video_payload_type_;
+ // Discard or invalidate all temporal/spatial layers with id greater than the
+ // selected one. -1 to disable filtering.
+ const int selected_tl_;
+ const int selected_sl_;
+ bool discarded_last_packet_;
+};
+
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_LAYER_FILTERING_TRANSPORT_H_
diff --git a/third_party/libwebrtc/webrtc/test/linux/glx_renderer.cc b/third_party/libwebrtc/webrtc/test/linux/glx_renderer.cc
new file mode 100644
index 0000000000..4dbf1c97d9
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/linux/glx_renderer.cc
@@ -0,0 +1,178 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/linux/glx_renderer.h"
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include <X11/Xatom.h>
+#include <X11/Xlib.h>
+
+#include "common_video/libyuv/include/webrtc_libyuv.h"
+
+namespace webrtc {
+namespace test {
+
+GlxRenderer::GlxRenderer(size_t width, size_t height)
+ : width_(width),
+ height_(height),
+ display_(NULL),
+ context_(NULL) {
+ assert(width > 0);
+ assert(height > 0);
+}
+
+GlxRenderer::~GlxRenderer() { Destroy(); }
+
+bool GlxRenderer::Init(const char* window_title) {
+ if ((display_ = XOpenDisplay(NULL)) == NULL) {
+ Destroy();
+ return false;
+ }
+
+ int screen = DefaultScreen(display_);
+
+ XVisualInfo* vi;
+ int attr_list[] = { GLX_DOUBLEBUFFER, GLX_RGBA, GLX_RED_SIZE, 4,
+ GLX_GREEN_SIZE, 4, GLX_BLUE_SIZE, 4, GLX_DEPTH_SIZE, 16,
+ None, };
+
+ if ((vi = glXChooseVisual(display_, screen, attr_list)) == NULL) {
+ Destroy();
+ return false;
+ }
+
+ context_ = glXCreateContext(display_, vi, 0, true);
+ if (context_ == NULL) {
+ Destroy();
+ return false;
+ }
+
+ XSetWindowAttributes window_attributes;
+ window_attributes.colormap = XCreateColormap(
+ display_, RootWindow(display_, vi->screen), vi->visual, AllocNone);
+ window_attributes.border_pixel = 0;
+ window_attributes.event_mask = StructureNotifyMask | ExposureMask;
+ window_ = XCreateWindow(display_, RootWindow(display_, vi->screen), 0, 0,
+ width_, height_, 0, vi->depth, InputOutput,
+ vi->visual, CWBorderPixel | CWColormap | CWEventMask,
+ &window_attributes);
+ XFree(vi);
+
+ XSetStandardProperties(display_, window_, window_title, window_title, None,
+ NULL, 0, NULL);
+
+ Atom wm_delete = XInternAtom(display_, "WM_DELETE_WINDOW", True);
+ if (wm_delete != None) {
+ XSetWMProtocols(display_, window_, &wm_delete, 1);
+ }
+
+ XMapRaised(display_, window_);
+
+ if (!glXMakeCurrent(display_, window_, context_)) {
+ Destroy();
+ return false;
+ }
+ GlRenderer::Init();
+ if (!glXMakeCurrent(display_, None, NULL)) {
+ Destroy();
+ return false;
+ }
+
+ Resize(width_, height_);
+ return true;
+}
+
+void GlxRenderer::Destroy() {
+ if (context_ != NULL) {
+ glXMakeCurrent(display_, window_, context_);
+ GlRenderer::Destroy();
+ glXMakeCurrent(display_, None, NULL);
+ glXDestroyContext(display_, context_);
+ context_ = NULL;
+ }
+
+ if (display_ != NULL) {
+ XCloseDisplay(display_);
+ display_ = NULL;
+ }
+}
+
+GlxRenderer* GlxRenderer::Create(const char* window_title, size_t width,
+ size_t height) {
+ GlxRenderer* glx_renderer = new GlxRenderer(width, height);
+ if (!glx_renderer->Init(window_title)) {
+ // TODO(pbos): Add GLX-failed warning here?
+ delete glx_renderer;
+ return NULL;
+ }
+ return glx_renderer;
+}
+
+void GlxRenderer::Resize(size_t width, size_t height) {
+ width_ = width;
+ height_ = height;
+ if (!glXMakeCurrent(display_, window_, context_)) {
+ abort();
+ }
+ GlRenderer::ResizeViewport(width_, height_);
+ if (!glXMakeCurrent(display_, None, NULL)) {
+ abort();
+ }
+
+ XSizeHints* size_hints = XAllocSizeHints();
+ if (size_hints == NULL) {
+ abort();
+ }
+ size_hints->flags = PAspect;
+ size_hints->min_aspect.x = size_hints->max_aspect.x = width_;
+ size_hints->min_aspect.y = size_hints->max_aspect.y = height_;
+ XSetWMNormalHints(display_, window_, size_hints);
+ XFree(size_hints);
+
+ XWindowChanges wc;
+ wc.width = static_cast<int>(width);
+ wc.height = static_cast<int>(height);
+ XConfigureWindow(display_, window_, CWWidth | CWHeight, &wc);
+}
+
+void GlxRenderer::OnFrame(const webrtc::VideoFrame& frame) {
+ if (static_cast<size_t>(frame.width()) != width_ ||
+ static_cast<size_t>(frame.height()) != height_) {
+ Resize(static_cast<size_t>(frame.width()),
+ static_cast<size_t>(frame.height()));
+ }
+
+ XEvent event;
+ if (!glXMakeCurrent(display_, window_, context_)) {
+ abort();
+ }
+ while (XPending(display_)) {
+ XNextEvent(display_, &event);
+ switch (event.type) {
+ case ConfigureNotify:
+ GlRenderer::ResizeViewport(event.xconfigure.width,
+ event.xconfigure.height);
+ break;
+ default:
+ break;
+ }
+ }
+
+ GlRenderer::OnFrame(frame);
+ glXSwapBuffers(display_, window_);
+
+ if (!glXMakeCurrent(display_, None, NULL)) {
+ abort();
+ }
+}
+} // test
+} // webrtc
diff --git a/third_party/libwebrtc/webrtc/test/linux/glx_renderer.h b/third_party/libwebrtc/webrtc/test/linux/glx_renderer.h
new file mode 100644
index 0000000000..63ef624262
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/linux/glx_renderer.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef TEST_LINUX_GLX_RENDERER_H_
+#define TEST_LINUX_GLX_RENDERER_H_
+
+#include <GL/glx.h>
+#include <X11/Xlib.h>
+
+#include "test/gl/gl_renderer.h"
+#include "typedefs.h" // NOLINT(build/include)
+
+namespace webrtc {
+namespace test {
+
+class GlxRenderer : public GlRenderer {
+ public:
+ static GlxRenderer* Create(const char* window_title, size_t width,
+ size_t height);
+ virtual ~GlxRenderer();
+
+ void OnFrame(const webrtc::VideoFrame& frame) override;
+
+ private:
+ GlxRenderer(size_t width, size_t height);
+
+ bool Init(const char* window_title);
+ void Resize(size_t width, size_t height);
+ void Destroy();
+
+ size_t width_, height_;
+
+ Display* display_;
+ Window window_;
+ GLXContext context_;
+};
+} // test
+} // webrtc
+
+#endif // TEST_LINUX_GLX_RENDERER_H_
diff --git a/third_party/libwebrtc/webrtc/test/linux/video_renderer_linux.cc b/third_party/libwebrtc/webrtc/test/linux/video_renderer_linux.cc
new file mode 100644
index 0000000000..942848942f
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/linux/video_renderer_linux.cc
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "test/video_renderer.h"
+
+#include "test/linux/glx_renderer.h"
+
+namespace webrtc {
+namespace test {
+
+VideoRenderer* VideoRenderer::CreatePlatformRenderer(const char* window_title,
+ size_t width,
+ size_t height) {
+ GlxRenderer* glx_renderer = GlxRenderer::Create(window_title, width, height);
+ if (glx_renderer != NULL) {
+ return glx_renderer;
+ }
+ return NULL;
+}
+} // test
+} // webrtc
diff --git a/third_party/libwebrtc/webrtc/test/mac/run_test.mm b/third_party/libwebrtc/webrtc/test/mac/run_test.mm
new file mode 100644
index 0000000000..38c6c8f8c1
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/mac/run_test.mm
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#import <Cocoa/Cocoa.h>
+
+#include "test/run_test.h"
+
+// Converting a C++ function pointer to an Objective-C block.
+typedef void(^TestBlock)();
+TestBlock functionToBlock(void(*function)()) {
+ return [^(void) { function(); } copy];
+}
+
+// Class calling the test function on the platform specific thread.
+@interface TestRunner : NSObject {
+ BOOL running_;
+}
+- (void)runAllTests:(TestBlock)ignored;
+- (BOOL)running;
+@end
+
+@implementation TestRunner
+- (id)init {
+ self = [super init];
+ if (self) {
+ running_ = YES;
+ }
+ return self;
+}
+
+- (void)runAllTests:(TestBlock)testBlock {
+ @autoreleasepool {
+ testBlock();
+ running_ = NO;
+ }
+}
+
+- (BOOL)running {
+ return running_;
+}
+@end
+
+namespace webrtc {
+namespace test {
+
+void RunTest(void(*test)()) {
+ @autoreleasepool {
+ [NSApplication sharedApplication];
+
+ // Convert the function pointer to an Objective-C block and call on a
+ // separate thread, to avoid blocking the main thread.
+ TestRunner *testRunner = [[TestRunner alloc] init];
+ TestBlock testBlock = functionToBlock(test);
+ [NSThread detachNewThreadSelector:@selector(runAllTests:)
+ toTarget:testRunner
+ withObject:testBlock];
+
+ NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
+ while ([testRunner running] && [runLoop runMode:NSDefaultRunLoopMode
+ beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]])
+ ;
+ }
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/mac/video_renderer_mac.h b/third_party/libwebrtc/webrtc/test/mac/video_renderer_mac.h
new file mode 100644
index 0000000000..19349c037a
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/mac/video_renderer_mac.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef TEST_MAC_VIDEO_RENDERER_MAC_H_
+#define TEST_MAC_VIDEO_RENDERER_MAC_H_
+
+#include "rtc_base/constructormagic.h"
+#include "test/gl/gl_renderer.h"
+
+@class CocoaWindow;
+
+namespace webrtc {
+namespace test {
+
+class MacRenderer : public GlRenderer {
+ public:
+ MacRenderer();
+ virtual ~MacRenderer();
+
+ bool Init(const char* window_title, int width, int height);
+
+ // Implements GlRenderer.
+ void OnFrame(const VideoFrame& frame) override;
+
+ private:
+ CocoaWindow* window_;
+
+ RTC_DISALLOW_COPY_AND_ASSIGN(MacRenderer);
+};
+} // test
+} // webrtc
+
+#endif // TEST_MAC_VIDEO_RENDERER_MAC_H_
diff --git a/third_party/libwebrtc/webrtc/test/mac/video_renderer_mac.mm b/third_party/libwebrtc/webrtc/test/mac/video_renderer_mac.mm
new file mode 100644
index 0000000000..56bf360986
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/mac/video_renderer_mac.mm
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/mac/video_renderer_mac.h"
+
+#import <Cocoa/Cocoa.h>
+
+// Creates a Cocoa Window with an OpenGL context, used together with an OpenGL
+// renderer.
+@interface CocoaWindow : NSObject {
+ @private
+ NSWindow *window_;
+ NSOpenGLContext *context_;
+ NSString *title_;
+ int width_;
+ int height_;
+}
+
+- (id)initWithTitle:(NSString *)title width:(int)width height:(int)height;
+// 'createWindow' must be called on the main thread.
+- (void)createWindow:(NSObject *)ignored;
+- (void)makeCurrentContext;
+
+@end
+
+@implementation CocoaWindow
+ static NSInteger nextXOrigin_;
+ static NSInteger nextYOrigin_;
+
+- (id)initWithTitle:(NSString *)title width:(int)width height:(int)height {
+ if (self = [super init]) {
+ title_ = title;
+ width_ = width;
+ height_ = height;
+ }
+ return self;
+}
+
+- (void)createWindow:(NSObject *)ignored {
+ NSInteger xOrigin = nextXOrigin_;
+ NSRect screenFrame = [[NSScreen mainScreen] frame];
+ if (nextXOrigin_ + width_ < screenFrame.size.width) {
+ nextXOrigin_ += width_;
+ } else {
+ xOrigin = 0;
+ nextXOrigin_ = 0;
+ nextYOrigin_ += height_;
+ }
+ if (nextYOrigin_ + height_ > screenFrame.size.height) {
+ xOrigin = 0;
+ nextXOrigin_ = 0;
+ nextYOrigin_ = 0;
+ }
+ NSInteger yOrigin = nextYOrigin_;
+ NSRect windowFrame = NSMakeRect(xOrigin, yOrigin, width_, height_);
+ window_ = [[NSWindow alloc] initWithContentRect:windowFrame
+ styleMask:NSTitledWindowMask
+ backing:NSBackingStoreBuffered
+ defer:NO];
+
+ NSRect viewFrame = NSMakeRect(0, 0, width_, height_);
+ NSOpenGLView *view = [[NSOpenGLView alloc] initWithFrame:viewFrame pixelFormat:nil];
+ context_ = [view openGLContext];
+
+ [[window_ contentView] addSubview:view];
+ [window_ setTitle:title_];
+ [window_ makeKeyAndOrderFront:NSApp];
+}
+
+- (void)makeCurrentContext {
+ [context_ makeCurrentContext];
+}
+
+@end
+
+namespace webrtc {
+namespace test {
+
+VideoRenderer* VideoRenderer::CreatePlatformRenderer(const char* window_title,
+ size_t width,
+ size_t height) {
+ MacRenderer* renderer = new MacRenderer();
+ if (!renderer->Init(window_title, width, height)) {
+ delete renderer;
+ return NULL;
+ }
+ return renderer;
+}
+
+MacRenderer::MacRenderer()
+ : window_(NULL) {}
+
+MacRenderer::~MacRenderer() {
+ GlRenderer::Destroy();
+}
+
+bool MacRenderer::Init(const char* window_title, int width, int height) {
+ window_ = [[CocoaWindow alloc]
+ initWithTitle:[NSString stringWithUTF8String:window_title]
+ width:width
+ height:height];
+ if (!window_)
+ return false;
+ [window_ performSelectorOnMainThread:@selector(createWindow:)
+ withObject:nil
+ waitUntilDone:YES];
+
+ [window_ makeCurrentContext];
+ GlRenderer::Init();
+ GlRenderer::ResizeViewport(width, height);
+ return true;
+}
+
+void MacRenderer::OnFrame(const VideoFrame& frame) {
+ [window_ makeCurrentContext];
+ GlRenderer::OnFrame(frame);
+}
+
+} // test
+} // webrtc
diff --git a/third_party/libwebrtc/webrtc/test/mock_audio_decoder.cc b/third_party/libwebrtc/webrtc/test/mock_audio_decoder.cc
new file mode 100644
index 0000000000..5af9f370cd
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/mock_audio_decoder.cc
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/mock_audio_decoder.h"
+
+namespace webrtc {
+
+MockAudioDecoder::MockAudioDecoder() = default;
+MockAudioDecoder::~MockAudioDecoder() {
+ Die();
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/mock_audio_decoder.h b/third_party/libwebrtc/webrtc/test/mock_audio_decoder.h
new file mode 100644
index 0000000000..67cd0f775c
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/mock_audio_decoder.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef TEST_MOCK_AUDIO_DECODER_H_
+#define TEST_MOCK_AUDIO_DECODER_H_
+
+#include "api/audio_codecs/audio_decoder.h"
+#include "test/gmock.h"
+
+namespace webrtc {
+
+class MockAudioDecoder : public AudioDecoder {
+ public:
+ MockAudioDecoder();
+ ~MockAudioDecoder();
+ MOCK_METHOD0(Die, void());
+ MOCK_METHOD5(DecodeInternal,
+ int(const uint8_t*, size_t, int, int16_t*, SpeechType*));
+ MOCK_CONST_METHOD0(HasDecodePlc, bool());
+ MOCK_METHOD2(DecodePlc, size_t(size_t, int16_t*));
+ MOCK_METHOD0(Reset, void());
+ MOCK_METHOD5(IncomingPacket,
+ int(const uint8_t*, size_t, uint16_t, uint32_t, uint32_t));
+ MOCK_METHOD0(ErrorCode, int());
+ MOCK_CONST_METHOD2(PacketDuration, int(const uint8_t*, size_t));
+ MOCK_CONST_METHOD0(Channels, size_t());
+ MOCK_CONST_METHOD0(SampleRateHz, int());
+};
+
+} // namespace webrtc
+#endif // TEST_MOCK_AUDIO_DECODER_H_
diff --git a/third_party/libwebrtc/webrtc/test/mock_audio_decoder_factory.h b/third_party/libwebrtc/webrtc/test/mock_audio_decoder_factory.h
new file mode 100644
index 0000000000..bc504d871e
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/mock_audio_decoder_factory.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef TEST_MOCK_AUDIO_DECODER_FACTORY_H_
+#define TEST_MOCK_AUDIO_DECODER_FACTORY_H_
+
+#include <memory>
+#include <vector>
+
+#include "api/audio_codecs/audio_decoder_factory.h"
+#include "api/audio_codecs/builtin_audio_decoder_factory.h"
+#include "rtc_base/refcountedobject.h"
+#include "rtc_base/scoped_ref_ptr.h"
+#include "test/gmock.h"
+
+namespace webrtc {
+
+class MockAudioDecoderFactory : public AudioDecoderFactory {
+ public:
+ MOCK_METHOD0(GetSupportedDecoders, std::vector<AudioCodecSpec>());
+ MOCK_METHOD1(IsSupportedDecoder, bool(const SdpAudioFormat&));
+ std::unique_ptr<AudioDecoder> MakeAudioDecoder(const SdpAudioFormat& format) {
+ std::unique_ptr<AudioDecoder> return_value;
+ MakeAudioDecoderMock(format, &return_value);
+ return return_value;
+ }
+ MOCK_METHOD2(MakeAudioDecoderMock,
+ void(const SdpAudioFormat& format,
+ std::unique_ptr<AudioDecoder>* return_value));
+
+ // Creates a MockAudioDecoderFactory with no formats and that may not be
+ // invoked to create a codec - useful for initializing a voice engine, for
+ // example.
+ static rtc::scoped_refptr<webrtc::MockAudioDecoderFactory>
+ CreateUnusedFactory() {
+ using testing::_;
+ using testing::AnyNumber;
+ using testing::Return;
+
+ rtc::scoped_refptr<webrtc::MockAudioDecoderFactory> factory =
+ new rtc::RefCountedObject<webrtc::MockAudioDecoderFactory>;
+ ON_CALL(*factory.get(), GetSupportedDecoders())
+ .WillByDefault(Return(std::vector<webrtc::AudioCodecSpec>()));
+ EXPECT_CALL(*factory.get(), GetSupportedDecoders()).Times(AnyNumber());
+ ON_CALL(*factory, IsSupportedDecoder(_)).WillByDefault(Return(false));
+ EXPECT_CALL(*factory, IsSupportedDecoder(_)).Times(AnyNumber());
+ EXPECT_CALL(*factory.get(), MakeAudioDecoderMock(_, _)).Times(0);
+ return factory;
+ }
+
+ // Creates a MockAudioDecoderFactory with no formats that may be invoked to
+ // create a codec any number of times. It will, though, return nullptr on each
+ // call, since it supports no codecs.
+ static rtc::scoped_refptr<webrtc::MockAudioDecoderFactory>
+ CreateEmptyFactory() {
+ using testing::_;
+ using testing::AnyNumber;
+ using testing::Return;
+ using testing::SetArgPointee;
+
+ rtc::scoped_refptr<webrtc::MockAudioDecoderFactory> factory =
+ new rtc::RefCountedObject<webrtc::MockAudioDecoderFactory>;
+ ON_CALL(*factory.get(), GetSupportedDecoders())
+ .WillByDefault(Return(std::vector<webrtc::AudioCodecSpec>()));
+ EXPECT_CALL(*factory.get(), GetSupportedDecoders()).Times(AnyNumber());
+ ON_CALL(*factory, IsSupportedDecoder(_)).WillByDefault(Return(false));
+ EXPECT_CALL(*factory, IsSupportedDecoder(_)).Times(AnyNumber());
+ ON_CALL(*factory.get(), MakeAudioDecoderMock(_, _))
+ .WillByDefault(SetArgPointee<1>(nullptr));
+ EXPECT_CALL(*factory.get(), MakeAudioDecoderMock(_, _)).Times(AnyNumber());
+ return factory;
+ }
+};
+
+} // namespace webrtc
+
+#endif // TEST_MOCK_AUDIO_DECODER_FACTORY_H_
diff --git a/third_party/libwebrtc/webrtc/test/mock_audio_encoder.cc b/third_party/libwebrtc/webrtc/test/mock_audio_encoder.cc
new file mode 100644
index 0000000000..cd89bdd4e8
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/mock_audio_encoder.cc
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/mock_audio_encoder.h"
+
+namespace webrtc {
+
+MockAudioEncoder::MockAudioEncoder() = default;
+MockAudioEncoder::~MockAudioEncoder() {
+ Die();
+}
+
+MockAudioEncoder::FakeEncoding::FakeEncoding(
+ const AudioEncoder::EncodedInfo& info)
+ : info_(info) {}
+
+MockAudioEncoder::FakeEncoding::FakeEncoding(size_t encoded_bytes) {
+ info_.encoded_bytes = encoded_bytes;
+}
+
+AudioEncoder::EncodedInfo MockAudioEncoder::FakeEncoding::operator()(
+ uint32_t timestamp,
+ rtc::ArrayView<const int16_t> audio,
+ rtc::Buffer* encoded) {
+ encoded->SetSize(encoded->size() + info_.encoded_bytes);
+ return info_;
+}
+
+MockAudioEncoder::CopyEncoding::~CopyEncoding() = default;
+
+MockAudioEncoder::CopyEncoding::CopyEncoding(
+ AudioEncoder::EncodedInfo info,
+ rtc::ArrayView<const uint8_t> payload)
+ : info_(info), payload_(payload) {}
+
+MockAudioEncoder::CopyEncoding::CopyEncoding(
+ rtc::ArrayView<const uint8_t> payload)
+ : payload_(payload) {
+ info_.encoded_bytes = payload_.size();
+}
+
+AudioEncoder::EncodedInfo MockAudioEncoder::CopyEncoding::operator()(
+ uint32_t timestamp,
+ rtc::ArrayView<const int16_t> audio,
+ rtc::Buffer* encoded) {
+ RTC_CHECK(encoded);
+ RTC_CHECK_LE(info_.encoded_bytes, payload_.size());
+ encoded->AppendData(payload_.data(), info_.encoded_bytes);
+ return info_;
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/mock_audio_encoder.h b/third_party/libwebrtc/webrtc/test/mock_audio_encoder.h
new file mode 100644
index 0000000000..8196cf18a7
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/mock_audio_encoder.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef TEST_MOCK_AUDIO_ENCODER_H_
+#define TEST_MOCK_AUDIO_ENCODER_H_
+
+#include <string>
+
+#include "api/array_view.h"
+#include "api/audio_codecs/audio_encoder.h"
+#include "test/gmock.h"
+
+namespace webrtc {
+
+class MockAudioEncoder : public AudioEncoder {
+ public:
+ // TODO(nisse): Valid overrides commented out, because the gmock
+ // methods don't use any override declarations, and we want to avoid
+ // warnings from -Winconsistent-missing-override. See
+ // http://crbug.com/428099.
+ MockAudioEncoder();
+ ~MockAudioEncoder();
+ MOCK_METHOD0(Die, void());
+ MOCK_METHOD1(Mark, void(std::string desc));
+ MOCK_CONST_METHOD0(SampleRateHz, int());
+ MOCK_CONST_METHOD0(NumChannels, size_t());
+ MOCK_CONST_METHOD0(RtpTimestampRateHz, int());
+ MOCK_CONST_METHOD0(Num10MsFramesInNextPacket, size_t());
+ MOCK_CONST_METHOD0(Max10MsFramesInAPacket, size_t());
+ MOCK_CONST_METHOD0(GetTargetBitrate, int());
+ MOCK_METHOD0(Reset, void());
+ MOCK_METHOD1(SetFec, bool(bool enable));
+ MOCK_METHOD1(SetDtx, bool(bool enable));
+ MOCK_METHOD1(SetApplication, bool(Application application));
+ MOCK_METHOD1(SetMaxPlaybackRate, void(int frequency_hz));
+ MOCK_METHOD1(SetMaxBitrate, void(int max_bps));
+ MOCK_METHOD1(SetMaxPayloadSize, void(int max_payload_size_bytes));
+ MOCK_METHOD2(OnReceivedUplinkBandwidth,
+ void(int target_audio_bitrate_bps,
+ rtc::Optional<int64_t> probing_interval_ms));
+ MOCK_METHOD1(OnReceivedUplinkPacketLossFraction,
+ void(float uplink_packet_loss_fraction));
+
+ MOCK_METHOD2(EnableAudioNetworkAdaptor,
+ bool(const std::string& config_string, RtcEventLog* event_log));
+
+ // Note, we explicitly chose not to create a mock for the Encode method.
+ MOCK_METHOD3(EncodeImpl,
+ EncodedInfo(uint32_t timestamp,
+ rtc::ArrayView<const int16_t> audio,
+ rtc::Buffer* encoded));
+
+ class FakeEncoding {
+ public:
+ // Creates a functor that will return |info| and adjust the rtc::Buffer
+ // given as input to it, so it is info.encoded_bytes larger.
+ explicit FakeEncoding(const AudioEncoder::EncodedInfo& info);
+
+ // Shorthand version of the constructor above, for when only setting
+ // encoded_bytes in the EncodedInfo object matters.
+ explicit FakeEncoding(size_t encoded_bytes);
+
+ AudioEncoder::EncodedInfo operator()(uint32_t timestamp,
+ rtc::ArrayView<const int16_t> audio,
+ rtc::Buffer* encoded);
+
+ private:
+ AudioEncoder::EncodedInfo info_;
+ };
+
+ class CopyEncoding {
+ public:
+ ~CopyEncoding();
+
+ // Creates a functor that will return |info| and append the data in the
+ // payload to the buffer given as input to it. Up to info.encoded_bytes are
+ // appended - make sure the payload is big enough! Since it uses an
+ // ArrayView, it _does not_ copy the payload. Make sure it doesn't fall out
+ // of scope!
+ CopyEncoding(AudioEncoder::EncodedInfo info,
+ rtc::ArrayView<const uint8_t> payload);
+
+ // Shorthand version of the constructor above, for when you wish to append
+ // the whole payload and do not care about any EncodedInfo attribute other
+ // than encoded_bytes.
+ explicit CopyEncoding(rtc::ArrayView<const uint8_t> payload);
+
+ AudioEncoder::EncodedInfo operator()(uint32_t timestamp,
+ rtc::ArrayView<const int16_t> audio,
+ rtc::Buffer* encoded);
+
+ private:
+ AudioEncoder::EncodedInfo info_;
+ rtc::ArrayView<const uint8_t> payload_;
+ };
+};
+
+} // namespace webrtc
+
+#endif // TEST_MOCK_AUDIO_ENCODER_H_
diff --git a/third_party/libwebrtc/webrtc/test/mock_audio_encoder_factory.h b/third_party/libwebrtc/webrtc/test/mock_audio_encoder_factory.h
new file mode 100644
index 0000000000..9b63f7d18f
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/mock_audio_encoder_factory.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef TEST_MOCK_AUDIO_ENCODER_FACTORY_H_
+#define TEST_MOCK_AUDIO_ENCODER_FACTORY_H_
+
+#include <memory>
+#include <vector>
+
+#include "api/audio_codecs/audio_encoder_factory.h"
+#include "rtc_base/scoped_ref_ptr.h"
+#include "test/gmock.h"
+
+namespace webrtc {
+
+class MockAudioEncoderFactory : public AudioEncoderFactory {
+ public:
+ MOCK_METHOD0(GetSupportedEncoders, std::vector<AudioCodecSpec>());
+ MOCK_METHOD1(QueryAudioEncoder,
+ rtc::Optional<AudioCodecInfo>(const SdpAudioFormat& format));
+
+ std::unique_ptr<AudioEncoder> MakeAudioEncoder(int payload_type,
+ const SdpAudioFormat& format) {
+ std::unique_ptr<AudioEncoder> return_value;
+ MakeAudioEncoderMock(payload_type, format, &return_value);
+ return return_value;
+ }
+ MOCK_METHOD3(MakeAudioEncoderMock,
+ void(int payload_type,
+ const SdpAudioFormat& format,
+ std::unique_ptr<AudioEncoder>* return_value));
+
+ // Creates a MockAudioEncoderFactory with no formats and that may not be
+ // invoked to create a codec - useful for initializing a voice engine, for
+ // example.
+ static rtc::scoped_refptr<webrtc::MockAudioEncoderFactory>
+ CreateUnusedFactory() {
+ using testing::_;
+ using testing::AnyNumber;
+ using testing::Return;
+
+ rtc::scoped_refptr<webrtc::MockAudioEncoderFactory> factory =
+ new rtc::RefCountedObject<webrtc::MockAudioEncoderFactory>;
+ ON_CALL(*factory.get(), GetSupportedEncoders())
+ .WillByDefault(Return(std::vector<webrtc::AudioCodecSpec>()));
+ ON_CALL(*factory.get(), QueryAudioEncoder(_))
+ .WillByDefault(Return(rtc::Optional<AudioCodecInfo>()));
+
+ EXPECT_CALL(*factory.get(), GetSupportedEncoders()).Times(AnyNumber());
+ EXPECT_CALL(*factory.get(), QueryAudioEncoder(_)).Times(AnyNumber());
+ EXPECT_CALL(*factory.get(), MakeAudioEncoderMock(_, _, _)).Times(0);
+ return factory;
+ }
+
+ // Creates a MockAudioEncoderFactory with no formats that may be invoked to
+ // create a codec any number of times. It will, though, return nullptr on each
+ // call, since it supports no codecs.
+ static rtc::scoped_refptr<webrtc::MockAudioEncoderFactory>
+ CreateEmptyFactory() {
+ using testing::_;
+ using testing::AnyNumber;
+ using testing::Return;
+ using testing::SetArgPointee;
+
+ rtc::scoped_refptr<webrtc::MockAudioEncoderFactory> factory =
+ new rtc::RefCountedObject<webrtc::MockAudioEncoderFactory>;
+ ON_CALL(*factory.get(), GetSupportedEncoders())
+ .WillByDefault(Return(std::vector<webrtc::AudioCodecSpec>()));
+ ON_CALL(*factory.get(), QueryAudioEncoder(_))
+ .WillByDefault(Return(rtc::Optional<AudioCodecInfo>()));
+ ON_CALL(*factory.get(), MakeAudioEncoderMock(_, _, _))
+ .WillByDefault(SetArgPointee<2>(nullptr));
+
+ EXPECT_CALL(*factory.get(), GetSupportedEncoders()).Times(AnyNumber());
+ EXPECT_CALL(*factory.get(), QueryAudioEncoder(_)).Times(AnyNumber());
+ EXPECT_CALL(*factory.get(), MakeAudioEncoderMock(_, _, _))
+ .Times(AnyNumber());
+ return factory;
+ }
+};
+
+} // namespace webrtc
+
+#endif // TEST_MOCK_AUDIO_ENCODER_FACTORY_H_
diff --git a/third_party/libwebrtc/webrtc/test/mock_transport.h b/third_party/libwebrtc/webrtc/test/mock_transport.h
new file mode 100644
index 0000000000..9837593f33
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/mock_transport.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef TEST_MOCK_TRANSPORT_H_
+#define TEST_MOCK_TRANSPORT_H_
+
+#include "api/call/transport.h"
+#include "test/gmock.h"
+
+namespace webrtc {
+
+class MockTransport : public Transport {
+ public:
+ MOCK_METHOD3(SendRtp,
+ bool(const uint8_t* data,
+ size_t len,
+ const PacketOptions& options));
+ MOCK_METHOD2(SendRtcp, bool(const uint8_t* data, size_t len));
+};
+} // namespace webrtc
+#endif // TEST_MOCK_TRANSPORT_H_
diff --git a/third_party/libwebrtc/webrtc/test/mock_voe_channel_proxy.h b/third_party/libwebrtc/webrtc/test/mock_voe_channel_proxy.h
new file mode 100644
index 0000000000..9bc48b10a0
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/mock_voe_channel_proxy.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef TEST_MOCK_VOE_CHANNEL_PROXY_H_
+#define TEST_MOCK_VOE_CHANNEL_PROXY_H_
+
+#include <string>
+
+#include "modules/rtp_rtcp/source/rtp_packet_received.h"
+#include "test/gmock.h"
+#include "voice_engine/channel_proxy.h"
+
+namespace webrtc {
+namespace test {
+
+class MockVoEChannelProxy : public voe::ChannelProxy {
+ public:
+ // GTest doesn't like move-only types, like std::unique_ptr
+ bool SetEncoder(int payload_type,
+ std::unique_ptr<AudioEncoder> encoder) {
+ return SetEncoderForMock(payload_type, &encoder);
+ }
+ MOCK_METHOD2(SetEncoderForMock,
+ bool(int payload_type,
+ std::unique_ptr<AudioEncoder>* encoder));
+ MOCK_METHOD1(
+ ModifyEncoder,
+ void(rtc::FunctionView<void(std::unique_ptr<AudioEncoder>*)> modifier));
+ MOCK_METHOD1(SetRTCPStatus, void(bool enable));
+ MOCK_METHOD1(SetLocalSSRC, void(uint32_t ssrc));
+ MOCK_METHOD1(SetRTCP_CNAME, void(const std::string& c_name));
+ MOCK_METHOD2(SetNACKStatus, void(bool enable, int max_packets));
+ MOCK_METHOD2(SetSendAudioLevelIndicationStatus, void(bool enable, int id));
+ MOCK_METHOD2(SetReceiveAudioLevelIndicationStatus, void(bool enable, int id));
+ MOCK_METHOD1(EnableSendTransportSequenceNumber, void(int id));
+ MOCK_METHOD1(EnableReceiveTransportSequenceNumber, void(int id));
+ MOCK_METHOD2(RegisterSenderCongestionControlObjects,
+ void(RtpTransportControllerSendInterface* transport,
+ RtcpBandwidthObserver* bandwidth_observer));
+ MOCK_METHOD1(RegisterReceiverCongestionControlObjects,
+ void(PacketRouter* packet_router));
+ MOCK_METHOD0(ResetSenderCongestionControlObjects, void());
+ MOCK_METHOD0(ResetReceiverCongestionControlObjects, void());
+ MOCK_CONST_METHOD0(GetRTCPStatistics, CallStatistics());
+ MOCK_CONST_METHOD0(GetRemoteRTCPReportBlocks, std::vector<ReportBlock>());
+ MOCK_CONST_METHOD0(GetNetworkStatistics, NetworkStatistics());
+ MOCK_CONST_METHOD0(GetDecodingCallStatistics, AudioDecodingCallStats());
+ MOCK_CONST_METHOD0(GetANAStatistics, ANAStats());
+ MOCK_CONST_METHOD0(GetSpeechOutputLevel, int());
+ MOCK_CONST_METHOD0(GetSpeechOutputLevelFullRange, int());
+ MOCK_CONST_METHOD0(GetTotalOutputEnergy, double());
+ MOCK_CONST_METHOD0(GetTotalOutputDuration, double());
+ MOCK_CONST_METHOD0(GetDelayEstimate, uint32_t());
+ MOCK_METHOD2(SetSendTelephoneEventPayloadType, bool(int payload_type,
+ int payload_frequency));
+ MOCK_METHOD2(SendTelephoneEventOutband, bool(int event, int duration_ms));
+ MOCK_METHOD2(SetBitrate, void(int bitrate_bps, int64_t probing_interval_ms));
+ // TODO(solenberg): Talk the compiler into accepting this mock method:
+ // MOCK_METHOD1(SetSink, void(std::unique_ptr<AudioSinkInterface> sink));
+ MOCK_METHOD1(SetInputMute, void(bool muted));
+ MOCK_METHOD1(RegisterTransport, void(Transport* transport));
+ MOCK_METHOD1(OnRtpPacket, void(const RtpPacketReceived& packet));
+ MOCK_METHOD2(ReceivedRTCPPacket, bool(const uint8_t* packet, size_t length));
+ MOCK_CONST_METHOD0(GetAudioDecoderFactory,
+ const rtc::scoped_refptr<AudioDecoderFactory>&());
+ MOCK_METHOD1(SetChannelOutputVolumeScaling, void(float scaling));
+ MOCK_METHOD1(SetRtcEventLog, void(RtcEventLog* event_log));
+ MOCK_METHOD1(SetRtcpRttStats, void(RtcpRttStats* rtcp_rtt_stats));
+ MOCK_METHOD2(GetAudioFrameWithInfo,
+ AudioMixer::Source::AudioFrameInfo(int sample_rate_hz,
+ AudioFrame* audio_frame));
+ MOCK_CONST_METHOD0(PreferredSampleRate, int());
+ MOCK_METHOD1(SetTransportOverhead, void(int transport_overhead_per_packet));
+ MOCK_METHOD1(AssociateSendChannel,
+ void(const ChannelProxy& send_channel_proxy));
+ MOCK_METHOD0(DisassociateSendChannel, void());
+ MOCK_CONST_METHOD2(GetRtpRtcp, void(RtpRtcp** rtp_rtcp,
+ RtpReceiver** rtp_receiver));
+ MOCK_CONST_METHOD0(GetPlayoutTimestamp, uint32_t());
+ MOCK_METHOD1(SetMinimumPlayoutDelay, void(int delay_ms));
+ MOCK_CONST_METHOD1(GetRecCodec, bool(CodecInst* codec_inst));
+ MOCK_METHOD1(SetReceiveCodecs,
+ void(const std::map<int, SdpAudioFormat>& codecs));
+ MOCK_METHOD1(OnTwccBasedUplinkPacketLossRate, void(float packet_loss_rate));
+ MOCK_METHOD1(OnRecoverableUplinkPacketLossRate,
+ void(float recoverable_packet_loss_rate));
+ MOCK_CONST_METHOD0(GetSources, std::vector<RtpSource>());
+};
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_MOCK_VOE_CHANNEL_PROXY_H_
diff --git a/third_party/libwebrtc/webrtc/test/mock_voice_engine.h b/third_party/libwebrtc/webrtc/test/mock_voice_engine.h
new file mode 100644
index 0000000000..57c6b58c67
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/mock_voice_engine.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef AUDIO_MOCK_VOICE_ENGINE_H_
+#define AUDIO_MOCK_VOICE_ENGINE_H_
+
+#include <memory>
+
+#include "modules/audio_device/include/mock_audio_transport.h"
+#include "modules/rtp_rtcp/mocks/mock_rtp_rtcp.h"
+#include "test/gmock.h"
+#include "test/mock_voe_channel_proxy.h"
+#include "voice_engine/voice_engine_impl.h"
+
+namespace webrtc {
+namespace voe {
+class TransmitMixer;
+} // namespace voe
+
+namespace test {
+
+// NOTE: This class inherits from VoiceEngineImpl so that its clients will be
+// able to get the various interfaces as usual, via T::GetInterface().
+class MockVoiceEngine : public VoiceEngineImpl {
+ public:
+ // TODO(nisse): Valid overrides commented out, because the gmock
+ // methods don't use any override declarations, and we want to avoid
+ // warnings from -Winconsistent-missing-override. See
+ // http://crbug.com/428099.
+ MockVoiceEngine(
+ rtc::scoped_refptr<AudioDecoderFactory> decoder_factory = nullptr)
+ : decoder_factory_(decoder_factory) {
+ // Increase ref count so this object isn't automatically deleted whenever
+ // interfaces are Release():d.
+ ++_ref_count;
+ // We add this default behavior to make the mock easier to use in tests. It
+ // will create a NiceMock of a voe::ChannelProxy.
+ // TODO(ossu): As long as AudioReceiveStream is implemented as a wrapper
+ // around Channel, we need to make sure ChannelProxy returns the same
+ // decoder factory as the one passed in when creating an AudioReceiveStream.
+ ON_CALL(*this, ChannelProxyFactory(testing::_))
+ .WillByDefault(testing::Invoke([this](int channel_id) {
+ auto* proxy =
+ new testing::NiceMock<webrtc::test::MockVoEChannelProxy>();
+ EXPECT_CALL(*proxy, GetAudioDecoderFactory())
+ .WillRepeatedly(testing::ReturnRef(decoder_factory_));
+ EXPECT_CALL(*proxy, SetReceiveCodecs(testing::_))
+ .WillRepeatedly(testing::Invoke(
+ [](const std::map<int, SdpAudioFormat>& codecs) {
+ EXPECT_THAT(codecs, testing::IsEmpty());
+ }));
+ EXPECT_CALL(*proxy, GetRtpRtcp(testing::_, testing::_))
+ .WillRepeatedly(
+ testing::SetArgPointee<0>(GetMockRtpRtcp(channel_id)));
+ return proxy;
+ }));
+
+ ON_CALL(*this, audio_transport())
+ .WillByDefault(testing::Return(&mock_audio_transport_));
+ }
+ virtual ~MockVoiceEngine() /* override */ {
+ // Decrease ref count before base class d-tor is called; otherwise it will
+ // trigger an assertion.
+ --_ref_count;
+ }
+
+ // These need to be the same each call to channel_id and must not leak.
+ MockRtpRtcp* GetMockRtpRtcp(int channel_id) {
+ if (mock_rtp_rtcps_.find(channel_id) == mock_rtp_rtcps_.end()) {
+ mock_rtp_rtcps_[channel_id].reset(new ::testing::NiceMock<MockRtpRtcp>);
+ }
+ return mock_rtp_rtcps_[channel_id].get();
+ }
+
+ // Allows injecting a ChannelProxy factory.
+ MOCK_METHOD1(ChannelProxyFactory, voe::ChannelProxy*(int channel_id));
+
+ // VoiceEngineImpl
+ virtual std::unique_ptr<voe::ChannelProxy> GetChannelProxy(
+ int channel_id) /* override */ {
+ return std::unique_ptr<voe::ChannelProxy>(ChannelProxyFactory(channel_id));
+ }
+
+ // VoEBase
+ MOCK_METHOD3(
+ Init,
+ int(AudioDeviceModule* external_adm,
+ AudioProcessing* external_apm,
+ const rtc::scoped_refptr<AudioDecoderFactory>& decoder_factory));
+ MOCK_METHOD0(transmit_mixer, voe::TransmitMixer*());
+ MOCK_METHOD0(Terminate, void());
+ MOCK_METHOD0(CreateChannel, int());
+ MOCK_METHOD1(CreateChannel, int(const ChannelConfig& config));
+ MOCK_METHOD1(DeleteChannel, int(int channel));
+ MOCK_METHOD1(StartPlayout, int(int channel));
+ MOCK_METHOD1(StopPlayout, int(int channel));
+ MOCK_METHOD1(StartSend, int(int channel));
+ MOCK_METHOD1(StopSend, int(int channel));
+ MOCK_METHOD0(audio_transport, AudioTransport*());
+
+ private:
+ // TODO(ossu): I'm not particularly happy about keeping the decoder factory
+ // here, but due to how gmock is implemented, I cannot just keep it in the
+ // functor implementing the default version of ChannelProxyFactory, above.
+ // GMock creates an unfortunate copy of the functor, which would cause us to
+ // return a dangling reference. Fortunately, this should go away once
+ // voe::Channel does.
+ rtc::scoped_refptr<AudioDecoderFactory> decoder_factory_;
+
+ std::map<int, std::unique_ptr<MockRtpRtcp>> mock_rtp_rtcps_;
+
+ MockAudioTransport mock_audio_transport_;
+};
+} // namespace test
+} // namespace webrtc
+
+#endif // AUDIO_MOCK_VOICE_ENGINE_H_
diff --git a/third_party/libwebrtc/webrtc/test/null_platform_renderer.cc b/third_party/libwebrtc/webrtc/test/null_platform_renderer.cc
new file mode 100644
index 0000000000..48e4cc0d8b
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/null_platform_renderer.cc
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/video_renderer.h"
+
+namespace webrtc {
+namespace test {
+
+VideoRenderer* VideoRenderer::CreatePlatformRenderer(const char* window_title,
+ size_t width,
+ size_t height) {
+ return NULL;
+}
+} // test
+} // webrtc
diff --git a/third_party/libwebrtc/webrtc/test/null_transport.cc b/third_party/libwebrtc/webrtc/test/null_transport.cc
new file mode 100644
index 0000000000..efbd9499d8
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/null_transport.cc
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "test/null_transport.h"
+
+namespace webrtc {
+namespace test {
+
+bool NullTransport::SendRtp(const uint8_t* packet,
+ size_t length,
+ const PacketOptions& options) {
+ return true;
+}
+
+bool NullTransport::SendRtcp(const uint8_t* packet, size_t length) {
+ return true;
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/null_transport.h b/third_party/libwebrtc/webrtc/test/null_transport.h
new file mode 100644
index 0000000000..f264e7b45a
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/null_transport.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef TEST_NULL_TRANSPORT_H_
+#define TEST_NULL_TRANSPORT_H_
+
+#include "api/call/transport.h"
+
+namespace webrtc {
+
+class PacketReceiver;
+
+namespace test {
+class NullTransport : public Transport {
+ public:
+ bool SendRtp(const uint8_t* packet,
+ size_t length,
+ const PacketOptions& options) override;
+ bool SendRtcp(const uint8_t* packet, size_t length) override;
+};
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_NULL_TRANSPORT_H_
diff --git a/third_party/libwebrtc/webrtc/test/rtcp_packet_parser.cc b/third_party/libwebrtc/webrtc/test/rtcp_packet_parser.cc
new file mode 100644
index 0000000000..2f9658a9e5
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/rtcp_packet_parser.cc
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/rtcp_packet_parser.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/logging.h"
+
+namespace webrtc {
+namespace test {
+
+RtcpPacketParser::RtcpPacketParser() = default;
+RtcpPacketParser::~RtcpPacketParser() = default;
+
+bool RtcpPacketParser::Parse(const void* data, size_t length) {
+ const uint8_t* const buffer = static_cast<const uint8_t*>(data);
+ const uint8_t* const buffer_end = buffer + length;
+ rtcp::CommonHeader header;
+ for (const uint8_t* next_packet = buffer; next_packet != buffer_end;
+ next_packet = header.NextPacket()) {
+ RTC_DCHECK_GT(buffer_end - next_packet, 0);
+ if (!header.Parse(next_packet, buffer_end - next_packet)) {
+ RTC_LOG(LS_WARNING)
+ << "Invalid rtcp header or unaligned rtcp packet at position "
+ << (next_packet - buffer);
+ return false;
+ }
+ switch (header.type()) {
+ case rtcp::App::kPacketType:
+ app_.Parse(header);
+ break;
+ case rtcp::Bye::kPacketType:
+ bye_.Parse(header, &sender_ssrc_);
+ break;
+ case rtcp::ExtendedReports::kPacketType:
+ xr_.Parse(header, &sender_ssrc_);
+ break;
+ case rtcp::ExtendedJitterReport::kPacketType:
+ ij_.Parse(header);
+ break;
+ case rtcp::Psfb::kPacketType:
+ switch (header.fmt()) {
+ case rtcp::Fir::kFeedbackMessageType:
+ fir_.Parse(header, &sender_ssrc_);
+ break;
+ case rtcp::Pli::kFeedbackMessageType:
+ pli_.Parse(header, &sender_ssrc_);
+ break;
+ case rtcp::Remb::kFeedbackMessageType:
+ remb_.Parse(header, &sender_ssrc_);
+ break;
+ default:
+ RTC_LOG(LS_WARNING)
+ << "Unknown rtcp payload specific feedback type "
+ << header.fmt();
+ break;
+ }
+ break;
+ case rtcp::ReceiverReport::kPacketType:
+ receiver_report_.Parse(header, &sender_ssrc_);
+ break;
+ case rtcp::Rtpfb::kPacketType:
+ switch (header.fmt()) {
+ case rtcp::Nack::kFeedbackMessageType:
+ nack_.Parse(header, &sender_ssrc_);
+ break;
+ case rtcp::RapidResyncRequest::kFeedbackMessageType:
+ rrr_.Parse(header, &sender_ssrc_);
+ break;
+ case rtcp::Tmmbn::kFeedbackMessageType:
+ tmmbn_.Parse(header, &sender_ssrc_);
+ break;
+ case rtcp::Tmmbr::kFeedbackMessageType:
+ tmmbr_.Parse(header, &sender_ssrc_);
+ break;
+ case rtcp::TransportFeedback::kFeedbackMessageType:
+ transport_feedback_.Parse(header, &sender_ssrc_);
+ break;
+ default:
+ RTC_LOG(LS_WARNING)
+ << "Unknown rtcp transport feedback type " << header.fmt();
+ break;
+ }
+ break;
+ case rtcp::Sdes::kPacketType:
+ sdes_.Parse(header);
+ break;
+ case rtcp::SenderReport::kPacketType:
+ sender_report_.Parse(header, &sender_ssrc_);
+ break;
+ default:
+ RTC_LOG(LS_WARNING) << "Unknown rtcp packet type " << header.type();
+ break;
+ }
+ }
+ return true;
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/rtcp_packet_parser.h b/third_party/libwebrtc/webrtc/test/rtcp_packet_parser.h
new file mode 100644
index 0000000000..96e97c107d
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/rtcp_packet_parser.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ *
+ */
+
+#ifndef TEST_RTCP_PACKET_PARSER_H_
+#define TEST_RTCP_PACKET_PARSER_H_
+
+#include "api/array_view.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/app.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/bye.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/common_header.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/extended_jitter_report.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/extended_reports.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/fir.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/nack.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/pli.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/rapid_resync_request.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/receiver_report.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/remb.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/sdes.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/sender_report.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/tmmbn.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/tmmbr.h"
+#include "modules/rtp_rtcp/source/rtcp_packet/transport_feedback.h"
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+namespace test {
+// Parse RTCP packet of given type. Assumes RTCP header is valid and that there
+// is excatly one packet of correct type in the buffer.
+template <typename Packet>
+bool ParseSinglePacket(const uint8_t* buffer, size_t size, Packet* packet) {
+ rtcp::CommonHeader header;
+ RTC_CHECK(header.Parse(buffer, size));
+ RTC_CHECK_EQ(size, header.NextPacket() - buffer);
+ return packet->Parse(header);
+}
+// Same function, but takes raw buffer as single argument instead of pair.
+template <typename Packet>
+bool ParseSinglePacket(rtc::ArrayView<const uint8_t> buffer, Packet* packet) {
+ return ParseSinglePacket(buffer.data(), buffer.size(), packet);
+}
+
+class RtcpPacketParser {
+ public:
+ // Keeps last parsed packet, count number of parsed packets of given type.
+ template <typename TypedRtcpPacket>
+ class PacketCounter : public TypedRtcpPacket {
+ public:
+ int num_packets() const { return num_packets_; }
+ void Parse(const rtcp::CommonHeader& header) {
+ if (TypedRtcpPacket::Parse(header))
+ ++num_packets_;
+ }
+ void Parse(const rtcp::CommonHeader& header, uint32_t* sender_ssrc) {
+ if (TypedRtcpPacket::Parse(header)) {
+ ++num_packets_;
+ if (*sender_ssrc == 0) // Use first sender ssrc in compound packet.
+ *sender_ssrc = TypedRtcpPacket::sender_ssrc();
+ }
+ }
+
+ private:
+ int num_packets_ = 0;
+ };
+
+ RtcpPacketParser();
+ ~RtcpPacketParser();
+
+ bool Parse(const void* packet, size_t packet_len);
+
+ PacketCounter<rtcp::App>* app() { return &app_; }
+ PacketCounter<rtcp::Bye>* bye() { return &bye_; }
+ PacketCounter<rtcp::ExtendedJitterReport>* ij() { return &ij_; }
+ PacketCounter<rtcp::ExtendedReports>* xr() { return &xr_; }
+ PacketCounter<rtcp::Fir>* fir() { return &fir_; }
+ PacketCounter<rtcp::Nack>* nack() { return &nack_; }
+ PacketCounter<rtcp::Pli>* pli() { return &pli_; }
+ PacketCounter<rtcp::RapidResyncRequest>* rrr() { return &rrr_; }
+ PacketCounter<rtcp::ReceiverReport>* receiver_report() {
+ return &receiver_report_;
+ }
+ PacketCounter<rtcp::Remb>* remb() { return &remb_; }
+ PacketCounter<rtcp::Sdes>* sdes() { return &sdes_; }
+ PacketCounter<rtcp::SenderReport>* sender_report() { return &sender_report_; }
+ PacketCounter<rtcp::Tmmbn>* tmmbn() { return &tmmbn_; }
+ PacketCounter<rtcp::Tmmbr>* tmmbr() { return &tmmbr_; }
+ PacketCounter<rtcp::TransportFeedback>* transport_feedback() {
+ return &transport_feedback_;
+ }
+ uint32_t sender_ssrc() const { return sender_ssrc_; }
+
+ private:
+ PacketCounter<rtcp::App> app_;
+ PacketCounter<rtcp::Bye> bye_;
+ PacketCounter<rtcp::ExtendedJitterReport> ij_;
+ PacketCounter<rtcp::ExtendedReports> xr_;
+ PacketCounter<rtcp::Fir> fir_;
+ PacketCounter<rtcp::Nack> nack_;
+ PacketCounter<rtcp::Pli> pli_;
+ PacketCounter<rtcp::RapidResyncRequest> rrr_;
+ PacketCounter<rtcp::ReceiverReport> receiver_report_;
+ PacketCounter<rtcp::Remb> remb_;
+ PacketCounter<rtcp::Sdes> sdes_;
+ PacketCounter<rtcp::SenderReport> sender_report_;
+ PacketCounter<rtcp::Tmmbn> tmmbn_;
+ PacketCounter<rtcp::Tmmbr> tmmbr_;
+ PacketCounter<rtcp::TransportFeedback> transport_feedback_;
+ uint32_t sender_ssrc_ = 0;
+};
+
+} // namespace test
+} // namespace webrtc
+#endif // TEST_RTCP_PACKET_PARSER_H_
diff --git a/third_party/libwebrtc/webrtc/test/rtp_file_reader.cc b/third_party/libwebrtc/webrtc/test/rtp_file_reader.cc
new file mode 100644
index 0000000000..0367487543
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/rtp_file_reader.cc
@@ -0,0 +1,667 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/rtp_file_reader.h"
+
+#include <stdio.h>
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "modules/rtp_rtcp/source/rtp_utility.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/constructormagic.h"
+#include "rtc_base/format_macros.h"
+#include "rtc_base/logging.h"
+
+namespace webrtc {
+namespace test {
+
+static const size_t kFirstLineLength = 40;
+static uint16_t kPacketHeaderSize = 8;
+
+#define TRY(expr) \
+ do { \
+ if (!(expr)) { \
+ RTC_LOG(LS_INFO) << "Failed to read"; \
+ return false; \
+ } \
+ } while (0)
+
+bool ReadUint32(uint32_t* out, FILE* file) {
+ *out = 0;
+ for (size_t i = 0; i < 4; ++i) {
+ *out <<= 8;
+ uint8_t tmp;
+ if (fread(&tmp, 1, sizeof(uint8_t), file) != sizeof(uint8_t))
+ return false;
+ *out |= tmp;
+ }
+ return true;
+}
+
+bool ReadUint16(uint16_t* out, FILE* file) {
+ *out = 0;
+ for (size_t i = 0; i < 2; ++i) {
+ *out <<= 8;
+ uint8_t tmp;
+ if (fread(&tmp, 1, sizeof(uint8_t), file) != sizeof(uint8_t))
+ return false;
+ *out |= tmp;
+ }
+ return true;
+}
+
+class RtpFileReaderImpl : public RtpFileReader {
+ public:
+ virtual bool Init(const std::string& filename,
+ const std::set<uint32_t>& ssrc_filter) = 0;
+};
+
+class InterleavedRtpFileReader : public RtpFileReaderImpl {
+ public:
+ virtual ~InterleavedRtpFileReader() {
+ if (file_ != NULL) {
+ fclose(file_);
+ file_ = NULL;
+ }
+ }
+
+ virtual bool Init(const std::string& filename,
+ const std::set<uint32_t>& ssrc_filter) {
+ file_ = fopen(filename.c_str(), "rb");
+ if (file_ == NULL) {
+ printf("ERROR: Can't open file: %s\n", filename.c_str());
+ return false;
+ }
+ return true;
+ }
+ virtual bool NextPacket(RtpPacket* packet) {
+ assert(file_ != NULL);
+ packet->length = RtpPacket::kMaxPacketBufferSize;
+ uint32_t len = 0;
+ TRY(ReadUint32(&len, file_));
+ if (packet->length < len) {
+ FATAL() << "Packet is too large to fit: " << len << " bytes vs "
+ << packet->length
+ << " bytes allocated. Consider increasing the buffer "
+ "size";
+ }
+ if (fread(packet->data, 1, len, file_) != len)
+ return false;
+
+ packet->length = len;
+ packet->original_length = len;
+ packet->time_ms = time_ms_;
+ time_ms_ += 5;
+ return true;
+ }
+
+ private:
+ FILE* file_ = NULL;
+ int64_t time_ms_ = 0;
+};
+
+// Read RTP packets from file in rtpdump format, as documented at:
+// http://www.cs.columbia.edu/irt/software/rtptools/
+class RtpDumpReader : public RtpFileReaderImpl {
+ public:
+ RtpDumpReader() : file_(NULL) {}
+ virtual ~RtpDumpReader() {
+ if (file_ != NULL) {
+ fclose(file_);
+ file_ = NULL;
+ }
+ }
+
+ bool Init(const std::string& filename,
+ const std::set<uint32_t>& ssrc_filter) override {
+ file_ = fopen(filename.c_str(), "rb");
+ if (file_ == NULL) {
+ printf("ERROR: Can't open file: %s\n", filename.c_str());
+ return false;
+ }
+
+ char firstline[kFirstLineLength + 1] = {0};
+ if (fgets(firstline, kFirstLineLength, file_) == NULL) {
+ RTC_LOG(LS_INFO) << "Can't read from file";
+ return false;
+ }
+ if (strncmp(firstline, "#!rtpplay", 9) == 0) {
+ if (strncmp(firstline, "#!rtpplay1.0", 12) != 0) {
+ RTC_LOG(LS_INFO) << "Wrong rtpplay version, must be 1.0";
+ return false;
+ }
+ } else if (strncmp(firstline, "#!RTPencode", 11) == 0) {
+ if (strncmp(firstline, "#!RTPencode1.0", 14) != 0) {
+ RTC_LOG(LS_INFO) << "Wrong RTPencode version, must be 1.0";
+ return false;
+ }
+ } else {
+ RTC_LOG(LS_INFO) << "Wrong file format of input file";
+ return false;
+ }
+
+ uint32_t start_sec;
+ uint32_t start_usec;
+ uint32_t source;
+ uint16_t port;
+ uint16_t padding;
+ TRY(ReadUint32(&start_sec, file_));
+ TRY(ReadUint32(&start_usec, file_));
+ TRY(ReadUint32(&source, file_));
+ TRY(ReadUint16(&port, file_));
+ TRY(ReadUint16(&padding, file_));
+
+ return true;
+ }
+
+ bool NextPacket(RtpPacket* packet) override {
+ uint8_t* rtp_data = packet->data;
+ packet->length = RtpPacket::kMaxPacketBufferSize;
+
+ uint16_t len;
+ uint16_t plen;
+ uint32_t offset;
+ TRY(ReadUint16(&len, file_));
+ TRY(ReadUint16(&plen, file_));
+ TRY(ReadUint32(&offset, file_));
+
+ // Use 'len' here because a 'plen' of 0 specifies rtcp.
+ len -= kPacketHeaderSize;
+ if (packet->length < len) {
+ FATAL() << "Packet is too large to fit: " << len << " bytes vs "
+ << packet->length
+ << " bytes allocated. Consider increasing the buffer "
+ "size";
+ }
+ if (fread(rtp_data, 1, len, file_) != len) {
+ return false;
+ }
+
+ packet->length = len;
+ packet->original_length = plen;
+ packet->time_ms = offset;
+ return true;
+ }
+
+ private:
+ FILE* file_;
+
+ RTC_DISALLOW_COPY_AND_ASSIGN(RtpDumpReader);
+};
+
+enum {
+ kResultFail = -1,
+ kResultSuccess = 0,
+ kResultSkip = 1,
+
+ kPcapVersionMajor = 2,
+ kPcapVersionMinor = 4,
+ kLinktypeNull = 0,
+ kLinktypeEthernet = 1,
+ kBsdNullLoopback1 = 0x00000002,
+ kBsdNullLoopback2 = 0x02000000,
+ kEthernetIIHeaderMacSkip = 12,
+ kEthertypeIp = 0x0800,
+ kIpVersion4 = 4,
+ kMinIpHeaderLength = 20,
+ kFragmentOffsetClear = 0x0000,
+ kFragmentOffsetDoNotFragment = 0x4000,
+ kProtocolTcp = 0x06,
+ kProtocolUdp = 0x11,
+ kUdpHeaderLength = 8,
+ kMaxReadBufferSize = 4096
+};
+
+const uint32_t kPcapBOMSwapOrder = 0xd4c3b2a1UL;
+const uint32_t kPcapBOMNoSwapOrder = 0xa1b2c3d4UL;
+
+#define TRY_PCAP(expr) \
+ do { \
+ int r = (expr); \
+ if (r == kResultFail) { \
+ RTC_LOG(LS_INFO) << "FAIL at " << __FILE__ << ":" << __LINE__; \
+ return kResultFail; \
+ } else if (r == kResultSkip) { \
+ return kResultSkip; \
+ } \
+ } while (0)
+
+// Read RTP packets from file in tcpdump/libpcap format, as documented at:
+// http://wiki.wireshark.org/Development/LibpcapFileFormat
+class PcapReader : public RtpFileReaderImpl {
+ public:
+ PcapReader()
+ : file_(NULL),
+ swap_pcap_byte_order_(false),
+#ifdef WEBRTC_ARCH_BIG_ENDIAN
+ swap_network_byte_order_(false),
+#else
+ swap_network_byte_order_(true),
+#endif
+ read_buffer_(),
+ packets_by_ssrc_(),
+ packets_(),
+ next_packet_it_() {
+ }
+
+ virtual ~PcapReader() {
+ if (file_ != NULL) {
+ fclose(file_);
+ file_ = NULL;
+ }
+ }
+
+ bool Init(const std::string& filename,
+ const std::set<uint32_t>& ssrc_filter) override {
+ return Initialize(filename, ssrc_filter) == kResultSuccess;
+ }
+
+ int Initialize(const std::string& filename,
+ const std::set<uint32_t>& ssrc_filter) {
+ file_ = fopen(filename.c_str(), "rb");
+ if (file_ == NULL) {
+ printf("ERROR: Can't open file: %s\n", filename.c_str());
+ return kResultFail;
+ }
+
+ if (ReadGlobalHeader() < 0) {
+ return kResultFail;
+ }
+
+ int total_packet_count = 0;
+ uint32_t stream_start_ms = 0;
+ int32_t next_packet_pos = ftell(file_);
+ for (;;) {
+ TRY_PCAP(fseek(file_, next_packet_pos, SEEK_SET));
+ int result = ReadPacket(&next_packet_pos, stream_start_ms,
+ ++total_packet_count, ssrc_filter);
+ if (result == kResultFail) {
+ break;
+ } else if (result == kResultSuccess && packets_.size() == 1) {
+ assert(stream_start_ms == 0);
+ PacketIterator it = packets_.begin();
+ stream_start_ms = it->time_offset_ms;
+ it->time_offset_ms = 0;
+ }
+ }
+
+ if (feof(file_) == 0) {
+ printf("Failed reading file!\n");
+ return kResultFail;
+ }
+
+ printf("Total packets in file: %d\n", total_packet_count);
+ printf("Total RTP/RTCP packets: %" PRIuS "\n", packets_.size());
+
+ for (SsrcMapIterator mit = packets_by_ssrc_.begin();
+ mit != packets_by_ssrc_.end(); ++mit) {
+ uint32_t ssrc = mit->first;
+ const std::vector<uint32_t>& packet_indices = mit->second;
+ uint8_t pt = packets_[packet_indices[0]].rtp_header.payloadType;
+ printf("SSRC: %08x, %" PRIuS " packets, pt=%d\n", ssrc,
+ packet_indices.size(), pt);
+ }
+
+ // TODO(solenberg): Better validation of identified SSRC streams.
+ //
+ // Since we're dealing with raw network data here, we will wrongly identify
+ // some packets as RTP. When these packets are consumed by RtpPlayer, they
+ // are unlikely to cause issues as they will ultimately be filtered out by
+ // the RtpRtcp module. However, we should really do better filtering here,
+ // which we can accomplish in a number of ways, e.g.:
+ //
+ // - Verify that the time stamps and sequence numbers for RTP packets are
+ // both increasing/decreasing. If they move in different directions, the
+ // SSRC is likely bogus and can be dropped. (Normally they should be inc-
+ // reasing but we must allow packet reordering).
+ // - If RTP sequence number is not changing, drop the stream.
+ // - Can also use srcip:port->dstip:port pairs, assuming few SSRC collisions
+ // for up/down streams.
+
+ next_packet_it_ = packets_.begin();
+ return kResultSuccess;
+ }
+
+ bool NextPacket(RtpPacket* packet) override {
+ uint32_t length = RtpPacket::kMaxPacketBufferSize;
+ if (NextPcap(packet->data, &length, &packet->time_ms) != kResultSuccess)
+ return false;
+ packet->length = static_cast<size_t>(length);
+ packet->original_length = packet->length;
+ return true;
+ }
+
+ virtual int NextPcap(uint8_t* data, uint32_t* length, uint32_t* time_ms) {
+ assert(data);
+ assert(length);
+ assert(time_ms);
+
+ if (next_packet_it_ == packets_.end()) {
+ return -1;
+ }
+ if (*length < next_packet_it_->payload_length) {
+ return -1;
+ }
+ TRY_PCAP(fseek(file_, next_packet_it_->pos_in_file, SEEK_SET));
+ TRY_PCAP(Read(data, next_packet_it_->payload_length));
+ *length = next_packet_it_->payload_length;
+ *time_ms = next_packet_it_->time_offset_ms;
+ next_packet_it_++;
+
+ return 0;
+ }
+
+ private:
+ // A marker of an RTP packet within the file.
+ struct RtpPacketMarker {
+ uint32_t packet_number; // One-based index (like in WireShark)
+ uint32_t time_offset_ms;
+ uint32_t source_ip;
+ uint32_t dest_ip;
+ uint16_t source_port;
+ uint16_t dest_port;
+ RTPHeader rtp_header;
+ int32_t pos_in_file; // Byte offset of payload from start of file.
+ uint32_t payload_length;
+ };
+
+ typedef std::vector<RtpPacketMarker>::iterator PacketIterator;
+ typedef std::map<uint32_t, std::vector<uint32_t> > SsrcMap;
+ typedef std::map<uint32_t, std::vector<uint32_t> >::iterator SsrcMapIterator;
+
+ int ReadGlobalHeader() {
+ uint32_t magic;
+ TRY_PCAP(Read(&magic, false));
+ if (magic == kPcapBOMSwapOrder) {
+ swap_pcap_byte_order_ = true;
+ } else if (magic == kPcapBOMNoSwapOrder) {
+ swap_pcap_byte_order_ = false;
+ } else {
+ return kResultFail;
+ }
+
+ uint16_t version_major;
+ uint16_t version_minor;
+ TRY_PCAP(Read(&version_major, false));
+ TRY_PCAP(Read(&version_minor, false));
+ if (version_major != kPcapVersionMajor ||
+ version_minor != kPcapVersionMinor) {
+ return kResultFail;
+ }
+
+ int32_t this_zone; // GMT to local correction.
+ uint32_t sigfigs; // Accuracy of timestamps.
+ uint32_t snaplen; // Max length of captured packets, in octets.
+ uint32_t network; // Data link type.
+ TRY_PCAP(Read(&this_zone, false));
+ TRY_PCAP(Read(&sigfigs, false));
+ TRY_PCAP(Read(&snaplen, false));
+ TRY_PCAP(Read(&network, false));
+
+ // Accept only LINKTYPE_NULL and LINKTYPE_ETHERNET.
+ // See: http://www.tcpdump.org/linktypes.html
+ if (network != kLinktypeNull && network != kLinktypeEthernet) {
+ return kResultFail;
+ }
+
+ return kResultSuccess;
+ }
+
+ int ReadPacket(int32_t* next_packet_pos,
+ uint32_t stream_start_ms,
+ uint32_t number,
+ const std::set<uint32_t>& ssrc_filter) {
+ assert(next_packet_pos);
+
+ uint32_t ts_sec; // Timestamp seconds.
+ uint32_t ts_usec; // Timestamp microseconds.
+ uint32_t incl_len; // Number of octets of packet saved in file.
+ uint32_t orig_len; // Actual length of packet.
+ TRY_PCAP(Read(&ts_sec, false));
+ TRY_PCAP(Read(&ts_usec, false));
+ TRY_PCAP(Read(&incl_len, false));
+ TRY_PCAP(Read(&orig_len, false));
+
+ *next_packet_pos = ftell(file_) + incl_len;
+
+ RtpPacketMarker marker = {0};
+ marker.packet_number = number;
+ marker.time_offset_ms = CalcTimeDelta(ts_sec, ts_usec, stream_start_ms);
+ TRY_PCAP(ReadPacketHeader(&marker));
+ marker.pos_in_file = ftell(file_);
+
+ if (marker.payload_length > sizeof(read_buffer_)) {
+ printf("Packet too large!\n");
+ return kResultFail;
+ }
+ TRY_PCAP(Read(read_buffer_, marker.payload_length));
+
+ RtpUtility::RtpHeaderParser rtp_parser(read_buffer_, marker.payload_length);
+ if (rtp_parser.RTCP()) {
+ rtp_parser.ParseRtcp(&marker.rtp_header);
+ packets_.push_back(marker);
+ } else {
+ if (!rtp_parser.Parse(&marker.rtp_header, nullptr)) {
+ RTC_LOG(LS_INFO) << "Not recognized as RTP/RTCP";
+ return kResultSkip;
+ }
+
+ uint32_t ssrc = marker.rtp_header.ssrc;
+ if (ssrc_filter.empty() || ssrc_filter.find(ssrc) != ssrc_filter.end()) {
+ packets_by_ssrc_[ssrc].push_back(
+ static_cast<uint32_t>(packets_.size()));
+ packets_.push_back(marker);
+ } else {
+ return kResultSkip;
+ }
+ }
+
+ return kResultSuccess;
+ }
+
+ int ReadPacketHeader(RtpPacketMarker* marker) {
+ int32_t file_pos = ftell(file_);
+
+ // Check for BSD null/loopback frame header. The header is just 4 bytes in
+ // native byte order, so we check for both versions as we don't care about
+ // the header as such and will likely fail reading the IP header if this is
+ // something else than null/loopback.
+ uint32_t protocol;
+ TRY_PCAP(Read(&protocol, true));
+ if (protocol == kBsdNullLoopback1 || protocol == kBsdNullLoopback2) {
+ int result = ReadXxpIpHeader(marker);
+ RTC_LOG(LS_INFO) << "Recognized loopback frame";
+ if (result != kResultSkip) {
+ return result;
+ }
+ }
+
+ TRY_PCAP(fseek(file_, file_pos, SEEK_SET));
+
+ // Check for Ethernet II, IP frame header.
+ uint16_t type;
+ TRY_PCAP(Skip(kEthernetIIHeaderMacSkip)); // Source+destination MAC.
+ TRY_PCAP(Read(&type, true));
+ if (type == kEthertypeIp) {
+ int result = ReadXxpIpHeader(marker);
+ RTC_LOG(LS_INFO) << "Recognized ethernet 2 frame";
+ if (result != kResultSkip) {
+ return result;
+ }
+ }
+
+ return kResultSkip;
+ }
+
+ uint32_t CalcTimeDelta(uint32_t ts_sec, uint32_t ts_usec, uint32_t start_ms) {
+ // Round to nearest ms.
+ uint64_t t2_ms = ((static_cast<uint64_t>(ts_sec) * 1000000) + ts_usec +
+ 500) / 1000;
+ uint64_t t1_ms = static_cast<uint64_t>(start_ms);
+ if (t2_ms < t1_ms) {
+ return 0;
+ } else {
+ return t2_ms - t1_ms;
+ }
+ }
+
+ int ReadXxpIpHeader(RtpPacketMarker* marker) {
+ assert(marker);
+
+ uint16_t version;
+ uint16_t length;
+ uint16_t id;
+ uint16_t fragment;
+ uint16_t protocol;
+ uint16_t checksum;
+ TRY_PCAP(Read(&version, true));
+ TRY_PCAP(Read(&length, true));
+ TRY_PCAP(Read(&id, true));
+ TRY_PCAP(Read(&fragment, true));
+ TRY_PCAP(Read(&protocol, true));
+ TRY_PCAP(Read(&checksum, true));
+ TRY_PCAP(Read(&marker->source_ip, true));
+ TRY_PCAP(Read(&marker->dest_ip, true));
+
+ if (((version >> 12) & 0x000f) != kIpVersion4) {
+ RTC_LOG(LS_INFO) << "IP header is not IPv4";
+ return kResultSkip;
+ }
+
+ if (fragment != kFragmentOffsetClear &&
+ fragment != kFragmentOffsetDoNotFragment) {
+ RTC_LOG(LS_INFO) << "IP fragments cannot be handled";
+ return kResultSkip;
+ }
+
+ // Skip remaining fields of IP header.
+ uint16_t header_length = (version & 0x0f00) >> (8 - 2);
+ assert(header_length >= kMinIpHeaderLength);
+ TRY_PCAP(Skip(header_length - kMinIpHeaderLength));
+
+ protocol = protocol & 0x00ff;
+ if (protocol == kProtocolTcp) {
+ RTC_LOG(LS_INFO) << "TCP packets are not handled";
+ return kResultSkip;
+ } else if (protocol == kProtocolUdp) {
+ uint16_t length;
+ uint16_t checksum;
+ TRY_PCAP(Read(&marker->source_port, true));
+ TRY_PCAP(Read(&marker->dest_port, true));
+ TRY_PCAP(Read(&length, true));
+ TRY_PCAP(Read(&checksum, true));
+ marker->payload_length = length - kUdpHeaderLength;
+ } else {
+ RTC_LOG(LS_INFO) << "Unknown transport (expected UDP or TCP)";
+ return kResultSkip;
+ }
+
+ return kResultSuccess;
+ }
+
+ int Read(uint32_t* out, bool expect_network_order) {
+ uint32_t tmp = 0;
+ if (fread(&tmp, 1, sizeof(uint32_t), file_) != sizeof(uint32_t)) {
+ return kResultFail;
+ }
+ if ((!expect_network_order && swap_pcap_byte_order_) ||
+ (expect_network_order && swap_network_byte_order_)) {
+ tmp = ((tmp >> 24) & 0x000000ff) | (tmp << 24) |
+ ((tmp >> 8) & 0x0000ff00) | ((tmp << 8) & 0x00ff0000);
+ }
+ *out = tmp;
+ return kResultSuccess;
+ }
+
+ int Read(uint16_t* out, bool expect_network_order) {
+ uint16_t tmp = 0;
+ if (fread(&tmp, 1, sizeof(uint16_t), file_) != sizeof(uint16_t)) {
+ return kResultFail;
+ }
+ if ((!expect_network_order && swap_pcap_byte_order_) ||
+ (expect_network_order && swap_network_byte_order_)) {
+ tmp = ((tmp >> 8) & 0x00ff) | (tmp << 8);
+ }
+ *out = tmp;
+ return kResultSuccess;
+ }
+
+ int Read(uint8_t* out, uint32_t count) {
+ if (fread(out, 1, count, file_) != count) {
+ return kResultFail;
+ }
+ return kResultSuccess;
+ }
+
+ int Read(int32_t* out, bool expect_network_order) {
+ int32_t tmp = 0;
+ if (fread(&tmp, 1, sizeof(uint32_t), file_) != sizeof(uint32_t)) {
+ return kResultFail;
+ }
+ if ((!expect_network_order && swap_pcap_byte_order_) ||
+ (expect_network_order && swap_network_byte_order_)) {
+ tmp = ((tmp >> 24) & 0x000000ff) | (tmp << 24) |
+ ((tmp >> 8) & 0x0000ff00) | ((tmp << 8) & 0x00ff0000);
+ }
+ *out = tmp;
+ return kResultSuccess;
+ }
+
+ int Skip(uint32_t length) {
+ if (fseek(file_, length, SEEK_CUR) != 0) {
+ return kResultFail;
+ }
+ return kResultSuccess;
+ }
+
+ FILE* file_;
+ bool swap_pcap_byte_order_;
+ const bool swap_network_byte_order_;
+ uint8_t read_buffer_[kMaxReadBufferSize];
+
+ SsrcMap packets_by_ssrc_;
+ std::vector<RtpPacketMarker> packets_;
+ PacketIterator next_packet_it_;
+
+ RTC_DISALLOW_COPY_AND_ASSIGN(PcapReader);
+};
+
+RtpFileReader* RtpFileReader::Create(FileFormat format,
+ const std::string& filename,
+ const std::set<uint32_t>& ssrc_filter) {
+ RtpFileReaderImpl* reader = NULL;
+ switch (format) {
+ case kPcap:
+ reader = new PcapReader();
+ break;
+ case kRtpDump:
+ reader = new RtpDumpReader();
+ break;
+ case kLengthPacketInterleaved:
+ reader = new InterleavedRtpFileReader();
+ break;
+ }
+ if (!reader->Init(filename, ssrc_filter)) {
+ delete reader;
+ return NULL;
+ }
+ return reader;
+}
+
+RtpFileReader* RtpFileReader::Create(FileFormat format,
+ const std::string& filename) {
+ return RtpFileReader::Create(format, filename, std::set<uint32_t>());
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/rtp_file_reader.h b/third_party/libwebrtc/webrtc/test/rtp_file_reader.h
new file mode 100644
index 0000000000..c044d3de26
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/rtp_file_reader.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef TEST_RTP_FILE_READER_H_
+#define TEST_RTP_FILE_READER_H_
+
+#include <set>
+#include <string>
+
+#include "common_types.h" // NOLINT(build/include)
+
+namespace webrtc {
+namespace test {
+
+struct RtpPacket {
+ // Accommodate for 50 ms packets of 32 kHz PCM16 samples (3200 bytes) plus
+ // some overhead.
+ static const size_t kMaxPacketBufferSize = 3500;
+ uint8_t data[kMaxPacketBufferSize];
+ size_t length;
+ // The length the packet had on wire. Will be different from |length| when
+ // reading a header-only RTP dump.
+ size_t original_length;
+
+ uint32_t time_ms;
+};
+
+class RtpFileReader {
+ public:
+ enum FileFormat { kPcap, kRtpDump, kLengthPacketInterleaved };
+
+ virtual ~RtpFileReader() {}
+ static RtpFileReader* Create(FileFormat format,
+ const std::string& filename);
+ static RtpFileReader* Create(FileFormat format,
+ const std::string& filename,
+ const std::set<uint32_t>& ssrc_filter);
+
+ virtual bool NextPacket(RtpPacket* packet) = 0;
+};
+} // namespace test
+} // namespace webrtc
+#endif // TEST_RTP_FILE_READER_H_
diff --git a/third_party/libwebrtc/webrtc/test/rtp_file_reader_unittest.cc b/third_party/libwebrtc/webrtc/test/rtp_file_reader_unittest.cc
new file mode 100644
index 0000000000..b41f32fc9c
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/rtp_file_reader_unittest.cc
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <map>
+#include <memory>
+
+#include "modules/rtp_rtcp/source/rtp_utility.h"
+#include "test/gtest.h"
+#include "test/rtp_file_reader.h"
+#include "test/testsupport/fileutils.h"
+
+namespace webrtc {
+
+class TestRtpFileReader : public ::testing::Test {
+ public:
+ void Init(const std::string& filename, bool headers_only_file) {
+ std::string filepath =
+ test::ResourcePath("video_coding/" + filename, "rtp");
+ rtp_packet_source_.reset(
+ test::RtpFileReader::Create(test::RtpFileReader::kRtpDump, filepath));
+ ASSERT_TRUE(rtp_packet_source_.get() != NULL);
+ headers_only_file_ = headers_only_file;
+ }
+
+ int CountRtpPackets() {
+ test::RtpPacket packet;
+ int c = 0;
+ while (rtp_packet_source_->NextPacket(&packet)) {
+ if (headers_only_file_)
+ EXPECT_LT(packet.length, packet.original_length);
+ else
+ EXPECT_EQ(packet.length, packet.original_length);
+ c++;
+ }
+ return c;
+ }
+
+ private:
+ std::unique_ptr<test::RtpFileReader> rtp_packet_source_;
+ bool headers_only_file_;
+};
+
+TEST_F(TestRtpFileReader, Test60Packets) {
+ Init("pltype103", false);
+ EXPECT_EQ(60, CountRtpPackets());
+}
+
+TEST_F(TestRtpFileReader, Test60PacketsHeaderOnly) {
+ Init("pltype103_header_only", true);
+ EXPECT_EQ(60, CountRtpPackets());
+}
+
+typedef std::map<uint32_t, int> PacketsPerSsrc;
+
+class TestPcapFileReader : public ::testing::Test {
+ public:
+ void Init(const std::string& filename) {
+ std::string filepath =
+ test::ResourcePath("video_coding/" + filename, "pcap");
+ rtp_packet_source_.reset(
+ test::RtpFileReader::Create(test::RtpFileReader::kPcap, filepath));
+ ASSERT_TRUE(rtp_packet_source_.get() != NULL);
+ }
+
+ int CountRtpPackets() {
+ int c = 0;
+ test::RtpPacket packet;
+ while (rtp_packet_source_->NextPacket(&packet)) {
+ EXPECT_EQ(packet.length, packet.original_length);
+ c++;
+ }
+ return c;
+ }
+
+ PacketsPerSsrc CountRtpPacketsPerSsrc() {
+ PacketsPerSsrc pps;
+ test::RtpPacket packet;
+ while (rtp_packet_source_->NextPacket(&packet)) {
+ RtpUtility::RtpHeaderParser rtp_header_parser(packet.data, packet.length);
+ webrtc::RTPHeader header;
+ if (!rtp_header_parser.RTCP() &&
+ rtp_header_parser.Parse(&header, nullptr)) {
+ pps[header.ssrc]++;
+ }
+ }
+ return pps;
+ }
+
+ private:
+ std::unique_ptr<test::RtpFileReader> rtp_packet_source_;
+};
+
+TEST_F(TestPcapFileReader, TestEthernetIIFrame) {
+ Init("frame-ethernet-ii");
+ EXPECT_EQ(368, CountRtpPackets());
+}
+
+TEST_F(TestPcapFileReader, TestLoopbackFrame) {
+ Init("frame-loopback");
+ EXPECT_EQ(491, CountRtpPackets());
+}
+
+TEST_F(TestPcapFileReader, TestTwoSsrc) {
+ Init("ssrcs-2");
+ PacketsPerSsrc pps = CountRtpPacketsPerSsrc();
+ EXPECT_EQ(2UL, pps.size());
+ EXPECT_EQ(370, pps[0x78d48f61]);
+ EXPECT_EQ(60, pps[0xae94130b]);
+}
+
+TEST_F(TestPcapFileReader, TestThreeSsrc) {
+ Init("ssrcs-3");
+ PacketsPerSsrc pps = CountRtpPacketsPerSsrc();
+ EXPECT_EQ(3UL, pps.size());
+ EXPECT_EQ(162, pps[0x938c5eaa]);
+ EXPECT_EQ(113, pps[0x59fe6ef0]);
+ EXPECT_EQ(61, pps[0xed2bd2ac]);
+}
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/rtp_file_writer.cc b/third_party/libwebrtc/webrtc/test/rtp_file_writer.cc
new file mode 100644
index 0000000000..132ce9a0a4
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/rtp_file_writer.cc
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/rtp_file_writer.h"
+
+#include <stdio.h>
+
+#include <string>
+
+#include "rtc_base/checks.h"
+#include "rtc_base/constructormagic.h"
+
+namespace webrtc {
+namespace test {
+
+static const uint16_t kPacketHeaderSize = 8;
+static const char kFirstLine[] = "#!rtpplay1.0 0.0.0.0/0\n";
+
+// Write RTP packets to file in rtpdump format, as documented at:
+// http://www.cs.columbia.edu/irt/software/rtptools/
+class RtpDumpWriter : public RtpFileWriter {
+ public:
+ explicit RtpDumpWriter(FILE* file) : file_(file) {
+ RTC_CHECK(file_ != NULL);
+ Init();
+ }
+ virtual ~RtpDumpWriter() {
+ if (file_ != NULL) {
+ fclose(file_);
+ file_ = NULL;
+ }
+ }
+
+ bool WritePacket(const RtpPacket* packet) override {
+ uint16_t len = static_cast<uint16_t>(packet->length + kPacketHeaderSize);
+ uint16_t plen = static_cast<uint16_t>(packet->original_length);
+ uint32_t offset = packet->time_ms;
+ RTC_CHECK(WriteUint16(len));
+ RTC_CHECK(WriteUint16(plen));
+ RTC_CHECK(WriteUint32(offset));
+ return fwrite(packet->data, sizeof(uint8_t), packet->length, file_) ==
+ packet->length;
+ }
+
+ private:
+ bool Init() {
+ fprintf(file_, "%s", kFirstLine);
+
+ RTC_CHECK(WriteUint32(0));
+ RTC_CHECK(WriteUint32(0));
+ RTC_CHECK(WriteUint32(0));
+ RTC_CHECK(WriteUint16(0));
+ RTC_CHECK(WriteUint16(0));
+
+ return true;
+ }
+
+ bool WriteUint32(uint32_t in) {
+ // Loop through shifts = {24, 16, 8, 0}.
+ for (int shifts = 24; shifts >= 0; shifts -= 8) {
+ uint8_t tmp = static_cast<uint8_t>((in >> shifts) & 0xFF);
+ if (fwrite(&tmp, sizeof(uint8_t), 1, file_) != 1)
+ return false;
+ }
+ return true;
+ }
+
+ bool WriteUint16(uint16_t in) {
+ // Write 8 MSBs.
+ uint8_t tmp = static_cast<uint8_t>((in >> 8) & 0xFF);
+ if (fwrite(&tmp, sizeof(uint8_t), 1, file_) != 1)
+ return false;
+ // Write 8 LSBs.
+ tmp = static_cast<uint8_t>(in & 0xFF);
+ if (fwrite(&tmp, sizeof(uint8_t), 1, file_) != 1)
+ return false;
+ return true;
+ }
+
+ FILE* file_;
+
+ RTC_DISALLOW_COPY_AND_ASSIGN(RtpDumpWriter);
+};
+
+RtpFileWriter* RtpFileWriter::Create(FileFormat format,
+ const std::string& filename) {
+ FILE* file = fopen(filename.c_str(), "wb");
+ if (file == NULL) {
+ printf("ERROR: Can't open file: %s\n", filename.c_str());
+ return NULL;
+ }
+ switch (format) {
+ case kRtpDump:
+ return new RtpDumpWriter(file);
+ }
+ fclose(file);
+ return NULL;
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/rtp_file_writer.h b/third_party/libwebrtc/webrtc/test/rtp_file_writer.h
new file mode 100644
index 0000000000..4496ca4a25
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/rtp_file_writer.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef TEST_RTP_FILE_WRITER_H_
+#define TEST_RTP_FILE_WRITER_H_
+
+#include <string>
+
+#include "common_types.h" // NOLINT(build/include)
+#include "test/rtp_file_reader.h"
+
+namespace webrtc {
+namespace test {
+class RtpFileWriter {
+ public:
+ enum FileFormat {
+ kRtpDump,
+ };
+
+ virtual ~RtpFileWriter() {}
+ static RtpFileWriter* Create(FileFormat format, const std::string& filename);
+
+ virtual bool WritePacket(const RtpPacket* packet) = 0;
+};
+} // namespace test
+} // namespace webrtc
+#endif // TEST_RTP_FILE_WRITER_H_
diff --git a/third_party/libwebrtc/webrtc/test/rtp_file_writer_unittest.cc b/third_party/libwebrtc/webrtc/test/rtp_file_writer_unittest.cc
new file mode 100644
index 0000000000..aec10f793b
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/rtp_file_writer_unittest.cc
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <string.h>
+
+#include <memory>
+
+#include "test/gtest.h"
+#include "test/rtp_file_reader.h"
+#include "test/rtp_file_writer.h"
+#include "test/testsupport/fileutils.h"
+
+namespace webrtc {
+
+class RtpFileWriterTest : public ::testing::Test {
+ public:
+ void Init(const std::string& filename) {
+ filename_ = test::OutputPath() + filename;
+ rtp_writer_.reset(
+ test::RtpFileWriter::Create(test::RtpFileWriter::kRtpDump, filename_));
+ }
+
+ void WriteRtpPackets(int num_packets) {
+ ASSERT_TRUE(rtp_writer_.get() != NULL);
+ test::RtpPacket packet;
+ for (int i = 1; i <= num_packets; ++i) {
+ packet.length = i;
+ packet.original_length = i;
+ packet.time_ms = i;
+ memset(packet.data, i, packet.length);
+ EXPECT_TRUE(rtp_writer_->WritePacket(&packet));
+ }
+ }
+
+ void CloseOutputFile() { rtp_writer_.reset(); }
+
+ void VerifyFileContents(int expected_packets) {
+ ASSERT_TRUE(rtp_writer_.get() == NULL)
+ << "Must call CloseOutputFile before VerifyFileContents";
+ std::unique_ptr<test::RtpFileReader> rtp_reader(
+ test::RtpFileReader::Create(test::RtpFileReader::kRtpDump, filename_));
+ ASSERT_TRUE(rtp_reader.get() != NULL);
+ test::RtpPacket packet;
+ int i = 0;
+ while (rtp_reader->NextPacket(&packet)) {
+ ++i;
+ EXPECT_EQ(static_cast<size_t>(i), packet.length);
+ EXPECT_EQ(static_cast<size_t>(i), packet.original_length);
+ EXPECT_EQ(static_cast<uint32_t>(i), packet.time_ms);
+ for (int j = 0; j < i; ++j) {
+ EXPECT_EQ(i, packet.data[j]);
+ }
+ }
+ EXPECT_EQ(expected_packets, i);
+ }
+
+ private:
+ std::unique_ptr<test::RtpFileWriter> rtp_writer_;
+ std::string filename_;
+};
+
+TEST_F(RtpFileWriterTest, WriteToRtpDump) {
+ Init("test_rtp_file_writer.rtp");
+ WriteRtpPackets(10);
+ CloseOutputFile();
+ VerifyFileContents(10);
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/rtp_rtcp_observer.h b/third_party/libwebrtc/webrtc/test/rtp_rtcp_observer.h
new file mode 100644
index 0000000000..5163d2248e
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/rtp_rtcp_observer.h
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef TEST_RTP_RTCP_OBSERVER_H_
+#define TEST_RTP_RTCP_OBSERVER_H_
+
+#include <map>
+#include <memory>
+#include <vector>
+
+#include "modules/rtp_rtcp/include/rtp_header_parser.h"
+#include "rtc_base/criticalsection.h"
+#include "rtc_base/event.h"
+#include "system_wrappers/include/field_trial.h"
+#include "test/constants.h"
+#include "test/direct_transport.h"
+#include "test/gtest.h"
+#include "typedefs.h" // NOLINT(build/include)
+#include "call/video_send_stream.h"
+
+namespace {
+const int kShortTimeoutMs = 500;
+}
+
+namespace webrtc {
+namespace test {
+
+class PacketTransport;
+class SingleThreadedTaskQueueForTesting;
+
+class RtpRtcpObserver {
+ public:
+ enum Action {
+ SEND_PACKET,
+ DROP_PACKET,
+ };
+
+ virtual ~RtpRtcpObserver() {}
+
+ virtual bool Wait() {
+ if (field_trial::IsEnabled("WebRTC-QuickPerfTest")) {
+ observation_complete_.Wait(kShortTimeoutMs);
+ return true;
+ }
+ return observation_complete_.Wait(timeout_ms_);
+ }
+
+ virtual Action OnSendRtp(const uint8_t* packet, size_t length) {
+ return SEND_PACKET;
+ }
+
+ virtual Action OnSendRtcp(const uint8_t* packet, size_t length) {
+ return SEND_PACKET;
+ }
+
+ virtual Action OnReceiveRtp(const uint8_t* packet, size_t length) {
+ return SEND_PACKET;
+ }
+
+ virtual Action OnReceiveRtcp(const uint8_t* packet, size_t length) {
+ return SEND_PACKET;
+ }
+
+ protected:
+ RtpRtcpObserver() : RtpRtcpObserver(0) {}
+ explicit RtpRtcpObserver(int event_timeout_ms)
+ : observation_complete_(false, false),
+ parser_(RtpHeaderParser::Create()),
+ timeout_ms_(event_timeout_ms) {
+ parser_->RegisterRtpHeaderExtension(kRtpExtensionTransmissionTimeOffset,
+ kTOffsetExtensionId);
+ parser_->RegisterRtpHeaderExtension(kRtpExtensionAbsoluteSendTime,
+ kAbsSendTimeExtensionId);
+ parser_->RegisterRtpHeaderExtension(kRtpExtensionTransportSequenceNumber,
+ kTransportSequenceNumberExtensionId);
+ }
+
+ rtc::Event observation_complete_;
+ const std::unique_ptr<RtpHeaderParser> parser_;
+
+ private:
+ const int timeout_ms_;
+};
+
+class PacketTransport : public test::DirectTransport {
+ public:
+ enum TransportType { kReceiver, kSender };
+
+ PacketTransport(SingleThreadedTaskQueueForTesting* task_queue,
+ Call* send_call,
+ RtpRtcpObserver* observer,
+ TransportType transport_type,
+ const std::map<uint8_t, MediaType>& payload_type_map,
+ const FakeNetworkPipe::Config& configuration)
+ : test::DirectTransport(task_queue,
+ configuration,
+ send_call,
+ payload_type_map),
+ observer_(observer),
+ transport_type_(transport_type) {}
+
+ PacketTransport(SingleThreadedTaskQueueForTesting* task_queue,
+ Call* send_call, RtpRtcpObserver* observer,
+ TransportType transport_type,
+ std::unique_ptr<FakeNetworkPipe> nw_pipe)
+ : test::DirectTransport(task_queue, std::move(nw_pipe), send_call),
+ observer_(observer),
+ transport_type_(transport_type) {}
+
+ private:
+ bool SendRtp(const uint8_t* packet,
+ size_t length,
+ const PacketOptions& options) override {
+ EXPECT_FALSE(RtpHeaderParser::IsRtcp(packet, length));
+ RtpRtcpObserver::Action action;
+ {
+ if (transport_type_ == kSender) {
+ action = observer_->OnSendRtp(packet, length);
+ } else {
+ action = observer_->OnReceiveRtp(packet, length);
+ }
+ }
+ switch (action) {
+ case RtpRtcpObserver::DROP_PACKET:
+ // Drop packet silently.
+ return true;
+ case RtpRtcpObserver::SEND_PACKET:
+ return test::DirectTransport::SendRtp(packet, length, options);
+ }
+ return true; // Will never happen, makes compiler happy.
+ }
+
+ bool SendRtcp(const uint8_t* packet, size_t length) override {
+ EXPECT_TRUE(RtpHeaderParser::IsRtcp(packet, length));
+ RtpRtcpObserver::Action action;
+ {
+ if (transport_type_ == kSender) {
+ action = observer_->OnSendRtcp(packet, length);
+ } else {
+ action = observer_->OnReceiveRtcp(packet, length);
+ }
+ }
+ switch (action) {
+ case RtpRtcpObserver::DROP_PACKET:
+ // Drop packet silently.
+ return true;
+ case RtpRtcpObserver::SEND_PACKET:
+ return test::DirectTransport::SendRtcp(packet, length);
+ }
+ return true; // Will never happen, makes compiler happy.
+ }
+
+ RtpRtcpObserver* const observer_;
+ TransportType transport_type_;
+};
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_RTP_RTCP_OBSERVER_H_
diff --git a/third_party/libwebrtc/webrtc/test/run_loop.cc b/third_party/libwebrtc/webrtc/test/run_loop.cc
new file mode 100644
index 0000000000..0d00ecd5e9
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/run_loop.cc
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "test/run_loop.h"
+
+#include <stdio.h>
+
+namespace webrtc {
+namespace test {
+
+void PressEnterToContinue() {
+ puts(">> Press ENTER to continue...");
+ while (getc(stdin) != '\n' && !feof(stdin));
+}
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/run_loop.h b/third_party/libwebrtc/webrtc/test/run_loop.h
new file mode 100644
index 0000000000..90063dc3e8
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/run_loop.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef TEST_RUN_LOOP_H_
+#define TEST_RUN_LOOP_H_
+
+namespace webrtc {
+namespace test {
+
+// Blocks until the user presses enter.
+void PressEnterToContinue();
+
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_RUN_LOOP_H_
diff --git a/third_party/libwebrtc/webrtc/test/run_test.cc b/third_party/libwebrtc/webrtc/test/run_test.cc
new file mode 100644
index 0000000000..ba0bf34d23
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/run_test.cc
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/run_test.h"
+
+#include <stdio.h>
+
+namespace webrtc {
+namespace test {
+
+void RunTest(void(*test)()) {
+ (*test)();
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/run_test.h b/third_party/libwebrtc/webrtc/test/run_test.h
new file mode 100644
index 0000000000..ed908570fd
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/run_test.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef TEST_RUN_TEST_H_
+#define TEST_RUN_TEST_H_
+
+namespace webrtc {
+namespace test {
+
+// Running a test function on a separate thread, if required by the OS.
+void RunTest(void(*test)());
+
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_RUN_TEST_H_
diff --git a/third_party/libwebrtc/webrtc/test/single_threaded_task_queue.cc b/third_party/libwebrtc/webrtc/test/single_threaded_task_queue.cc
new file mode 100644
index 0000000000..8a8cbea614
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/single_threaded_task_queue.cc
@@ -0,0 +1,144 @@
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/single_threaded_task_queue.h"
+
+#include <utility>
+
+#include "rtc_base/checks.h"
+#include "rtc_base/numerics/safe_conversions.h"
+#include "rtc_base/ptr_util.h"
+#include "rtc_base/timeutils.h"
+
+namespace webrtc {
+namespace test {
+
+SingleThreadedTaskQueueForTesting::QueuedTask::QueuedTask(
+ SingleThreadedTaskQueueForTesting::TaskId task_id,
+ int64_t earliest_execution_time,
+ SingleThreadedTaskQueueForTesting::Task task)
+ : task_id(task_id),
+ earliest_execution_time(earliest_execution_time),
+ task(task) {}
+
+SingleThreadedTaskQueueForTesting::QueuedTask::~QueuedTask() = default;
+
+SingleThreadedTaskQueueForTesting::SingleThreadedTaskQueueForTesting(
+ const char* name)
+ : thread_(Run, this, name),
+ running_(true),
+ next_task_id_(0),
+ wake_up_(false, false) {
+ thread_.Start();
+}
+
+SingleThreadedTaskQueueForTesting::~SingleThreadedTaskQueueForTesting() {
+ RTC_DCHECK_RUN_ON(&owner_thread_checker_);
+ {
+ rtc::CritScope lock(&cs_);
+ running_ = false;
+ }
+ wake_up_.Set();
+ thread_.Stop();
+}
+
+SingleThreadedTaskQueueForTesting::TaskId
+SingleThreadedTaskQueueForTesting::PostTask(Task task) {
+ return PostDelayedTask(task, 0);
+}
+
+SingleThreadedTaskQueueForTesting::TaskId
+SingleThreadedTaskQueueForTesting::PostDelayedTask(Task task,
+ int64_t delay_ms) {
+ int64_t earliest_exec_time = rtc::TimeAfter(delay_ms);
+
+ rtc::CritScope lock(&cs_);
+
+ TaskId id = next_task_id_++;
+
+ // Insert after any other tasks with an earlier-or-equal target time.
+ auto it = tasks_.begin();
+ for (; it != tasks_.end(); it++) {
+ if (earliest_exec_time < (*it)->earliest_execution_time) {
+ break;
+ }
+ }
+ tasks_.insert(it, rtc::MakeUnique<QueuedTask>(id, earliest_exec_time, task));
+
+ // This class is optimized for simplicty, not for performance. This will wake
+ // the thread up even if the next task in the queue is only scheduled for
+ // quite some time from now. In that case, the thread will just send itself
+ // back to sleep.
+ wake_up_.Set();
+
+ return id;
+}
+
+void SingleThreadedTaskQueueForTesting::SendTask(Task task) {
+ rtc::Event done(true, false);
+ PostTask([&task, &done]() {
+ task();
+ done.Set();
+ });
+ done.Wait(rtc::Event::kForever);
+}
+
+bool SingleThreadedTaskQueueForTesting::CancelTask(TaskId task_id) {
+ rtc::CritScope lock(&cs_);
+ for (auto it = tasks_.begin(); it != tasks_.end(); it++) {
+ if ((*it)->task_id == task_id) {
+ tasks_.erase(it);
+ return true;
+ }
+ }
+ return false;
+}
+
+void SingleThreadedTaskQueueForTesting::Run(void* obj) {
+ static_cast<SingleThreadedTaskQueueForTesting*>(obj)->RunLoop();
+}
+
+void SingleThreadedTaskQueueForTesting::RunLoop() {
+ while (true) {
+ std::unique_ptr<QueuedTask> queued_task;
+
+ // An empty queue would lead to sleeping until the queue becoems non-empty.
+ // A queue where the earliest task is shceduled for later than now, will
+ // lead to sleeping until the time of the next scheduled task (or until
+ // more tasks are scheduled).
+ int wait_time = rtc::Event::kForever;
+
+ {
+ rtc::CritScope lock(&cs_);
+ if (!running_) {
+ return;
+ }
+ if (!tasks_.empty()) {
+ int64_t remaining_delay_ms = rtc::TimeDiff(
+ tasks_.front()->earliest_execution_time, rtc::TimeMillis());
+ if (remaining_delay_ms <= 0) {
+ queued_task = std::move(tasks_.front());
+ tasks_.pop_front();
+ } else {
+ wait_time = rtc::saturated_cast<int>(remaining_delay_ms);
+ }
+ }
+ }
+
+ if (queued_task) {
+ queued_task->task();
+ } else {
+ wake_up_.Wait(wait_time);
+ }
+ }
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/single_threaded_task_queue.h b/third_party/libwebrtc/webrtc/test/single_threaded_task_queue.h
new file mode 100644
index 0000000000..0721891263
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/single_threaded_task_queue.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef TEST_SINGLE_THREADED_TASK_QUEUE_H_
+#define TEST_SINGLE_THREADED_TASK_QUEUE_H_
+
+#include <functional>
+#include <list>
+#include <memory>
+
+#include "rtc_base/criticalsection.h"
+#include "rtc_base/event.h"
+#include "rtc_base/platform_thread.h"
+#include "rtc_base/thread_checker.h"
+
+namespace webrtc {
+namespace test {
+
+// This class gives capabilities similar to rtc::TaskQueue, but ensures
+// everything happens on the same thread. This is intended to make the
+// threading model of unit-tests (specifically end-to-end tests) more closely
+// resemble that of real WebRTC, thereby allowing us to replace some critical
+// sections by thread-checkers.
+// This task is NOT tuned for performance, but rather for simplicity.
+class SingleThreadedTaskQueueForTesting {
+ public:
+ using Task = std::function<void()>;
+ using TaskId = size_t;
+
+ explicit SingleThreadedTaskQueueForTesting(const char* name);
+ ~SingleThreadedTaskQueueForTesting();
+
+ // Sends one task to the task-queue, and returns a handle by which the
+ // task can be cancelled.
+ // This mimics the behavior of TaskQueue, but only for lambdas, rather than
+ // for both lambdas and QueuedTask objects.
+ TaskId PostTask(Task task);
+
+ // Same as PostTask(), but ensures that the task will not begin execution
+ // less than |delay_ms| milliseconds after being posted; an upper bound
+ // is not provided.
+ TaskId PostDelayedTask(Task task, int64_t delay_ms);
+
+ // Send one task to the queue. The function does not return until the task
+ // has finished executing. No support for canceling the task.
+ void SendTask(Task task);
+
+ // Given an identifier to the task, attempts to eject it from the queue.
+ // Returns true if the task was found and cancelled. Failure possible
+ // only for invalid task IDs, or for tasks which have already been executed.
+ bool CancelTask(TaskId task_id);
+
+ private:
+ struct QueuedTask {
+ QueuedTask(TaskId task_id, int64_t earliest_execution_time, Task task);
+ ~QueuedTask();
+
+ TaskId task_id;
+ int64_t earliest_execution_time;
+ Task task;
+ };
+
+ static void Run(void* obj);
+
+ void RunLoop();
+
+ rtc::CriticalSection cs_;
+ std::list<std::unique_ptr<QueuedTask>> tasks_ RTC_GUARDED_BY(cs_);
+ rtc::ThreadChecker owner_thread_checker_;
+ rtc::PlatformThread thread_;
+ bool running_ RTC_GUARDED_BY(cs_);
+
+ TaskId next_task_id_;
+
+ // The task-queue will sleep when not executing a task. Wake up occurs when:
+ // * Upon destruction, to make sure that the |thead_| terminates, so that it
+ // may be joined. [Event will be set.]
+ // * New task added. Because we optimize for simplicity rahter than for
+ // performance (this class is a testing facility only), waking up occurs
+ // when we get a new task even if it is scheduled with a delay. The RunLoop
+ // is in charge of sending itself back to sleep if the next task is only
+ // to be executed at a later time. [Event will be set.]
+ // * When the next task in the queue is a delayed-task, and the time for
+ // its execution has come. [Event will time-out.]
+ rtc::Event wake_up_;
+};
+
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_SINGLE_THREADED_TASK_QUEUE_H_
diff --git a/third_party/libwebrtc/webrtc/test/single_threaded_task_queue_unittest.cc b/third_party/libwebrtc/webrtc/test/single_threaded_task_queue_unittest.cc
new file mode 100644
index 0000000000..5bd40d704a
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/single_threaded_task_queue_unittest.cc
@@ -0,0 +1,364 @@
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/single_threaded_task_queue.h"
+
+#include <atomic>
+#include <memory>
+#include <vector>
+
+#include "rtc_base/event.h"
+#include "rtc_base/ptr_util.h"
+#include "test/gtest.h"
+
+namespace webrtc {
+namespace test {
+
+namespace {
+
+using TaskId = SingleThreadedTaskQueueForTesting::TaskId;
+
+// Test should not rely on the object under test not being faulty. If the task
+// queue ever blocks forever, we want the tests to fail, rather than hang.
+constexpr int kMaxWaitTimeMs = 10000;
+
+TEST(SingleThreadedTaskQueueForTestingTest, SanityConstructionDestruction) {
+ SingleThreadedTaskQueueForTesting task_queue("task_queue");
+}
+
+TEST(SingleThreadedTaskQueueForTestingTest, ExecutesPostedTasks) {
+ SingleThreadedTaskQueueForTesting task_queue("task_queue");
+
+ std::atomic<bool> executed(false);
+ rtc::Event done(true, false);
+
+ task_queue.PostTask([&executed, &done]() {
+ executed.store(true);
+ done.Set();
+ });
+ ASSERT_TRUE(done.Wait(kMaxWaitTimeMs));
+
+ EXPECT_TRUE(executed.load());
+}
+
+TEST(SingleThreadedTaskQueueForTestingTest,
+ PostMultipleTasksFromSameExternalThread) {
+ SingleThreadedTaskQueueForTesting task_queue("task_queue");
+
+ constexpr size_t kCount = 3;
+ std::atomic<bool> executed[kCount];
+ for (std::atomic<bool>& exec : executed) {
+ exec.store(false);
+ }
+
+ std::vector<std::unique_ptr<rtc::Event>> done_events;
+ for (size_t i = 0; i < kCount; i++) {
+ done_events.emplace_back(rtc::MakeUnique<rtc::Event>(false, false));
+ }
+
+ // To avoid the tasks which comprise the actual test from running before they
+ // have all be posted, which could result in only one task ever being in the
+ // queue at any given time, post one waiting task that would block the
+ // task-queue, and unblock only after all tasks have been posted.
+ rtc::Event rendezvous(true, false);
+ task_queue.PostTask([&rendezvous]() {
+ ASSERT_TRUE(rendezvous.Wait(kMaxWaitTimeMs));
+ });
+
+ // Post the tasks which comprise the test.
+ for (size_t i = 0; i < kCount; i++) {
+ task_queue.PostTask([&executed, &done_events, i]() { // |i| by value.
+ executed[i].store(true);
+ done_events[i]->Set();
+ });
+ }
+
+ rendezvous.Set(); // Release the task-queue.
+
+ // Wait until the task queue has executed all the tasks.
+ for (size_t i = 0; i < kCount; i++) {
+ ASSERT_TRUE(done_events[i]->Wait(kMaxWaitTimeMs));
+ }
+
+ for (size_t i = 0; i < kCount; i++) {
+ EXPECT_TRUE(executed[i].load());
+ }
+}
+
+TEST(SingleThreadedTaskQueueForTestingTest, PostToTaskQueueFromOwnThread) {
+ SingleThreadedTaskQueueForTesting task_queue("task_queue");
+
+ std::atomic<bool> executed(false);
+ rtc::Event done(true, false);
+
+ auto internally_posted_task = [&executed, &done]() {
+ executed.store(true);
+ done.Set();
+ };
+
+ auto externally_posted_task = [&task_queue, &internally_posted_task]() {
+ task_queue.PostTask(internally_posted_task);
+ };
+
+ task_queue.PostTask(externally_posted_task);
+
+ ASSERT_TRUE(done.Wait(kMaxWaitTimeMs));
+ EXPECT_TRUE(executed.load());
+}
+
+TEST(SingleThreadedTaskQueueForTestingTest, TasksExecutedInSequence) {
+ SingleThreadedTaskQueueForTesting task_queue("task_queue");
+
+ // The first task would perform:
+ // accumulator = 10 * accumulator + i
+ // Where |i| is 1, 2 and 3 for the 1st, 2nd and 3rd tasks, respectively.
+ // The result would be 123 if and only iff the tasks were executed in order.
+ size_t accumulator = 0;
+ size_t expected_value = 0; // Updates to the correct value.
+
+ // Prevent the chain from being set in motion before we've had time to
+ // schedule it all, lest the queue only contain one task at a time.
+ rtc::Event rendezvous(true, false);
+ task_queue.PostTask([&rendezvous]() {
+ ASSERT_TRUE(rendezvous.Wait(kMaxWaitTimeMs));
+ });
+
+ for (size_t i = 0; i < 3; i++) {
+ task_queue.PostTask([&accumulator, i]() { // |i| passed by value.
+ accumulator = 10 * accumulator + i;
+ });
+ expected_value = 10 * expected_value + i;
+ }
+
+ // The test will wait for the task-queue to finish.
+ rtc::Event done(true, false);
+ task_queue.PostTask([&done]() {
+ done.Set();
+ });
+
+ rendezvous.Set(); // Set the chain in motion.
+
+ ASSERT_TRUE(done.Wait(kMaxWaitTimeMs));
+
+ EXPECT_EQ(accumulator, expected_value);
+}
+
+TEST(SingleThreadedTaskQueueForTestingTest, ExecutesPostedDelayedTask) {
+ SingleThreadedTaskQueueForTesting task_queue("task_queue");
+
+ std::atomic<bool> executed(false);
+ rtc::Event done(true, false);
+
+ constexpr int64_t delay_ms = 20;
+ static_assert(delay_ms < kMaxWaitTimeMs / 2, "Delay too long for tests.");
+
+ task_queue.PostDelayedTask([&executed, &done]() {
+ executed.store(true);
+ done.Set();
+ }, delay_ms);
+ ASSERT_TRUE(done.Wait(kMaxWaitTimeMs));
+
+ EXPECT_TRUE(executed.load());
+}
+
+TEST(SingleThreadedTaskQueueForTestingTest, DoesNotExecuteDelayedTaskTooSoon) {
+ SingleThreadedTaskQueueForTesting task_queue("task_queue");
+
+ std::atomic<bool> executed(false);
+
+ constexpr int64_t delay_ms = 2000;
+ static_assert(delay_ms < kMaxWaitTimeMs / 2, "Delay too long for tests.");
+
+ task_queue.PostDelayedTask([&executed]() {
+ executed.store(true);
+ }, delay_ms);
+
+ // Wait less than is enough, make sure the task was not yet executed.
+ rtc::Event not_done(true, false);
+ ASSERT_FALSE(not_done.Wait(delay_ms / 2));
+ EXPECT_FALSE(executed.load());
+}
+
+TEST(SingleThreadedTaskQueueForTestingTest,
+ TaskWithLesserDelayPostedAfterFirstDelayedTaskExectuedBeforeFirst) {
+ SingleThreadedTaskQueueForTesting task_queue("task_queue");
+
+ std::atomic<bool> earlier_executed(false);
+ constexpr int64_t earlier_delay_ms = 500;
+
+ std::atomic<bool> later_executed(false);
+ constexpr int64_t later_delay_ms = 1000;
+
+ static_assert(earlier_delay_ms + later_delay_ms < kMaxWaitTimeMs / 2,
+ "Delay too long for tests.");
+
+ rtc::Event done(true, false);
+
+ auto earlier_task = [&earlier_executed, &later_executed]() {
+ EXPECT_FALSE(later_executed.load());
+ earlier_executed.store(true);
+ };
+
+ auto later_task = [&earlier_executed, &later_executed, &done]() {
+ EXPECT_TRUE(earlier_executed.load());
+ later_executed.store(true);
+ done.Set();
+ };
+
+ task_queue.PostDelayedTask(later_task, later_delay_ms);
+ task_queue.PostDelayedTask(earlier_task, earlier_delay_ms);
+
+ ASSERT_TRUE(done.Wait(kMaxWaitTimeMs));
+ ASSERT_TRUE(earlier_executed);
+ ASSERT_TRUE(later_executed);
+}
+
+TEST(SingleThreadedTaskQueueForTestingTest,
+ TaskWithGreaterDelayPostedAfterFirstDelayedTaskExectuedAfterFirst) {
+ SingleThreadedTaskQueueForTesting task_queue("task_queue");
+
+ std::atomic<bool> earlier_executed(false);
+ constexpr int64_t earlier_delay_ms = 500;
+
+ std::atomic<bool> later_executed(false);
+ constexpr int64_t later_delay_ms = 1000;
+
+ static_assert(earlier_delay_ms + later_delay_ms < kMaxWaitTimeMs / 2,
+ "Delay too long for tests.");
+
+ rtc::Event done(true, false);
+
+ auto earlier_task = [&earlier_executed, &later_executed]() {
+ EXPECT_FALSE(later_executed.load());
+ earlier_executed.store(true);
+ };
+
+ auto later_task = [&earlier_executed, &later_executed, &done]() {
+ EXPECT_TRUE(earlier_executed.load());
+ later_executed.store(true);
+ done.Set();
+ };
+
+ task_queue.PostDelayedTask(earlier_task, earlier_delay_ms);
+ task_queue.PostDelayedTask(later_task, later_delay_ms);
+
+ ASSERT_TRUE(done.Wait(kMaxWaitTimeMs));
+ ASSERT_TRUE(earlier_executed);
+ ASSERT_TRUE(later_executed);
+}
+
+TEST(SingleThreadedTaskQueueForTestingTest, ExternalThreadCancelsTask) {
+ SingleThreadedTaskQueueForTesting task_queue("task_queue");
+
+ rtc::Event done(true, false);
+
+ // Prevent the to-be-cancelled task from being executed before we've had
+ // time to cancel it.
+ rtc::Event rendezvous(true, false);
+ task_queue.PostTask([&rendezvous]() {
+ ASSERT_TRUE(rendezvous.Wait(kMaxWaitTimeMs));
+ });
+
+ TaskId cancelled_task_id = task_queue.PostTask([]() {
+ EXPECT_TRUE(false);
+ });
+ task_queue.PostTask([&done]() {
+ done.Set();
+ });
+
+ task_queue.CancelTask(cancelled_task_id);
+
+ // Set the tasks in motion; the cancelled task does not run (otherwise the
+ // test would fail). The last task ends the test, showing that the queue
+ // progressed beyond the cancelled task.
+ rendezvous.Set();
+ ASSERT_TRUE(done.Wait(kMaxWaitTimeMs));
+}
+
+// In this test, we'll set off a chain where the first task cancels the second
+// task, then a third task runs (showing that we really cancelled the task,
+// rather than just halted the task-queue).
+TEST(SingleThreadedTaskQueueForTestingTest, InternalThreadCancelsTask) {
+ SingleThreadedTaskQueueForTesting task_queue("task_queue");
+
+ rtc::Event done(true, false);
+
+ // Prevent the chain from being set-off before we've set everything up.
+ rtc::Event rendezvous(true, false);
+ task_queue.PostTask([&rendezvous]() {
+ ASSERT_TRUE(rendezvous.Wait(kMaxWaitTimeMs));
+ });
+
+ // This is the canceller-task. It takes cancelled_task_id by reference,
+ // because the ID will only become known after the cancelled task is
+ // scheduled.
+ TaskId cancelled_task_id;
+ auto canceller_task = [&task_queue, &cancelled_task_id]() {
+ task_queue.CancelTask(cancelled_task_id);
+ };
+ task_queue.PostTask(canceller_task);
+
+ // This task will be cancelled by the task before it.
+ auto cancelled_task = []() {
+ EXPECT_TRUE(false);
+ };
+ cancelled_task_id = task_queue.PostTask(cancelled_task);
+
+ // When this task runs, it will allow the test to be finished.
+ auto completion_marker_task = [&done]() {
+ done.Set();
+ };
+ task_queue.PostTask(completion_marker_task);
+
+ rendezvous.Set(); // Set the chain in motion.
+
+ ASSERT_TRUE(done.Wait(kMaxWaitTimeMs));
+}
+
+TEST(SingleThreadedTaskQueueForTestingTest, SendTask) {
+ SingleThreadedTaskQueueForTesting task_queue("task_queue");
+
+ std::atomic<bool> executed(false);
+
+ task_queue.SendTask([&executed]() {
+ // Intentionally delay, so that if SendTask didn't block, the sender thread
+ // would have time to read |executed|.
+ rtc::Event delay(true, false);
+ ASSERT_FALSE(delay.Wait(1000));
+ executed.store(true);
+ });
+
+ EXPECT_TRUE(executed);
+}
+
+TEST(SingleThreadedTaskQueueForTestingTest,
+ DestructTaskQueueWhileTasksPending) {
+ auto task_queue =
+ rtc::MakeUnique<SingleThreadedTaskQueueForTesting>("task_queue");
+
+ std::atomic<size_t> counter(0);
+
+ constexpr size_t tasks = 10;
+ for (size_t i = 0; i < tasks; i++) {
+ task_queue->PostTask([&counter]() {
+ std::atomic_fetch_add(&counter, static_cast<size_t>(1));
+ rtc::Event delay(true, false);
+ ASSERT_FALSE(delay.Wait(500));
+ });
+ }
+
+ task_queue.reset();
+
+ EXPECT_LT(counter, tasks);
+}
+
+} // namespace
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/statistics.cc b/third_party/libwebrtc/webrtc/test/statistics.cc
new file mode 100644
index 0000000000..c43dde96fa
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/statistics.cc
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "test/statistics.h"
+
+#include <math.h>
+
+namespace webrtc {
+namespace test {
+
+Statistics::Statistics() : sum_(0.0), sum_squared_(0.0), count_(0) {}
+
+void Statistics::AddSample(double sample) {
+ sum_ += sample;
+ sum_squared_ += sample * sample;
+ ++count_;
+}
+
+double Statistics::Mean() const {
+ if (count_ == 0)
+ return 0.0;
+ return sum_ / count_;
+}
+
+double Statistics::Variance() const {
+ if (count_ == 0)
+ return 0.0;
+ return sum_squared_ / count_ - Mean() * Mean();
+}
+
+double Statistics::StandardDeviation() const {
+ return sqrt(Variance());
+}
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/statistics.h b/third_party/libwebrtc/webrtc/test/statistics.h
new file mode 100644
index 0000000000..d52d92dc11
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/statistics.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef TEST_STATISTICS_H_
+#define TEST_STATISTICS_H_
+
+#include "typedefs.h" // NOLINT(build/include)
+
+namespace webrtc {
+namespace test {
+
+class Statistics {
+ public:
+ Statistics();
+
+ void AddSample(double sample);
+
+ double Mean() const;
+ double Variance() const;
+ double StandardDeviation() const;
+
+ private:
+ double sum_;
+ double sum_squared_;
+ uint64_t count_;
+};
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_STATISTICS_H_
diff --git a/third_party/libwebrtc/webrtc/test/test_main.cc b/third_party/libwebrtc/webrtc/test/test_main.cc
new file mode 100644
index 0000000000..8bd2ed2244
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/test_main.cc
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "rtc_base/flags.h"
+#include "rtc_base/logging.h"
+#include "system_wrappers/include/metrics_default.h"
+#include "test/field_trial.h"
+#include "test/gmock.h"
+#include "test/gtest.h"
+#include "test/testsupport/fileutils.h"
+
+#if defined(WEBRTC_IOS)
+#include "test/ios/test_support.h"
+
+DEFINE_string(NSTreatUnknownArgumentsAsOpen, "",
+ "Intentionally ignored flag intended for iOS simulator.");
+DEFINE_string(ApplePersistenceIgnoreState, "",
+ "Intentionally ignored flag intended for iOS simulator.");
+#endif
+
+DEFINE_bool(logs, false, "print logs to stderr");
+
+DEFINE_string(force_fieldtrials, "",
+ "Field trials control experimental feature code which can be forced. "
+ "E.g. running with --force_fieldtrials=WebRTC-FooFeature/Enable/"
+ " will assign the group Enable to field trial WebRTC-FooFeature.");
+
+DEFINE_bool(help, false, "Print this message.");
+
+int main(int argc, char* argv[]) {
+ ::testing::InitGoogleMock(&argc, argv);
+
+ // Default to LS_INFO, even for release builds to provide better test logging.
+ // TODO(pbos): Consider adding a command-line override.
+ if (rtc::LogMessage::GetLogToDebug() > rtc::LS_INFO)
+ rtc::LogMessage::LogToDebug(rtc::LS_INFO);
+
+ if (rtc::FlagList::SetFlagsFromCommandLine(&argc, argv, false)) {
+ return 1;
+ }
+ if (FLAG_help) {
+ rtc::FlagList::Print(nullptr, false);
+ return 0;
+ }
+
+ webrtc::test::SetExecutablePath(argv[0]);
+ std::string fieldtrials = FLAG_force_fieldtrials;
+ webrtc::test::InitFieldTrialsFromString(fieldtrials);
+ webrtc::metrics::Enable();
+
+ rtc::LogMessage::SetLogToStderr(FLAG_logs);
+#if defined(WEBRTC_IOS)
+ rtc::test::InitTestSuite(RUN_ALL_TESTS, argc, argv);
+ rtc::test::RunTestsFromIOSApp();
+#endif
+
+ return RUN_ALL_TESTS();
+}
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/always_passing_unittest.cc b/third_party/libwebrtc/webrtc/test/testsupport/always_passing_unittest.cc
new file mode 100644
index 0000000000..e6318f7e0b
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/always_passing_unittest.cc
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/gtest.h"
+
+namespace webrtc {
+
+// A test that always passes. Useful when all tests in a executable are
+// disabled, since a gtest returns exit code 1 if no tests have executed.
+TEST(AlwaysPassingTest, AlwaysPassingTest) {}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/fileutils.cc b/third_party/libwebrtc/webrtc/test/testsupport/fileutils.cc
new file mode 100644
index 0000000000..2aff75a4d9
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/fileutils.cc
@@ -0,0 +1,363 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/testsupport/fileutils.h"
+
+#include <assert.h>
+
+#ifdef WIN32
+#include <direct.h>
+#include <tchar.h>
+#include <windows.h>
+#include <algorithm>
+
+#include "Shlwapi.h"
+#include "WinDef.h"
+
+#include "rtc_base/win32.h"
+#define GET_CURRENT_DIR _getcwd
+#else
+#include <dirent.h>
+#include <unistd.h>
+
+#define GET_CURRENT_DIR getcwd
+#endif
+
+#include <sys/stat.h> // To check for directory existence.
+#ifndef S_ISDIR // Not defined in stat.h on Windows.
+#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <memory>
+#include <utility>
+
+#include "rtc_base/checks.h"
+#include "typedefs.h" // NOLINT(build/include) // For architecture defines
+
+namespace webrtc {
+namespace test {
+
+#if defined(WEBRTC_IOS)
+// Defined in iosfileutils.mm. No header file to discourage use elsewhere.
+std::string IOSOutputPath();
+std::string IOSRootPath();
+std::string IOSResourcePath(std::string name, std::string extension);
+#endif
+
+namespace {
+
+#ifdef WIN32
+const char* kPathDelimiter = "\\";
+#else
+const char* kPathDelimiter = "/";
+#endif
+
+#ifdef WEBRTC_ANDROID
+const char* kRootDirName = "/sdcard/chromium_tests_root/";
+#else
+#if !defined(WEBRTC_IOS)
+const char* kOutputDirName = "out";
+#endif
+const char* kFallbackPath = "./";
+#endif // !defined(WEBRTC_ANDROID)
+
+#if !defined(WEBRTC_IOS)
+const char* kResourcesDirName = "resources";
+#endif
+
+char relative_dir_path[FILENAME_MAX];
+bool relative_dir_path_set = false;
+
+} // namespace
+
+const char* kCannotFindProjectRootDir = "ERROR_CANNOT_FIND_PROJECT_ROOT_DIR";
+
+void SetExecutablePath(const std::string& path) {
+ std::string working_dir = WorkingDir();
+ std::string temp_path = path;
+
+ // Handle absolute paths; convert them to relative paths to the working dir.
+ if (path.find(working_dir) != std::string::npos) {
+ temp_path = path.substr(working_dir.length() + 1);
+ }
+ // On Windows, when tests are run under memory tools like DrMemory and TSan,
+ // slashes occur in the path as directory separators. Make sure we replace
+ // such cases with backslashes in order for the paths to be correct.
+#ifdef WIN32
+ std::replace(temp_path.begin(), temp_path.end(), '/', '\\');
+#endif
+
+ // Trim away the executable name; only store the relative dir path.
+ temp_path = temp_path.substr(0, temp_path.find_last_of(kPathDelimiter));
+ strncpy(relative_dir_path, temp_path.c_str(), FILENAME_MAX);
+ relative_dir_path_set = true;
+}
+
+bool FileExists(const std::string& file_name) {
+ struct stat file_info = {0};
+ return stat(file_name.c_str(), &file_info) == 0;
+}
+
+bool DirExists(const std::string& directory_name) {
+ struct stat directory_info = {0};
+ return stat(directory_name.c_str(), &directory_info) == 0 && S_ISDIR(
+ directory_info.st_mode);
+}
+
+#ifdef WEBRTC_ANDROID
+
+std::string ProjectRootPath() {
+ return kRootDirName;
+}
+
+std::string OutputPath() {
+ return kRootDirName;
+}
+
+std::string WorkingDir() {
+ return kRootDirName;
+}
+
+#else // WEBRTC_ANDROID
+
+std::string ProjectRootPath() {
+#if defined(WEBRTC_IOS)
+ return IOSRootPath();
+#else
+ std::string path = WorkingDir();
+ if (path == kFallbackPath) {
+ return kCannotFindProjectRootDir;
+ }
+ if (relative_dir_path_set) {
+ path = path + kPathDelimiter + relative_dir_path;
+ }
+ path = path + kPathDelimiter + ".." + kPathDelimiter + "..";
+ char canonical_path[FILENAME_MAX];
+#ifdef WIN32
+ BOOL succeeded = PathCanonicalizeA(canonical_path, path.c_str());
+#else
+ bool succeeded = realpath(path.c_str(), canonical_path) != NULL;
+#endif
+ if (succeeded) {
+ path = std::string(canonical_path) + kPathDelimiter;
+ return path;
+ } else {
+ fprintf(stderr, "Cannot find project root directory!\n");
+ return kCannotFindProjectRootDir;
+ }
+#endif
+}
+
+std::string OutputPath() {
+#if defined(WEBRTC_IOS)
+ return IOSOutputPath();
+#else
+ std::string path = ProjectRootPath();
+ if (path == kCannotFindProjectRootDir) {
+ return kFallbackPath;
+ }
+ path += kOutputDirName;
+ if (!CreateDir(path)) {
+ return kFallbackPath;
+ }
+ return path + kPathDelimiter;
+#endif
+}
+
+std::string WorkingDir() {
+ char path_buffer[FILENAME_MAX];
+ if (!GET_CURRENT_DIR(path_buffer, sizeof(path_buffer))) {
+ fprintf(stderr, "Cannot get current directory!\n");
+ return kFallbackPath;
+ } else {
+ return std::string(path_buffer);
+ }
+}
+
+#endif // !WEBRTC_ANDROID
+
+// Generate a temporary filename in a safe way.
+// Largely copied from talk/base/{unixfilesystem,win32filesystem}.cc.
+std::string TempFilename(const std::string &dir, const std::string &prefix) {
+#ifdef WIN32
+ wchar_t filename[MAX_PATH];
+ if (::GetTempFileName(rtc::ToUtf16(dir).c_str(),
+ rtc::ToUtf16(prefix).c_str(), 0, filename) != 0)
+ return rtc::ToUtf8(filename);
+ assert(false);
+ return "";
+#else
+ int len = dir.size() + prefix.size() + 2 + 6;
+ std::unique_ptr<char[]> tempname(new char[len]);
+
+ snprintf(tempname.get(), len, "%s/%sXXXXXX", dir.c_str(),
+ prefix.c_str());
+ int fd = ::mkstemp(tempname.get());
+ if (fd == -1) {
+ assert(false);
+ return "";
+ } else {
+ ::close(fd);
+ }
+ std::string ret(tempname.get());
+ return ret;
+#endif
+}
+
+rtc::Optional<std::vector<std::string>> ReadDirectory(std::string path) {
+ if (path.length() == 0)
+ return rtc::Optional<std::vector<std::string>>();
+
+#if defined(WEBRTC_WIN)
+ // Append separator character if needed.
+ if (path.back() != '\\')
+ path += '\\';
+
+ // Init.
+ WIN32_FIND_DATA data;
+ HANDLE handle = ::FindFirstFile(rtc::ToUtf16(path + '*').c_str(), &data);
+ if (handle == INVALID_HANDLE_VALUE)
+ return rtc::Optional<std::vector<std::string>>();
+
+ // Populate output.
+ std::vector<std::string> found_entries;
+ do {
+ const std::string name = rtc::ToUtf8(data.cFileName);
+ if (name != "." && name != "..")
+ found_entries.emplace_back(path + name);
+ } while (::FindNextFile(handle, &data) == TRUE);
+
+ // Release resources.
+ if (handle != INVALID_HANDLE_VALUE)
+ ::FindClose(handle);
+#else
+ // Append separator character if needed.
+ if (path.back() != '/')
+ path += '/';
+
+ // Init.
+ DIR* dir = ::opendir(path.c_str());
+ if (dir == nullptr)
+ return rtc::Optional<std::vector<std::string>>();
+
+ // Populate output.
+ std::vector<std::string> found_entries;
+ while (dirent* dirent = readdir(dir)) {
+ const std::string& name = dirent->d_name;
+ if (name != "." && name != "..")
+ found_entries.emplace_back(path + name);
+ }
+
+ // Release resources.
+ closedir(dir);
+#endif
+
+ return rtc::Optional<std::vector<std::string>>(std::move(found_entries));
+}
+
+bool CreateDir(const std::string& directory_name) {
+ struct stat path_info = {0};
+ // Check if the path exists already:
+ if (stat(directory_name.c_str(), &path_info) == 0) {
+ if (!S_ISDIR(path_info.st_mode)) {
+ fprintf(stderr, "Path %s exists but is not a directory! Remove this "
+ "file and re-run to create the directory.\n",
+ directory_name.c_str());
+ return false;
+ }
+ } else {
+#ifdef WIN32
+ return _mkdir(directory_name.c_str()) == 0;
+#else
+ return mkdir(directory_name.c_str(), S_IRWXU | S_IRWXG | S_IRWXO) == 0;
+#endif
+ }
+ return true;
+}
+
+bool RemoveDir(const std::string& directory_name) {
+#ifdef WIN32
+ return RemoveDirectoryA(directory_name.c_str()) != FALSE;
+#else
+ return rmdir(directory_name.c_str()) == 0;
+#endif
+}
+
+bool RemoveFile(const std::string& file_name) {
+#ifdef WIN32
+ return DeleteFileA(file_name.c_str()) != FALSE;
+#else
+ return unlink(file_name.c_str()) == 0;
+#endif
+}
+
+std::string ResourcePath(const std::string& name,
+ const std::string& extension) {
+#if defined(WEBRTC_IOS)
+ return IOSResourcePath(name, extension);
+#else
+ std::string platform = "win";
+#ifdef WEBRTC_LINUX
+ platform = "linux";
+#endif // WEBRTC_LINUX
+#ifdef WEBRTC_MAC
+ platform = "mac";
+#endif // WEBRTC_MAC
+#ifdef WEBRTC_ANDROID
+ platform = "android";
+#endif // WEBRTC_ANDROID
+
+#ifdef WEBRTC_ARCH_64_BITS
+ std::string architecture = "64";
+#else
+ std::string architecture = "32";
+#endif // WEBRTC_ARCH_64_BITS
+
+ std::string resources_path = ProjectRootPath() + kResourcesDirName +
+ kPathDelimiter;
+ std::string resource_file = resources_path + name + "_" + platform + "_" +
+ architecture + "." + extension;
+ if (FileExists(resource_file)) {
+ return resource_file;
+ }
+ // Try without architecture.
+ resource_file = resources_path + name + "_" + platform + "." + extension;
+ if (FileExists(resource_file)) {
+ return resource_file;
+ }
+ // Try without platform.
+ resource_file = resources_path + name + "_" + architecture + "." + extension;
+ if (FileExists(resource_file)) {
+ return resource_file;
+ }
+
+ // Fall back on name without architecture or platform.
+ return resources_path + name + "." + extension;
+#endif // defined (WEBRTC_IOS)
+}
+
+size_t GetFileSize(const std::string& filename) {
+ FILE* f = fopen(filename.c_str(), "rb");
+ size_t size = 0;
+ if (f != NULL) {
+ if (fseek(f, 0, SEEK_END) == 0) {
+ size = ftell(f);
+ }
+ fclose(f);
+ }
+ return size;
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/fileutils.h b/third_party/libwebrtc/webrtc/test/testsupport/fileutils.h
new file mode 100644
index 0000000000..f0560cf979
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/fileutils.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <stdio.h>
+
+#ifndef TEST_TESTSUPPORT_FILEUTILS_H_
+#define TEST_TESTSUPPORT_FILEUTILS_H_
+
+#include <string>
+#include <vector>
+
+#include "api/optional.h"
+
+namespace webrtc {
+namespace test {
+
+// This is the "directory" returned if the ProjectPath() function fails
+// to find the project root.
+extern const char* kCannotFindProjectRootDir;
+
+// Creates and returns the absolute path to the output directory where log files
+// and other test artifacts should be put. The output directory is generally a
+// directory named "out" at the top-level of the project, i.e. a subfolder to
+// the path returned by ProjectRootPath(). The exception is Android where we use
+// /sdcard/ instead.
+//
+// If symbolic links occur in the path they will be resolved and the actual
+// directory will be returned.
+//
+// Returns the path WITH a trailing path delimiter. If the project root is not
+// found, the current working directory ("./") is returned as a fallback.
+std::string OutputPath();
+
+// Generates an empty file with a unique name in the specified directory and
+// returns the file name and path.
+std::string TempFilename(const std::string &dir, const std::string &prefix);
+
+// Returns a path to a resource file for the currently executing platform.
+// Adapts to what filenames are currently present in the
+// [project-root]/resources/ dir.
+// Returns an absolute path according to this priority list (the directory
+// part of the path is left out for readability):
+// 1. [name]_[platform]_[architecture].[extension]
+// 2. [name]_[platform].[extension]
+// 3. [name]_[architecture].[extension]
+// 4. [name].[extension]
+// Where
+// * platform is either of "win", "mac" or "linux".
+// * architecture is either of "32" or "64".
+//
+// Arguments:
+// name - Name of the resource file. If a plain filename (no directory path)
+// is supplied, the file is assumed to be located in resources/
+// If a directory path is prepended to the filename, a subdirectory
+// hierarchy reflecting that path is assumed to be present.
+// extension - File extension, without the dot, i.e. "bmp" or "yuv".
+std::string ResourcePath(const std::string& name,
+ const std::string& extension);
+
+// Gets the current working directory for the executing program.
+// Returns "./" if for some reason it is not possible to find the working
+// directory.
+std::string WorkingDir();
+
+// Reads the content of a directory and, in case of success, returns a vector
+// of strings with one element for each found file or directory. Each element is
+// a path created by prepending |dir| to the file/directory name. "." and ".."
+// are never added in the returned vector.
+rtc::Optional<std::vector<std::string>> ReadDirectory(std::string path);
+
+// Creates a directory if it not already exists.
+// Returns true if successful. Will print an error message to stderr and return
+// false if a file with the same name already exists.
+bool CreateDir(const std::string& directory_name);
+
+// Removes a directory, which must already be empty.
+bool RemoveDir(const std::string& directory_name);
+
+// Removes a file.
+bool RemoveFile(const std::string& file_name);
+
+// Checks if a file exists.
+bool FileExists(const std::string& file_name);
+
+// Checks if a directory exists.
+bool DirExists(const std::string& directory_name);
+
+// File size of the supplied file in bytes. Will return 0 if the file is
+// empty or if the file does not exist/is readable.
+size_t GetFileSize(const std::string& filename);
+
+// Sets the executable path, i.e. the path to the executable that is being used
+// when launching it. This is usually the path relative to the working directory
+// but can also be an absolute path. The intention with this function is to pass
+// the argv[0] being sent into the main function to make it possible for
+// fileutils.h to find the correct project paths even when the working directory
+// is outside the project tree (which happens in some cases).
+void SetExecutablePath(const std::string& path_to_executable);
+
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_TESTSUPPORT_FILEUTILS_H_
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/fileutils_unittest.cc b/third_party/libwebrtc/webrtc/test/testsupport/fileutils_unittest.cc
new file mode 100644
index 0000000000..79988c0dd3
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/fileutils_unittest.cc
@@ -0,0 +1,240 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/testsupport/fileutils.h"
+
+#include <stdio.h>
+
+#include <fstream>
+#include <iostream>
+#include <list>
+#include <string>
+
+#include "api/optional.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/pathutils.h"
+#include "test/gtest.h"
+
+#ifdef WIN32
+#define chdir _chdir
+static const char* kPathDelimiter = "\\";
+#else
+static const char* kPathDelimiter = "/";
+#endif
+
+static const char kTestName[] = "fileutils_unittest";
+static const char kExtension[] = "tmp";
+
+namespace webrtc {
+namespace test {
+
+namespace {
+
+// Remove files and directories in a directory non-recursively and writes the
+// number of deleted items in |num_deleted_entries|.
+void CleanDir(const std::string& dir, size_t* num_deleted_entries) {
+ RTC_DCHECK(num_deleted_entries);
+ *num_deleted_entries = 0;
+ rtc::Optional<std::vector<std::string>> dir_content = ReadDirectory(dir);
+ EXPECT_TRUE(dir_content);
+ for (const auto& entry : *dir_content) {
+ if (DirExists(entry)) {
+ EXPECT_TRUE(RemoveDir(entry));
+ (*num_deleted_entries)++;
+ } else if (FileExists(entry)) {
+ EXPECT_TRUE(RemoveFile(entry));
+ (*num_deleted_entries)++;
+ } else {
+ FAIL();
+ }
+ }
+}
+
+void WriteStringInFile(const std::string& what, const std::string& file_path) {
+ std::ofstream out(file_path);
+ out << what;
+ out.close();
+}
+
+} // namespace
+
+// Test fixture to restore the working directory between each test, since some
+// of them change it with chdir during execution (not restored by the
+// gtest framework).
+class FileUtilsTest : public testing::Test {
+ protected:
+ FileUtilsTest() {
+ }
+ ~FileUtilsTest() override {}
+ // Runs before the first test
+ static void SetUpTestCase() {
+ original_working_dir_ = webrtc::test::WorkingDir();
+ }
+ void SetUp() override {
+ ASSERT_EQ(chdir(original_working_dir_.c_str()), 0);
+ }
+ void TearDown() override {
+ ASSERT_EQ(chdir(original_working_dir_.c_str()), 0);
+ }
+ private:
+ static std::string original_working_dir_;
+};
+
+std::string FileUtilsTest::original_working_dir_ = "";
+
+// Tests that the project output dir path is returned for the default working
+// directory that is automatically set when the test executable is launched.
+// The test is not fully testing the implementation, since we cannot be sure
+// of where the executable was launched from.
+#if defined(WEBRTC_ANDROID) || defined(WEBRTC_IOS)
+#define MAYBE_OutputPathFromUnchangedWorkingDir \
+ DISABLED_OutputPathFromUnchangedWorkingDir
+#else
+#define MAYBE_OutputPathFromUnchangedWorkingDir \
+ OutputPathFromUnchangedWorkingDir
+#endif
+TEST_F(FileUtilsTest, MAYBE_OutputPathFromUnchangedWorkingDir) {
+ std::string path = webrtc::test::OutputPath();
+ std::string expected_end = "out";
+ expected_end = kPathDelimiter + expected_end + kPathDelimiter;
+ ASSERT_EQ(path.length() - expected_end.length(), path.find(expected_end));
+}
+
+// Tests with current working directory set to a directory higher up in the
+// directory tree than the project root dir.
+#if defined(WEBRTC_ANDROID) || defined(WIN32) || defined(WEBRTC_IOS)
+#define MAYBE_OutputPathFromRootWorkingDir DISABLED_OutputPathFromRootWorkingDir
+#else
+#define MAYBE_OutputPathFromRootWorkingDir OutputPathFromRootWorkingDir
+#endif
+TEST_F(FileUtilsTest, MAYBE_OutputPathFromRootWorkingDir) {
+ ASSERT_EQ(0, chdir(kPathDelimiter));
+ ASSERT_EQ("./", webrtc::test::OutputPath());
+}
+
+TEST_F(FileUtilsTest, TempFilename) {
+ std::string temp_filename = webrtc::test::TempFilename(
+ webrtc::test::OutputPath(), "TempFilenameTest");
+ ASSERT_TRUE(webrtc::test::FileExists(temp_filename))
+ << "Couldn't find file: " << temp_filename;
+ remove(temp_filename.c_str());
+}
+
+// Only tests that the code executes
+#if defined(WEBRTC_IOS)
+#define MAYBE_CreateDir DISABLED_CreateDir
+#else
+#define MAYBE_CreateDir CreateDir
+#endif
+TEST_F(FileUtilsTest, MAYBE_CreateDir) {
+ std::string directory = "fileutils-unittest-empty-dir";
+ // Make sure it's removed if a previous test has failed:
+ remove(directory.c_str());
+ ASSERT_TRUE(webrtc::test::CreateDir(directory));
+ remove(directory.c_str());
+}
+
+TEST_F(FileUtilsTest, WorkingDirReturnsValue) {
+ // Hard to cover all platforms. Just test that it returns something without
+ // crashing:
+ std::string working_dir = webrtc::test::WorkingDir();
+ ASSERT_GT(working_dir.length(), 0u);
+}
+
+// Due to multiple platforms, it is hard to make a complete test for
+// ResourcePath. Manual testing has been performed by removing files and
+// verified the result confirms with the specified documentation for the
+// function.
+TEST_F(FileUtilsTest, ResourcePathReturnsValue) {
+ std::string resource = webrtc::test::ResourcePath(kTestName, kExtension);
+ ASSERT_GT(resource.find(kTestName), 0u);
+ ASSERT_GT(resource.find(kExtension), 0u);
+}
+
+TEST_F(FileUtilsTest, ResourcePathFromRootWorkingDir) {
+ ASSERT_EQ(0, chdir(kPathDelimiter));
+ std::string resource = webrtc::test::ResourcePath(kTestName, kExtension);
+#if !defined(WEBRTC_IOS)
+ ASSERT_NE(resource.find("resources"), std::string::npos);
+#endif
+ ASSERT_GT(resource.find(kTestName), 0u);
+ ASSERT_GT(resource.find(kExtension), 0u);
+}
+
+TEST_F(FileUtilsTest, GetFileSizeExistingFile) {
+ // Create a file with some dummy data in.
+ std::string temp_filename = webrtc::test::TempFilename(
+ webrtc::test::OutputPath(), "fileutils_unittest");
+ FILE* file = fopen(temp_filename.c_str(), "wb");
+ ASSERT_TRUE(file != NULL) << "Failed to open file: " << temp_filename;
+ ASSERT_GT(fprintf(file, "%s", "Dummy data"), 0) <<
+ "Failed to write to file: " << temp_filename;
+ fclose(file);
+ ASSERT_GT(webrtc::test::GetFileSize(std::string(temp_filename.c_str())), 0u);
+ remove(temp_filename.c_str());
+}
+
+TEST_F(FileUtilsTest, GetFileSizeNonExistingFile) {
+ ASSERT_EQ(0u, webrtc::test::GetFileSize("non-existing-file.tmp"));
+}
+
+TEST_F(FileUtilsTest, DirExists) {
+ // Check that an existing directory is recognized as such.
+ ASSERT_TRUE(webrtc::test::DirExists(webrtc::test::OutputPath()))
+ << "Existing directory not found";
+
+ // Check that a non-existing directory is recognized as such.
+ std::string directory = "direxists-unittest-non_existing-dir";
+ ASSERT_FALSE(webrtc::test::DirExists(directory))
+ << "Non-existing directory found";
+
+ // Check that an existing file is not recognized as an existing directory.
+ std::string temp_filename = webrtc::test::TempFilename(
+ webrtc::test::OutputPath(), "TempFilenameTest");
+ ASSERT_TRUE(webrtc::test::FileExists(temp_filename))
+ << "Couldn't find file: " << temp_filename;
+ ASSERT_FALSE(webrtc::test::DirExists(temp_filename))
+ << "Existing file recognized as existing directory";
+ remove(temp_filename.c_str());
+}
+
+TEST_F(FileUtilsTest, WriteReadDeleteFilesAndDirs) {
+ size_t num_deleted_entries;
+
+ // Create an empty temporary directory for this test.
+ const std::string temp_directory =
+ OutputPath() + "TempFileUtilsTestReadDirectory" + kPathDelimiter;
+ CreateDir(temp_directory);
+ EXPECT_NO_FATAL_FAILURE(CleanDir(temp_directory, &num_deleted_entries));
+ EXPECT_TRUE(DirExists(temp_directory));
+
+ // Add a file.
+ const std::string temp_filename = temp_directory + "TempFilenameTest";
+ WriteStringInFile("test\n", temp_filename);
+ EXPECT_TRUE(FileExists(temp_filename));
+
+ // Add an empty directory.
+ const std::string temp_subdir = temp_directory + "subdir" + kPathDelimiter;
+ EXPECT_TRUE(CreateDir(temp_subdir));
+ EXPECT_TRUE(DirExists(temp_subdir));
+
+ // Checks.
+ rtc::Optional<std::vector<std::string>> dir_content =
+ ReadDirectory(temp_directory);
+ EXPECT_TRUE(dir_content);
+ EXPECT_EQ(2u, dir_content->size());
+ EXPECT_NO_FATAL_FAILURE(CleanDir(temp_directory, &num_deleted_entries));
+ EXPECT_EQ(2u, num_deleted_entries);
+ EXPECT_TRUE(RemoveDir(temp_directory));
+ EXPECT_FALSE(DirExists(temp_directory));
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/frame_reader.h b/third_party/libwebrtc/webrtc/test/testsupport/frame_reader.h
new file mode 100644
index 0000000000..2e19af344e
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/frame_reader.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef TEST_TESTSUPPORT_FRAME_READER_H_
+#define TEST_TESTSUPPORT_FRAME_READER_H_
+
+#include <stdio.h>
+
+#include <string>
+
+#include "rtc_base/scoped_ref_ptr.h"
+#include "typedefs.h" // NOLINT(build/include)
+
+namespace webrtc {
+class I420Buffer;
+namespace test {
+
+// Handles reading of I420 frames from video files.
+class FrameReader {
+ public:
+ virtual ~FrameReader() {}
+
+ // Initializes the frame reader, i.e. opens the input file.
+ // This must be called before reading of frames has started.
+ // Returns false if an error has occurred, in addition to printing to stderr.
+ virtual bool Init() = 0;
+
+ // Reads a frame from the input file. On success, returns the frame.
+ // Returns nullptr if encountering end of file or a read error.
+ virtual rtc::scoped_refptr<I420Buffer> ReadFrame() = 0;
+
+ // Closes the input file if open. Essentially makes this class impossible
+ // to use anymore. Will also be invoked by the destructor.
+ virtual void Close() = 0;
+
+ // Frame length in bytes of a single frame image.
+ virtual size_t FrameLength() = 0;
+ // Total number of frames in the input video source.
+ virtual int NumberOfFrames() = 0;
+};
+
+class YuvFrameReaderImpl : public FrameReader {
+ public:
+ // Creates a file handler. The input file is assumed to exist and be readable.
+ // Parameters:
+ // input_filename The file to read from.
+ // width, height Size of each frame to read.
+ YuvFrameReaderImpl(std::string input_filename, int width, int height);
+ ~YuvFrameReaderImpl() override;
+ bool Init() override;
+ rtc::scoped_refptr<I420Buffer> ReadFrame() override;
+ void Close() override;
+ size_t FrameLength() override;
+ int NumberOfFrames() override;
+
+ private:
+ const std::string input_filename_;
+ size_t frame_length_in_bytes_;
+ const int width_;
+ const int height_;
+ int number_of_frames_;
+ FILE* input_file_;
+};
+
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_TESTSUPPORT_FRAME_READER_H_
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/frame_writer.h b/third_party/libwebrtc/webrtc/test/testsupport/frame_writer.h
new file mode 100644
index 0000000000..7556050a21
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/frame_writer.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef TEST_TESTSUPPORT_FRAME_WRITER_H_
+#define TEST_TESTSUPPORT_FRAME_WRITER_H_
+
+#include <stdio.h>
+
+#include <string>
+
+#include "api/video/video_frame.h"
+#include "typedefs.h" // NOLINT(build/include)
+
+namespace webrtc {
+namespace test {
+
+// Handles writing of video files.
+class FrameWriter {
+ public:
+ virtual ~FrameWriter() {}
+
+ // Initializes the file handler, i.e. opens the input and output files etc.
+ // This must be called before reading or writing frames has started.
+ // Returns false if an error has occurred, in addition to printing to stderr.
+ virtual bool Init() = 0;
+
+ // Writes a frame of the configured frame length to the output file.
+ // Returns true if the write was successful, false otherwise.
+ virtual bool WriteFrame(uint8_t* frame_buffer) = 0;
+
+ // Closes the output file if open. Essentially makes this class impossible
+ // to use anymore. Will also be invoked by the destructor.
+ virtual void Close() = 0;
+
+ // Frame length in bytes of a single frame image.
+ virtual size_t FrameLength() = 0;
+};
+
+// Writes raw I420 frames in sequence.
+class YuvFrameWriterImpl : public FrameWriter {
+ public:
+ // Creates a file handler. The input file is assumed to exist and be readable
+ // and the output file must be writable.
+ // Parameters:
+ // output_filename The file to write. Will be overwritten if already
+ // existing.
+ // width, height Size of each frame to read.
+ YuvFrameWriterImpl(std::string output_filename, int width, int height);
+ ~YuvFrameWriterImpl() override;
+ bool Init() override;
+ bool WriteFrame(uint8_t* frame_buffer) override;
+ void Close() override;
+ size_t FrameLength() override;
+
+ protected:
+ const std::string output_filename_;
+ size_t frame_length_in_bytes_;
+ const int width_;
+ const int height_;
+ FILE* output_file_;
+};
+
+// Writes raw I420 frames in sequence, but with Y4M file and frame headers for
+// more convenient playback in external media players.
+class Y4mFrameWriterImpl : public YuvFrameWriterImpl {
+ public:
+ Y4mFrameWriterImpl(std::string output_filename,
+ int width,
+ int height,
+ int frame_rate);
+ ~Y4mFrameWriterImpl() override;
+ bool Init() override;
+ bool WriteFrame(uint8_t* frame_buffer) override;
+
+ private:
+ const int frame_rate_;
+};
+
+// LibJpeg is not available on iOS. This class will do nothing on iOS.
+class JpegFrameWriter {
+ public:
+ JpegFrameWriter(const std::string &output_filename);
+ // Quality can be from 0 (worst) to 100 (best). Best quality is still lossy.
+ // WriteFrame can be called only once. Subsequent calls will fail.
+ bool WriteFrame(const VideoFrame& input_frame, int quality);
+
+#if !defined(WEBRTC_IOS)
+ private:
+ bool frame_written_;
+ const std::string output_filename_;
+ FILE* output_file_;
+#endif
+};
+
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_TESTSUPPORT_FRAME_WRITER_H_
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/iosfileutils.mm b/third_party/libwebrtc/webrtc/test/testsupport/iosfileutils.mm
new file mode 100644
index 0000000000..a9156db656
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/iosfileutils.mm
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2015 The WebRTC Project Authors. All rights reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#if defined(WEBRTC_IOS)
+
+#import <Foundation/Foundation.h>
+#include <string.h>
+
+#include "rtc_base/checks.h"
+#include "sdk/objc/Framework/Classes/Common/helpers.h"
+#include "typedefs.h" // NOLINT(build/include)
+
+namespace webrtc {
+namespace test {
+
+using webrtc::ios::NSStringFromStdString;
+using webrtc::ios::StdStringFromNSString;
+
+// For iOS, resource files are added to the application bundle in the root
+// and not in separate folders as is the case for other platforms. This method
+// therefore removes any prepended folders and uses only the actual file name.
+std::string IOSResourcePath(std::string name, std::string extension) {
+ @autoreleasepool {
+ NSString* path = NSStringFromStdString(name);
+ NSString* fileName = path.lastPathComponent;
+ NSString* fileType = NSStringFromStdString(extension);
+ // Get full pathname for the resource identified by the name and extension.
+ NSString* pathString = [[NSBundle mainBundle] pathForResource:fileName
+ ofType:fileType];
+ return StdStringFromNSString(pathString);
+ }
+}
+
+std::string IOSRootPath() {
+ @autoreleasepool {
+ NSBundle* mainBundle = [NSBundle mainBundle];
+ return StdStringFromNSString(mainBundle.bundlePath) + "/";
+ }
+}
+
+// For iOS, we don't have access to the output directory. Return the path to the
+// temporary directory instead. This is mostly used by tests that need to write
+// output files to disk.
+std::string IOSOutputPath() {
+ @autoreleasepool {
+ NSString* tempDir = NSTemporaryDirectory();
+ if (tempDir == nil)
+ tempDir = @"/tmp";
+ return StdStringFromNSString(tempDir);
+ }
+}
+
+} // namespace test
+} // namespace webrtc
+
+#endif // defined(WEBRTC_IOS)
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/jpeg_frame_writer.cc b/third_party/libwebrtc/webrtc/test/testsupport/jpeg_frame_writer.cc
new file mode 100644
index 0000000000..4888f65aeb
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/jpeg_frame_writer.cc
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <stdio.h>
+
+
+#include "common_types.h" // NOLINT(build/include)
+#include "common_video/libyuv/include/webrtc_libyuv.h"
+#include "rtc_base/checks.h"
+#include "rtc_base/logging.h"
+#include "test/testsupport/frame_writer.h"
+
+extern "C" {
+#if defined(USE_SYSTEM_LIBJPEG)
+#include <jpeglib.h>
+#else
+// Include directory supplied by gn
+#include "jpeglib.h" // NOLINT
+#endif
+}
+
+namespace webrtc {
+namespace test {
+
+JpegFrameWriter::JpegFrameWriter(const std::string &output_filename)
+ : frame_written_(false),
+ output_filename_(output_filename),
+ output_file_(nullptr) {}
+
+bool JpegFrameWriter::WriteFrame(const VideoFrame& input_frame, int quality) {
+ if (frame_written_) {
+ RTC_LOG(LS_ERROR) << "Only a single frame can be saved to Jpeg.";
+ return false;
+ }
+ const int kColorPlanes = 3; // R, G and B.
+ size_t rgb_len = input_frame.height() * input_frame.width() * kColorPlanes;
+ std::unique_ptr<uint8_t[]> rgb_buf(new uint8_t[rgb_len]);
+
+ // kRGB24 actually corresponds to FourCC 24BG which is 24-bit BGR.
+ if (ConvertFromI420(input_frame, VideoType::kRGB24, 0, rgb_buf.get()) < 0) {
+ RTC_LOG(LS_ERROR) << "Could not convert input frame to RGB.";
+ return false;
+ }
+ output_file_ = fopen(output_filename_.c_str(), "wb");
+ if (!output_file_) {
+ RTC_LOG(LS_ERROR) << "Couldn't open file to write jpeg frame to:"
+ << output_filename_;
+ return false;
+ }
+
+ // Invoking LIBJPEG
+ struct jpeg_compress_struct cinfo;
+ struct jpeg_error_mgr jerr;
+ JSAMPROW row_pointer[1];
+ cinfo.err = jpeg_std_error(&jerr);
+ jpeg_create_compress(&cinfo);
+
+ jpeg_stdio_dest(&cinfo, output_file_);
+
+ cinfo.image_width = input_frame.width();
+ cinfo.image_height = input_frame.height();
+ cinfo.input_components = kColorPlanes;
+ cinfo.in_color_space = JCS_EXT_BGR;
+ jpeg_set_defaults(&cinfo);
+ jpeg_set_quality(&cinfo, quality, TRUE);
+
+ jpeg_start_compress(&cinfo, TRUE);
+ int row_stride = input_frame.width() * kColorPlanes;
+ while (cinfo.next_scanline < cinfo.image_height) {
+ row_pointer[0] = &rgb_buf.get()[cinfo.next_scanline * row_stride];
+ jpeg_write_scanlines(&cinfo, row_pointer, 1);
+ }
+
+ jpeg_finish_compress(&cinfo);
+ jpeg_destroy_compress(&cinfo);
+ fclose(output_file_);
+
+ frame_written_ = true;
+ return true;
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/jpeg_frame_writer_ios.cc b/third_party/libwebrtc/webrtc/test/testsupport/jpeg_frame_writer_ios.cc
new file mode 100644
index 0000000000..567e75e254
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/jpeg_frame_writer_ios.cc
@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "rtc_base/checks.h"
+#include "rtc_base/logging.h"
+#include "test/testsupport/frame_writer.h"
+
+
+namespace webrtc {
+namespace test {
+
+JpegFrameWriter::JpegFrameWriter(const std::string& /*output_filename*/) {}
+
+bool JpegFrameWriter::WriteFrame(const VideoFrame& /*input_frame*/,
+ int /*quality*/) {
+ RTC_LOG(LS_WARNING)
+ << "Libjpeg isn't available on IOS. Jpeg frame writer is not "
+ "supported. No frame will be saved.";
+ // Don't fail.
+ return true;
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/metrics/video_metrics.cc b/third_party/libwebrtc/webrtc/test/testsupport/metrics/video_metrics.cc
new file mode 100644
index 0000000000..ea5d3f2b5f
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/metrics/video_metrics.cc
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/testsupport/metrics/video_metrics.h"
+
+#include <assert.h>
+#include <stdio.h>
+
+#include <algorithm> // min_element, max_element
+#include <memory>
+
+#include "api/video/i420_buffer.h"
+#include "api/video/video_frame.h"
+#include "common_video/libyuv/include/webrtc_libyuv.h"
+#include "test/frame_utils.h"
+#include "libyuv/convert.h"
+
+namespace webrtc {
+namespace test {
+
+// Copy here so our callers won't need to include libyuv for this constant.
+double kMetricsPerfectPSNR = kPerfectPSNR;
+
+// Used for calculating min and max values.
+static bool LessForFrameResultValue(const FrameResult& s1,
+ const FrameResult& s2) {
+ return s1.value < s2.value;
+}
+
+enum VideoMetricsType { kPSNR, kSSIM, kBoth };
+
+// Calculates metrics for a frame and adds statistics to the result for it.
+void CalculateFrame(VideoMetricsType video_metrics_type,
+ const I420BufferInterface& ref,
+ const I420BufferInterface& test,
+ int frame_number,
+ QualityMetricsResult* result) {
+ FrameResult frame_result = {0, 0};
+ frame_result.frame_number = frame_number;
+ switch (video_metrics_type) {
+ case kPSNR:
+ frame_result.value = I420PSNR(ref, test);
+ break;
+ case kSSIM:
+ frame_result.value = I420SSIM(ref, test);
+ break;
+ default:
+ assert(false);
+ }
+ result->frames.push_back(frame_result);
+}
+
+// Calculates average, min and max values for the supplied struct, if non-NULL.
+void CalculateStats(QualityMetricsResult* result) {
+ if (result == NULL || result->frames.size() == 0) {
+ return;
+ }
+ // Calculate average.
+ std::vector<FrameResult>::iterator iter;
+ double metrics_values_sum = 0.0;
+ for (iter = result->frames.begin(); iter != result->frames.end(); ++iter) {
+ metrics_values_sum += iter->value;
+ }
+ result->average = metrics_values_sum / result->frames.size();
+
+ // Calculate min/max statistics.
+ iter = std::min_element(result->frames.begin(), result->frames.end(),
+ LessForFrameResultValue);
+ result->min = iter->value;
+ result->min_frame_number = iter->frame_number;
+ iter = std::max_element(result->frames.begin(), result->frames.end(),
+ LessForFrameResultValue);
+ result->max = iter->value;
+ result->max_frame_number = iter->frame_number;
+}
+
+// Single method that handles all combinations of video metrics calculation, to
+// minimize code duplication. Either psnr_result or ssim_result may be NULL,
+// depending on which VideoMetricsType is targeted.
+int CalculateMetrics(VideoMetricsType video_metrics_type,
+ const char* ref_filename,
+ const char* test_filename,
+ int width,
+ int height,
+ QualityMetricsResult* psnr_result,
+ QualityMetricsResult* ssim_result) {
+ assert(ref_filename != NULL);
+ assert(test_filename != NULL);
+ assert(width > 0);
+ assert(height > 0);
+
+ FILE* ref_fp = fopen(ref_filename, "rb");
+ if (ref_fp == NULL) {
+ // Cannot open reference file.
+ fprintf(stderr, "Cannot open file %s\n", ref_filename);
+ return -1;
+ }
+ FILE* test_fp = fopen(test_filename, "rb");
+ if (test_fp == NULL) {
+ // Cannot open test file.
+ fprintf(stderr, "Cannot open file %s\n", test_filename);
+ fclose(ref_fp);
+ return -2;
+ }
+ int frame_number = 0;
+
+ // Read reference and test frames.
+ for (;;) {
+ rtc::scoped_refptr<I420Buffer> ref_i420_buffer(
+ test::ReadI420Buffer(width, height, ref_fp));
+ if (!ref_i420_buffer)
+ break;
+
+ rtc::scoped_refptr<I420Buffer> test_i420_buffer(
+ test::ReadI420Buffer(width, height, test_fp));
+
+ if (!test_i420_buffer)
+ break;
+
+ switch (video_metrics_type) {
+ case kPSNR:
+ CalculateFrame(kPSNR, *ref_i420_buffer, *test_i420_buffer, frame_number,
+ psnr_result);
+ break;
+ case kSSIM:
+ CalculateFrame(kSSIM, *ref_i420_buffer, *test_i420_buffer, frame_number,
+ ssim_result);
+ break;
+ case kBoth:
+ CalculateFrame(kPSNR, *ref_i420_buffer, *test_i420_buffer, frame_number,
+ psnr_result);
+ CalculateFrame(kSSIM, *ref_i420_buffer, *test_i420_buffer, frame_number,
+ ssim_result);
+ break;
+ }
+ frame_number++;
+ }
+ int return_code = 0;
+ if (frame_number == 0) {
+ fprintf(stderr, "Tried to measure video metrics from empty files "
+ "(reference file: %s test file: %s)\n", ref_filename,
+ test_filename);
+ return_code = -3;
+ } else {
+ CalculateStats(psnr_result);
+ CalculateStats(ssim_result);
+ }
+ fclose(ref_fp);
+ fclose(test_fp);
+ return return_code;
+}
+
+int I420MetricsFromFiles(const char* ref_filename,
+ const char* test_filename,
+ int width,
+ int height,
+ QualityMetricsResult* psnr_result,
+ QualityMetricsResult* ssim_result) {
+ assert(psnr_result != NULL);
+ assert(ssim_result != NULL);
+ return CalculateMetrics(kBoth, ref_filename, test_filename, width, height,
+ psnr_result, ssim_result);
+}
+
+int I420PSNRFromFiles(const char* ref_filename,
+ const char* test_filename,
+ int width,
+ int height,
+ QualityMetricsResult* result) {
+ assert(result != NULL);
+ return CalculateMetrics(kPSNR, ref_filename, test_filename, width, height,
+ result, NULL);
+}
+
+int I420SSIMFromFiles(const char* ref_filename,
+ const char* test_filename,
+ int width,
+ int height,
+ QualityMetricsResult* result) {
+ assert(result != NULL);
+ return CalculateMetrics(kSSIM, ref_filename, test_filename, width, height,
+ NULL, result);
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/metrics/video_metrics.h b/third_party/libwebrtc/webrtc/test/testsupport/metrics/video_metrics.h
new file mode 100644
index 0000000000..f72ea9b7bb
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/metrics/video_metrics.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef TESTSUPPORT_METRICS_VIDEO_METRICS_H_
+#define TESTSUPPORT_METRICS_VIDEO_METRICS_H_
+
+#include <limits>
+#include <vector>
+
+namespace webrtc {
+namespace test {
+
+// The highest PSNR value our algorithms will return.
+extern double kMetricsPerfectPSNR;
+
+// Contains video quality metrics result for a single frame.
+struct FrameResult {
+ int frame_number;
+ double value;
+};
+
+// Result from a PSNR/SSIM calculation operation.
+// The frames in this data structure are 0-indexed.
+struct QualityMetricsResult {
+ QualityMetricsResult() :
+ average(0.0),
+ min(std::numeric_limits<double>::max()),
+ max(std::numeric_limits<double>::min()),
+ min_frame_number(-1),
+ max_frame_number(-1)
+ {};
+ double average;
+ double min;
+ double max;
+ int min_frame_number;
+ int max_frame_number;
+ std::vector<FrameResult> frames;
+};
+
+// Calculates PSNR and SSIM values for the reference and test video files
+// (must be in I420 format). All calculated values are filled into the
+// QualityMetricsResult structs.
+//
+// PSNR values have the unit decibel (dB) where a high value means the test file
+// is similar to the reference file. The higher value, the more similar. The
+// maximum PSNR value is kMetricsInfinitePSNR. For more info about PSNR, see
+// http://en.wikipedia.org/wiki/PSNR.
+//
+// SSIM values range between -1.0 and 1.0, where 1.0 means the files are
+// identical. For more info about SSIM, see http://en.wikipedia.org/wiki/SSIM
+// This function only compares video frames up to the point when the shortest
+// video ends.
+// Return value:
+// 0 if successful, negative on errors:
+// -1 if the source file cannot be opened
+// -2 if the test file cannot be opened
+// -3 if any of the files are empty
+// -4 if any arguments are invalid.
+int I420MetricsFromFiles(const char* ref_filename,
+ const char* test_filename,
+ int width,
+ int height,
+ QualityMetricsResult* psnr_result,
+ QualityMetricsResult* ssim_result);
+
+// Calculates PSNR values for the reference and test video files (must be in
+// I420 format). All calculated values are filled into the QualityMetricsResult
+// struct.
+//
+// PSNR values have the unit decibel (dB) where a high value means the test file
+// is similar to the reference file. The higher value, the more similar. The
+// maximum PSNR value is kMetricsInfinitePSNR. For more info about PSNR, see
+// http://en.wikipedia.org/wiki/PSNR.
+//
+// This function only compares video frames up to the point when the shortest
+// video ends.
+//
+// Return value:
+// 0 if successful, negative on errors:
+// -1 if the source file cannot be opened
+// -2 if the test file cannot be opened
+// -3 if any of the files are empty
+// -4 if any arguments are invalid.
+int I420PSNRFromFiles(const char* ref_filename,
+ const char* test_filename,
+ int width,
+ int height,
+ QualityMetricsResult* result);
+
+// Calculates SSIM values for the reference and test video files (must be in
+// I420 format). All calculated values are filled into the QualityMetricsResult
+// struct.
+// SSIM values range between -1.0 and 1.0, where 1.0 means the files are
+// identical.
+// This function only compares video frames up to the point when the shortest
+// video ends.
+// For more info about SSIM, see http://en.wikipedia.org/wiki/SSIM
+//
+// Return value:
+// 0 if successful, negative on errors:
+// -1 if the source file cannot be opened
+// -2 if the test file cannot be opened
+// -3 if any of the files are empty
+// -4 if any arguments are invalid.
+int I420SSIMFromFiles(const char* ref_filename,
+ const char* test_filename,
+ int width,
+ int height,
+ QualityMetricsResult* result);
+
+} // namespace test
+} // namespace webrtc
+
+#endif // TESTSUPPORT_METRICS_VIDEO_METRICS_H_
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/metrics/video_metrics_unittest.cc b/third_party/libwebrtc/webrtc/test/testsupport/metrics/video_metrics_unittest.cc
new file mode 100644
index 0000000000..5b00458761
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/metrics/video_metrics_unittest.cc
@@ -0,0 +1,147 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/testsupport/metrics/video_metrics.h"
+
+#include "test/gtest.h"
+#include "test/testsupport/fileutils.h"
+
+namespace webrtc {
+
+static const int kWidth = 352;
+static const int kHeight = 288;
+
+static const int kMissingReferenceFileReturnCode = -1;
+static const int kMissingTestFileReturnCode = -2;
+static const int kEmptyFileReturnCode = -3;
+static const double kPsnrPerfectResult = 48.0;
+static const double kSsimPerfectResult = 1.0;
+
+class VideoMetricsTest: public testing::Test {
+ protected:
+ VideoMetricsTest() {
+ video_file_ = webrtc::test::ResourcePath("foreman_cif_short", "yuv");
+ }
+ virtual ~VideoMetricsTest() {}
+ void SetUp() {
+ non_existing_file_ = webrtc::test::OutputPath() +
+ "video_metrics_unittest_non_existing";
+ remove(non_existing_file_.c_str()); // To be sure it doesn't exist.
+
+ // Create an empty file:
+ empty_file_ = webrtc::test::TempFilename(
+ webrtc::test::OutputPath(), "video_metrics_unittest_empty_file");
+ FILE* dummy = fopen(empty_file_.c_str(), "wb");
+ fclose(dummy);
+ }
+ void TearDown() {
+ remove(empty_file_.c_str());
+ }
+ webrtc::test::QualityMetricsResult psnr_result_;
+ webrtc::test::QualityMetricsResult ssim_result_;
+ std::string non_existing_file_;
+ std::string empty_file_;
+ std::string video_file_;
+};
+
+// Tests that it is possible to run with the same reference as test file
+TEST_F(VideoMetricsTest, ReturnsPerfectResultForIdenticalFilesPSNR) {
+ EXPECT_EQ(0, I420PSNRFromFiles(video_file_.c_str(), video_file_.c_str(),
+ kWidth, kHeight, &psnr_result_));
+ EXPECT_EQ(kPsnrPerfectResult, psnr_result_.average);
+}
+
+TEST_F(VideoMetricsTest, ReturnsPerfectResultForIdenticalFilesSSIM) {
+ EXPECT_EQ(0, I420SSIMFromFiles(video_file_.c_str(), video_file_.c_str(),
+ kWidth, kHeight, &ssim_result_));
+ EXPECT_EQ(kSsimPerfectResult, ssim_result_.average);
+}
+
+TEST_F(VideoMetricsTest, ReturnsPerfectResultForIdenticalFilesBothMetrics) {
+ EXPECT_EQ(0, I420MetricsFromFiles(video_file_.c_str(), video_file_.c_str(),
+ kWidth, kHeight, &psnr_result_,
+ &ssim_result_));
+ EXPECT_EQ(kPsnrPerfectResult, psnr_result_.average);
+ EXPECT_EQ(kSsimPerfectResult, ssim_result_.average);
+}
+
+// Tests that the right return code is given when the reference file is missing.
+TEST_F(VideoMetricsTest, MissingReferenceFilePSNR) {
+ EXPECT_EQ(kMissingReferenceFileReturnCode,
+ I420PSNRFromFiles(non_existing_file_.c_str(),
+ video_file_.c_str(), kWidth, kHeight,
+ &ssim_result_));
+}
+
+TEST_F(VideoMetricsTest, MissingReferenceFileSSIM) {
+ EXPECT_EQ(kMissingReferenceFileReturnCode,
+ I420SSIMFromFiles(non_existing_file_.c_str(),
+ video_file_.c_str(), kWidth, kHeight,
+ &ssim_result_));
+}
+
+TEST_F(VideoMetricsTest, MissingReferenceFileBothMetrics) {
+ EXPECT_EQ(kMissingReferenceFileReturnCode,
+ I420MetricsFromFiles(non_existing_file_.c_str(),
+ video_file_.c_str(), kWidth, kHeight,
+ &psnr_result_, &ssim_result_));
+}
+
+// Tests that the right return code is given when the test file is missing.
+TEST_F(VideoMetricsTest, MissingTestFilePSNR) {
+ EXPECT_EQ(kMissingTestFileReturnCode,
+ I420PSNRFromFiles(video_file_.c_str(), non_existing_file_.c_str(),
+ kWidth, kHeight, &ssim_result_));
+}
+
+TEST_F(VideoMetricsTest, MissingTestFileSSIM) {
+ EXPECT_EQ(kMissingTestFileReturnCode,
+ I420SSIMFromFiles(video_file_.c_str(), non_existing_file_.c_str(),
+ kWidth, kHeight, &ssim_result_));
+}
+
+TEST_F(VideoMetricsTest, MissingTestFileBothMetrics) {
+ EXPECT_EQ(kMissingTestFileReturnCode,
+ I420MetricsFromFiles(video_file_.c_str(),
+ non_existing_file_.c_str(), kWidth, kHeight,
+ &psnr_result_, &ssim_result_));
+}
+
+// Tests that the method can be executed with empty files.
+TEST_F(VideoMetricsTest, EmptyFilesPSNR) {
+ EXPECT_EQ(kEmptyFileReturnCode,
+ I420PSNRFromFiles(empty_file_.c_str(), video_file_.c_str(),
+ kWidth, kHeight, &ssim_result_));
+ EXPECT_EQ(kEmptyFileReturnCode,
+ I420PSNRFromFiles(video_file_.c_str(), empty_file_.c_str(),
+ kWidth, kHeight, &ssim_result_));
+}
+
+TEST_F(VideoMetricsTest, EmptyFilesSSIM) {
+ EXPECT_EQ(kEmptyFileReturnCode,
+ I420SSIMFromFiles(empty_file_.c_str(), video_file_.c_str(),
+ kWidth, kHeight, &ssim_result_));
+ EXPECT_EQ(kEmptyFileReturnCode,
+ I420SSIMFromFiles(video_file_.c_str(), empty_file_.c_str(),
+ kWidth, kHeight, &ssim_result_));
+}
+
+TEST_F(VideoMetricsTest, EmptyFilesBothMetrics) {
+ EXPECT_EQ(kEmptyFileReturnCode,
+ I420MetricsFromFiles(empty_file_.c_str(), video_file_.c_str(),
+ kWidth, kHeight,
+ &psnr_result_, &ssim_result_));
+ EXPECT_EQ(kEmptyFileReturnCode,
+ I420MetricsFromFiles(video_file_.c_str(), empty_file_.c_str(),
+ kWidth, kHeight,
+ &psnr_result_, &ssim_result_));
+}
+
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/mock/mock_frame_reader.h b/third_party/libwebrtc/webrtc/test/testsupport/mock/mock_frame_reader.h
new file mode 100644
index 0000000000..4ba416fedf
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/mock/mock_frame_reader.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef TEST_TESTSUPPORT_MOCK_MOCK_FRAME_READER_H_
+#define TEST_TESTSUPPORT_MOCK_MOCK_FRAME_READER_H_
+
+#include "test/testsupport/frame_reader.h"
+
+#include "test/gmock.h"
+
+namespace webrtc {
+namespace test {
+
+class MockFrameReader : public FrameReader {
+ public:
+ MOCK_METHOD0(Init, bool());
+ MOCK_METHOD0(ReadFrame, rtc::scoped_refptr<I420Buffer>());
+ MOCK_METHOD0(Close, void());
+ MOCK_METHOD0(FrameLength, size_t());
+ MOCK_METHOD0(NumberOfFrames, int());
+};
+
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_TESTSUPPORT_MOCK_MOCK_FRAME_READER_H_
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/packet_reader.cc b/third_party/libwebrtc/webrtc/test/testsupport/packet_reader.cc
new file mode 100644
index 0000000000..ba52f94e57
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/packet_reader.cc
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/testsupport/packet_reader.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <algorithm>
+
+namespace webrtc {
+namespace test {
+
+PacketReader::PacketReader()
+ : initialized_(false) {}
+
+PacketReader::~PacketReader() {}
+
+void PacketReader::InitializeReading(uint8_t* data,
+ size_t data_length_in_bytes,
+ size_t packet_size_in_bytes) {
+ assert(data);
+ assert(packet_size_in_bytes > 0);
+ data_ = data;
+ data_length_ = data_length_in_bytes;
+ packet_size_ = packet_size_in_bytes;
+ currentIndex_ = 0;
+ initialized_ = true;
+}
+
+int PacketReader::NextPacket(uint8_t** packet_pointer) {
+ if (!initialized_) {
+ fprintf(stderr, "Attempting to use uninitialized PacketReader!\n");
+ return -1;
+ }
+ *packet_pointer = data_ + currentIndex_;
+ size_t old_index = currentIndex_;
+ currentIndex_ = std::min(currentIndex_ + packet_size_, data_length_);
+ return static_cast<int>(currentIndex_ - old_index);
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/packet_reader.h b/third_party/libwebrtc/webrtc/test/testsupport/packet_reader.h
new file mode 100644
index 0000000000..dbdb3da9e9
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/packet_reader.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2011 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef TEST_TESTSUPPORT_PACKET_READER_H_
+#define TEST_TESTSUPPORT_PACKET_READER_H_
+
+#include <cstddef>
+#include "typedefs.h" // NOLINT(build/include)
+
+namespace webrtc {
+namespace test {
+
+// Reads chunks of data to simulate network packets from a byte array.
+class PacketReader {
+ public:
+ PacketReader();
+ virtual ~PacketReader();
+
+ // Inizializes a new reading operation. Must be done before invoking the
+ // NextPacket method.
+ // * data_length_in_bytes is the length of the data byte array.
+ // 0 length will result in no packets are read.
+ // * packet_size_in_bytes is the number of bytes to read in each NextPacket
+ // method call. Must be > 0
+ virtual void InitializeReading(uint8_t* data, size_t data_length_in_bytes,
+ size_t packet_size_in_bytes);
+
+ // Moves the supplied pointer to the beginning of the next packet.
+ // Returns:
+ // * The size of the packet ready to read (lower than the packet size for
+ // the last packet)
+ // * 0 if there are no more packets to read
+ // * -1 if InitializeReading has not been called (also prints to stderr).
+ virtual int NextPacket(uint8_t** packet_pointer);
+
+ private:
+ uint8_t* data_;
+ size_t data_length_;
+ size_t packet_size_;
+ size_t currentIndex_;
+ bool initialized_;
+};
+
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_TESTSUPPORT_PACKET_READER_H_
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/packet_reader_unittest.cc b/third_party/libwebrtc/webrtc/test/testsupport/packet_reader_unittest.cc
new file mode 100644
index 0000000000..3255151d05
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/packet_reader_unittest.cc
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/testsupport/packet_reader.h"
+
+#include "test/gtest.h"
+#include "test/testsupport/unittest_utils.h"
+
+namespace webrtc {
+namespace test {
+
+class PacketReaderTest: public PacketRelatedTest {
+ protected:
+ PacketReaderTest() {}
+ virtual ~PacketReaderTest() {}
+ void SetUp() {
+ reader_ = new PacketReader();
+ }
+ void TearDown() {
+ delete reader_;
+ }
+ void VerifyPacketData(size_t expected_length,
+ int actual_length,
+ uint8_t* original_data_pointer,
+ uint8_t* new_data_pointer) {
+ EXPECT_EQ(static_cast<int>(expected_length), actual_length);
+ EXPECT_EQ(*original_data_pointer, *new_data_pointer);
+ EXPECT_EQ(0, memcmp(original_data_pointer, new_data_pointer,
+ actual_length));
+ }
+ PacketReader* reader_;
+};
+
+// Test lack of initialization
+TEST_F(PacketReaderTest, Uninitialized) {
+ uint8_t* data_pointer = NULL;
+ EXPECT_EQ(-1, reader_->NextPacket(&data_pointer));
+ EXPECT_EQ(NULL, data_pointer);
+}
+
+TEST_F(PacketReaderTest, InitializeZeroLengthArgument) {
+ reader_->InitializeReading(packet_data_, 0, kPacketSizeInBytes);
+ ASSERT_EQ(0, reader_->NextPacket(&packet_data_pointer_));
+}
+
+// Test with something smaller than one packet
+TEST_F(PacketReaderTest, NormalSmallData) {
+ const int kDataLengthInBytes = 1499;
+ uint8_t data[kDataLengthInBytes];
+ uint8_t* data_pointer = data;
+ memset(data, 1, kDataLengthInBytes);
+
+ reader_->InitializeReading(data, kDataLengthInBytes, kPacketSizeInBytes);
+ int length_to_read = reader_->NextPacket(&data_pointer);
+ VerifyPacketData(kDataLengthInBytes, length_to_read, data, data_pointer);
+ EXPECT_EQ(0, data_pointer - data); // pointer hasn't moved
+
+ // Reading another one shall result in 0 bytes:
+ length_to_read = reader_->NextPacket(&data_pointer);
+ EXPECT_EQ(0, length_to_read);
+ EXPECT_EQ(kDataLengthInBytes, data_pointer - data);
+}
+
+// Test with data length that exactly matches one packet
+TEST_F(PacketReaderTest, NormalOnePacketData) {
+ uint8_t data[kPacketSizeInBytes];
+ uint8_t* data_pointer = data;
+ memset(data, 1, kPacketSizeInBytes);
+
+ reader_->InitializeReading(data, kPacketSizeInBytes, kPacketSizeInBytes);
+ int length_to_read = reader_->NextPacket(&data_pointer);
+ VerifyPacketData(kPacketSizeInBytes, length_to_read, data, data_pointer);
+ EXPECT_EQ(0, data_pointer - data); // pointer hasn't moved
+
+ // Reading another one shall result in 0 bytes:
+ length_to_read = reader_->NextPacket(&data_pointer);
+ EXPECT_EQ(0, length_to_read);
+ EXPECT_EQ(kPacketSizeInBytes, static_cast<size_t>(data_pointer - data));
+}
+
+// Test with data length that will result in 3 packets
+TEST_F(PacketReaderTest, NormalLargeData) {
+ reader_->InitializeReading(packet_data_, kPacketDataLength,
+ kPacketSizeInBytes);
+
+ int length_to_read = reader_->NextPacket(&packet_data_pointer_);
+ VerifyPacketData(kPacketSizeInBytes, length_to_read,
+ packet1_, packet_data_pointer_);
+
+ length_to_read = reader_->NextPacket(&packet_data_pointer_);
+ VerifyPacketData(kPacketSizeInBytes, length_to_read,
+ packet2_, packet_data_pointer_);
+
+ length_to_read = reader_->NextPacket(&packet_data_pointer_);
+ VerifyPacketData(1u, length_to_read,
+ packet3_, packet_data_pointer_);
+
+ // Reading another one shall result in 0 bytes:
+ length_to_read = reader_->NextPacket(&packet_data_pointer_);
+ EXPECT_EQ(0, length_to_read);
+ EXPECT_EQ(kPacketDataLength,
+ static_cast<size_t>(packet_data_pointer_ - packet_data_));
+}
+
+// Test with empty data.
+TEST_F(PacketReaderTest, EmptyData) {
+ const int kDataLengthInBytes = 0;
+ // But don't really try to allocate a zero-length array...
+ uint8_t data[kPacketSizeInBytes];
+ uint8_t* data_pointer = data;
+ reader_->InitializeReading(data, kDataLengthInBytes, kPacketSizeInBytes);
+ EXPECT_EQ(kDataLengthInBytes, reader_->NextPacket(&data_pointer));
+ // Do it again to make sure nothing changes
+ EXPECT_EQ(kDataLengthInBytes, reader_->NextPacket(&data_pointer));
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/perf_test.cc b/third_party/libwebrtc/webrtc/test/testsupport/perf_test.cc
new file mode 100644
index 0000000000..b7578d101e
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/perf_test.cc
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+// A stripped-down version of Chromium's chrome/test/perf/perf_test.cc.
+// ResultsToString(), PrintResult(size_t value) and AppendResult(size_t value)
+// have been modified. The remainder are identical to the Chromium version.
+
+#include "test/testsupport/perf_test.h"
+
+#include <sstream>
+#include <stdio.h>
+#include <vector>
+
+namespace {
+
+void PrintResultsImpl(const std::string& graph_name,
+ const std::string& trace,
+ const std::string& values,
+ const std::string& units,
+ bool important) {
+ // <*>RESULT <graph_name>: <trace_name>= <value> <units>
+ // <*>RESULT <graph_name>: <trace_name>= {<mean>, <std deviation>} <units>
+ // <*>RESULT <graph_name>: <trace_name>= [<value>,value,value,...,] <units>
+
+ if (important) {
+ printf("*");
+ }
+ printf("RESULT %s: %s= %s %s\n", graph_name.c_str(), trace.c_str(),
+ values.c_str(), units.c_str());
+}
+
+} // namespace
+
+namespace webrtc {
+namespace test {
+
+void PrintResult(const std::string& measurement,
+ const std::string& modifier,
+ const std::string& trace,
+ const double value,
+ const std::string& units,
+ bool important) {
+ std::ostringstream value_stream;
+ value_stream << value;
+ PrintResultsImpl(measurement + modifier, trace, value_stream.str(), units,
+ important);
+}
+
+void PrintResultMeanAndError(const std::string& measurement,
+ const std::string& modifier,
+ const std::string& trace,
+ const double mean,
+ const double error,
+ const std::string& units,
+ bool important) {
+ std::ostringstream value_stream;
+ value_stream << '{' << mean << ',' << error << '}';
+ PrintResultsImpl(measurement + modifier, trace, value_stream.str(), units,
+ important);
+}
+
+void PrintResultList(const std::string& measurement,
+ const std::string& modifier,
+ const std::string& trace,
+ const std::vector<double>& values,
+ const std::string& units,
+ bool important) {
+ std::ostringstream value_stream;
+ value_stream << '[';
+ if (!values.empty()) {
+ auto it = values.begin();
+ while (true) {
+ value_stream << *it;
+ if (++it == values.end())
+ break;
+ value_stream << ',';
+ }
+ }
+ value_stream << ']';
+ PrintResultsImpl(measurement + modifier, trace, value_stream.str(), units,
+ important);
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/perf_test.h b/third_party/libwebrtc/webrtc/test/testsupport/perf_test.h
new file mode 100644
index 0000000000..31b7b1345c
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/perf_test.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+// A stripped-down version of Chromium's chrome/test/perf/perf_test.h.
+// Several functions have been removed; the prototypes of the remainder have
+// not been changed.
+
+#ifndef TEST_TESTSUPPORT_PERF_TEST_H_
+#define TEST_TESTSUPPORT_PERF_TEST_H_
+
+#include <sstream>
+#include <string>
+#include <vector>
+
+namespace webrtc {
+namespace test {
+
+// Prints numerical information to stdout in a controlled format, for
+// post-processing. |measurement| is a description of the quantity being
+// measured, e.g. "vm_peak"; |modifier| is provided as a convenience and
+// will be appended directly to the name of the |measurement|, e.g.
+// "_browser"; |trace| is a description of the particular data point, e.g.
+// "reference"; |value| is the measured value; and |units| is a description
+// of the units of measure, e.g. "bytes". If |important| is true, the output
+// line will be specially marked, to notify the post-processor. The strings
+// may be empty. They should not contain any colons (:) or equals signs (=).
+// A typical post-processing step would be to produce graphs of the data
+// produced for various builds, using the combined |measurement| + |modifier|
+// string to specify a particular graph and the |trace| to identify a trace
+// (i.e., data series) on that graph.
+void PrintResult(const std::string& measurement,
+ const std::string& modifier,
+ const std::string& trace,
+ const double value,
+ const std::string& units,
+ bool important);
+
+// Like PrintResult(), but prints a (mean, standard deviation) result pair.
+// The |<values>| should be two comma-separated numbers, the mean and
+// standard deviation (or other error metric) of the measurement.
+void PrintResultMeanAndError(const std::string& measurement,
+ const std::string& modifier,
+ const std::string& trace,
+ const double mean,
+ const double error,
+ const std::string& units,
+ bool important);
+
+
+// Like PrintResult(), but prints an entire list of results. The |values|
+// will generally be a list of comma-separated numbers. A typical
+// post-processing step might produce plots of their mean and standard
+// deviation.
+void PrintResultList(const std::string& measurement,
+ const std::string& modifier,
+ const std::string& trace,
+ const std::vector<double>& values,
+ const std::string& units,
+ bool important);
+
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_TESTSUPPORT_PERF_TEST_H_
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/perf_test_unittest.cc b/third_party/libwebrtc/webrtc/test/testsupport/perf_test_unittest.cc
new file mode 100644
index 0000000000..466e2b3e69
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/perf_test_unittest.cc
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/testsupport/perf_test.h"
+
+#include <string>
+
+#include "test/gtest.h"
+
+namespace webrtc {
+namespace test {
+
+TEST(PerfTest, AppendResult) {
+ testing::internal::CaptureStdout();
+ std::string expected = "RESULT measurementmodifier: trace= 42 units\n";
+ PrintResult("measurement", "modifier", "trace", 42, "units", false);
+
+ expected += "*RESULT foobar: baz= 7 widgets\n";
+ PrintResult("foo", "bar", "baz", 7, "widgets", true);
+
+ expected += "RESULT foobar: baz= {1,2} lemurs\n";
+ PrintResultMeanAndError("foo", "bar", "baz", 1, 2, "lemurs", false);
+
+ expected += "RESULT foobar: baz= [1,2,3] units\n";
+ PrintResultList("foo", "bar", "baz", {1, 2, 3}, "units", false);
+
+ std::string output = testing::internal::GetCapturedStdout();
+ EXPECT_EQ(expected, output);
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/test_artifacts.cc b/third_party/libwebrtc/webrtc/test/testsupport/test_artifacts.cc
new file mode 100644
index 0000000000..3d97a94472
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/test_artifacts.cc
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/testsupport/test_artifacts.h"
+
+#include <string.h>
+
+#include "rtc_base/file.h"
+#include "rtc_base/flags.h"
+#include "rtc_base/logging.h"
+#include "rtc_base/pathutils.h"
+#include "test/testsupport/fileutils.h"
+
+namespace {
+const std::string& DefaultArtifactPath() {
+ static const std::string path = webrtc::test::OutputPath();
+ return path;
+}
+}
+
+DEFINE_string(test_artifacts_dir,
+ DefaultArtifactPath().c_str(),
+ "The output folder where test output should be saved.");
+
+namespace webrtc {
+namespace test {
+
+bool GetTestArtifactsDir(std::string* out_dir) {
+ if (strlen(FLAG_test_artifacts_dir) == 0) {
+ RTC_LOG(LS_WARNING) << "No test_out_dir defined.";
+ return false;
+ }
+ *out_dir = FLAG_test_artifacts_dir;
+ return true;
+}
+
+bool WriteToTestArtifactsDir(const char* filename,
+ const uint8_t* buffer,
+ size_t length) {
+ if (strlen(FLAG_test_artifacts_dir) == 0) {
+ RTC_LOG(LS_WARNING) << "No test_out_dir defined.";
+ return false;
+ }
+
+ if (filename == nullptr || strlen(filename) == 0) {
+ RTC_LOG(LS_WARNING) << "filename must be provided.";
+ return false;
+ }
+
+ rtc::File output =
+ rtc::File::Create(rtc::Pathname(FLAG_test_artifacts_dir, filename));
+
+ return output.IsOpen() && output.Write(buffer, length) == length;
+}
+
+bool WriteToTestArtifactsDir(const char* filename, const std::string& content) {
+ return WriteToTestArtifactsDir(
+ filename, reinterpret_cast<const uint8_t*>(content.c_str()),
+ content.length());
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/test_artifacts.h b/third_party/libwebrtc/webrtc/test/testsupport/test_artifacts.h
new file mode 100644
index 0000000000..ee07a9be52
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/test_artifacts.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef TEST_TESTSUPPORT_TEST_ARTIFACTS_H_
+#define TEST_TESTSUPPORT_TEST_ARTIFACTS_H_
+
+#include <stdlib.h>
+
+#include <string>
+
+namespace webrtc {
+namespace test {
+
+// If the test_artifacts_dir flag is set, returns true and copies the location
+// of the dir to |out_dir|. Otherwise, return false.
+bool GetTestArtifactsDir(std::string* out_dir);
+
+// Writes a |length| bytes array |buffer| to |filename| in isolated output
+// directory defined by swarming. If the file is existing, content will be
+// appended. Otherwise a new file will be created. This function returns false
+// if isolated output directory has not been defined, or |filename| indicates an
+// invalid or non-writable file, or underlying file system errors.
+bool WriteToTestArtifactsDir(const char* filename,
+ const uint8_t* buffer,
+ size_t length);
+
+bool WriteToTestArtifactsDir(const char* filename, const std::string& content);
+
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_TESTSUPPORT_TEST_ARTIFACTS_H_
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/test_artifacts_unittest.cc b/third_party/libwebrtc/webrtc/test/testsupport/test_artifacts_unittest.cc
new file mode 100644
index 0000000000..251c5cde88
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/test_artifacts_unittest.cc
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/testsupport/test_artifacts.h"
+
+#include <string.h>
+
+#include <string>
+
+#include "rtc_base/file.h"
+#include "rtc_base/flags.h"
+#include "rtc_base/pathutils.h"
+#include "rtc_base/platform_file.h"
+#include "test/gtest.h"
+
+DECLARE_string(test_artifacts_dir);
+
+namespace webrtc {
+namespace test {
+
+TEST(IsolatedOutputTest, ShouldRejectInvalidIsolatedOutDir) {
+ const char* backup = FLAG_test_artifacts_dir;
+ FLAG_test_artifacts_dir = "";
+ ASSERT_FALSE(WriteToTestArtifactsDir("a-file", "some-contents"));
+ FLAG_test_artifacts_dir = backup;
+}
+
+TEST(IsolatedOutputTest, ShouldRejectInvalidFileName) {
+ ASSERT_FALSE(WriteToTestArtifactsDir(nullptr, "some-contents"));
+ ASSERT_FALSE(WriteToTestArtifactsDir("", "some-contents"));
+}
+
+// Sets isolated_out_dir=<a-writable-path> to execute this test.
+TEST(IsolatedOutputTest, ShouldBeAbleToWriteContent) {
+ const char* filename = "a-file";
+ const char* content = "some-contents";
+ if (WriteToTestArtifactsDir(filename, content)) {
+ rtc::Pathname out_file(FLAG_test_artifacts_dir, filename);
+ rtc::File input = rtc::File::Open(out_file);
+ EXPECT_TRUE(input.IsOpen());
+ EXPECT_TRUE(input.Seek(0));
+ uint8_t buffer[32];
+ EXPECT_EQ(input.Read(buffer, strlen(content)), strlen(content));
+ buffer[strlen(content)] = 0;
+ EXPECT_EQ(std::string(content),
+ std::string(reinterpret_cast<char*>(buffer)));
+ input.Close();
+
+ EXPECT_TRUE(rtc::File::Remove(out_file));
+ }
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/unittest_utils.h b/third_party/libwebrtc/webrtc/test/testsupport/unittest_utils.h
new file mode 100644
index 0000000000..5fee2ca454
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/unittest_utils.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef TEST_TESTSUPPORT_UNITTEST_UTILS_H_
+#define TEST_TESTSUPPORT_UNITTEST_UTILS_H_
+
+namespace webrtc {
+namespace test {
+
+const size_t kPacketSizeInBytes = 1500;
+const size_t kPacketDataLength = kPacketSizeInBytes * 2 + 1;
+const int kPacketDataNumberOfPackets = 3;
+
+// A base test fixture for packet related tests. Contains
+// two full prepared packets with 1s, 2s in their data and a third packet with
+// a single 3 in it (size=1).
+// A packet data structure is also available, that contains these three packets
+// in order.
+class PacketRelatedTest: public testing::Test {
+ protected:
+ // Tree packet byte arrays with data used for verification:
+ uint8_t packet1_[kPacketSizeInBytes];
+ uint8_t packet2_[kPacketSizeInBytes];
+ uint8_t packet3_[1];
+ // Construct a data structure containing these packets
+ uint8_t packet_data_[kPacketDataLength];
+ uint8_t* packet_data_pointer_;
+
+ PacketRelatedTest() {
+ packet_data_pointer_ = packet_data_;
+
+ memset(packet1_, 1, kPacketSizeInBytes);
+ memset(packet2_, 2, kPacketSizeInBytes);
+ memset(packet3_, 3, 1);
+ // Fill the packet_data:
+ memcpy(packet_data_pointer_, packet1_, kPacketSizeInBytes);
+ memcpy(packet_data_pointer_ + kPacketSizeInBytes, packet2_,
+ kPacketSizeInBytes);
+ memcpy(packet_data_pointer_ + kPacketSizeInBytes * 2, packet3_, 1);
+ }
+ virtual ~PacketRelatedTest() {}
+ void SetUp() {}
+ void TearDown() {}
+};
+
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_TESTSUPPORT_UNITTEST_UTILS_H_
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/y4m_frame_writer.cc b/third_party/libwebrtc/webrtc/test/testsupport/y4m_frame_writer.cc
new file mode 100644
index 0000000000..e0c1ed54ba
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/y4m_frame_writer.cc
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "rtc_base/checks.h"
+#include "test/testsupport/frame_writer.h"
+
+namespace webrtc {
+namespace test {
+
+Y4mFrameWriterImpl::Y4mFrameWriterImpl(std::string output_filename,
+ int width,
+ int height,
+ int frame_rate)
+ : YuvFrameWriterImpl(output_filename, width, height),
+ frame_rate_(frame_rate) {}
+
+Y4mFrameWriterImpl::~Y4mFrameWriterImpl() = default;
+
+bool Y4mFrameWriterImpl::Init() {
+ if (!YuvFrameWriterImpl::Init()) {
+ return false;
+ }
+ int bytes_written = fprintf(output_file_, "YUV4MPEG2 W%d H%d F%d:1 C420\n",
+ width_, height_, frame_rate_);
+ if (bytes_written < 0) {
+ fprintf(stderr, "Failed to write Y4M file header to file %s\n",
+ output_filename_.c_str());
+ return false;
+ }
+ return true;
+}
+
+bool Y4mFrameWriterImpl::WriteFrame(uint8_t* frame_buffer) {
+ if (output_file_ == nullptr) {
+ fprintf(stderr,
+ "Y4mFrameWriterImpl is not initialized (output file is NULL)\n");
+ return false;
+ }
+ int bytes_written = fprintf(output_file_, "FRAME\n");
+ if (bytes_written < 0) {
+ fprintf(stderr, "Failed to write Y4M frame header to file %s\n",
+ output_filename_.c_str());
+ return false;
+ }
+ return YuvFrameWriterImpl::WriteFrame(frame_buffer);
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/y4m_frame_writer_unittest.cc b/third_party/libwebrtc/webrtc/test/testsupport/y4m_frame_writer_unittest.cc
new file mode 100644
index 0000000000..d9ec09a2b7
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/y4m_frame_writer_unittest.cc
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <memory>
+#include <string>
+
+#include "test/gtest.h"
+#include "test/testsupport/fileutils.h"
+#include "test/testsupport/frame_writer.h"
+
+namespace webrtc {
+namespace test {
+
+namespace {
+const size_t kFrameWidth = 50;
+const size_t kFrameHeight = 20;
+const size_t kFrameLength = 3 * kFrameWidth * kFrameHeight / 2; // I420.
+const size_t kFrameRate = 30;
+
+const std::string kFileHeader = "YUV4MPEG2 W50 H20 F30:1 C420\n";
+const std::string kFrameHeader = "FRAME\n";
+} // namespace
+
+class Y4mFrameWriterTest : public testing::Test {
+ protected:
+ Y4mFrameWriterTest() = default;
+ ~Y4mFrameWriterTest() override = default;
+
+ void SetUp() override {
+ temp_filename_ = webrtc::test::TempFilename(webrtc::test::OutputPath(),
+ "y4m_frame_writer_unittest");
+ frame_writer_.reset(new Y4mFrameWriterImpl(temp_filename_, kFrameWidth,
+ kFrameHeight, kFrameRate));
+ ASSERT_TRUE(frame_writer_->Init());
+ }
+
+ void TearDown() override { remove(temp_filename_.c_str()); }
+
+ std::unique_ptr<FrameWriter> frame_writer_;
+ std::string temp_filename_;
+};
+
+TEST_F(Y4mFrameWriterTest, InitSuccess) {}
+
+TEST_F(Y4mFrameWriterTest, FrameLength) {
+ EXPECT_EQ(kFrameLength, frame_writer_->FrameLength());
+}
+
+TEST_F(Y4mFrameWriterTest, WriteFrame) {
+ uint8_t buffer[kFrameLength];
+ memset(buffer, 9, kFrameLength); // Write lots of 9s to the buffer.
+ bool result = frame_writer_->WriteFrame(buffer);
+ ASSERT_TRUE(result);
+ result = frame_writer_->WriteFrame(buffer);
+ ASSERT_TRUE(result);
+
+ frame_writer_->Close();
+ EXPECT_EQ(kFileHeader.size() + 2 * kFrameHeader.size() + 2 * kFrameLength,
+ GetFileSize(temp_filename_));
+}
+
+TEST_F(Y4mFrameWriterTest, WriteFrameUninitialized) {
+ uint8_t buffer[kFrameLength];
+ Y4mFrameWriterImpl frame_writer(temp_filename_, kFrameWidth, kFrameHeight,
+ kFrameRate);
+ EXPECT_FALSE(frame_writer.WriteFrame(buffer));
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/yuv_frame_reader.cc b/third_party/libwebrtc/webrtc/test/testsupport/yuv_frame_reader.cc
new file mode 100644
index 0000000000..60f9994b14
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/yuv_frame_reader.cc
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/testsupport/frame_reader.h"
+
+#include "api/video/i420_buffer.h"
+#include "test/frame_utils.h"
+#include "test/testsupport/fileutils.h"
+
+namespace webrtc {
+namespace test {
+
+YuvFrameReaderImpl::YuvFrameReaderImpl(std::string input_filename,
+ int width,
+ int height)
+ : input_filename_(input_filename),
+ frame_length_in_bytes_(0),
+ width_(width),
+ height_(height),
+ number_of_frames_(-1),
+ input_file_(nullptr) {}
+
+YuvFrameReaderImpl::~YuvFrameReaderImpl() {
+ Close();
+}
+
+bool YuvFrameReaderImpl::Init() {
+ if (width_ <= 0 || height_ <= 0) {
+ fprintf(stderr, "Frame width and height must be >0, was %d x %d\n", width_,
+ height_);
+ return false;
+ }
+ frame_length_in_bytes_ =
+ width_ * height_ + 2 * ((width_ + 1) / 2) * ((height_ + 1) / 2);
+
+ input_file_ = fopen(input_filename_.c_str(), "rb");
+ if (input_file_ == nullptr) {
+ fprintf(stderr, "Couldn't open input file for reading: %s\n",
+ input_filename_.c_str());
+ return false;
+ }
+ // Calculate total number of frames.
+ size_t source_file_size = GetFileSize(input_filename_);
+ if (source_file_size <= 0u) {
+ fprintf(stderr, "Found empty file: %s\n", input_filename_.c_str());
+ return false;
+ }
+ number_of_frames_ =
+ static_cast<int>(source_file_size / frame_length_in_bytes_);
+ return true;
+}
+
+rtc::scoped_refptr<I420Buffer> YuvFrameReaderImpl::ReadFrame() {
+ if (input_file_ == nullptr) {
+ fprintf(stderr,
+ "YuvFrameReaderImpl is not initialized (input file is NULL)\n");
+ return nullptr;
+ }
+ rtc::scoped_refptr<I420Buffer> buffer(
+ ReadI420Buffer(width_, height_, input_file_));
+ if (!buffer && ferror(input_file_)) {
+ fprintf(stderr, "Error reading from input file: %s\n",
+ input_filename_.c_str());
+ }
+ return buffer;
+}
+
+void YuvFrameReaderImpl::Close() {
+ if (input_file_ != nullptr) {
+ fclose(input_file_);
+ input_file_ = nullptr;
+ }
+}
+
+size_t YuvFrameReaderImpl::FrameLength() {
+ return frame_length_in_bytes_;
+}
+
+int YuvFrameReaderImpl::NumberOfFrames() {
+ return number_of_frames_;
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/yuv_frame_reader_unittest.cc b/third_party/libwebrtc/webrtc/test/testsupport/yuv_frame_reader_unittest.cc
new file mode 100644
index 0000000000..dd4b980c71
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/yuv_frame_reader_unittest.cc
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <memory>
+#include <string>
+
+#include "api/video/i420_buffer.h"
+#include "test/gtest.h"
+#include "test/testsupport/fileutils.h"
+#include "test/testsupport/frame_reader.h"
+
+namespace webrtc {
+namespace test {
+
+namespace {
+const std::string kInputFileContents = "bazouk";
+
+const size_t kFrameWidth = 2;
+const size_t kFrameHeight = 2;
+const size_t kFrameLength = 3 * kFrameWidth * kFrameHeight / 2; // I420.
+} // namespace
+
+class YuvFrameReaderTest : public testing::Test {
+ protected:
+ YuvFrameReaderTest() = default;
+ ~YuvFrameReaderTest() override = default;
+
+ void SetUp() override {
+ temp_filename_ = webrtc::test::TempFilename(webrtc::test::OutputPath(),
+ "yuv_frame_reader_unittest");
+ FILE* dummy = fopen(temp_filename_.c_str(), "wb");
+ fprintf(dummy, "%s", kInputFileContents.c_str());
+ fclose(dummy);
+
+ frame_reader_.reset(
+ new YuvFrameReaderImpl(temp_filename_, kFrameWidth, kFrameHeight));
+ ASSERT_TRUE(frame_reader_->Init());
+ }
+
+ void TearDown() override { remove(temp_filename_.c_str()); }
+
+ std::unique_ptr<FrameReader> frame_reader_;
+ std::string temp_filename_;
+};
+
+TEST_F(YuvFrameReaderTest, InitSuccess) {}
+
+TEST_F(YuvFrameReaderTest, FrameLength) {
+ EXPECT_EQ(kFrameLength, frame_reader_->FrameLength());
+}
+
+TEST_F(YuvFrameReaderTest, NumberOfFrames) {
+ EXPECT_EQ(1, frame_reader_->NumberOfFrames());
+}
+
+TEST_F(YuvFrameReaderTest, ReadFrame) {
+ rtc::scoped_refptr<I420BufferInterface> buffer = frame_reader_->ReadFrame();
+ ASSERT_TRUE(buffer);
+ // Expect I420 packed as YUV.
+ EXPECT_EQ(kInputFileContents[0], buffer->DataY()[0]);
+ EXPECT_EQ(kInputFileContents[1], buffer->DataY()[1]);
+ EXPECT_EQ(kInputFileContents[2], buffer->DataY()[2]);
+ EXPECT_EQ(kInputFileContents[3], buffer->DataY()[3]);
+ EXPECT_EQ(kInputFileContents[4], buffer->DataU()[0]);
+ EXPECT_EQ(kInputFileContents[5], buffer->DataV()[0]);
+ EXPECT_FALSE(frame_reader_->ReadFrame()); // End of file.
+}
+
+TEST_F(YuvFrameReaderTest, ReadFrameUninitialized) {
+ YuvFrameReaderImpl file_reader(temp_filename_, kFrameWidth, kFrameHeight);
+ EXPECT_FALSE(file_reader.ReadFrame());
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/yuv_frame_writer.cc b/third_party/libwebrtc/webrtc/test/testsupport/yuv_frame_writer.cc
new file mode 100644
index 0000000000..1bd343c513
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/yuv_frame_writer.cc
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "rtc_base/checks.h"
+#include "test/testsupport/frame_writer.h"
+
+namespace webrtc {
+namespace test {
+
+YuvFrameWriterImpl::YuvFrameWriterImpl(std::string output_filename,
+ int width,
+ int height)
+ : output_filename_(output_filename),
+ frame_length_in_bytes_(0),
+ width_(width),
+ height_(height),
+ output_file_(nullptr) {}
+
+YuvFrameWriterImpl::~YuvFrameWriterImpl() {
+ Close();
+}
+
+bool YuvFrameWriterImpl::Init() {
+ if (width_ <= 0 || height_ <= 0) {
+ fprintf(stderr, "Frame width and height must be >0, was %d x %d\n", width_,
+ height_);
+ return false;
+ }
+ frame_length_in_bytes_ =
+ width_ * height_ + 2 * ((width_ + 1) / 2) * ((height_ + 1) / 2);
+
+ output_file_ = fopen(output_filename_.c_str(), "wb");
+ if (output_file_ == nullptr) {
+ fprintf(stderr, "Couldn't open output file for writing: %s\n",
+ output_filename_.c_str());
+ return false;
+ }
+ return true;
+}
+
+bool YuvFrameWriterImpl::WriteFrame(uint8_t* frame_buffer) {
+ RTC_DCHECK(frame_buffer);
+ if (output_file_ == nullptr) {
+ fprintf(stderr,
+ "YuvFrameWriterImpl is not initialized (output file is NULL)\n");
+ return false;
+ }
+ size_t bytes_written =
+ fwrite(frame_buffer, 1, frame_length_in_bytes_, output_file_);
+ if (bytes_written != frame_length_in_bytes_) {
+ fprintf(stderr, "Failed to write %zu bytes to file %s\n",
+ frame_length_in_bytes_, output_filename_.c_str());
+ return false;
+ }
+ return true;
+}
+
+void YuvFrameWriterImpl::Close() {
+ if (output_file_ != nullptr) {
+ fclose(output_file_);
+ output_file_ = nullptr;
+ }
+}
+
+size_t YuvFrameWriterImpl::FrameLength() {
+ return frame_length_in_bytes_;
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/testsupport/yuv_frame_writer_unittest.cc b/third_party/libwebrtc/webrtc/test/testsupport/yuv_frame_writer_unittest.cc
new file mode 100644
index 0000000000..49b595e1da
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/testsupport/yuv_frame_writer_unittest.cc
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include <memory>
+
+#include "test/gtest.h"
+#include "test/testsupport/fileutils.h"
+#include "test/testsupport/frame_writer.h"
+
+namespace webrtc {
+namespace test {
+
+namespace {
+const size_t kFrameWidth = 50;
+const size_t kFrameHeight = 20;
+const size_t kFrameLength = 3 * kFrameWidth * kFrameHeight / 2; // I420.
+} // namespace
+
+class YuvFrameWriterTest : public testing::Test {
+ protected:
+ YuvFrameWriterTest() = default;
+ ~YuvFrameWriterTest() override = default;
+
+ void SetUp() override {
+ temp_filename_ = webrtc::test::TempFilename(webrtc::test::OutputPath(),
+ "yuv_frame_writer_unittest");
+ frame_writer_.reset(
+ new YuvFrameWriterImpl(temp_filename_, kFrameWidth, kFrameHeight));
+ ASSERT_TRUE(frame_writer_->Init());
+ }
+
+ void TearDown() override { remove(temp_filename_.c_str()); }
+
+ std::unique_ptr<FrameWriter> frame_writer_;
+ std::string temp_filename_;
+};
+
+TEST_F(YuvFrameWriterTest, InitSuccess) {}
+
+TEST_F(YuvFrameWriterTest, FrameLength) {
+ EXPECT_EQ(kFrameLength, frame_writer_->FrameLength());
+}
+
+TEST_F(YuvFrameWriterTest, WriteFrame) {
+ uint8_t buffer[kFrameLength];
+ memset(buffer, 9, kFrameLength); // Write lots of 9s to the buffer.
+ bool result = frame_writer_->WriteFrame(buffer);
+ ASSERT_TRUE(result);
+
+ frame_writer_->Close();
+ EXPECT_EQ(kFrameLength, GetFileSize(temp_filename_));
+}
+
+TEST_F(YuvFrameWriterTest, WriteFrameUninitialized) {
+ uint8_t buffer[kFrameLength];
+ YuvFrameWriterImpl frame_writer(temp_filename_, kFrameWidth, kFrameHeight);
+ EXPECT_FALSE(frame_writer.WriteFrame(buffer));
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/vcm_capturer.cc b/third_party/libwebrtc/webrtc/test/vcm_capturer.cc
new file mode 100644
index 0000000000..aba0263ca7
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/vcm_capturer.cc
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/vcm_capturer.h"
+
+#include "modules/video_capture/video_capture_factory.h"
+#include "rtc_base/logging.h"
+#include "call/video_send_stream.h"
+namespace webrtc {
+namespace test {
+
+VcmCapturer::VcmCapturer() : started_(false), sink_(nullptr), vcm_(nullptr) {}
+
+bool VcmCapturer::Init(size_t width,
+ size_t height,
+ size_t target_fps,
+ size_t capture_device_index) {
+ std::unique_ptr<VideoCaptureModule::DeviceInfo> device_info(
+ VideoCaptureFactory::CreateDeviceInfo());
+
+ char device_name[256];
+ char unique_name[256];
+ if (device_info->GetDeviceName(static_cast<uint32_t>(capture_device_index),
+ device_name, sizeof(device_name), unique_name,
+ sizeof(unique_name)) != 0) {
+ Destroy();
+ return false;
+ }
+
+ vcm_ = webrtc::VideoCaptureFactory::Create(unique_name);
+ vcm_->RegisterCaptureDataCallback(this);
+
+ device_info->GetCapability(vcm_->CurrentDeviceName(), 0, capability_);
+
+ capability_.width = static_cast<int32_t>(width);
+ capability_.height = static_cast<int32_t>(height);
+ capability_.maxFPS = static_cast<int32_t>(target_fps);
+ capability_.videoType = VideoType::kI420;
+
+ if (vcm_->StartCapture(capability_) != 0) {
+ Destroy();
+ return false;
+ }
+
+ RTC_CHECK(vcm_->CaptureStarted());
+
+ return true;
+}
+
+VcmCapturer* VcmCapturer::Create(size_t width,
+ size_t height,
+ size_t target_fps,
+ size_t capture_device_index) {
+ std::unique_ptr<VcmCapturer> vcm_capturer(new VcmCapturer());
+ if (!vcm_capturer->Init(width, height, target_fps, capture_device_index)) {
+ RTC_LOG(LS_WARNING) << "Failed to create VcmCapturer(w = " << width
+ << ", h = " << height << ", fps = " << target_fps
+ << ")";
+ return nullptr;
+ }
+ return vcm_capturer.release();
+}
+
+
+void VcmCapturer::Start() {
+ rtc::CritScope lock(&crit_);
+ started_ = true;
+}
+
+void VcmCapturer::Stop() {
+ rtc::CritScope lock(&crit_);
+ started_ = false;
+}
+
+void VcmCapturer::AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink,
+ const rtc::VideoSinkWants& wants) {
+ rtc::CritScope lock(&crit_);
+ RTC_CHECK(!sink_ || sink_ == sink);
+ sink_ = sink;
+ VideoCapturer::AddOrUpdateSink(sink, wants);
+}
+
+void VcmCapturer::RemoveSink(rtc::VideoSinkInterface<VideoFrame>* sink) {
+ rtc::CritScope lock(&crit_);
+ RTC_CHECK(sink_ == sink);
+ sink_ = nullptr;
+}
+
+void VcmCapturer::Destroy() {
+ if (!vcm_)
+ return;
+
+ vcm_->StopCapture();
+ vcm_->DeRegisterCaptureDataCallback(this);
+ // Release reference to VCM.
+ vcm_ = nullptr;
+}
+
+VcmCapturer::~VcmCapturer() { Destroy(); }
+
+void VcmCapturer::OnFrame(const VideoFrame& frame) {
+ rtc::CritScope lock(&crit_);
+ if (started_ && sink_) {
+ rtc::Optional<VideoFrame> out_frame = AdaptFrame(frame);
+ if (out_frame)
+ sink_->OnFrame(*out_frame);
+ }
+}
+
+} // test
+} // webrtc
diff --git a/third_party/libwebrtc/webrtc/test/vcm_capturer.h b/third_party/libwebrtc/webrtc/test/vcm_capturer.h
new file mode 100644
index 0000000000..9d158c3fcd
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/vcm_capturer.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef TEST_VCM_CAPTURER_H_
+#define TEST_VCM_CAPTURER_H_
+
+#include <memory>
+
+#include "common_types.h" // NOLINT(build/include)
+#include "common_video/libyuv/include/webrtc_libyuv.h"
+#include "modules/video_capture/video_capture.h"
+#include "rtc_base/criticalsection.h"
+#include "rtc_base/scoped_ref_ptr.h"
+#include "test/video_capturer.h"
+
+namespace webrtc {
+namespace test {
+
+class VcmCapturer
+ : public VideoCapturer,
+ public rtc::VideoSinkInterface<VideoFrame> {
+ public:
+ static VcmCapturer* Create(size_t width,
+ size_t height,
+ size_t target_fps,
+ size_t capture_device_index);
+ virtual ~VcmCapturer();
+
+ void Start() override;
+ void Stop() override;
+ void AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink,
+ const rtc::VideoSinkWants& wants) override;
+ void RemoveSink(rtc::VideoSinkInterface<VideoFrame>* sink) override;
+
+ void OnFrame(const VideoFrame& frame) override;
+
+ private:
+ VcmCapturer();
+ bool Init(size_t width,
+ size_t height,
+ size_t target_fps,
+ size_t capture_device_index);
+ void Destroy();
+
+ rtc::CriticalSection crit_;
+ bool started_ RTC_GUARDED_BY(crit_);
+ rtc::VideoSinkInterface<VideoFrame>* sink_ RTC_GUARDED_BY(crit_);
+ rtc::scoped_refptr<VideoCaptureModule> vcm_;
+ VideoCaptureCapability capability_;
+};
+
+} // test
+} // webrtc
+
+#endif // TEST_VCM_CAPTURER_H_
diff --git a/third_party/libwebrtc/webrtc/test/video_capturer.cc b/third_party/libwebrtc/webrtc/test/video_capturer.cc
new file mode 100644
index 0000000000..b95936feb9
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/video_capturer.cc
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "test/video_capturer.h"
+
+#include "rtc_base/basictypes.h"
+#include "rtc_base/constructormagic.h"
+
+namespace webrtc {
+namespace test {
+VideoCapturer::VideoCapturer() : video_adapter_(new cricket::VideoAdapter()) {}
+VideoCapturer::~VideoCapturer() {}
+
+rtc::Optional<VideoFrame> VideoCapturer::AdaptFrame(const VideoFrame& frame) {
+ int cropped_width = 0;
+ int cropped_height = 0;
+ int out_width = 0;
+ int out_height = 0;
+
+ if (!video_adapter_->AdaptFrameResolution(
+ frame.width(), frame.height(), frame.timestamp_us() * 1000,
+ &cropped_width, &cropped_height, &out_width, &out_height)) {
+ // Drop frame in order to respect frame rate constraint.
+ return rtc::Optional<VideoFrame>();
+ }
+
+ rtc::Optional<VideoFrame> out_frame;
+ if (out_height != frame.height() || out_width != frame.width()) {
+ // Video adapter has requested a down-scale. Allocate a new buffer and
+ // return scaled version.
+ rtc::scoped_refptr<I420Buffer> scaled_buffer =
+ I420Buffer::Create(out_width, out_height);
+ scaled_buffer->ScaleFrom(*frame.video_frame_buffer()->ToI420());
+ out_frame.emplace(
+ VideoFrame(scaled_buffer, kVideoRotation_0, frame.timestamp_us()));
+ } else {
+ // No adaptations needed, just return the frame as is.
+ out_frame.emplace(frame);
+ }
+
+ return out_frame;
+}
+
+void VideoCapturer::AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink,
+ const rtc::VideoSinkWants& wants) {
+ video_adapter_->OnResolutionFramerateRequest(
+ wants.target_pixel_count, wants.max_pixel_count, wants.max_framerate_fps);
+}
+
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/video_capturer.h b/third_party/libwebrtc/webrtc/test/video_capturer.h
new file mode 100644
index 0000000000..eba5d61111
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/video_capturer.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef TEST_VIDEO_CAPTURER_H_
+#define TEST_VIDEO_CAPTURER_H_
+
+#include <stddef.h>
+
+#include <memory>
+
+#include "api/optional.h"
+#include "api/video/i420_buffer.h"
+#include "api/video/video_frame.h"
+#include "media/base/videoadapter.h"
+#include "media/base/videosourceinterface.h"
+#include "rtc_base/criticalsection.h"
+
+namespace cricket {
+class VideoAdapter;
+} // namespace cricket
+
+namespace webrtc {
+class Clock;
+namespace test {
+
+class VideoCapturer : public rtc::VideoSourceInterface<VideoFrame> {
+ public:
+ VideoCapturer();
+ virtual ~VideoCapturer();
+
+ virtual void Start() = 0;
+ virtual void Stop() = 0;
+
+ void AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink,
+ const rtc::VideoSinkWants& wants) override;
+
+ protected:
+ rtc::Optional<VideoFrame> AdaptFrame(const VideoFrame& frame);
+ rtc::VideoSinkWants GetSinkWants();
+
+ private:
+ const std::unique_ptr<cricket::VideoAdapter> video_adapter_;
+};
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_VIDEO_CAPTURER_H_
diff --git a/third_party/libwebrtc/webrtc/test/video_codec_settings.h b/third_party/libwebrtc/webrtc/test/video_codec_settings.h
new file mode 100644
index 0000000000..b52fbc7f42
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/video_codec_settings.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef TEST_VIDEO_CODEC_SETTINGS_H_
+#define TEST_VIDEO_CODEC_SETTINGS_H_
+
+#include "api/video_codecs/video_encoder.h"
+
+namespace webrtc {
+namespace test {
+
+const uint16_t kTestWidth = 352;
+const uint16_t kTestHeight = 288;
+const uint32_t kTestFrameRate = 30;
+const unsigned int kTestMinBitrateKbps = 30;
+const unsigned int kTestStartBitrateKbps = 300;
+const uint8_t kTestPayloadType = 100;
+const int64_t kTestTimingFramesDelayMs = 200;
+const uint16_t kTestOutlierFrameSizePercent = 250;
+
+static void CodecSettings(VideoCodecType codec_type, VideoCodec* settings) {
+ memset(settings, 0, sizeof(VideoCodec));
+ switch (codec_type) {
+ case kVideoCodecVP8:
+ strncpy(settings->plName, "VP8", 4);
+ settings->codecType = kVideoCodecVP8;
+ // 96 to 127 dynamic payload types for video codecs.
+ settings->plType = kTestPayloadType;
+ settings->startBitrate = kTestStartBitrateKbps;
+ settings->minBitrate = kTestMinBitrateKbps;
+ settings->maxBitrate = 0;
+ settings->maxFramerate = kTestFrameRate;
+ settings->width = kTestWidth;
+ settings->height = kTestHeight;
+ settings->numberOfSimulcastStreams = 0;
+ settings->qpMax = 56;
+ settings->timing_frame_thresholds = {
+ kTestTimingFramesDelayMs, kTestOutlierFrameSizePercent,
+ };
+ *(settings->VP8()) = VideoEncoder::GetDefaultVp8Settings();
+ return;
+ case kVideoCodecVP9:
+ strncpy(settings->plName, "VP9", 4);
+ settings->codecType = kVideoCodecVP9;
+ // 96 to 127 dynamic payload types for video codecs.
+ settings->plType = kTestPayloadType;
+ settings->startBitrate = 100;
+ settings->minBitrate = kTestMinBitrateKbps;
+ settings->maxBitrate = 0;
+ settings->maxFramerate = kTestFrameRate;
+ settings->width = kTestWidth;
+ settings->height = kTestHeight;
+ settings->numberOfSimulcastStreams = 0;
+ settings->qpMax = 56;
+ settings->timing_frame_thresholds = {
+ kTestTimingFramesDelayMs, kTestOutlierFrameSizePercent,
+ };
+ *(settings->VP9()) = VideoEncoder::GetDefaultVp9Settings();
+ return;
+ case kVideoCodecH264:
+ strncpy(settings->plName, "H264", 5);
+ settings->codecType = kVideoCodecH264;
+ // 96 to 127 dynamic payload types for video codecs.
+ settings->plType = kTestPayloadType;
+ settings->startBitrate = kTestStartBitrateKbps;
+ settings->minBitrate = kTestMinBitrateKbps;
+ settings->maxBitrate = 0;
+ settings->maxFramerate = kTestFrameRate;
+ settings->width = kTestWidth;
+ settings->height = kTestHeight;
+ settings->numberOfSimulcastStreams = 0;
+ settings->qpMax = 56;
+ settings->timing_frame_thresholds = {
+ kTestTimingFramesDelayMs, kTestOutlierFrameSizePercent,
+ };
+ *(settings->H264()) = VideoEncoder::GetDefaultH264Settings();
+ return;
+ case kVideoCodecI420:
+ strncpy(settings->plName, "I420", 5);
+ settings->codecType = kVideoCodecI420;
+ // 96 to 127 dynamic payload types for video codecs.
+ settings->plType = kTestPayloadType;
+ // Bitrate needed for this size and framerate.
+ settings->startBitrate =
+ 3 * kTestWidth * kTestHeight * 8 * kTestFrameRate / 1000 / 2;
+ settings->maxBitrate = settings->startBitrate;
+ settings->maxFramerate = kTestFrameRate;
+ settings->width = kTestWidth;
+ settings->height = kTestHeight;
+ settings->minBitrate = kTestMinBitrateKbps;
+ settings->numberOfSimulcastStreams = 0;
+ return;
+ case kVideoCodecRED:
+ case kVideoCodecULPFEC:
+ case kVideoCodecFlexfec:
+ case kVideoCodecGeneric:
+ case kVideoCodecUnknown:
+ RTC_NOTREACHED();
+ return;
+ }
+}
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_VIDEO_CODEC_SETTINGS_H_
diff --git a/third_party/libwebrtc/webrtc/test/video_renderer.cc b/third_party/libwebrtc/webrtc/test/video_renderer.cc
new file mode 100644
index 0000000000..68a20f3752
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/video_renderer.cc
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "test/video_renderer.h"
+
+// TODO(pbos): Android renderer
+
+#include "typedefs.h" // NOLINT(build/include)
+
+namespace webrtc {
+namespace test {
+
+class NullRenderer : public VideoRenderer {
+ void OnFrame(const VideoFrame& video_frame) override {}
+};
+
+VideoRenderer* VideoRenderer::Create(const char* window_title,
+ size_t width,
+ size_t height) {
+ VideoRenderer* renderer = CreatePlatformRenderer(window_title, width, height);
+ if (renderer != nullptr)
+ return renderer;
+
+ return new NullRenderer();
+}
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/video_renderer.h b/third_party/libwebrtc/webrtc/test/video_renderer.h
new file mode 100644
index 0000000000..6a00e8803b
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/video_renderer.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef TEST_VIDEO_RENDERER_H_
+#define TEST_VIDEO_RENDERER_H_
+
+#include <stddef.h>
+
+#include "media/base/videosinkinterface.h"
+
+namespace webrtc {
+class VideoFrame;
+
+namespace test {
+class VideoRenderer : public rtc::VideoSinkInterface<VideoFrame> {
+ public:
+ // Creates a platform-specific renderer if possible, or a null implementation
+ // if failing.
+ static VideoRenderer* Create(const char* window_title, size_t width,
+ size_t height);
+ // Returns a renderer rendering to a platform specific window if possible,
+ // NULL if none can be created.
+ // Creates a platform-specific renderer if possible, returns NULL if a
+ // platform renderer could not be created. This occurs, for instance, when
+ // running without an X environment on Linux.
+ static VideoRenderer* CreatePlatformRenderer(const char* window_title,
+ size_t width, size_t height);
+ virtual ~VideoRenderer() {}
+ protected:
+ VideoRenderer() {}
+};
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_VIDEO_RENDERER_H_
diff --git a/third_party/libwebrtc/webrtc/test/win/d3d_renderer.cc b/third_party/libwebrtc/webrtc/test/win/d3d_renderer.cc
new file mode 100644
index 0000000000..1f791a91ef
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/win/d3d_renderer.cc
@@ -0,0 +1,220 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "test/win/d3d_renderer.h"
+
+#include "common_video/libyuv/include/webrtc_libyuv.h"
+#include "rtc_base/checks.h"
+
+namespace webrtc {
+namespace test {
+
+#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_TEX1)
+
+struct D3dCustomVertex {
+ float x, y, z;
+ float u, v;
+};
+
+const char kD3DClassName[] = "d3d_renderer";
+
+VideoRenderer* VideoRenderer::CreatePlatformRenderer(const char* window_title,
+ size_t width,
+ size_t height) {
+ return D3dRenderer::Create(window_title, width, height);
+}
+
+D3dRenderer::D3dRenderer(size_t width, size_t height)
+ : width_(width),
+ height_(height),
+ hwnd_(NULL),
+ d3d_(NULL),
+ d3d_device_(NULL),
+ texture_(NULL),
+ vertex_buffer_(NULL) {
+ RTC_DCHECK_GT(width, 0);
+ RTC_DCHECK_GT(height, 0);
+}
+
+D3dRenderer::~D3dRenderer() { Destroy(); }
+
+LRESULT WINAPI D3dRenderer::WindowProc(HWND hwnd, UINT msg, WPARAM wparam,
+ LPARAM lparam) {
+ if (msg == WM_DESTROY || (msg == WM_CHAR && wparam == VK_RETURN)) {
+ PostQuitMessage(0);
+ return 0;
+ }
+
+ return DefWindowProcA(hwnd, msg, wparam, lparam);
+}
+
+void D3dRenderer::Destroy() {
+ texture_ = NULL;
+ vertex_buffer_ = NULL;
+ d3d_device_ = NULL;
+ d3d_ = NULL;
+
+ if (hwnd_ != NULL) {
+ DestroyWindow(hwnd_);
+ RTC_DCHECK(!IsWindow(hwnd_));
+ hwnd_ = NULL;
+ }
+}
+
+bool D3dRenderer::Init(const char* window_title) {
+ hwnd_ = CreateWindowA(kD3DClassName,
+ window_title,
+ WS_OVERLAPPEDWINDOW,
+ 0,
+ 0,
+ static_cast<int>(width_),
+ static_cast<int>(height_),
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+
+ if (hwnd_ == NULL) {
+ Destroy();
+ return false;
+ }
+
+ d3d_ = Direct3DCreate9(D3D_SDK_VERSION);
+ if (d3d_ == NULL) {
+ Destroy();
+ return false;
+ }
+
+ D3DPRESENT_PARAMETERS d3d_params = {};
+
+ d3d_params.Windowed = TRUE;
+ d3d_params.SwapEffect = D3DSWAPEFFECT_COPY;
+
+ IDirect3DDevice9* d3d_device;
+ if (d3d_->CreateDevice(D3DADAPTER_DEFAULT,
+ D3DDEVTYPE_HAL,
+ hwnd_,
+ D3DCREATE_SOFTWARE_VERTEXPROCESSING,
+ &d3d_params,
+ &d3d_device) != D3D_OK) {
+ Destroy();
+ return false;
+ }
+ d3d_device_ = d3d_device;
+ d3d_device->Release();
+
+ IDirect3DVertexBuffer9* vertex_buffer;
+ const int kRectVertices = 4;
+ if (d3d_device_->CreateVertexBuffer(kRectVertices * sizeof(D3dCustomVertex),
+ 0,
+ D3DFVF_CUSTOMVERTEX,
+ D3DPOOL_MANAGED,
+ &vertex_buffer,
+ NULL) != D3D_OK) {
+ Destroy();
+ return false;
+ }
+ vertex_buffer_ = vertex_buffer;
+ vertex_buffer->Release();
+
+ d3d_device_->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
+ d3d_device_->SetRenderState(D3DRS_LIGHTING, FALSE);
+ Resize(width_, height_);
+
+ ShowWindow(hwnd_, SW_SHOWNOACTIVATE);
+ d3d_device_->Present(NULL, NULL, NULL, NULL);
+
+ return true;
+}
+
+D3dRenderer* D3dRenderer::Create(const char* window_title,
+ size_t width,
+ size_t height) {
+ static ATOM wc_atom = 0;
+ if (wc_atom == 0) {
+ WNDCLASSA wc = {};
+
+ wc.style = CS_HREDRAW | CS_VREDRAW;
+ wc.lpfnWndProc = WindowProc;
+ wc.hCursor = LoadCursor(NULL, IDC_ARROW);
+ wc.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW);
+ wc.lpszClassName = kD3DClassName;
+
+ wc_atom = RegisterClassA(&wc);
+ if (wc_atom == 0)
+ return false;
+ }
+
+ D3dRenderer* d3d_renderer = new D3dRenderer(width, height);
+ if (!d3d_renderer->Init(window_title)) {
+ delete d3d_renderer;
+ return NULL;
+ }
+
+ return d3d_renderer;
+}
+
+void D3dRenderer::Resize(size_t width, size_t height) {
+ width_ = width;
+ height_ = height;
+ IDirect3DTexture9* texture;
+
+ d3d_device_->CreateTexture(static_cast<UINT>(width_),
+ static_cast<UINT>(height_),
+ 1,
+ 0,
+ D3DFMT_A8R8G8B8,
+ D3DPOOL_MANAGED,
+ &texture,
+ NULL);
+ texture_ = texture;
+ texture->Release();
+
+ // Vertices for the video frame to be rendered to.
+ static const D3dCustomVertex rect[] = {
+ {-1.0f, -1.0f, 0.0f, 0.0f, 1.0f},
+ {-1.0f, 1.0f, 0.0f, 0.0f, 0.0f},
+ {1.0f, -1.0f, 0.0f, 1.0f, 1.0f},
+ {1.0f, 1.0f, 0.0f, 1.0f, 0.0f},
+ };
+
+ void* buf_data;
+ if (vertex_buffer_->Lock(0, 0, &buf_data, 0) != D3D_OK)
+ return;
+
+ memcpy(buf_data, &rect, sizeof(rect));
+ vertex_buffer_->Unlock();
+}
+
+void D3dRenderer::OnFrame(const webrtc::VideoFrame& frame) {
+ if (static_cast<size_t>(frame.width()) != width_ ||
+ static_cast<size_t>(frame.height()) != height_) {
+ Resize(static_cast<size_t>(frame.width()),
+ static_cast<size_t>(frame.height()));
+ }
+
+ D3DLOCKED_RECT lock_rect;
+ if (texture_->LockRect(0, &lock_rect, NULL, 0) != D3D_OK)
+ return;
+
+ ConvertFromI420(frame, VideoType::kARGB, 0,
+ static_cast<uint8_t*>(lock_rect.pBits));
+ texture_->UnlockRect(0);
+
+ d3d_device_->BeginScene();
+ d3d_device_->SetFVF(D3DFVF_CUSTOMVERTEX);
+ d3d_device_->SetStreamSource(0, vertex_buffer_, 0, sizeof(D3dCustomVertex));
+ d3d_device_->SetTexture(0, texture_);
+ d3d_device_->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2);
+ d3d_device_->EndScene();
+
+ d3d_device_->Present(NULL, NULL, NULL, NULL);
+}
+} // namespace test
+} // namespace webrtc
diff --git a/third_party/libwebrtc/webrtc/test/win/d3d_renderer.h b/third_party/libwebrtc/webrtc/test/win/d3d_renderer.h
new file mode 100644
index 0000000000..68a5a802f2
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/win/d3d_renderer.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#ifndef TEST_WIN_D3D_RENDERER_H_
+#define TEST_WIN_D3D_RENDERER_H_
+
+#include <Windows.h>
+#include <d3d9.h>
+#pragma comment(lib, "d3d9.lib") // located in DirectX SDK
+
+#include "rtc_base/scoped_ref_ptr.h"
+#include "test/video_renderer.h"
+#include "typedefs.h" // NOLINT(build/include)
+
+namespace webrtc {
+namespace test {
+
+class D3dRenderer : public VideoRenderer {
+ public:
+ static D3dRenderer* Create(const char* window_title, size_t width,
+ size_t height);
+ virtual ~D3dRenderer();
+
+ void OnFrame(const webrtc::VideoFrame& frame) override;
+
+ private:
+ D3dRenderer(size_t width, size_t height);
+
+ static LRESULT WINAPI WindowProc(HWND hwnd, UINT msg, WPARAM wparam,
+ LPARAM lparam);
+ bool Init(const char* window_title);
+ void Resize(size_t width, size_t height);
+ void Destroy();
+
+ size_t width_, height_;
+
+ HWND hwnd_;
+ rtc::scoped_refptr<IDirect3D9> d3d_;
+ rtc::scoped_refptr<IDirect3DDevice9> d3d_device_;
+
+ rtc::scoped_refptr<IDirect3DTexture9> texture_;
+ rtc::scoped_refptr<IDirect3DVertexBuffer9> vertex_buffer_;
+};
+} // namespace test
+} // namespace webrtc
+
+#endif // TEST_WIN_D3D_RENDERER_H_
diff --git a/third_party/libwebrtc/webrtc/test/win/run_loop_win.cc b/third_party/libwebrtc/webrtc/test/win/run_loop_win.cc
new file mode 100644
index 0000000000..494adc47d6
--- /dev/null
+++ b/third_party/libwebrtc/webrtc/test/win/run_loop_win.cc
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+#include "test/run_loop.h"
+
+#include <assert.h>
+
+#include <conio.h>
+#include <stdio.h>
+#include <Windows.h>
+
+namespace webrtc {
+namespace test {
+
+void PressEnterToContinue() {
+ puts(">> Press ENTER to continue...");
+
+ MSG msg;
+ BOOL ret;
+ while ((ret = GetMessage(&msg, NULL, 0, 0)) != 0) {
+ assert(ret != -1);
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+}
+} // namespace test
+} // namespace webrtc