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); }
/* 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); } }
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)); } } }
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; }