Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(198)

Side by Side Diff: webrtc/modules/audio_coding/neteq/tools/neteq_rtpplay.cc

Issue 1316903002: Update to the neteq_rtpplay utility to support RtcEventLog input files. (Closed) Base URL: https://chromium.googlesource.com/external/webrtc.git@master
Patch Set: Replaced filetype detection code, and various small improvements. Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 // TODO(hlundin): The functionality in this file should be moved into one or 11 // TODO(hlundin): The functionality in this file should be moved into one or
12 // several classes. 12 // several classes.
13 13
14 #include <assert.h> 14 #include <assert.h>
15 #include <errno.h> 15 #include <errno.h>
16 #include <limits.h> // For ULONG_MAX returned by strtoul. 16 #include <limits.h> // For ULONG_MAX returned by strtoul.
17 #include <stdio.h> 17 #include <stdio.h>
18 #include <stdlib.h> // For strtoul. 18 #include <stdlib.h> // For strtoul.
19 19
20 #include <algorithm> 20 #include <algorithm>
21 #include <iostream> 21 #include <iostream>
22 #include <limits>
22 #include <string> 23 #include <string>
23 24
24 #include "google/gflags.h" 25 #include "google/gflags.h"
25 #include "webrtc/base/checks.h" 26 #include "webrtc/base/checks.h"
27 #include "webrtc/base/safe_conversions.h"
26 #include "webrtc/base/scoped_ptr.h" 28 #include "webrtc/base/scoped_ptr.h"
27 #include "webrtc/modules/audio_coding/codecs/pcm16b/include/pcm16b.h" 29 #include "webrtc/modules/audio_coding/codecs/pcm16b/include/pcm16b.h"
28 #include "webrtc/modules/audio_coding/neteq/interface/neteq.h" 30 #include "webrtc/modules/audio_coding/neteq/interface/neteq.h"
29 #include "webrtc/modules/audio_coding/neteq/tools/input_audio_file.h" 31 #include "webrtc/modules/audio_coding/neteq/tools/input_audio_file.h"
30 #include "webrtc/modules/audio_coding/neteq/tools/output_audio_file.h" 32 #include "webrtc/modules/audio_coding/neteq/tools/output_audio_file.h"
31 #include "webrtc/modules/audio_coding/neteq/tools/output_wav_file.h" 33 #include "webrtc/modules/audio_coding/neteq/tools/output_wav_file.h"
32 #include "webrtc/modules/audio_coding/neteq/tools/packet.h" 34 #include "webrtc/modules/audio_coding/neteq/tools/packet.h"
35 #include "webrtc/modules/audio_coding/neteq/tools/rtc_event_log_source.h"
33 #include "webrtc/modules/audio_coding/neteq/tools/rtp_file_source.h" 36 #include "webrtc/modules/audio_coding/neteq/tools/rtp_file_source.h"
34 #include "webrtc/modules/interface/module_common_types.h" 37 #include "webrtc/modules/interface/module_common_types.h"
35 #include "webrtc/system_wrappers/interface/trace.h" 38 #include "webrtc/system_wrappers/interface/trace.h"
39 #include "webrtc/test/rtp_file_reader.h"
36 #include "webrtc/test/testsupport/fileutils.h" 40 #include "webrtc/test/testsupport/fileutils.h"
37 #include "webrtc/typedefs.h" 41 #include "webrtc/typedefs.h"
38 42
39 using webrtc::NetEq; 43 using webrtc::NetEq;
40 using webrtc::WebRtcRTPHeader; 44 using webrtc::WebRtcRTPHeader;
41 45
42 namespace { 46 namespace {
43 47
44 // Parses the input string for a valid SSRC (at the start of the string). If a 48 // Parses the input string for a valid SSRC (at the start of the string). If a
45 // valid SSRC is found, it is written to the output variable |ssrc|, and true is 49 // valid SSRC is found, it is written to the output variable |ssrc|, and true is
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after
377 if (FLAGS_codec_map) { 381 if (FLAGS_codec_map) {
378 // We have already printed the codec map. Just end the program. 382 // We have already printed the codec map. Just end the program.
379 return 0; 383 return 0;
380 } 384 }
381 // Print usage information. 385 // Print usage information.
382 std::cout << google::ProgramUsage(); 386 std::cout << google::ProgramUsage();
383 return 0; 387 return 0;
384 } 388 }
385 389
386 printf("Input file: %s\n", argv[1]); 390 printf("Input file: %s\n", argv[1]);
387 rtc::scoped_ptr<webrtc::test::RtpFileSource> file_source( 391
388 webrtc::test::RtpFileSource::Create(argv[1])); 392 // TODO(ivoc): Modify the RtpFileSource::Create and RtcEventLogSource::Create
393 // functions to return a nullptr on failure instead of crashing
394 // the program.
395
396 // This temporary solution uses a RtpFileReader directly to check if the file
397 // is a valid RtpDump file.
398 bool is_rtp_dump = false;
399 {
400 rtc::scoped_ptr<webrtc::test::RtpFileReader> rtp_reader(
401 webrtc::test::RtpFileReader::Create(
402 webrtc::test::RtpFileReader::kRtpDump, argv[1]));
403 if (rtp_reader)
404 is_rtp_dump = true;
405 }
406 rtc::scoped_ptr<webrtc::test::PacketSource> file_source;
407 webrtc::test::RtcEventLogSource* event_log_source = nullptr;
408 if (is_rtp_dump) {
409 file_source.reset(webrtc::test::RtpFileSource::Create(argv[1]));
410 } else {
411 event_log_source = webrtc::test::RtcEventLogSource::Create(argv[1]);
412 file_source.reset(event_log_source);
413 }
414
389 assert(file_source.get()); 415 assert(file_source.get());
390 416
391 // Check if an SSRC value was provided. 417 // Check if an SSRC value was provided.
392 if (!FLAGS_ssrc.empty()) { 418 if (!FLAGS_ssrc.empty()) {
393 uint32_t ssrc; 419 uint32_t ssrc;
394 CHECK(ParseSsrc(FLAGS_ssrc, &ssrc)) << "Flag verification has failed."; 420 CHECK(ParseSsrc(FLAGS_ssrc, &ssrc)) << "Flag verification has failed.";
395 file_source->SelectSsrc(ssrc); 421 file_source->SelectSsrc(ssrc);
396 } 422 }
397 423
398 // Check if a replacement audio file was provided, and if so, open it. 424 // Check if a replacement audio file was provided, and if so, open it.
399 bool replace_payload = false; 425 bool replace_payload = false;
400 rtc::scoped_ptr<webrtc::test::InputAudioFile> replacement_audio_file; 426 rtc::scoped_ptr<webrtc::test::InputAudioFile> replacement_audio_file;
401 if (!FLAGS_replacement_audio_file.empty()) { 427 if (!FLAGS_replacement_audio_file.empty()) {
402 replacement_audio_file.reset( 428 replacement_audio_file.reset(
403 new webrtc::test::InputAudioFile(FLAGS_replacement_audio_file)); 429 new webrtc::test::InputAudioFile(FLAGS_replacement_audio_file));
404 replace_payload = true; 430 replace_payload = true;
405 } 431 }
406 432
407 // Read first packet. 433 // Read first packet.
408 rtc::scoped_ptr<webrtc::test::Packet> packet(file_source->NextPacket()); 434 rtc::scoped_ptr<webrtc::test::Packet> packet(file_source->NextPacket());
409 if (!packet) { 435 if (!packet) {
410 printf( 436 printf(
411 "Warning: input file is empty, or the filters did not match any " 437 "Warning: input file is empty, or the filters did not match any "
412 "packets\n"); 438 "packets\n");
413 webrtc::Trace::ReturnTrace(); 439 webrtc::Trace::ReturnTrace();
414 return 0; 440 return 0;
415 } 441 }
416 bool packet_available = true; 442 if (packet->payload_length_bytes() == 0 && !replace_payload) {
443 std::cerr << "Warning: input file contains header-only packets, but no "
444 << "replacement file is specified." << std::endl;
445 webrtc::Trace::ReturnTrace();
446 return -1;
447 }
417 448
418 // Check the sample rate. 449 // Check the sample rate.
419 int sample_rate_hz = CodecSampleRate(packet->header().payloadType); 450 int sample_rate_hz = CodecSampleRate(packet->header().payloadType);
420 if (sample_rate_hz <= 0) { 451 if (sample_rate_hz <= 0) {
421 printf("Warning: Invalid sample rate from RTP packet.\n"); 452 printf("Warning: Invalid sample rate from RTP packet.\n");
422 webrtc::Trace::ReturnTrace(); 453 webrtc::Trace::ReturnTrace();
423 return 0; 454 return 0;
424 } 455 }
425 456
426 // Open the output file now that we know the sample rate. (Rate is only needed 457 // Open the output file now that we know the sample rate. (Rate is only needed
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
468 replacement_audio.reset(new int16_t[input_frame_size_timestamps]); 499 replacement_audio.reset(new int16_t[input_frame_size_timestamps]);
469 payload_mem_size_bytes = 2 * input_frame_size_timestamps; 500 payload_mem_size_bytes = 2 * input_frame_size_timestamps;
470 payload.reset(new uint8_t[payload_mem_size_bytes]); 501 payload.reset(new uint8_t[payload_mem_size_bytes]);
471 next_packet.reset(file_source->NextPacket()); 502 next_packet.reset(file_source->NextPacket());
472 assert(next_packet); 503 assert(next_packet);
473 next_packet_available = true; 504 next_packet_available = true;
474 } 505 }
475 506
476 // This is the main simulation loop. 507 // This is the main simulation loop.
477 // Set the simulation clock to start immediately with the first packet. 508 // Set the simulation clock to start immediately with the first packet.
478 int start_time_ms = packet->time_ms(); 509 int64_t start_time_ms = rtc::checked_cast<int64_t>(packet->time_ms());
479 int time_now_ms = packet->time_ms(); 510 int64_t time_now_ms = start_time_ms;
480 int next_input_time_ms = time_now_ms; 511 int64_t next_input_time_ms = time_now_ms;
481 int next_output_time_ms = time_now_ms; 512 int64_t next_output_time_ms = time_now_ms;
482 if (time_now_ms % kOutputBlockSizeMs != 0) { 513 if (time_now_ms % kOutputBlockSizeMs != 0) {
483 // Make sure that next_output_time_ms is rounded up to the next multiple 514 // Make sure that next_output_time_ms is rounded up to the next multiple
484 // of kOutputBlockSizeMs. (Legacy bit-exactness.) 515 // of kOutputBlockSizeMs. (Legacy bit-exactness.)
485 next_output_time_ms += 516 next_output_time_ms +=
486 kOutputBlockSizeMs - time_now_ms % kOutputBlockSizeMs; 517 kOutputBlockSizeMs - time_now_ms % kOutputBlockSizeMs;
487 } 518 }
488 while (packet_available) { 519
520 bool packet_available = true;
521 bool output_event_available = true;
522 if (!is_rtp_dump) {
523 next_output_time_ms = event_log_source->NextAudioOutputEventMs();
524 if (next_output_time_ms == std::numeric_limits<int64_t>::max())
525 output_event_available = false;
526 start_time_ms = time_now_ms =
527 std::min(next_input_time_ms, next_output_time_ms);
528 }
529 while (packet_available || output_event_available) {
530 // Advance time to next event.
531 time_now_ms = std::min(next_input_time_ms, next_output_time_ms);
489 // Check if it is time to insert packet. 532 // Check if it is time to insert packet.
490 while (time_now_ms >= next_input_time_ms && packet_available) { 533 while (time_now_ms >= next_input_time_ms && packet_available) {
491 assert(packet->virtual_payload_length_bytes() > 0); 534 assert(packet->virtual_payload_length_bytes() > 0);
492 // Parse RTP header. 535 // Parse RTP header.
493 WebRtcRTPHeader rtp_header; 536 WebRtcRTPHeader rtp_header;
494 packet->ConvertHeader(&rtp_header); 537 packet->ConvertHeader(&rtp_header);
495 const uint8_t* payload_ptr = packet->payload(); 538 const uint8_t* payload_ptr = packet->payload();
496 size_t payload_len = packet->payload_length_bytes(); 539 size_t payload_len = packet->payload_length_bytes();
497 if (replace_payload) { 540 if (replace_payload) {
498 payload_len = ReplacePayload(replacement_audio_file.get(), 541 payload_len = ReplacePayload(replacement_audio_file.get(),
499 &replacement_audio, 542 &replacement_audio,
500 &payload, 543 &payload,
501 &payload_mem_size_bytes, 544 &payload_mem_size_bytes,
502 &input_frame_size_timestamps, 545 &input_frame_size_timestamps,
503 &rtp_header, 546 &rtp_header,
504 next_packet.get()); 547 next_packet.get());
505 payload_ptr = payload.get(); 548 payload_ptr = payload.get();
506 } 549 }
507 int error = 550 int error =
508 neteq->InsertPacket(rtp_header, 551 neteq->InsertPacket(rtp_header,
509 payload_ptr, 552 payload_ptr,
510 payload_len, 553 payload_len,
511 packet->time_ms() * sample_rate_hz / 1000); 554 rtc::checked_cast<uint32_t>(
hlundin-webrtc 2015/09/07 11:46:57 I don't think you want the checked_cast here, just
555 packet->time_ms() * sample_rate_hz / 1000));
512 if (error != NetEq::kOK) { 556 if (error != NetEq::kOK) {
513 if (neteq->LastError() == NetEq::kUnknownRtpPayloadType) { 557 if (neteq->LastError() == NetEq::kUnknownRtpPayloadType) {
514 std::cerr << "RTP Payload type " 558 std::cerr << "RTP Payload type "
515 << static_cast<int>(rtp_header.header.payloadType) 559 << static_cast<int>(rtp_header.header.payloadType)
516 << " is unknown." << std::endl; 560 << " is unknown." << std::endl;
517 std::cerr << "Use --codec_map to view default mapping." << std::endl; 561 std::cerr << "Use --codec_map to view default mapping." << std::endl;
518 std::cerr << "Use --helpshort for information on how to make custom " 562 std::cerr << "Use --helpshort for information on how to make custom "
519 "mappings." << std::endl; 563 "mappings." << std::endl;
520 } else { 564 } else {
521 std::cerr << "InsertPacket returned error code " << neteq->LastError() 565 std::cerr << "InsertPacket returned error code " << neteq->LastError()
522 << std::endl; 566 << std::endl;
523 std::cerr << "Header data:" << std::endl; 567 std::cerr << "Header data:" << std::endl;
524 std::cerr << " PT = " 568 std::cerr << " PT = "
525 << static_cast<int>(rtp_header.header.payloadType) 569 << static_cast<int>(rtp_header.header.payloadType)
526 << std::endl; 570 << std::endl;
527 std::cerr << " SN = " << rtp_header.header.sequenceNumber 571 std::cerr << " SN = " << rtp_header.header.sequenceNumber
528 << std::endl; 572 << std::endl;
529 std::cerr << " TS = " << rtp_header.header.timestamp << std::endl; 573 std::cerr << " TS = " << rtp_header.header.timestamp << std::endl;
530 } 574 }
531 } 575 }
532 576
533 // Get next packet from file. 577 // Get next packet from file.
534 webrtc::test::Packet* temp_packet = file_source->NextPacket(); 578 webrtc::test::Packet* temp_packet = file_source->NextPacket();
535 if (temp_packet) { 579 if (temp_packet) {
536 packet.reset(temp_packet); 580 packet.reset(temp_packet);
581 if (replace_payload) {
582 // At this point |packet| contains the packet *after* |next_packet|.
583 // Swap Packet objects between |packet| and |next_packet|.
584 packet.swap(next_packet);
585 // Swap the status indicators unless they're already the same.
586 if (packet_available != next_packet_available) {
587 packet_available = !packet_available;
588 next_packet_available = !next_packet_available;
589 }
590 }
591 next_input_time_ms = rtc::checked_cast<int64_t>(packet->time_ms());
537 } else { 592 } else {
593 // Set next input time to the maximum value of int64_t to prevent the
594 // time_now_ms from becoming stuck at the final value.
595 next_input_time_ms = std::numeric_limits<int64_t>::max();
538 packet_available = false; 596 packet_available = false;
539 } 597 }
540 if (replace_payload) {
541 // At this point |packet| contains the packet *after* |next_packet|.
542 // Swap Packet objects between |packet| and |next_packet|.
543 packet.swap(next_packet);
544 // Swap the status indicators unless they're already the same.
545 if (packet_available != next_packet_available) {
546 packet_available = !packet_available;
547 next_packet_available = !next_packet_available;
548 }
549 }
550 next_input_time_ms = packet->time_ms();
551 } 598 }
552 599
553 // Check if it is time to get output audio. 600 // Check if it is time to get output audio.
554 if (time_now_ms >= next_output_time_ms) { 601 while (time_now_ms >= next_output_time_ms && output_event_available) {
555 static const int kOutDataLen = 602 static const int kOutDataLen =
556 kOutputBlockSizeMs * kMaxSamplesPerMs * kMaxChannels; 603 kOutputBlockSizeMs * kMaxSamplesPerMs * kMaxChannels;
557 int16_t out_data[kOutDataLen]; 604 int16_t out_data[kOutDataLen];
558 int num_channels; 605 int num_channels;
559 int samples_per_channel; 606 int samples_per_channel;
560 int error = neteq->GetAudio(kOutDataLen, out_data, &samples_per_channel, 607 int error = neteq->GetAudio(kOutDataLen, out_data, &samples_per_channel,
561 &num_channels, NULL); 608 &num_channels, NULL);
562 if (error != NetEq::kOK) { 609 if (error != NetEq::kOK) {
563 std::cerr << "GetAudio returned error code " << 610 std::cerr << "GetAudio returned error code " <<
564 neteq->LastError() << std::endl; 611 neteq->LastError() << std::endl;
565 } else { 612 } else {
566 // Calculate sample rate from output size. 613 // Calculate sample rate from output size.
567 sample_rate_hz = 1000 * samples_per_channel / kOutputBlockSizeMs; 614 sample_rate_hz = 1000 * samples_per_channel / kOutputBlockSizeMs;
568 } 615 }
569 616
570 // Write to file. 617 // Write to file.
571 // TODO(hlundin): Make writing to file optional. 618 // TODO(hlundin): Make writing to file optional.
572 size_t write_len = samples_per_channel * num_channels; 619 size_t write_len = samples_per_channel * num_channels;
573 if (!output->WriteArray(out_data, write_len)) { 620 if (!output->WriteArray(out_data, write_len)) {
574 std::cerr << "Error while writing to file" << std::endl; 621 std::cerr << "Error while writing to file" << std::endl;
575 webrtc::Trace::ReturnTrace(); 622 webrtc::Trace::ReturnTrace();
576 exit(1); 623 exit(1);
577 } 624 }
578 next_output_time_ms += kOutputBlockSizeMs; 625 if (is_rtp_dump) {
626 next_output_time_ms += kOutputBlockSizeMs;
627 if (!packet_available)
628 output_event_available = false;
629 } else {
630 next_output_time_ms = event_log_source->NextAudioOutputEventMs();
631 if (next_output_time_ms == std::numeric_limits<int64_t>::max())
632 output_event_available = false;
633 }
579 } 634 }
580 // Advance time to next event.
581 time_now_ms = std::min(next_input_time_ms, next_output_time_ms);
582 } 635 }
583
584 printf("Simulation done\n"); 636 printf("Simulation done\n");
585 printf("Produced %i ms of audio\n", time_now_ms - start_time_ms); 637 printf("Produced %i ms of audio\n",
638 static_cast<int>(time_now_ms - start_time_ms));
586 639
587 delete neteq; 640 delete neteq;
588 webrtc::Trace::ReturnTrace(); 641 webrtc::Trace::ReturnTrace();
589 return 0; 642 return 0;
590 } 643 }
OLDNEW
« no previous file with comments | « webrtc/modules/audio_coding/neteq/neteq_tests.gypi ('k') | webrtc/modules/audio_coding/neteq/tools/rtc_event_log_source.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698