Home | History | Annotate | Download | only in test
      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 
     26 #include <assert.h>
     27 
     28 #include "testing/gtest/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){ \
     37     fprintf(stderr,"\n %s \n line: %d \nerror at %s\n",__FILE__,__LINE__,#a ); \
     38     return(-1);}
     39 
     40 struct arr_time {
     41   float time;
     42   uint32_t ix;
     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 {
     66   unsigned int  dat_len, rtp_len, Npack, k;
     67   arr_time    *time_vec;
     68   char      firstline[FIRSTLINELEN];
     69   unsigned char* rtp_vec = NULL;
     70         unsigned char** packet_ptr = NULL;
     71         unsigned char* temp_packet = NULL;
     72   const unsigned int kRtpDumpHeaderSize = 4 + 4 + 4 + 2 + 2;
     73   uint16_t      len;
     74   uint32_t      *offset;
     75 
     76 /* check number of parameters */
     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");
     90 
     91     printf("RTP_infile       : RTP stream input file\n\n");
     92 
     93     printf("dat_file         : file with packet arrival times in ms\n\n");
     94 
     95     printf("RTP_outfile      : RTP stream output file\n\n");
     96 
     97     return(0);
     98   }
     99 
    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]);
    109 
    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 
    124   if (dat_len == 0) {
    125     fprintf(stderr, "Error: dat_file is empty, no arrival time is given.\n");
    126     goto closing;
    127   }
    128 
    129   qsort(time_vec,dat_len,sizeof(arr_time),compare_arr_time);
    130 
    131 
    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   }
    137 
    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));
    145 
    146   // read all RTP packets into vector
    147   rtp_len=0;
    148   Npack=0;
    149 
    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++;
    162 
    163     // read length of next packet.
    164     len=(uint16_t) fread(&rtp_vec[rtp_len], sizeof(unsigned char), 2, in_file);
    165   }
    166 
    167   if (Npack == 0) {
    168     fprintf(stderr, "Error: No RTP packet found.\n");
    169     goto closing;
    170   }
    171 
    172   packet_ptr = (unsigned char **) malloc(Npack*sizeof(unsigned char*));
    173 
    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   }
    204 
    205 
    206 closing:
    207   free(time_vec);
    208   free(rtp_vec);
    209         if (packet_ptr != NULL) {
    210     free(packet_ptr);
    211         }
    212         fclose(in_file);
    213   fclose(dat_file);
    214   fclose(out_file);
    215 
    216   return(0);
    217 }
    218 
    219 
    220 
    221 int compare_arr_time(const void *xp, const void *yp) {
    222 
    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);
    227 
    228   return(-1);
    229 }
    230