henrik.lundin@webrtc.org | d94659d | 2013-01-29 12:09:21 +0000 | [diff] [blame] | 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 | //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.org | 12dc1a3 | 2013-08-05 16:22:53 +0000 | [diff] [blame] | 26 | #include <assert.h> |
henrik.lundin@webrtc.org | d94659d | 2013-01-29 12:09:21 +0000 | [diff] [blame] | 27 | |
Mirko Bonadei | 92ea95e | 2017-09-15 06:47:31 +0200 | [diff] [blame] | 28 | #include "test/gtest.h" |
Mirko Bonadei | 7120742 | 2017-09-15 13:58:09 +0200 | [diff] [blame^] | 29 | #include "typedefs.h" // NOLINT(build/include) |
henrik.lundin@webrtc.org | d94659d | 2013-01-29 12:09:21 +0000 | [diff] [blame] | 30 | |
| 31 | /*********************/ |
| 32 | /* Misc. definitions */ |
| 33 | /*********************/ |
| 34 | |
| 35 | #define FIRSTLINELEN 40 |
kjellander@webrtc.org | 3c0aae1 | 2014-09-04 09:55:40 +0000 | [diff] [blame] | 36 | #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.org | d94659d | 2013-01-29 12:09:21 +0000 | [diff] [blame] | 39 | |
| 40 | struct arr_time { |
kjellander@webrtc.org | 3c0aae1 | 2014-09-04 09:55:40 +0000 | [diff] [blame] | 41 | float time; |
| 42 | uint32_t ix; |
henrik.lundin@webrtc.org | d94659d | 2013-01-29 12:09:21 +0000 | [diff] [blame] | 43 | }; |
| 44 | |
| 45 | int 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 | |
| 62 | int compare_arr_time(const void *x, const void *y); |
| 63 | |
| 64 | int main(int argc, char* argv[]) |
| 65 | { |
kjellander@webrtc.org | 3c0aae1 | 2014-09-04 09:55:40 +0000 | [diff] [blame] | 66 | 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.org | 58cd316 | 2013-10-31 15:15:55 +0000 | [diff] [blame] | 70 | unsigned char** packet_ptr = NULL; |
| 71 | unsigned char* temp_packet = NULL; |
kjellander@webrtc.org | 3c0aae1 | 2014-09-04 09:55:40 +0000 | [diff] [blame] | 72 | const unsigned int kRtpDumpHeaderSize = 4 + 4 + 4 + 2 + 2; |
| 73 | uint16_t len; |
| 74 | uint32_t *offset; |
henrik.lundin@webrtc.org | d94659d | 2013-01-29 12:09:21 +0000 | [diff] [blame] | 75 | |
| 76 | /* check number of parameters */ |
kjellander@webrtc.org | 3c0aae1 | 2014-09-04 09:55:40 +0000 | [diff] [blame] | 77 | 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.org | d94659d | 2013-01-29 12:09:21 +0000 | [diff] [blame] | 90 | |
kjellander@webrtc.org | 3c0aae1 | 2014-09-04 09:55:40 +0000 | [diff] [blame] | 91 | printf("RTP_infile : RTP stream input file\n\n"); |
henrik.lundin@webrtc.org | d94659d | 2013-01-29 12:09:21 +0000 | [diff] [blame] | 92 | |
kjellander@webrtc.org | 3c0aae1 | 2014-09-04 09:55:40 +0000 | [diff] [blame] | 93 | printf("dat_file : file with packet arrival times in ms\n\n"); |
henrik.lundin@webrtc.org | d94659d | 2013-01-29 12:09:21 +0000 | [diff] [blame] | 94 | |
kjellander@webrtc.org | 3c0aae1 | 2014-09-04 09:55:40 +0000 | [diff] [blame] | 95 | printf("RTP_outfile : RTP stream output file\n\n"); |
henrik.lundin@webrtc.org | d94659d | 2013-01-29 12:09:21 +0000 | [diff] [blame] | 96 | |
kjellander@webrtc.org | 3c0aae1 | 2014-09-04 09:55:40 +0000 | [diff] [blame] | 97 | return(0); |
| 98 | } |
henrik.lundin@webrtc.org | d94659d | 2013-01-29 12:09:21 +0000 | [diff] [blame] | 99 | |
kjellander@webrtc.org | 3c0aae1 | 2014-09-04 09:55:40 +0000 | [diff] [blame] | 100 | 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.org | d94659d | 2013-01-29 12:09:21 +0000 | [diff] [blame] | 109 | |
kjellander@webrtc.org | 3c0aae1 | 2014-09-04 09:55:40 +0000 | [diff] [blame] | 110 | // 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.org | 58cd316 | 2013-10-31 15:15:55 +0000 | [diff] [blame] | 124 | 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.org | 3c0aae1 | 2014-09-04 09:55:40 +0000 | [diff] [blame] | 129 | qsort(time_vec,dat_len,sizeof(arr_time),compare_arr_time); |
henrik.lundin@webrtc.org | d94659d | 2013-01-29 12:09:21 +0000 | [diff] [blame] | 130 | |
| 131 | |
kjellander@webrtc.org | 3c0aae1 | 2014-09-04 09:55:40 +0000 | [diff] [blame] | 132 | 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.org | d94659d | 2013-01-29 12:09:21 +0000 | [diff] [blame] | 137 | |
kjellander@webrtc.org | 3c0aae1 | 2014-09-04 09:55:40 +0000 | [diff] [blame] | 138 | // 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.org | d94659d | 2013-01-29 12:09:21 +0000 | [diff] [blame] | 145 | |
kjellander@webrtc.org | 3c0aae1 | 2014-09-04 09:55:40 +0000 | [diff] [blame] | 146 | // read all RTP packets into vector |
| 147 | rtp_len=0; |
| 148 | Npack=0; |
henrik.lundin@webrtc.org | d94659d | 2013-01-29 12:09:21 +0000 | [diff] [blame] | 149 | |
kjellander@webrtc.org | 3c0aae1 | 2014-09-04 09:55:40 +0000 | [diff] [blame] | 150 | // 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.org | 58cd316 | 2013-10-31 15:15:55 +0000 | [diff] [blame] | 162 | |
kjellander@webrtc.org | 3c0aae1 | 2014-09-04 09:55:40 +0000 | [diff] [blame] | 163 | // read length of next packet. |
| 164 | len=(uint16_t) fread(&rtp_vec[rtp_len], sizeof(unsigned char), 2, in_file); |
| 165 | } |
henrik.lundin@webrtc.org | d94659d | 2013-01-29 12:09:21 +0000 | [diff] [blame] | 166 | |
kjellander@webrtc.org | 3c0aae1 | 2014-09-04 09:55:40 +0000 | [diff] [blame] | 167 | if (Npack == 0) { |
| 168 | fprintf(stderr, "Error: No RTP packet found.\n"); |
| 169 | goto closing; |
| 170 | } |
henrik.lundin@webrtc.org | d94659d | 2013-01-29 12:09:21 +0000 | [diff] [blame] | 171 | |
kjellander@webrtc.org | 3c0aae1 | 2014-09-04 09:55:40 +0000 | [diff] [blame] | 172 | packet_ptr = (unsigned char **) malloc(Npack*sizeof(unsigned char*)); |
henrik.lundin@webrtc.org | d94659d | 2013-01-29 12:09:21 +0000 | [diff] [blame] | 173 | |
kjellander@webrtc.org | 3c0aae1 | 2014-09-04 09:55:40 +0000 | [diff] [blame] | 174 | 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.org | d94659d | 2013-01-29 12:09:21 +0000 | [diff] [blame] | 204 | |
| 205 | |
| 206 | closing: |
kjellander@webrtc.org | 3c0aae1 | 2014-09-04 09:55:40 +0000 | [diff] [blame] | 207 | free(time_vec); |
| 208 | free(rtp_vec); |
turaj@webrtc.org | 58cd316 | 2013-10-31 15:15:55 +0000 | [diff] [blame] | 209 | if (packet_ptr != NULL) { |
kjellander@webrtc.org | 3c0aae1 | 2014-09-04 09:55:40 +0000 | [diff] [blame] | 210 | free(packet_ptr); |
turaj@webrtc.org | 58cd316 | 2013-10-31 15:15:55 +0000 | [diff] [blame] | 211 | } |
| 212 | fclose(in_file); |
kjellander@webrtc.org | 3c0aae1 | 2014-09-04 09:55:40 +0000 | [diff] [blame] | 213 | fclose(dat_file); |
| 214 | fclose(out_file); |
henrik.lundin@webrtc.org | d94659d | 2013-01-29 12:09:21 +0000 | [diff] [blame] | 215 | |
kjellander@webrtc.org | 3c0aae1 | 2014-09-04 09:55:40 +0000 | [diff] [blame] | 216 | return(0); |
henrik.lundin@webrtc.org | d94659d | 2013-01-29 12:09:21 +0000 | [diff] [blame] | 217 | } |
| 218 | |
| 219 | |
| 220 | |
| 221 | int compare_arr_time(const void *xp, const void *yp) { |
| 222 | |
kjellander@webrtc.org | 3c0aae1 | 2014-09-04 09:55:40 +0000 | [diff] [blame] | 223 | 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.org | d94659d | 2013-01-29 12:09:21 +0000 | [diff] [blame] | 227 | |
kjellander@webrtc.org | 3c0aae1 | 2014-09-04 09:55:40 +0000 | [diff] [blame] | 228 | return(-1); |
henrik.lundin@webrtc.org | d94659d | 2013-01-29 12:09:21 +0000 | [diff] [blame] | 229 | } |