int speex_inband_handler(SpeexBits *bits, SpeexCallback *callback_list, void *state) { int id; SpeexCallback *callback; /*speex_bits_advance(bits, 5);*/ id=speex_bits_unpack_unsigned(bits, 4); callback = callback_list+id; if (callback->func) { return callback->func(bits, state, callback->data); } else /*If callback is not registered, skip the right number of bits*/ { int adv; if (id<2) adv = 1; else if (id<8) adv = 4; else if (id<10) adv = 8; else if (id<12) adv = 16; else if (id<14) adv = 32; else adv = 64; speex_bits_advance(bits, adv); } return 0; }
/* * Decode frame. */ static pj_status_t spx_codec_decode( pjmedia_codec *codec, const struct pjmedia_frame *input, unsigned output_buf_len, struct pjmedia_frame *output) { struct spx_private *spx; unsigned samples_per_frame; spx = (struct spx_private*) codec->codec_data; samples_per_frame=spx_factory.speex_param[spx->param_id].samples_per_frame; PJ_ASSERT_RETURN(output_buf_len >= samples_per_frame << 1, PJMEDIA_CODEC_EPCMTOOSHORT); if (input->type != PJMEDIA_FRAME_TYPE_AUDIO) { pjmedia_zero_samples((pj_int16_t*)output->buf, samples_per_frame); output->size = samples_per_frame << 1; output->timestamp.u64 = input->timestamp.u64; output->type = PJMEDIA_FRAME_TYPE_AUDIO; return PJ_SUCCESS; } /* Copy the data into the bit-stream struct */ speex_bits_read_from(&spx->dec_bits, (char*)input->buf, (int)input->size); /* Set Speex dec_bits pointer to the start bit of the frame */ speex_bits_advance(&spx->dec_bits, input->bit_info); /* Decode the data */ speex_decode_int(spx->dec, &spx->dec_bits, (spx_int16_t*)output->buf); output->type = PJMEDIA_FRAME_TYPE_AUDIO; output->size = samples_per_frame << 1; output->timestamp.u64 = input->timestamp.u64; return PJ_SUCCESS; }
/* This function will iterate frames & submodes in the Speex bits. * Returns 0 if a frame found, otherwise returns -1. */ int speex_get_next_frame(SpeexBits *bits) { static const int inband_skip_table[NB_SUBMODES] = {1, 1, 4, 4, 4, 4, 4, 4, 8, 8, 16, 16, 32, 32, 64, 64 }; static const int wb_skip_table[SB_SUBMODES] = {SB_SUBMODE_BITS+1, 36, 112, 192, 352, -1, -1, -1}; unsigned submode; unsigned nb_count = 0; while (speex_bits_remaining(bits) >= 5) { unsigned wb_count = 0; unsigned bit_ptr = bits->bitPtr; unsigned char_ptr = bits->charPtr; /* WB frame */ while ((speex_bits_remaining(bits) >= 4) && speex_bits_unpack_unsigned(bits, 1)) { int advance; submode = speex_bits_unpack_unsigned(bits, 3); advance = wb_skip_table[submode]; if (advance < 0) { TRACE__((THIS_FUNC, "Invalid mode encountered. " "The stream is corrupted.")); return -1; } TRACE__((THIS_FUNC, "WB layer skipped: %d bits", advance)); advance -= (SB_SUBMODE_BITS+1); speex_bits_advance(bits, advance); bit_ptr = bits->bitPtr; char_ptr = bits->charPtr; /* Consecutive subband frames may not exceed 2 frames */ if (++wb_count > 2) return -1; } /* End of bits, return the frame */ if (speex_bits_remaining(bits) < 4) { TRACE__((THIS_FUNC, "End of stream")); return 0; } /* Stop iteration, return the frame */ if (nb_count > 0) { bits->bitPtr = bit_ptr; bits->charPtr = char_ptr; return 0; } /* Get control bits */ submode = speex_bits_unpack_unsigned(bits, 4); TRACE__((THIS_FUNC, "Control bits: %d at %d", submode, bits->charPtr*8+bits->bitPtr)); if (submode == 15) { TRACE__((THIS_FUNC, "Found submode: terminator")); return -1; } else if (submode == 14) { /* in-band signal; next 4 bits contain signal id */ submode = speex_bits_unpack_unsigned(bits, 4); TRACE__((THIS_FUNC, "Found submode: in-band %d bits", inband_skip_table[submode])); speex_bits_advance(bits, inband_skip_table[submode]); } else if (submode == 13) { /* user in-band; next 5 bits contain msg len */ submode = speex_bits_unpack_unsigned(bits, 5); TRACE__((THIS_FUNC, "Found submode: user-band %d bytes", submode)); speex_bits_advance(bits, submode * 8); } else if (submode > 8) { TRACE__((THIS_FUNC, "Unknown sub-mode %d", submode)); return -1; } else { /* NB frame */ unsigned int advance = submode; speex_mode_query(&speex_nb_mode, SPEEX_SUBMODE_BITS_PER_FRAME, &advance); if (advance < 0) { TRACE__((THIS_FUNC, "Invalid mode encountered. " "The stream is corrupted.")); return -1; } TRACE__((THIS_FUNC, "Submode %d: %d bits", submode, advance)); advance -= (NB_SUBMODE_BITS+1); speex_bits_advance(bits, advance); ++nb_count; } } return 0; }
/* Default handler for user callbacks: skip it */ int speex_default_user_handler(SpeexBits *bits, void *state, void *data) { int req_size = speex_bits_unpack_unsigned(bits, 4); speex_bits_advance(bits, 5+8*req_size); return 0; }