xref: /aosp_15_r20/external/webrtc/modules/audio_coding/test/RTPFile.cc (revision d9f758449e529ab9291ac668be2861e7a55c2422)
1 /*
2  *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
3  *
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
6  *  tree. An additional intellectual property rights grant can be found
7  *  in the file PATENTS.  All contributing project authors may
8  *  be found in the AUTHORS file in the root of the source tree.
9  */
10 
11 #include "RTPFile.h"
12 
13 #include <stdlib.h>
14 
15 #include <limits>
16 
17 #include "absl/strings/string_view.h"
18 
19 #ifdef WIN32
20 #include <Winsock2.h>
21 #else
22 #include <arpa/inet.h>
23 #endif
24 
25 // TODO(tlegrand): Consider removing usage of gtest.
26 #include "test/gtest.h"
27 
28 namespace webrtc {
29 
ParseRTPHeader(RTPHeader * rtp_header,const uint8_t * rtpHeader)30 void RTPStream::ParseRTPHeader(RTPHeader* rtp_header,
31                                const uint8_t* rtpHeader) {
32   rtp_header->payloadType = rtpHeader[1];
33   rtp_header->sequenceNumber =
34       (static_cast<uint16_t>(rtpHeader[2]) << 8) | rtpHeader[3];
35   rtp_header->timestamp = (static_cast<uint32_t>(rtpHeader[4]) << 24) |
36                           (static_cast<uint32_t>(rtpHeader[5]) << 16) |
37                           (static_cast<uint32_t>(rtpHeader[6]) << 8) |
38                           rtpHeader[7];
39   rtp_header->ssrc = (static_cast<uint32_t>(rtpHeader[8]) << 24) |
40                      (static_cast<uint32_t>(rtpHeader[9]) << 16) |
41                      (static_cast<uint32_t>(rtpHeader[10]) << 8) |
42                      rtpHeader[11];
43 }
44 
MakeRTPheader(uint8_t * rtpHeader,uint8_t payloadType,int16_t seqNo,uint32_t timeStamp,uint32_t ssrc)45 void RTPStream::MakeRTPheader(uint8_t* rtpHeader,
46                               uint8_t payloadType,
47                               int16_t seqNo,
48                               uint32_t timeStamp,
49                               uint32_t ssrc) {
50   rtpHeader[0] = 0x80;
51   rtpHeader[1] = payloadType;
52   rtpHeader[2] = (seqNo >> 8) & 0xFF;
53   rtpHeader[3] = seqNo & 0xFF;
54   rtpHeader[4] = timeStamp >> 24;
55   rtpHeader[5] = (timeStamp >> 16) & 0xFF;
56   rtpHeader[6] = (timeStamp >> 8) & 0xFF;
57   rtpHeader[7] = timeStamp & 0xFF;
58   rtpHeader[8] = ssrc >> 24;
59   rtpHeader[9] = (ssrc >> 16) & 0xFF;
60   rtpHeader[10] = (ssrc >> 8) & 0xFF;
61   rtpHeader[11] = ssrc & 0xFF;
62 }
63 
RTPPacket(uint8_t payloadType,uint32_t timeStamp,int16_t seqNo,const uint8_t * payloadData,size_t payloadSize,uint32_t frequency)64 RTPPacket::RTPPacket(uint8_t payloadType,
65                      uint32_t timeStamp,
66                      int16_t seqNo,
67                      const uint8_t* payloadData,
68                      size_t payloadSize,
69                      uint32_t frequency)
70     : payloadType(payloadType),
71       timeStamp(timeStamp),
72       seqNo(seqNo),
73       payloadSize(payloadSize),
74       frequency(frequency) {
75   if (payloadSize > 0) {
76     this->payloadData = new uint8_t[payloadSize];
77     memcpy(this->payloadData, payloadData, payloadSize);
78   }
79 }
80 
~RTPPacket()81 RTPPacket::~RTPPacket() {
82   delete[] payloadData;
83 }
84 
Write(const uint8_t payloadType,const uint32_t timeStamp,const int16_t seqNo,const uint8_t * payloadData,const size_t payloadSize,uint32_t frequency)85 void RTPBuffer::Write(const uint8_t payloadType,
86                       const uint32_t timeStamp,
87                       const int16_t seqNo,
88                       const uint8_t* payloadData,
89                       const size_t payloadSize,
90                       uint32_t frequency) {
91   RTPPacket* packet = new RTPPacket(payloadType, timeStamp, seqNo, payloadData,
92                                     payloadSize, frequency);
93   MutexLock lock(&mutex_);
94   _rtpQueue.push(packet);
95 }
96 
Read(RTPHeader * rtp_header,uint8_t * payloadData,size_t payloadSize,uint32_t * offset)97 size_t RTPBuffer::Read(RTPHeader* rtp_header,
98                        uint8_t* payloadData,
99                        size_t payloadSize,
100                        uint32_t* offset) {
101   RTPPacket* packet;
102   {
103     MutexLock lock(&mutex_);
104     packet = _rtpQueue.front();
105     _rtpQueue.pop();
106   }
107   rtp_header->markerBit = 1;
108   rtp_header->payloadType = packet->payloadType;
109   rtp_header->sequenceNumber = packet->seqNo;
110   rtp_header->ssrc = 0;
111   rtp_header->timestamp = packet->timeStamp;
112   if (packet->payloadSize > 0 && payloadSize >= packet->payloadSize) {
113     memcpy(payloadData, packet->payloadData, packet->payloadSize);
114   } else {
115     return 0;
116   }
117   *offset = (packet->timeStamp / (packet->frequency / 1000));
118 
119   return packet->payloadSize;
120 }
121 
EndOfFile() const122 bool RTPBuffer::EndOfFile() const {
123   MutexLock lock(&mutex_);
124   return _rtpQueue.empty();
125 }
126 
Open(absl::string_view filename,absl::string_view mode)127 void RTPFile::Open(absl::string_view filename, absl::string_view mode) {
128   std::string filename_str = std::string(filename);
129   if ((_rtpFile = fopen(filename_str.c_str(), std::string(mode).c_str())) ==
130       NULL) {
131     printf("Cannot write file %s.\n", filename_str.c_str());
132     ADD_FAILURE() << "Unable to write file";
133     exit(1);
134   }
135 }
136 
Close()137 void RTPFile::Close() {
138   if (_rtpFile != NULL) {
139     fclose(_rtpFile);
140     _rtpFile = NULL;
141   }
142 }
143 
WriteHeader()144 void RTPFile::WriteHeader() {
145   // Write data in a format that NetEQ and RTP Play can parse
146   fprintf(_rtpFile, "#!RTPencode%s\n", "1.0");
147   uint32_t dummy_variable = 0;
148   // should be converted to network endian format, but does not matter when 0
149   EXPECT_EQ(1u, fwrite(&dummy_variable, 4, 1, _rtpFile));
150   EXPECT_EQ(1u, fwrite(&dummy_variable, 4, 1, _rtpFile));
151   EXPECT_EQ(1u, fwrite(&dummy_variable, 4, 1, _rtpFile));
152   EXPECT_EQ(1u, fwrite(&dummy_variable, 2, 1, _rtpFile));
153   EXPECT_EQ(1u, fwrite(&dummy_variable, 2, 1, _rtpFile));
154   fflush(_rtpFile);
155 }
156 
ReadHeader()157 void RTPFile::ReadHeader() {
158   uint32_t start_sec, start_usec, source;
159   uint16_t port, padding;
160   char fileHeader[40];
161   EXPECT_TRUE(fgets(fileHeader, 40, _rtpFile) != 0);
162   EXPECT_EQ(1u, fread(&start_sec, 4, 1, _rtpFile));
163   start_sec = ntohl(start_sec);
164   EXPECT_EQ(1u, fread(&start_usec, 4, 1, _rtpFile));
165   start_usec = ntohl(start_usec);
166   EXPECT_EQ(1u, fread(&source, 4, 1, _rtpFile));
167   source = ntohl(source);
168   EXPECT_EQ(1u, fread(&port, 2, 1, _rtpFile));
169   port = ntohs(port);
170   EXPECT_EQ(1u, fread(&padding, 2, 1, _rtpFile));
171   padding = ntohs(padding);
172 }
173 
Write(const uint8_t payloadType,const uint32_t timeStamp,const int16_t seqNo,const uint8_t * payloadData,const size_t payloadSize,uint32_t frequency)174 void RTPFile::Write(const uint8_t payloadType,
175                     const uint32_t timeStamp,
176                     const int16_t seqNo,
177                     const uint8_t* payloadData,
178                     const size_t payloadSize,
179                     uint32_t frequency) {
180   /* write RTP packet to file */
181   uint8_t rtpHeader[12];
182   MakeRTPheader(rtpHeader, payloadType, seqNo, timeStamp, 0);
183   ASSERT_LE(12 + payloadSize + 8, std::numeric_limits<u_short>::max());
184   uint16_t lengthBytes = htons(static_cast<u_short>(12 + payloadSize + 8));
185   uint16_t plen = htons(static_cast<u_short>(12 + payloadSize));
186   uint32_t offsetMs;
187 
188   offsetMs = (timeStamp / (frequency / 1000));
189   offsetMs = htonl(offsetMs);
190   EXPECT_EQ(1u, fwrite(&lengthBytes, 2, 1, _rtpFile));
191   EXPECT_EQ(1u, fwrite(&plen, 2, 1, _rtpFile));
192   EXPECT_EQ(1u, fwrite(&offsetMs, 4, 1, _rtpFile));
193   EXPECT_EQ(1u, fwrite(&rtpHeader, 12, 1, _rtpFile));
194   EXPECT_EQ(payloadSize, fwrite(payloadData, 1, payloadSize, _rtpFile));
195 }
196 
Read(RTPHeader * rtp_header,uint8_t * payloadData,size_t payloadSize,uint32_t * offset)197 size_t RTPFile::Read(RTPHeader* rtp_header,
198                      uint8_t* payloadData,
199                      size_t payloadSize,
200                      uint32_t* offset) {
201   uint16_t lengthBytes;
202   uint16_t plen;
203   uint8_t rtpHeader[12];
204   size_t read_len = fread(&lengthBytes, 2, 1, _rtpFile);
205   /* Check if we have reached end of file. */
206   if ((read_len == 0) && feof(_rtpFile)) {
207     _rtpEOF = true;
208     return 0;
209   }
210   EXPECT_EQ(1u, fread(&plen, 2, 1, _rtpFile));
211   EXPECT_EQ(1u, fread(offset, 4, 1, _rtpFile));
212   lengthBytes = ntohs(lengthBytes);
213   plen = ntohs(plen);
214   *offset = ntohl(*offset);
215   EXPECT_GT(plen, 11);
216 
217   EXPECT_EQ(1u, fread(rtpHeader, 12, 1, _rtpFile));
218   ParseRTPHeader(rtp_header, rtpHeader);
219   EXPECT_EQ(lengthBytes, plen + 8);
220 
221   if (plen == 0) {
222     return 0;
223   }
224   if (lengthBytes < 20) {
225     return 0;
226   }
227   if (payloadSize < static_cast<size_t>((lengthBytes - 20))) {
228     return 0;
229   }
230   lengthBytes -= 20;
231   EXPECT_EQ(lengthBytes, fread(payloadData, 1, lengthBytes, _rtpFile));
232   return lengthBytes;
233 }
234 
235 }  // namespace webrtc
236