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 |
(...skipping 12 matching lines...) Expand all Loading... | |
23 | 23 |
24 #include "google/gflags.h" | 24 #include "google/gflags.h" |
25 #include "webrtc/base/checks.h" | 25 #include "webrtc/base/checks.h" |
26 #include "webrtc/base/scoped_ptr.h" | 26 #include "webrtc/base/scoped_ptr.h" |
27 #include "webrtc/modules/audio_coding/codecs/pcm16b/include/pcm16b.h" | 27 #include "webrtc/modules/audio_coding/codecs/pcm16b/include/pcm16b.h" |
28 #include "webrtc/modules/audio_coding/neteq/interface/neteq.h" | 28 #include "webrtc/modules/audio_coding/neteq/interface/neteq.h" |
29 #include "webrtc/modules/audio_coding/neteq/tools/input_audio_file.h" | 29 #include "webrtc/modules/audio_coding/neteq/tools/input_audio_file.h" |
30 #include "webrtc/modules/audio_coding/neteq/tools/output_audio_file.h" | 30 #include "webrtc/modules/audio_coding/neteq/tools/output_audio_file.h" |
31 #include "webrtc/modules/audio_coding/neteq/tools/output_wav_file.h" | 31 #include "webrtc/modules/audio_coding/neteq/tools/output_wav_file.h" |
32 #include "webrtc/modules/audio_coding/neteq/tools/packet.h" | 32 #include "webrtc/modules/audio_coding/neteq/tools/packet.h" |
33 #include "webrtc/modules/audio_coding/neteq/tools/rtc_event_log_source.h" | |
33 #include "webrtc/modules/audio_coding/neteq/tools/rtp_file_source.h" | 34 #include "webrtc/modules/audio_coding/neteq/tools/rtp_file_source.h" |
34 #include "webrtc/modules/interface/module_common_types.h" | 35 #include "webrtc/modules/interface/module_common_types.h" |
35 #include "webrtc/system_wrappers/interface/trace.h" | 36 #include "webrtc/system_wrappers/interface/trace.h" |
36 #include "webrtc/test/testsupport/fileutils.h" | 37 #include "webrtc/test/testsupport/fileutils.h" |
37 #include "webrtc/typedefs.h" | 38 #include "webrtc/typedefs.h" |
38 | 39 |
39 using webrtc::NetEq; | 40 using webrtc::NetEq; |
40 using webrtc::WebRtcRTPHeader; | 41 using webrtc::WebRtcRTPHeader; |
41 | 42 |
42 namespace { | 43 namespace { |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
130 const bool cn_swb48_dummy = | 131 const bool cn_swb48_dummy = |
131 google::RegisterFlagValidator(&FLAGS_cn_swb48, &ValidatePayloadType); | 132 google::RegisterFlagValidator(&FLAGS_cn_swb48, &ValidatePayloadType); |
132 DEFINE_bool(codec_map, false, "Prints the mapping between RTP payload type and " | 133 DEFINE_bool(codec_map, false, "Prints the mapping between RTP payload type and " |
133 "codec"); | 134 "codec"); |
134 DEFINE_string(replacement_audio_file, "", | 135 DEFINE_string(replacement_audio_file, "", |
135 "A PCM file that will be used to populate ""dummy"" RTP packets"); | 136 "A PCM file that will be used to populate ""dummy"" RTP packets"); |
136 DEFINE_string(ssrc, | 137 DEFINE_string(ssrc, |
137 "", | 138 "", |
138 "Only use packets with this SSRC (decimal or hex, the latter " | 139 "Only use packets with this SSRC (decimal or hex, the latter " |
139 "starting with 0x)"); | 140 "starting with 0x)"); |
141 DEFINE_bool(rtc_event_log, | |
142 false, | |
143 "Enables using a stored RtcEventLog as input " | |
hlundin-webrtc
2015/08/28 12:06:24
No need to break this line.
ivoc
2015/09/01 10:03:50
Fixed. The string was longer before and I forgot t
| |
144 "file."); | |
140 const bool hex_ssrc_dummy = | 145 const bool hex_ssrc_dummy = |
141 google::RegisterFlagValidator(&FLAGS_ssrc, &ValidateSsrcValue); | 146 google::RegisterFlagValidator(&FLAGS_ssrc, &ValidateSsrcValue); |
142 | 147 |
143 // Maps a codec type to a printable name string. | 148 // Maps a codec type to a printable name string. |
144 std::string CodecName(webrtc::NetEqDecoder codec) { | 149 std::string CodecName(webrtc::NetEqDecoder codec) { |
145 switch (codec) { | 150 switch (codec) { |
146 case webrtc::kDecoderPCMu: | 151 case webrtc::kDecoderPCMu: |
147 return "PCM-u"; | 152 return "PCM-u"; |
148 case webrtc::kDecoderPCMa: | 153 case webrtc::kDecoderPCMa: |
149 return "PCM-a"; | 154 return "PCM-a"; |
(...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
377 if (FLAGS_codec_map) { | 382 if (FLAGS_codec_map) { |
378 // We have already printed the codec map. Just end the program. | 383 // We have already printed the codec map. Just end the program. |
379 return 0; | 384 return 0; |
380 } | 385 } |
381 // Print usage information. | 386 // Print usage information. |
382 std::cout << google::ProgramUsage(); | 387 std::cout << google::ProgramUsage(); |
383 return 0; | 388 return 0; |
384 } | 389 } |
385 | 390 |
386 printf("Input file: %s\n", argv[1]); | 391 printf("Input file: %s\n", argv[1]); |
387 rtc::scoped_ptr<webrtc::test::RtpFileSource> file_source( | 392 rtc::scoped_ptr<webrtc::test::PacketSource> file_source; |
388 webrtc::test::RtpFileSource::Create(argv[1])); | 393 webrtc::test::RtcEventLogSource* event_log_source = nullptr; |
394 if (FLAGS_rtc_event_log) { | |
395 event_log_source = webrtc::test::RtcEventLogSource::Create(argv[1]); | |
minyue-webrtc
2015/08/28 14:50:21
Is there a way to detect the format automatically?
ivoc
2015/09/01 10:03:50
Good idea. I added this feature by checking if the
| |
396 file_source.reset(event_log_source); | |
397 } else { | |
398 file_source.reset(webrtc::test::RtpFileSource::Create(argv[1])); | |
399 } | |
400 | |
389 assert(file_source.get()); | 401 assert(file_source.get()); |
390 | 402 |
391 // Check if an SSRC value was provided. | 403 // Check if an SSRC value was provided. |
392 if (!FLAGS_ssrc.empty()) { | 404 if (!FLAGS_ssrc.empty()) { |
393 uint32_t ssrc; | 405 uint32_t ssrc; |
394 CHECK(ParseSsrc(FLAGS_ssrc, &ssrc)) << "Flag verification has failed."; | 406 CHECK(ParseSsrc(FLAGS_ssrc, &ssrc)) << "Flag verification has failed."; |
395 file_source->SelectSsrc(ssrc); | 407 file_source->SelectSsrc(ssrc); |
396 } | 408 } |
397 | 409 |
398 // Check if a replacement audio file was provided, and if so, open it. | 410 // Check if a replacement audio file was provided, and if so, open it. |
399 bool replace_payload = false; | 411 bool replace_payload = false; |
400 rtc::scoped_ptr<webrtc::test::InputAudioFile> replacement_audio_file; | 412 rtc::scoped_ptr<webrtc::test::InputAudioFile> replacement_audio_file; |
401 if (!FLAGS_replacement_audio_file.empty()) { | 413 if (!FLAGS_replacement_audio_file.empty()) { |
402 replacement_audio_file.reset( | 414 replacement_audio_file.reset( |
403 new webrtc::test::InputAudioFile(FLAGS_replacement_audio_file)); | 415 new webrtc::test::InputAudioFile(FLAGS_replacement_audio_file)); |
404 replace_payload = true; | 416 replace_payload = true; |
405 } | 417 } |
406 | 418 |
407 // Read first packet. | 419 // Read first packet. |
408 rtc::scoped_ptr<webrtc::test::Packet> packet(file_source->NextPacket()); | 420 rtc::scoped_ptr<webrtc::test::Packet> packet(file_source->NextPacket()); |
409 if (!packet) { | 421 if (!packet) { |
410 printf( | 422 printf( |
411 "Warning: input file is empty, or the filters did not match any " | 423 "Warning: input file is empty, or the filters did not match any " |
412 "packets\n"); | 424 "packets\n"); |
413 webrtc::Trace::ReturnTrace(); | 425 webrtc::Trace::ReturnTrace(); |
414 return 0; | 426 return 0; |
415 } | 427 } |
416 bool packet_available = true; | 428 bool packet_available = true; |
429 bool output_event_available = true; | |
minyue-webrtc
2015/08/28 16:54:17
I think 428 and 429 are too far, move to 500 if po
ivoc
2015/09/01 10:03:50
Done.
| |
417 | 430 |
418 // Check the sample rate. | 431 // Check the sample rate. |
419 int sample_rate_hz = CodecSampleRate(packet->header().payloadType); | 432 int sample_rate_hz = CodecSampleRate(packet->header().payloadType); |
420 if (sample_rate_hz <= 0) { | 433 if (sample_rate_hz <= 0) { |
421 printf("Warning: Invalid sample rate from RTP packet.\n"); | 434 printf("Warning: Invalid sample rate from RTP packet.\n"); |
422 webrtc::Trace::ReturnTrace(); | 435 webrtc::Trace::ReturnTrace(); |
423 return 0; | 436 return 0; |
424 } | 437 } |
425 | 438 |
426 // Open the output file now that we know the sample rate. (Rate is only needed | 439 // Open the output file now that we know the sample rate. (Rate is only needed |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
478 int start_time_ms = packet->time_ms(); | 491 int start_time_ms = packet->time_ms(); |
479 int time_now_ms = packet->time_ms(); | 492 int time_now_ms = packet->time_ms(); |
480 int next_input_time_ms = time_now_ms; | 493 int next_input_time_ms = time_now_ms; |
481 int next_output_time_ms = time_now_ms; | 494 int next_output_time_ms = time_now_ms; |
482 if (time_now_ms % kOutputBlockSizeMs != 0) { | 495 if (time_now_ms % kOutputBlockSizeMs != 0) { |
483 // Make sure that next_output_time_ms is rounded up to the next multiple | 496 // Make sure that next_output_time_ms is rounded up to the next multiple |
484 // of kOutputBlockSizeMs. (Legacy bit-exactness.) | 497 // of kOutputBlockSizeMs. (Legacy bit-exactness.) |
485 next_output_time_ms += | 498 next_output_time_ms += |
486 kOutputBlockSizeMs - time_now_ms % kOutputBlockSizeMs; | 499 kOutputBlockSizeMs - time_now_ms % kOutputBlockSizeMs; |
487 } | 500 } |
488 while (packet_available) { | 501 if (FLAGS_rtc_event_log) { |
502 next_output_time_ms = event_log_source->NextAudioOutputEventMs(); | |
minyue-webrtc
2015/08/28 16:54:17
why not keeping -1 or let NextAudioOutputEventMs g
ivoc
2015/09/01 10:03:50
Keeping it at -1 would not work because later on t
| |
503 if (next_output_time_ms == -1) { | |
504 output_event_available = false; | |
505 next_output_time_ms = INT_MAX; | |
506 } | |
507 start_time_ms = time_now_ms = | |
508 std::min(next_input_time_ms, next_output_time_ms); | |
509 } | |
510 while (packet_available || output_event_available) { | |
489 // Check if it is time to insert packet. | 511 // Check if it is time to insert packet. |
490 while (time_now_ms >= next_input_time_ms && packet_available) { | 512 while (time_now_ms >= next_input_time_ms && packet_available) { |
491 assert(packet->virtual_payload_length_bytes() > 0); | 513 assert(packet->virtual_payload_length_bytes() > 0); |
492 // Parse RTP header. | 514 // Parse RTP header. |
493 WebRtcRTPHeader rtp_header; | 515 WebRtcRTPHeader rtp_header; |
494 packet->ConvertHeader(&rtp_header); | 516 packet->ConvertHeader(&rtp_header); |
495 const uint8_t* payload_ptr = packet->payload(); | 517 const uint8_t* payload_ptr = packet->payload(); |
496 size_t payload_len = packet->payload_length_bytes(); | 518 size_t payload_len = packet->payload_length_bytes(); |
497 if (replace_payload) { | 519 if (replace_payload) { |
498 payload_len = ReplacePayload(replacement_audio_file.get(), | 520 payload_len = ReplacePayload(replacement_audio_file.get(), |
(...skipping 29 matching lines...) Expand all Loading... | |
528 << std::endl; | 550 << std::endl; |
529 std::cerr << " TS = " << rtp_header.header.timestamp << std::endl; | 551 std::cerr << " TS = " << rtp_header.header.timestamp << std::endl; |
530 } | 552 } |
531 } | 553 } |
532 | 554 |
533 // Get next packet from file. | 555 // Get next packet from file. |
534 webrtc::test::Packet* temp_packet = file_source->NextPacket(); | 556 webrtc::test::Packet* temp_packet = file_source->NextPacket(); |
535 if (temp_packet) { | 557 if (temp_packet) { |
536 packet.reset(temp_packet); | 558 packet.reset(temp_packet); |
537 } else { | 559 } else { |
560 // Set next input time to INT_MAX to prevent the time_now_ms from | |
561 // becoming stuck at the final value. | |
562 next_input_time_ms = INT_MAX; | |
538 packet_available = false; | 563 packet_available = false; |
564 break; | |
hlundin-webrtc
2015/08/28 12:06:24
What are you breaking out of, and why do you have
ivoc
2015/09/01 10:03:50
This break is for the while loop on line 512, it i
| |
539 } | 565 } |
540 if (replace_payload) { | 566 if (replace_payload) { |
hlundin-webrtc
2015/08/28 12:06:25
Did you try to run with a replacement audio file?
ivoc
2015/09/01 10:03:50
It seems like next_input_time_ms is not used at al
hlundin-webrtc
2015/09/02 08:48:51
Acknowledged.
| |
541 // At this point |packet| contains the packet *after* |next_packet|. | 567 // At this point |packet| contains the packet *after* |next_packet|. |
542 // Swap Packet objects between |packet| and |next_packet|. | 568 // Swap Packet objects between |packet| and |next_packet|. |
543 packet.swap(next_packet); | 569 packet.swap(next_packet); |
544 // Swap the status indicators unless they're already the same. | 570 // Swap the status indicators unless they're already the same. |
545 if (packet_available != next_packet_available) { | 571 if (packet_available != next_packet_available) { |
546 packet_available = !packet_available; | 572 packet_available = !packet_available; |
547 next_packet_available = !next_packet_available; | 573 next_packet_available = !next_packet_available; |
548 } | 574 } |
549 } | 575 } |
550 next_input_time_ms = packet->time_ms(); | 576 next_input_time_ms = packet->time_ms(); |
551 } | 577 } |
552 | 578 |
553 // Check if it is time to get output audio. | 579 // Check if it is time to get output audio. |
554 if (time_now_ms >= next_output_time_ms) { | 580 while (time_now_ms >= next_output_time_ms && output_event_available) { |
555 static const int kOutDataLen = | 581 static const int kOutDataLen = |
556 kOutputBlockSizeMs * kMaxSamplesPerMs * kMaxChannels; | 582 kOutputBlockSizeMs * kMaxSamplesPerMs * kMaxChannels; |
557 int16_t out_data[kOutDataLen]; | 583 int16_t out_data[kOutDataLen]; |
558 int num_channels; | 584 int num_channels; |
559 int samples_per_channel; | 585 int samples_per_channel; |
560 int error = neteq->GetAudio(kOutDataLen, out_data, &samples_per_channel, | 586 int error = neteq->GetAudio(kOutDataLen, out_data, &samples_per_channel, |
561 &num_channels, NULL); | 587 &num_channels, NULL); |
562 if (error != NetEq::kOK) { | 588 if (error != NetEq::kOK) { |
563 std::cerr << "GetAudio returned error code " << | 589 std::cerr << "GetAudio returned error code " << |
564 neteq->LastError() << std::endl; | 590 neteq->LastError() << std::endl; |
565 } else { | 591 } else { |
566 // Calculate sample rate from output size. | 592 // Calculate sample rate from output size. |
567 sample_rate_hz = 1000 * samples_per_channel / kOutputBlockSizeMs; | 593 sample_rate_hz = 1000 * samples_per_channel / kOutputBlockSizeMs; |
568 } | 594 } |
569 | 595 |
570 // Write to file. | 596 // Write to file. |
571 // TODO(hlundin): Make writing to file optional. | 597 // TODO(hlundin): Make writing to file optional. |
572 size_t write_len = samples_per_channel * num_channels; | 598 size_t write_len = samples_per_channel * num_channels; |
573 if (!output->WriteArray(out_data, write_len)) { | 599 if (!output->WriteArray(out_data, write_len)) { |
574 std::cerr << "Error while writing to file" << std::endl; | 600 std::cerr << "Error while writing to file" << std::endl; |
575 webrtc::Trace::ReturnTrace(); | 601 webrtc::Trace::ReturnTrace(); |
576 exit(1); | 602 exit(1); |
577 } | 603 } |
578 next_output_time_ms += kOutputBlockSizeMs; | 604 next_output_time_ms += kOutputBlockSizeMs; |
605 if (FLAGS_rtc_event_log) { | |
606 next_output_time_ms = event_log_source->NextAudioOutputEventMs(); | |
607 if (next_output_time_ms == -1) { | |
608 output_event_available = false; | |
609 // Set the next output time to INT_MAX to prevent the time_now_ms | |
610 // from being set to -1. | |
611 next_output_time_ms = INT_MAX; | |
612 break; | |
hlundin-webrtc
2015/08/28 12:06:24
Same as the break above.
ivoc
2015/09/01 10:03:50
Here the break is for the while loop on line 580,
| |
613 } | |
614 } else { | |
615 if (!packet_available) { | |
616 output_event_available = false; | |
617 } | |
618 } | |
579 } | 619 } |
580 // Advance time to next event. | 620 // Advance time to next event. |
581 time_now_ms = std::min(next_input_time_ms, next_output_time_ms); | 621 time_now_ms = std::min(next_input_time_ms, next_output_time_ms); |
582 } | 622 } |
583 | |
584 printf("Simulation done\n"); | 623 printf("Simulation done\n"); |
585 printf("Produced %i ms of audio\n", time_now_ms - start_time_ms); | 624 printf("Produced %i ms of audio\n", time_now_ms - start_time_ms); |
586 | 625 |
587 delete neteq; | 626 delete neteq; |
588 webrtc::Trace::ReturnTrace(); | 627 webrtc::Trace::ReturnTrace(); |
589 return 0; | 628 return 0; |
590 } | 629 } |
OLD | NEW |