diff options
author | Pin-chih Lin <johnylin@google.com> | 2020-07-29 15:46:47 +0800 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2020-08-10 08:31:24 +0000 |
commit | 592625514061ca68630566b86dacbe47cd027a93 (patch) | |
tree | a5e49fc349925fe2b5ce5876218de23d24b1f971 /cras/src/server/cras_iodev_list.c | |
parent | 3418709c9ee544524a130228a6c4bba41089dcc4 (diff) | |
download | adhd-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.c | 48 |
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 |