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

Commit a85974b3 authored by Cheney Ni's avatar Cheney Ni
Browse files

A2DP: Based on the AAC parameters to calculate its encoder interval

When running AAC software encoder, the PCM data size per AAC frame is:
  1024 (sample counts per frame) * 2 (16 bits per sample) * 2 (stereo)
If we are using 44.1 kHz, the interval is about 23.22 ms. When using 48
kHz, it is about 21.33 ms. Here we determine the interval based on the
codec configuration and feeding parameters while updating the AAC
encoder.

Bug: 146399686
Test: There were AAC frames every 23 ms in BTSnoop
Change-Id: I8af7696917b007cb751a8991f21b344724b9ba94
parent 0428d33d
Loading
Loading
Loading
Loading
+29 −7
Original line number Diff line number Diff line
@@ -93,6 +93,8 @@ typedef struct {
  a2dp_aac_encoder_stats_t stats;
} tA2DP_AAC_ENCODER_CB;

static uint32_t a2dp_aac_encoder_interval_ms = A2DP_AAC_ENCODER_INTERVAL_MS;

static tA2DP_AAC_ENCODER_CB a2dp_aac_encoder_cb;

static void a2dp_aac_encoder_update(uint16_t peer_mtu,
@@ -218,7 +220,6 @@ static void a2dp_aac_encoder_update(uint16_t peer_mtu,
  LOG_DEBUG(LOG_TAG, "%s: sample_rate=%u bits_per_sample=%u channel_count=%u",
            __func__, p_feeding_params->sample_rate,
            p_feeding_params->bits_per_sample, p_feeding_params->channel_count);
  a2dp_aac_feeding_reset();

  // The codec parameters
  p_encoder_params->sample_rate =
@@ -451,6 +452,9 @@ static void a2dp_aac_encoder_update(uint16_t peer_mtu,
            __func__, p_encoder_params->frame_length,
            p_encoder_params->input_channels_n,
            p_encoder_params->max_encoded_buffer_bytes);

  // After encoder params ready, reset the feeding state and its interval.
  a2dp_aac_feeding_reset();
}

void a2dp_aac_encoder_cleanup(void) {
@@ -460,6 +464,23 @@ void a2dp_aac_encoder_cleanup(void) {
}

void a2dp_aac_feeding_reset(void) {
  auto frame_length = a2dp_aac_encoder_cb.aac_encoder_params.frame_length;
  auto sample_rate = a2dp_aac_encoder_cb.feeding_params.sample_rate;
  if (frame_length == 0 || sample_rate == 0) {
    LOG_WARN(LOG_TAG, "%s: AAC encoder is not configured", __func__);
    a2dp_aac_encoder_interval_ms = A2DP_AAC_ENCODER_INTERVAL_MS;
  } else {
    // PCM data size per AAC frame (bits)
    // = aac_encoder_params.frame_length * feeding_params.bits_per_sample
    //   * feeding_params.channel_count
    // = feeding_params.sample_rate * feeding_params.bits_per_sample
    //   * feeding_params.channel_count * (T_interval_ms / 1000);
    // Here we use the nearest integer not greater than the value.
    a2dp_aac_encoder_interval_ms = frame_length * 1000 / sample_rate;
    if (a2dp_aac_encoder_interval_ms < A2DP_AAC_ENCODER_INTERVAL_MS)
      a2dp_aac_encoder_interval_ms = A2DP_AAC_ENCODER_INTERVAL_MS;
  }

  /* By default, just clear the entire state */
  memset(&a2dp_aac_encoder_cb.aac_feeding_state, 0,
         sizeof(a2dp_aac_encoder_cb.aac_feeding_state));
@@ -468,11 +489,12 @@ void a2dp_aac_feeding_reset(void) {
      (a2dp_aac_encoder_cb.feeding_params.sample_rate *
       a2dp_aac_encoder_cb.feeding_params.bits_per_sample / 8 *
       a2dp_aac_encoder_cb.feeding_params.channel_count *
       A2DP_AAC_ENCODER_INTERVAL_MS) /
       a2dp_aac_encoder_interval_ms) /
      1000;

  LOG_DEBUG(LOG_TAG, "%s: PCM bytes per tick %u", __func__,
            a2dp_aac_encoder_cb.aac_feeding_state.bytes_per_tick);
  LOG_INFO(LOG_TAG, "%s: PCM bytes %u per tick %u ms", __func__,
           a2dp_aac_encoder_cb.aac_feeding_state.bytes_per_tick,
           a2dp_aac_encoder_interval_ms);
}

void a2dp_aac_feeding_flush(void) {
@@ -480,7 +502,7 @@ void a2dp_aac_feeding_flush(void) {
}

uint64_t a2dp_aac_get_encoder_interval_ms(void) {
  return A2DP_AAC_ENCODER_INTERVAL_MS;
  return a2dp_aac_encoder_interval_ms;
}

void a2dp_aac_send_frames(uint64_t timestamp_us) {
@@ -515,7 +537,7 @@ static void a2dp_aac_get_num_frame_iteration(uint8_t* num_of_iterations,
  LOG_VERBOSE(LOG_TAG, "%s: pcm_bytes_per_frame %u", __func__,
              pcm_bytes_per_frame);

  uint32_t us_this_tick = A2DP_AAC_ENCODER_INTERVAL_MS * 1000;
  uint32_t us_this_tick = a2dp_aac_encoder_interval_ms * 1000;
  uint64_t now_us = timestamp_us;
  if (a2dp_aac_encoder_cb.aac_feeding_state.last_frame_us != 0)
    us_this_tick =
@@ -524,7 +546,7 @@ static void a2dp_aac_get_num_frame_iteration(uint8_t* num_of_iterations,

  a2dp_aac_encoder_cb.aac_feeding_state.counter +=
      a2dp_aac_encoder_cb.aac_feeding_state.bytes_per_tick * us_this_tick /
      (A2DP_AAC_ENCODER_INTERVAL_MS * 1000);
      (a2dp_aac_encoder_interval_ms * 1000);

  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;