Skip to content

Commit 799ec53

Browse files
committed
Merge branch 'feature/add_mixer_in_acquire_wait_time_check' into 'main'
Add mixer in acquire wait time check See merge request adf/multimedia/esp-gmf!94
2 parents 0c50ff4 + 0ee827d commit 799ec53

File tree

8 files changed

+68
-26
lines changed

8 files changed

+68
-26
lines changed

elements/gmf_audio/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
- Added TRUNCATE support for SONIC element to enable its flexible placement at any position within the pipeline
2020
- Supported scenarios where the input data for audio encoding is not a complete frame
2121
- Added PTS (Presentation Time Stamp) calculation and propagation for the `aud_alc`, `aud_eq`, `aud_fade`, `aud_enc`
22+
- Supported user-configurable input frame length and load acquisition timeout for the mixer
2223

2324
### Bug Fixes
2425

@@ -30,6 +31,7 @@
3031
- Fixed the issue where the encoder modified the configuration during runtime
3132
- Fixed the issue where the mixer did not forward the out_load parameter to downstream components when all input stream were no data
3233
- Fixed bugs that not check validation of in and out buffer for mixer which will cause crash
34+
- Fixed bugs where setting parameters before opening had no effect for `aud_fade` and `aud_mixer`
3335

3436
## v0.6.3
3537

elements/gmf_audio/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
idf_component_register(SRC_DIRS "./"
22
INCLUDE_DIRS "./include"
3-
PRIV_INCLUDE_DIRS "./private_include")
3+
PRIV_INCLUDE_DIRS "./private_include"
4+
REQUIRES esp_timer)

