OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
| 10 #include "webrtc/video/video_quality_test.h" |
| 11 |
10 #include <stdio.h> | 12 #include <stdio.h> |
11 | |
12 #include <algorithm> | 13 #include <algorithm> |
13 #include <deque> | 14 #include <deque> |
14 #include <map> | 15 #include <map> |
15 #include <sstream> | 16 #include <sstream> |
16 #include <string> | 17 #include <string> |
17 #include <vector> | 18 #include <vector> |
18 | 19 |
19 #include "testing/gtest/include/gtest/gtest.h" | 20 #include "testing/gtest/include/gtest/gtest.h" |
20 | |
21 #include "webrtc/base/checks.h" | 21 #include "webrtc/base/checks.h" |
22 #include "webrtc/base/event.h" | 22 #include "webrtc/base/event.h" |
23 #include "webrtc/base/format_macros.h" | 23 #include "webrtc/base/format_macros.h" |
24 #include "webrtc/base/optional.h" | 24 #include "webrtc/base/optional.h" |
25 #include "webrtc/base/timeutils.h" | 25 #include "webrtc/base/timeutils.h" |
26 #include "webrtc/call.h" | 26 #include "webrtc/call.h" |
27 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" | 27 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" |
28 #include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h" | 28 #include "webrtc/modules/rtp_rtcp/include/rtp_header_parser.h" |
29 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" | 29 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" |
30 #include "webrtc/system_wrappers/include/cpu_info.h" | 30 #include "webrtc/system_wrappers/include/cpu_info.h" |
31 #include "webrtc/test/layer_filtering_transport.h" | 31 #include "webrtc/test/layer_filtering_transport.h" |
32 #include "webrtc/test/run_loop.h" | 32 #include "webrtc/test/run_loop.h" |
33 #include "webrtc/test/statistics.h" | 33 #include "webrtc/test/statistics.h" |
34 #include "webrtc/test/testsupport/fileutils.h" | 34 #include "webrtc/test/testsupport/fileutils.h" |
| 35 #include "webrtc/test/vcm_capturer.h" |
35 #include "webrtc/test/video_renderer.h" | 36 #include "webrtc/test/video_renderer.h" |
36 #include "webrtc/video/video_quality_test.h" | |
37 | 37 |
38 namespace webrtc { | 38 namespace webrtc { |
39 | 39 |
40 static const int kSendStatsPollingIntervalMs = 1000; | 40 static const int kSendStatsPollingIntervalMs = 1000; |
41 static const int kPayloadTypeH264 = 122; | 41 static const int kPayloadTypeH264 = 122; |
42 static const int kPayloadTypeVP8 = 123; | 42 static const int kPayloadTypeVP8 = 123; |
43 static const int kPayloadTypeVP9 = 124; | 43 static const int kPayloadTypeVP9 = 124; |
44 static const size_t kMaxComparisons = 10; | 44 static const size_t kMaxComparisons = 10; |
45 | 45 |
46 class VideoAnalyzer : public PacketReceiver, | 46 class VideoAnalyzer : public PacketReceiver, |
47 public Transport, | 47 public Transport, |
48 public rtc::VideoSinkInterface<VideoFrame>, | 48 public rtc::VideoSinkInterface<VideoFrame>, |
49 public VideoCaptureInput, | |
50 public EncodedFrameObserver { | 49 public EncodedFrameObserver { |
51 public: | 50 public: |
52 VideoAnalyzer(test::LayerFilteringTransport* transport, | 51 VideoAnalyzer(test::LayerFilteringTransport* transport, |
53 const std::string& test_label, | 52 const std::string& test_label, |
54 double avg_psnr_threshold, | 53 double avg_psnr_threshold, |
55 double avg_ssim_threshold, | 54 double avg_ssim_threshold, |
56 int duration_frames, | 55 int duration_frames, |
57 FILE* graph_data_output_file, | 56 FILE* graph_data_output_file, |
58 const std::string& graph_title, | 57 const std::string& graph_title, |
59 uint32_t ssrc_to_analyze) | 58 uint32_t ssrc_to_analyze) |
60 : input_(nullptr), | 59 : transport_(transport), |
61 transport_(transport), | |
62 receiver_(nullptr), | 60 receiver_(nullptr), |
63 send_stream_(nullptr), | 61 send_stream_(nullptr), |
| 62 captured_frame_forwarder_(this), |
64 test_label_(test_label), | 63 test_label_(test_label), |
65 graph_data_output_file_(graph_data_output_file), | 64 graph_data_output_file_(graph_data_output_file), |
66 graph_title_(graph_title), | 65 graph_title_(graph_title), |
67 ssrc_to_analyze_(ssrc_to_analyze), | 66 ssrc_to_analyze_(ssrc_to_analyze), |
68 pre_encode_proxy_(this), | 67 pre_encode_proxy_(this), |
69 encode_timing_proxy_(this), | 68 encode_timing_proxy_(this), |
70 frames_to_process_(duration_frames), | 69 frames_to_process_(duration_frames), |
71 frames_recorded_(0), | 70 frames_recorded_(0), |
72 frames_processed_(0), | 71 frames_processed_(0), |
73 dropped_frames_(0), | 72 dropped_frames_(0), |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
109 | 108 |
110 ~VideoAnalyzer() { | 109 ~VideoAnalyzer() { |
111 for (rtc::PlatformThread* thread : comparison_thread_pool_) { | 110 for (rtc::PlatformThread* thread : comparison_thread_pool_) { |
112 thread->Stop(); | 111 thread->Stop(); |
113 delete thread; | 112 delete thread; |
114 } | 113 } |
115 } | 114 } |
116 | 115 |
117 virtual void SetReceiver(PacketReceiver* receiver) { receiver_ = receiver; } | 116 virtual void SetReceiver(PacketReceiver* receiver) { receiver_ = receiver; } |
118 | 117 |
| 118 void SetSendSendStream(VideoSendStream* stream) { |
| 119 rtc::CritScope lock(&crit_); |
| 120 RTC_DCHECK(!send_stream_); |
| 121 send_stream_ = stream; |
| 122 } |
| 123 |
| 124 rtc::VideoSinkInterface<VideoFrame>* InputInterface() { |
| 125 return &captured_frame_forwarder_; |
| 126 } |
| 127 rtc::VideoSourceInterface<VideoFrame>* OutputInterface() { |
| 128 return &captured_frame_forwarder_; |
| 129 } |
| 130 |
119 DeliveryStatus DeliverPacket(MediaType media_type, | 131 DeliveryStatus DeliverPacket(MediaType media_type, |
120 const uint8_t* packet, | 132 const uint8_t* packet, |
121 size_t length, | 133 size_t length, |
122 const PacketTime& packet_time) override { | 134 const PacketTime& packet_time) override { |
123 // Ignore timestamps of RTCP packets. They're not synchronized with | 135 // Ignore timestamps of RTCP packets. They're not synchronized with |
124 // RTP packet timestamps and so they would confuse wrap_handler_. | 136 // RTP packet timestamps and so they would confuse wrap_handler_. |
125 if (RtpHeaderParser::IsRtcp(packet, length)) { | 137 if (RtpHeaderParser::IsRtcp(packet, length)) { |
126 return receiver_->DeliverPacket(media_type, packet, length, packet_time); | 138 return receiver_->DeliverPacket(media_type, packet, length, packet_time); |
127 } | 139 } |
128 | 140 |
129 RtpUtility::RtpHeaderParser parser(packet, length); | 141 RtpUtility::RtpHeaderParser parser(packet, length); |
130 RTPHeader header; | 142 RTPHeader header; |
131 parser.Parse(&header); | 143 parser.Parse(&header); |
132 { | 144 { |
133 rtc::CritScope lock(&crit_); | 145 rtc::CritScope lock(&crit_); |
134 int64_t timestamp = | 146 int64_t timestamp = |
135 wrap_handler_.Unwrap(header.timestamp - rtp_timestamp_delta_); | 147 wrap_handler_.Unwrap(header.timestamp - rtp_timestamp_delta_); |
136 recv_times_[timestamp] = | 148 recv_times_[timestamp] = |
137 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds(); | 149 Clock::GetRealTimeClock()->CurrentNtpInMilliseconds(); |
138 } | 150 } |
139 | 151 |
140 return receiver_->DeliverPacket(media_type, packet, length, packet_time); | 152 return receiver_->DeliverPacket(media_type, packet, length, packet_time); |
141 } | 153 } |
142 | 154 |
143 void MeasuredEncodeTiming(int64_t ntp_time_ms, int encode_time_ms) { | 155 void MeasuredEncodeTiming(int64_t ntp_time_ms, int encode_time_ms) { |
144 rtc::CritScope crit(&comparison_lock_); | 156 rtc::CritScope crit(&comparison_lock_); |
145 samples_encode_time_ms_[ntp_time_ms] = encode_time_ms; | 157 samples_encode_time_ms_[ntp_time_ms] = encode_time_ms; |
146 } | 158 } |
147 | 159 |
148 void IncomingCapturedFrame(const VideoFrame& video_frame) override { | |
149 VideoFrame copy = video_frame; | |
150 copy.set_timestamp(copy.ntp_time_ms() * 90); | |
151 { | |
152 rtc::CritScope lock(&crit_); | |
153 frames_.push_back(copy); | |
154 } | |
155 | |
156 input_->IncomingCapturedFrame(video_frame); | |
157 } | |
158 | |
159 void PreEncodeOnFrame(const VideoFrame& video_frame) { | 160 void PreEncodeOnFrame(const VideoFrame& video_frame) { |
160 rtc::CritScope lock(&crit_); | 161 rtc::CritScope lock(&crit_); |
161 if (!first_send_timestamp_ && rtp_timestamp_delta_ == 0) { | 162 if (!first_send_timestamp_ && rtp_timestamp_delta_ == 0) { |
162 while (frames_.front().timestamp() != video_frame.timestamp()) { | 163 while (frames_.front().timestamp() != video_frame.timestamp()) { |
163 ++dropped_frames_before_first_encode_; | 164 ++dropped_frames_before_first_encode_; |
164 frames_.pop_front(); | 165 frames_.pop_front(); |
165 RTC_CHECK(!frames_.empty()); | 166 RTC_CHECK(!frames_.empty()); |
166 } | 167 } |
167 first_send_timestamp_ = rtc::Optional<uint32_t>(video_frame.timestamp()); | 168 first_send_timestamp_ = rtc::Optional<uint32_t>(video_frame.timestamp()); |
168 } | 169 } |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
286 printf("- Farewell, sweet Concorde!\n"); | 287 printf("- Farewell, sweet Concorde!\n"); |
287 | 288 |
288 stats_polling_thread_.Stop(); | 289 stats_polling_thread_.Stop(); |
289 } | 290 } |
290 | 291 |
291 rtc::VideoSinkInterface<VideoFrame>* pre_encode_proxy() { | 292 rtc::VideoSinkInterface<VideoFrame>* pre_encode_proxy() { |
292 return &pre_encode_proxy_; | 293 return &pre_encode_proxy_; |
293 } | 294 } |
294 EncodedFrameObserver* encode_timing_proxy() { return &encode_timing_proxy_; } | 295 EncodedFrameObserver* encode_timing_proxy() { return &encode_timing_proxy_; } |
295 | 296 |
296 VideoCaptureInput* input_; | |
297 test::LayerFilteringTransport* const transport_; | 297 test::LayerFilteringTransport* const transport_; |
298 PacketReceiver* receiver_; | 298 PacketReceiver* receiver_; |
299 VideoSendStream* send_stream_; | |
300 | 299 |
301 private: | 300 private: |
302 struct FrameComparison { | 301 struct FrameComparison { |
303 FrameComparison() | 302 FrameComparison() |
304 : dropped(false), | 303 : dropped(false), |
305 send_time_ms(0), | 304 send_time_ms(0), |
306 recv_time_ms(0), | 305 recv_time_ms(0), |
307 render_time_ms(0), | 306 render_time_ms(0), |
308 encoded_frame_size(0) {} | 307 encoded_frame_size(0) {} |
309 | 308 |
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
637 sample.encoded_frame_size, sample.psnr, sample.ssim, | 636 sample.encoded_frame_size, sample.psnr, sample.ssim, |
638 encode_time_ms); | 637 encode_time_ms); |
639 } | 638 } |
640 if (missing_encode_time_samples) { | 639 if (missing_encode_time_samples) { |
641 fprintf(stderr, | 640 fprintf(stderr, |
642 "Warning: Missing encode_time_ms samples for %d frame(s).\n", | 641 "Warning: Missing encode_time_ms samples for %d frame(s).\n", |
643 missing_encode_time_samples); | 642 missing_encode_time_samples); |
644 } | 643 } |
645 } | 644 } |
646 | 645 |
| 646 // Implements VideoSinkInterface to receive captured frames from a |
| 647 // FrameGeneratorCapturer. Implements VideoSourceInterface to be able to act |
| 648 // as a source to VideoSendStream. |
| 649 // It forwards all input frames to the VideoAnalyser for later comparison and |
| 650 // forwards the captured frames to the VideoSendStream. |
| 651 class CapturedFrameForwarder : public rtc::VideoSinkInterface<VideoFrame>, |
| 652 public rtc::VideoSourceInterface<VideoFrame> { |
| 653 public: |
| 654 explicit CapturedFrameForwarder(VideoAnalyzer* analyzer) |
| 655 : analyzer_(analyzer), send_stream_input_(nullptr) {} |
| 656 |
| 657 private: |
| 658 void OnFrame(const VideoFrame& video_frame) override { |
| 659 VideoFrame copy = video_frame; |
| 660 copy.set_timestamp(copy.ntp_time_ms() * 90); |
| 661 |
| 662 analyzer_->AddCapturedFrameForComparison(video_frame); |
| 663 rtc::CritScope lock(&crit_); |
| 664 if (send_stream_input_) |
| 665 send_stream_input_->OnFrame(video_frame); |
| 666 } |
| 667 // Called when |send_stream_.SetSource()| is called. |
| 668 void AddOrUpdateSink(rtc::VideoSinkInterface<VideoFrame>* sink, |
| 669 const rtc::VideoSinkWants& wants) override { |
| 670 rtc::CritScope lock(&crit_); |
| 671 RTC_DCHECK(!send_stream_input_ || send_stream_input_ == sink); |
| 672 send_stream_input_ = sink; |
| 673 } |
| 674 |
| 675 // Called by |send_stream_| when |send_stream_.SetSource()| is called. |
| 676 void RemoveSink(rtc::VideoSinkInterface<VideoFrame>* sink) override { |
| 677 rtc::CritScope lock(&crit_); |
| 678 RTC_DCHECK(sink == send_stream_input_); |
| 679 send_stream_input_ = nullptr; |
| 680 } |
| 681 |
| 682 VideoAnalyzer* const analyzer_; |
| 683 rtc::CriticalSection crit_; |
| 684 rtc::VideoSinkInterface<VideoFrame>* send_stream_input_ GUARDED_BY(crit_); |
| 685 }; |
| 686 |
| 687 void AddCapturedFrameForComparison(const VideoFrame& video_frame) { |
| 688 rtc::CritScope lock(&crit_); |
| 689 frames_.push_back(video_frame); |
| 690 } |
| 691 |
| 692 VideoSendStream* send_stream_; |
| 693 CapturedFrameForwarder captured_frame_forwarder_; |
647 const std::string test_label_; | 694 const std::string test_label_; |
648 FILE* const graph_data_output_file_; | 695 FILE* const graph_data_output_file_; |
649 const std::string graph_title_; | 696 const std::string graph_title_; |
650 const uint32_t ssrc_to_analyze_; | 697 const uint32_t ssrc_to_analyze_; |
651 PreEncodeProxy pre_encode_proxy_; | 698 PreEncodeProxy pre_encode_proxy_; |
652 OnEncodeTimingProxy encode_timing_proxy_; | 699 OnEncodeTimingProxy encode_timing_proxy_; |
653 std::vector<Sample> samples_ GUARDED_BY(comparison_lock_); | 700 std::vector<Sample> samples_ GUARDED_BY(comparison_lock_); |
654 std::map<int64_t, int> samples_encode_time_ms_ GUARDED_BY(comparison_lock_); | 701 std::map<int64_t, int> samples_encode_time_ms_ GUARDED_BY(comparison_lock_); |
655 test::Statistics sender_time_ GUARDED_BY(comparison_lock_); | 702 test::Statistics sender_time_ GUARDED_BY(comparison_lock_); |
656 test::Statistics receiver_time_ GUARDED_BY(comparison_lock_); | 703 test::Statistics receiver_time_ GUARDED_BY(comparison_lock_); |
(...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
968 params_.screenshare.slide_change_interval); | 1015 params_.screenshare.slide_change_interval); |
969 | 1016 |
970 frame_generator_.reset( | 1017 frame_generator_.reset( |
971 test::FrameGenerator::CreateScrollingInputFromYuvFiles( | 1018 test::FrameGenerator::CreateScrollingInputFromYuvFiles( |
972 clock_, slides, kWidth, kHeight, params_.common.width, | 1019 clock_, slides, kWidth, kHeight, params_.common.width, |
973 params_.common.height, params_.screenshare.scroll_duration * 1000, | 1020 params_.common.height, params_.screenshare.scroll_duration * 1000, |
974 kPauseDurationMs)); | 1021 kPauseDurationMs)); |
975 } | 1022 } |
976 } | 1023 } |
977 | 1024 |
978 void VideoQualityTest::CreateCapturer(VideoCaptureInput* input) { | 1025 void VideoQualityTest::CreateCapturer() { |
979 if (params_.screenshare.enabled) { | 1026 if (params_.screenshare.enabled) { |
980 test::FrameGeneratorCapturer* frame_generator_capturer = | 1027 test::FrameGeneratorCapturer* frame_generator_capturer = |
981 new test::FrameGeneratorCapturer( | 1028 new test::FrameGeneratorCapturer(clock_, frame_generator_.release(), |
982 clock_, input, frame_generator_.release(), params_.common.fps); | 1029 params_.common.fps); |
983 EXPECT_TRUE(frame_generator_capturer->Init()); | 1030 EXPECT_TRUE(frame_generator_capturer->Init()); |
984 capturer_.reset(frame_generator_capturer); | 1031 capturer_.reset(frame_generator_capturer); |
985 } else { | 1032 } else { |
986 if (params_.video.clip_name.empty()) { | 1033 if (params_.video.clip_name.empty()) { |
987 capturer_.reset(test::VideoCapturer::Create(input, params_.common.width, | 1034 capturer_.reset(test::VcmCapturer::Create( |
988 params_.common.height, | 1035 params_.common.width, params_.common.height, params_.common.fps)); |
989 params_.common.fps, clock_)); | |
990 } else { | 1036 } else { |
991 capturer_.reset(test::FrameGeneratorCapturer::CreateFromYuvFile( | 1037 capturer_.reset(test::FrameGeneratorCapturer::CreateFromYuvFile( |
992 input, test::ResourcePath(params_.video.clip_name, "yuv"), | 1038 test::ResourcePath(params_.video.clip_name, "yuv"), |
993 params_.common.width, params_.common.height, params_.common.fps, | 1039 params_.common.width, params_.common.height, params_.common.fps, |
994 clock_)); | 1040 clock_)); |
995 ASSERT_TRUE(capturer_) << "Could not create capturer for " | 1041 ASSERT_TRUE(capturer_) << "Could not create capturer for " |
996 << params_.video.clip_name | 1042 << params_.video.clip_name |
997 << ".yuv. Is this resource file present?"; | 1043 << ".yuv. Is this resource file present?"; |
998 } | 1044 } |
999 } | 1045 } |
1000 } | 1046 } |
1001 | 1047 |
1002 void VideoQualityTest::RunWithAnalyzer(const Params& params) { | 1048 void VideoQualityTest::RunWithAnalyzer(const Params& params) { |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1066 video_send_config_.pre_encode_callback = analyzer.pre_encode_proxy(); | 1112 video_send_config_.pre_encode_callback = analyzer.pre_encode_proxy(); |
1067 for (auto& config : video_receive_configs_) | 1113 for (auto& config : video_receive_configs_) |
1068 config.pre_decode_callback = &analyzer; | 1114 config.pre_decode_callback = &analyzer; |
1069 RTC_DCHECK(!video_send_config_.post_encode_callback); | 1115 RTC_DCHECK(!video_send_config_.post_encode_callback); |
1070 video_send_config_.post_encode_callback = analyzer.encode_timing_proxy(); | 1116 video_send_config_.post_encode_callback = analyzer.encode_timing_proxy(); |
1071 | 1117 |
1072 if (params_.screenshare.enabled) | 1118 if (params_.screenshare.enabled) |
1073 SetupScreenshare(); | 1119 SetupScreenshare(); |
1074 | 1120 |
1075 CreateVideoStreams(); | 1121 CreateVideoStreams(); |
1076 analyzer.input_ = video_send_stream_->Input(); | 1122 analyzer.SetSendSendStream(video_send_stream_); |
1077 analyzer.send_stream_ = video_send_stream_; | 1123 video_send_stream_->SetSource(analyzer.OutputInterface()); |
1078 | 1124 |
1079 CreateCapturer(&analyzer); | 1125 CreateCapturer(); |
| 1126 rtc::VideoSinkWants wants; |
| 1127 capturer_->AddOrUpdateSink(analyzer.InputInterface(), wants); |
1080 | 1128 |
1081 video_send_stream_->Start(); | 1129 video_send_stream_->Start(); |
1082 for (VideoReceiveStream* receive_stream : video_receive_streams_) | 1130 for (VideoReceiveStream* receive_stream : video_receive_streams_) |
1083 receive_stream->Start(); | 1131 receive_stream->Start(); |
1084 capturer_->Start(); | 1132 capturer_->Start(); |
1085 | 1133 |
1086 analyzer.Wait(); | 1134 analyzer.Wait(); |
1087 | 1135 |
1088 send_transport.StopSending(); | 1136 send_transport.StopSending(); |
1089 recv_transport.StopSending(); | 1137 recv_transport.StopSending(); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1150 kUlpfecPayloadType; | 1198 kUlpfecPayloadType; |
1151 } | 1199 } |
1152 | 1200 |
1153 if (params_.screenshare.enabled) | 1201 if (params_.screenshare.enabled) |
1154 SetupScreenshare(); | 1202 SetupScreenshare(); |
1155 | 1203 |
1156 video_send_stream_ = call->CreateVideoSendStream( | 1204 video_send_stream_ = call->CreateVideoSendStream( |
1157 video_send_config_.Copy(), video_encoder_config_.Copy()); | 1205 video_send_config_.Copy(), video_encoder_config_.Copy()); |
1158 VideoReceiveStream* receive_stream = | 1206 VideoReceiveStream* receive_stream = |
1159 call->CreateVideoReceiveStream(video_receive_configs_[stream_id].Copy()); | 1207 call->CreateVideoReceiveStream(video_receive_configs_[stream_id].Copy()); |
1160 CreateCapturer(video_send_stream_->Input()); | 1208 CreateCapturer(); |
| 1209 video_send_stream_->SetSource(capturer_.get()); |
1161 | 1210 |
1162 receive_stream->Start(); | 1211 receive_stream->Start(); |
1163 video_send_stream_->Start(); | 1212 video_send_stream_->Start(); |
1164 capturer_->Start(); | 1213 capturer_->Start(); |
1165 | 1214 |
1166 test::PressEnterToContinue(); | 1215 test::PressEnterToContinue(); |
1167 | 1216 |
1168 capturer_->Stop(); | 1217 capturer_->Stop(); |
1169 video_send_stream_->Stop(); | 1218 video_send_stream_->Stop(); |
1170 receive_stream->Stop(); | 1219 receive_stream->Stop(); |
1171 | 1220 |
1172 call->DestroyVideoReceiveStream(receive_stream); | 1221 call->DestroyVideoReceiveStream(receive_stream); |
1173 call->DestroyVideoSendStream(video_send_stream_); | 1222 call->DestroyVideoSendStream(video_send_stream_); |
1174 | 1223 |
1175 transport.StopSending(); | 1224 transport.StopSending(); |
1176 } | 1225 } |
1177 | 1226 |
1178 } // namespace webrtc | 1227 } // namespace webrtc |
OLD | NEW |