/* * 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_audio_inited = 0; // 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; } } aac->m_info = faacDecOpen(); unsigned long srate; unsigned char chan; if ((userdata == NULL && fmtp == NULL) || (faacDecInit2(aac->m_info, (uint8_t *)userdata, userdata_size, &srate, &chan) < 0)) { if (fmtp != NULL) free_fmtp_parse(fmtp); return NULL; } mp4AudioSpecificConfig mp4ASC; aac->m_output_frame_size = 1024; if (AudioSpecificConfig((unsigned char *)userdata, userdata_size, &mp4ASC)) { if (mp4ASC.frameLengthFlag) { aac->m_output_frame_size = 960; } } aac->m_freq = srate; aac->m_chans = chan; aac->m_faad_inited = 1; 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; }
/* * Create CAACodec class */ static codec_data_t *aac_codec_create (const char *stream_type, 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 *= TO_U64(1000); 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; }
/* * 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. */ abort(); unsigned long freq; unsigned char chans; faacDecInit(aac->m_info, (unsigned char *)buffer, buflen, &freq, &chans); aac->m_freq = freq; aac->m_chans = chans; aac->m_faad_inited = 1; } uint8_t *buff; unsigned long samples; bytes_consummed = buflen; //aa_message(LOG_DEBUG, aaclib, "decoding %d bits", buflen * 8); faacDecFrameInfo frame_info; buff = (uint8_t *)faacDecDecode(aac->m_info, &frame_info, buffer, buflen); if (buff != NULL) { bytes_consummed = frame_info.bytesconsumed; #if 0 aa_message(LOG_DEBUG, aaclib, LLU" bytes %d samples %d", ts, bytes_consummed, frame_info.samples); #endif if (aac->m_audio_inited != 0) { int tempchans = frame_info.channels; if (tempchans != aac->m_chans) { aa_message(LOG_NOTICE, aaclib, "chupdate - chans from data is %d", tempchans); } } else { int tempchans = frame_info.channels; if (tempchans == 0) { aa_message(LOG_ERR, aaclib, "initializing aac, returned channels are 0"); aac->m_resync_with_header = 1; aac->m_record_sync_time = 1; return bytes_consummed; } aac->m_chans = tempchans; aac->m_freq = frame_info.samplerate; 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); 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 if (frame_info.samples != 0) { aac->m_vft->audio_load_buffer(aac->m_ifptr, buff, frame_info.samples * 2, aac->m_last_ts, 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 } } } else { aa_message(LOG_ERR, aaclib, "error return is %d", frame_info.error); aac->m_resync_with_header = 1; #ifdef DEBUG_SYNC aa_message(LOG_ERR, aaclib, "Audio decode problem - at "LLU, aac->m_current_time); #endif } aac->m_last_ts = aac->m_current_time; return (bytes_consummed); }
/* * Decode task call for FAAC */ static int aac_decode (codec_data_t *ptr, frame_timestamp_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; uint32_t freq_timestamp; freq_timestamp = ts->audio_freq_timestamp; if (ts->audio_freq != aac->m_freq) { freq_timestamp = convert_timescale(freq_timestamp, ts->audio_freq, aac->m_freq); } if (aac->m_record_sync_time) { aac->m_current_frame = 0; aac->m_record_sync_time = 0; aac->m_current_time = ts->msec_timestamp; aac->m_last_rtp_ts = ts->msec_timestamp; } else { if (aac->m_last_rtp_ts == ts->msec_timestamp) { aac->m_current_frame++; aac->m_current_time = aac->m_last_rtp_ts; aac->m_current_time += aac->m_output_frame_size * aac->m_current_frame * TO_U64(1000) / aac->m_freq; freq_timestamp += aac->m_output_frame_size * aac->m_current_frame; } else { aac->m_last_rtp_ts = ts->msec_timestamp; aac->m_current_time = ts->msec_timestamp; 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, freq_timestamp, aac->m_current_time); } if (buff == NULL) { //player_debug_message("Can't get buffer in aa"); return (0); } unsigned long samples; bytes_consummed = buflen; //aa_message(LOG_DEBUG, aaclib, "decoding %d bits", buflen * 8); 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_FMT_S16, aac->m_output_frame_size); uint8_t *now = aac->m_vft->audio_get_buffer(aac->m_ifptr, freq_timestamp, aac->m_current_time); 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); 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 "U64, 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 "U64, aac->m_current_time); #endif break; } return (bytes_consummed); }