root/branches/streaming-rework/tests/test-timestampedbuffer.cpp

Revision 395, 16.1 kB (checked in by pieterpalmers, 17 years ago)

debugmodule.cpp:
- removed path from the source file name when printing debug messages

IsoStream?.cpp, StreamProcessor?.cpp:
- debug message modifications

StreamProcessorManager?.cpp:
- removed obsolete debug code

AmdtpStreamProcessor?.cpp:
- debug message modifications
- removed DLL that calculates framerate, as it is also calculated in the

TimestampedBuffer?

- converted code to use the new offset feature of the TimestampedBuffer?
- converted code to use the new frame timestamp calculation feature

of the TimestampedBuffer?

- first try at xmit sync code (unfinished)
- fixed 'unable to start' bug in receive SP

bebob_avdevice.cpp:
- added some #ifdef code to test with xmit SP's only (temporary)

TimestampedBuffer?.cpp:
- add offset feature
- add abitrary frame timestamp calculation

Line 
1 /***************************************************************************
2 Copyright (C) 2007 by Pieter Palmers   *
3                                                                         *
4 This program is free software; you can redistribute it and/or modify  *
5 it under the terms of the GNU General Public License as published by  *
6 the Free Software Foundation; either version 2 of the License, or     *
7 (at your option) any later version.                                   *
8                                                                         *
9 This program is distributed in the hope that it will be useful,       *
10 but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12 GNU General Public License for more details.                          *
13                                                                         *
14 You should have received a copy of the GNU General Public License     *
15 along with this program; if not, write to the                         *
16 Free Software Foundation, Inc.,                                       *
17 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
18 ***************************************************************************/
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <argp.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <endian.h>
29
30 #include <signal.h>
31 #include "src/debugmodule/debugmodule.h"
32
33 #include <netinet/in.h>
34
35 #include "src/libstreaming/cycletimer.h"
36
37 #include "src/libutil/TimestampedBuffer.h"
38
39 #include <pthread.h>
40
41 using namespace FreebobUtil;
42
43 class TimestampedBufferTestClient
44     : public TimestampedBufferClient {
45 public:
46     bool processReadBlock(char *data, unsigned int nevents, unsigned int offset) {return true;};
47     bool processWriteBlock(char *data, unsigned int nevents, unsigned int offset) {return true;};
48    
49     void setVerboseLevel(int l) {setDebugLevel(l);};
50 private:
51     DECLARE_DEBUG_MODULE;
52 };
53
54 IMPL_DEBUG_MODULE( TimestampedBufferTestClient, TimestampedBufferTestClient, DEBUG_LEVEL_VERBOSE );
55
56 DECLARE_GLOBAL_DEBUG_MODULE;
57
58 int run;
59 // Program documentation.
60 static char doc[] = "FreeBoB -- Timestamped buffer test\n\n";
61
62 // A description of the arguments we accept.
63 static char args_doc[] = "";
64
65
66 struct arguments
67 {
68     short verbose;
69     uint64_t wrap_at;
70     uint64_t frames_per_packet;
71     uint64_t events_per_frame;
72     float rate;
73     uint64_t total_cycles;
74     uint64_t buffersize;
75     uint64_t start_at_cycle;
76 };
77
78 // The options we understand.
79 static struct argp_option options[] = {
80     {"verbose",     'v',    "n",    0,  "Verbose level" },
81     {"wrap",        'w',    "n",    0,  "Wrap at (ticks) (3072000)" },
82     {"fpp",        'f',    "n",    0,  "Frames per packet (8)" },
83     {"epf",        'e',    "n",    0,  "Events per frame (10)" },
84     {"rate",        'r',    "n",    0,  "Rate (ticks/frame) (512.0)" },
85     {"cycles",        'c',    "n",    0,  "Total cycles to run (2000)" },
86     {"buffersize",        'b',    "n",    0,  "Buffer size (in frames) (1024)" },
87     {"startcycle",        's',    "n",    0,  "Start at cycle (0)" },
88     { 0 }
89 };
90
91 //-------------------------------------------------------------
92
93 // Parse a single option.
94 static error_t
95 parse_opt( int key, char* arg, struct argp_state* state )
96 {
97     // Get the input argument from `argp_parse', which we
98     // know is a pointer to our arguments structure.
99     struct arguments* arguments = ( struct arguments* ) state->input;
100     char* tail;
101
102     switch (key) {
103         case 'v':
104             if (arg) {
105                 arguments->verbose = strtoll( arg, &tail, 0 );
106                 if ( errno ) {
107                     fprintf( stderr, "Could not parse 'verbose' argument\n" );
108                     return ARGP_ERR_UNKNOWN;
109                 }
110             } else {
111                 if ( errno ) {
112                     fprintf( stderr, "Could not parse 'verbose' argument\n" );
113                     return ARGP_ERR_UNKNOWN;
114                 }
115             }
116             break;
117         case 'w':
118             if (arg) {
119                 arguments->wrap_at = strtoll( arg, &tail, 0 );
120                 if ( errno ) {
121                     fprintf( stderr, "Could not parse 'wrap' argument\n" );
122                     return ARGP_ERR_UNKNOWN;
123                 }
124             } else {
125                 if ( errno ) {
126                     fprintf( stderr, "Could not parse 'wrap' argument\n" );
127                     return ARGP_ERR_UNKNOWN;
128                 }
129             }
130             break;
131         case 'f':
132             if (arg) {
133                 arguments->frames_per_packet = strtoll( arg, &tail, 0 );
134                 if ( errno ) {
135                     fprintf( stderr, "Could not parse 'fpp' argument\n" );
136                     return ARGP_ERR_UNKNOWN;
137                 }
138             } else {
139                 if ( errno ) {
140                     fprintf( stderr, "Could not parse 'fpp' argument\n" );
141                     return ARGP_ERR_UNKNOWN;
142                 }
143             }
144             break;
145         case 'e':
146             if (arg) {
147                 arguments->events_per_frame = strtoll( arg, &tail, 0 );
148                 if ( errno ) {
149                     fprintf( stderr, "Could not parse 'epf' argument\n" );
150                     return ARGP_ERR_UNKNOWN;
151                 }
152             } else {
153                 if ( errno ) {
154                     fprintf( stderr, "Could not parse 'epf' argument\n" );
155                     return ARGP_ERR_UNKNOWN;
156                 }
157             }
158             break;
159         case 'c':
160             if (arg) {
161                 arguments->total_cycles = strtoll( arg, &tail, 0 );
162                 if ( errno ) {
163                     fprintf( stderr, "Could not parse 'cycles' argument\n" );
164                     return ARGP_ERR_UNKNOWN;
165                 }
166             } else {
167                 if ( errno ) {
168                     fprintf( stderr, "Could not parse 'cycles' argument\n" );
169                     return ARGP_ERR_UNKNOWN;
170                 }
171             }
172             break;
173         case 's':
174             if (arg) {
175                 arguments->start_at_cycle = strtoll( arg, &tail, 0 );
176                 if ( errno ) {
177                     fprintf( stderr, "Could not parse 'startcycle' argument\n" );
178                     return ARGP_ERR_UNKNOWN;
179                 }
180             } else {
181                 if ( errno ) {
182                     fprintf( stderr, "Could not parse 'startcycle' argument\n" );
183                     return ARGP_ERR_UNKNOWN;
184                 }
185             }
186             break;
187         case 'b':
188             if (arg) {
189                 arguments->buffersize = strtoll( arg, &tail, 0 );
190                 if ( errno ) {
191                     fprintf( stderr, "Could not parse 'buffersize' argument\n" );
192                     return ARGP_ERR_UNKNOWN;
193                 }
194             } else {
195                 if ( errno ) {
196                     fprintf( stderr, "Could not parse 'buffersize' argument\n" );
197                     return ARGP_ERR_UNKNOWN;
198                 }
199             }
200             break;
201         case 'r':
202             if (arg) {
203                 arguments->rate = strtof( arg, &tail );
204                 if ( errno ) {
205                     fprintf( stderr, "Could not parse 'rate' argument\n" );
206                     return ARGP_ERR_UNKNOWN;
207                 }
208             } else {
209                 if ( errno ) {
210                     fprintf( stderr, "Could not parse 'rate' argument\n" );
211                     return ARGP_ERR_UNKNOWN;
212                 }
213             }
214             break;                       
215        default:
216             return ARGP_ERR_UNKNOWN;
217     }
218     return 0;
219 }
220
221 // Our argp parser.
222 static struct argp argp = { options, parse_opt, args_doc, doc };
223
224
225 static void sighandler (int sig)
226 {
227         run = 0;
228 }
229
230 int main(int argc, char *argv[])
231 {
232    
233     TimestampedBuffer *t=NULL;
234     TimestampedBufferTestClient *c=NULL;
235    
236     struct arguments arguments;
237
238     // Default values.
239     arguments.verbose        = 0;
240     arguments.wrap_at = 3072000LLU; // 1000 cycles
241     arguments.frames_per_packet = 8;
242     arguments.events_per_frame = 10;
243     arguments.rate = 512.0;
244     arguments.total_cycles = 2000;
245     arguments.buffersize = 1024;
246     arguments.start_at_cycle = 0;
247    
248     // Parse our arguments; every option seen by `parse_opt' will
249     // be reflected in `arguments'.
250     if ( argp_parse ( &argp, argc, argv, 0, 0, &arguments ) ) {
251         fprintf( stderr, "Could not parse command line\n" );
252         exit(1);
253     }
254    
255     setDebugLevel(arguments.verbose);
256    
257     run=1;
258
259     signal (SIGINT, sighandler);
260     signal (SIGPIPE, sighandler);
261    
262     c=new TimestampedBufferTestClient();
263    
264     if(!c) {
265         debugOutput(DEBUG_LEVEL_NORMAL, "Could not create TimestampedBufferTestClient\n");
266         exit(1);
267     }
268     c->setVerboseLevel(arguments.verbose);
269    
270     t=new TimestampedBuffer(c);
271    
272     if(!t) {
273         debugOutput(DEBUG_LEVEL_NORMAL, "Could not create TimestampedBuffer\n");
274         delete c;
275         exit(1);
276     }
277     t->setVerboseLevel(arguments.verbose);
278
279     t->init();
280    
281     // Setup the buffer
282     t->setBufferSize(arguments.buffersize);
283     t->setEventSize(sizeof(int));
284     t->setEventsPerFrame(arguments.events_per_frame);
285
286     t->setUpdatePeriod(arguments.frames_per_packet);
287     t->setNominalRate(arguments.rate);
288    
289     t->setWrapValue(arguments.wrap_at);
290    
291     t->setTickOffset(10000);
292    
293     t->prepare();
294    
295     usleep(1000);
296    
297     debugOutput(DEBUG_LEVEL_NORMAL, "Start test 1...\n");
298
299     int dummyframe_in[arguments.events_per_frame*arguments.frames_per_packet];
300     int dummyframe_out[arguments.events_per_frame*arguments.frames_per_packet];
301    
302     for (unsigned int i=0;i<arguments.events_per_frame*arguments.frames_per_packet;i++) {
303         dummyframe_in[i]=i;
304     }
305    
306     uint64_t time=arguments.start_at_cycle*3072;
307    
308     // initialize the timestamp
309     uint64_t timestamp=time;
310     if (timestamp >= arguments.wrap_at) {
311         // here we need a modulo because start_at_cycle can be large
312         timestamp %= arguments.wrap_at;
313     }
314     t->setBufferTailTimestamp(timestamp);
315    
316     timestamp += (uint64_t)(arguments.rate * arguments.frames_per_packet);
317     if (timestamp >= arguments.wrap_at) {
318         timestamp -= arguments.wrap_at;
319     }
320    
321     for(unsigned int cycle=arguments.start_at_cycle;
322         cycle < arguments.start_at_cycle+arguments.total_cycles;
323         cycle++) {
324        
325         // simulate the rate adaptation
326         int64_t diff=(time%arguments.wrap_at)-timestamp;
327        
328         if (diff>(int64_t)arguments.wrap_at/2) {
329             diff -= arguments.wrap_at;
330         } else if (diff<(-(int64_t)arguments.wrap_at)/2){
331             diff += arguments.wrap_at;
332         }
333        
334         debugOutput(DEBUG_LEVEL_NORMAL, "Simulating cycle %d @ time=%011llu, diff=%lld\n",cycle,time,diff);
335        
336         if(diff>0) {
337             uint64_t ts_head, fc_head;
338             uint64_t ts_tail, fc_tail;
339            
340             // write one packet
341             t->writeFrames(arguments.frames_per_packet, (char *)&dummyframe_in, timestamp);
342
343             // read the buffer head timestamp
344             t->getBufferHeadTimestamp(&ts_head, &fc_head);
345             t->getBufferTailTimestamp(&ts_tail, &fc_tail);
346             debugOutput(DEBUG_LEVEL_NORMAL,
347                     " TS after write: HEAD: %011llu, FC=%04u\n",
348                     ts_head,fc_head);
349             debugOutput(DEBUG_LEVEL_NORMAL,
350                     "                 TAIL: %011llu, FC=%04u\n",
351                     ts_tail,fc_tail);
352
353             // read one packet
354             t->readFrames(arguments.frames_per_packet, (char *)&dummyframe_out);
355
356             // read the buffer head timestamp
357             t->getBufferHeadTimestamp(&ts_head, &fc_head);
358             t->getBufferTailTimestamp(&ts_tail, &fc_tail);
359             debugOutput(DEBUG_LEVEL_NORMAL,
360                     " TS after write: HEAD: %011llu, FC=%04u\n",
361                     ts_head,fc_head);
362             debugOutput(DEBUG_LEVEL_NORMAL,
363                     "                 TAIL: %011llu, FC=%04u\n",
364                     ts_tail,fc_tail);
365
366             // check
367             bool pass=true;
368             for (unsigned int i=0;i<arguments.events_per_frame*arguments.frames_per_packet;i++) {
369                 pass = pass && (dummyframe_in[i]==dummyframe_out[i]);
370             }
371             if (!pass) {
372                 debugOutput(DEBUG_LEVEL_NORMAL, "write/read check for cycle %d failed\n",cycle);
373             }
374
375             // update the timestamp
376             timestamp += (uint64_t)(arguments.rate * arguments.frames_per_packet);
377             if (timestamp >= arguments.wrap_at) {
378                 timestamp -= arguments.wrap_at;
379             }
380         }
381
382         // simulate the cycle timer clock in ticks
383         time += 3072;
384         if (time >= arguments.wrap_at) {
385             time -= arguments.wrap_at;
386         }
387        
388         // allow for the messagebuffer thread to catch up
389         usleep(200);
390        
391         if(!run) break;
392     }
393
394     // second run, now do block processing
395     debugOutput(DEBUG_LEVEL_NORMAL, "Start test 2...\n");
396     unsigned int blocksize=32;
397     int dummyframe_out_block[arguments.events_per_frame*arguments.frames_per_packet*blocksize];
398    
399     time=arguments.start_at_cycle*3072;
400    
401     // initialize the timestamp
402     timestamp=time;
403     if (timestamp >= arguments.wrap_at) {
404         // here we need a modulo because start_at_cycle can be large
405         timestamp %= arguments.wrap_at;
406     }
407     t->setBufferTailTimestamp(timestamp);
408    
409     timestamp += (uint64_t)(arguments.rate * arguments.frames_per_packet);
410     if (timestamp >= arguments.wrap_at) {
411         timestamp -= arguments.wrap_at;
412     }
413    
414     for(unsigned int cycle=arguments.start_at_cycle;
415         cycle < arguments.start_at_cycle+arguments.total_cycles;
416         cycle++) {
417        
418         // simulate the rate adaptation
419         int64_t diff=(time%arguments.wrap_at)-timestamp;
420        
421         if (diff>(int64_t)arguments.wrap_at/2) {
422             diff -= arguments.wrap_at;
423         } else if (diff<(-(int64_t)arguments.wrap_at)/2){
424             diff += arguments.wrap_at;
425         }
426        
427         debugOutput(DEBUG_LEVEL_NORMAL, "Simulating cycle %d @ time=%011llu, diff=%lld\n",cycle,time,diff);
428        
429         if(diff>0) {
430             uint64_t ts_head, fc_head;
431             uint64_t ts_tail, fc_tail;
432            
433             // write one packet
434             t->writeFrames(arguments.frames_per_packet, (char *)&dummyframe_in, timestamp);
435
436             // read the buffer head timestamp
437             t->getBufferHeadTimestamp(&ts_head, &fc_head);
438             t->getBufferTailTimestamp(&ts_tail, &fc_tail);
439             debugOutput(DEBUG_LEVEL_NORMAL,
440                     " TS after write: HEAD: %011llu, FC=%04u\n",
441                     ts_head,fc_head);
442             debugOutput(DEBUG_LEVEL_NORMAL,
443                     "                 TAIL: %011llu, FC=%04u\n",
444                     ts_tail,fc_tail);
445
446             if (fc_head > blocksize) {
447                 debugOutput(DEBUG_LEVEL_NORMAL,"Reading one block (%u frames)\n",blocksize);
448                
449                 // read one block
450                 t->readFrames(blocksize, (char *)&dummyframe_out_block);
451    
452                 // read the buffer head timestamp
453                 t->getBufferHeadTimestamp(&ts_head, &fc_head);
454                 t->getBufferTailTimestamp(&ts_tail, &fc_tail);
455                 debugOutput(DEBUG_LEVEL_NORMAL,
456                         " TS after read: HEAD: %011llu, FC=%04u\n",
457                         ts_head,fc_head);
458                 debugOutput(DEBUG_LEVEL_NORMAL,
459                         "                TAIL: %011llu, FC=%04u\n",
460                         ts_tail,fc_tail);
461             }
462            
463             // update the timestamp
464             timestamp += (uint64_t)(arguments.rate * arguments.frames_per_packet);
465             if (timestamp >= arguments.wrap_at) {
466                 timestamp -= arguments.wrap_at;
467             }
468         }
469
470         // simulate the cycle timer clock in ticks
471         time += 3072;
472         if (time >= arguments.wrap_at) {
473             time -= arguments.wrap_at;
474         }
475        
476         // allow for the messagebuffer thread to catch up
477         usleep(200);
478        
479         if(!run) break;
480     }
481    
482
483     delete t;
484     delete c;
485        
486     return EXIT_SUCCESS;
487 }
488
489
Note: See TracBrowser for help on using the browser.