root/rat/trunk/session.c @ 2058

Revision 2058, 18.5 KB (checked in by ucaccsp, 16 years ago)

Remove tool.rat.redundancy and tool.rat.interleaving, and merge their
functions into audio.channel.coding

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2 * FILE:    session.c
3 * PROGRAM: RAT
4 * AUTHORS: Vicky Hardman + Isidor Kouvelas + Colin Perkins + Orion Hodson
5 *
6 * $Revision$
7 * $Date$
8 *
9 * Copyright (c) 1995,1996,1997 University College London
10 * All rights reserved.
11 *
12 * Redistribution and use in source and binary forms, with or without
13 * modification, is permitted, for non-commercial use only, provided
14 * that the following conditions are met:
15 * 1. Redistributions of source code must retain the above copyright
16 *    notice, this list of conditions and the following disclaimer.
17 * 2. Redistributions in binary form must reproduce the above copyright
18 *    notice, this list of conditions and the following disclaimer in the
19 *    documentation and/or other materials provided with the distribution.
20 * 3. All advertising materials mentioning features or use of this software
21 *    must display the following acknowledgement:
22 *      This product includes software developed by the Computer Science
23 *      Department at University College London
24 * 4. Neither the name of the University nor of the Department may be used
25 *    to endorse or promote products derived from this software without
26 *    specific prior written permission.
27 * Use of this software for commercial purposes is explicitly forbidden
28 * unless prior written permission is obtained from the authors.
29 *
30 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
31 * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
32 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
33 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
34 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
38 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
39 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 * SUCH DAMAGE.
41 */
42
43#include "config_unix.h"
44#include "config_win32.h"
45#include "assert.h"
46#include "debug.h"
47#include "memory.h"
48#include "version.h"
49#include "session.h"
50#include "timers.h"
51#include "repair.h"
52#include "codec.h"
53#include "receive.h"
54#include "convert.h"
55#include "channel.h"
56#include "parameters.h"
57#include "audio.h"
58#include "ui.h"
59#include "crypt.h"
60
61static void 
62usage(void)
63{
64        printf("Usage: rat [options] -t <ttl> <addr>/<port>\n");
65        exit(1);
66}
67
68void
69init_session(session_struct *sp)
70{
71        struct hostent *addr;
72        u_long          netaddr;
73        char            hostname[MAXHOSTNAMELEN + 1];
74        struct s_codec  *cp;
75
76        memset(sp, 0, sizeof(session_struct));
77
78        set_dynamic_payload(&sp->dpt_list, "WBS-16K-MONO",   PT_WBS_16K_MONO);
79        set_dynamic_payload(&sp->dpt_list, "L16-8K-MONO",    PT_L16_8K_MONO);
80        set_dynamic_payload(&sp->dpt_list, "L16-8K-STEREO",  PT_L16_8K_STEREO);
81        set_dynamic_payload(&sp->dpt_list, "L16-16K-MONO",   PT_L16_16K_MONO);
82        set_dynamic_payload(&sp->dpt_list, "L16-16K-STEREO", PT_L16_16K_STEREO);
83        set_dynamic_payload(&sp->dpt_list, "L16-32K-MONO",   PT_L16_32K_MONO);
84        set_dynamic_payload(&sp->dpt_list, "L16-32K-STEREO", PT_L16_32K_STEREO);
85        set_dynamic_payload(&sp->dpt_list, "L16-48K-MONO",   PT_L16_48K_MONO);
86        set_dynamic_payload(&sp->dpt_list, "L16-48K-STEREO", PT_L16_48K_STEREO);
87
88        codec_init(sp);
89        vu_table_init();
90        cp = get_codec_by_name("DVI-8K-MONO");
91        channel_set_coder(sp, PT_VANILLA);
92        sp->last_depart_ts              = 1;
93        sp->encodings[0]                = cp->pt;       /* user chosen encoding for primary */
94        sp->num_encodings               = 1;            /* Number of encodings in packet */
95        sp->next_encoding               = -1; /* Coding to change to */
96        sp->clock                       = new_fast_time(GLOBAL_CLOCK_FREQ); /* this is the global clock */
97        sp->device_clock                = new_time(sp->clock, cp->freq);
98        assert(!(GLOBAL_CLOCK_FREQ%cp->freq));                        /* just in case someone adds weird freq codecs */
99        sp->collator                    = collator_create();
100        sp->mode                        = AUDIO_TOOL;   
101        sp->input_mode                  = AUDIO_NO_DEVICE;
102        sp->output_mode                 = AUDIO_NO_DEVICE;
103        sp->rtp_port                    = 5004;         /* default: draft-ietf-avt-profile-new-00 */
104        sp->rtcp_port                   = 5005;         /* default: draft-ietf-avt-profile-new-00 */
105        sp->ttl                         = 16;
106        sp->rtp_socket                  = NULL;
107        sp->rtcp_socket                 = NULL;
108        sp->filter_loopback             = TRUE;
109        sp->sending_audio               = FALSE;
110        sp->playing_audio               = TRUE;
111        sp->lecture                     = FALSE;
112        sp->auto_lecture                = 0;
113        sp->transmit_audit_required     = FALSE;
114        sp->receive_audit_required      = FALSE;
115        sp->detect_silence              = TRUE;
116        sp->sync_on                     = FALSE;
117        sp->agc_on                      = FALSE;
118        sp->ui_on                       = TRUE;
119        sp->ui_addr                     = NULL;
120        sp->repair                      = REPAIR_REPEAT;/* Packet repetition */
121        sp->meter                       = TRUE;         /* Powermeter operation */
122        sp->drop                        = 0.0;
123        sp->in_file                     = NULL;
124        sp->out_file                    = NULL;
125        sp->audio_device                = 0;
126        sp->rtp_seq                     = lrand48() & 0xffff;
127        sp->speakers_active             = NULL;
128        sp->mbus_engine_base            = NULL;
129        sp->mbus_engine_conf            = NULL;
130        sp->mbus_ui_base                = NULL;
131        sp->mbus_ui_conf                = NULL;
132        sp->mbus_channel                = 0;
133        sp->min_playout                 = 0;
134        sp->max_playout                 = 1000;
135        sp->wait_on_startup             = FALSE;
136        sp->next_selected_device        = -1;
137
138        strcpy(sp->title, "<Untitled Session>");
139       
140        if (gethostname(hostname, MAXHOSTNAMELEN + 1) != 0) {
141                perror("Cannot get hostname");
142                abort();
143        }
144        if ((addr = gethostbyname(hostname)) == NULL) {
145                perror("Cannot get host address");
146                abort();
147        }
148        memcpy(&netaddr, addr->h_addr, 4);
149        sp->ipaddr = ntohl(netaddr);
150
151        gettimeofday(&(sp->device_time), NULL);
152
153        strcpy(sp->asc_address, "127.0.0.3");   /* Yeuch! This value should never be used! */
154}
155
156void
157end_session(session_struct *sp)
158{
159        codec_end(sp);
160        free_fast_time(sp->clock);
161        if (sp->device_clock) {
162                xfree(sp->device_clock);
163                sp->device_clock = NULL;
164        }
165        collator_destroy(sp->collator);
166}
167
168static void 
169parse_early_options_common(int argc, char *argv[], session_struct *sp[], int sp_size)
170{
171        /* Parse command-line options common to all the modes of operation.     */
172        /* Variables: i scans through the options, s scans through the sessions */
173        /* This is for options set initially, before the main initialisation is */
174        /* done. For example, the UI is not yet setup, and anything initialised */
175        /* there will overwrite changes made here...                            */
176        int i, s;
177
178        for (i = 1; i < argc; i++) {
179                for (s = 0; s < sp_size; s++) {
180                        if ((strcmp(argv[i], "-ui") == 0) && (argc > i+1)) {
181                                sp[s]->ui_on   = FALSE;
182                                sp[s]->ui_addr = strdup(argv[i+1]);
183                        }
184                        if (strcmp(argv[i], "-allowloopback") == 0 || strcmp(argv[i], "-allow_loopback") == 0) {
185                                sp[s]->filter_loopback = FALSE;
186                        }
187                        if ((strcmp(argv[i], "-C") == 0) && (argc > i+1)) {
188                                strncpy(sp[s]->title, argv[i+1], SESSION_TITLE_LEN);
189                                i++;
190                        }
191                        if ((strcmp(argv[i], "-mbus") == 0) && (argc > i+1)) {
192                                sp[s]->mbus_channel = atoi(argv[i + 1]);
193                                i++;
194                        }
195                        if (strcmp(argv[i], "-wait") == 0) {
196                                sp[s]->wait_on_startup = TRUE;
197                        }
198                        if ((strcmp(argv[i], "-t") == 0) && (argc > i+1)) {
199                                sp[s]->ttl = atoi(argv[i + 1]);
200                                if (sp[s]->ttl > 255) {
201                                        usage();
202                                }
203                                i++;
204                        }
205                        if ((strcmp(argv[i], "-p") == 0) && (argc > i+1)) {
206                                if ((thread_pri = atoi(argv[i + 1])) > 3) {
207                                        usage();
208                                }
209                                i++;
210                        }
211                        if ((strcmp(argv[i], "-drop") == 0) && (argc > i+1)) {
212                                sp[s]->drop = (float)atof(argv[++i]);
213                                if (sp[s]->drop > 1.0) {
214                                        sp[s]->drop = sp[s]->drop/100;
215                                }
216                                i++;
217                        }
218                        if (strcmp(argv[i], "-seed") == 0) {
219                                srand48(atoi(argv[++i]));
220                        }
221                        if ((strcmp(argv[i], "-pt") == 0) && (argc > i+1)) {
222                                /* Dynamic payload type mapping. Format: "-pt pt/codec/clock/channels" */
223                                /* pt/codec must be specified. clock and channels are optional.        */
224                                /* At present we only support "-pt .../redundancy"                     */
225                                char *t;
226                                int pt;
227                                pt = atoi(strtok(argv[i + 1], "/"));
228                                if ((pt > 127) || (pt < 96)) {
229                                        printf("Dynamic payload types must be in the range 96-127. So there.\n");
230                                        usage();
231                                }
232                                t = strtok(NULL, "/");
233                                if (!set_cc_pt(t,pt)) {
234                                    printf("Hmmm.... Don't understand that -pt option\n");
235                                    usage();
236                                }
237                                i++;
238                        }
239                }
240        }
241}
242
243static void 
244parse_early_options_audio_tool(int argc, char *argv[], session_struct *sp)
245{
246        /* Parse command-line options specific to the audio tool */
247        char *p;
248
249        p = strtok(argv[argc - 1], "/");
250        strcpy(sp->asc_address, p);
251        if ((p = strtok(NULL, "/")) != NULL) {
252                sp->rtp_port = atoi(p);
253                sp->rtp_port &= ~1;
254                sp->rtcp_port = sp->rtp_port + 1;
255        }
256}
257
258static void 
259parse_early_options_transcoder(int argc, char *argv[], session_struct *sp[])
260{
261        /* Parse command-line options specific to the transcoder */
262        int   i, j;
263        char *p;
264
265        if (argc < 4) {
266                usage();
267        }
268
269        for (i = 0; i < 2; i++) {
270                /* addr */
271                p = strtok(argv[argc-i-1], "/");
272                strcpy(sp[i]->asc_address, p);
273                /* port */
274                if ((p = strtok(NULL, "/")) != NULL) {
275                        sp[i]->rtp_port  = atoi(p);
276                        sp[i]->rtp_port &= ~1;
277                        sp[i]->rtcp_port = sp[i]->rtp_port + 1;
278                } else {
279                        continue;
280                }
281                /* ttl */
282                if ((p = strtok(NULL, "/")) != NULL) {
283                        sp[i]->ttl = atoi(p);
284                } else {
285                        continue;
286                }
287                /* encoding */
288                j = 0;
289                while ((p = strtok(NULL, "/")) != NULL) {
290                        codec_t *cp;
291                        char *pu;
292                        for (pu = p; *pu; pu++)
293                                        *pu = toupper(*pu);
294                        if ((cp = get_codec_by_name(p)) == NULL)
295                                usage();
296                        else {
297                                sp[i]->encodings[j]  = cp->pt;
298                                sp[i]->num_encodings = ++j;
299                        }
300                }
301        }
302}
303
304int
305parse_early_options(int argc, char *argv[], session_struct *sp[])
306{
307        int     i, num_sessions = 0;
308
309        if (argc < 2) {
310                usage();
311        }
312        /* Set the mode of operation, and number of valid sessions, based on the first command line option. */
313        if (strcmp(argv[1], "-version") == 0) {
314                printf("%s\n", RAT_VERSION);
315                exit(0);
316        } else if (strcmp(argv[1], "-T") == 0) {
317                sp[0]->mode = TRANSCODER;
318                sp[1]->mode = TRANSCODER;
319                num_sessions= 2;
320        } else {
321                sp[0]->mode = AUDIO_TOOL;
322                num_sessions= 1;
323        }
324        parse_early_options_common(argc, argv, sp, num_sessions);
325        switch (sp[0]->mode) {
326                case AUDIO_TOOL: parse_early_options_audio_tool(argc, argv, sp[0]);
327                                 break;
328                case TRANSCODER: parse_early_options_transcoder(argc, argv, sp);
329                                 break;
330                default        : abort();
331        }
332        for (i=0; i<num_sessions; i++) {
333                if (sp[i]->rtp_port == 0) {
334                        usage();
335                }
336        }
337        return num_sessions;
338}
339
340/************************************************************************************************************/
341
342static void 
343parse_late_options_common(int argc, char *argv[], session_struct *sp[], int sp_size)
344{
345        /* Parse command-line options common to all the modes of operation.     */
346        /* Variables: i scans through the options, s scans through the sessions */
347        /* This is the final chance to set any options, before the main program */
348        /* starts. In particular, it is done after the UI has been configured.  */
349        /* Remember: if anything here changes the state of the system, you must */
350        /* update the UI too!                                                   */
351        int i, s;
352
353        for (i = 1; i < argc; i++) {
354                for (s = 0; s < sp_size; s++) {
355                        if (strcmp(argv[i], "-K") == 0) {
356                                argv[i] = "-crypt";
357                        }
358                        if ((strcmp(argv[i], "-crypt") == 0) && (argc > i+1)) {
359                                Set_Key(argv[i+1]);
360                                ui_update_key(sp[s], argv[i+1]);
361                                i++;
362                        }
363                        if (strcmp(argv[i], "-sync") == 0) {
364                                if (sp[s]->mbus_channel != 0) {
365                                        sp[s]->sync_on = TRUE;
366                                } else {
367                                        printf("Lip-sync can only be used if an mbus channel is specified\n");
368                                        usage();
369                                }
370                        }
371                        if ((strcmp(argv[i], "-agc") == 0) && (argc > i+1)) {
372                                if (strcmp(argv[i+1], "on") == 0) {
373                                        sp[s]->agc_on = TRUE;
374                                        i++;
375                                } else if (strcmp(argv[i+1], "off") == 0) {
376                                        sp[s]->agc_on = FALSE;
377                                        i++;
378                                } else {
379                                        printf("Unrecognized -agc option.\n");
380                                }
381                        }
382                        if ((strcmp(argv[i], "-silence") == 0) && (argc > i+1)) {
383                                if (strcmp(argv[i+1], "on") == 0) {
384                                        sp[s]->detect_silence = TRUE;
385                                        i++;
386                                } else if (strcmp(argv[i+1], "off") == 0) {
387                                        sp[s]->detect_silence = FALSE;
388                                        i++;
389                                } else {
390                                        printf("Unrecognized -silence option.\n");
391                                }
392                        }       
393                        if ((strcmp(argv[i], "-repair") == 0) && (argc > i+1)) {
394                                if (strncmp(argv[i+1], "none", 4)==0) {
395                                        sp[s]->repair = REPAIR_NONE;
396                                        i++;
397                                } else if (strncmp(argv[i+1], "repeat", 6)==0) {
398                                        sp[s]->repair = REPAIR_REPEAT;
399                                        i++;
400                                } else {
401                                        printf("Unsupported -repair option: %s\n", argv[i++]);
402                                }
403                        }
404                        if ((strcmp(argv[i], "-interleave") == 0) && (argc > i+1)) {
405                                /* expects string of form "codec/units/separation" */
406                                int pt = get_cc_pt(sp[s], "interleaver");
407                                if (pt != -1) {
408                                        debug_msg("Configure interleaver %d %s\n", pt, argv[i+1]);
409                                        config_channel_coder(sp[s], pt, argv[i+1]);
410                                        channel_set_coder(sp[s], pt);
411                                        ui_update_channel(sp[s]);
412                                } else {
413                                        printf("Can't determine interleaver payload type\n");
414                                        abort();
415                                }
416                                i++;
417                        }
418                        if ((strcmp(argv[i], "-redundancy") == 0) && (argc > i+1)) {
419                                /* Takes "-redundancy  redundant_codec/offset" */
420                                codec_t *pcp = get_codec_by_pt(sp[s]->encodings[0]);
421                                int      pt  = get_cc_pt(sp[s], "redundancy");
422                                char     cfg[80];
423
424                                sprintf(cfg, "%s/0/%s", pcp->name, argv[i+1]);
425                                debug_msg("Configure redundancy %s\n", cfg);
426                                config_channel_coder(sp[s], pt, cfg);
427                                channel_set_coder(sp[s], pt);
428                                ui_update_primary(sp[s]);
429                                ui_update_channel(sp[s]);
430                                i++;
431                        }
432                        if ((strcmp(argv[i], "-f") == 0) && (argc > i+1)) {
433                                codec_t *cp;
434                                char    *pu;
435                                int      pt;
436                                for (pu = argv[i+1]; *pu; pu++) {
437                                        *pu = toupper(*pu);
438                                }
439                                pu = argv[i+1];
440                                if ((cp = get_codec_by_name(pu)) != NULL) {
441                                        change_freq(sp[s]->device_clock, cp->freq);
442                                        sp[s]->encodings[0]  = cp->pt;
443                                        sp[s]->num_encodings = 1;
444                                        channel_set_coder(sp[s], get_cc_pt(sp[s], "vanilla"));
445                                        debug_msg("Configure codec %d\n", sp[s]->encodings[0]);
446                                } else if (((pt = codec_matching(pu, 8000, 1)) != -1) && ((cp = get_codec_by_pt(pt)) != NULL)) {
447                                        change_freq(sp[s]->device_clock, cp->freq);
448                                        sp[s]->encodings[0]  = cp->pt;
449                                        sp[s]->num_encodings = 1;
450                                        channel_set_coder(sp[s], get_cc_pt(sp[s], "vanilla"));
451                                        debug_msg("Configure codec %d\n", sp[s]->encodings[0]);
452                                } else {
453                                        /* This is not a valid codec name. One last chance: it might be a */
454                                        /* combined codec and redundancy specifier such as "dvi+lpc" used */
455                                        /* by sdr. Try to parse it that way, just in case...        [csp] */
456                                        char *pri_name = strtok(argv[i+1], "/");
457                                        char *sec_name = strtok(NULL, "/");
458                                        int   pri_pt, sec_pt;
459                                        codec_t *pri_cp, *sec_cp;
460                                        char     cfg[80];
461                                        int     red_pt;
462
463                                        if (pri_name == NULL || sec_name == NULL) {
464                                                printf("Unknown codec\n");
465                                                usage();
466                                        }
467                                        if (((pri_pt = codec_matching(pri_name, 8000, 1)) == -1) || ((pri_cp = get_codec_by_pt(pri_pt)) == NULL)) {
468                                                printf("Unknown primary codec\n");
469                                                usage();
470                                        }
471                                        if (((sec_pt = codec_matching(sec_name, 8000, 1)) == -1) || ((sec_cp = get_codec_by_pt(sec_pt)) == NULL)) {
472                                                printf("Unknown redundant codec\n");
473                                                usage();
474                                        }
475                                        change_freq(sp[s]->device_clock, pri_cp->freq);
476                                        sp[s]->encodings[0]  = pri_cp->pt;
477                                        sp[s]->num_encodings = 1;
478                                        sprintf(cfg, "%s/0/%s/1", pri_cp->name, sec_cp->name);
479                                        debug_msg("Configuring codec+redundancy: %s+%s\n", pri_name, sec_name);
480                                        red_pt = get_cc_pt(sp[s], "redundancy");
481                                        config_channel_coder(sp[s], red_pt, cfg);
482                                        channel_set_coder(sp[s], red_pt);
483                                }
484                                ui_update_primary(sp[s]);
485                                ui_update_channel(sp[s]);
486                                i++;
487                        }
488                }
489        }
490}
491
492static void parse_late_options_audio_tool(int argc, char *argv[], session_struct *sp)
493{
494        /* Audio tool specific late setup... */
495        UNUSED(argc);
496        UNUSED(argv);
497        UNUSED(sp);
498}
499
500static void parse_late_options_transcoder(int argc, char *argv[], session_struct *sp[])
501{
502        /* Transcoder specific late setup... */
503        int     i;
504
505        UNUSED(argc);
506        UNUSED(argv);
507
508        for (i = 0; i < 2; i++) {
509                sp[i]->playing_audio = TRUE;
510                sp[i]->agc_on        = FALSE;
511        }
512}
513
514void parse_late_options(int argc, char *argv[], session_struct *sp[])
515{
516        int     i, num_sessions = 0;
517
518        if (argc < 2) {
519                usage();
520        }
521        /* Set the mode of operation, and number of valid sessions, based on the first command line option. */
522        if (strcmp(argv[1], "-T") == 0) {
523                sp[0]->mode = TRANSCODER;
524                sp[1]->mode = TRANSCODER;
525                num_sessions= 2;
526        } else {
527                sp[0]->mode = AUDIO_TOOL;
528                num_sessions= 1;
529        }
530        parse_late_options_common(argc, argv, sp, num_sessions);
531        switch (sp[0]->mode) {
532                case AUDIO_TOOL: parse_late_options_audio_tool(argc, argv, sp[0]);
533                                 break;
534                case TRANSCODER: parse_late_options_transcoder(argc, argv, sp);
535                                 break;
536                default        : abort();
537        }
538        for (i=0; i<num_sessions; i++) {
539                if (sp[i]->rtp_port == 0) {
540                        usage();
541                }
542        }
543}
Note: See TracBrowser for help on using the browser.