OSDN Git Service

Add a mechanism to dump A2DP codec stats
authorPavlin Radoslavov <pavlin@google.com>
Wed, 12 Oct 2016 16:45:30 +0000 (09:45 -0700)
committerPavlin Radoslavov <pavlin@google.com>
Fri, 14 Oct 2016 03:53:14 +0000 (03:53 +0000)
Also, added-back A2DP SBC frames related stats:
  - media_read_total_limited_frames
  - media_read_max_limited_frames
  - media_read_limited_count
  - media_read_total_expected_frames
  - media_read_max_expected_frames
  - media_read_expected_count

A2DP SBC State:
  Frames expected (total/max/ave)                         : 9131 / 8 / 6
  Frames limited (total/max/ave)                          : 0 / 0 / 0
  Counts (expected/limited)                               : 1322 / 0

Bug: 30958229
Test: manual
Change-Id: Id6ddea5eb9d39cf03cae84c79968081d56984e91

btif/src/btif_a2dp_source.cc
stack/a2dp/a2d_sbc.c
stack/a2dp/a2d_sbc_encoder.c
stack/include/a2d_api.h
stack/include/a2d_sbc_encoder.h

index 2e90187..bc87773 100644 (file)
@@ -940,6 +940,12 @@ void btif_a2dp_source_debug_dump(int fd)
             (unsigned long long)dequeue_stats->max_premature_scheduling_delta_us / 1000,
             (unsigned long long)ave_time_us / 1000);
 
+
+    //
+    // Codec-specific stats
+    //
+    if (btif_a2dp_source_cb.encoder_interface != NULL)
+        btif_a2dp_source_cb.encoder_interface->debug_codec_dump(fd);
 }
 
 void btif_a2dp_source_update_metrics(void)
