Changeset 2866

Show
Ignore:
Timestamp:
10/30/99 11:14:21 (14 years ago)
Author:
ucacoxh
Message:

- Put cont_toged check into source_process packets. Added check for

cont_toged in rtp_callback.

- source_process now takes two time arguments, time, and time + cushion

so source_process_packets can do cont_toged check.

- Added time constants and replaced lots of ts_map32 functions with

them in source.c.

Location:
rat/trunk
Files:
5 modified

Legend:

Unmodified
Added
Removed
  • rat/trunk/MODS

    r2865 r2866  
    907907        - Initialize sp->cur_ts in main_engine, before tx_start.  Should fix  
    908908          occasional assert failure during transmitter startup. 
     909        - Put cont_toged check into source_process packets.  Added check for 
     910          cont_toged in rtp_callback. 
     911        - Added time constants and replaced lots of ts_map32 functions with 
     912          them in source.c. 
    909913 
    910914TODO -- They're features not bugs dammit! 
  • rat/trunk/main_engine.c

    r2865 r2866  
    232232                                        pdb_entry_t *e; 
    233233                                        ts_t         two_secs, delta; 
    234                                         source_process(s, sp->ms, sp->render_3d, sp->repair, cush_ts); 
     234                                        source_process(s, sp->ms, sp->render_3d, sp->repair, sp->cur_ts, cush_ts); 
    235235                                        source_audit(s); 
    236236                                        /* Check for UI update necessary, updating once per 2 secs */ 
  • rat/trunk/rtp_callback.c

    r2817 r2866  
    4545static rtp_assoc_t rtp_as; 
    4646static int rtp_as_inited; 
     47 
     48#define NO_CONT_TOGED_FOR_PLAYOUT_RECALC 4 
    4749 
    4850void  
     
    223225        /* happens when jitter or transit estimate is no longer consistent */ 
    224226        /* with the real world.                                            */ 
    225         if (e->cont_toged == 4) { 
     227        if (e->cont_toged == NO_CONT_TOGED_FOR_PLAYOUT_RECALC) { 
     228                adjust_playout = TRUE; 
    226229                e->cont_toged  = 0; 
    227230        } 
     
    231234        playout = playout_calc(sp, ssrc, src_ts, adjust_playout); 
    232235 
    233         if (ts_gt(sp->cur_ts, playout)) { 
    234                 /* The playout point for this packet has already gone */ 
    235                 /* so it get's discarded.                             */ 
    236                 e->jit_toged  ++; 
    237                 e->cont_toged ++; 
    238         } else { 
    239                 source_add_packet(s, (u_char*)p, RTP_MAX_PACKET_LEN, (u_char)p->pt, playout); 
    240                 e->cont_toged = 0; 
    241         } 
     236        source_add_packet(s, (u_char*)p, RTP_MAX_PACKET_LEN, (u_char)p->pt, playout); 
    242237 
    243238        /* Update persistent database fields. */ 
  • rat/trunk/source.c

    r2858 r2866  
    6868        struct s_pb_iterator       *media_pos; 
    6969        struct s_converter         *converter; 
    70         /* fine grained playout buffer adjustment variables - attempts to correct for clock skew */ 
     70        /* Fine grained playout buffer adjustment variables.  Used in        */ 
     71        /* attempts to correct for clock skew between source and local host. */ 
    7172        skew_t                      skew; 
    7273        ts_t                        skew_adjust; 
    7374        int32                       skew_offenses; 
    74         /* b/w estimation variables */ 
     75        /* b/w estimation variables                                          */ 
    7576        u_int32                     byte_count; 
    7677        ts_t                        byte_count_start; 
     
    7879} source; 
    7980 
    80 /* A linked list is used for sources and this is fine since we mostly 
    81  * expect 1 or 2 sources to be simultaneously active and so efficiency 
    82  * is not a killer.  */ 
     81/* A linked list is used for sources and this is fine since we mostly expect */ 
     82/* 1 or 2 sources to be simultaneously active and so efficiency is not a     */ 
     83/* killer.                                                                   */ 
    8384 
    8485typedef struct s_source_list { 
     
    8788} source_list; 
    8889 
    89 /****************************************************************************/ 
    90 /* Source List functions.  Source List is used as a container for sources   */ 
    91 /****************************************************************************/ 
     90/*****************************************************************************/ 
     91/* Source List functions.  Source List is used as a container for sources    */ 
     92/*****************************************************************************/ 
    9293 
    9394int 
     
    166167} 
    167168 
    168 /****************************************************************************/ 
    169 /* Source functions.  A source is an active audio source.                   */ 
    170 /****************************************************************************/ 
     169/*****************************************************************************/ 
     170/* Timestamp constants and initialization                                    */ 
     171/*****************************************************************************/ 
     172 
     173static ts_t zero_ts;        /* No time at all :-)                            */ 
     174static ts_t keep_source_ts; /* How long source kept after source goes quiet  */ 
     175static ts_t history_ts;     /* How much old audio hang onto for repair usage */ 
     176static ts_t bw_avg_period;  /* Average period for bandwidth estimate         */ 
     177static int  time_constants_inited = FALSE; 
     178 
     179static void 
     180time_constants_init() 
     181{ 
     182        /* We use these time constants *all* the time.   Initialize once     */ 
     183        zero_ts        = ts_map32(8000, 0); 
     184        keep_source_ts = ts_map32(8000, 2000);  
     185        history_ts     = ts_map32(8000, 1000);  
     186        bw_avg_period  = ts_map32(8000, 8000); 
     187        time_constants_inited = TRUE; 
     188} 
     189 
     190/*****************************************************************************/ 
     191/* Source functions.  A source is an active audio source.                    */ 
     192/*****************************************************************************/ 
    171193 
    172194source* 
     
    185207        assert(source_get_by_ssrc(plist, ssrc) == NULL); 
    186208 
     209        /* Time constant initialization. Nothing to do with source creation  */ 
     210        /* just has to go somewhere before sources might be active, here it  */ 
     211        /* definitely is!                                                    */ 
     212        if (time_constants_inited == FALSE) { 
     213                time_constants_init(); 
     214        } 
     215 
     216        /* On with the show...                                               */ 
    187217        psrc = (source*)block_alloc(sizeof(source)); 
    188          
    189218        if (psrc == NULL) { 
    190219                return NULL; 
    191220        } 
    192  
    193221        memset(psrc, 0, sizeof(source)); 
    194222 
     
    198226        } 
    199227 
    200         psrc->pdbe->first_mix = 1; /* Used to note we have not mixed anything 
    201                                     * for this decode path yet */ 
    202         psrc->channel_state   = NULL;         
    203         psrc->skew            = SOURCE_SKEW_NONE; 
    204         psrc->skew_offenses   = 0; 
    205         /* Allocate channel and media buffers */ 
    206         success = pb_create(&psrc->channel, (playoutfreeproc)channel_data_destroy); 
     228        psrc->pdbe->first_mix  = 1; /* Used to note nothing mixed anything   */ 
     229        psrc->pdbe->cont_toged = 0; /* Reset continuous thrown on ground cnt */ 
     230        psrc->channel_state    = NULL;         
     231        psrc->skew             = SOURCE_SKEW_NONE; 
     232        psrc->skew_offenses    = 0; 
     233 
     234        /* Allocate channel and media buffers                                */ 
     235        success = pb_create(&psrc->channel,  
     236                            (playoutfreeproc)channel_data_destroy); 
    207237        if (!success) { 
    208238                debug_msg("Failed to allocate channel buffer\n"); 
     
    319349                } 
    320350                assert(src->pdbe->render_3D_data); 
    321                 /* Render 3d is before sample rate/channel conversion, 
    322                  * and output 2 channels. 
    323                  */ 
     351                /* Render 3d is before sample rate/channel conversion, and   */ 
     352                /* output 2 channels.                                        */ 
    324353                src_channels = 2; 
    325354        } else { 
    326                 /* Rendering is switched off so destroy info */ 
     355                /* Rendering is switched off so destroy info.                */ 
    327356                if (src->pdbe->render_3D_data != NULL) { 
    328357                        render_3D_free(&src->pdbe->render_3D_data); 
     
    330359        } 
    331360 
    332         /* Now destroy converter if it is already there */ 
     361        /* Now destroy converter if it is already there.                    */ 
    333362        if (src->converter) { 
    334363                converter_destroy(&src->converter); 
     
    337366        if (src_rate != out_rate || src_channels != out_channels) { 
    338367                converter_fmt_t c; 
    339                 c.src_freq     = src_rate; 
     368                c.src_freq      = src_rate; 
    340369                c.from_channels = src_channels; 
    341                 c.dst_freq       = out_rate; 
     370                c.dst_freq      = out_rate; 
    342371                c.to_channels   = out_channels; 
    343372                converter_create(conv_id, &c, &src->converter); 
     
    530559 
    531560static void 
    532 source_process_packets(source *src) 
     561source_process_packets(source *src, ts_t now) 
    533562{ 
    534563        ts_t    timestamp; 
     
    542571                ulen = p->data_len; 
    543572                u    = (u_char*)block_alloc((int)ulen); 
    544                 /* Would be great if memcpy occured after validation in source_process_packet */ 
     573                /* Would be great if memcpy occured after validation in     */ 
     574                /* source_process_packet (or not at all)                    */ 
    545575                memcpy(u, p->data, p->data_len); 
    546576                if (source_process_packet(src, u, ulen, payload, timestamp) == FALSE) { 
    547577                        block_free(u, (int)ulen); 
     578                } else if (ts_gt(now, timestamp)) { 
     579                        /* Packet being decoded is before start of current  */ 
     580                        /* so there is now way it's audio will be played    */ 
     581                        /* Playout recalculation gets triggered in          */ 
     582                        /* rtp_callback if cont_toged hits a critical       */ 
     583                        /* threshold.  It signifies current playout delay   */ 
     584                        /* is inappropriate.                                */ 
     585                        src->pdbe->cont_toged++; 
     586                        src->pdbe->jit_toged++; 
     587                } else { 
     588                        src->pdbe->cont_toged = 0; 
    548589                } 
    549590                xfree(data); 
     
    558599                   ts_t    playout) 
    559600{ 
    560         static ts_t bw_avg_period; 
    561         static int inited; 
    562601        ts_t delta; 
    563602         
    564         if (!inited) { 
    565                 bw_avg_period = ts_map32(8000, 8000); /* one second */ 
    566                 inited        = TRUE; 
    567         } 
    568  
    569603        /* Update b/w estimate */ 
    570604        if (src->byte_count == 0) { 
     
    594628} 
    595629 
    596 /* recommend_drop_dur does quick pattern match with audio that is 
    597  * about to be played i.e. first few samples to determine how much 
    598  * audio can be dropped with causing glitch. 
    599  */ 
     630/* recommend_drop_dur does quick pattern match with audio that is about to   */ 
     631/* be played i.e. first few samples to determine how much audio can be       */ 
     632/* dropped with causing glitch.                                              */ 
    600633 
    601634#define SOURCE_COMPARE_WINDOW_SIZE 8 
    602 /* Match threshold is mean abs diff. lower score gives less noise, but less 
    603  * adaption..., might be better if threshold adapted with how much extra 
    604  * data we have buffered... */ 
     635/* Match threshold is mean abs diff. lower score gives less noise, but less  */ 
     636/* adaption..., might be better if threshold adapted with how much extra     */ 
     637/* data we have buffered...                                                  */ 
    605638#define MATCH_THRESHOLD 70 
    606639 
     
    645678                return ts_map32(rate, lowest_begin); 
    646679        } else { 
    647                 return ts_map32(8000, 0); 
     680                return zero_ts; 
    648681        } 
    649682} 
     
    654687conceal_dropped_samples(media_data *md, ts_t drop_dur) 
    655688{ 
    656         /* We are dropping drop_dur samples and want signal to be 
    657          * continuous.  So we blend samples that would have been 
    658          * played if they weren't dropped with where signal continues 
    659          * after the drop.  */ 
     689        /* We are dropping drop_dur samples and want signal to be            */ 
     690        /* continuous.  So we blend samples that would have been played if   */ 
     691        /* they weren't dropped with where signal continues after the drop.  */ 
    660692        u_int32 drop_samples; 
    661693        u_int16 rate, channels; 
     
    689721} 
    690722 
    691 /* source_check_buffering is supposed to check amount of audio buffered 
    692  * corresponds to what we expect from playout so we can think about 
    693  * skew adjustment.  */ 
     723/* source_check_buffering is supposed to check amount of audio buffered      */ 
     724/* corresponds to what we expect from playout so we can think about skew     */ 
     725/* adjustment.                                                               */ 
    694726 
    695727int 
     
    699731 
    700732        if (src->age < SOURCE_YOUNG_AGE) { 
    701                 /* If the source is new(ish) then not enough audio 
    702                  * will be in the playout buffer because it hasn't 
    703                  * arrived yet.  This age 
    704                  */ 
    705  
     733                /* If the source is new(ish) then not enough audio will be   */ 
     734                /* in the playout buffer because it hasn't arrived yet.      */ 
    706735                return FALSE; 
    707736        } 
     
    749778} 
    750779 
    751 /* source_skew_adapt exists to shift playout units if source clock 
    752  * appears to be fast or slow.  The media_data unit is here so that it 
    753  * can be examined to see if it is low energy and adjustment would be okay. 
    754  * Might want to be more sophisticated and put a silence detector in 
    755  * rather than static threshold. 
    756  * 
    757  * Returns what adaption type occurred. 
    758  */ 
     780/* source_skew_adapt exists to shift playout units if source clock appears   */ 
     781/* to be fast or slow.  The media_data unit is here so that it can be        */ 
     782/* examined to see if it is low energy and adjustment would be okay.  Might  */ 
     783/* want to be more sophisticated and put a silence detector in rather than   */ 
     784/* static threshold.                                                         */ 
     785/*                                                                           */ 
     786/* Returns what adaption type occurred.                                      */ 
    759787 
    760788static skew_t 
     
    779807 
    780808        if (i == md->nrep) { 
    781                 /* don't adapt if unit has not been decoded (error) or 
    782                  *  signal has too much energy  
    783                  */ 
     809                /* don't adapt if unit has not been decoded (error) or       */ 
     810                /* signal has too much energy                                */ 
    784811                return SOURCE_SKEW_NONE; 
    785812        } 
    786813 
    787         /* When we are making the adjustment we must shift playout 
    788          * buffers and timestamps that the source decode process 
    789          * uses. Must be careful with last repair because it is not 
    790          * valid if no repair has taken place. 
    791          */ 
     814        /* When we are making the adjustment we must shift playout buffers   */ 
     815        /* and timestamps that the source decode process uses.  Must be      */ 
     816        /* careful with last repair because it is not valid if no repair has */ 
     817        /* taken place.                                                      */ 
    792818 
    793819        if (src->skew == SOURCE_SKEW_FAST && 
     
    845871 
    846872                if (ts_gt(adjustment, src->skew_adjust)) { 
    847                         src->skew_adjust = ts_map32(8000, 0); 
     873                        src->skew_adjust = zero_ts; 
    848874                } else { 
    849875                        src->skew_adjust = ts_sub(src->skew_adjust, adjustment); 
     
    936962 
    937963int 
    938 source_process(source *src, struct s_mix_info *ms, int render_3d, repair_id_t repair_type, ts_t now) 
     964source_process(source            *src,  
     965               struct s_mix_info *ms,  
     966               int                render_3d,  
     967               repair_id_t        repair_type,  
     968               ts_t               start_ts,    /* Real-world time           */ 
     969               ts_t               end_ts)      /* Real-world time + cushion */ 
    939970{ 
    940971        media_data  *md; 
     
    952983         */ 
    953984         
    954         source_process_packets(src); 
     985        source_process_packets(src, start_ts); 
    955986 
    956987        /* Split channel coder units up into media units */ 
     
    959990                                       src->channel, 
    960991                                       src->media, 
    961                                        now); 
     992                                       end_ts); 
    962993        } 
    963994 
     
    9791010                 * (d) last decoded was not too long ago. 
    9801011                 */ 
    981                 cutoff = ts_sub(now, ts_map32(src_freq, SOURCE_AUDIO_HISTORY_MS)); 
     1012                cutoff = ts_sub(end_ts, ts_map32(src_freq, SOURCE_AUDIO_HISTORY_MS)); 
    9821013 
    9831014                assert((ts_valid(src->last_played) == FALSE) || ts_eq(playout, src->last_played) == FALSE); 
     
    10021033                } 
    10031034 
    1004                 if (ts_gt(playout, now)) { 
     1035                if (ts_gt(playout, end_ts)) { 
    10051036                        /* This playout point is after now so stop */ 
    10061037                        pb_iterator_retreat(src->media_pos); 
     
    10701101                } 
    10711102 
    1072                 if (src->skew != SOURCE_SKEW_NONE && source_skew_adapt(src, md, playout) != SOURCE_SKEW_NONE) { 
    1073                         /* We have skew and we have adjusted playout 
    1074                          *  buffer timestamps, so re-get unit to get 
    1075                          *  correct timestamp info */ 
     1103                if (src->skew != SOURCE_SKEW_NONE &&  
     1104                    source_skew_adapt(src, md, playout) != SOURCE_SKEW_NONE) { 
     1105                        /* We have skew and we have adjusted playout buffer  */ 
     1106                        /* timestamps, so re-get unit to get correct         */ 
     1107                        /* timestamp info.                                   */ 
    10761108                        pb_iterator_get_at(src->media_pos,  
    10771109                                           (u_char**)&md,  
     
    10891121 
    10901122                if (mix_process(ms, src->pdbe, md->rep[md->nrep - 1], playout) == FALSE) { 
    1091                         /* Sources sampling rate changed mid-flow?, 
    1092                          * dump data, make source look irrelevant, it 
    1093                          * should get destroyed and the recreated with 
    1094                          * proper decode path when new data arrives. 
    1095                          * Not graceful..  A better way would be just 
    1096                          * to flush media then invoke source_reconfigure  
    1097                          * if this is ever really an issue.  */ 
     1123                        /* Sources sampling rate changed mid-flow? dump data */ 
     1124                        /* make source look irrelevant, it should get        */ 
     1125                        /* destroyed and the recreated with proper decode    */ 
     1126                        /* path when new data arrives.  Not graceful..       */ 
     1127                        /* A better way would be just to flush media then    */ 
     1128                        /* invoke source_reconfigure if this is ever really  */ 
     1129                        /* an issue.                                         */ 
    10981130                        pb_flush(src->media); 
    10991131                        pb_flush(src->channel); 
     
    11131145 
    11141146int 
    1115 source_audit(source *src) { 
     1147source_audit(source *src)  
     1148{ 
    11161149        if (src->age != 0) { 
    1117                 ts_t history; 
    11181150                /* Keep 1/8 seconds worth of audio */ 
    1119                 history =  ts_map32(8000,1000); 
    1120                 pb_iterator_audit(src->media_pos,history); 
     1151                pb_iterator_audit(src->media_pos, history_ts); 
    11211152                return TRUE; 
    11221153        } 
    11231154        return FALSE; 
    11241155} 
    1125  
    11261156 
    11271157ts_sequencer* 
     
    11361166        ts_t last, extra; 
    11371167 
    1138         /* If we have a channel unit in the channel buffer the amount of audio */ 
    1139         /* we have buffered is the difference between now and the channel unit */ 
    1140         /* end plus the length of the unit.                                    */ 
     1168        /* If we have a channel unit in the channel buffer the amount of     */ 
     1169        /* audio we have buffered is the difference between now and the      */ 
     1170        /* channel unit end plus the length of the unit.                     */ 
    11411171        if (pb_get_end_ts(src->channel, &last)) { 
    11421172                int freq = get_freq(src->pdbe->clock); 
    11431173                extra    = ts_map32(freq, src->pdbe->inter_pkt_gap); 
    1144 /* 
    1145                 last     = ts_add(last, extra); 
    1146                 */ 
    11471174                return ts_sub(last, now); 
    11481175        } 
    1149         /* Else if we have an end time for a media unit then the very last audio */ 
    1150         /* we have is the media unit time plus it's length less now.             */ 
     1176 
     1177        /* Else if we have an end time for a media unit then the very last   */ 
     1178        /* audio we have is the media unit time plus it's length less now.   */ 
    11511179        if (pb_get_end_ts(src->media, &last)) { 
    11521180                int freq = get_freq(src->pdbe->clock); 
    11531181                extra    = ts_map32(freq, src->pdbe->inter_pkt_gap / src->pdbe->units_per_packet); 
    1154 /* 
    1155                 last     = ts_add(last, extra); 
    1156                 */ 
    11571182                if (ts_gt(last, now)) { 
    11581183                        return ts_sub(last, now); 
     
    11601185        } 
    11611186 
    1162         return ts_map32(8000,0); 
     1187        return zero_ts; 
    11631188} 
    11641189 
     
    11721197source_relevant(source *src, ts_t now) 
    11731198{ 
    1174         ts_t keep_source_time; 
    11751199        assert(src); 
    11761200 
     
    11781202                return TRUE; 
    11791203        } 
    1180  
    1181         keep_source_time = ts_map32(8000, 2000); /* 1 quarter of a second */ 
    1182  
    1183         if (!ts_eq(source_get_audio_buffered(src, now), ts_map32(8000, 0)) || 
    1184                 ts_gt(ts_add(src->pdbe->last_arr, keep_source_time), now)) { 
     1204         
     1205        if (!ts_eq(source_get_audio_buffered(src, now), zero_ts) || 
     1206                ts_gt(ts_add(src->pdbe->last_arr, keep_source_ts), now)) { 
    11851207                return TRUE; 
    11861208        } 
  • rat/trunk/source.h

    r2819 r2866  
    6767                                            int                render_3d, 
    6868                                            repair_id_t        repair, 
    69                                             ts_t               now); 
     69                                            ts_t               start_ts, 
     70                                            ts_t               end_ts); 
    7071 
    7172int              source_relevant           (struct s_source *src,