OSDN Git Service

Add missing free after read device info
[android-x86/system-media.git] / alsa_utils / alsa_device_profile.c
index 3ee0f4b..1ab0d80 100644 (file)
@@ -32,7 +32,7 @@
 
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
 
-#define PERIOD_SIZE_US (5 * 1000)
+#define PERIOD_DURATION_US (5 * 1000)
 
 #define DEFAULT_PERIOD_SIZE 1024
 
@@ -113,7 +113,7 @@ unsigned profile_calc_min_period_size(alsa_device_profile* profile, unsigned sam
     if (profile == NULL) {
         return DEFAULT_PERIOD_SIZE;
     } else {
-        unsigned period_us = property_get_int32("ro.audio.usb.period_us", PERIOD_SIZE_US);
+        unsigned period_us = property_get_int32("ro.audio.usb.period_us", PERIOD_DURATION_US);
         unsigned num_sample_frames = ((uint64_t)sample_rate * period_us) / 1000000;
 
         if (num_sample_frames < profile->min_period_size) {
@@ -192,6 +192,21 @@ unsigned profile_get_default_channel_count(alsa_device_profile* profile)
     return profile_is_valid(profile) ? profile->channel_counts[0] : DEFAULT_CHANNEL_COUNT;
 }
 
+unsigned profile_get_closest_channel_count(alsa_device_profile* profile, unsigned count)
+{
+    if (profile_is_valid(profile)) {
+        if (count < profile->min_channel_count) {
+            return profile->min_channel_count;
+        } else if (count > profile->max_channel_count) {
+            return profile->max_channel_count;
+        } else {
+            return count;
+        }
+    } else {
+        return 0;
+    }
+}
+
 bool profile_is_channel_count_valid(alsa_device_profile* profile, unsigned count)
 {
     if (profile_is_initialized(profile)) {
@@ -334,7 +349,21 @@ static int read_alsa_device_config(alsa_device_profile * profile, struct pcm_con
 #endif
 
     config->channels = pcm_params_get_min(alsa_hw_params, PCM_PARAM_CHANNELS);
+    // For output devices, let's make sure we choose at least stereo
+    // (assuming the device supports it).
+    if (profile->direction == PCM_OUT &&
+        config->channels < 2 && pcm_params_get_max(alsa_hw_params, PCM_PARAM_CHANNELS) >= 2) {
+        config->channels = 2;
+    }
     config->rate = pcm_params_get_min(alsa_hw_params, PCM_PARAM_RATE);
+    // Prefer 48K or 44.1K
+    if (config->rate < 48000 &&
+        pcm_params_get_max(alsa_hw_params, PCM_PARAM_RATE) >= 48000) {
+        config->rate = 48000;
+    } else if (config->rate < 44100 &&
+               pcm_params_get_max(alsa_hw_params, PCM_PARAM_RATE) >= 44100) {
+        config->rate = 44100;
+    }
     config->period_size = profile_calc_min_period_size(profile, config->rate);
     config->period_count = pcm_params_get_min(alsa_hw_params, PCM_PARAM_PERIODS);
     config->format = get_pcm_format_for_mask(pcm_params_get_mask(alsa_hw_params, PCM_PARAM_FORMAT));
@@ -386,6 +415,7 @@ bool profile_read_device_info(alsa_device_profile* profile)
 
     profile->is_valid = true;
 
+    pcm_params_free(alsa_hw_params);
     return true;
 }
 
@@ -552,3 +582,59 @@ char * profile_get_channel_count_strs(alsa_device_profile* profile)
 
     return strdup(buffer);
 }
+
+void profile_dump(const alsa_device_profile* profile, int fd)
+{
+    if (profile == NULL) {
+        dprintf(fd, "  %s\n", "No USB Profile");
+        return; /* bail early */
+    }
+
+    if (!profile->is_valid) {
+        dprintf(fd, "  Profile is INVALID");
+    }
+
+    /* card/device/direction */
+    dprintf(fd, "  card:%d, device:%d - %s\n",
+                profile->card, profile->device, profile->direction == PCM_OUT ? "OUT" : "IN");
+
+    /* formats */
+    dprintf(fd, "  Formats: ");
+    for (int fmtIndex = 0;
+          profile->formats[fmtIndex] != PCM_FORMAT_INVALID && fmtIndex < MAX_PROFILE_FORMATS;
+          fmtIndex++) {
+        dprintf(fd, "%d ", profile->formats[fmtIndex]);
+    }
+    dprintf(fd, "\n");
+
+    /* sample rates */
+    dprintf(fd, "  Rates: ");
+    for (int rateIndex = 0;
+          profile->sample_rates[rateIndex] != 0 && rateIndex < MAX_PROFILE_SAMPLE_RATES;
+          rateIndex++) {
+        dprintf(fd, "%u ", profile->sample_rates[rateIndex]);
+    }
+    dprintf(fd, "\n");
+
+    // channel counts
+    dprintf(fd, "  Channel Counts: ");
+    for (int cntIndex = 0;
+          profile->channel_counts[cntIndex] != 0 && cntIndex < MAX_PROFILE_CHANNEL_COUNTS;
+          cntIndex++) {
+        dprintf(fd, "%u ", profile->channel_counts[cntIndex]);
+    }
+    dprintf(fd, "\n");
+
+    dprintf(fd, "  min/max period size [%u : %u]\n",
+            profile->min_period_size,profile-> max_period_size);
+    dprintf(fd, "  min/max channel count [%u : %u]\n",
+            profile->min_channel_count, profile->max_channel_count);
+
+    // struct pcm_config default_config;
+    dprintf(fd, "  Default Config:\n");
+    dprintf(fd, "    channels: %d\n", profile->default_config.channels);
+    dprintf(fd, "    rate: %d\n", profile->default_config.rate);
+    dprintf(fd, "    period_size: %d\n", profile->default_config.period_size);
+    dprintf(fd, "    period_count: %d\n", profile->default_config.period_count);
+    dprintf(fd, "    format: %d\n", profile->default_config.format);
+}