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 |