int vanilla_decoder_peek(uint8_t pkt_pt, u_char *buf, uint32_t len, uint16_t *upp, uint8_t *pt) { codec_id_t cid; assert(buf != NULL); assert(upp != NULL); assert(pt != NULL); cid = codec_get_by_payload(pkt_pt); if (cid) { const codec_format_t *cf; uint32_t unit, done, step; /* Vanilla coding does nothing but group * units. */ cf = codec_get_format(cid); unit = 0; done = cf->mean_per_packet_state_size; while(done < len) { step = codec_peek_frame_size(cid, buf+done, (uint16_t)(len - done)); if (step == 0) { debug_msg("Zero data len for audio unit ?\n"); goto fail; } done += step; unit ++; } assert(done >= len); if (done != len) goto fail; *upp = (uint16_t)unit; *pt = pkt_pt; return TRUE; } fail: *upp = 0; *pt = 255; return FALSE; }
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); }
int layered_decoder_peek(uint8_t pkt_pt, u_char *buf, uint32_t len, uint16_t *upp, uint8_t *pt) { codec_id_t cid; u_char *p, *data; uint32_t hdr32; uint8_t hdrpt; uint16_t blen, mrk; assert(buf != NULL); assert(upp != NULL); assert(pt != NULL); UNUSED(pkt_pt); p = data = buf; hdr32 = ntohl(*(uint32_t*)p); if(hdr32 & LAY_HDR32_PAT) { hdrpt = (uint8_t)(LAY_HDR32_GET_PT(hdr32)); mrk = (uint16_t)(LAY_HDR32_GET_MRK(hdr32)); blen = (uint16_t)(LAY_HDR32_GET_LEN(hdr32)); p+=4; data += 4 + blen; hdr32 = ntohl(*(uint32_t*)p); /* assert(((uint32_t)data - (uint32_t)buf) <= blen); */ } else { debug_msg("Invalid layered header\n"); goto fail; } /* I'm haven't decided what exactly to do here yet, so for * the time being if the header seems OK we return TRUE. The * options are: * (i) have a new function codec_peek_layer_frame_size * (ii) work out length of total frame from length in header * (iii) just check that length of packet matches what is in * the header * But what to do about *upp? * The problem is that codec_peek_frame_size, if used with * codec_vdvi, calls vdvi_decode, assuming a complete frame. * Of course we only have one layer at this stage, so the * decode function will fail. I am going to ignore this for * the time being. */ *pt = hdrpt; cid = codec_get_by_payload(*pt); if (cid) { const codec_format_t *cf; uint32_t unit, done, step; /* extra check since the header check seems * to fail quite a lot (why?) */ if(codec_can_layer(cid)==1) goto fail; cf = codec_get_format(cid); unit = 0; done = cf->mean_per_packet_state_size; done += 4; /* step over header */ while(done < len) { step = codec_peek_frame_size(cid, buf+done, (uint16_t)(len)); if (step == 0) { debug_msg("Zero data len for audio unit ?\n"); goto fail; } done += blen; unit ++; } /* assert(done <= len);*/ if (done != len) goto fail; *upp = (uint16_t)unit; return TRUE; } debug_msg("layered_decoder_peek - codec not found\n"); fail: debug_msg("layered_decoder_peek error (len = %d)\n", len); *upp = 0; *pt = 255; return FALSE; }
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_decoder_peek(uint8_t pkt_pt, u_char *buf, uint32_t len, uint16_t *upp, uint8_t *pt) { const codec_format_t *cf; codec_id_t cid; u_char *p, *data; uint32_t hdr32, dlen, blen; uint16_t units; assert(buf != NULL); assert(upp != NULL); assert(pt != NULL); /* Just check primary, so skip over other headers and * advance data pointer past them. */ p = data = buf; hdr32 = ntohl(*(uint32_t*)p); while ((hdr32 & RED_HDR32_PAT)) { blen = RED_HDR32_GET_LEN(hdr32); p += 4; /* goto next hdr */ data += 4 + blen; hdr32 = ntohl(*(uint32_t*)p); assert(((unsigned long)data - (unsigned long)buf) <= len); } *pt = *p; data += 1; /* step over payload field of primary */ cid = codec_get_by_payload(*pt); if (!cid) { debug_msg("Codec not found\n"); return FALSE; } /* Primary data length */ dlen = len - (uint32_t)(data - buf); cf = codec_get_format(cid); assert(cf); data += cf->mean_per_packet_state_size; dlen -= cf->mean_per_packet_state_size; assert(((unsigned long)data - (unsigned long)buf) <= len); units = 0; while (dlen != 0) { blen = codec_peek_frame_size(cid, p, (uint16_t)dlen); assert(blen != 0); data += blen; dlen -= blen; units ++; assert(((unsigned long)data - (unsigned long)buf) <= len); } *upp = units; assert(*upp < 50); UNUSED(pkt_pt); return TRUE; }