Index: webrtc/modules/audio_coding/neteq/tools/neteq_rtpplay.cc |
diff --git a/webrtc/modules/audio_coding/neteq/tools/neteq_rtpplay.cc b/webrtc/modules/audio_coding/neteq/tools/neteq_rtpplay.cc |
index 1c0807843f4f3aa687078c8c01d51a2840419da1..d4219767cfa90b302318e71245163a4a168172ec 100644 |
--- a/webrtc/modules/audio_coding/neteq/tools/neteq_rtpplay.cc |
+++ b/webrtc/modules/audio_coding/neteq/tools/neteq_rtpplay.cc |
@@ -19,6 +19,7 @@ |
#include <algorithm> |
#include <iostream> |
+#include <limits> |
#include <string> |
#include "google/gflags.h" |
@@ -31,9 +32,11 @@ |
#include "webrtc/modules/audio_coding/neteq/tools/output_audio_file.h" |
#include "webrtc/modules/audio_coding/neteq/tools/output_wav_file.h" |
#include "webrtc/modules/audio_coding/neteq/tools/packet.h" |
+#include "webrtc/modules/audio_coding/neteq/tools/rtc_event_log_source.h" |
#include "webrtc/modules/audio_coding/neteq/tools/rtp_file_source.h" |
#include "webrtc/modules/interface/module_common_types.h" |
#include "webrtc/system_wrappers/interface/trace.h" |
+#include "webrtc/test/rtp_file_reader.h" |
#include "webrtc/test/testsupport/fileutils.h" |
#include "webrtc/typedefs.h" |
@@ -385,8 +388,30 @@ int main(int argc, char* argv[]) { |
} |
printf("Input file: %s\n", argv[1]); |
- rtc::scoped_ptr<webrtc::test::RtpFileSource> file_source( |
- webrtc::test::RtpFileSource::Create(argv[1])); |
+ |
+ // TODO(ivoc): Modify the RtpFileSource::Create and RtcEventLogSource::Create |
+ // functions to return a nullptr on failure instead of crashing |
+ // the program. |
+ |
+ // This temporary solution uses a RtpFileReader directly to check if the file |
+ // is a valid RtpDump file. |
+ bool is_rtp_dump = false; |
+ { |
+ rtc::scoped_ptr<webrtc::test::RtpFileReader> rtp_reader( |
+ webrtc::test::RtpFileReader::Create( |
+ webrtc::test::RtpFileReader::kRtpDump, argv[1])); |
+ if (rtp_reader) |
+ is_rtp_dump = true; |
+ } |
+ rtc::scoped_ptr<webrtc::test::PacketSource> file_source; |
+ webrtc::test::RtcEventLogSource* event_log_source = nullptr; |
+ if (is_rtp_dump) { |
+ file_source.reset(webrtc::test::RtpFileSource::Create(argv[1])); |
+ } else { |
+ event_log_source = webrtc::test::RtcEventLogSource::Create(argv[1]); |
+ file_source.reset(event_log_source); |
+ } |
+ |
assert(file_source.get()); |
// Check if an SSRC value was provided. |
@@ -414,7 +439,12 @@ int main(int argc, char* argv[]) { |
webrtc::Trace::ReturnTrace(); |
return 0; |
} |
- bool packet_available = true; |
+ if (packet->payload_length_bytes() == 0 && !replace_payload) { |
+ std::cerr << "Warning: input file contains header-only packets, but no " |
+ << "replacement file is specified." << std::endl; |
+ webrtc::Trace::ReturnTrace(); |
+ return -1; |
+ } |
// Check the sample rate. |
int sample_rate_hz = CodecSampleRate(packet->header().payloadType); |
@@ -476,17 +506,29 @@ int main(int argc, char* argv[]) { |
// This is the main simulation loop. |
// Set the simulation clock to start immediately with the first packet. |
- int start_time_ms = packet->time_ms(); |
- int time_now_ms = packet->time_ms(); |
- int next_input_time_ms = time_now_ms; |
- int next_output_time_ms = time_now_ms; |
+ int64_t start_time_ms = rtc::checked_cast<int64_t>(packet->time_ms()); |
+ int64_t time_now_ms = start_time_ms; |
+ int64_t next_input_time_ms = time_now_ms; |
+ int64_t next_output_time_ms = time_now_ms; |
if (time_now_ms % kOutputBlockSizeMs != 0) { |
// Make sure that next_output_time_ms is rounded up to the next multiple |
// of kOutputBlockSizeMs. (Legacy bit-exactness.) |
next_output_time_ms += |
kOutputBlockSizeMs - time_now_ms % kOutputBlockSizeMs; |
} |
- while (packet_available) { |
+ |
+ bool packet_available = true; |
+ bool output_event_available = true; |
+ if (!is_rtp_dump) { |
+ next_output_time_ms = event_log_source->NextAudioOutputEventMs(); |
+ if (next_output_time_ms == std::numeric_limits<int64_t>::max()) |
+ output_event_available = false; |
+ start_time_ms = time_now_ms = |
+ std::min(next_input_time_ms, next_output_time_ms); |
+ } |
+ while (packet_available || output_event_available) { |
+ // Advance time to next event. |
+ time_now_ms = std::min(next_input_time_ms, next_output_time_ms); |
// Check if it is time to insert packet. |
while (time_now_ms >= next_input_time_ms && packet_available) { |
assert(packet->virtual_payload_length_bytes() > 0); |
@@ -505,11 +547,9 @@ int main(int argc, char* argv[]) { |
next_packet.get()); |
payload_ptr = payload.get(); |
} |
- int error = |
- neteq->InsertPacket(rtp_header, |
- payload_ptr, |
- payload_len, |
- packet->time_ms() * sample_rate_hz / 1000); |
+ int error = neteq->InsertPacket( |
+ rtp_header, payload_ptr, payload_len, |
+ static_cast<uint32_t>(packet->time_ms() * sample_rate_hz / 1000)); |
if (error != NetEq::kOK) { |
if (neteq->LastError() == NetEq::kUnknownRtpPayloadType) { |
std::cerr << "RTP Payload type " |
@@ -535,24 +575,27 @@ int main(int argc, char* argv[]) { |
webrtc::test::Packet* temp_packet = file_source->NextPacket(); |
if (temp_packet) { |
packet.reset(temp_packet); |
+ if (replace_payload) { |
+ // At this point |packet| contains the packet *after* |next_packet|. |
+ // Swap Packet objects between |packet| and |next_packet|. |
+ packet.swap(next_packet); |
+ // Swap the status indicators unless they're already the same. |
+ if (packet_available != next_packet_available) { |
+ packet_available = !packet_available; |
+ next_packet_available = !next_packet_available; |
+ } |
+ } |
+ next_input_time_ms = rtc::checked_cast<int64_t>(packet->time_ms()); |
} else { |
+ // Set next input time to the maximum value of int64_t to prevent the |
+ // time_now_ms from becoming stuck at the final value. |
+ next_input_time_ms = std::numeric_limits<int64_t>::max(); |
packet_available = false; |
} |
- if (replace_payload) { |
- // At this point |packet| contains the packet *after* |next_packet|. |
- // Swap Packet objects between |packet| and |next_packet|. |
- packet.swap(next_packet); |
- // Swap the status indicators unless they're already the same. |
- if (packet_available != next_packet_available) { |
- packet_available = !packet_available; |
- next_packet_available = !next_packet_available; |
- } |
- } |
- next_input_time_ms = packet->time_ms(); |
} |
// Check if it is time to get output audio. |
- if (time_now_ms >= next_output_time_ms) { |
+ while (time_now_ms >= next_output_time_ms && output_event_available) { |
static const size_t kOutDataLen = |
kOutputBlockSizeMs * kMaxSamplesPerMs * kMaxChannels; |
int16_t out_data[kOutDataLen]; |
@@ -577,14 +620,20 @@ int main(int argc, char* argv[]) { |
webrtc::Trace::ReturnTrace(); |
exit(1); |
} |
- next_output_time_ms += kOutputBlockSizeMs; |
+ if (is_rtp_dump) { |
+ next_output_time_ms += kOutputBlockSizeMs; |
+ if (!packet_available) |
+ output_event_available = false; |
+ } else { |
+ next_output_time_ms = event_log_source->NextAudioOutputEventMs(); |
+ if (next_output_time_ms == std::numeric_limits<int64_t>::max()) |
+ output_event_available = false; |
+ } |
} |
- // Advance time to next event. |
- time_now_ms = std::min(next_input_time_ms, next_output_time_ms); |
} |
- |
printf("Simulation done\n"); |
- printf("Produced %i ms of audio\n", time_now_ms - start_time_ms); |
+ printf("Produced %i ms of audio\n", |
+ static_cast<int>(time_now_ms - start_time_ms)); |
delete neteq; |
webrtc::Trace::ReturnTrace(); |