Beispiel #1
0
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);
}
static int
read_and_encode(coded_unit        *out,
                codec_state       *encoder, 
                struct s_sndfile  *sf_in)
{
        const codec_format_t *cf;
        coded_unit           dummy;
        sample               *buf;
        uint16_t req_samples, act_samples;

        req_samples = codec_get_samples_per_frame(encoder->id);
        buf         = (sample*)block_alloc(sizeof(sample) * req_samples);

        act_samples = (uint16_t)snd_read_audio(&sf_in, buf, req_samples);

        if (req_samples != act_samples) {
                memset(buf + act_samples, 0, sizeof(short) * (req_samples - act_samples));
        }

        cf = codec_get_format(encoder->id);
        assert(cf != NULL);
        dummy.id = codec_get_native_coding((uint16_t)cf->format.sample_rate, 
                                            (uint16_t)cf->format.channels);
        dummy.state     = NULL;
        dummy.state_len = 0;
        dummy.data      = (u_char*)buf;
        dummy.data_len  = req_samples * sizeof(short);

        assert(out != NULL);

        if (codec_encode(encoder, &dummy, out) == FALSE) {
                abort();
        }

        block_free(dummy.data, dummy.data_len);

        return (sf_in != NULL);
}
Beispiel #3
0
/* Adds header to next free slot in channel_data */
static void
add_hdr(channel_unit *chu, int hdr_type, codec_id_t cid, uint32_t uo, uint32_t len)
{
        uint32_t so;             /* sample time offset */
        u_char  pt;

        assert(chu != NULL);
        assert(chu->data == NULL);

        pt = codec_get_payload(cid);
        assert(payload_is_valid(pt));

        so = codec_get_samples_per_frame(cid) * uo;

        assert(so <= RED_MAX_OFFSET);
        assert(len <= RED_MAX_LEN );

        if (hdr_type == RED_EXTRA) {
                uint32_t *h;
                h = (uint32_t*)block_alloc(4);
                RED_HDR32_INIT(*h);
                RED_HDR32_SET_PT(*h, (uint32_t)pt);
                RED_HDR32_SET_OFF(*h, so);
                RED_HDR32_SET_LEN(*h, len);
                *h = htonl(*h);
                chu->data     = (u_char*)h;
                chu->data_len = sizeof(*h);
        } else {
                u_char *h;
                assert(hdr_type == RED_PRIMARY);
                h = (u_char*)block_alloc(1);
                RED_HDR8_INIT(*h);
                RED_HDR8_SET_PT(*h, pt);
                chu->data     = h;
                chu->data_len = sizeof(*h);
        }
}
Beispiel #4
0
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;
}
Beispiel #5
0
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));
                }
        }
}
Beispiel #6
0
int
redundancy_encoder_set_parameters(u_char *state, char *cmd)
{
        u_char *encbuf;
        red_enc_state *n, *cur;
        const codec_format_t *cf;
        uint32_t nl, po;
        codec_id_t  cid;
        char *s;
        int success = FALSE;

        assert(state != NULL);
        assert(cmd   != NULL);

        /* Create a temporary encoder, try to set it's params */
        redundancy_encoder_create(&encbuf, &nl);
        n = (red_enc_state*)encbuf;
        assert(n != NULL);

        s = (char *) strtok(cmd, "/");
        cid = codec_get_by_name(s);
        if (!codec_id_is_valid(cid)) {
                debug_msg("codec not recognized\n");
                goto done;
        }

        s = (char *) strtok(NULL, "/");
        po = atoi(s);

        if (po > 20) {
                debug_msg("offset too big\n");
                goto done;
        }

        n->layer[0].cid       = cid;
        n->layer[0].pkts_off  = po;
        n->n_layers           = 1;

        while (n->n_layers < RED_MAX_LAYERS) {
                s = (char *) strtok(NULL, "/");
                if (s == NULL) break;
                cid = codec_get_by_name(s);
                if (!codec_id_is_valid(cid)) {
                        debug_msg("codec not recognized\n");
                        goto done;
                }

                s = (char *) strtok(NULL, "/");
                if (s == NULL) {
                        debug_msg("Incomplete layer info\n");
                        goto done;
                }
                po = atoi(s);
                if (po > 20) {
                        debug_msg("offset too big\n");
                        goto done;
                }

                n->layer[n->n_layers].cid      = cid;
                n->layer[n->n_layers].pkts_off = po;
                n->n_layers ++;
        }


        redundancy_encoder_reset(state);
        /* Take bits from temporary encoder state we want */
        cur = (red_enc_state*)state;
        memcpy(cur->layer, n->layer, sizeof(red_layer)*RED_MAX_LAYERS);
        cur->n_layers = n->n_layers;

        /* work out history = duration of audio frame * maximum offset */
        cf = codec_get_format(cur->layer[cur->n_layers - 1].cid);
        cur->history = ts_map32(cf->format.sample_rate,
                                codec_get_samples_per_frame(cur->layer[cur->n_layers - 1].cid) *
                                cur->layer[cur->n_layers - 1].pkts_off);

        success = TRUE;
done:
        encbuf = (u_char*)n;
        redundancy_encoder_destroy(&encbuf, nl);
        return success;
}