Chromium Code Reviews| 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 |