| 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 |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 62 uint8_t tmp; | 62 uint8_t tmp; |
| 63 if (fread(&tmp, 1, sizeof(uint8_t), file) != sizeof(uint8_t)) | 63 if (fread(&tmp, 1, sizeof(uint8_t), file) != sizeof(uint8_t)) |
| 64 return false; | 64 return false; |
| 65 *out |= tmp; | 65 *out |= tmp; |
| 66 } | 66 } |
| 67 return true; | 67 return true; |
| 68 } | 68 } |
| 69 | 69 |
| 70 class RtpFileReaderImpl : public RtpFileReader { | 70 class RtpFileReaderImpl : public RtpFileReader { |
| 71 public: | 71 public: |
| 72 virtual bool Init(const std::string& filename) = 0; | 72 virtual bool Init(const std::string& filename, |
| 73 const std::set<uint32_t>& ssrc_filter) = 0; |
| 73 }; | 74 }; |
| 74 | 75 |
| 75 class InterleavedRtpFileReader : public RtpFileReaderImpl { | 76 class InterleavedRtpFileReader : public RtpFileReaderImpl { |
| 76 public: | 77 public: |
| 77 virtual ~InterleavedRtpFileReader() { | 78 virtual ~InterleavedRtpFileReader() { |
| 78 if (file_ != NULL) { | 79 if (file_ != NULL) { |
| 79 fclose(file_); | 80 fclose(file_); |
| 80 file_ = NULL; | 81 file_ = NULL; |
| 81 } | 82 } |
| 82 } | 83 } |
| 83 | 84 |
| 84 virtual bool Init(const std::string& filename) { | 85 virtual bool Init(const std::string& filename, |
| 86 const std::set<uint32_t>& ssrc_filter) { |
| 85 file_ = fopen(filename.c_str(), "rb"); | 87 file_ = fopen(filename.c_str(), "rb"); |
| 86 if (file_ == NULL) { | 88 if (file_ == NULL) { |
| 87 printf("ERROR: Can't open file: %s\n", filename.c_str()); | 89 printf("ERROR: Can't open file: %s\n", filename.c_str()); |
| 88 return false; | 90 return false; |
| 89 } | 91 } |
| 90 return true; | 92 return true; |
| 91 } | 93 } |
| 92 virtual bool NextPacket(RtpPacket* packet) { | 94 virtual bool NextPacket(RtpPacket* packet) { |
| 93 assert(file_ != NULL); | 95 assert(file_ != NULL); |
| 94 packet->length = RtpPacket::kMaxPacketBufferSize; | 96 packet->length = RtpPacket::kMaxPacketBufferSize; |
| (...skipping 25 matching lines...) Expand all Loading... |
| 120 class RtpDumpReader : public RtpFileReaderImpl { | 122 class RtpDumpReader : public RtpFileReaderImpl { |
| 121 public: | 123 public: |
| 122 RtpDumpReader() : file_(NULL) {} | 124 RtpDumpReader() : file_(NULL) {} |
| 123 virtual ~RtpDumpReader() { | 125 virtual ~RtpDumpReader() { |
| 124 if (file_ != NULL) { | 126 if (file_ != NULL) { |
| 125 fclose(file_); | 127 fclose(file_); |
| 126 file_ = NULL; | 128 file_ = NULL; |
| 127 } | 129 } |
| 128 } | 130 } |
| 129 | 131 |
| 130 bool Init(const std::string& filename) { | 132 bool Init(const std::string& filename, |
| 133 const std::set<uint32_t>& ssrc_filter) { |
| 131 file_ = fopen(filename.c_str(), "rb"); | 134 file_ = fopen(filename.c_str(), "rb"); |
| 132 if (file_ == NULL) { | 135 if (file_ == NULL) { |
| 133 printf("ERROR: Can't open file: %s\n", filename.c_str()); | 136 printf("ERROR: Can't open file: %s\n", filename.c_str()); |
| 134 return false; | 137 return false; |
| 135 } | 138 } |
| 136 | 139 |
| 137 char firstline[kFirstLineLength + 1] = {0}; | 140 char firstline[kFirstLineLength + 1] = {0}; |
| 138 if (fgets(firstline, kFirstLineLength, file_) == NULL) { | 141 if (fgets(firstline, kFirstLineLength, file_) == NULL) { |
| 139 DEBUG_LOG("ERROR: Can't read from file\n"); | 142 DEBUG_LOG("ERROR: Can't read from file\n"); |
| 140 return false; | 143 return false; |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 258 next_packet_it_() { | 261 next_packet_it_() { |
| 259 } | 262 } |
| 260 | 263 |
| 261 virtual ~PcapReader() { | 264 virtual ~PcapReader() { |
| 262 if (file_ != NULL) { | 265 if (file_ != NULL) { |
| 263 fclose(file_); | 266 fclose(file_); |
| 264 file_ = NULL; | 267 file_ = NULL; |
| 265 } | 268 } |
| 266 } | 269 } |
| 267 | 270 |
| 268 bool Init(const std::string& filename) override { | 271 bool Init(const std::string& filename, |
| 269 return Initialize(filename) == kResultSuccess; | 272 const std::set<uint32_t>& ssrc_filter) override { |
| 273 return Initialize(filename, ssrc_filter) == kResultSuccess; |
| 270 } | 274 } |
| 271 | 275 |
| 272 int Initialize(const std::string& filename) { | 276 int Initialize(const std::string& filename, |
| 277 const std::set<uint32_t>& ssrc_filter) { |
| 273 file_ = fopen(filename.c_str(), "rb"); | 278 file_ = fopen(filename.c_str(), "rb"); |
| 274 if (file_ == NULL) { | 279 if (file_ == NULL) { |
| 275 printf("ERROR: Can't open file: %s\n", filename.c_str()); | 280 printf("ERROR: Can't open file: %s\n", filename.c_str()); |
| 276 return kResultFail; | 281 return kResultFail; |
| 277 } | 282 } |
| 278 | 283 |
| 279 if (ReadGlobalHeader() < 0) { | 284 if (ReadGlobalHeader() < 0) { |
| 280 return kResultFail; | 285 return kResultFail; |
| 281 } | 286 } |
| 282 | 287 |
| 283 int total_packet_count = 0; | 288 int total_packet_count = 0; |
| 284 uint32_t stream_start_ms = 0; | 289 uint32_t stream_start_ms = 0; |
| 285 int32_t next_packet_pos = ftell(file_); | 290 int32_t next_packet_pos = ftell(file_); |
| 286 for (;;) { | 291 for (;;) { |
| 287 TRY_PCAP(fseek(file_, next_packet_pos, SEEK_SET)); | 292 TRY_PCAP(fseek(file_, next_packet_pos, SEEK_SET)); |
| 288 int result = ReadPacket(&next_packet_pos, stream_start_ms, | 293 int result = ReadPacket(&next_packet_pos, stream_start_ms, |
| 289 ++total_packet_count); | 294 ++total_packet_count, ssrc_filter); |
| 290 if (result == kResultFail) { | 295 if (result == kResultFail) { |
| 291 break; | 296 break; |
| 292 } else if (result == kResultSuccess && packets_.size() == 1) { | 297 } else if (result == kResultSuccess && packets_.size() == 1) { |
| 293 assert(stream_start_ms == 0); | 298 assert(stream_start_ms == 0); |
| 294 PacketIterator it = packets_.begin(); | 299 PacketIterator it = packets_.begin(); |
| 295 stream_start_ms = it->time_offset_ms; | 300 stream_start_ms = it->time_offset_ms; |
| 296 it->time_offset_ms = 0; | 301 it->time_offset_ms = 0; |
| 297 } | 302 } |
| 298 } | 303 } |
| 299 | 304 |
| 300 if (feof(file_) == 0) { | 305 if (feof(file_) == 0) { |
| 301 printf("Failed reading file!\n"); | 306 printf("Failed reading file!\n"); |
| 302 return kResultFail; | 307 return kResultFail; |
| 303 } | 308 } |
| 304 | 309 |
| 305 printf("Total packets in file: %d\n", total_packet_count); | 310 printf("Total packets in file: %d\n", total_packet_count); |
| 306 printf("Total RTP/RTCP packets: %" PRIuS "\n", packets_.size()); | 311 printf("Total RTP/RTCP packets: %" PRIuS "\n", packets_.size()); |
| 307 | 312 |
| 308 for (SsrcMapIterator mit = packets_by_ssrc_.begin(); | 313 for (SsrcMapIterator mit = packets_by_ssrc_.begin(); |
| 309 mit != packets_by_ssrc_.end(); ++mit) { | 314 mit != packets_by_ssrc_.end(); ++mit) { |
| 310 uint32_t ssrc = mit->first; | 315 uint32_t ssrc = mit->first; |
| 311 const std::vector<uint32_t>& packet_numbers = mit->second; | 316 const std::vector<uint32_t>& packet_indices = mit->second; |
| 312 uint8_t pt = packets_[packet_numbers[0]].rtp_header.payloadType; | 317 uint8_t pt = packets_[packet_indices[0]].rtp_header.payloadType; |
| 313 printf("SSRC: %08x, %" PRIuS " packets, pt=%d\n", ssrc, | 318 printf("SSRC: %08x, %" PRIuS " packets, pt=%d\n", ssrc, |
| 314 packet_numbers.size(), pt); | 319 packet_indices.size(), pt); |
| 315 } | 320 } |
| 316 | 321 |
| 317 // TODO(solenberg): Better validation of identified SSRC streams. | 322 // TODO(solenberg): Better validation of identified SSRC streams. |
| 318 // | 323 // |
| 319 // Since we're dealing with raw network data here, we will wrongly identify | 324 // Since we're dealing with raw network data here, we will wrongly identify |
| 320 // some packets as RTP. When these packets are consumed by RtpPlayer, they | 325 // some packets as RTP. When these packets are consumed by RtpPlayer, they |
| 321 // are unlikely to cause issues as they will ultimately be filtered out by | 326 // are unlikely to cause issues as they will ultimately be filtered out by |
| 322 // the RtpRtcp module. However, we should really do better filtering here, | 327 // the RtpRtcp module. However, we should really do better filtering here, |
| 323 // which we can accomplish in a number of ways, e.g.: | 328 // which we can accomplish in a number of ways, e.g.: |
| 324 // | 329 // |
| (...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 412 | 417 |
| 413 // Accept only LINKTYPE_NULL and LINKTYPE_ETHERNET. | 418 // Accept only LINKTYPE_NULL and LINKTYPE_ETHERNET. |
| 414 // See: http://www.tcpdump.org/linktypes.html | 419 // See: http://www.tcpdump.org/linktypes.html |
| 415 if (network != kLinktypeNull && network != kLinktypeEthernet) { | 420 if (network != kLinktypeNull && network != kLinktypeEthernet) { |
| 416 return kResultFail; | 421 return kResultFail; |
| 417 } | 422 } |
| 418 | 423 |
| 419 return kResultSuccess; | 424 return kResultSuccess; |
| 420 } | 425 } |
| 421 | 426 |
| 422 int ReadPacket(int32_t* next_packet_pos, uint32_t stream_start_ms, | 427 int ReadPacket(int32_t* next_packet_pos, |
| 423 uint32_t number) { | 428 uint32_t stream_start_ms, |
| 429 uint32_t number, |
| 430 const std::set<uint32_t>& ssrc_filter) { |
| 424 assert(next_packet_pos); | 431 assert(next_packet_pos); |
| 425 | 432 |
| 426 uint32_t ts_sec; // Timestamp seconds. | 433 uint32_t ts_sec; // Timestamp seconds. |
| 427 uint32_t ts_usec; // Timestamp microseconds. | 434 uint32_t ts_usec; // Timestamp microseconds. |
| 428 uint32_t incl_len; // Number of octets of packet saved in file. | 435 uint32_t incl_len; // Number of octets of packet saved in file. |
| 429 uint32_t orig_len; // Actual length of packet. | 436 uint32_t orig_len; // Actual length of packet. |
| 430 TRY_PCAP(Read(&ts_sec, false)); | 437 TRY_PCAP(Read(&ts_sec, false)); |
| 431 TRY_PCAP(Read(&ts_usec, false)); | 438 TRY_PCAP(Read(&ts_usec, false)); |
| 432 TRY_PCAP(Read(&incl_len, false)); | 439 TRY_PCAP(Read(&incl_len, false)); |
| 433 TRY_PCAP(Read(&orig_len, false)); | 440 TRY_PCAP(Read(&orig_len, false)); |
| (...skipping 16 matching lines...) Expand all Loading... |
| 450 if (rtp_parser.RTCP()) { | 457 if (rtp_parser.RTCP()) { |
| 451 rtp_parser.ParseRtcp(&marker.rtp_header); | 458 rtp_parser.ParseRtcp(&marker.rtp_header); |
| 452 packets_.push_back(marker); | 459 packets_.push_back(marker); |
| 453 } else { | 460 } else { |
| 454 if (!rtp_parser.Parse(marker.rtp_header, NULL)) { | 461 if (!rtp_parser.Parse(marker.rtp_header, NULL)) { |
| 455 DEBUG_LOG("Not recognized as RTP/RTCP"); | 462 DEBUG_LOG("Not recognized as RTP/RTCP"); |
| 456 return kResultSkip; | 463 return kResultSkip; |
| 457 } | 464 } |
| 458 | 465 |
| 459 uint32_t ssrc = marker.rtp_header.ssrc; | 466 uint32_t ssrc = marker.rtp_header.ssrc; |
| 460 packets_by_ssrc_[ssrc].push_back(marker.packet_number); | 467 if (ssrc_filter.empty() || ssrc_filter.find(ssrc) != ssrc_filter.end()) { |
| 461 packets_.push_back(marker); | 468 packets_by_ssrc_[ssrc].push_back( |
| 469 static_cast<uint32_t>(packets_.size())); |
| 470 packets_.push_back(marker); |
| 471 } else { |
| 472 return kResultSkip; |
| 473 } |
| 462 } | 474 } |
| 463 | 475 |
| 464 return kResultSuccess; | 476 return kResultSuccess; |
| 465 } | 477 } |
| 466 | 478 |
| 467 int ReadPacketHeader(RtpPacketMarker* marker) { | 479 int ReadPacketHeader(RtpPacketMarker* marker) { |
| 468 int32_t file_pos = ftell(file_); | 480 int32_t file_pos = ftell(file_); |
| 469 | 481 |
| 470 // Check for BSD null/loopback frame header. The header is just 4 bytes in | 482 // Check for BSD null/loopback frame header. The header is just 4 bytes in |
| 471 // native byte order, so we check for both versions as we don't care about | 483 // native byte order, so we check for both versions as we don't care about |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 625 uint8_t read_buffer_[kMaxReadBufferSize]; | 637 uint8_t read_buffer_[kMaxReadBufferSize]; |
| 626 | 638 |
| 627 SsrcMap packets_by_ssrc_; | 639 SsrcMap packets_by_ssrc_; |
| 628 std::vector<RtpPacketMarker> packets_; | 640 std::vector<RtpPacketMarker> packets_; |
| 629 PacketIterator next_packet_it_; | 641 PacketIterator next_packet_it_; |
| 630 | 642 |
| 631 DISALLOW_COPY_AND_ASSIGN(PcapReader); | 643 DISALLOW_COPY_AND_ASSIGN(PcapReader); |
| 632 }; | 644 }; |
| 633 | 645 |
| 634 RtpFileReader* RtpFileReader::Create(FileFormat format, | 646 RtpFileReader* RtpFileReader::Create(FileFormat format, |
| 635 const std::string& filename) { | 647 const std::string& filename, |
| 648 const std::set<uint32_t>& ssrc_filter) { |
| 636 RtpFileReaderImpl* reader = NULL; | 649 RtpFileReaderImpl* reader = NULL; |
| 637 switch (format) { | 650 switch (format) { |
| 638 case kPcap: | 651 case kPcap: |
| 639 reader = new PcapReader(); | 652 reader = new PcapReader(); |
| 640 break; | 653 break; |
| 641 case kRtpDump: | 654 case kRtpDump: |
| 642 reader = new RtpDumpReader(); | 655 reader = new RtpDumpReader(); |
| 643 break; | 656 break; |
| 644 case kLengthPacketInterleaved: | 657 case kLengthPacketInterleaved: |
| 645 reader = new InterleavedRtpFileReader(); | 658 reader = new InterleavedRtpFileReader(); |
| 646 break; | 659 break; |
| 647 } | 660 } |
| 648 if (!reader->Init(filename)) { | 661 if (!reader->Init(filename, ssrc_filter)) { |
| 649 delete reader; | 662 delete reader; |
| 650 return NULL; | 663 return NULL; |
| 651 } | 664 } |
| 652 return reader; | 665 return reader; |
| 653 } | 666 } |
| 654 | 667 |
| 668 RtpFileReader* RtpFileReader::Create(FileFormat format, |
| 669 const std::string& filename) { |
| 670 return RtpFileReader::Create(format, filename, std::set<uint32_t>()); |
| 671 } |
| 672 |
| 655 } // namespace test | 673 } // namespace test |
| 656 } // namespace webrtc | 674 } // namespace webrtc |
| OLD | NEW |