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 |