Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1049a172 authored by Kenmochi, Chisato's avatar Kenmochi, Chisato Committed by android-build-merger
Browse files

Fix AAC bitrate computation and add missing parameters am: 8c1c1ee3

am: b6b96789

Change-Id: I232ee1e8b0f7b7b2b9a22ea60411497d3f392391
parents 1e725faa b6b96789
Loading
Loading
Loading
Loading
+43 −4
Original line number Diff line number Diff line
@@ -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?
@@ -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
+52 −26
Original line number Diff line number Diff line
@@ -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;
@@ -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?
@@ -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) {
@@ -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;
@@ -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) {
+8 −0
Original line number Diff line number Diff line
@@ -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.