| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2013 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 | 10 |
| 11 #include <stdio.h> | 11 #include <stdio.h> |
| 12 #include <string.h> |
| 12 | 13 |
| 13 #include <memory> | 14 #include <memory> |
| 14 | 15 |
| 15 #include "gflags/gflags.h" | |
| 16 #include "webrtc/common_types.h" | 16 #include "webrtc/common_types.h" |
| 17 #include "webrtc/modules/audio_coding/codecs/audio_format_conversion.h" | 17 #include "webrtc/modules/audio_coding/codecs/audio_format_conversion.h" |
| 18 #include "webrtc/modules/audio_coding/include/audio_coding_module.h" | 18 #include "webrtc/modules/audio_coding/include/audio_coding_module.h" |
| 19 #include "webrtc/modules/audio_coding/test/Channel.h" | 19 #include "webrtc/modules/audio_coding/test/Channel.h" |
| 20 #include "webrtc/modules/audio_coding/test/PCMFile.h" | 20 #include "webrtc/modules/audio_coding/test/PCMFile.h" |
| 21 #include "webrtc/modules/include/module_common_types.h" | 21 #include "webrtc/modules/include/module_common_types.h" |
| 22 #include "webrtc/rtc_base/flags.h" |
| 22 #include "webrtc/system_wrappers/include/clock.h" | 23 #include "webrtc/system_wrappers/include/clock.h" |
| 23 #include "webrtc/test/gtest.h" | 24 #include "webrtc/test/gtest.h" |
| 24 #include "webrtc/test/testsupport/fileutils.h" | 25 #include "webrtc/test/testsupport/fileutils.h" |
| 25 | 26 |
| 26 // Codec. | 27 // Codec. |
| 27 DEFINE_string(codec, "opus", "Codec Name"); | 28 DEFINE_string(codec, "opus", "Codec Name"); |
| 28 DEFINE_int32(codec_sample_rate_hz, 48000, "Sampling rate in Hertz."); | 29 DEFINE_int(codec_sample_rate_hz, 48000, "Sampling rate in Hertz."); |
| 29 DEFINE_int32(codec_channels, 1, "Number of channels of the codec."); | 30 DEFINE_int(codec_channels, 1, "Number of channels of the codec."); |
| 30 | 31 |
| 31 // PCM input/output. | 32 // PCM input/output. |
| 32 DEFINE_string(input, "", "Input PCM file at 16 kHz."); | 33 DEFINE_string(input, "", "Input PCM file at 16 kHz."); |
| 33 DEFINE_bool(input_stereo, false, "Input is stereo."); | 34 DEFINE_bool(input_stereo, false, "Input is stereo."); |
| 34 DEFINE_int32(input_fs_hz, 32000, "Input sample rate Hz."); | 35 DEFINE_int(input_fs_hz, 32000, "Input sample rate Hz."); |
| 35 DEFINE_string(output, "insert_rtp_with_timing_out.pcm", "OutputFile"); | 36 DEFINE_string(output, "insert_rtp_with_timing_out.pcm", "OutputFile"); |
| 36 DEFINE_int32(output_fs_hz, 32000, "Output sample rate Hz"); | 37 DEFINE_int(output_fs_hz, 32000, "Output sample rate Hz"); |
| 37 | 38 |
| 38 // Timing files | 39 // Timing files |
| 39 DEFINE_string(seq_num, "seq_num", "Sequence number file."); | 40 DEFINE_string(seq_num, "seq_num", "Sequence number file."); |
| 40 DEFINE_string(send_ts, "send_timestamp", "Send timestamp file."); | 41 DEFINE_string(send_ts, "send_timestamp", "Send timestamp file."); |
| 41 DEFINE_string(receive_ts, "last_rec_timestamp", "Receive timestamp file"); | 42 DEFINE_string(receive_ts, "last_rec_timestamp", "Receive timestamp file"); |
| 42 | 43 |
| 43 // Delay logging | 44 // Delay logging |
| 44 DEFINE_string(delay, "", "Log for delay."); | 45 DEFINE_string(delay, "", "Log for delay."); |
| 45 | 46 |
| 46 // Other setups | 47 // Other setups |
| 47 DEFINE_bool(verbose, false, "Verbosity."); | 48 DEFINE_bool(verbose, false, "Verbosity."); |
| 48 DEFINE_double(loss_rate, 0, "Rate of packet loss < 1"); | 49 DEFINE_float(loss_rate, 0, "Rate of packet loss < 1"); |
| 50 |
| 51 DEFINE_bool(help, false, "Prints this message."); |
| 49 | 52 |
| 50 const int32_t kAudioPlayedOut = 0x00000001; | 53 const int32_t kAudioPlayedOut = 0x00000001; |
| 51 const int32_t kPacketPushedIn = 0x00000001 << 1; | 54 const int32_t kPacketPushedIn = 0x00000001 << 1; |
| 52 const int kPlayoutPeriodMs = 10; | 55 const int kPlayoutPeriodMs = 10; |
| 53 | 56 |
| 54 namespace webrtc { | 57 namespace webrtc { |
| 55 | 58 |
| 56 class InsertPacketWithTiming { | 59 class InsertPacketWithTiming { |
| 57 public: | 60 public: |
| 58 InsertPacketWithTiming() | 61 InsertPacketWithTiming() |
| 59 : sender_clock_(new SimulatedClock(0)), | 62 : sender_clock_(new SimulatedClock(0)), |
| 60 receiver_clock_(new SimulatedClock(0)), | 63 receiver_clock_(new SimulatedClock(0)), |
| 61 send_acm_(AudioCodingModule::Create(0, sender_clock_)), | 64 send_acm_(AudioCodingModule::Create(0, sender_clock_)), |
| 62 receive_acm_(AudioCodingModule::Create(0, receiver_clock_)), | 65 receive_acm_(AudioCodingModule::Create(0, receiver_clock_)), |
| 63 channel_(new Channel), | 66 channel_(new Channel), |
| 64 seq_num_fid_(fopen(FLAGS_seq_num.c_str(), "rt")), | 67 seq_num_fid_(fopen(FLAG_seq_num, "rt")), |
| 65 send_ts_fid_(fopen(FLAGS_send_ts.c_str(), "rt")), | 68 send_ts_fid_(fopen(FLAG_send_ts, "rt")), |
| 66 receive_ts_fid_(fopen(FLAGS_receive_ts.c_str(), "rt")), | 69 receive_ts_fid_(fopen(FLAG_receive_ts, "rt")), |
| 67 pcm_out_fid_(fopen(FLAGS_output.c_str(), "wb")), | 70 pcm_out_fid_(fopen(FLAG_output, "wb")), |
| 68 samples_in_1ms_(48), | 71 samples_in_1ms_(48), |
| 69 num_10ms_in_codec_frame_(2), // Typical 20 ms frames. | 72 num_10ms_in_codec_frame_(2), // Typical 20 ms frames. |
| 70 time_to_insert_packet_ms_(3), // An arbitrary offset on pushing packet. | 73 time_to_insert_packet_ms_(3), // An arbitrary offset on pushing packet. |
| 71 next_receive_ts_(0), | 74 next_receive_ts_(0), |
| 72 time_to_playout_audio_ms_(kPlayoutPeriodMs), | 75 time_to_playout_audio_ms_(kPlayoutPeriodMs), |
| 73 loss_threshold_(0), | 76 loss_threshold_(0), |
| 74 playout_timing_fid_(fopen("playout_timing.txt", "wt")) {} | 77 playout_timing_fid_(fopen("playout_timing.txt", "wt")) {} |
| 75 | 78 |
| 76 void SetUp() { | 79 void SetUp() { |
| 77 ASSERT_TRUE(sender_clock_ != NULL); | 80 ASSERT_TRUE(sender_clock_ != NULL); |
| 78 ASSERT_TRUE(receiver_clock_ != NULL); | 81 ASSERT_TRUE(receiver_clock_ != NULL); |
| 79 | 82 |
| 80 ASSERT_TRUE(send_acm_.get() != NULL); | 83 ASSERT_TRUE(send_acm_.get() != NULL); |
| 81 ASSERT_TRUE(receive_acm_.get() != NULL); | 84 ASSERT_TRUE(receive_acm_.get() != NULL); |
| 82 ASSERT_TRUE(channel_ != NULL); | 85 ASSERT_TRUE(channel_ != NULL); |
| 83 | 86 |
| 84 ASSERT_TRUE(seq_num_fid_ != NULL); | 87 ASSERT_TRUE(seq_num_fid_ != NULL); |
| 85 ASSERT_TRUE(send_ts_fid_ != NULL); | 88 ASSERT_TRUE(send_ts_fid_ != NULL); |
| 86 ASSERT_TRUE(receive_ts_fid_ != NULL); | 89 ASSERT_TRUE(receive_ts_fid_ != NULL); |
| 87 | 90 |
| 88 ASSERT_TRUE(playout_timing_fid_ != NULL); | 91 ASSERT_TRUE(playout_timing_fid_ != NULL); |
| 89 | 92 |
| 90 next_receive_ts_ = ReceiveTimestamp(); | 93 next_receive_ts_ = ReceiveTimestamp(); |
| 91 | 94 |
| 92 CodecInst codec; | 95 CodecInst codec; |
| 93 ASSERT_EQ(0, AudioCodingModule::Codec(FLAGS_codec.c_str(), &codec, | 96 ASSERT_EQ(0, AudioCodingModule::Codec(FLAG_codec, &codec, |
| 94 FLAGS_codec_sample_rate_hz, | 97 FLAG_codec_sample_rate_hz, |
| 95 FLAGS_codec_channels)); | 98 FLAG_codec_channels)); |
| 96 ASSERT_EQ(0, receive_acm_->InitializeReceiver()); | 99 ASSERT_EQ(0, receive_acm_->InitializeReceiver()); |
| 97 ASSERT_EQ(0, send_acm_->RegisterSendCodec(codec)); | 100 ASSERT_EQ(0, send_acm_->RegisterSendCodec(codec)); |
| 98 ASSERT_EQ(true, receive_acm_->RegisterReceiveCodec(codec.pltype, | 101 ASSERT_EQ(true, receive_acm_->RegisterReceiveCodec(codec.pltype, |
| 99 CodecInstToSdp(codec))); | 102 CodecInstToSdp(codec))); |
| 100 | 103 |
| 101 // Set codec-dependent parameters. | 104 // Set codec-dependent parameters. |
| 102 samples_in_1ms_ = codec.plfreq / 1000; | 105 samples_in_1ms_ = codec.plfreq / 1000; |
| 103 num_10ms_in_codec_frame_ = codec.pacsize / (codec.plfreq / 100); | 106 num_10ms_in_codec_frame_ = codec.pacsize / (codec.plfreq / 100); |
| 104 | 107 |
| 105 channel_->RegisterReceiverACM(receive_acm_.get()); | 108 channel_->RegisterReceiverACM(receive_acm_.get()); |
| 106 send_acm_->RegisterTransportCallback(channel_); | 109 send_acm_->RegisterTransportCallback(channel_); |
| 107 | 110 |
| 108 if (FLAGS_input.size() == 0) { | 111 if (strlen(FLAG_input) == 0) { |
| 109 std::string file_name = test::ResourcePath("audio_coding/testfile32kHz", | 112 std::string file_name = test::ResourcePath("audio_coding/testfile32kHz", |
| 110 "pcm"); | 113 "pcm"); |
| 111 pcm_in_fid_.Open(file_name, 32000, "r", true); // auto-rewind | 114 pcm_in_fid_.Open(file_name, 32000, "r", true); // auto-rewind |
| 112 std::cout << "Input file " << file_name << " 32 kHz mono." << std::endl; | 115 std::cout << "Input file " << file_name << " 32 kHz mono." << std::endl; |
| 113 } else { | 116 } else { |
| 114 pcm_in_fid_.Open(FLAGS_input, static_cast<uint16_t>(FLAGS_input_fs_hz), | 117 pcm_in_fid_.Open(FLAG_input, static_cast<uint16_t>(FLAG_input_fs_hz), |
| 115 "r", true); // auto-rewind | 118 "r", true); // auto-rewind |
| 116 std::cout << "Input file " << FLAGS_input << "at " << FLAGS_input_fs_hz | 119 std::cout << "Input file " << FLAG_input << "at " << FLAG_input_fs_hz |
| 117 << " Hz in " << ((FLAGS_input_stereo) ? "stereo." : "mono.") | 120 << " Hz in " << ((FLAG_input_stereo) ? "stereo." : "mono.") |
| 118 << std::endl; | 121 << std::endl; |
| 119 pcm_in_fid_.ReadStereo(FLAGS_input_stereo); | 122 pcm_in_fid_.ReadStereo(FLAG_input_stereo); |
| 120 } | 123 } |
| 121 | 124 |
| 122 ASSERT_TRUE(pcm_out_fid_ != NULL); | 125 ASSERT_TRUE(pcm_out_fid_ != NULL); |
| 123 std::cout << "Output file " << FLAGS_output << " at " << FLAGS_output_fs_hz | 126 std::cout << "Output file " << FLAG_output << " at " << FLAG_output_fs_hz |
| 124 << " Hz." << std::endl; | 127 << " Hz." << std::endl; |
| 125 | 128 |
| 126 // Other setups | 129 // Other setups |
| 127 if (FLAGS_loss_rate > 0) | 130 if (FLAG_loss_rate > 0) |
| 128 loss_threshold_ = RAND_MAX * FLAGS_loss_rate; | 131 loss_threshold_ = RAND_MAX * FLAG_loss_rate; |
| 129 else | 132 else |
| 130 loss_threshold_ = 0; | 133 loss_threshold_ = 0; |
| 131 } | 134 } |
| 132 | 135 |
| 133 void TickOneMillisecond(uint32_t* action) { | 136 void TickOneMillisecond(uint32_t* action) { |
| 134 // One millisecond passed. | 137 // One millisecond passed. |
| 135 time_to_insert_packet_ms_--; | 138 time_to_insert_packet_ms_--; |
| 136 time_to_playout_audio_ms_--; | 139 time_to_playout_audio_ms_--; |
| 137 sender_clock_->AdvanceTimeMilliseconds(1); | 140 sender_clock_->AdvanceTimeMilliseconds(1); |
| 138 receiver_clock_->AdvanceTimeMilliseconds(1); | 141 receiver_clock_->AdvanceTimeMilliseconds(1); |
| 139 | 142 |
| 140 // Reset action. | 143 // Reset action. |
| 141 *action = 0; | 144 *action = 0; |
| 142 | 145 |
| 143 // Is it time to pull audio? | 146 // Is it time to pull audio? |
| 144 if (time_to_playout_audio_ms_ == 0) { | 147 if (time_to_playout_audio_ms_ == 0) { |
| 145 time_to_playout_audio_ms_ = kPlayoutPeriodMs; | 148 time_to_playout_audio_ms_ = kPlayoutPeriodMs; |
| 146 bool muted; | 149 bool muted; |
| 147 receive_acm_->PlayoutData10Ms(static_cast<int>(FLAGS_output_fs_hz), | 150 receive_acm_->PlayoutData10Ms(static_cast<int>(FLAG_output_fs_hz), |
| 148 &frame_, &muted); | 151 &frame_, &muted); |
| 149 ASSERT_FALSE(muted); | 152 ASSERT_FALSE(muted); |
| 150 fwrite(frame_.data(), sizeof(*frame_.data()), | 153 fwrite(frame_.data(), sizeof(*frame_.data()), |
| 151 frame_.samples_per_channel_ * frame_.num_channels_, pcm_out_fid_); | 154 frame_.samples_per_channel_ * frame_.num_channels_, pcm_out_fid_); |
| 152 *action |= kAudioPlayedOut; | 155 *action |= kAudioPlayedOut; |
| 153 } | 156 } |
| 154 | 157 |
| 155 // Is it time to push in next packet? | 158 // Is it time to push in next packet? |
| 156 if (time_to_insert_packet_ms_ <= .5) { | 159 if (time_to_insert_packet_ms_ <= .5) { |
| 157 *action |= kPacketPushedIn; | 160 *action |= kPacketPushedIn; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 173 uint32_t ts = SendTimestamp(); | 176 uint32_t ts = SendTimestamp(); |
| 174 int seq_num = SequenceNumber(); | 177 int seq_num = SequenceNumber(); |
| 175 bool lost = false; | 178 bool lost = false; |
| 176 channel_->set_send_timestamp(ts); | 179 channel_->set_send_timestamp(ts); |
| 177 channel_->set_sequence_number(seq_num); | 180 channel_->set_sequence_number(seq_num); |
| 178 if (loss_threshold_ > 0 && rand() < loss_threshold_) { | 181 if (loss_threshold_ > 0 && rand() < loss_threshold_) { |
| 179 channel_->set_num_packets_to_drop(1); | 182 channel_->set_num_packets_to_drop(1); |
| 180 lost = true; | 183 lost = true; |
| 181 } | 184 } |
| 182 | 185 |
| 183 if (FLAGS_verbose) { | 186 if (FLAG_verbose) { |
| 184 if (!lost) { | 187 if (!lost) { |
| 185 std::cout << "\nInserting packet number " << seq_num | 188 std::cout << "\nInserting packet number " << seq_num |
| 186 << " timestamp " << ts << std::endl; | 189 << " timestamp " << ts << std::endl; |
| 187 } else { | 190 } else { |
| 188 std::cout << "\nLost packet number " << seq_num | 191 std::cout << "\nLost packet number " << seq_num |
| 189 << " timestamp " << ts << std::endl; | 192 << " timestamp " << ts << std::endl; |
| 190 } | 193 } |
| 191 } | 194 } |
| 192 } | 195 } |
| 193 } | 196 } |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 272 double loss_threshold_; | 275 double loss_threshold_; |
| 273 | 276 |
| 274 // Output (text), sequence number, playout timestamp, time (ms) of playout, | 277 // Output (text), sequence number, playout timestamp, time (ms) of playout, |
| 275 // per line. | 278 // per line. |
| 276 FILE* playout_timing_fid_; | 279 FILE* playout_timing_fid_; |
| 277 }; | 280 }; |
| 278 | 281 |
| 279 } // webrtc | 282 } // webrtc |
| 280 | 283 |
| 281 int main(int argc, char* argv[]) { | 284 int main(int argc, char* argv[]) { |
| 282 google::ParseCommandLineFlags(&argc, &argv, true); | 285 if (rtc::FlagList::SetFlagsFromCommandLine(&argc, argv, true)) { |
| 286 return 1; |
| 287 } |
| 288 if (FLAG_help) { |
| 289 rtc::FlagList::Print(nullptr, false); |
| 290 return 0; |
| 291 } |
| 292 |
| 283 webrtc::InsertPacketWithTiming test; | 293 webrtc::InsertPacketWithTiming test; |
| 284 test.SetUp(); | 294 test.SetUp(); |
| 285 | 295 |
| 286 FILE* delay_log = NULL; | 296 FILE* delay_log = NULL; |
| 287 if (FLAGS_delay.size() > 0) { | 297 if (strlen(FLAG_delay) > 0) { |
| 288 delay_log = fopen(FLAGS_delay.c_str(), "wt"); | 298 delay_log = fopen(FLAG_delay, "wt"); |
| 289 if (delay_log == NULL) { | 299 if (delay_log == NULL) { |
| 290 std::cout << "Cannot open the file to log delay values." << std::endl; | 300 std::cout << "Cannot open the file to log delay values." << std::endl; |
| 291 exit(1); | 301 exit(1); |
| 292 } | 302 } |
| 293 } | 303 } |
| 294 | 304 |
| 295 uint32_t action_taken; | 305 uint32_t action_taken; |
| 296 int optimal_delay_ms; | 306 int optimal_delay_ms; |
| 297 int current_delay_ms; | 307 int current_delay_ms; |
| 298 while (test.HasPackets()) { | 308 while (test.HasPackets()) { |
| 299 test.TickOneMillisecond(&action_taken); | 309 test.TickOneMillisecond(&action_taken); |
| 300 | 310 |
| 301 if (action_taken != 0) { | 311 if (action_taken != 0) { |
| 302 test.Delay(&optimal_delay_ms, ¤t_delay_ms); | 312 test.Delay(&optimal_delay_ms, ¤t_delay_ms); |
| 303 if (delay_log != NULL) { | 313 if (delay_log != NULL) { |
| 304 fprintf(delay_log, "%3d %3d\n", optimal_delay_ms, current_delay_ms); | 314 fprintf(delay_log, "%3d %3d\n", optimal_delay_ms, current_delay_ms); |
| 305 } | 315 } |
| 306 } | 316 } |
| 307 } | 317 } |
| 308 std::cout << std::endl; | 318 std::cout << std::endl; |
| 309 test.TearDown(); | 319 test.TearDown(); |
| 310 if (delay_log != NULL) | 320 if (delay_log != NULL) |
| 311 fclose(delay_log); | 321 fclose(delay_log); |
| 312 } | 322 } |
| OLD | NEW |