Skip to content

Commit 2c7240c

Browse files
Pattara TeerapongChromeos LUCI
Pattara Teerapong
authored and
Chromeos LUCI
committed
cras_stream_apm: Apply aecdump to future APM
When we enable aecdump via chrome://webrtc-internals, it is only applied to the current active APM on that stream. The APM may be removed and a new one is created, or the active APM can be changed due to iodev switching. This cause the future APM to not have aecdump applied. Store the aecdump state on the cras_stream_apm and apply it to the future APM. BUG=b:333982642 TEST=Manual test: 1. Go to chrome://webrtc-internals and start aecdump 2. Start Meet 3. Stop aecdump 4. Unpack the dump and verify that the last stream has aec_enabled=1 and the reverse.wav is not empty TEST=Manual test (Switching device): 1. Start aecdump 2. Select internal mic 3. Start Meet 4. Switch input to 3.5mm mic jack 5. Stop aecdump 6. Check that there is a dump for each input, unpack and check the dump TEST=tast run $DUT audio.ChromeAECDump Change-Id: I4a807ba3a612d0a4ac19d5761aceebff0d2f7c89 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/third_party/adhd/+/5524641 Commit-Queue: Pattara Teerapong <[email protected]> Tested-by: [email protected] <[email protected]> Reviewed-by: Li-Yu Yu <[email protected]>
1 parent 9d9b995 commit 2c7240c

File tree

1 file changed

+114
-16
lines changed

1 file changed

+114
-16
lines changed

cras/src/server/cras_stream_apm.c

Lines changed: 114 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,9 @@ struct cras_apm {
111111
// The time when the apm started.
112112
struct timespec start_ts;
113113
struct cras_apm *prev, *next;
114+
// Indicate if AEC dump is active on this APM. If this APM is
115+
// stopped while AEC dump is active, the dump will be stopped.
116+
bool aec_dump_active;
114117
};
115118

