/* * Copyright (c) 2014 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree. */ #include "test/rtp_file_writer.h" #include #include #include #include "absl/types/optional.h" #include "rtc_base/checks.h" namespace webrtc { namespace test { static const uint16_t kPacketHeaderSize = 8; static const char kFirstLine[] = "#!rtpplay1.0 0.0.0.0/0\n"; // Write RTP packets to file in rtpdump format, as documented at: // http://www.cs.columbia.edu/irt/software/rtptools/ class RtpDumpWriter : public RtpFileWriter { public: explicit RtpDumpWriter(FILE* file) : file_(file) { RTC_CHECK(file_ != NULL); Init(); } ~RtpDumpWriter() override { if (file_ != NULL) { fclose(file_); file_ = NULL; } } RtpDumpWriter(const RtpDumpWriter&) = delete; RtpDumpWriter& operator=(const RtpDumpWriter&) = delete; bool WritePacket(const RtpPacket* packet) override { if (!first_packet_time_) { first_packet_time_ = packet->time_ms; } uint16_t len = static_cast(packet->length + kPacketHeaderSize); uint16_t plen = static_cast(packet->original_length); uint32_t offset = packet->time_ms - *first_packet_time_; RTC_CHECK(WriteUint16(len)); RTC_CHECK(WriteUint16(plen)); RTC_CHECK(WriteUint32(offset)); return fwrite(packet->data, sizeof(uint8_t), packet->length, file_) == packet->length; } private: bool Init() { fprintf(file_, "%s", kFirstLine); RTC_CHECK(WriteUint32(0)); RTC_CHECK(WriteUint32(0)); RTC_CHECK(WriteUint32(0)); RTC_CHECK(WriteUint16(0)); RTC_CHECK(WriteUint16(0)); return true; } bool WriteUint32(uint32_t in) { // Loop through shifts = {24, 16, 8, 0}. for (int shifts = 24; shifts >= 0; shifts -= 8) { uint8_t tmp = static_cast((in >> shifts) & 0xFF); if (fwrite(&tmp, sizeof(uint8_t), 1, file_) != 1) return false; } return true; } bool WriteUint16(uint16_t in) { // Write 8 MSBs. uint8_t tmp = static_cast((in >> 8) & 0xFF); if (fwrite(&tmp, sizeof(uint8_t), 1, file_) != 1) return false; // Write 8 LSBs. tmp = static_cast(in & 0xFF); if (fwrite(&tmp, sizeof(uint8_t), 1, file_) != 1) return false; return true; } FILE* file_; absl::optional first_packet_time_; }; RtpFileWriter* RtpFileWriter::Create(FileFormat format, const std::string& filename) { FILE* file = fopen(filename.c_str(), "wb"); if (file == NULL) { printf("ERROR: Can't open file: %s\n", filename.c_str()); return NULL; } switch (format) { case kRtpDump: return new RtpDumpWriter(file); } fclose(file); return NULL; } } // namespace test } // namespace webrtc