summaryrefslogtreecommitdiff
path: root/cras/src/server/cras_iodev_list.c
diff options
context:
space:
mode:
authorPin-chih Lin <johnylin@google.com>2020-07-29 15:46:47 +0800
committerCommit Bot <commit-bot@chromium.org>2020-08-10 08:31:24 +0000
commit592625514061ca68630566b86dacbe47cd027a93 (patch)
treea5e49fc349925fe2b5ce5876218de23d24b1f971 /cras/src/server/cras_iodev_list.c
parent3418709c9ee544524a130228a6c4bba41089dcc4 (diff)
downloadadhd-592625514061ca68630566b86dacbe47cd027a93.tar.gz
CRAS: Re-open iodev for higher channel count per request
Re-open the device with the format of the attached stream if it has higher channel count than the current format of the device. Fallback device will be transciently enabled during the device re-opening. For stream_list_add(), keep streams in the stream list descending ordered by channel count. It guarantees that while iterating the stream list, the first attachable stream will have the highest channel count. BUG=b:162211010 TEST=On Stadia gameplay, it will first provide two 2-channel streams then a 6-channel stream. Check num_channels in device stat is 6 (for a 5.1 sound system) and all 6 channels have sounds. TEST=FEATURES="test" emerge adhd Change-Id: Ic822f35adcabaf8b72231b84551bc78f3bc75288 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/adhd/+/2319443 Tested-by: Pin-chih Lin <johnylin@chromium.org> Reviewed-by: Cheng-Yi Chiang <cychiang@chromium.org> Commit-Queue: Pin-chih Lin <johnylin@chromium.org> Auto-Submit: Pin-chih Lin <johnylin@chromium.org>
Diffstat (limited to 'cras/src/server/cras_iodev_list.c')
-rw-r--r--cras/src/server/cras_iodev_list.c48
1 files changed, 36 insertions, 12 deletions
diff --git a/cras/src/server/cras_iodev_list.c b/cras/src/server/cras_iodev_list.c
index 29ed64b6..41850f34 100644
--- a/cras/src/server/cras_iodev_list.c
+++ b/cras/src/server/cras_iodev_list.c
@@ -682,6 +682,11 @@ static int init_and_attach_streams(struct cras_iodev *dev)
if (!can_attach)
continue;
+ /*
+ * Note that the stream list is descending ordered by channel
+ * count, which guarantees the first attachable stream will have
+ * the highest channel count.
+ */
rc = init_device(dev, stream);
if (rc) {
syslog(LOG_ERR, "Enable %s failed, rc = %d",
@@ -806,6 +811,7 @@ static int stream_added_cb(struct cras_rstream *rstream)
struct cras_iodev *iodevs[10];
unsigned int num_iodevs;
int rc;
+ bool iodev_reopened;
if (stream_list_suspended)
return 0;
@@ -816,24 +822,42 @@ static int stream_added_cb(struct cras_rstream *rstream)
/* Add the new stream to all enabled iodevs at once to avoid offset
* in shm level between different ouput iodevs. */
num_iodevs = 0;
+ iodev_reopened = false;
DL_FOREACH (enabled_devs[rstream->direction], edev) {
if (num_iodevs >= ARRAY_SIZE(iodevs)) {
syslog(LOG_ERR, "too many enabled devices");
break;
}
- rc = init_device(edev->dev, rstream);
- if (rc) {
- /* Error log but don't return error here, because
- * stopping audio could block video playback.
+ if (cras_iodev_is_open(edev->dev) &&
+ (rstream->format.num_channels >
+ edev->dev->format->num_channels)) {
+ /* Re-open the device with the format of the attached
+ * stream if it has higher channel count than the
+ * current format of the device. Fallback device will
+ * be transciently enabled during the device re-opening.
*/
- syslog(LOG_ERR, "Init %s failed, rc = %d",
- edev->dev->info.name, rc);
- schedule_init_device_retry(edev->dev);
- continue;
- }
+ syslog(LOG_INFO, "re-open %s for higher channel count",
+ edev->dev->info.name);
+ possibly_enable_fallback(rstream->direction, false);
+ cras_iodev_list_suspend_dev(edev->dev->info.idx);
+ cras_iodev_list_resume_dev(edev->dev->info.idx);
+ possibly_disable_fallback(rstream->direction);
+ iodev_reopened = true;
+ } else {
+ rc = init_device(edev->dev, rstream);
+ if (rc) {
+ /* Error log but don't return error here, because
+ * stopping audio could block video playback.
+ */
+ syslog(LOG_ERR, "Init %s failed, rc = %d",
+ edev->dev->info.name, rc);
+ schedule_init_device_retry(edev->dev);
+ continue;
+ }
- iodevs[num_iodevs++] = edev->dev;
+ iodevs[num_iodevs++] = edev->dev;
+ }
}
if (num_iodevs) {
rc = add_stream_to_open_devs(rstream, iodevs, num_iodevs);
@@ -841,9 +865,9 @@ static int stream_added_cb(struct cras_rstream *rstream)
syslog(LOG_ERR, "adding stream to thread fail");
return rc;
}
- } else {
+ } else if (!iodev_reopened) {
/* Enable fallback device if no other iodevs can be initialized
- * successfully.
+ * or re-opened successfully.
* For error codes like EAGAIN and ENOENT, a new iodev will be
* enabled soon so streams are going to route there. As for the
* rest of the error cases, silence will be played or recorded