blob: 77b29ecadec6271063e0a6a288ae498261c935ca [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
26#include <cassert>
27
28#include "gtest/gtest.h"
29#include "webrtc/typedefs.h"
30
31/*********************/
32/* Misc. definitions */
33/*********************/
34
35#define FIRSTLINELEN 40
36#define CHECK_NOT_NULL(a) if((a)==NULL){fprintf(stderr,"\n %s \n line: %d \nerror at %s\n",__FILE__,__LINE__,#a );return(-1);}
37
38struct arr_time {
39 float time;
40 WebRtc_UWord32 ix;
41};
42
43int filelen(FILE *fid)
44{
45 fpos_t cur_pos;
46 int len;
47
48 if (!fid || fgetpos(fid, &cur_pos)) {
49 return(-1);
50 }
51
52 fseek(fid, 0, SEEK_END);
53 len = ftell(fid);
54
55 fsetpos(fid, &cur_pos);
56
57 return (len);
58}
59
60int compare_arr_time(const void *x, const void *y);
61
62int main(int argc, char* argv[])
63{
64 unsigned int dat_len, rtp_len, Npack, k;
65 arr_time *time_vec;
66 char firstline[FIRSTLINELEN];
67 unsigned char *rtp_vec = NULL, **packet_ptr, *temp_packet;
68 const unsigned int kRtpDumpHeaderSize = 4 + 4 + 4 + 2 + 2;
69 WebRtc_UWord16 len;
70 WebRtc_UWord32 *offset;
71
72/* check number of parameters */
73 if (argc != 4) {
74 /* print help text and exit */
75 printf("Apply jitter on RTP stream.\n");
76 printf("The program reads an RTP stream and packet timing from two files.\n");
77 printf("The RTP stream is modified to have the same jitter as described in the timing files.\n");
78 printf("The format of the RTP stream file should be the same as for rtpplay,\n");
79 printf("and can be obtained e.g., from Ethereal by using\n");
80 printf("Statistics -> RTP -> Show All Streams -> [select a stream] -> Save As\n\n");
81 printf("Usage:\n\n");
82 printf("%s RTP_infile dat_file RTP_outfile\n", argv[0]);
83 printf("where:\n");
84
85 printf("RTP_infile : RTP stream input file\n\n");
86
87 printf("dat_file : file with packet arrival times in ms\n\n");
88
89 printf("RTP_outfile : RTP stream output file\n\n");
90
91 return(0);
92 }
93
94 FILE* in_file=fopen(argv[1],"rb");
95 CHECK_NOT_NULL(in_file);
96 printf("Input file: %s\n",argv[1]);
97 FILE* dat_file=fopen(argv[2],"rb");
98 CHECK_NOT_NULL(dat_file);
99 printf("Dat-file: %s\n",argv[2]);
100 FILE* out_file=fopen(argv[3],"wb");
101 CHECK_NOT_NULL(out_file);
102 printf("Output file: %s\n\n",argv[3]);
103
104 time_vec = (arr_time *) malloc(sizeof(arr_time)*(filelen(dat_file)/sizeof(float)) + 1000); // add 1000 bytes to avoid (rare) strange error
105 if (time_vec==NULL) {
106 fprintf(stderr, "Error: could not allocate memory for reading dat file\n");
107 goto closing;
108 }
109
110 dat_len=0;
111 while(fread(&(time_vec[dat_len].time),sizeof(float),1,dat_file)>0) {
112 time_vec[dat_len].ix=dat_len;
113 dat_len++;
114 }
115
116 qsort(time_vec,dat_len,sizeof(arr_time),compare_arr_time);
117
118
119 rtp_vec = (unsigned char *) malloc(sizeof(unsigned char)*filelen(in_file));
120 if (rtp_vec==NULL) {
121 fprintf(stderr,"Error: could not allocate memory for reading rtp file\n");
122 goto closing;
123 }
124
125 // read file header and write directly to output file
126 EXPECT_TRUE(fgets(firstline, FIRSTLINELEN, in_file) != NULL);
127 EXPECT_GT(fputs(firstline, out_file), 0);
128 EXPECT_EQ(kRtpDumpHeaderSize, fread(firstline, 1, kRtpDumpHeaderSize,
129 in_file));
130 EXPECT_EQ(kRtpDumpHeaderSize, fwrite(firstline, 1, kRtpDumpHeaderSize,
131 out_file));
132
133 // read all RTP packets into vector
134 rtp_len=0;
135 Npack=0;
136 len=(WebRtc_UWord16) fread(&rtp_vec[rtp_len], sizeof(unsigned char), 2, in_file); // read length of first packet
137 while(len==2) {
138 len = ntohs(*((WebRtc_UWord16 *)(rtp_vec + rtp_len)));
139 rtp_len += 2;
140 if(fread(&rtp_vec[rtp_len], sizeof(unsigned char), len-2, in_file)!=(unsigned) (len-2)) {
141 fprintf(stderr,"Error: currupt packet length\n");
142 goto closing;
143 }
144 rtp_len += len-2;
145 Npack++;
146 len=(WebRtc_UWord16) fread(&rtp_vec[rtp_len], sizeof(unsigned char), 2, in_file); // read length of next packet
147 }
148
149 packet_ptr = (unsigned char **) malloc(Npack*sizeof(unsigned char*));
150
151 packet_ptr[0]=rtp_vec;
152 k=1;
153 while(k<Npack) {
154 len = ntohs(*((WebRtc_UWord16 *) packet_ptr[k-1]));
155 packet_ptr[k]=packet_ptr[k-1]+len;
156 k++;
157 }
158
159 for(k=0; k<dat_len && k<Npack; k++) {
160 if(time_vec[k].time < FLT_MAX && time_vec[k].ix < Npack){
161 temp_packet = packet_ptr[time_vec[k].ix];
162 offset = (WebRtc_UWord32 *) (temp_packet+4);
163 if ( time_vec[k].time >= 0 ) {
164 *offset = htonl((WebRtc_UWord32) time_vec[k].time);
165 }
166 else {
167 *offset = htonl((WebRtc_UWord32) 0);
168 fprintf(stderr, "Warning: negative receive time in dat file transformed to 0.\n");
169 }
170
171 // write packet to file
172 if (fwrite(temp_packet, sizeof(unsigned char),
173 ntohs(*((WebRtc_UWord16*) temp_packet)),
174 out_file) !=
175 ntohs(*((WebRtc_UWord16*) temp_packet))) {
176 return -1;
177 }
178 }
179 }
180
181
182closing:
183 free(time_vec);
184 free(rtp_vec);
185 fclose(in_file);
186 fclose(dat_file);
187 fclose(out_file);
188
189 return(0);
190}
191
192
193
194int compare_arr_time(const void *xp, const void *yp) {
195
196 if(((arr_time *)xp)->time == ((arr_time *)yp)->time)
197 return(0);
198 else if(((arr_time *)xp)->time > ((arr_time *)yp)->time)
199 return(1);
200
201 return(-1);
202}