static int modesreader_setmode(modesreader *self, PyObject *mode, void *dummy) { int i; if (mode == Py_None) { set_decoder_mode(self, DECODER_NONE); return 0; } for (i = 0; modetable[i].cstr != NULL; ++i) { int res = PyObject_RichCompareBool(modetable[i].pystr, mode, Py_EQ); if (res < 0) return -1; if (res == 1) { set_decoder_mode(self, modetable[i].mode); break; } } if (modetable[i].cstr == NULL) { PyErr_SetString(PyExc_ValueError, "unrecognized decoder mode"); return -1; } return 0; }
static int decode(struct audec_state *st, int16_t *sampv, size_t *sampc, const uint8_t *buf, size_t len) { /* Try to detect mode */ if (st->dec_bytes != len) { st->dec_bytes = len; switch (st->dec_bytes) { case NO_OF_BYTES_20MS: set_decoder_mode(st, 20); break; case NO_OF_BYTES_30MS: set_decoder_mode(st, 30); break; default: warning("ilbc: decode: expect %u, got %u\n", st->dec_bytes, len); return EINVAL; } } return do_dec(st, sampv, sampc, buf, len); }
static int decode_update(struct audec_state **adsp, const struct aucodec *ac, const char *fmtp) { struct audec_state *st; int err = 0; (void)fmtp; if (!adsp || !ac) return EINVAL; if (*adsp) return 0; st = mem_zalloc(sizeof(*st), decode_destructor); if (!st) return ENOMEM; set_decoder_mode(st, DEFAULT_MODE); if (str_isset(fmtp)) decoder_fmtp_decode(st, fmtp); if (err) mem_deref(st); else *adsp = st; return err; }
static void decoder_fmtp_decode(struct audec_state *st, const char *fmtp) { struct pl mode; if (!fmtp) return; if (re_regex(fmtp, strlen(fmtp), "mode=[0-9]+", &mode)) return; set_decoder_mode(st, pl_u32(&mode)); }
static PyObject *modesreader_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { modesreader *self; self = (modesreader *)type->tp_alloc(type, 0); if (self == NULL) return NULL; /* minimal init */ set_decoder_mode(self, DECODER_NONE); self->last_timestamp = 0; self->allow_mode_change = 1; self->want_zero_timestamps = 0; self->want_mlat_messages = 0; self->want_modeac_messages = 0; self->want_invalid_messages = 0; self->want_events = 1; self->seen = self->default_filter = self->specific_filter = NULL; self->received_messages = self->suppressed_messages = 0; return (PyObject *)self; }
/* feed implementation for Beast-format data (including Radarcape) */ static PyObject *feed_beast(modesreader *self, Py_buffer *buffer, int max_messages) { PyObject *rv = NULL; uint8_t *buffer_start, *p, *eod; int message_count = 0; PyObject *message_tuple = NULL; PyObject **messages = NULL; int error_pending = 0; buffer_start = buffer->buf; if (max_messages <= 0) { /* allocate the maximum size we might need, given a minimal encoding of: * <1A> <'1'> <6 bytes timestamp> <1 byte signal> <2 bytes message> = 11 bytes total */ max_messages = buffer->len / 11 + 2; } messages = calloc(max_messages, sizeof(PyObject*)); if (!messages) { PyErr_NoMemory(); goto out; } /* parse messages */ p = buffer_start; eod = buffer_start + buffer->len; while (p+2 <= eod && message_count+2 < max_messages) { int message_len = -1; uint64_t timestamp; uint8_t signal; uint8_t data[14]; uint8_t *m, *eom; int i; uint8_t type; PyObject *message; int wanted; if (p[0] != 0x1a) { error_pending = 1; if (message_count > 0) goto nomoredata; PyErr_Format(PyExc_ValueError, "Lost sync with input stream: expected a 0x1A marker at offset %d but found 0x%02x instead", (int) (p - buffer_start), (int)p[0]); goto out; } type = p[1]; switch (type) { case '1': message_len = 2; break; /* mode A/C */ case '2': message_len = 7; break; /* mode S short */ case '3': message_len = 14; break; /* mode S long */ case '4': message_len = 14; break; /* radarcape status message */ default: error_pending = 1; if (message_count > 0) goto nomoredata; PyErr_Format(PyExc_ValueError, "Lost sync with input stream: unexpected message type 0x%02x after 0x1A marker at offset %d", (int)p[1], (int) (p - buffer_start)); goto out; } m = p + 2; eom = m + 7 + message_len; if (eom > eod) break; #define ADVANCE \ do { \ if (*m++ == 0x1a) { \ if (m < eod && *m != 0x1a) { \ error_pending = 1; \ if (message_count > 0) \ goto nomoredata; \ PyErr_SetString(PyExc_ValueError, "Lost sync with input stream: expected 0x1A after 0x1A escape"); \ goto out; \ } \ ++m, ++eom; \ if (eom > eod) \ goto nomoredata; \ } \ } while(0) /* timestamp, 6 bytes */ timestamp = *m; ADVANCE; timestamp = (timestamp << 8) | *m; ADVANCE; timestamp = (timestamp << 8) | *m; ADVANCE; timestamp = (timestamp << 8) | *m; ADVANCE; timestamp = (timestamp << 8) | *m; ADVANCE; timestamp = (timestamp << 8) | *m; ADVANCE; /* signal, 1 byte */ signal = *m; ADVANCE; /* message, N bytes */ for (i = 0; i < message_len; ++i) { data[i] = *m; ADVANCE; } /* do some filtering */ if (type == '4') { /* radarcape-style status message, use this to switch our decoder type */ self->radarcape_utc_bugfix = (data[2] & 0x80) == 0x80; if (self->allow_mode_change) { decoder_mode newmode; if (data[0] & 0x10) { /* radarcape in GPS timestamp mode */ if ((data[2] & 0x20) == 0x20) { newmode = DECODER_RADARCAPE_EMULATED; } else { newmode = DECODER_RADARCAPE; } } else { /* radarcape in 12MHz timestamp mode */ newmode = DECODER_BEAST; } /* handle mode changes by inserting an event message */ if (newmode != self->decoder_mode) { set_decoder_mode(self, newmode); if (self->want_events) { if (! (messages[message_count++] = make_mode_change_event(self))) goto out; } } } } if (self->decoder_mode == DECODER_BEAST) { /* 12MHz mode */ /* check for very out of range value * (dump1090 can hold messages for up to 60 seconds! so be conservative here) * also work around dump1090-mutability issue #47 which can send very stale Mode A/C messages */ if (self->want_events && type != '1' && !timestamp_check(self, timestamp)) { if (! (messages[message_count++] = make_timestamp_jump_event(self, timestamp))) goto out; } } else { /* gps mode */ /* adjust timestamp so that it is a contiguous nanoseconds-since- * midnight value, rather than the raw form which skips values once * a second */ uint64_t nanos = timestamp & 0x00003FFFFFFF; uint64_t secs = timestamp >> 30; if (!self->radarcape_utc_bugfix) { /* fix up the timestamp so it is UTC, not 1 second ahead */ --secs; } timestamp = nanos + secs * 1000000000; /* adjust for the timestamp being at the _end_ of the frame; * we don't really care about getting a particular starting point * (that's just a fixed offset), so long as it is _the same in * every frame_. * * (but don't do this for status messages as they have a timestamp * as at the start of the message, which is basically the time of * the PPS) */ if (type != '4') { uint64_t adjust = (8000 + message_len * 8000); /* each byte takes 8us to transmit, plus 8us preamble */ if (adjust <= timestamp) { timestamp = timestamp - adjust; } else { /* wrap it to the previous day */ timestamp = timestamp + 86400 * 1000000000ULL - adjust; } } /* check for end of day rollover */ if (self->want_events && self->last_timestamp >= (86340 * 1000000000ULL) && timestamp <= (60 * 1000000000ULL)) { if (! (messages[message_count++] = make_epoch_rollover_event(self, timestamp))) goto out; } else if (self->want_events && type != '1' && !timestamp_check(self, timestamp)) { if (! (messages[message_count++] = make_timestamp_jump_event(self, timestamp))) goto out; } } if (type != '1') { timestamp_update(self, timestamp); } if (type == '4') { /* radarcape-style status message, emit the status event if wanted */ if (self->want_events) { if (! (messages[message_count++] = make_radarcape_status_event(self, timestamp, data))) goto out; } /* don't try to process this as a Mode S message */ p = m; continue; } /* it's a Mode A/C or Mode S message, parse it */ if (! (message = modesmessage_from_buffer(timestamp, signal, data, message_len))) goto out; /* apply filters, update seen-set */ ++self->received_messages; wanted = filter_message(self, message); if (wanted < 0) goto out; else if (wanted) messages[message_count++] = message; else { ++self->suppressed_messages; Py_DECREF(message); } p = m; } nomoredata: if (! (message_tuple = PyTuple_New(message_count))) goto out; while (--message_count >= 0) { PyTuple_SET_ITEM(message_tuple, message_count, messages[message_count]); /* steals ref */ } rv = Py_BuildValue("(l,N,N)", (long) (p - buffer_start), message_tuple, PyBool_FromLong(error_pending)); out: while (--message_count >= 0) { Py_XDECREF(messages[message_count]); } free(messages); return rv; }