📄 aac.cpp
字号:
/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is MPEG4IP. * * The Initial Developer of the Original Code is Cisco Systems Inc. * Portions created by Cisco Systems Inc. are * Copyright (C) Cisco Systems Inc. 2000, 2001. All Rights Reserved. * * Contributor(s): * Bill May wmay@cisco.com */#include "aac.h"#include <mp4util/mpeg4_audio_config.h>#include <mp4util/mpeg4_sdp.h>#include <mp4v2/mp4.h>#define DEBUG_SYNC 2const char *aaclib="aac";/* * Create CAACodec class */static codec_data_t *aac_codec_create (const char *compressor, int type, int profile, format_list_t *media_fmt, audio_info_t *audio, const uint8_t *userdata, uint32_t userdata_size, audio_vft_t *vft, void *ifptr){ aac_codec_t *aac; aac = (aac_codec_t *)malloc(sizeof(aac_codec_t)); memset(aac, 0, sizeof(aac_codec_t)); aac->m_vft = vft; aac->m_ifptr = ifptr; fmtp_parse_t *fmtp = NULL; // Start setting up FAAC stuff... aac->m_resync_with_header = 1; aac->m_record_sync_time = 1; aac->m_faad_inited = 0; aac->m_audio_inited = 0; aac->m_temp_buff = (uint8_t *)malloc(4096); // Use media_fmt to indicate that we're streaming. if (media_fmt != NULL) { // haven't checked for null buffer // This is not necessarilly right - it is, for the most part, but // we should be reading the fmtp statement, and looking at the config. // (like we do below in the userdata section... aac->m_freq = media_fmt->rtpmap->clock_rate; fmtp = parse_fmtp_for_mpeg4(media_fmt->fmt_param, vft->log_msg); if (fmtp != NULL) { userdata = fmtp->config_binary; userdata_size = fmtp->config_binary_len; } } else { if (audio != NULL) { aac->m_freq = audio->freq; } else { aac->m_freq = 44100; } } aac->m_chans = 2; // this may be wrong - the isma spec, Appendix A.1.1 of // Appendix H says the default is 1 channel... aac->m_output_frame_size = 1024; aac->m_object_type = AACMAIN; if (userdata != NULL || fmtp != NULL) { mpeg4_audio_config_t audio_config; decode_mpeg4_audio_config(userdata, userdata_size, &audio_config); aac->m_object_type = audio_config.audio_object_type; aac->m_freq = audio_config.frequency; aac->m_chans = audio_config.channels; if (audio_config.codec.aac.frame_len_1024 == 0) { aac->m_output_frame_size = 960; } } aa_message(LOG_INFO, aaclib,"AAC object type is %d", aac->m_object_type); aac->m_info = faacDecOpen(); faacDecConfiguration config; config.defObjectType = aac->m_object_type; config.defSampleRate = aac->m_freq; faacDecSetConfiguration(aac->m_info, &config); aac->m_msec_per_frame = aac->m_output_frame_size; aac->m_msec_per_frame *= M_LLU; aac->m_msec_per_frame /= aac->m_freq; // faad_init_bytestream(&m_info->ld, c_read_byte, c_bookmark, m_bytestream); aa_message(LOG_INFO, aaclib, "Setting freq to %d", aac->m_freq);#if DUMP_OUTPUT_TO_FILE aac->m_outfile = fopen("temp.raw", "w");#endif if (fmtp != NULL) { free_fmtp_parse(fmtp); } return (codec_data_t *)aac;}void aac_close (codec_data_t *ptr){ if (ptr == NULL) { printf("\nin aac close\n"); return; } aac_codec_t *aac = (aac_codec_t *)ptr; faacDecClose(aac->m_info); aac->m_info = NULL; if (aac->m_temp_buff) { free(aac->m_temp_buff); aac->m_temp_buff = NULL; }#if DUMP_OUTPUT_TO_FILE fclose(aac->m_outfile);#endif free(aac);}/* * Handle pause - basically re-init the codec */static void aac_do_pause (codec_data_t *ifptr){ aac_codec_t *aac = (aac_codec_t *)ifptr; aac->m_resync_with_header = 1; aac->m_record_sync_time = 1; aac->m_audio_inited = 0; aac->m_faad_inited = 0; if (aac->m_temp_buff == NULL) aac->m_temp_buff = (uint8_t *)malloc(4096);}/* * Decode task call for FAAC */static int aac_decode (codec_data_t *ptr, uint64_t ts, int from_rtp, int *sync_frame, uint8_t *buffer, uint32_t buflen, void *userdata){ aac_codec_t *aac = (aac_codec_t *)ptr; unsigned long bytes_consummed; int bits = -1; // struct timezone tz; if (aac->m_record_sync_time) { aac->m_current_frame = 0; aac->m_record_sync_time = 0; aac->m_current_time = ts; aac->m_last_rtp_ts = ts; } else { if (aac->m_last_rtp_ts == ts) { aac->m_current_time += aac->m_msec_per_frame; aac->m_current_frame++; } else { aac->m_last_rtp_ts = ts; aac->m_current_time = ts; aac->m_current_frame = 0; } // Note - here m_current_time should pretty much always be >= rtpts. // If we're not, we most likely want to stop and resync. We don't // need to keep decoding - just decode this frame and indicate we // need a resync... That should handle fast forwards... We need // someway to handle reverses - perhaps if we're more than .5 seconds // later... } if (aac->m_faad_inited == 0) { /* * If not initialized, do so. */ unsigned long freq, chans; faacDecInit(aac->m_info, (unsigned char *)buffer, &freq, &chans); aac->m_freq = freq; aac->m_chans = chans; aac->m_faad_inited = 1; } uint8_t *buff; /* * Get an audio buffer */ if (aac->m_audio_inited == 0) { buff = aac->m_temp_buff; } else { buff = aac->m_vft->audio_get_buffer(aac->m_ifptr); } if (buff == NULL) { //player_debug_message("Can't get buffer in aa"); return (0); } unsigned long samples; bytes_consummed = buflen; bits = faacDecDecode(aac->m_info, (unsigned char *)buffer, &bytes_consummed, (short *)buff, &samples); switch (bits) { case FAAD_OK_CHUPDATE: if (aac->m_audio_inited != 0) { int tempchans = faacDecGetProgConfig(aac->m_info, NULL); if (tempchans != aac->m_chans) { aa_message(LOG_NOTICE, aaclib, "chupdate - chans from data is %d", tempchans); } } // fall through... case FAAD_OK: if (aac->m_audio_inited == 0) { int tempchans = faacDecGetProgConfig(aac->m_info, NULL); if (tempchans == 0) { aac->m_resync_with_header = 1; aac->m_record_sync_time = 1; return bytes_consummed; } if (tempchans != aac->m_chans) { aa_message(LOG_NOTICE, aaclib, "chans from data is %d conf %d", tempchans, aac->m_chans); aac->m_chans = tempchans; } aac->m_vft->audio_configure(aac->m_ifptr, aac->m_freq, aac->m_chans, AUDIO_S16SYS, aac->m_output_frame_size); uint8_t *now = aac->m_vft->audio_get_buffer(aac->m_ifptr); if (now != NULL) { memcpy(now, buff, tempchans * aac->m_output_frame_size * sizeof(int16_t)); } aac->m_audio_inited = 1; } /* * good result - give it to audio sync class */#if DUMP_OUTPUT_TO_FILE fwrite(buff, aac->m_output_frame_size * 4, 1, aac->m_outfile);#endif aac->m_vft->audio_filled_buffer(aac->m_ifptr, aac->m_current_time, aac->m_resync_with_header); if (aac->m_resync_with_header == 1) { aac->m_resync_with_header = 0;#ifdef DEBUG_SYNC aa_message(LOG_DEBUG, aaclib, "Back to good at "LLU, aac->m_current_time);#endif } break; default: aa_message(LOG_ERR, aaclib, "Bits return is %d", bits); aac->m_resync_with_header = 1;#ifdef DEBUG_SYNC aa_message(LOG_ERR, aaclib, "Audio decode problem - at "LLU, aac->m_current_time);#endif break; } return (bytes_consummed);}static const char *aac_compressors[] = { "aac ", "mp4a", NULL};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){ 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); if (fmtp != NULL) free_fmtp_parse(fmtp); if (audio_object_type_is_aac(&audio_config) == 0) { 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;}AUDIO_CODEC_WITH_RAW_FILE_PLUGIN("aac", aac_codec_create, aac_do_pause, aac_decode, NULL, aac_close, aac_codec_check, aac_file_check, aac_file_next_frame, aac_file_used_for_frame, aac_raw_file_seek_to, aac_file_eof);/* end file aa.cpp */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -