Fix AAC bitrate computation and add missing parameters

* Compute the AAC codec bitrate based on the MTU and the AAC
  object type such that the AAC frames are not fragmented.
  The spec recommendation is to avoid fragmentation, and
  some sink devices cannot process fragmented frames.

* Setup/assign AACENC_PEAK_BITRATE as the peak bitrate to
  make sure we never go over the MTU frame size.

* Add missing AAC parameter setup for AACENC_AUDIOMUXVER
  and AACENC_SIGNALING_MODE

* Add a fix for selecting the bitrate if the sink device reports
  capability with zero bitrate - for such devices we negotiate
  our bitrate. For the actual AAC codec bitrate we still compute
  it based on the MTU and the AAC object type.

Test: Tested with numerous AAC sink devices
Bug: 34953385
Change-Id: I9ca6353b0e1ee107f1242803de4e82d568a3394b
(cherry picked from commit 3b8f12614fd2a97332104230cb98a4c13bda93c7)
diff --git a/stack/a2dp/a2dp_aac.cc b/stack/a2dp/a2dp_aac.cc
index 6681008..d06ac79 100644
--- a/stack/a2dp/a2dp_aac.cc
+++ b/stack/a2dp/a2dp_aac.cc
@@ -497,6 +497,40 @@
   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?
@@ -928,10 +962,15 @@
 
   // 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
-  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));
+  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
diff --git a/stack/a2dp/a2dp_aac_encoder.cc b/stack/a2dp/a2dp_aac_encoder.cc
index cdf5156..62d7d78 100644
--- a/stack/a2dp/a2dp_aac_encoder.cc
+++ b/stack/a2dp/a2dp_aac_encoder.cc
@@ -187,7 +187,7 @@
       &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;
@@ -277,20 +277,25 @@
     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) {
-    LOG_ERROR(LOG_TAG,
-              "%s: Cannot set AAC parameter AACENC_BITRATE: "
-              "invalid codec bit rate",
-              __func__);
-    return;  // TODO: Return an error?
-  }
+  // Set the encoder's parameters: audioMuxVersion
+  aac_param_value = 1;  // audioMuxVersion = 1
   aac_error = aacEncoder_SetParam(a2dp_aac_encoder_cb.aac_handle,
-                                  AACENC_BITRATE, aac_param_value);
+                                  AACENC_AUDIOMUXVER, 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_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_SIGNALING_MODE, aac_param_value);
+  if (aac_error != AACENC_OK) {
+    LOG_ERROR(LOG_TAG,
+              "%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?
@@ -307,6 +312,44 @@
               __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) {
@@ -470,7 +513,6 @@
       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;
@@ -480,22 +522,6 @@
 
   *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) {
diff --git a/stack/include/a2dp_aac.h b/stack/include/a2dp_aac.h
index b9a6b69..ba0a80d 100644
--- a/stack/include/a2dp_aac.h
+++ b/stack/include/a2dp_aac.h
@@ -174,6 +174,14 @@
 // 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.