static int celp_codec_check (lib_message_func_t message, const char *stream_type, const char *compressor, int type, int profile, format_list_t *fptr, const uint8_t *userdata, uint32_t userdata_size, CConfigSet *pConfig) { fmtp_parse_t *fmtp = NULL; if (strcasecmp(stream_type, STREAM_TYPE_MP4_FILE) == 0 && type != -1) { switch (type) { case MP4_MPEG4_AUDIO_TYPE: break; default: return -1; } } if (strcasecmp(stream_type, STREAM_TYPE_RTP) == 0 && fptr != NULL && fptr->rtpmap != NULL && fptr->rtpmap->encode_name != NULL) { if (strcasecmp(fptr->rtpmap->encode_name, "mpeg4-generic") != 0) { return -1; } if (userdata == NULL) { fmtp = parse_fmtp_for_mpeg4(fptr->fmt_param, message); if (fmtp != NULL) { userdata = fmtp->config_binary; userdata_size = fmtp->config_binary_len; } } } if (userdata != NULL) { mpeg4_audio_config_t audio_config; decode_mpeg4_audio_config(userdata, userdata_size, &audio_config, false); if (fmtp != NULL) free_fmtp_parse(fmtp); if (audio_object_type_is_celp(&audio_config) == 0) { return -1; } return 1; } if (compressor != NULL) { const char **lptr = celp_compressors; while (*lptr != NULL) { if (strcasecmp(*lptr, compressor) == 0) { return 1; } lptr++; } } return -1; }
extern "C" void decode_mpeg4_audio_config (const uint8_t *buffer, uint32_t buf_len, mpeg4_audio_config_t *mptr) { CBitstream bit; uint32_t ret; bit.init(buffer, buf_len * 8); if (bit.getbits(5, &ret) < 0) return; mptr->audio_object_type = ret; if (bit.getbits(4, &ret) < 0) return; if (ret == 0xf) { if (bit.getbits(24, &ret) < 0) return; mptr->frequency = ret; } else { mptr->frequency = freq_index_to_freq[ret]; } if (bit.getbits(4, &ret) < 0) return; mptr->channels = ret; // rptr points to remaining bits - starting with 0x04, moving // down buffer_len. if (audio_object_type_is_aac(mptr)) { if (bit.getbits(1, &ret) < 0) return; if (ret == 0) { mptr->codec.aac.frame_len_1024 = 1; } else { mptr->codec.aac.frame_len_1024 = 0; } } else if (audio_object_type_is_celp(mptr)){ try { mptr->codec.celp.isBaseLayer = bit.GetBits(1); if (mptr->codec.celp.isBaseLayer == 0) { mptr->codec.celp.isBWSLayer = bit.GetBits(1); if (mptr->codec.celp.isBWSLayer == 0) { mptr->codec.celp.CELP_BRS_id = bit.GetBits(2); } } mptr->codec.celp.NumOfBitsInBuffer=bit.bits_remain(); mptr->codec.celp.excitation_mode = bit.GetBits(1); mptr->codec.celp.sample_rate_mode = bit.GetBits(1); mptr->codec.celp.fine_rate_control = bit.GetBits(1); if (mptr->codec.celp.excitation_mode == CELP_EXCITATION_MODE_RPE) { mptr->codec.celp.rpe_config = bit.GetBits(3); // 16000 is 10 msec, all others are 15 msec if (mptr->codec.celp.rpe_config == 1) // 16000 bitrate mptr->codec.celp.samples_per_frame = (16000 * 10) / 1000; else mptr->codec.celp.samples_per_frame = (16000 * 15) / 1000; } else { mptr->codec.celp.mpe_config = bit.GetBits(5); mptr->codec.celp.num_enh_layers = bit.GetBits(2); if (mptr->codec.celp.sample_rate_mode == 1) { // 16kHz sample rate if (mptr->codec.celp.mpe_config < 16) { mptr->codec.celp.samples_per_frame = (16000 * 20) / 1000; } else { mptr->codec.celp.samples_per_frame = (16000 * 10) / 1000; } } else { if (bit.bits_remain() > 0) { mptr->codec.celp.bwsm = bit.GetBits(1); } else { mptr->codec.celp.bwsm = 0; } if (mptr->codec.celp.mpe_config < 3) { //40 mptr->codec.celp.samples_per_frame = (8000 * 40) / 1000; } else if (mptr->codec.celp.mpe_config < 6) { // 30 mptr->codec.celp.samples_per_frame = (8000 * 30) / 1000; } else if (mptr->codec.celp.mpe_config < 22) { // 20 mptr->codec.celp.samples_per_frame = (8000 * 20) / 1000; } else if (mptr->codec.celp.mpe_config < 27) { // 10 mptr->codec.celp.samples_per_frame = (8000 * 10) / 1000; } else { // 30 mptr->codec.celp.samples_per_frame = (8000 * 30) / 1000; } if (mptr->codec.celp.bwsm != 0) { mptr->codec.celp.samples_per_frame *= 2; } } } } catch (...) {} } }