caddr_t bif_dateadd (caddr_t * qst, caddr_t * err_ret, state_slot_t ** args) { caddr_t res; caddr_t part = bif_string_arg (qst, args, 0, "dateadd"); boxint n = bif_long_arg (qst, args, 1, "dateadd"); caddr_t dt = bif_date_arg (qst, args, 2, "dateadd"); TIMESTAMP_STRUCT ts; int dt_type = DT_DT_TYPE (dt); int year_or_month_tz_tweak = (((!strcmp ("year", part)) || (!strcmp ("month", part))) ? DT_TZ (dt) : 0); DT_AUDIT_FIELDS (dt); dt_to_GMTimestamp_struct (dt, &ts); if (year_or_month_tz_tweak) ts_add (&ts, year_or_month_tz_tweak, "minute"); ts_add (&ts, n, part); if (year_or_month_tz_tweak) ts_add (&ts, -year_or_month_tz_tweak, "minute"); res = dk_alloc_box (DT_LENGTH, DV_DATETIME); GMTimestamp_struct_to_dt (&ts, res); DT_SET_TZ (res, DT_TZ (dt)); if (DT_TYPE_DATE == dt_type && (0 == stricmp (part, "year") || 0 == stricmp (part, "month") || 0 == stricmp (part, "day"))) DT_SET_DT_TYPE (res, dt_type); DT_AUDIT_FIELDS (dt); return res; }
/// Replacement pthread_cond_timedwait() /// /// WARNING: This replacement calls through to the 2.3.2 version of the /// real pthread_cond_timedwait, regardless of the version the calling code /// assumed it would be calling. This will need updating to support other /// libc versions. /// /// WARNING THE SECOND: This assumes that the condition variable was created /// with a condattr that specifies CLOCK_MONOTONIC. /// /// http://blog.fesnel.com/blog/2009/08/25/preloading-with-multiple-symbol-versions/ int pthread_cond_timedwait(pthread_cond_t* cond, pthread_mutex_t* mutex, const struct timespec* abstime) { struct timespec fixed_time; if (!real_pthread_cond_timedwait) { real_pthread_cond_timedwait = (pthread_cond_timedwait_func_t)(intptr_t)dlvsym(RTLD_NEXT, "pthread_cond_timedwait", "GLIBC_2.3.2"); } // Subtract our fake time and add the real time, this means the // relative delay is correct while allowing the calling code to think // it's woking with absolute time. // // Note we call the fake clock_gettime first, meaning that real_clock_gettime // will be set before the call to it in the next line. struct timespec fake_time; struct timespec real_time; struct timespec delta_time; clock_gettime(CLOCK_MONOTONIC, &fake_time); real_clock_gettime(CLOCK_MONOTONIC, &real_time); ts_sub(*abstime, fake_time, delta_time); ts_add(real_time, delta_time, fixed_time); return real_pthread_cond_timedwait(cond, mutex, &fixed_time); }
/// Alter the fabric of space-time. void cwtest_advance_time_ms(long delta_ms) ///< Delta to add to the current offset applied to returned times (in ms). { struct timespec delta = { delta_ms / 1000, (delta_ms % 1000) * 1000L * 1000L }; pthread_mutex_lock(&time_lock); ts_add(time_offset, delta, time_offset); pthread_mutex_unlock(&time_lock); }
void *spr_worker(void *data) { int rc=-1, nc; void *sp=NULL, *set; size_t len; char *buf; set = kv_set_new(); sp = kv_spoolreader_new(CF.dir); if (!sp) goto done; while (kv_spool_read(sp,set,1) > 0) { if (set_to_buf(set,&buf,&len) < 0) goto done; assert(len < MAX_BUF); nc = nn_send(CF.ingress_socket_push, buf, len, 0); free(buf); if (nc < 0) { fprintf(stderr,"nn_send: %s\n", nn_strerror(errno)); goto done; } ts_add(CF.spr_msgs_ts, CF.now, NULL); if (CF.shutdown) break; } done: CF.shutdown = 1; kv_set_free(set); if (sp) kv_spoolreader_free(sp); return NULL; }
bool ib_ctx_time_converter::sync_clocks(struct timespec* st, uint64_t* hw_clock){ struct timespec st1, st2, diff, st_min = TIMESPEC_INITIALIZER; struct ibv_exp_values queried_values; int64_t interval, best_interval = 0; uint64_t hw_clock_min = 0; memset(&queried_values, 0, sizeof(queried_values)); queried_values.comp_mask = IBV_EXP_VALUES_HW_CLOCK; for (int i = 0 ; i < 10 ; i++) { clock_gettime(CLOCK_REALTIME, &st1); if (ibv_exp_query_values(m_p_ibv_context,IBV_EXP_VALUES_HW_CLOCK, &queried_values) || !queried_values.hwclock) { return false; } clock_gettime(CLOCK_REALTIME, &st2); interval = (st2.tv_sec - st1.tv_sec) * NSEC_PER_SEC + (st2.tv_nsec - st1.tv_nsec); if (!best_interval || interval < best_interval) { best_interval = interval; hw_clock_min = queried_values.hwclock; interval /= 2; diff.tv_sec = interval / NSEC_PER_SEC; diff.tv_nsec = interval - (diff.tv_sec * NSEC_PER_SEC); ts_add(&st1, &diff, &st_min); } } *st = st_min; *hw_clock = hw_clock_min; return true; }
timestamp_t playout_calc(session_t *sp, uint32_t ssrc, timestamp_t transit, int new_spurt) /*****************************************************************************/ /* The primary purpose of this function is to calculate the playout point */ /* for new talkspurts (new_spurt). It also maintains the jitter and transit */ /* time estimates from the source to us. The value returned is the local */ /* playout time. */ /*****************************************************************************/ { timestamp_t delta_transit; pdb_entry_t *e; pdb_item_get(sp->pdb, ssrc, &e); assert(e != NULL); delta_transit = ts_abs_diff(transit, e->avg_transit); if (ts_gt(transit, e->avg_transit)) { e->avg_transit = ts_add(e->avg_transit, ts_div(delta_transit,16)); } else { e->avg_transit = ts_sub(e->avg_transit, ts_div(delta_transit,16)); } if (new_spurt == TRUE) { timestamp_t hvar, jvar; /* Host and jitter components */ debug_msg("New talkspurt\n"); hvar = playout_constraints_component(sp, e); jvar = ts_mul(e->jitter, PLAYOUT_JITTER_SCALE); if (ts_gt(hvar, jvar)) { e->playout = hvar; } else { e->playout = jvar; } e->transit = e->avg_transit; } else { /* delta_transit is abs((s[j+1] - d[j+1]) - (s[j] - d[j])) */ delta_transit = ts_abs_diff(transit, e->last_transit); /* Update jitter estimate using */ /* jitter = (7/8)jitter + (1/8) new_jitter */ e->jitter = ts_mul(e->jitter, 7); e->jitter = ts_add(e->jitter, delta_transit); e->jitter = ts_div(e->jitter, 8); } e->last_transit = transit; return e->playout; }
caddr_t bif_date_diff (caddr_t * qst, caddr_t * err_ret, state_slot_t ** args) { caddr_t unit = bif_string_arg (qst, args, 0, "datediff"); caddr_t dt1 = bif_date_arg (qst, args, 1, "datediff"); caddr_t dt2 = bif_date_arg (qst, args, 2, "datediff"); boxint s1 = (boxint)DT_DAY (dt1) * 24 * 60 * 60 + (boxint)DT_HOUR (dt1) * 60 * 60 + (boxint)DT_MINUTE (dt1) * 60 + DT_SECOND (dt1); boxint s2 = (boxint)DT_DAY (dt2) * 24 * 60 * 60 + (boxint)DT_HOUR (dt2) * 60 * 60 + (boxint)DT_MINUTE (dt2) * 60 + DT_SECOND (dt2); int frac1, frac2; int diffyear, diffmonth; if (0 == stricmp (unit, "day")) return box_num ((boxint)DT_DAY (dt2) - (boxint)DT_DAY (dt1)); if (0 == stricmp (unit, "hour")) return box_num ((s2 - s1) / (60 * 60)); if (0 == stricmp (unit, "minute")) return box_num ((s2 - s1) / 60); if (0 == stricmp (unit, "second")) return box_num (s2 - s1); diffyear = !stricmp (unit, "year"); diffmonth = (diffyear ? 0 : !stricmp (unit, "month")); if (diffyear || diffmonth) { TIMESTAMP_STRUCT ts1; TIMESTAMP_STRUCT ts2; int tz_tweak = DT_TZ (dt1); dt_to_GMTimestamp_struct (dt2, &ts2); dt_to_GMTimestamp_struct (dt1, &ts1); ts_add (&ts1, tz_tweak, "minute"); ts_add (&ts2, tz_tweak, "minute"); if (diffyear) return box_num ((boxint)ts2.year - (boxint)ts1.year); if (diffmonth) return box_num ((boxint)(ts2.year * 12 + ts2.month) - (boxint)(ts1.year * 12 + ts1.month)); } frac1 = DT_FRACTION(dt1); frac2 = DT_FRACTION(dt2); if (0 == stricmp (unit, "millisecond")) return box_num ((s2 - s1) * (boxint)1000 + (frac2 / 1000000 - frac1 / 1000000)); if (0 == stricmp (unit, "microsecond")) return box_num ((s2 - s1) * (boxint)1000000 + (frac2 / 1000 - frac1 / 1000)); if (0 == stricmp (unit, "nanosecond")) return box_num ((s2 - s1) * (boxint)1000000000 + (frac2 - frac1)); sqlr_new_error ("22023", "DT002", "Bad unit in datediff: %s.", unit); return NULL; }
void pb_shift_units_back_after(pb_t *pb, timestamp_t ref_ts, timestamp_t delta) { pb_node_t *stop, *curr; pb_validate(pb); stop = pb->psentinel; curr = pb->psentinel->prev; while(curr != stop && ts_gt(curr->playout, ref_ts)) { curr->playout = ts_add(curr->playout, delta); curr = curr->prev; } pb_validate(pb); }
void pb_shift_back(pb_t *pb, timestamp_t delta) { pb_node_t *stop, *curr; pb_validate(pb); stop = pb->psentinel; curr = pb->psentinel->next; while(curr != stop) { curr->playout = ts_add(curr->playout, delta); curr = curr->next; } pb_validate(pb); }
caddr_t bif_timestampadd (caddr_t * qst, caddr_t * err_ret, state_slot_t ** args) { caddr_t res; ptrlong part = bif_long_arg (qst, args, 0, "timestampadd"); int n = (int) bif_long_arg (qst, args, 1, "timestampadd"); caddr_t dt = bif_date_arg (qst, args, 2, "timestampadd"); int saved_tz = DT_TZ (dt); GMTIMESTAMP_STRUCT ts; dt_to_GMTimestamp_struct (dt, &ts); ts_add (&ts, n, interval_odbc_to_text (part, "timestampadd")); res = dk_alloc_box (DT_LENGTH, DV_DATETIME); GMTimestamp_struct_to_dt (&ts, res); DT_SET_TZ (res, saved_tz); return res; }
/* * applies regular expression pattern to contents of the directory * * for entries that match, the fully qualified pathname is inserted into * the treeset */ static int applyRe(char *dir, RegExp *reg, TreeSet *ts) { DIR *dd; struct dirent *dent; int status = 1; /* * open the directory */ if ((dd = opendir(dir)) == NULL) { fprintf(stderr, "Error opening directory `%s'\n", dir); return 0; } /* * for each entry in the directory */ while (status && (dent = readdir(dd)) != NULL) { if (strcmp(".", dent->d_name) == 0 || strcmp("..", dent->d_name) == 0) continue; if (!(dent->d_type & DT_DIR)) { char b[4096], *sp; /* * see if filename matches regular expression */ if (! re_match(reg, dent->d_name)) continue; sprintf(b, "%s/%s", dir, dent->d_name); /* * duplicate fully qualified pathname for insertion into treeset */ if ((sp = strdup(b)) != NULL) { if (!ts_add(ts, sp)) { fprintf(stderr, "Error adding `%s' to tree set\n", sp); free(sp); status = 0; break; } } else { fprintf(stderr, "Error adding `%s' to tree set\n", b); status = 0; break; } } } (void) closedir(dd); return status; }
/// Replacement clock_gettime. int clock_gettime(clockid_t clk_id, struct timespec *tp) throw () { int rc; if (!real_clock_gettime) { real_clock_gettime = (int (*)(clockid_t, struct timespec *))(intptr_t)dlsym(RTLD_NEXT, "clock_gettime"); } pthread_mutex_lock(&time_lock); if (completely_control_time) { if (abs_timespecs.find(clk_id) != abs_timespecs.end()) { *tp = abs_timespecs[clk_id]; rc = 0; } else { // We don't support this clock ID. Print a warning, and act like an // invalid clock ID has been requested. fprintf(stderr, "WARNING: Clock ID %d is not supported (%s:%d)\n", clk_id, __FILE__, __LINE__); rc = -1; errno = EINVAL; } } else { rc = real_clock_gettime(clk_id, tp); } if (!rc) { ts_add(*tp, time_offset, *tp); } pthread_mutex_unlock(&time_lock); return rc; }
static void vanilla_decoder_output(channel_unit *cu, struct s_pb *out, timestamp_t playout) { const codec_format_t *cf; codec_id_t id; uint32_t data_len; u_char *p, *end; media_data *m; timestamp_t unit_dur; id = codec_get_by_payload(cu->pt); cf = codec_get_format(id); unit_dur = ts_map32(cf->format.sample_rate, codec_get_samples_per_frame(id)); p = cu->data; end = cu->data + cu->data_len; while(p < end) { media_data_create(&m, 1); m->rep[0]->id = id; if (p == cu->data && cf->mean_per_packet_state_size) { /* First unit out of packet may have state */ m->rep[0]->state_len = cf->mean_per_packet_state_size; m->rep[0]->state = (u_char*)block_alloc(m->rep[0]->state_len); memcpy(m->rep[0]->state, p, cf->mean_per_packet_state_size); p += cf->mean_per_packet_state_size; } /* Now do data section */ data_len = codec_peek_frame_size(id, p, (uint16_t)(end - p)); m->rep[0]->data = (u_char*)block_alloc(data_len); m->rep[0]->data_len = (uint16_t)data_len; memcpy(m->rep[0]->data, p, data_len); if (pb_add(out, (u_char *)m, sizeof(media_data), playout) == FALSE) { debug_msg("Vanilla decode failed\n"); media_data_destroy(&m, sizeof(media_data)); return; } p += data_len; playout = ts_add(playout, unit_dur); } assert(p == end); }
/* extract a Packet* from the asyncBuffer */ Packet* AsyncBuffer::pop(double timeout) { struct timespec to; clock_gettime(CLOCK_REALTIME, &to); ts_add(&to, double2ts(timeout)) ; pthread_mutex_lock(&access_lock); if (packet_queue.empty()) { //wait the queue is not empty until timeout if(pthread_cond_timedwait(&empty_flag, &access_lock, &to)==ETIMEDOUT) { pthread_mutex_unlock(&access_lock); return NULL; } } Packet* pkt = packet_queue.front(); packet_queue.pop(); pthread_mutex_unlock(&access_lock); return pkt; }
void ib_ctx_time_converter::convert_hw_time_to_system_time(uint64_t packet_hw_time, struct timespec* packet_systime) { ctx_timestamping_params_t* current_parameters_set = &m_ctx_convert_parmeters[m_ctx_parmeters_id]; if (current_parameters_set->hca_core_clock && packet_hw_time) { struct timespec hw_to_timespec, sync_systime; uint64_t hw_time_diff, hca_core_clock, sync_hw_clock; hca_core_clock = current_parameters_set->hca_core_clock; sync_hw_clock = current_parameters_set->sync_hw_clock; sync_systime = current_parameters_set->sync_systime; hw_time_diff = packet_hw_time - sync_hw_clock; // sync_hw_clock should be zero when m_conversion_mode is CONVERSION_MODE_RAW_OR_FAIL or CONVERSION_MODE_DISABLE hw_to_timespec.tv_sec = hw_time_diff / hca_core_clock; hw_time_diff -= hw_to_timespec.tv_sec * hca_core_clock; hw_to_timespec.tv_nsec = (hw_time_diff * NSEC_PER_SEC) / hca_core_clock; ts_add(&sync_systime, &hw_to_timespec, packet_systime); } }
static void redundancy_decoder_output(channel_unit *chu, struct s_pb *out, timestamp_t playout) { const codec_format_t *cf; codec_id_t cid; u_char *hp, *dp, *de, ppt, bpt; uint32_t hdr32, blen, boff; timestamp_t ts_max_off, ts_blk_off, this_playout; hp = dp = chu->data; de = chu->data + chu->data_len; /* move data pointer past header */ while (ntohl(*((uint32_t*)dp)) & RED_HDR32_PAT) { dp += 4; } if (dp == hp) { debug_msg("Not a redundant block\n"); return; } /* At this point dp points to primary payload type. * This is a most useful quantity... */ ppt = *dp; dp += 1; assert(dp < de); /* Max offset should be in first header. Want max offset * as we nobble timestamps to be: * playout + max_offset - this_offset */ cid = codec_get_by_payload(ppt); if (codec_id_is_valid(cid) == FALSE) { debug_msg("Primary not recognized.\n"); return; } cf = codec_get_format(cid); assert(cf != NULL); hdr32 = ntohl(*(uint32_t*)hp); ts_max_off = ts_map32(cf->format.sample_rate, RED_HDR32_GET_OFF(hdr32)); blen = 0; while (hdr32 & RED_HDR32_PAT) { boff = RED_HDR32_GET_OFF(hdr32); blen = RED_HDR32_GET_LEN(hdr32); bpt = (u_char)RED_HDR32_GET_PT(hdr32); /* Calculate playout point = playout + max_offset - offset */ ts_blk_off = ts_map32(cf->format.sample_rate, boff); this_playout = ts_add(playout, ts_max_off); this_playout = ts_sub(this_playout, ts_blk_off); hp += 4; /* hdr */ red_split_unit(ppt, bpt, dp, blen, this_playout, out); xmemchk(); dp += blen; hdr32 = ntohl(*(uint32_t*)hp); } this_playout = ts_add(playout, ts_max_off); hp += 1; blen = (uint32_t) (de - dp); red_split_unit(ppt, ppt, dp, blen, this_playout, out); xmemchk(); }
/* transmitter worker */ void *kaf_worker(void *thread_id) { char buf[MAX_BUF], *b; int rc=-1, nr, len, l, count=0,kr; /* kafka connection setup */ char errstr[512]; rd_kafka_t *k; rd_kafka_topic_t *t; rd_kafka_conf_t *conf; rd_kafka_topic_conf_t *topic_conf; int partition = RD_KAFKA_PARTITION_UA; char *key = NULL; int keylen = key ? strlen(key) : 0; /* set up global options */ conf = rd_kafka_conf_new(); rd_kafka_conf_set_error_cb(conf, err_cb); //rd_kafka_conf_set_throttle_cb(conf, throttle_cb); rd_kafka_conf_set_stats_cb(conf, stats_cb); kr = rd_kafka_conf_set(conf, "statistics.interval.ms", "60000", errstr, sizeof(errstr)); if (kr != RD_KAFKA_CONF_OK) { fprintf(stderr,"error: rd_kafka_conf_set: statistics.interval.ms 60000 => %s\n", errstr); goto done; } char **opt=NULL; while( (opt=(char **)utarray_next(CF.rdkafka_options,opt))) { char *eq = strchr(*opt,'='); if (eq == NULL) { fprintf(stderr,"error: specify rdkafka params as key=value\n"); goto done; } char *k = strdup(*opt), *v; k[eq-*opt] = '\0'; v = &k[eq-*opt + 1]; if (CF.verbose) fprintf(stderr,"setting %s %s\n", k, v); kr = rd_kafka_conf_set(conf, k, v, errstr, sizeof(errstr)); if (kr != RD_KAFKA_CONF_OK) { fprintf(stderr,"error: rd_kafka_conf_set: %s %s => %s\n", k, v, errstr); goto done; } free(k); } /* set up topic options */ topic_conf = rd_kafka_topic_conf_new(); opt=NULL; while( (opt=(char **)utarray_next(CF.rdkafka_topic_options,opt))) { char *eq = strchr(*opt,'='); if (eq == NULL) { fprintf(stderr,"error: specify rdkafka topic params as key=value\n"); goto done; } char *k = strdup(*opt), *v; k[eq-*opt] = '\0'; v = &k[eq-*opt + 1]; if (CF.verbose) fprintf(stderr,"setting %s %s\n", k, v); kr = rd_kafka_topic_conf_set(topic_conf, k, v, errstr, sizeof(errstr)); if (kr != RD_KAFKA_CONF_OK) { fprintf(stderr,"error: rd_kafka_conf_set: %s %s => %s\n", k, v, errstr); goto done; } free(k); } k = rd_kafka_new(RD_KAFKA_PRODUCER, conf, errstr, sizeof(errstr)); if (k == NULL) { fprintf(stderr, "rd_kafka_new: %s\n", errstr); goto done; } if (rd_kafka_brokers_add(k, CF.broker) < 1) { fprintf(stderr, "invalid broker\n"); goto done; } t = rd_kafka_topic_new(k, CF.topic, topic_conf); while (CF.shutdown == 0) { len = nn_recv(CF.egress_socket_pull, buf, MAX_BUF, 0); if (len < 0) { fprintf(stderr,"nn_recv: %s\n", nn_strerror(errno)); goto done; } rc = rd_kafka_produce(t, partition, RD_KAFKA_MSG_F_COPY, buf, len, key, keylen, NULL); if (rc == -1) { fprintf(stderr,"rd_kafka_produce: %s %s\n", rd_kafka_err2str( rd_kafka_errno2err(errno)), ((errno == ENOBUFS) ? "(backpressure)" : "")); goto done; } // cause rdkafka to invoke optional callbacks (msg delivery reports or error) if ((++count % 1000) == 0) rd_kafka_poll(k, 0); if (thread_id == 0) { /* only emit these stats from the first worker thread (not thread safe) */ ts_add(CF.kaf_bytes_ts, CF.now, &len); ts_add(CF.kaf_msgs_ts, CF.now, NULL); } } rc = 0; done: CF.shutdown = 1; return NULL; }
int main(int argc, char **argv) { struct fdelay_time t_start, t_delta, t_width; int mode = -1; int channel = -1; int count = 1; int wait_trigger = 0; int opt; int relative = 1; int devid = 0; int do_pps = 0, do_10m = 0; uint64_t default_width = 250000; fdelay_pico_to_time(&default_width, &t_width); while ((opt = getopt(argc, argv, "p1hctd:m:o:a:s:w:g:q:")) != -1) { switch (opt) { case 'h': help(argc, argv); break; case 'c': count = -1; break; case 'q': count = atoi(optarg); break; case 't': wait_trigger = 1; break; case 'g': parse_time(optarg, &t_delta); break; case 'w': parse_time(optarg, &t_width); break; case 's': parse_time(optarg, &t_start); relative = 1; break; case 'a': parse_time(optarg, &t_start); relative = 0; break; case 'o': channel = atoi(optarg); if (channel < 1 || channel > 4) { fprintf(stderr, "Invalid output channel.\n"); exit(1); } break; case 'm': if (!strcmp(optarg, "pulse")) mode = FD_OUT_MODE_PULSE; else if (!strcmp(optarg, "delay")) mode = FD_OUT_MODE_DELAY; else if (!strcmp(optarg, "disable")) mode = FD_OUT_MODE_DISABLED; else { fprintf(stderr, "Invalid output mode.\n"); exit(1); } break; case 'd': sscanf(optarg, "%i", &devid); break; case 'p': do_pps = 1; break; case '1': do_10m = 1; break; } } struct fdelay_board *b; struct fdelay_pulse p; /* init before going on parsing */ int i = fdelay_init(); if (i < 0) { fprintf(stderr, "%s: fdelay_init(): %s\n", argv[0], strerror(errno)); exit(1); } if (i == 0) { fprintf(stderr, "%s: no boards found\n", argv[0]); exit(1); } b = fdelay_open(devid, -1); if (!b) b = fdelay_open(-1, devid); if (!b) { fprintf(stderr, "%s: fdelay_open(0x%x): %s\n", argv[0], devid, strerror(errno)); exit(1); } if ((mode < 0 || channel < 0) && !do_pps && !do_10m) { fprintf(stderr, "You must specify the mode and the channel to generate pulses\n"); exit(1); } if (mode == FD_OUT_MODE_PULSE && relative) { fdelay_get_time(b, &p.start); p.start = ts_add(p.start, t_start); } else { p.start = t_start; } p.end = ts_add(p.start, t_width); p.loop = t_delta; p.rep = count; p.mode = mode; if (do_pps || do_10m) { uint64_t width = do_pps ? 1000000 : 48000; uint64_t delta = do_pps ? 1000000000000ULL : 100000ULL; fdelay_pico_to_time(&width, &t_width); fdelay_get_time(b, &p.start); p.start.utc += 2; p.start.coarse = 0; p.start.frac = 0; p.end = ts_add(p.start, t_width); fdelay_pico_to_time(&delta, &p.loop); p.rep = -1; p.mode = FD_OUT_MODE_PULSE; } /* And finally work */ if (fdelay_config_pulse(b, channel - 1, &p) < 0) { fprintf(stderr, "%s: fdelay_config_pulse(): %s\n", argv[0], strerror(errno)); exit(1); } while (wait_trigger) { usleep(10 * 1000); i = fdelay_has_triggered(b, channel - 1); if (i < 0) { fprintf(stderr, "%s: waiting for trigger: %s\n", argv[0], strerror(errno)); exit(1); } wait_trigger = !i; } fdelay_close(b); fdelay_exit(); return 0; }
enum fsm_event e2e_event(struct port *p, int fd_index) { int cnt, fd = p->fda.fd[fd_index]; enum fsm_event event = EV_NONE; struct ptp_message *msg, *dup; switch (fd_index) { case FD_ANNOUNCE_TIMER: case FD_SYNC_RX_TIMER: pr_debug("port %hu: %s timeout", portnum(p), fd_index == FD_SYNC_RX_TIMER ? "rx sync" : "announce"); if (p->best) { fc_clear(p->best); } port_set_announce_tmo(p); return EV_ANNOUNCE_RECEIPT_TIMEOUT_EXPIRES; case FD_DELAY_TIMER: pr_debug("port %hu: delay timeout", portnum(p)); port_set_delay_tmo(p); delay_req_prune(p); tc_prune(p); if (!clock_free_running(p->clock)) { switch (p->state) { case PS_UNCALIBRATED: case PS_SLAVE: if (port_delay_request(p)) { event = EV_FAULT_DETECTED; } break; default: break; }; } return event; case FD_QUALIFICATION_TIMER: pr_debug("port %hu: qualification timeout", portnum(p)); return EV_QUALIFICATION_TIMEOUT_EXPIRES; case FD_MANNO_TIMER: case FD_SYNC_TX_TIMER: case FD_UNICAST_REQ_TIMER: case FD_UNICAST_SRV_TIMER: pr_err("unexpected timer expiration"); return EV_NONE; case FD_RTNL: pr_debug("port %hu: received link status notification", portnum(p)); rtnl_link_status(fd, p->name, port_link_status, p); if (p->link_status == (LINK_UP|LINK_STATE_CHANGED)) { return EV_FAULT_CLEARED; } else if ((p->link_status == (LINK_DOWN|LINK_STATE_CHANGED)) || (p->link_status & TS_LABEL_CHANGED)) { return EV_FAULT_DETECTED; } else { return EV_NONE; } } msg = msg_allocate(); if (!msg) { return EV_FAULT_DETECTED; } msg->hwts.type = p->timestamping; cnt = transport_recv(p->trp, fd, msg); if (cnt <= 0) { pr_err("port %hu: recv message failed", portnum(p)); msg_put(msg); return EV_FAULT_DETECTED; } if (msg_sots_valid(msg)) { ts_add(&msg->hwts.ts, -p->rx_timestamp_offset); } if (msg_unicast(msg)) { pl_warning(600, "cannot handle unicast messages!"); msg_put(msg); return EV_NONE; } dup = msg_duplicate(msg, cnt); if (!dup) { msg_put(msg); return EV_NONE; } if (tc_ignore(p, dup)) { msg_put(dup); dup = NULL; } switch (msg_type(msg)) { case SYNC: if (tc_fwd_sync(p, msg)) { event = EV_FAULT_DETECTED; break; } if (dup) { process_sync(p, dup); } break; case DELAY_REQ: if (tc_fwd_request(p, msg)) { event = EV_FAULT_DETECTED; } break; case PDELAY_REQ: break; case PDELAY_RESP: break; case FOLLOW_UP: if (tc_fwd_folup(p, msg)) { event = EV_FAULT_DETECTED; break; } if (dup) { process_follow_up(p, dup); } break; case DELAY_RESP: if (tc_fwd_response(p, msg)) { event = EV_FAULT_DETECTED; } if (dup) { process_delay_resp(p, dup); } break; case PDELAY_RESP_FOLLOW_UP: break; case ANNOUNCE: if (tc_forward(p, msg)) { event = EV_FAULT_DETECTED; break; } if (dup && process_announce(p, dup)) { event = EV_STATE_DECISION_EVENT; } break; case SIGNALING: case MANAGEMENT: if (tc_forward(p, msg)) { event = EV_FAULT_DETECTED; } break; } msg_put(msg); if (dup) { msg_put(dup); } return event; }
caddr_t arithm_dt_add_num (ccaddr_t box1, ccaddr_t box2, int subtraction, caddr_t *err_ret) { int dt_type = DT_DT_TYPE (box1); dtp_t dtp2 = DV_TYPE_OF (box2); boxint whole_seconds = 0; boxint nanoseconds = 0; TIMESTAMP_STRUCT ts; caddr_t res; switch (dtp2) { case DV_LONG_INT: whole_seconds = unbox (box2); break; case DV_DOUBLE_FLOAT: { double n = unbox_double (box2); double rest; whole_seconds = (n >= 0.0) ? floor(n + 0.5) : ceil(n - 0.5); rest = n - whole_seconds; if (abs(rest/n) > (3 * DBL_EPSILON)) nanoseconds = (n - whole_seconds) * 1000000000L; break; } case DV_NUMERIC: { numeric_t n = (numeric_t)box2; if (NUMERIC_STS_SUCCESS != numeric_to_int64 (n, &whole_seconds)) { err_ret[0] = srv_make_new_error ("22003", "SR087", "Wrong arguments for datetime arithmetic: decimal is out of range."); return NULL; } if (n->n_scale > 0) { char *nptr = n->n_value + n->n_len; int ctr; int mult = 1; for (ctr = 9; ctr > n->n_scale; ctr--) mult *= 10; while (ctr--) { nanoseconds += mult * nptr[ctr]; mult *= 10; } } break; } default: return NULL; } DT_AUDIT_FIELDS (dt); dt_to_GMTimestamp_struct (box1, &ts); ts_add (&ts, (subtraction ? -whole_seconds : whole_seconds), "second"); if (nanoseconds) ts_add (&ts, (subtraction ? -nanoseconds : nanoseconds), "nanosecond"); res = dk_alloc_box (DT_LENGTH, DV_DATETIME); GMTimestamp_struct_to_dt (&ts, res); DT_SET_TZ (res, DT_TZ (box1)); if ((DT_TYPE_DATE == dt_type) && (0 == (((whole_seconds * 1000000000L) + nanoseconds) % (SPERDAY * 1000000000L)))) DT_SET_DT_TYPE (res, dt_type); DT_AUDIT_FIELDS (dt); return res; }
static int layered_decoder_reorganise(channel_data *in, struct s_pb *out, timestamp_t playout) { const codec_format_t *cf; codec_id_t id; coded_unit *cu; u_char *p[LAY_MAX_LAYERS], *end; uint32_t hdr32, data_len; uint8_t hdrpt, i; uint16_t len[LAY_MAX_LAYERS], mrk[LAY_MAX_LAYERS]; media_data *m; timestamp_t playout_step; media_data_create(&m, 1); assert(m->nrep == 1); if(in->nelem > LAY_MAX_LAYERS) { debug_msg("Too many layers to reorganise\n"); goto done; } /* Since layer_decoder_peek checks all the headers, we can * assume they are OK. We still need to check that they match * up, however, i.e. that all the layers are intact, and that * they are all using the same codec. Layers need to be sorted * into order as well. We use the markers to determine how to * join the layers together into one media_data, and then get * out of here. */ p[0] = in->elem[0]->data; hdr32 = ntohl(*(uint32_t*)p[0]); if(hdr32 & LAY_HDR32_PAT) { hdrpt = (uint8_t)(LAY_HDR32_GET_PT(hdr32)); mrk[0] = (uint8_t)(LAY_HDR32_GET_MRK(hdr32)); len[0] = (uint8_t)(LAY_HDR32_GET_LEN(hdr32)); p[0] += 4; } else { debug_msg("Invalid layered header\n"); goto done; } for(i=1; i<in->nelem; i++) { p[i] = in->elem[i]->data; hdr32 = ntohl(*(uint32_t*)p[i]); if(hdr32 & LAY_HDR32_PAT) { if(hdrpt != (uint8_t)(LAY_HDR32_GET_PT(hdr32))) { debug_msg("layered headers do not match!\n"); goto done; } mrk[i] = (uint16_t)(LAY_HDR32_GET_MRK(hdr32)); len[i] = (uint16_t)(LAY_HDR32_GET_LEN(hdr32)); p[i] += 4; } else { debug_msg("Invalid layered header\n"); goto done; } } end = in->elem[in->nelem-1]->data + in->elem[in->nelem-1]->data_len; /* if layers missing say so */ if(in->nelem!=LAY_MAX_LAYERS) { debug_msg("Not all layers arrived:\n"); for(i=0; i<in->nelem; i++) { debug_msg("marker[%d] = %d\n", i, mrk[i]); } } /* Everything matches, so we'll use the first layer's details */ cu = (coded_unit*)block_alloc(sizeof(coded_unit)); memset(cu, 0, sizeof(coded_unit)); id = codec_get_by_payload(hdrpt); if (codec_id_is_valid(id) == FALSE) { debug_msg("Layered channel coder - codec_id not recognised.\n"); goto fail; } cf = codec_get_format(id); assert(cf != NULL); /* Do first unit separately as that may have state */ if (cf->mean_per_packet_state_size) { cu->state_len = cf->mean_per_packet_state_size; cu->state = (u_char*)block_alloc(cu->state_len); memcpy(cu->state, p[0], cf->mean_per_packet_state_size); for(i=0; i<in->nelem; i++) p[i] += cf->mean_per_packet_state_size; } data_len = codec_peek_frame_size(id, p[0], (uint16_t)(len[0])); m->rep[0]->id = cu->id = id; cu->data = (u_char*)block_alloc(data_len); cu->data_len = (uint16_t)data_len; memset(cu->data, 0, data_len); /* join the layers up here */ for(i=0; i<in->nelem; i++) { memcpy(cu->data + mrk[i], p[i], len[i]); p[i] += len[i]; } codec_combine_layer(id, cu, m->rep[0], in->nelem, mrk); if (cu->state_len) { block_free(cu->state, cu->state_len); cu->state = NULL; cu->state_len = 0; } assert(cu->state_len == 0); if (cu->data_len) { block_free(cu->data, cu->data_len); cu->data = NULL; cu->data_len = 0; } assert(cu->data_len == 0); if (pb_add(out, (u_char *)m, sizeof(media_data), playout) == FALSE) { debug_msg("layered decode failed\n"); goto fail; } /* Now do other units which do not have state*/ playout_step = ts_map32(cf->format.sample_rate, codec_get_samples_per_frame(id)); while(p[in->nelem - 1] < end) { playout = ts_add(playout, playout_step); media_data_create(&m, 1); m->rep[0]->id = id; assert(m->nrep == 1); cu->data = (u_char*)block_alloc(data_len); cu->data_len = (uint16_t)data_len; memset(cu->data, 0, data_len); for(i=0; i<in->nelem; i++) { memcpy(cu->data + mrk[i], p[i], len[i]); p[i] += len[i]; } codec_combine_layer(id, cu, m->rep[0], in->nelem, mrk); block_free(cu->data, cu->data_len); cu->data = 0; cu->data_len = 0; if (pb_add(out, (u_char *)m, sizeof(media_data), playout) == FALSE) { debug_msg("layered decode failed\n"); goto fail; } } assert(p[in->nelem - 1] == end); block_free(cu, sizeof(coded_unit)); channel_data_destroy(&in, sizeof(channel_data)); xmemchk(); return TRUE; fail: if (cu->state) { block_free(cu->state, cu->state_len); cu->state = 0; cu->state_len = 0; } assert(cu->state_len == 0); if (cu->data) { block_free(cu->data, cu->data_len); cu->data = 0; cu->data_len = 0; } assert(cu->data_len == 0); block_free(cu, sizeof(coded_unit)); done: media_data_destroy(&m, sizeof(media_data)); channel_data_destroy(&in, sizeof(channel_data)); xmemchk(); return FALSE; }
static void red_split_unit(u_char ppt, /* Primary payload type */ u_char bpt, /* Block payload type */ u_char *b, /* Block pointer */ uint32_t blen, /* Block len */ timestamp_t playout, /* Block playout time */ struct s_pb *out) /* media buffer */ { const codec_format_t *cf; media_data *md; codec_id_t cid, pid; coded_unit *cu; u_char *p,*pe; timestamp_t step; pid = codec_get_by_payload(ppt); if (!pid) { debug_msg("Payload not recognized\n"); return; } cid = codec_get_by_payload(bpt); if (!cid) { debug_msg("Payload not recognized\n"); return; } if (!codec_audio_formats_compatible(pid, cid)) { debug_msg("Primary (%d) and redundant (%d) not compatible\n", ppt, bpt); return; } cf = codec_get_format(cid); assert(cf != NULL); step = ts_map32(cf->format.sample_rate, codec_get_samples_per_frame(cid)); p = b; pe = b + blen; while(p < pe) { cu = (coded_unit*)block_alloc(sizeof(coded_unit)); cu->id = cid; if (p == b && cf->mean_per_packet_state_size) { cu->state_len = cf->mean_per_packet_state_size; cu->state = block_alloc(cu->state_len); memcpy(cu->state, p, cu->state_len); p += cu->state_len; } else { cu->state = NULL; cu->state_len = 0; } cu->data_len = (uint16_t)codec_peek_frame_size(cid, p, (uint16_t)(pe - p)); cu->data = block_alloc(cu->data_len); memcpy(cu->data, p, cu->data_len); p += cu->data_len; md = red_media_data_create_or_get(out, playout); if (md->nrep == MAX_MEDIA_UNITS) continue; if (place_unit(md, cu) == TRUE) { playout = ts_add(playout, step); } else { /* unit could not be placed - destroy */ if (cu->state_len) { block_free(cu->state, cu->state_len); } block_free(cu->data, cu->data_len); block_free(cu, sizeof(coded_unit)); } } }