Loading system/stack/a2dp/a2dp_aac.cc +43 −4 Original line number Diff line number Diff line Loading @@ -497,6 +497,40 @@ int A2DP_GetBitRateAac(const uint8_t* p_codec_info) { return aac_cie.bitRate; } int A2DP_ComputeMaxBitRateAac(const uint8_t* p_codec_info, uint16_t mtu) { tA2DP_AAC_CIE aac_cie; // Check whether the codec info contains valid data tA2DP_STATUS a2dp_status = A2DP_ParseInfoAac(&aac_cie, p_codec_info, false); if (a2dp_status != A2DP_SUCCESS) { LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, a2dp_status); return -1; } int sampling_freq = A2DP_GetTrackSampleRateAac(p_codec_info); if (sampling_freq == -1) return -1; int pcm_channel_samples_per_frame = 0; switch (aac_cie.objectType) { case A2DP_AAC_OBJECT_TYPE_MPEG2_LC: case A2DP_AAC_OBJECT_TYPE_MPEG4_LC: pcm_channel_samples_per_frame = 1024; break; case A2DP_AAC_OBJECT_TYPE_MPEG4_LTP: case A2DP_AAC_OBJECT_TYPE_MPEG4_SCALABLE: // TODO: The MPEG documentation doesn't specify the value. break; default: break; } if (pcm_channel_samples_per_frame == 0) return -1; // See Section 3.2.1 Estimating Average Frame Size from // the aacEncoder.pdf document included with the AAC source code. return (8 * mtu * sampling_freq) / pcm_channel_samples_per_frame; } bool A2DP_GetPacketTimestampAac(const uint8_t* p_codec_info, const uint8_t* p_data, uint32_t* p_timestamp) { // TODO: Is this function really codec-specific? Loading Loading @@ -928,10 +962,15 @@ bool A2dpCodecConfigAac::setCodecConfig(const uint8_t* p_peer_codec_info, // Set the bit rate to the smaller of the local and peer bit rate // However, make sure the bit rate doesn't go beyond a certain threshold if (sink_info_cie.bitRate == 0) { // NOTE: Some devices report bitRate of zero - in that case use our bitRate result_config_cie.bitRate = a2dp_aac_caps.bitRate; } else { result_config_cie.bitRate = std::min(a2dp_aac_caps.bitRate, sink_info_cie.bitRate); result_config_cie.bitRate = std::max( result_config_cie.bitRate, static_cast<uint32_t>(A2DP_AAC_MIN_BITRATE)); } // // Select the sample frequency Loading system/stack/a2dp/a2dp_aac_encoder.cc +52 −26 Original line number Diff line number Diff line Loading @@ -187,7 +187,7 @@ static void a2dp_aac_encoder_update(uint16_t peer_mtu, &a2dp_aac_encoder_cb.aac_encoder_params; uint8_t codec_info[AVDT_CODEC_SIZE]; AACENC_ERROR aac_error; int aac_param_value; int aac_param_value, aac_sampling_freq, aac_bit_rate; *p_restart_input = false; *p_restart_output = false; Loading Loading @@ -277,20 +277,25 @@ static void a2dp_aac_encoder_update(uint16_t peer_mtu, return; // TODO: Return an error? } // Set the encoder's parameters: Bit Rate - MANDATORY aac_param_value = A2DP_GetBitRateAac(p_codec_info); if (aac_param_value == -1) { // Set the encoder's parameters: audioMuxVersion aac_param_value = 1; // audioMuxVersion = 1 aac_error = aacEncoder_SetParam(a2dp_aac_encoder_cb.aac_handle, AACENC_AUDIOMUXVER, aac_param_value); if (aac_error != AACENC_OK) { LOG_ERROR(LOG_TAG, "%s: Cannot set AAC parameter AACENC_BITRATE: " "invalid codec bit rate", __func__); "%s: Cannot set AAC parameter AACENC_AUDIOMUXVER to %d: " "AAC error 0x%x", __func__, aac_param_value, aac_error); return; // TODO: Return an error? } // Set the encoder's parameters: Signaling mode of the extension AOT aac_param_value = 1; // Signaling mode of the extension AOT = 1 aac_error = aacEncoder_SetParam(a2dp_aac_encoder_cb.aac_handle, AACENC_BITRATE, aac_param_value); AACENC_SIGNALING_MODE, aac_param_value); if (aac_error != AACENC_OK) { LOG_ERROR(LOG_TAG, "%s: Cannot set AAC parameter AACENC_BITRATE to %d: " "%s: Cannot set AAC parameter AACENC_SIGNALING_MODE to %d: " "AAC error 0x%x", __func__, aac_param_value, aac_error); return; // TODO: Return an error? Loading @@ -307,6 +312,44 @@ static void a2dp_aac_encoder_update(uint16_t peer_mtu, __func__, aac_param_value, aac_error); return; // TODO: Return an error? } aac_sampling_freq = aac_param_value; // Save for extra usage below // Set the encoder's parameters: Bit Rate - MANDATORY aac_param_value = A2DP_GetBitRateAac(p_codec_info); // Calculate the bit rate from MTU and sampling frequency aac_bit_rate = A2DP_ComputeMaxBitRateAac(p_codec_info, a2dp_aac_encoder_cb.TxAaMtuSize); aac_bit_rate = std::min(aac_param_value, aac_bit_rate); LOG_DEBUG(LOG_TAG, "%s: MTU = %d Sampling Frequency = %d Bit Rate = %d", __func__, a2dp_aac_encoder_cb.TxAaMtuSize, aac_sampling_freq, aac_bit_rate); if (aac_bit_rate == -1) { LOG_ERROR(LOG_TAG, "%s: Cannot set AAC parameter AACENC_BITRATE: " "invalid codec bit rate", __func__); return; // TODO: Return an error? } aac_error = aacEncoder_SetParam(a2dp_aac_encoder_cb.aac_handle, AACENC_BITRATE, aac_bit_rate); if (aac_error != AACENC_OK) { LOG_ERROR(LOG_TAG, "%s: Cannot set AAC parameter AACENC_BITRATE to %d: " "AAC error 0x%x", __func__, aac_bit_rate, aac_error); return; // TODO: Return an error? } // Set the encoder's parameters: PEAK Bit Rate aac_error = aacEncoder_SetParam(a2dp_aac_encoder_cb.aac_handle, AACENC_PEAK_BITRATE, aac_bit_rate); if (aac_error != AACENC_OK) { LOG_ERROR(LOG_TAG, "%s: Cannot set AAC parameter AACENC_PEAK_BITRATE to %d: " "AAC error 0x%x", __func__, aac_bit_rate, aac_error); return; // TODO: Return an error? } // Set the encoder's parameters: Channel Mode - MANDATORY if (A2DP_GetTrackChannelCountAac(p_codec_info) == 1) { Loading Loading @@ -470,7 +513,6 @@ static void a2dp_aac_get_num_frame_iteration(uint8_t* num_of_iterations, a2dp_aac_encoder_cb.aac_feeding_state.bytes_per_tick * us_this_tick / (A2DP_AAC_ENCODER_INTERVAL_MS * 1000); #if 1 result = a2dp_aac_encoder_cb.aac_feeding_state.counter / pcm_bytes_per_frame; a2dp_aac_encoder_cb.aac_feeding_state.counter -= result * pcm_bytes_per_frame; nof = result; Loading @@ -480,22 +522,6 @@ static void a2dp_aac_get_num_frame_iteration(uint8_t* num_of_iterations, *num_of_frames = nof; *num_of_iterations = noi; #else pcm_bytes_per_frame = 800; result = a2dp_aac_encoder_cb.aac_feeding_state.counter / pcm_bytes_per_frame; nof = result; noi = 1; a2dp_aac_encoder_cb.aac_feeding_state.counter -= result * pcm_bytes_per_frame; LOG_VERBOSE(LOG_TAG, "%s: effective num of frames %u, iterations %u", __func__, nof, noi); *num_of_frames = nof; *num_of_iterations = noi; #endif } static void a2dp_aac_encode_frames(uint8_t nb_frame) { Loading system/stack/include/a2dp_aac.h +8 −0 Original line number Diff line number Diff line Loading @@ -174,6 +174,14 @@ int A2DP_GetVariableBitRateSupportAac(const uint8_t* p_codec_info); // contains invalid codec information. int A2DP_GetBitRateAac(const uint8_t* p_codec_info); // Computes the maximum bit rate for the A2DP AAC codec based on the MTU. // The actual value is codec-specific - for AAC it is in bits per second. // |p_codec_info| is a pointer to the AAC codec_info to decode. // |mtu| is the MTU to use for the computation. // Returns the maximum bit rate on success, or -1 if |p_codec_info| // contains invalid codec information. int A2DP_ComputeMaxBitRateAac(const uint8_t* p_codec_info, uint16_t mtu); // Gets the A2DP AAC audio data timestamp from an audio packet. // |p_codec_info| contains the codec information. // |p_data| contains the audio data. Loading Loading
system/stack/a2dp/a2dp_aac.cc +43 −4 Original line number Diff line number Diff line Loading @@ -497,6 +497,40 @@ int A2DP_GetBitRateAac(const uint8_t* p_codec_info) { return aac_cie.bitRate; } int A2DP_ComputeMaxBitRateAac(const uint8_t* p_codec_info, uint16_t mtu) { tA2DP_AAC_CIE aac_cie; // Check whether the codec info contains valid data tA2DP_STATUS a2dp_status = A2DP_ParseInfoAac(&aac_cie, p_codec_info, false); if (a2dp_status != A2DP_SUCCESS) { LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__, a2dp_status); return -1; } int sampling_freq = A2DP_GetTrackSampleRateAac(p_codec_info); if (sampling_freq == -1) return -1; int pcm_channel_samples_per_frame = 0; switch (aac_cie.objectType) { case A2DP_AAC_OBJECT_TYPE_MPEG2_LC: case A2DP_AAC_OBJECT_TYPE_MPEG4_LC: pcm_channel_samples_per_frame = 1024; break; case A2DP_AAC_OBJECT_TYPE_MPEG4_LTP: case A2DP_AAC_OBJECT_TYPE_MPEG4_SCALABLE: // TODO: The MPEG documentation doesn't specify the value. break; default: break; } if (pcm_channel_samples_per_frame == 0) return -1; // See Section 3.2.1 Estimating Average Frame Size from // the aacEncoder.pdf document included with the AAC source code. return (8 * mtu * sampling_freq) / pcm_channel_samples_per_frame; } bool A2DP_GetPacketTimestampAac(const uint8_t* p_codec_info, const uint8_t* p_data, uint32_t* p_timestamp) { // TODO: Is this function really codec-specific? Loading Loading @@ -928,10 +962,15 @@ bool A2dpCodecConfigAac::setCodecConfig(const uint8_t* p_peer_codec_info, // Set the bit rate to the smaller of the local and peer bit rate // However, make sure the bit rate doesn't go beyond a certain threshold if (sink_info_cie.bitRate == 0) { // NOTE: Some devices report bitRate of zero - in that case use our bitRate result_config_cie.bitRate = a2dp_aac_caps.bitRate; } else { result_config_cie.bitRate = std::min(a2dp_aac_caps.bitRate, sink_info_cie.bitRate); result_config_cie.bitRate = std::max( result_config_cie.bitRate, static_cast<uint32_t>(A2DP_AAC_MIN_BITRATE)); } // // Select the sample frequency Loading
system/stack/a2dp/a2dp_aac_encoder.cc +52 −26 Original line number Diff line number Diff line Loading @@ -187,7 +187,7 @@ static void a2dp_aac_encoder_update(uint16_t peer_mtu, &a2dp_aac_encoder_cb.aac_encoder_params; uint8_t codec_info[AVDT_CODEC_SIZE]; AACENC_ERROR aac_error; int aac_param_value; int aac_param_value, aac_sampling_freq, aac_bit_rate; *p_restart_input = false; *p_restart_output = false; Loading Loading @@ -277,20 +277,25 @@ static void a2dp_aac_encoder_update(uint16_t peer_mtu, return; // TODO: Return an error? } // Set the encoder's parameters: Bit Rate - MANDATORY aac_param_value = A2DP_GetBitRateAac(p_codec_info); if (aac_param_value == -1) { // Set the encoder's parameters: audioMuxVersion aac_param_value = 1; // audioMuxVersion = 1 aac_error = aacEncoder_SetParam(a2dp_aac_encoder_cb.aac_handle, AACENC_AUDIOMUXVER, aac_param_value); if (aac_error != AACENC_OK) { LOG_ERROR(LOG_TAG, "%s: Cannot set AAC parameter AACENC_BITRATE: " "invalid codec bit rate", __func__); "%s: Cannot set AAC parameter AACENC_AUDIOMUXVER to %d: " "AAC error 0x%x", __func__, aac_param_value, aac_error); return; // TODO: Return an error? } // Set the encoder's parameters: Signaling mode of the extension AOT aac_param_value = 1; // Signaling mode of the extension AOT = 1 aac_error = aacEncoder_SetParam(a2dp_aac_encoder_cb.aac_handle, AACENC_BITRATE, aac_param_value); AACENC_SIGNALING_MODE, aac_param_value); if (aac_error != AACENC_OK) { LOG_ERROR(LOG_TAG, "%s: Cannot set AAC parameter AACENC_BITRATE to %d: " "%s: Cannot set AAC parameter AACENC_SIGNALING_MODE to %d: " "AAC error 0x%x", __func__, aac_param_value, aac_error); return; // TODO: Return an error? Loading @@ -307,6 +312,44 @@ static void a2dp_aac_encoder_update(uint16_t peer_mtu, __func__, aac_param_value, aac_error); return; // TODO: Return an error? } aac_sampling_freq = aac_param_value; // Save for extra usage below // Set the encoder's parameters: Bit Rate - MANDATORY aac_param_value = A2DP_GetBitRateAac(p_codec_info); // Calculate the bit rate from MTU and sampling frequency aac_bit_rate = A2DP_ComputeMaxBitRateAac(p_codec_info, a2dp_aac_encoder_cb.TxAaMtuSize); aac_bit_rate = std::min(aac_param_value, aac_bit_rate); LOG_DEBUG(LOG_TAG, "%s: MTU = %d Sampling Frequency = %d Bit Rate = %d", __func__, a2dp_aac_encoder_cb.TxAaMtuSize, aac_sampling_freq, aac_bit_rate); if (aac_bit_rate == -1) { LOG_ERROR(LOG_TAG, "%s: Cannot set AAC parameter AACENC_BITRATE: " "invalid codec bit rate", __func__); return; // TODO: Return an error? } aac_error = aacEncoder_SetParam(a2dp_aac_encoder_cb.aac_handle, AACENC_BITRATE, aac_bit_rate); if (aac_error != AACENC_OK) { LOG_ERROR(LOG_TAG, "%s: Cannot set AAC parameter AACENC_BITRATE to %d: " "AAC error 0x%x", __func__, aac_bit_rate, aac_error); return; // TODO: Return an error? } // Set the encoder's parameters: PEAK Bit Rate aac_error = aacEncoder_SetParam(a2dp_aac_encoder_cb.aac_handle, AACENC_PEAK_BITRATE, aac_bit_rate); if (aac_error != AACENC_OK) { LOG_ERROR(LOG_TAG, "%s: Cannot set AAC parameter AACENC_PEAK_BITRATE to %d: " "AAC error 0x%x", __func__, aac_bit_rate, aac_error); return; // TODO: Return an error? } // Set the encoder's parameters: Channel Mode - MANDATORY if (A2DP_GetTrackChannelCountAac(p_codec_info) == 1) { Loading Loading @@ -470,7 +513,6 @@ static void a2dp_aac_get_num_frame_iteration(uint8_t* num_of_iterations, a2dp_aac_encoder_cb.aac_feeding_state.bytes_per_tick * us_this_tick / (A2DP_AAC_ENCODER_INTERVAL_MS * 1000); #if 1 result = a2dp_aac_encoder_cb.aac_feeding_state.counter / pcm_bytes_per_frame; a2dp_aac_encoder_cb.aac_feeding_state.counter -= result * pcm_bytes_per_frame; nof = result; Loading @@ -480,22 +522,6 @@ static void a2dp_aac_get_num_frame_iteration(uint8_t* num_of_iterations, *num_of_frames = nof; *num_of_iterations = noi; #else pcm_bytes_per_frame = 800; result = a2dp_aac_encoder_cb.aac_feeding_state.counter / pcm_bytes_per_frame; nof = result; noi = 1; a2dp_aac_encoder_cb.aac_feeding_state.counter -= result * pcm_bytes_per_frame; LOG_VERBOSE(LOG_TAG, "%s: effective num of frames %u, iterations %u", __func__, nof, noi); *num_of_frames = nof; *num_of_iterations = noi; #endif } static void a2dp_aac_encode_frames(uint8_t nb_frame) { Loading
system/stack/include/a2dp_aac.h +8 −0 Original line number Diff line number Diff line Loading @@ -174,6 +174,14 @@ int A2DP_GetVariableBitRateSupportAac(const uint8_t* p_codec_info); // contains invalid codec information. int A2DP_GetBitRateAac(const uint8_t* p_codec_info); // Computes the maximum bit rate for the A2DP AAC codec based on the MTU. // The actual value is codec-specific - for AAC it is in bits per second. // |p_codec_info| is a pointer to the AAC codec_info to decode. // |mtu| is the MTU to use for the computation. // Returns the maximum bit rate on success, or -1 if |p_codec_info| // contains invalid codec information. int A2DP_ComputeMaxBitRateAac(const uint8_t* p_codec_info, uint16_t mtu); // Gets the A2DP AAC audio data timestamp from an audio packet. // |p_codec_info| contains the codec information. // |p_data| contains the audio data. Loading