index ed672d1..1b190f5 100644 (file)
@@ -98,7 +98,8 @@ static const tA2D_ENCODER_INTERFACE a2d_encoder_interface_sbc = {
     a2d_sbc_feeding_reset,
     a2d_sbc_feeding_flush,
     a2d_sbc_get_encoder_interval_ms,
-    a2d_sbc_send_frames
+    a2d_sbc_send_frames,
+    a2d_sbc_debug_codec_dump
 };
 
 static tA2D_STATUS A2D_CodecInfoMatchesCapabilitySbc(
index fcd2859..88d0449 100644 (file)
@@ -20,6 +20,7 @@
 #define LOG_TAG "a2d_sbc_encoder"
 
 #include <assert.h>
+#include <stdio.h>
 
 #include "bt_target.h"
 #include "bt_common.h"
 #include "avdt_api.h"
 #include "embdrv/sbc/encoder/include/sbc_encoder.h"
 #include "osi/include/log.h"
+#include "osi/include/time.h"
+
+#define STATS_UPDATE_MAX(current_value_storage, new_value) \
+do { \
+    if ((new_value) > (current_value_storage)) \
+        (current_value_storage) = (new_value); \
+} while (0)
 
 /* Buffer pool */
 #define A2D_SBC_BUFFER_SIZE  BT_DEFAULT_BUFFER_SIZE
@@ -79,6 +87,18 @@ typedef struct {
 } tA2D_FEEDING_STATE;
 
 typedef struct {
+    uint64_t session_start_us;
+
+    size_t media_read_total_expected_frames;
+    size_t media_read_max_expected_frames;
+    size_t media_read_expected_count;
+
+    size_t media_read_total_limited_frames;
+    size_t media_read_max_limited_frames;
+    size_t media_read_limited_count;
+} a2d_sbc_encoder_stats_t;
+
+typedef struct {
     a2d_source_read_callback_t read_callback;
     a2d_source_enqueue_callback_t enqueue_callback;
     uint16_t TxAaMtuSize;
@@ -89,6 +109,8 @@ typedef struct {
     SBC_ENC_PARAMS sbc_encoder_params;
     tA2D_FEEDING_PARAMS feeding_params;
     tA2D_FEEDING_STATE feeding_state;
+
+    a2d_sbc_encoder_stats_t stats;
 } tA2D_SBC_ENCODER_CB;
 
 static tA2D_SBC_ENCODER_CB a2d_sbc_encoder_cb;
@@ -111,6 +133,8 @@ void a2d_sbc_encoder_init(bool is_peer_edr, bool peer_supports_3mbps,
 
     memset(&a2d_sbc_encoder_cb, 0, sizeof(a2d_sbc_encoder_cb));
 
+    a2d_sbc_encoder_cb.stats.session_start_us = time_get_os_boottime_us();
+
     a2d_sbc_encoder_cb.read_callback = read_callback;
     a2d_sbc_encoder_cb.enqueue_callback = enqueue_callback;
     a2d_sbc_encoder_cb.is_peer_edr = is_peer_edr;
@@ -457,11 +481,25 @@ static void a2d_sbc_get_num_frame_iteration(uint8_t *num_of_iterations,
         us_this_tick / (A2D_SBC_ENCODER_INTERVAL_MS * 1000);
 
     /* Calculate the number of frames pending for this media tick */
-    projected_nof = a2d_sbc_encoder_cb.feeding_state.counter / pcm_bytes_per_frame;
+    projected_nof =
+        a2d_sbc_encoder_cb.feeding_state.counter / pcm_bytes_per_frame;
+    // Update the stats
+    STATS_UPDATE_MAX(a2d_sbc_encoder_cb.stats.media_read_max_expected_frames,
+                     projected_nof);
+    a2d_sbc_encoder_cb.stats.media_read_total_expected_frames += projected_nof;
+    a2d_sbc_encoder_cb.stats.media_read_expected_count++;
 
     if (projected_nof > MAX_PCM_FRAME_NUM_PER_TICK) {
         LOG_WARN(LOG_TAG, "%s: limiting frames to be sent from %d to %d",
                  __func__, projected_nof, MAX_PCM_FRAME_NUM_PER_TICK);
+
+        // Update the stats
+        size_t delta = projected_nof - MAX_PCM_FRAME_NUM_PER_TICK;
+        a2d_sbc_encoder_cb.stats.media_read_limited_count++;
+        a2d_sbc_encoder_cb.stats.media_read_total_limited_frames += delta;
+        STATS_UPDATE_MAX(a2d_sbc_encoder_cb.stats.media_read_max_limited_frames,
+                         delta);
+
         projected_nof = MAX_PCM_FRAME_NUM_PER_TICK;
     }
 
@@ -878,3 +916,35 @@ static uint32_t a2d_sbc_frame_length(void)
                 __func__, frame_len);
     return frame_len;
 }
+
+void a2d_sbc_debug_codec_dump(int fd)
+{
+    a2d_sbc_encoder_stats_t *stats = &a2d_sbc_encoder_cb.stats;
+    size_t ave_size;
+
+    dprintf(fd, "\nA2DP SBC State:\n");
+
+    ave_size = 0;
+    if (stats->media_read_expected_count != 0) {
+        ave_size = stats->media_read_total_expected_frames /
+            stats->media_read_expected_count;
+    }
+    dprintf(fd, "  Frames expected (total/max/ave)                         : %zu / %zu / %zu\n",
+            stats->media_read_total_expected_frames,
+            stats->media_read_max_expected_frames,
+            ave_size);
+
+    ave_size = 0;
+    if (stats->media_read_limited_count != 0) {
+        ave_size = stats->media_read_total_limited_frames /
+            stats->media_read_limited_count;
+    }
+    dprintf(fd, "  Frames limited (total/max/ave)                          : %zu / %zu / %zu\n",
+            stats->media_read_total_limited_frames,
+            stats->media_read_max_limited_frames,
+            ave_size);
+
+    dprintf(fd, "  Counts (expected/limited)                               : %zu / %zu\n",
+            stats->media_read_expected_count,
+            stats->media_read_limited_count);
+}
index f70b169..9942d4d 100644 (file)
@@ -229,6 +229,11 @@ typedef struct {
     // Prepare and send A2DP encoded frames.
     // |timestamp_us| is the current timestamp (in microseconds).
     void (*send_frames)(uint64_t timestamp_us);
+
+    // Dump codec-related statistics.
+    // |fd| is the file descriptor to use to dump the statistics information
+    // in user-friendly test format.
+    void (*debug_codec_dump)(int fd);
 } tA2D_ENCODER_INTERFACE;
 
 /*****************************************************************************
index 5a973d9..e9fcf1e 100644 (file)
@@ -65,6 +65,11 @@ period_ms_t a2d_sbc_get_encoder_interval_ms(void);
 // |timestamp_us| is the current timestamp (in microseconds).
 void a2d_sbc_send_frames(uint64_t timestamp_us);
 
+// Dump SBC codec-related statistics.
+// |fd| is the file descriptor to use to dump the statistics information
+// in user-friendly test format.
+void a2d_sbc_debug_codec_dump(int fd);
+
 #ifdef __cplusplus
 }
 #endif