blob: ca73292832b440aed2438f8ddc75a0aeccff35a1 [file] [log] [blame]
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +00001/*
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//TODO(hlundin): Reformat file to meet style guide.
12
13/* header includes */
14#include <float.h>
15#include <stdio.h>
16#include <stdlib.h>
17#include <string.h>
18#ifdef WIN32
19#include <winsock2.h>
20#include <io.h>
21#endif
22#ifdef WEBRTC_LINUX
23#include <netinet/in.h>
24#endif
25
pbos@webrtc.org12dc1a32013-08-05 16:22:53 +000026#include <assert.h>
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000027
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020028#include "test/gtest.h"
Mirko Bonadei71207422017-09-15 13:58:09 +020029#include "typedefs.h" // NOLINT(build/include)
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000030
31/*********************/
32/* Misc. definitions */
33/*********************/
34
35#define FIRSTLINELEN 40
kjellander@webrtc.org3c0aae12014-09-04 09:55:40 +000036#define CHECK_NOT_NULL(a) if((a)==NULL){ \
37 fprintf(stderr,"\n %s \n line: %d \nerror at %s\n",__FILE__,__LINE__,#a ); \
38 return(-1);}
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000039
40struct arr_time {
kjellander@webrtc.org3c0aae12014-09-04 09:55:40 +000041 float time;
42 uint32_t ix;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000043};
44
45int filelen(FILE *fid)
46{
47 fpos_t cur_pos;
48 int len;
49
50 if (!fid || fgetpos(fid, &cur_pos)) {
51 return(-1);
52 }
53
54 fseek(fid, 0, SEEK_END);
55 len = ftell(fid);
56
57 fsetpos(fid, &cur_pos);
58
59 return (len);
60}
61
62int compare_arr_time(const void *x, const void *y);
63
64int main(int argc, char* argv[])
65{
kjellander@webrtc.org3c0aae12014-09-04 09:55:40 +000066 unsigned int dat_len, rtp_len, Npack, k;
67 arr_time *time_vec;
68 char firstline[FIRSTLINELEN];
69 unsigned char* rtp_vec = NULL;
turaj@webrtc.org58cd3162013-10-31 15:15:55 +000070 unsigned char** packet_ptr = NULL;
71 unsigned char* temp_packet = NULL;
kjellander@webrtc.org3c0aae12014-09-04 09:55:40 +000072 const unsigned int kRtpDumpHeaderSize = 4 + 4 + 4 + 2 + 2;
73 uint16_t len;
74 uint32_t *offset;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000075
76/* check number of parameters */
kjellander@webrtc.org3c0aae12014-09-04 09:55:40 +000077 if (argc != 4) {
78 /* print help text and exit */
79 printf("Apply jitter on RTP stream.\n");
80 printf("Reads an RTP stream and packet timing from two files.\n");
81 printf("The RTP stream is modified to have the same jitter as described in "
82 "the timing files.\n");
83 printf("The format of the RTP stream file should be the same as for \n");
84 printf("rtpplay, and can be obtained e.g., from Ethereal by using\n");
85 printf("Statistics -> RTP -> Show All Streams -> [select a stream] -> "
86 "Save As\n\n");
87 printf("Usage:\n\n");
88 printf("%s RTP_infile dat_file RTP_outfile\n", argv[0]);
89 printf("where:\n");
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000090
kjellander@webrtc.org3c0aae12014-09-04 09:55:40 +000091 printf("RTP_infile : RTP stream input file\n\n");
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000092
kjellander@webrtc.org3c0aae12014-09-04 09:55:40 +000093 printf("dat_file : file with packet arrival times in ms\n\n");
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000094
kjellander@webrtc.org3c0aae12014-09-04 09:55:40 +000095 printf("RTP_outfile : RTP stream output file\n\n");
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000096
kjellander@webrtc.org3c0aae12014-09-04 09:55:40 +000097 return(0);
98 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000099
kjellander@webrtc.org3c0aae12014-09-04 09:55:40 +0000100 FILE* in_file=fopen(argv[1],"rb");
101 CHECK_NOT_NULL(in_file);
102 printf("Input file: %s\n",argv[1]);
103 FILE* dat_file=fopen(argv[2],"rb");
104 CHECK_NOT_NULL(dat_file);
105 printf("Dat-file: %s\n",argv[2]);
106 FILE* out_file=fopen(argv[3],"wb");
107 CHECK_NOT_NULL(out_file);
108 printf("Output file: %s\n\n",argv[3]);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000109
kjellander@webrtc.org3c0aae12014-09-04 09:55:40 +0000110 // add 1000 bytes to avoid (rare) strange error.
111 time_vec = (arr_time *) malloc(sizeof(arr_time)
112 *(filelen(dat_file)/sizeof(float)) + 1000);
113 if (time_vec==NULL) {
114 fprintf(stderr, "Error: could not allocate memory for reading dat file\n");
115 goto closing;
116 }
117
118 dat_len=0;
119 while(fread(&(time_vec[dat_len].time),sizeof(float),1,dat_file)>0) {
120 time_vec[dat_len].ix=dat_len;
121 dat_len++;
122 }
123
turaj@webrtc.org58cd3162013-10-31 15:15:55 +0000124 if (dat_len == 0) {
125 fprintf(stderr, "Error: dat_file is empty, no arrival time is given.\n");
126 goto closing;
127 }
128
kjellander@webrtc.org3c0aae12014-09-04 09:55:40 +0000129 qsort(time_vec,dat_len,sizeof(arr_time),compare_arr_time);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000130
131
kjellander@webrtc.org3c0aae12014-09-04 09:55:40 +0000132 rtp_vec = (unsigned char *) malloc(sizeof(unsigned char)*filelen(in_file));
133 if (rtp_vec==NULL) {
134 fprintf(stderr,"Error: could not allocate memory for reading rtp file\n");
135 goto closing;
136 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000137
kjellander@webrtc.org3c0aae12014-09-04 09:55:40 +0000138 // read file header and write directly to output file
139 EXPECT_TRUE(fgets(firstline, FIRSTLINELEN, in_file) != NULL);
140 EXPECT_GT(fputs(firstline, out_file), 0);
141 EXPECT_EQ(kRtpDumpHeaderSize, fread(firstline, 1, kRtpDumpHeaderSize,
142 in_file));
143 EXPECT_EQ(kRtpDumpHeaderSize, fwrite(firstline, 1, kRtpDumpHeaderSize,
144 out_file));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000145
kjellander@webrtc.org3c0aae12014-09-04 09:55:40 +0000146 // read all RTP packets into vector
147 rtp_len=0;
148 Npack=0;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000149
kjellander@webrtc.org3c0aae12014-09-04 09:55:40 +0000150 // read length of first packet.
151 len=(uint16_t) fread(&rtp_vec[rtp_len], sizeof(unsigned char), 2, in_file);
152 while(len==2) {
153 len = ntohs(*((uint16_t *)(rtp_vec + rtp_len)));
154 rtp_len += 2;
155 if(fread(&rtp_vec[rtp_len], sizeof(unsigned char),
156 len-2, in_file)!=(unsigned) (len-2)) {
157 fprintf(stderr,"Error: currupt packet length\n");
158 goto closing;
159 }
160 rtp_len += len-2;
161 Npack++;
turaj@webrtc.org58cd3162013-10-31 15:15:55 +0000162
kjellander@webrtc.org3c0aae12014-09-04 09:55:40 +0000163 // read length of next packet.
164 len=(uint16_t) fread(&rtp_vec[rtp_len], sizeof(unsigned char), 2, in_file);
165 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000166
kjellander@webrtc.org3c0aae12014-09-04 09:55:40 +0000167 if (Npack == 0) {
168 fprintf(stderr, "Error: No RTP packet found.\n");
169 goto closing;
170 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000171
kjellander@webrtc.org3c0aae12014-09-04 09:55:40 +0000172 packet_ptr = (unsigned char **) malloc(Npack*sizeof(unsigned char*));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000173
kjellander@webrtc.org3c0aae12014-09-04 09:55:40 +0000174 packet_ptr[0]=rtp_vec;
175 k=1;
176 while(k<Npack) {
177 len = ntohs(*((uint16_t *) packet_ptr[k-1]));
178 packet_ptr[k]=packet_ptr[k-1]+len;
179 k++;
180 }
181
182 for(k=0; k<dat_len && k<Npack; k++) {
183 if(time_vec[k].time < FLT_MAX && time_vec[k].ix < Npack){
184 temp_packet = packet_ptr[time_vec[k].ix];
185 offset = (uint32_t *) (temp_packet+4);
186 if ( time_vec[k].time >= 0 ) {
187 *offset = htonl((uint32_t) time_vec[k].time);
188 }
189 else {
190 *offset = htonl((uint32_t) 0);
191 fprintf(stderr, "Warning: negative receive time in dat file transformed"
192 " to 0.\n");
193 }
194
195 // write packet to file
196 if (fwrite(temp_packet, sizeof(unsigned char),
197 ntohs(*((uint16_t*) temp_packet)),
198 out_file) !=
199 ntohs(*((uint16_t*) temp_packet))) {
200 return -1;
201 }
202 }
203 }
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000204
205
206closing:
kjellander@webrtc.org3c0aae12014-09-04 09:55:40 +0000207 free(time_vec);
208 free(rtp_vec);
turaj@webrtc.org58cd3162013-10-31 15:15:55 +0000209 if (packet_ptr != NULL) {
kjellander@webrtc.org3c0aae12014-09-04 09:55:40 +0000210 free(packet_ptr);
turaj@webrtc.org58cd3162013-10-31 15:15:55 +0000211 }
212 fclose(in_file);
kjellander@webrtc.org3c0aae12014-09-04 09:55:40 +0000213 fclose(dat_file);
214 fclose(out_file);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000215
kjellander@webrtc.org3c0aae12014-09-04 09:55:40 +0000216 return(0);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000217}
218
219
220
221int compare_arr_time(const void *xp, const void *yp) {
222
kjellander@webrtc.org3c0aae12014-09-04 09:55:40 +0000223 if(((arr_time *)xp)->time == ((arr_time *)yp)->time)
224 return(0);
225 else if(((arr_time *)xp)->time > ((arr_time *)yp)->time)
226 return(1);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000227
kjellander@webrtc.org3c0aae12014-09-04 09:55:40 +0000228 return(-1);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000229}