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 (...) {} } }
static int aac_codec_check (lib_message_func_t message, const char *compressor, int type, int profile, format_list_t *fptr, const uint8_t *userdata, uint32_t userdata_size #ifdef HAVE_PLUGIN_VERSION_0_8 ,CConfigSet *pConfig #endif ) { fmtp_parse_t *fmtp = NULL; if (compressor != NULL && strcasecmp(compressor, "MP4 FILE") == 0 && type != -1) { switch (type) { case MP4_MPEG2_AAC_MAIN_AUDIO_TYPE: case MP4_MPEG2_AAC_LC_AUDIO_TYPE: case MP4_MPEG2_AAC_SSR_AUDIO_TYPE: case MP4_MPEG4_AUDIO_TYPE: break; default: return -1; } } if (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); message(LOG_DEBUG, "aac", "audio type is %d", audio_config.audio_object_type); if (fmtp != NULL) free_fmtp_parse(fmtp); if (audio_object_type_is_aac(&audio_config) == 0) { return -1; } #if 0 if (audio_config.audio_object_type == 17) { message(LOG_INFO, "aac", "audio type is legal ISMA, but not supported"); return -1; } #endif return 2; } #if 0 // I'm not sure I want to be here if we don't have an audio config if (compressor != NULL) { const char **lptr = aac_compressors; while (*lptr != NULL) { if (strcasecmp(*lptr, compressor) == 0) { return 2; } lptr++; } } #endif return -1; }
/* * Isma rtp bytestream has a potential set of headers at the beginning * of each rtp frame. This can interleave frames in different packets */ rtp_plugin_data_t *isma_rtp_plugin_create (format_list_t *media_fmt, uint8_t rtp_payload_type, rtp_vft_t *vft, void *ifptr) { isma_enc_rtp_data_t *iptr; fmtp_parse_t *fmtp; iptr = MALLOC_STRUCTURE(isma_enc_rtp_data_t); if ( iptr == NULL ) return NULL; memset(iptr, 0, sizeof(isma_enc_rtp_data_t)); if (strcasecmp(media_fmt->media->media, "audio") == 0) { ismacrypInitSession(&(iptr->myEncSID), KeyTypeAudio); } iptr->m_vft = vft; iptr->m_ifptr = ifptr; iptr->m_rtp_packet_mutex = SDL_CreateMutex(); #ifdef ISMA_RTP_DUMP_OUTPUT_TO_FILE iptr->m_outfile = fopen("isma.aac", "w"); #endif iptr->m_frame_data_head = NULL; iptr->m_frame_data_on = NULL; iptr->m_frame_data_free = NULL; isma_frame_data_t *p; for (iptr->m_frame_data_max = 0; iptr->m_frame_data_max < 25; iptr->m_frame_data_max++) { p = (isma_frame_data_t *)malloc(sizeof(isma_frame_data_t)); p->frame_data_next = iptr->m_frame_data_free; iptr->m_frame_data_free = p; } fmtp = parse_fmtp_for_mpeg4(media_fmt->fmt_param, iptr->m_vft->log_msg); mpeg4_audio_config_t audio_config; decode_mpeg4_audio_config(fmtp->config_binary, fmtp->config_binary_len, &audio_config); if (audio_object_type_is_aac(&audio_config)) { iptr->m_rtp_ts_add = audio_config.codec.aac.frame_len_1024 != 0 ? 1024 : 960; } else { iptr->m_rtp_ts_add = audio_config.codec.celp.samples_per_frame; isma_message(LOG_DEBUG, ismaencrtp, "celp spf is %d", iptr->m_rtp_ts_add); } iptr->m_rtp_ts_add = (iptr->m_rtp_ts_add * media_fmt->rtpmap->clock_rate) / audio_config.frequency; isma_message(LOG_DEBUG, ismaencrtp, "Rtp ts add is %d (%d %d)", iptr->m_rtp_ts_add, media_fmt->rtpmap->clock_rate, audio_config.frequency); iptr->m_fmtp = fmtp; iptr->m_min_first_header_bits = iptr->m_fmtp->size_length + iptr->m_fmtp->index_length; iptr->m_min_header_bits = iptr->m_fmtp->size_length + iptr->m_fmtp->index_delta_length; if (iptr->m_fmtp->CTS_delta_length > 0) { iptr->m_min_header_bits++; iptr->m_min_first_header_bits++; } if (iptr->m_fmtp->DTS_delta_length > 0) { iptr->m_min_header_bits++; iptr->m_min_first_header_bits++; } isma_message(LOG_DEBUG, ismaencrtp, "min headers are %d %d", iptr->m_min_first_header_bits, iptr->m_min_header_bits); iptr->m_min_header_bits += iptr->m_fmtp->auxiliary_data_size_length; iptr->m_min_first_header_bits += iptr->m_fmtp->auxiliary_data_size_length; iptr->m_frag_reass_buffer = NULL; iptr->m_frag_reass_size_max = 0; return (&iptr->plug); }
static int aac_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 (compressor != NULL && strcasecmp(stream_type, "MP4 FILE") == 0 && type != -1) { switch (type) { case MP4_MPEG2_AAC_MAIN_AUDIO_TYPE: case MP4_MPEG2_AAC_LC_AUDIO_TYPE: case MP4_MPEG2_AAC_SSR_AUDIO_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) && (strcasecmp(fptr->rtpmap->encode_name, "enc-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); // message(LOG_DEBUG, "aac", "audio type is %d", audio_config.audio_object_type); if (fmtp != NULL) free_fmtp_parse(fmtp); if (audio_object_type_is_aac(&audio_config) == 0) { return -1; } if (audio_config.audio_object_type == 17) { message(LOG_INFO, "aac", "audio type is legal ISMA, but not supported"); return -1; } return 1; } if (compressor != NULL) { const char **lptr = aac_compressors; while (*lptr != NULL) { if (strcasecmp(*lptr, compressor) == 0) { return 1; } lptr++; } } return -1; }