@@ -111,6 +111,9 @@ struct cras_apm {
111
111
// The time when the apm started.
112
112
struct timespec start_ts ;
113
113
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 ;
114
117
};
115
118
116
119
/*
@@ -123,7 +126,7 @@ struct cras_apm {
123
126
* Access with cautious from audio thread.
124
127
*/
125
128
struct cras_stream_apm {
126
- // The effecets bit map of APM.
129
+ // The effects bit map of APM.
127
130
uint64_t effects ;
128
131
// List of APMs for stream processing. It is a list because
129
132
// multiple input devices could be configured by user.
@@ -132,6 +135,13 @@ struct cras_stream_apm {
132
135
// used as echo ref for this apm. When set to NULL it means to
133
136
// follow what the default_rmod provides as echo ref.
134
137
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 ;
135
145
};
136
146
137
147
static struct actx_apm {
@@ -433,6 +443,64 @@ static inline bool apm_needed_for_effects(uint64_t effects,
433
443
return false;
434
444
}
435
445
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
+
436
504
struct cras_stream_apm * cras_stream_apm_create (uint64_t effects ) {
437
505
if (!apm_needed_for_effects (
438
506
effects ,
@@ -456,6 +524,9 @@ struct cras_stream_apm* cras_stream_apm_create(uint64_t effects) {
456
524
stream -> effects = effects ;
457
525
stream -> apms = NULL ;
458
526
stream -> echo_ref = NULL ;
527
+ stream -> aec_dump_enabled = false;
528
+ stream -> aec_dump_fd = -1 ;
529
+ stream -> aec_dump_active_apm = NULL ;
459
530
460
531
return stream ;
461
532
}
@@ -558,6 +629,9 @@ void cras_stream_apm_remove(struct cras_stream_apm* stream,
558
629
DL_FOREACH (stream -> apms , apm ) {
559
630
if (apm -> idev == idev ) {
560
631
DL_DELETE (stream -> apms , apm );
632
+ if (stream -> aec_dump_active_apm == apm ) {
633
+ stream -> aec_dump_active_apm = NULL ;
634
+ }
561
635
apm_destroy (& apm );
562
636
}
563
637
}
@@ -781,6 +855,11 @@ void cras_stream_apm_start(struct cras_stream_apm* stream,
781
855
cras_apm_reverse_state_update ();
782
856
update_supported_dsp_effects_activation (actx );
783
857
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
+ }
784
863
}
785
864
786
865
void cras_stream_apm_stop (struct cras_stream_apm * stream ,
@@ -805,6 +884,11 @@ void cras_stream_apm_stop(struct cras_stream_apm* stream,
805
884
apm_state .last_nc_closed = now ;
806
885
}
807
886
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
+
808
892
DL_DELETE (actx -> apm -> active_apms , active );
809
893
free (active );
810
894
}
@@ -835,6 +919,10 @@ int cras_stream_apm_destroy(struct cras_stream_apm* stream) {
835
919
// Unlink any linked echo ref.
836
920
cras_apm_reverse_link_echo_ref (stream , NULL );
837
921
922
+ if (stream -> aec_dump_enabled ) {
923
+ close (stream -> aec_dump_fd );
924
+ }
925
+
838
926
DL_FOREACH (stream -> apms , apm ) {
839
927
DL_DELETE (stream -> apms , apm );
840
928
apm_destroy (& apm );
@@ -1270,31 +1358,41 @@ void cras_stream_apm_set_aec_dump(struct cras_stream_apm* stream,
1270
1358
int start ,
1271
1359
int fd ) {
1272
1360
struct cras_apm * apm ;
1273
- char file_name [256 ];
1274
- int rc ;
1275
- FILE * handle ;
1276
1361
1277
1362
DL_SEARCH_SCALAR (stream -> apms , apm , idev , idev );
1278
1363
if (apm == NULL ) {
1279
1364
return ;
1280
1365
}
1281
1366
1282
1367
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
+ }
1292
1379
}
1380
+ stream -> aec_dump_enabled = true;
1381
+ stream -> aec_dump_fd = fd ;
1382
+ possibly_start_apm_aec_dump (stream , apm );
1293
1383
} 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 );
1297
1392
}
1393
+
1394
+ stream -> aec_dump_enabled = false;
1395
+ close (stream -> aec_dump_fd );
1298
1396
}
1299
1397
}
1300
1398
0 commit comments