116119
/*
@@ -123,7 +126,7 @@ struct cras_apm {
123126
* Access with cautious from audio thread.
124127
*/
125128
struct cras_stream_apm {
126-
// The effecets bit map of APM.
129+
// The effects bit map of APM.
127130
uint64_t effects;
128131
// List of APMs for stream processing. It is a list because
129132
// multiple input devices could be configured by user.
@@ -132,6 +135,13 @@ struct cras_stream_apm {
132135
// used as echo ref for this apm. When set to NULL it means to
133136
// follow what the default_rmod provides as echo ref.
134137
struct cras_iodev* echo_ref;
138+
// Indicate if AEC dump is running or not. AEC dump can be
139+
// started and stopped via cras_stream_apm_set_aec_dump.
140+
bool aec_dump_enabled;
141+
// fd to the AEC dump file if it is running.
142+
int aec_dump_fd;
143+
// Reference to the APM with AEC dump active.
144+
struct cras_apm* aec_dump_active_apm;
135145
};
136146

137147
static struct actx_apm {
@@ -433,6 +443,64 @@ static inline bool apm_needed_for_effects(uint64_t effects,
433443
return false;
434444
}
435445

446+
// Start AEC dump for the APM. Caller must ensure that the stream contains the
447+
// APM.
448+
void possibly_start_apm_aec_dump(struct cras_stream_apm* stream,
449+
struct cras_apm* apm) {
450+
if (!stream->aec_dump_enabled) {
451+
return;
452+
}
453+
if (stream->aec_dump_active_apm) {
454+
return;
455+
}
456+
457+
// Create or append to the dump file fd.
458+
//
459+
// aecdump format is appendable. It consists of events in the
460+
// third_party/webrtc/modules/audio_processing/debug.proto file.
461+
//
462+
// Example of aecdump file:
463+
// [CONFIG] [INIT] [REVERSE_STREAM] [STREAM] [REVERSE_STREAM] [STREAM] ...
464+
//
465+
// unpack_aecdump read through the events. It will create a new set of wave
466+
// files on INIT event, and append REVERSE_STREAM and STREAM data to them.
467+
//
468+
// Appended aecdump content will be in different wave files due to the INIT
469+
// event. The frame counter will be continued from the previous aecdump
470+
// instead of starting from 0, but the data will be correct.
471+
FILE* handle = fdopen(dup(stream->aec_dump_fd), "w");
472+
if (handle == NULL) {
473+
syslog(LOG_WARNING, "Create dump handle failed, errno %d", errno);
474+
return;
475+
}
476+
477+
// webrtc apm will own the FILE handle and close it.
478+
int rc = webrtc_apm_aec_dump(apm->apm_ptr, &apm->work_queue, 1, handle);
479+
if (rc) {
480+
syslog(LOG_WARNING, "Start apm aec dump failed, rc %d", rc);
481+
}
482+
483+
apm->aec_dump_active = true;
484+
stream->aec_dump_active_apm = apm;
485+
}
486+
487+
// Stop AEC dump for the APM. Caller must ensure that the stream contains the
488+
// APM.
489+
void possibly_stop_apm_aec_dump(struct cras_stream_apm* stream,
490+
struct cras_apm* apm) {
491+
if (!apm->aec_dump_active) {
492+
return;
493+
}
494+
495+
int rc = webrtc_apm_aec_dump(apm->apm_ptr, &apm->work_queue, 0, NULL);
496+
if (rc) {
497+
syslog(LOG_WARNING, "Stop apm aec dump failed, rc %d", rc);
498+
}
499+
500+
apm->aec_dump_active = false;
501+
stream->aec_dump_active_apm = NULL;
502+
}
503+
436504
struct cras_stream_apm* cras_stream_apm_create(uint64_t effects) {
437505
if (!apm_needed_for_effects(
438506
effects,
@@ -456,6 +524,9 @@ struct cras_stream_apm* cras_stream_apm_create(uint64_t effects) {
456524
stream->effects = effects;
457525
stream->apms = NULL;
458526
stream->echo_ref = NULL;
527+
stream->aec_dump_enabled = false;
528+
stream->aec_dump_fd = -1;
529+
stream->aec_dump_active_apm = NULL;
459530

460531
return stream;
461532
}
@@ -558,6 +629,9 @@ void cras_stream_apm_remove(struct cras_stream_apm* stream,
558629
DL_FOREACH (stream->apms, apm) {
559630
if (apm->idev == idev) {
560631
DL_DELETE(stream->apms, apm);
632+
if (stream->aec_dump_active_apm == apm) {
633+
stream->aec_dump_active_apm = NULL;
634+
}
561635
apm_destroy(&apm);
562636
}
563637
}
@@ -781,6 +855,11 @@ void cras_stream_apm_start(struct cras_stream_apm* stream,
781855
cras_apm_reverse_state_update();
782856
update_supported_dsp_effects_activation(actx);
783857
reconfigure_apm_vad(actx);
858+
859+
// If AEC dump is running, start AEC dump for this new APM.
860+
if (stream->aec_dump_enabled) {
861+
possibly_start_apm_aec_dump(stream, apm);
862+
}
784863
}
785864

786865
void cras_stream_apm_stop(struct cras_stream_apm* stream,
@@ -805,6 +884,11 @@ void cras_stream_apm_stop(struct cras_stream_apm* stream,
805884
apm_state.last_nc_closed = now;
806885
}
807886

887+
// If AEC dump is active on this APM, stop it.
888+
if (active->apm->aec_dump_active) {
889+
possibly_stop_apm_aec_dump(stream, active->apm);
890+
}
891+
808892
DL_DELETE(actx->apm->active_apms, active);
809893
free(active);
810894
}
@@ -835,6 +919,10 @@ int cras_stream_apm_destroy(struct cras_stream_apm* stream) {
835919
// Unlink any linked echo ref.
836920
cras_apm_reverse_link_echo_ref(stream, NULL);
837921

922+
if (stream->aec_dump_enabled) {
923+
close(stream->aec_dump_fd);
924+
}
925+
838926
DL_FOREACH (stream->apms, apm) {
839927
DL_DELETE(stream->apms, apm);
840928
apm_destroy(&apm);
@@ -1270,31 +1358,41 @@ void cras_stream_apm_set_aec_dump(struct cras_stream_apm* stream,
12701358
int start,
12711359
int fd) {
12721360
struct cras_apm* apm;
1273-
char file_name[256];
1274-
int rc;
1275-
FILE* handle;
12761361

12771362
DL_SEARCH_SCALAR(stream->apms, apm, idev, idev);
12781363
if (apm == NULL) {
12791364
return;
12801365
}
12811366

12821367
if (start) {
1283-
handle = fdopen(fd, "w");
1284-
if (handle == NULL) {
1285-
syslog(LOG_WARNING, "Create dump handle fail, errno %d", errno);
1286-
return;
1287-
}
1288-
// webrtc apm will own the FILE handle and close it.
1289-
rc = webrtc_apm_aec_dump(apm->apm_ptr, &apm->work_queue, start, handle);
1290-
if (rc) {
1291-
syslog(LOG_WARNING, "Fail to dump debug file %s, rc %d", file_name, rc);
1368+
if (stream->aec_dump_enabled) {
1369+
// If AEC dump is already running, keep it running. If the new fd is
1370+
// different, close the previous one.
1371+
//
1372+
// If there is an APM with active AEC dump, possibly_start_apm_aec_dump
1373+
// will fail (do nothing). New APM created after that will use the new fd.
1374+
syslog(LOG_WARNING,
1375+
"got aec dump start request, but it is already running");
1376+
if (fd != stream->aec_dump_fd) {
1377+
close(stream->aec_dump_fd);
1378+
}
12921379
}
1380+
stream->aec_dump_enabled = true;
1381+
stream->aec_dump_fd = fd;
1382+
possibly_start_apm_aec_dump(stream, apm);
12931383
} else {
1294-
rc = webrtc_apm_aec_dump(apm->apm_ptr, &apm->work_queue, 0, NULL);
1295-
if (rc) {
1296-
syslog(LOG_WARNING, "Failed to stop apm debug, rc %d", rc);
1384+
if (!stream->aec_dump_enabled) {
1385+
syslog(LOG_WARNING, "got aec dump stop request, but it is not running");
1386+
return;
1387+
}
1388+
1389+
// Stop the AEC dump on the APM with active dump.
1390+
if (stream->aec_dump_active_apm) {
1391+
possibly_stop_apm_aec_dump(stream, stream->aec_dump_active_apm);
12971392
}
1393+
1394+
stream->aec_dump_enabled = false;
1395+
close(stream->aec_dump_fd);
12981396
}
12991397
}
13001398

0 commit comments

Comments
 (0)