| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2014 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 "webrtc/test/rtp_file_reader.h" | 11 #include "webrtc/test/rtp_file_reader.h" |
| 12 | 12 |
| 13 #include <stdio.h> | 13 #include <stdio.h> |
| 14 | 14 |
| 15 #include <map> | 15 #include <map> |
| 16 #include <string> | 16 #include <string> |
| 17 #include <vector> | 17 #include <vector> |
| 18 | 18 |
| 19 #include "webrtc/base/checks.h" | 19 #include "webrtc/base/checks.h" |
| 20 #include "webrtc/base/constructormagic.h" | 20 #include "webrtc/base/constructormagic.h" |
| 21 #include "webrtc/base/format_macros.h" | 21 #include "webrtc/base/format_macros.h" |
| 22 #include "webrtc/base/logging.h" |
| 22 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" | 23 #include "webrtc/modules/rtp_rtcp/source/rtp_utility.h" |
| 23 | 24 |
| 24 namespace webrtc { | 25 namespace webrtc { |
| 25 namespace test { | 26 namespace test { |
| 26 | 27 |
| 27 static const size_t kFirstLineLength = 40; | 28 static const size_t kFirstLineLength = 40; |
| 28 static uint16_t kPacketHeaderSize = 8; | 29 static uint16_t kPacketHeaderSize = 8; |
| 29 | 30 |
| 30 #if 1 | |
| 31 # define DEBUG_LOG(text) | |
| 32 # define DEBUG_LOG1(text, arg) | |
| 33 #else | |
| 34 # define DEBUG_LOG(text) (printf(text "\n")) | |
| 35 # define DEBUG_LOG1(text, arg) (printf(text "\n", arg)) | |
| 36 #endif | |
| 37 | |
| 38 #define TRY(expr) \ | 31 #define TRY(expr) \ |
| 39 do { \ | 32 do { \ |
| 40 if (!(expr)) { \ | 33 if (!(expr)) { \ |
| 41 DEBUG_LOG1("FAIL at " __FILE__ ":%d", __LINE__); \ | 34 LOG(LS_INFO) << "Failed to read"; \ |
| 42 return false; \ | 35 return false; \ |
| 43 } \ | 36 } \ |
| 44 } while (0) | 37 } while (0) |
| 45 | 38 |
| 46 bool ReadUint32(uint32_t* out, FILE* file) { | 39 bool ReadUint32(uint32_t* out, FILE* file) { |
| 47 *out = 0; | 40 *out = 0; |
| 48 for (size_t i = 0; i < 4; ++i) { | 41 for (size_t i = 0; i < 4; ++i) { |
| 49 *out <<= 8; | 42 *out <<= 8; |
| 50 uint8_t tmp; | 43 uint8_t tmp; |
| 51 if (fread(&tmp, 1, sizeof(uint8_t), file) != sizeof(uint8_t)) | 44 if (fread(&tmp, 1, sizeof(uint8_t), file) != sizeof(uint8_t)) |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 132 bool Init(const std::string& filename, | 125 bool Init(const std::string& filename, |
| 133 const std::set<uint32_t>& ssrc_filter) override { | 126 const std::set<uint32_t>& ssrc_filter) override { |
| 134 file_ = fopen(filename.c_str(), "rb"); | 127 file_ = fopen(filename.c_str(), "rb"); |
| 135 if (file_ == NULL) { | 128 if (file_ == NULL) { |
| 136 printf("ERROR: Can't open file: %s\n", filename.c_str()); | 129 printf("ERROR: Can't open file: %s\n", filename.c_str()); |
| 137 return false; | 130 return false; |
| 138 } | 131 } |
| 139 | 132 |
| 140 char firstline[kFirstLineLength + 1] = {0}; | 133 char firstline[kFirstLineLength + 1] = {0}; |
| 141 if (fgets(firstline, kFirstLineLength, file_) == NULL) { | 134 if (fgets(firstline, kFirstLineLength, file_) == NULL) { |
| 142 DEBUG_LOG("ERROR: Can't read from file\n"); | 135 LOG(LS_INFO) << "Can't read from file"; |
| 143 return false; | 136 return false; |
| 144 } | 137 } |
| 145 if (strncmp(firstline, "#!rtpplay", 9) == 0) { | 138 if (strncmp(firstline, "#!rtpplay", 9) == 0) { |
| 146 if (strncmp(firstline, "#!rtpplay1.0", 12) != 0) { | 139 if (strncmp(firstline, "#!rtpplay1.0", 12) != 0) { |
| 147 DEBUG_LOG("ERROR: wrong rtpplay version, must be 1.0\n"); | 140 LOG(LS_INFO) << "Wrong rtpplay version, must be 1.0"; |
| 148 return false; | 141 return false; |
| 149 } | 142 } |
| 150 } else if (strncmp(firstline, "#!RTPencode", 11) == 0) { | 143 } else if (strncmp(firstline, "#!RTPencode", 11) == 0) { |
| 151 if (strncmp(firstline, "#!RTPencode1.0", 14) != 0) { | 144 if (strncmp(firstline, "#!RTPencode1.0", 14) != 0) { |
| 152 DEBUG_LOG("ERROR: wrong RTPencode version, must be 1.0\n"); | 145 LOG(LS_INFO) << "Wrong RTPencode version, must be 1.0"; |
| 153 return false; | 146 return false; |
| 154 } | 147 } |
| 155 } else { | 148 } else { |
| 156 DEBUG_LOG("ERROR: wrong file format of input file\n"); | 149 LOG(LS_INFO) << "Wrong file format of input file"; |
| 157 return false; | 150 return false; |
| 158 } | 151 } |
| 159 | 152 |
| 160 uint32_t start_sec; | 153 uint32_t start_sec; |
| 161 uint32_t start_usec; | 154 uint32_t start_usec; |
| 162 uint32_t source; | 155 uint32_t source; |
| 163 uint16_t port; | 156 uint16_t port; |
| 164 uint16_t padding; | 157 uint16_t padding; |
| 165 TRY(ReadUint32(&start_sec, file_)); | 158 TRY(ReadUint32(&start_sec, file_)); |
| 166 TRY(ReadUint32(&start_usec, file_)); | 159 TRY(ReadUint32(&start_usec, file_)); |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 229 kMaxReadBufferSize = 4096 | 222 kMaxReadBufferSize = 4096 |
| 230 }; | 223 }; |
| 231 | 224 |
| 232 const uint32_t kPcapBOMSwapOrder = 0xd4c3b2a1UL; | 225 const uint32_t kPcapBOMSwapOrder = 0xd4c3b2a1UL; |
| 233 const uint32_t kPcapBOMNoSwapOrder = 0xa1b2c3d4UL; | 226 const uint32_t kPcapBOMNoSwapOrder = 0xa1b2c3d4UL; |
| 234 | 227 |
| 235 #define TRY_PCAP(expr) \ | 228 #define TRY_PCAP(expr) \ |
| 236 do { \ | 229 do { \ |
| 237 int r = (expr); \ | 230 int r = (expr); \ |
| 238 if (r == kResultFail) { \ | 231 if (r == kResultFail) { \ |
| 239 DEBUG_LOG1("FAIL at " __FILE__ ":%d", __LINE__); \ | 232 LOG(LS_INFO) << "FAIL at " << __FILE__ << ":" << __LINE__; \ |
| 240 return kResultFail; \ | 233 return kResultFail; \ |
| 241 } else if (r == kResultSkip) { \ | 234 } else if (r == kResultSkip) { \ |
| 242 return kResultSkip; \ | 235 return kResultSkip; \ |
| 243 } \ | 236 } \ |
| 244 } while (0) | 237 } while (0) |
| 245 | 238 |
| 246 // Read RTP packets from file in tcpdump/libpcap format, as documented at: | 239 // Read RTP packets from file in tcpdump/libpcap format, as documented at: |
| 247 // http://wiki.wireshark.org/Development/LibpcapFileFormat | 240 // http://wiki.wireshark.org/Development/LibpcapFileFormat |
| 248 class PcapReader : public RtpFileReaderImpl { | 241 class PcapReader : public RtpFileReaderImpl { |
| 249 public: | 242 public: |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 452 return kResultFail; | 445 return kResultFail; |
| 453 } | 446 } |
| 454 TRY_PCAP(Read(read_buffer_, marker.payload_length)); | 447 TRY_PCAP(Read(read_buffer_, marker.payload_length)); |
| 455 | 448 |
| 456 RtpUtility::RtpHeaderParser rtp_parser(read_buffer_, marker.payload_length); | 449 RtpUtility::RtpHeaderParser rtp_parser(read_buffer_, marker.payload_length); |
| 457 if (rtp_parser.RTCP()) { | 450 if (rtp_parser.RTCP()) { |
| 458 rtp_parser.ParseRtcp(&marker.rtp_header); | 451 rtp_parser.ParseRtcp(&marker.rtp_header); |
| 459 packets_.push_back(marker); | 452 packets_.push_back(marker); |
| 460 } else { | 453 } else { |
| 461 if (!rtp_parser.Parse(&marker.rtp_header, nullptr)) { | 454 if (!rtp_parser.Parse(&marker.rtp_header, nullptr)) { |
| 462 DEBUG_LOG("Not recognized as RTP/RTCP"); | 455 LOG(LS_INFO) << "Not recognized as RTP/RTCP"; |
| 463 return kResultSkip; | 456 return kResultSkip; |
| 464 } | 457 } |
| 465 | 458 |
| 466 uint32_t ssrc = marker.rtp_header.ssrc; | 459 uint32_t ssrc = marker.rtp_header.ssrc; |
| 467 if (ssrc_filter.empty() || ssrc_filter.find(ssrc) != ssrc_filter.end()) { | 460 if (ssrc_filter.empty() || ssrc_filter.find(ssrc) != ssrc_filter.end()) { |
| 468 packets_by_ssrc_[ssrc].push_back( | 461 packets_by_ssrc_[ssrc].push_back( |
| 469 static_cast<uint32_t>(packets_.size())); | 462 static_cast<uint32_t>(packets_.size())); |
| 470 packets_.push_back(marker); | 463 packets_.push_back(marker); |
| 471 } else { | 464 } else { |
| 472 return kResultSkip; | 465 return kResultSkip; |
| 473 } | 466 } |
| 474 } | 467 } |
| 475 | 468 |
| 476 return kResultSuccess; | 469 return kResultSuccess; |
| 477 } | 470 } |
| 478 | 471 |
| 479 int ReadPacketHeader(RtpPacketMarker* marker) { | 472 int ReadPacketHeader(RtpPacketMarker* marker) { |
| 480 int32_t file_pos = ftell(file_); | 473 int32_t file_pos = ftell(file_); |
| 481 | 474 |
| 482 // Check for BSD null/loopback frame header. The header is just 4 bytes in | 475 // Check for BSD null/loopback frame header. The header is just 4 bytes in |
| 483 // native byte order, so we check for both versions as we don't care about | 476 // native byte order, so we check for both versions as we don't care about |
| 484 // the header as such and will likely fail reading the IP header if this is | 477 // the header as such and will likely fail reading the IP header if this is |
| 485 // something else than null/loopback. | 478 // something else than null/loopback. |
| 486 uint32_t protocol; | 479 uint32_t protocol; |
| 487 TRY_PCAP(Read(&protocol, true)); | 480 TRY_PCAP(Read(&protocol, true)); |
| 488 if (protocol == kBsdNullLoopback1 || protocol == kBsdNullLoopback2) { | 481 if (protocol == kBsdNullLoopback1 || protocol == kBsdNullLoopback2) { |
| 489 int result = ReadXxpIpHeader(marker); | 482 int result = ReadXxpIpHeader(marker); |
| 490 DEBUG_LOG("Recognized loopback frame"); | 483 LOG(LS_INFO) << "Recognized loopback frame"; |
| 491 if (result != kResultSkip) { | 484 if (result != kResultSkip) { |
| 492 return result; | 485 return result; |
| 493 } | 486 } |
| 494 } | 487 } |
| 495 | 488 |
| 496 TRY_PCAP(fseek(file_, file_pos, SEEK_SET)); | 489 TRY_PCAP(fseek(file_, file_pos, SEEK_SET)); |
| 497 | 490 |
| 498 // Check for Ethernet II, IP frame header. | 491 // Check for Ethernet II, IP frame header. |
| 499 uint16_t type; | 492 uint16_t type; |
| 500 TRY_PCAP(Skip(kEthernetIIHeaderMacSkip)); // Source+destination MAC. | 493 TRY_PCAP(Skip(kEthernetIIHeaderMacSkip)); // Source+destination MAC. |
| 501 TRY_PCAP(Read(&type, true)); | 494 TRY_PCAP(Read(&type, true)); |
| 502 if (type == kEthertypeIp) { | 495 if (type == kEthertypeIp) { |
| 503 int result = ReadXxpIpHeader(marker); | 496 int result = ReadXxpIpHeader(marker); |
| 504 DEBUG_LOG("Recognized ethernet 2 frame"); | 497 LOG(LS_INFO) << "Recognized ethernet 2 frame"; |
| 505 if (result != kResultSkip) { | 498 if (result != kResultSkip) { |
| 506 return result; | 499 return result; |
| 507 } | 500 } |
| 508 } | 501 } |
| 509 | 502 |
| 510 return kResultSkip; | 503 return kResultSkip; |
| 511 } | 504 } |
| 512 | 505 |
| 513 uint32_t CalcTimeDelta(uint32_t ts_sec, uint32_t ts_usec, uint32_t start_ms) { | 506 uint32_t CalcTimeDelta(uint32_t ts_sec, uint32_t ts_usec, uint32_t start_ms) { |
| 514 // Round to nearest ms. | 507 // Round to nearest ms. |
| (...skipping 19 matching lines...) Expand all Loading... |
| 534 TRY_PCAP(Read(&version, true)); | 527 TRY_PCAP(Read(&version, true)); |
| 535 TRY_PCAP(Read(&length, true)); | 528 TRY_PCAP(Read(&length, true)); |
| 536 TRY_PCAP(Read(&id, true)); | 529 TRY_PCAP(Read(&id, true)); |
| 537 TRY_PCAP(Read(&fragment, true)); | 530 TRY_PCAP(Read(&fragment, true)); |
| 538 TRY_PCAP(Read(&protocol, true)); | 531 TRY_PCAP(Read(&protocol, true)); |
| 539 TRY_PCAP(Read(&checksum, true)); | 532 TRY_PCAP(Read(&checksum, true)); |
| 540 TRY_PCAP(Read(&marker->source_ip, true)); | 533 TRY_PCAP(Read(&marker->source_ip, true)); |
| 541 TRY_PCAP(Read(&marker->dest_ip, true)); | 534 TRY_PCAP(Read(&marker->dest_ip, true)); |
| 542 | 535 |
| 543 if (((version >> 12) & 0x000f) != kIpVersion4) { | 536 if (((version >> 12) & 0x000f) != kIpVersion4) { |
| 544 DEBUG_LOG("IP header is not IPv4"); | 537 LOG(LS_INFO) << "IP header is not IPv4"; |
| 545 return kResultSkip; | 538 return kResultSkip; |
| 546 } | 539 } |
| 547 | 540 |
| 548 if (fragment != kFragmentOffsetClear && | 541 if (fragment != kFragmentOffsetClear && |
| 549 fragment != kFragmentOffsetDoNotFragment) { | 542 fragment != kFragmentOffsetDoNotFragment) { |
| 550 DEBUG_LOG("IP fragments cannot be handled"); | 543 LOG(LS_INFO) << "IP fragments cannot be handled"; |
| 551 return kResultSkip; | 544 return kResultSkip; |
| 552 } | 545 } |
| 553 | 546 |
| 554 // Skip remaining fields of IP header. | 547 // Skip remaining fields of IP header. |
| 555 uint16_t header_length = (version & 0x0f00) >> (8 - 2); | 548 uint16_t header_length = (version & 0x0f00) >> (8 - 2); |
| 556 assert(header_length >= kMinIpHeaderLength); | 549 assert(header_length >= kMinIpHeaderLength); |
| 557 TRY_PCAP(Skip(header_length - kMinIpHeaderLength)); | 550 TRY_PCAP(Skip(header_length - kMinIpHeaderLength)); |
| 558 | 551 |
| 559 protocol = protocol & 0x00ff; | 552 protocol = protocol & 0x00ff; |
| 560 if (protocol == kProtocolTcp) { | 553 if (protocol == kProtocolTcp) { |
| 561 DEBUG_LOG("TCP packets are not handled"); | 554 LOG(LS_INFO) << "TCP packets are not handled"; |
| 562 return kResultSkip; | 555 return kResultSkip; |
| 563 } else if (protocol == kProtocolUdp) { | 556 } else if (protocol == kProtocolUdp) { |
| 564 uint16_t length; | 557 uint16_t length; |
| 565 uint16_t checksum; | 558 uint16_t checksum; |
| 566 TRY_PCAP(Read(&marker->source_port, true)); | 559 TRY_PCAP(Read(&marker->source_port, true)); |
| 567 TRY_PCAP(Read(&marker->dest_port, true)); | 560 TRY_PCAP(Read(&marker->dest_port, true)); |
| 568 TRY_PCAP(Read(&length, true)); | 561 TRY_PCAP(Read(&length, true)); |
| 569 TRY_PCAP(Read(&checksum, true)); | 562 TRY_PCAP(Read(&checksum, true)); |
| 570 marker->payload_length = length - kUdpHeaderLength; | 563 marker->payload_length = length - kUdpHeaderLength; |
| 571 } else { | 564 } else { |
| 572 DEBUG_LOG("Unknown transport (expected UDP or TCP)"); | 565 LOG(LS_INFO) << "Unknown transport (expected UDP or TCP)"; |
| 573 return kResultSkip; | 566 return kResultSkip; |
| 574 } | 567 } |
| 575 | 568 |
| 576 return kResultSuccess; | 569 return kResultSuccess; |
| 577 } | 570 } |
| 578 | 571 |
| 579 int Read(uint32_t* out, bool expect_network_order) { | 572 int Read(uint32_t* out, bool expect_network_order) { |
| 580 uint32_t tmp = 0; | 573 uint32_t tmp = 0; |
| 581 if (fread(&tmp, 1, sizeof(uint32_t), file_) != sizeof(uint32_t)) { | 574 if (fread(&tmp, 1, sizeof(uint32_t), file_) != sizeof(uint32_t)) { |
| 582 return kResultFail; | 575 return kResultFail; |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 665 return reader; | 658 return reader; |
| 666 } | 659 } |
| 667 | 660 |
| 668 RtpFileReader* RtpFileReader::Create(FileFormat format, | 661 RtpFileReader* RtpFileReader::Create(FileFormat format, |
| 669 const std::string& filename) { | 662 const std::string& filename) { |
| 670 return RtpFileReader::Create(format, filename, std::set<uint32_t>()); | 663 return RtpFileReader::Create(format, filename, std::set<uint32_t>()); |
| 671 } | 664 } |
| 672 | 665 |
| 673 } // namespace test | 666 } // namespace test |
| 674 } // namespace webrtc | 667 } // namespace webrtc |
| OLD | NEW |