OSDN Git Service

A2DP: AAC encoding counter errata
authorCheney Ni <cheneyni@google.com>
Thu, 13 Feb 2020 14:25:51 +0000 (22:25 +0800)
committerCheney Ni <cheneyni@google.com>
Tue, 10 Mar 2020 03:54:55 +0000 (11:54 +0800)
When the encoder interval is 23 milliseconds per tick for {44.1 kHz /
16 bits per sample / Stereo}, 3 microseconds shift every tick would
cause one AAC frame mismatched after 180 seconds. Here try to adjust the
timeline to increase the accuracy by following methods:

1. add the remainder back to the timeline when converting the time
   period to data size.
2. change the timestamp to be presented by values in 1/10 microseconds.

Bug: 149546181
Test: manually
Change-Id: I16742042ba64a9355c39c0248be9208567312a9f

stack/a2dp/a2dp_aac_encoder.cc

index 20dfb9f..fd73db3 100644 (file)
@@ -19,6 +19,7 @@
 #include "a2dp_aac_encoder.h"
 
 #include <inttypes.h>
+#include <math.h>
 #include <stdio.h>
 #include <string.h>
 
@@ -56,8 +57,8 @@ typedef struct {
 
 typedef struct {
   uint32_t counter;
-  uint32_t bytes_per_tick; /* pcm bytes read each media task tick */
-  uint64_t last_frame_us;
+  uint32_t bytes_per_tick;              // pcm bytes read each media task tick
+  uint64_t last_frame_timestamp_100ns;  // values in 1/10 microseconds
 } tA2DP_AAC_FEEDING_STATE;
 
 typedef struct {
@@ -533,16 +534,29 @@ static void a2dp_aac_get_num_frame_iteration(uint8_t* num_of_iterations,
       a2dp_aac_encoder_cb.feeding_params.bits_per_sample / 8;
   LOG_VERBOSE("%s: pcm_bytes_per_frame %u", __func__, pcm_bytes_per_frame);
 
-  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 =
-        (now_us - a2dp_aac_encoder_cb.aac_feeding_state.last_frame_us);
-  a2dp_aac_encoder_cb.aac_feeding_state.last_frame_us = now_us;
-
-  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);
+  uint32_t hecto_ns_this_tick = a2dp_aac_encoder_interval_ms * 10000;
+  uint64_t* last_100ns =
+      &a2dp_aac_encoder_cb.aac_feeding_state.last_frame_timestamp_100ns;
+  uint64_t now_100ns = timestamp_us * 10;
+  if (*last_100ns != 0) {
+    hecto_ns_this_tick = (now_100ns - *last_100ns);
+  }
+  *last_100ns = now_100ns;
+
+  uint32_t bytes_this_tick =
+      a2dp_aac_encoder_cb.aac_feeding_state.bytes_per_tick *
+      hecto_ns_this_tick / (a2dp_aac_encoder_interval_ms * 10000);
+  a2dp_aac_encoder_cb.aac_feeding_state.counter += bytes_this_tick;
+  // Without this erratum, there was a three microseocnd shift per tick which
+  // would cause one frame mismatched after every 180 seconds
+  uint32_t erratum_100ns =
+      ceil(1.0f * bytes_this_tick * a2dp_aac_encoder_interval_ms * 10000 /
+           a2dp_aac_encoder_cb.aac_feeding_state.bytes_per_tick);
+  if (erratum_100ns < hecto_ns_this_tick) {
+    LOG_VERBOSE("%s: hecto_ns_this_tick=%d, bytes=%d, erratum_100ns=%d",
+                __func__, hecto_ns_this_tick, bytes_this_tick, erratum_100ns);
+    *last_100ns -= hecto_ns_this_tick - erratum_100ns;
+  }
 
   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;