コード例 #1
0
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;
}
コード例 #2
0
ファイル: ilbc.c プロジェクト: GGGO/baresip
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);
}
コード例 #3
0
ファイル: ilbc.c プロジェクト: GGGO/baresip
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;
}
コード例 #4
0
ファイル: ilbc.c プロジェクト: GGGO/baresip
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));
}
コード例 #5
0
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;
}
コード例 #6
0
/* 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;
}