int media_data_create(media_data **ppmd, int nrep) { media_data *pmd; int i; *ppmd = NULL; pmd = (media_data*)block_alloc(sizeof(media_data)); if (pmd) { memset(pmd, 0, sizeof(media_data)); for(i = 0; i < nrep; i++) { pmd->rep[i] = block_alloc(sizeof(coded_unit)); if (pmd->rep[i] == NULL) { pmd->nrep = i; media_data_destroy(&pmd, sizeof(media_data)); return FALSE; } memset(pmd->rep[i], 0, sizeof(coded_unit)); } pmd->nrep = nrep; *ppmd = pmd; return TRUE; } return FALSE; }
int vanilla_encoder_reset(u_char *state) { ve_state *ve = (ve_state*)state; uint32_t i; for(i = 0; i < ve->nelem; i++) { media_data_destroy(&ve->elem[i], sizeof(media_data)); } ve->nelem = 0; return TRUE; }
int layered_encoder_reset(u_char *state) { lay_state *le = (lay_state*)state; uint32_t i; for(i = 0; i < le->nelem; i++) { media_data_destroy(&le->elem[i], sizeof(media_data)); } le->nelem = 0; /* Should we be resetting the number of layers? * * This is only called in tx_stop(). */ /*le->n_layers = 1; */ debug_msg("layered_encoder_reset!\n"); return TRUE; }
static void vanilla_encoder_output(ve_state *ve, struct s_pb *out) { uint32_t i, used; channel_data *cd; /* We have state for first unit and data for all others */ channel_data_create(&cd, ve->nelem + 1); /* Fill in payload */ cd->elem[0]->pt = codec_get_payload(ve->codec_id); used = 0; /* Get state for first unit if there */ if (ve->elem[0]->rep[0]->state) { cd->elem[0]->data = ve->elem[0]->rep[0]->state; cd->elem[0]->data_len = ve->elem[0]->rep[0]->state_len; ve->elem[0]->rep[0]->state = NULL; ve->elem[0]->rep[0]->state_len = 0; used++; } /* Transfer coded data to channel_data */ for(i = 0; i < ve->nelem; i++) { cd->elem[used]->data = ve->elem[i]->rep[0]->data; cd->elem[used]->data_len = ve->elem[i]->rep[0]->data_len; ve->elem[i]->rep[0]->data = NULL; ve->elem[i]->rep[0]->data_len = 0; used++; media_data_destroy(&ve->elem[i], sizeof(media_data)); } ve->nelem = 0; assert(used <= cd->nelem); pb_add(out, (u_char*)cd, sizeof(channel_data), ve->playout); }
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); }
/* new unit dst. Returns TRUE on success. */ int media_data_dup(media_data **dst, media_data *src) { media_data *m; uint8_t i; if (media_data_create(&m, src->nrep) == FALSE) { *dst = NULL; return FALSE; } for(i = 0; i < src->nrep; i++) { if (coded_unit_dup(m->rep[i], src->rep[i]) == FALSE) { goto media_dup_failure; } } *dst = m; return TRUE; media_dup_failure: media_data_destroy(&m, sizeof(media_data)); return FALSE; }
static void test_repair(struct s_sndfile *sf_out, codec_id_t cid, repair_id_t repair_type, struct s_sndfile *sf_in) { codec_state *encoder; struct s_codec_state_store *decoder_states; media_data *md_prev, *md_cur; coded_unit *cu; int32_t consec_lost = 0, total_lost, total_done; const codec_format_t *cf; uint16_t i; repair_id_t repair_none; for (i = 0; i < repair_get_count(); i++) { const repair_details_t *rd; rd = repair_get_details(i); if (strcasecmp(rd->name, "none") == 0) { repair_none = rd->id; break; } } codec_encoder_create(cid, &encoder); codec_state_store_create(&decoder_states, DECODER); cf = codec_get_format(cid); /* Read and write one unit to kick off with */ media_data_create(&md_cur, 1); read_and_encode(md_cur->rep[0], encoder, sf_in); decode_and_write(sf_out, decoder_states, md_cur); /* Initialize next reading cycle */ md_prev = md_cur; md_cur = NULL; media_data_create(&md_cur, 1); total_lost = total_done = 0; while(read_and_encode(md_cur->rep[0], encoder, sf_in)) { total_done++; if (do_drop()) { total_lost++; media_data_destroy(&md_cur, sizeof(media_data)); media_data_create(&md_cur, 0); cu = (coded_unit*)block_alloc(sizeof(coded_unit)); assert(cu != NULL); memset(cu, 0, sizeof(coded_unit)); /* Loss happens - invoke repair */ if (repair_type != repair_none) { cu->id = cid; repair(repair_type, consec_lost, decoder_states, md_prev, cu); } else { /* Create a silent unit */ cu->id = codec_get_native_coding((uint16_t)cf->format.sample_rate, (uint16_t)cf->format.channels); cu->state = NULL; cu->state_len = 0; cu->data = (u_char*)block_alloc(cf->format.bytes_per_block); cu->data_len = cf->format.bytes_per_block; memset(cu->data, 0, cu->data_len); } /* Add repaired audio to frame */ md_cur->rep[md_cur->nrep] = cu; md_cur->nrep++; consec_lost++; } else { consec_lost = 0; } decode_and_write(sf_out, decoder_states, md_cur); media_data_destroy(&md_prev, sizeof(media_data)); md_prev = md_cur; md_cur = NULL; media_data_create(&md_cur, 1); } printf("# Dropped %d frames out of %d (%f loss %%)\n", total_lost, total_done, 100.0 * total_lost / (double)total_done); media_data_destroy(&md_cur, sizeof(media_data)); media_data_destroy(&md_prev, sizeof(media_data)); codec_encoder_destroy(&encoder); codec_state_store_destroy(&decoder_states); }
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; }
int layered_encoder_encode (u_char *state, struct s_pb *in, struct s_pb *out, uint32_t upp) { uint32_t m_len; timestamp_t playout; struct s_pb_iterator *pi; u_char *m_get; media_data *m; lay_state *le = (lay_state*)state; assert(upp != 0 && upp <= MAX_UNITS_PER_PACKET); pb_iterator_create(in, &pi); pb_iterator_advance(pi); /* Move to first element */ while(pb_iterator_detach_at(pi, &m_get, &m_len, &playout)) { /* Remove element from playout buffer - it belongs to * the layered encoder now. */ m = (media_data*)m_get; assert(m != NULL); if (le->nelem == 0) { /* If it's the first unit make a note of it's * playout */ le->playout = playout; if (m->nrep == 0) { /* We have no data ready to go and no data * came off on incoming queue. */ media_data_destroy(&m, sizeof(media_data)); continue; } } else { /* Check for early send required: * (a) if this unit has no media respresentations * e.g. end of talkspurt. * (b) codec type of incoming unit is different * from what is on queue. */ if (m->nrep == 0) { layered_encoder_output(le, out); media_data_destroy(&m, sizeof(media_data)); continue; } else if (m->rep[0]->id != le->codec_id) { layered_encoder_output(le, out); } } assert(m_len == sizeof(media_data)); le->codec_id = m->rep[0]->id; le->elem[le->nelem] = m; le->nelem++; if (le->nelem >= (uint32_t)upp) { layered_encoder_output(le, out); } } pb_iterator_destroy(in, &pi); xmemchk(); return TRUE; }
static void layered_encoder_output(lay_state *le, struct s_pb *out) { uint32_t i, used; channel_data *cd; uint8_t j; uint16_t cd_len[LAY_MAX_LAYERS], markers[LAY_MAX_LAYERS]; coded_unit *lu; /* We have state for first unit and data for all others */ channel_data_create(&cd, (le->nelem + 2)*(le->n_layers)); /* Fill in payload */ cd->elem[0]->pt = codec_get_payload(le->codec_id); used = 0; /* leave space for headers */ used += le->n_layers; /* Get state for first unit if there */ if (le->elem[0]->rep[0]->state) { for(j=0; j<le->n_layers; j++) { cd->elem[used]->data_len = le->elem[0]->rep[0]->state_len; //SV-XXX cd->elem[used]->data = (char *)block_alloc(le->elem[0]->rep[0]->state_len); cd->elem[used]->data = (unsigned char*)block_alloc(le->elem[0]->rep[0]->state_len); memcpy(cd->elem[used]->data, le->elem[0]->rep[0]->state, le->elem[0]->rep[0]->state_len); used++; } } for(j = 0; j < le->n_layers; j++) { cd_len[j] = 0; } lu = (coded_unit*)block_alloc(sizeof(coded_unit)); /* Transfer coded data to channel_data */ for(i = 0; i < le->nelem; i++) { for(j = 0; j < le->n_layers; j++) { codec_get_layer(le->codec_id, le->elem[i]->rep[0], j, markers, lu); cd->elem[used]->data_len = lu->data_len; //SV-XXX cd->elem[used]->data = (char*)block_alloc(lu->data_len); cd->elem[used]->data = (unsigned char*)block_alloc(lu->data_len); memcpy(cd->elem[used]->data, lu->data, lu->data_len); used++; if(i==0) cd_len[j] = (uint16_t)lu->data_len; if(lu->state_len) { block_free(lu->state, lu->state_len); lu->state = NULL; lu->state_len = 0; } if(lu->data_len) { block_free(lu->data, lu->data_len); lu->data = NULL; lu->data_len = 0; } } block_free(le->elem[i]->rep[0]->data, le->elem[i]->rep[0]->data_len); le->elem[i]->rep[0]->data = NULL; le->elem[i]->rep[0]->data_len = 0; media_data_destroy(&le->elem[i], sizeof(media_data)); } le->nelem = 0; assert(lu->data_len == 0); block_free(lu, sizeof(coded_unit)); for(j=0; j<le->n_layers; j++) { add_hdr(cd->elem[j], cd->elem[0]->pt, markers[j], cd_len[j]); } assert(used <= cd->nelem); pb_add(out, (u_char*)cd, sizeof(channel_data), le->playout); }
int redundancy_encoder_encode (u_char *state, struct s_pb *in, struct s_pb *out, uint32_t upp) { uint32_t m_len; timestamp_t playout; struct s_pb_iterator *pi; u_char *m_get; media_data *m; red_enc_state *re = (red_enc_state*)state; assert(upp != 0 && upp <= MAX_UNITS_PER_PACKET); pb_iterator_create(in, &pi); assert(pi != NULL); pb_iterator_advance(pi); while(pb_iterator_detach_at(pi, &m_get, &m_len, &playout)) { m = (media_data*)m_get; /* Remove element from playout buffer - it belongs to * the redundancy encoder now. */ #ifdef DEBUG_REDUNDANCY debug_msg("claimed %d, prev %d\n", playout.ticks, re->last_in.ticks); #endif /* DEBUG_REDUNDANCY */ assert(m != NULL); if (re->units_ready == 0) { re->last_in = playout; re->last_in.ticks--; } assert(ts_gt(playout, re->last_in)); re->last_in = playout; if (m->nrep > 0) { pb_add(re->media_buffer, (u_char*)m, m_len, playout); re->units_ready++; } else { /* Incoming unit has no data so transmission is * not happening. */ #ifdef DEBUG_REDUNDANCY debug_msg("No incoming data\n"); #endif /* DEBUG_REDUNDANCY */ media_data_destroy(&m, sizeof(media_data)); pb_flush(re->media_buffer); re->units_ready = 0; continue; } if (re->units_ready && (re->units_ready % upp) == 0) { channel_data *cd; int s; cd = redundancy_encoder_output(re, upp); assert(cd != NULL); s = pb_add(out, (u_char*)cd, sizeof(channel_data), playout); #ifdef DEBUG_REDUNDANCY debug_msg("Ready %d, Added %d\n", re->units_ready, playout.ticks); #endif /* DEBUG_REDUNDANCY */ assert(s); } } pb_iterator_destroy(in, &pi); return TRUE; }