int codec_encode(codec_state *cs, coded_unit *in_native, coded_unit *cu) { uint16_t ifs, fmt; int success; assert(cs != NULL); assert(in_native != NULL); assert(cu != NULL); assert(codec_is_native_coding(in_native->id)); assert (in_native->state == NULL); #ifdef DEBUG { const codec_format_t *cf = codec_get_format(cs->id); assert (cf->format.bytes_per_block == in_native->data_len); } #endif cu->id = cs->id; ifs = CODEC_GET_IFS_INDEX(cu->id); fmt = CODEC_GET_FMT_INDEX(cu->id); xmemchk(); success = codec_table[ifs].cx_encode(fmt, cs->state, (sample*)in_native->data, cu); xmemchk(); return success; }
static int place_unit(media_data *md, coded_unit *cu) { int16_t i; #ifdef DEBUG_REDUNDANCY const codec_format_t *cf; cf = codec_get_format(cu->id); debug_msg("%d %s\n", md->nrep, cf->long_name); #endif /* DEBUG_REDUNDANCY */ assert(md->nrep < MAX_MEDIA_UNITS); for (i = 0; i < md->nrep; i++) { if (md->rep[i]->id == cu->id) { return FALSE; } } if (md->nrep > 0 && codec_is_native_coding(md->rep[md->nrep - 1]->id)) { /* Buffer shifts can mean redundancy is received after primary decoded. */ /* Just discard. i.e. pkt 1 (t1 t0) pkt2 (t2 t1), if pkt2 arrives after */ /* pkt1 decoded we don't want to append redundant t1 data as it confuses */ /* decoder. */ /* XXX Should check for packet re-ordering i.e. pkt2 arrives and is */ /* decoded before pkt 1 then should use pkt 1's data as this will be */ /* higher quality under normal circumstances. */ return FALSE; } md->rep[md->nrep] = cu; md->nrep++; return TRUE; }
static void decode_and_write(struct s_sndfile *sf_out, struct s_codec_state_store *decoder_states, media_data *md) { codec_state *decoder; coded_unit *cu; int i; assert(md->nrep > 0); for(i = 0; i < md->nrep; i++) { if (codec_is_native_coding(md->rep[i]->id)) { break; } } if (i == md->nrep) { /* no decoded audio available for frame */ cu = (coded_unit*)block_alloc(sizeof(coded_unit)); assert(cu != NULL); memset(cu, 0, sizeof(coded_unit)); decoder = codec_state_store_get(decoder_states, md->rep[0]->id); codec_decode(decoder, md->rep[0], cu); assert(md->rep[md->nrep] == NULL); md->rep[md->nrep] = cu; md->nrep++; } assert(codec_is_native_coding(md->rep[md->nrep - 1]->id)); assert(sf_out != NULL); snd_write_audio(&sf_out, (sample*)md->rep[md->nrep - 1]->data, md->rep[md->nrep - 1]->data_len / sizeof(sample)); }
int codec_decode(codec_state *cs, coded_unit *in, coded_unit *out) { const codec_format_t *cf; codec_id_t id; uint16_t ifs, fmt, rate, channels; int success; assert(cs != NULL); assert(out != NULL); assert(in != NULL); id = cs->id; assert(in->id == cs->id); assert(codec_is_native_coding(in->id) == FALSE); ifs = CODEC_GET_IFS_INDEX(id); fmt = CODEC_GET_FMT_INDEX(id); /* Setup outgoing data block */ cf = codec_get_format(id); assert(out->state == NULL); assert(out->data == NULL); rate = (uint16_t)cf->format.sample_rate; channels = (uint16_t)cf->format.channels; out->id = codec_get_native_coding(rate, channels); out->data_len = cf->format.bytes_per_block; out->data = (u_char*)block_alloc(out->data_len); /* Decode */ xmemchk(); success = codec_table[ifs].cx_decode(fmt, cs->state, in, (sample*)out->data); xmemchk(); return success; }
int codec_get_native_info(codec_id_t cid, uint16_t *p_rate, uint16_t *p_channels) { uint32_t i, c, index; if (codec_is_native_coding(cid)) { index = CODEC_GET_FMT_INDEX(cid); /* Calculate and verify index in table of acceptable rates */ i = index / max_channels; if (p_rate != NULL) { *p_rate = sampling_rates[i]; } /* Calculate and verify number of channels */ c = (index % max_channels) + 1; if (p_channels != NULL) { *p_channels = (uint16_t)c; } return TRUE; } return FALSE; }
int codec_id_is_valid(codec_id_t id) { uint32_t ifs, fmt; if (codec_is_native_coding(id)) { /* Native codings should be tested with * codec_is_native_coding */ debug_msg("Coding is invalid because it is a native coding\n"); return FALSE; } if (!CODEC_VALID_PAD(id) || !CODEC_VALID_IFS(id) || !CODEC_VALID_FMT(id)) { debug_msg("Codec id (0x%08x) invalid (pad %x, ifs %x, fmt %x)", id, CODEC_VALID_PAD(id), CODEC_VALID_IFS(id), CODEC_VALID_FMT(id)); return FALSE; } ifs = CODEC_GET_IFS_INDEX(id); fmt = CODEC_GET_FMT_INDEX(id); if (ifs >= NUM_CODEC_INTERFACES) { /* Table index too large */ debug_msg("Codec index outside table\n"); return FALSE; } if (fmt >= num_fmts_supported[ifs]) { /* Format index too large */ debug_msg("Format index outside table %d / %d\n", fmt, num_fmts_supported[ifs]); return FALSE; } return TRUE; }
int repair(repair_id_t r, int consec_lost, struct s_codec_state_store *states, media_data *prev, coded_unit *missing) { int src, success; r = REPAIR_ID_TO_IDX(r); assert((unsigned)r < REPAIR_NUM_SCHEMES); if (prev->nrep == 0) { debug_msg("No data to repair from\n"); return FALSE; } assert(missing->state == 0); assert(missing->data == 0); /* check if first encoding has repair routine, test does * not make sense with a native (raw) encoding so check * that first */ if (codec_specific_repair_allowed && codec_is_native_coding(prev->rep[0]->id) == FALSE && codec_decoder_can_repair(prev->rep[0]->id) && prev->rep[0]->id == missing->id) { codec_state *st; st = codec_state_store_get(states, prev->rep[0]->id); success = codec_decoder_repair(prev->rep[0]->id, st, (uint16_t)consec_lost, prev->rep[0], missing, NULL); return success; } /* If native (waveform) audio is available, the last entry is device * compatible if it is native. We use this as it means we don't have to * re-apply 3d rendering and sample rate conversion if they are in use. */ src = prev->nrep - 1; if (src >= 0 && codec_is_native_coding(prev->rep[src]->id)) { const audio_format *pfmts[2]; audio_format fmt; coded_unit *p; uint32_t rate; uint16_t channels; sample *bufs[2]; p = prev->rep[src]; /* set up missing block */ missing->id = p->id; missing->data = (u_char*)block_alloc(p->data_len); missing->data_len = p->data_len; /* set up format */ codec_get_native_info(p->id, &rate, &channels); fmt.encoding = DEV_S16; fmt.sample_rate = (int)rate; fmt.bits_per_sample = 16; fmt.channels = channels; fmt.bytes_per_block = p->data_len; /* Pointer tweaking to get data in format repair function * expects. */ pfmts[0] = &fmt; pfmts[1] = &fmt; bufs[0] = (sample*) p->data; bufs[1] = (sample*) missing->data; schemes[r].action(bufs, pfmts, 2, 1, consec_lost); return TRUE; } else { debug_msg("No native audio in previous unit to use for repair\n"); } return FALSE; }