elements/gmf_audio/esp_gmf_fade.c

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ typedef struct {
2424
esp_gmf_audio_element_t parent; /*!< The GMF fade handle */
2525
esp_ae_fade_handle_t fade_hd; /*!< The audio effects fade handle */
2626
uint8_t bytes_per_sample; /*!< Bytes number of per sampling point */
27-
esp_ae_fade_mode_t mode; /*!< The current fade mode */
2827
bool need_reopen : 1; /*!< Whether need to reopen.
2928
True: Execute the close function first, then execute the open function
3029
False: Do nothing */
@@ -236,6 +235,8 @@ esp_gmf_err_t esp_gmf_fade_set_mode(esp_gmf_element_handle_t handle, esp_ae_fade
236235
{
237236
ESP_GMF_NULL_CHECK(TAG, handle, { return ESP_GMF_ERR_INVALID_ARG;});
238237
esp_gmf_fade_t *fade = (esp_gmf_fade_t *)handle;
238+
esp_ae_fade_cfg_t *cfg = (esp_ae_fade_cfg_t *)OBJ_GET_CFG(handle);
239+
ESP_GMF_NULL_CHECK(TAG, cfg, return ESP_GMF_ERR_FAIL);
239240
if (fade->fade_hd) {
240241
esp_gmf_oal_mutex_lock(((esp_gmf_audio_element_t *)handle)->lock);
241242
esp_ae_err_t ret = esp_ae_fade_set_mode(fade->fade_hd, mode);
@@ -244,29 +245,33 @@ esp_gmf_err_t esp_gmf_fade_set_mode(esp_gmf_element_handle_t handle, esp_ae_fade
244245
return ESP_GMF_JOB_ERR_FAIL;
245246
}
246247
}
247-
fade->mode = mode;
248+
cfg->mode = mode;
248249
return ESP_GMF_JOB_ERR_OK;
249250
}
250251

251252
esp_gmf_err_t esp_gmf_fade_get_mode(esp_gmf_element_handle_t handle, esp_ae_fade_mode_t *mode)
252253
{
253254
ESP_GMF_NULL_CHECK(TAG, handle, { return ESP_GMF_ERR_INVALID_ARG;});
254255
ESP_GMF_NULL_CHECK(TAG, mode, { return ESP_GMF_ERR_INVALID_ARG;});
256+
esp_ae_fade_cfg_t *cfg = (esp_ae_fade_cfg_t *)OBJ_GET_CFG(handle);
257+
ESP_GMF_NULL_CHECK(TAG, cfg, return ESP_GMF_ERR_FAIL);
255258
esp_gmf_fade_t *fade = (esp_gmf_fade_t *)handle;
256259
if (fade->fade_hd) {
257260
esp_ae_err_t ret = esp_ae_fade_get_mode(fade->fade_hd, mode);
258261
if (ret != ESP_AE_ERR_OK) {
259262
return ESP_GMF_JOB_ERR_FAIL;
260263
}
261264
} else {
262-
*mode = fade->mode;
265+
*mode = cfg->mode;
263266
}
264267
return ESP_GMF_JOB_ERR_OK;
265268
}
266269

267270
esp_gmf_err_t esp_gmf_fade_reset_weight(esp_gmf_element_handle_t handle)
268271
{
269272
ESP_GMF_NULL_CHECK(TAG, handle, { return ESP_GMF_ERR_INVALID_ARG;});
273+
esp_ae_fade_cfg_t *cfg = (esp_ae_fade_cfg_t *)OBJ_GET_CFG(handle);
274+
ESP_GMF_NULL_CHECK(TAG, cfg, return ESP_GMF_ERR_FAIL);
270275
esp_gmf_fade_t *fade = (esp_gmf_fade_t *)handle;
271276
if(fade->fade_hd) {
272277
esp_gmf_oal_mutex_lock(((esp_gmf_audio_element_t *)handle)->lock);
@@ -275,7 +280,7 @@ esp_gmf_err_t esp_gmf_fade_reset_weight(esp_gmf_element_handle_t handle)
275280
if (ret != ESP_AE_ERR_OK) {
276281
return ESP_GMF_JOB_ERR_FAIL;
277282
}
278-
esp_ae_fade_get_mode(fade->fade_hd, &fade->mode);
283+
esp_ae_fade_get_mode(fade->fade_hd, &cfg->mode);
279284
}
280285
return ESP_GMF_JOB_ERR_OK;
281286
}

elements/gmf_audio/esp_gmf_mixer.c

Lines changed: 43 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,24 @@
1717
#include "esp_gmf_cap.h"
1818
#include "esp_gmf_caps_def.h"
1919
#include "esp_gmf_audio_element.h"
20+
#ifdef MIXER_DEBUG
21+
#include "esp_timer.h"
22+
#endif
2023

21-
#define MIXER_DEFAULT_PROC_TIME_MS (10)
24+
#define MIXER_DEFAULT_PROC_TIME_MS (10)
25+
#define MIXER_GET_FRAME_BYTE_SIZE(info) (MIXER_DEFAULT_PROC_TIME_MS * info->sample_rate * info->channel * info->bits_per_sample / 8000)
2226

2327
typedef struct {
2428
esp_gmf_audio_element_t parent; /*!< The GMF mixer handle */
2529
esp_ae_mixer_handle_t mixer_hd; /*!< The audio effects mixer handle */
2630
uint8_t bytes_per_sample; /*!< Bytes number of per sampling point */
2731
uint32_t process_num; /*!< The data number of mixer processing */
32+
uint32_t frame_time; /*!< The time of one frame, unit: ms */
2833
esp_gmf_payload_t **in_load; /*!< The array of input payload */
2934
esp_gmf_payload_t *out_load; /*!< The output payload */
3035
uint8_t **in_arr; /*!< The input buffer pointer array of mixer */
3136
esp_ae_mixer_mode_t *mode; /*!< The mixer mode */
37+
uint8_t src_num; /*!< The number of source */
3238
bool need_reopen : 1; /*!< Whether need to reopen.
3339
True: Execute the close function first, then execute the open function
3440
False: Do nothing */
@@ -102,9 +108,15 @@ static esp_gmf_job_err_t esp_gmf_mixer_open(esp_gmf_element_handle_t self, void
102108
esp_ae_mixer_cfg_t *mixer_info = (esp_ae_mixer_cfg_t *)OBJ_GET_CFG(self);
103109
ESP_GMF_NULL_CHECK(TAG, mixer_info, {return ESP_GMF_JOB_ERR_FAIL;})
104110
mixer->bytes_per_sample = (mixer_info->bits_per_sample >> 3) * mixer_info->channel;
105-
mixer->process_num = MIXER_DEFAULT_PROC_TIME_MS * mixer_info->sample_rate * mixer->bytes_per_sample / 1000;
106111
esp_ae_mixer_open(mixer_info, &mixer->mixer_hd);
107112
ESP_GMF_CHECK(TAG, mixer->mixer_hd, {return ESP_GMF_JOB_ERR_FAIL;}, "Failed to create mixer handle");
113+
for (int i = 0; i < mixer_info->src_num; i++) {
114+
esp_ae_mixer_set_mode(mixer->mixer_hd, i, mixer->mode[i]);
115+
}
116+
uint32_t process_num = MIXER_GET_FRAME_BYTE_SIZE(mixer_info);
117+
mixer->process_num = (ESP_GMF_ELEMENT_GET(mixer)->in_attr.data_size == 0) ? (process_num) : (ESP_GMF_ELEMENT_GET(mixer)->in_attr.data_size);
118+
mixer->frame_time = GMF_AUDIO_CALC_PTS(mixer->process_num, mixer_info->sample_rate, mixer_info->channel, mixer_info->bits_per_sample);
119+
mixer->src_num = mixer_info->src_num;
108120
mixer->in_load = esp_gmf_oal_calloc(1, sizeof(esp_gmf_payload_t *) * mixer_info->src_num);
109121
ESP_GMF_MEM_VERIFY(TAG, mixer->in_load, {return ESP_GMF_JOB_ERR_FAIL;},
110122
"in load", sizeof(esp_gmf_payload_t *) * mixer_info->src_num);
@@ -156,16 +168,27 @@ static esp_gmf_job_err_t esp_gmf_mixer_process(esp_gmf_element_handle_t self, vo
156168
esp_gmf_port_handle_t in = ESP_GMF_ELEMENT_GET(self)->in;
157169
esp_gmf_port_handle_t in_port = in;
158170
esp_gmf_port_handle_t out_port = ESP_GMF_ELEMENT_GET(self)->out;
159-
esp_ae_mixer_cfg_t *mixer_info = (esp_ae_mixer_cfg_t *)OBJ_GET_CFG(self);
160-
ESP_GMF_NULL_CHECK(TAG, mixer_info, return ESP_GMF_JOB_ERR_FAIL);
161-
int index = mixer_info->src_num;
171+
int index = mixer->src_num;
162172
memset(mixer->in_load, 0, sizeof(esp_gmf_payload_t *) * index);
163173
mixer->out_load = NULL;
164174
int i = 0;
165-
int wait_time = 0;
175+
#ifdef MIXER_DEBUG
176+
uint64_t start = 0;
177+
uint64_t end = 0;
178+
uint64_t acquire_in_time = 0;
179+
uint32_t frame_time = mixer->frame_time;
180+
#endif
166181
while (in_port != NULL) {
167-
wait_time = i == 0 ? ESP_GMF_MAX_DELAY : 0;
168-
ret = esp_gmf_port_acquire_in(in_port, &(mixer->in_load[i]), mixer->process_num, wait_time);
182+
#ifdef MIXER_DEBUG
183+
start = esp_timer_get_time();
184+
#endif
185+
int wait_ticks = ((in_port->wait_ticks < (mixer->frame_time / index)) ? (mixer->frame_time / index) : (in_port->wait_ticks));
186+
ret = esp_gmf_port_acquire_in(in_port, &(mixer->in_load[i]), mixer->process_num, wait_ticks);
187+
#ifdef MIXER_DEBUG
188+
end = esp_timer_get_time();
189+
acquire_in_time += ((end - start) / 1000);
190+
ESP_LOGD(TAG, "Port %d acquire in time: %lld ms, wait ticks: %d", i, (end - start) / 1000, wait_ticks);
191+
#endif
169192
if (ret == ESP_GMF_IO_FAIL || mixer->in_load[i]->buf == NULL) {
170193
ESP_LOGE(TAG, "Acquire in failed, idx:%d, ret: %d", i, ret);
171194
out_len = ESP_GMF_JOB_ERR_FAIL;
@@ -180,11 +203,16 @@ static esp_gmf_job_err_t esp_gmf_mixer_process(esp_gmf_element_handle_t self, vo
180203
memset(mixer->in_arr[i] + read_len, 0, mixer->process_num - read_len);
181204
}
182205
in_port = in_port->next;
183-
i++;
184206
ESP_LOGV(TAG, "IN: idx: %d load: %p, buf: %p, valid size: %d, buf length: %d, done: %d",
185207
i, mixer->in_load[i], mixer->in_load[i]->buf, mixer->in_load[i]->valid_size,
186208
mixer->in_load[i]->buf_length, mixer->in_load[i]->is_done);
209+
i++;
210+
}
211+
#ifdef MIXER_DEBUG
212+
if (acquire_in_time > frame_time) {
213+
ESP_LOGW(TAG, "Total acquire in time: %lld ms, frame time: %ld ms", acquire_in_time, frame_time);
187214
}
215+
#endif
188216
ret = esp_gmf_port_acquire_out(out_port, &mixer->out_load, mixer->process_num, ESP_GMF_MAX_DELAY);
189217
ESP_GMF_PORT_ACQUIRE_OUT_CHECK(TAG, ret, out_len, { goto __mixer_release;});
190218
// Down-mixer never stop in gmf, only user can set to stop
@@ -380,13 +408,17 @@ esp_gmf_err_t esp_gmf_mixer_init(esp_ae_mixer_cfg_t *config, esp_gmf_element_han
380408
esp_gmf_obj_set_config(obj, cfg, sizeof(esp_ae_mixer_cfg_t));
381409
mixer->mode = esp_gmf_oal_calloc(cfg->src_num, sizeof(esp_ae_mixer_mode_t));
382410
ESP_GMF_MEM_VERIFY(TAG, mixer->mode, {ret = ESP_GMF_ERR_MEMORY_LACK; goto MIXER_INIT_FAIL;}, "Allocate(%d) failed", cfg->src_num * sizeof(esp_ae_mixer_mode_t));
411+
for (int i = 0; i < cfg->src_num; i++) {
412+
mixer->mode[i] = ESP_AE_MIXER_MODE_FADE_UPWARD;
413+
}
383414
ret = esp_gmf_obj_set_tag(obj, "aud_mixer");
384415
ESP_GMF_RET_ON_NOT_OK(TAG, ret, goto MIXER_INIT_FAIL, "Failed to set obj tag");
385416
esp_gmf_element_cfg_t el_cfg = {0};
417+
mixer->process_num = MIXER_GET_FRAME_BYTE_SIZE(cfg);
386418
ESP_GMF_ELEMENT_IN_PORT_ATTR_SET(el_cfg.in_attr, ESP_GMF_EL_PORT_CAP_MULTI, 0, 0,
387-
ESP_GMF_PORT_TYPE_BLOCK | ESP_GMF_PORT_TYPE_BYTE, ESP_GMF_ELEMENT_PORT_DATA_SIZE_DEFAULT);
419+
ESP_GMF_PORT_TYPE_BLOCK | ESP_GMF_PORT_TYPE_BYTE, mixer->process_num);
388420
ESP_GMF_ELEMENT_IN_PORT_ATTR_SET(el_cfg.out_attr, ESP_GMF_EL_PORT_CAP_SINGLE, 0, 0,
389-
ESP_GMF_PORT_TYPE_BLOCK | ESP_GMF_PORT_TYPE_BYTE, ESP_GMF_ELEMENT_PORT_DATA_SIZE_DEFAULT);
421+
ESP_GMF_PORT_TYPE_BLOCK | ESP_GMF_PORT_TYPE_BYTE, mixer->process_num);
390422
el_cfg.dependency = true;
391423
ret = esp_gmf_audio_el_init(mixer, &el_cfg);
392424
ESP_GMF_RET_ON_NOT_OK(TAG, ret, goto MIXER_INIT_FAIL, "Failed to initialize mixer element");

elements/test_apps/main/elements/gmf_audio_effects_test.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -498,11 +498,10 @@ TEST_CASE("Audio mixer Play", "[ESP_GMF_Effects]")
498498
TEST_ASSERT_EQUAL(ESP_GMF_ERR_OK, esp_gmf_pipeline_run(pipe3));
499499
esp_gmf_element_handle_t mixer_hd = NULL;
500500
TEST_ASSERT_EQUAL(ESP_GMF_ERR_OK, esp_gmf_pipeline_get_el_by_name(pipe3, "aud_mixer", &mixer_hd));
501-
esp_ae_mixer_mode_t mode = ESP_AE_MIXER_MODE_FADE_UPWARD;
502501
xEventGroupWaitBits(pipe_sync_evt3, PIPELINE_BLOCK_RUN_BIT, pdTRUE, pdFALSE, portMAX_DELAY);
503502
// set mode
504-
TEST_ASSERT_EQUAL(ESP_GMF_ERR_OK, esp_gmf_mixer_set_mode(mixer_hd, 0, mode));
505-
TEST_ASSERT_EQUAL(ESP_GMF_ERR_OK, esp_gmf_mixer_set_mode(mixer_hd, 1, mode));
503+
TEST_ASSERT_EQUAL(ESP_GMF_ERR_OK, esp_gmf_mixer_set_mode(mixer_hd, 0, ESP_AE_MIXER_MODE_FADE_UPWARD));
504+
TEST_ASSERT_EQUAL(ESP_GMF_ERR_OK, esp_gmf_mixer_set_mode(mixer_hd, 1, ESP_AE_MIXER_MODE_FADE_DOWNWARD));
506505

507506
xEventGroupWaitBits(pipe_sync_evt1, PIPELINE_BLOCK_BIT, pdTRUE, pdFALSE, portMAX_DELAY);
508507
xEventGroupWaitBits(pipe_sync_evt2, PIPELINE_BLOCK_BIT, pdTRUE, pdFALSE, portMAX_DELAY);

packages/esp_audio_simple_player/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
### Features
66

77
- Replaced the interface for decoding reconfig
8+
- Supported placing the audio processing task stack in RAM or SPI-RAM using `stack_in_ext` in `esp_asp_cfg_t`
89

910
## v0.9.3
1011

packages/esp_audio_simple_player/include/esp_audio_simple_player.h

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,14 @@ typedef struct {
6969
* @brief Configuration structure for the audio simple player
7070
*/
7171
typedef struct {
72-
esp_asp_func_t in; /*!< Input data callback, it is required only for raw data(raw://xxx/xxx.mp3), and is ignored in other cases */
73-
esp_asp_func_t out; /*!< Output data callback configuration, it is required for all cases */
74-
int task_prio; /*!< Priority of the player task */
75-
int task_stack; /*!< Size of the task stack */
76-
uint8_t task_core; /*!< CPU core affinity for the task */
77-
esp_asp_prev_func_t prev; /*!< An optional callback invoked before the pipeline starts (e.g., configure linked elements before running) */
78-
void *prev_ctx; /*!< User context passed to the previous action callback */
72+
esp_asp_func_t in; /*!< Input data callback, it is required only for raw data(raw://xxx/xxx.mp3), and is ignored in other cases */
73+
esp_asp_func_t out; /*!< Output data callback configuration, it is required for all cases */
74+
int task_prio; /*!< Priority of the player task */
75+
int task_stack; /*!< Size of the task stack */
76+
uint8_t task_core; /*!< CPU core affinity for the task */
77+
bool task_stack_in_ext : 1; /*!< Whether the task stack is in external memory */
78+
esp_asp_prev_func_t prev; /*!< An optional callback invoked before the pipeline starts (e.g., configure linked elements before running) */
79+
void *prev_ctx; /*!< User context passed to the previous action callback */
7980
} esp_asp_cfg_t;
8081

8182
/**

packages/esp_audio_simple_player/src/esp_audio_simple_player.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@ esp_gmf_err_t esp_audio_simple_player_new(esp_asp_cfg_t *cfg, esp_asp_handle_t *
300300
task_cfg.thread.prio = cfg->task_prio;
301301
}
302302
task_cfg.thread.core = cfg->task_core;
303+
task_cfg.thread.stack_in_ext = cfg->task_stack_in_ext;
303304
esp_gmf_task_init(&task_cfg, &player->work_task);
304305
if (player->work_task == NULL) {
305306
ESP_LOGE(TAG, "Failed to create the pipeline task");

0 commit comments

Comments
 (0)