blob: eeb4c90140cbb985d4dd7c779ec8818b836c3277 [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
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;
pbos@webrtc.org0946a562013-04-09 00:28:06 +000040 uint32_t ix;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000041};
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];
turaj@webrtc.org58cd3162013-10-31 15:15:55 +000067 unsigned char* rtp_vec = NULL;
68 unsigned char** packet_ptr = NULL;
69 unsigned char* temp_packet = NULL;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000070 const unsigned int kRtpDumpHeaderSize = 4 + 4 + 4 + 2 + 2;
pbos@webrtc.org0946a562013-04-09 00:28:06 +000071 uint16_t len;
72 uint32_t *offset;
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +000073
74/* check number of parameters */
75 if (argc != 4) {
76 /* print help text and exit */
77 printf("Apply jitter on RTP stream.\n");
78 printf("The program reads an RTP stream and packet timing from two files.\n");
79 printf("The RTP stream is modified to have the same jitter as described in the timing files.\n");
80 printf("The format of the RTP stream file should be the same as for rtpplay,\n");
81 printf("and can be obtained e.g., from Ethereal by using\n");
82 printf("Statistics -> RTP -> Show All Streams -> [select a stream] -> Save As\n\n");
83 printf("Usage:\n\n");
84 printf("%s RTP_infile dat_file RTP_outfile\n", argv[0]);
85 printf("where:\n");
86
87 printf("RTP_infile : RTP stream input file\n\n");
88
89 printf("dat_file : file with packet arrival times in ms\n\n");
90
91 printf("RTP_outfile : RTP stream output file\n\n");
92
93 return(0);
94 }
95
96 FILE* in_file=fopen(argv[1],"rb");
97 CHECK_NOT_NULL(in_file);
98 printf("Input file: %s\n",argv[1]);
99 FILE* dat_file=fopen(argv[2],"rb");
100 CHECK_NOT_NULL(dat_file);
101 printf("Dat-file: %s\n",argv[2]);
102 FILE* out_file=fopen(argv[3],"wb");
103 CHECK_NOT_NULL(out_file);
104 printf("Output file: %s\n\n",argv[3]);
105
106 time_vec = (arr_time *) malloc(sizeof(arr_time)*(filelen(dat_file)/sizeof(float)) + 1000); // add 1000 bytes to avoid (rare) strange error
107 if (time_vec==NULL) {
108 fprintf(stderr, "Error: could not allocate memory for reading dat file\n");
109 goto closing;
110 }
111
112 dat_len=0;
113 while(fread(&(time_vec[dat_len].time),sizeof(float),1,dat_file)>0) {
114 time_vec[dat_len].ix=dat_len;
115 dat_len++;
116 }
117
turaj@webrtc.org58cd3162013-10-31 15:15:55 +0000118 if (dat_len == 0) {
119 fprintf(stderr, "Error: dat_file is empty, no arrival time is given.\n");
120 goto closing;
121 }
122
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000123 qsort(time_vec,dat_len,sizeof(arr_time),compare_arr_time);
124
125
126 rtp_vec = (unsigned char *) malloc(sizeof(unsigned char)*filelen(in_file));
127 if (rtp_vec==NULL) {
128 fprintf(stderr,"Error: could not allocate memory for reading rtp file\n");
129 goto closing;
130 }
131
132 // read file header and write directly to output file
133 EXPECT_TRUE(fgets(firstline, FIRSTLINELEN, in_file) != NULL);
134 EXPECT_GT(fputs(firstline, out_file), 0);
135 EXPECT_EQ(kRtpDumpHeaderSize, fread(firstline, 1, kRtpDumpHeaderSize,
136 in_file));
137 EXPECT_EQ(kRtpDumpHeaderSize, fwrite(firstline, 1, kRtpDumpHeaderSize,
138 out_file));
139
140 // read all RTP packets into vector
141 rtp_len=0;
142 Npack=0;
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000143 len=(uint16_t) fread(&rtp_vec[rtp_len], sizeof(unsigned char), 2, in_file); // read length of first packet
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000144 while(len==2) {
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000145 len = ntohs(*((uint16_t *)(rtp_vec + rtp_len)));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000146 rtp_len += 2;
147 if(fread(&rtp_vec[rtp_len], sizeof(unsigned char), len-2, in_file)!=(unsigned) (len-2)) {
148 fprintf(stderr,"Error: currupt packet length\n");
149 goto closing;
150 }
151 rtp_len += len-2;
152 Npack++;
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000153 len=(uint16_t) fread(&rtp_vec[rtp_len], sizeof(unsigned char), 2, in_file); // read length of next packet
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000154 }
155
turaj@webrtc.org58cd3162013-10-31 15:15:55 +0000156 if (Npack == 0) {
157 fprintf(stderr, "Error: No RTP packet found.\n");
158 goto closing;
159 }
160
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000161 packet_ptr = (unsigned char **) malloc(Npack*sizeof(unsigned char*));
162
163 packet_ptr[0]=rtp_vec;
164 k=1;
165 while(k<Npack) {
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000166 len = ntohs(*((uint16_t *) packet_ptr[k-1]));
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000167 packet_ptr[k]=packet_ptr[k-1]+len;
168 k++;
169 }
170
171 for(k=0; k<dat_len && k<Npack; k++) {
172 if(time_vec[k].time < FLT_MAX && time_vec[k].ix < Npack){
173 temp_packet = packet_ptr[time_vec[k].ix];
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000174 offset = (uint32_t *) (temp_packet+4);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000175 if ( time_vec[k].time >= 0 ) {
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000176 *offset = htonl((uint32_t) time_vec[k].time);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000177 }
178 else {
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000179 *offset = htonl((uint32_t) 0);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000180 fprintf(stderr, "Warning: negative receive time in dat file transformed to 0.\n");
181 }
182
183 // write packet to file
184 if (fwrite(temp_packet, sizeof(unsigned char),
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000185 ntohs(*((uint16_t*) temp_packet)),
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000186 out_file) !=
pbos@webrtc.org0946a562013-04-09 00:28:06 +0000187 ntohs(*((uint16_t*) temp_packet))) {
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000188 return -1;
189 }
190 }
191 }
192
193
194closing:
195 free(time_vec);
196 free(rtp_vec);
turaj@webrtc.org58cd3162013-10-31 15:15:55 +0000197 if (packet_ptr != NULL) {
198 free(packet_ptr);
199 }
200 fclose(in_file);
henrik.lundin@webrtc.orgd94659d2013-01-29 12:09:21 +0000201 fclose(dat_file);
202 fclose(out_file);
203
204 return(0);
205}
206
207
208
209int compare_arr_time(const void *xp, const void *yp) {
210
211 if(((arr_time *)xp)->time == ((arr_time *)yp)->time)
212 return(0);
213 else if(((arr_time *)xp)->time > ((arr_time *)yp)->time)
214 return(1);
215
216 return(-1);
217}