int redundancy_decoder_decode(u_char *state, struct s_pb *in, struct s_pb *out, timestamp_t now) { struct s_pb_iterator *pi; u_char *c_get; channel_data *c; uint32_t clen; timestamp_t cplayout; pb_iterator_create(in, &pi); assert(pi != NULL); assert(state == NULL); /* No decoder state necesssary */ UNUSED(state); while(pb_iterator_get_at(pi, &c_get, &clen, &cplayout)) { c = (channel_data*)c_get; assert(c != NULL); assert(clen == sizeof(channel_data)); if (ts_gt(cplayout, now)) { break; } pb_iterator_detach_at(pi, &c_get, &clen, &cplayout); c = (channel_data*)c_get; assert(c->nelem == 1); redundancy_decoder_output(c->elem[0], out, cplayout); channel_data_destroy(&c, sizeof(channel_data)); } pb_iterator_destroy(in, &pi); return TRUE; }
int vanilla_decoder_decode(u_char *state, struct s_pb *in, struct s_pb *out, timestamp_t now) { struct s_pb_iterator *pi; channel_unit *cu; u_char *c_get; channel_data *c; uint32_t clen; timestamp_t playout; assert(state == NULL); /* No decoder state needed */ UNUSED(state); pb_iterator_create(in, &pi); assert(pi != NULL); while(pb_iterator_get_at(pi, &c_get, &clen, &playout)) { c = (channel_data*)c_get; assert(c != NULL); assert(clen == sizeof(channel_data)); if (ts_gt(playout, now)) { /* Playout point of unit is after now. Stop! */ break; } pb_iterator_detach_at(pi, &c_get, &clen, &playout); c = (channel_data*)c_get; assert(c != NULL); assert(c->nelem == 1); cu = c->elem[0]; vanilla_decoder_output(cu, out, playout); channel_data_destroy(&c, sizeof(channel_data)); } pb_iterator_destroy(in, &pi); return TRUE; }
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 channel_data * redundancy_encoder_output(red_enc_state *re, uint32_t upp) { struct s_pb_iterator *pbm; channel_data *cd_coded[RED_MAX_LAYERS], *cd_out; uint32_t offset ; int i, j, layers, success = 0, used = 0; pbm = re->media_pos; pb_iterator_ffwd(pbm); /*** Stage 1: Packing coded audio units ******************************/ /* Rewind iterator to start of first pdu */ for(i = 1; (uint32_t)i < upp; i++) { success = pb_iterator_retreat(pbm); assert(success); } offset = 0; layers = 0; for (i = 0; (uint32_t)i < re->n_layers; i++) { if (re->units_ready <= re->layer[i].pkts_off * upp) { break; } /* Move back to start of this layer */ while (offset < re->layer[i].pkts_off * upp) { success = pb_iterator_retreat(pbm); if (success == FALSE) break; offset++; } xmemchk(); /* need upp data elements + 1 for state */ channel_data_create(&cd_coded[i], upp + 1); success = make_pdu(pbm, upp, re->layer[i].cid, cd_coded[i]); /* make_pdu may fail because coding not available */ if (success == FALSE) { channel_data_destroy(&cd_coded[i], sizeof(channel_data)); break; } layers++; } #ifdef DEBUG_REDUNDANCY debug_msg("end of data collection\n"); #endif /* DEBUG_REDUNDANCY */ assert(layers != 0); /* Create channel_data unit that will get output */ channel_data_create(&cd_out, layers * (upp + 1) + re->n_layers); /*** Stage 2: Packing redundancy headers *****************************/ used = 0; if ((uint32_t)layers != re->n_layers) { /* Add max offset if we didn't make all units */ add_hdr(cd_out->elem[used], RED_EXTRA, re->layer[re->n_layers - 1].cid, re->layer[re->n_layers - 1].pkts_off * upp, 0); used++; } i = layers - 1; while (i > 0) { add_hdr(cd_out->elem[used], RED_EXTRA, re->layer[re->n_layers - 1].cid, re->layer[re->n_layers - 1].pkts_off * upp, channel_data_bytes(cd_coded[i])); used++; i--; } add_hdr(cd_out->elem[used], RED_PRIMARY, re->layer[0].cid, re->layer[0].pkts_off * upp, 0); used++; /*** Stage 3: Transfering coded units into output unit ***************/ for(i = layers - 1; i >= 0; i--) { for (j = 0; j < cd_coded[i]->nelem && cd_coded[i]->elem[j]->data != NULL; j++) { cd_out->elem[used]->data = cd_coded[i]->elem[j]->data; cd_out->elem[used]->data_len = cd_coded[i]->elem[j]->data_len; cd_coded[i]->elem[j]->data = NULL; cd_coded[i]->elem[j]->data_len = 0; used++; assert(used <= cd_out->nelem); } assert(used <= cd_out->nelem); channel_data_destroy(&cd_coded[i], sizeof(channel_data)); } pb_iterator_audit(pbm, re->history); /* Clear old rubbish */ return cd_out; }