Skip to content

Commit cbfd5bc

Browse files
committed
Merge branch 'bugfix/fix_stop_and_pause_flag' into 'main'
bugfix(gmf_core): Fixed a bug where the pause and stop operations lagged and caused the run API call to fail See merge request adf/multimedia/esp-gmf!114
2 parents 2fc257d + b6cdb46 commit cbfd5bc

File tree

4 files changed

+204
-5
lines changed

4 files changed

+204
-5
lines changed

gmf_core/CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# Changelog
22

3+
## v0.7.1
4+
5+
### Bug Fixes
6+
7+
- Fixed a bug where the pause and stop operations lagged and caused the run API call to fail
8+
39
## v0.7.0
410

511
### Features

gmf_core/idf_component.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
version: "0.7.0"
1+
version: "0.7.1"
22
description: Espressif General Multimedia Framework (gmf-core) module
33
url: https://github.com/espressif/esp-gmf/tree/main/gmf_core
44
documentation: "https://github.com/espressif/esp-gmf/blob/main/gmf_core/README.md"

gmf_core/src/esp_gmf_task.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -239,13 +239,11 @@ static inline int process_func(esp_gmf_task_handle_t handle, void *para)
239239
esp_gmf_event_get_state_str(tsk->state));
240240
GMF_TASK_SET_STATE_BITS(tsk->event_group, GMF_TASK_PAUSE_BIT);
241241
}
242-
tsk->_pause = 0;
243242
}
244243
if (tsk->_stop && (tsk->state != ESP_GMF_EVENT_STATE_ERROR)) {
245244
ESP_LOGV(TAG, "Stop job, [%s-%p, wk:%p, job:%p-%s]", OBJ_GET_TAG((esp_gmf_obj_handle_t)tsk), tsk, worker, worker->ctx, worker->label);
246245
__esp_gmf_task_delete_jobs(tsk);
247246
quit_state = ESP_GMF_EVENT_STATE_STOPPED;
248-
tsk->_stop = 0;
249247
break;
250248
}
251249
ESP_LOGD(TAG, "Find next job to process, [%s-%p, cur:%p-%p-%s]", OBJ_GET_TAG((esp_gmf_obj_handle_t)tsk), tsk, worker, worker->ctx, worker->label);
@@ -511,8 +509,10 @@ esp_gmf_err_t esp_gmf_task_stop(esp_gmf_task_handle_t handle)
511509
if (GMF_TASK_WAIT_FOR_STATE_BITS(tsk->event_group, GMF_TASK_STOP_BIT, tsk->api_sync_time) == false) {
512510
ESP_LOGE(TAG, "Stop timeout,[%s,%p]", OBJ_GET_TAG((esp_gmf_obj_handle_t)tsk), tsk);
513511
esp_gmf_oal_mutex_unlock(tsk->lock);
512+
tsk->_stop = 0;
514513
return ESP_GMF_ERR_TIMEOUT;
515514
}
515+
tsk->_stop = 0;
516516
esp_gmf_oal_mutex_unlock(tsk->lock);
517517
return ESP_GMF_ERR_OK;
518518
}
@@ -542,8 +542,10 @@ esp_gmf_err_t esp_gmf_task_pause(esp_gmf_task_handle_t handle)
542542
if (GMF_TASK_WAIT_FOR_MULTI_STATE_BITS(tsk->event_group, GMF_TASK_PAUSE_BIT | GMF_TASK_STOP_BIT, tsk->api_sync_time) == false) {
543543
ESP_LOGE(TAG, "Pause timeout,[%s,%p]", OBJ_GET_TAG((esp_gmf_obj_handle_t)tsk), tsk);
544544
esp_gmf_oal_mutex_unlock(tsk->lock);
545+
tsk->_pause = 0;
545546
return ESP_GMF_ERR_TIMEOUT;
546547
}
548+
tsk->_pause = 0;
547549
// Only clear pause bits
548550
GMF_TASK_CLR_STATE_BITS(tsk->event_group, GMF_TASK_PAUSE_BIT);
549551
esp_gmf_oal_mutex_unlock(tsk->lock);

packages/esp_audio_simple_player/test_apps/main/aud_simp_player_test.c

Lines changed: 193 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,24 @@
2828
#include "esp_gmf_io.h"
2929
#include "esp_gmf_io_embed_flash.h"
3030

31-
static const char *TAG = "PLAYER_TEST";
32-
3331
#define PIPELINE_BLOCK_BIT BIT(0)
3432

33+
// 定义事件组标志位
34+
#define STATE_RUNNING_BIT (1 << 0)
35+
#define STATE_STOPPED_BIT (1 << 1)
36+
#define STATE_PAUSED_BIT (1 << 2)
37+
#define STATE_FINISHED_BIT (1 << 3)
38+
#define CUSTOM_HIGH_PRIO_TASK_STOP_BIT (1 << 4)
39+
#define CUSTOM_LOW_PRIO_TASK_STOP_BIT (1 << 5)
40+
41+
typedef struct {
42+
esp_asp_handle_t *player_handle;
43+
volatile bool *test_flag;
44+
EventGroupHandle_t state_event_group;
45+
} test_task_params_t;
46+
47+
static const char *TAG = "PLAYER_TEST";
48+
3549
static const char *dec_file_path[] = {
3650
"file://sdcard/test.mp3",
3751
"file://sdcard/test.opus",
@@ -605,3 +619,180 @@ TEST_CASE("Play, Multiple-file Async Playing", "[Simple_Player][leaks=14000]")
605619
vTaskDelay(1000 / portTICK_PERIOD_MS);
606620
ESP_GMF_MEM_SHOW(TAG);
607621
}
622+
623+
static int test_event_callback(esp_asp_event_pkt_t *event, void *ctx)
624+
{
625+
if (event->type == ESP_ASP_EVENT_TYPE_MUSIC_INFO) {
626+
esp_asp_music_info_t info = {0};
627+
memcpy(&info, event->payload, event->payload_size);
628+
ESP_LOGW(TAG, "Get info, rate:%d, channels:%d, bits:%d", info.sample_rate, info.channels, info.bits);
629+
} else if (event->type == ESP_ASP_EVENT_TYPE_STATE) {
630+
esp_asp_state_t st = 0;
631+
memcpy(&st, event->payload, event->payload_size);
632+
ESP_LOGW(TAG, "Get State, %d,%s", st, esp_audio_simple_player_state_to_str(st));
633+
634+
uint8_t bits = 0;
635+
switch (st) {
636+
case ESP_ASP_STATE_RUNNING:
637+
bits = STATE_RUNNING_BIT;
638+
break;
639+
case ESP_ASP_STATE_STOPPED:
640+
bits = STATE_STOPPED_BIT;
641+
break;
642+
case ESP_ASP_STATE_PAUSED:
643+
bits = STATE_PAUSED_BIT;
644+
break;
645+
case ESP_ASP_STATE_FINISHED:
646+
bits = STATE_FINISHED_BIT;
647+
break;
648+
default:
649+
break;
650+
}
651+
if (bits != 0) {
652+
// Set event group bits
653+
xEventGroupSetBits((EventGroupHandle_t)ctx, bits);
654+
}
655+
}
656+
return 0;
657+
}
658+
659+
// Low priority task:run simple player and randomly pause or stop it
660+
void low_priority_task(void *pvParameters)
661+
{
662+
ESP_LOGI(TAG, "Low priority task running ...");
663+
srand(xTaskGetTickCount() ^ (uint32_t)pvParameters);
664+
665+
test_task_params_t *task_params = (test_task_params_t *)pvParameters;
666+
esp_asp_handle_t *handle = task_params->player_handle;
667+
EventGroupHandle_t event_group = task_params->state_event_group;
668+
669+
esp_asp_state_t state;
670+
esp_gmf_err_t err;
671+
672+
err = esp_audio_simple_player_run(*handle, "file://sdcard/alarm_44100hz_16bit_2ch_100ms.mp3", NULL);
673+
TEST_ASSERT_EQUAL(ESP_OK, err);
674+
675+
while (*(task_params->test_flag)) {
676+
vTaskDelay(pdMS_TO_TICKS(90 + rand() % 40));
677+
678+
err = esp_audio_simple_player_get_state(*handle, &state);
679+
TEST_ASSERT_EQUAL(ESP_OK, err);
680+
681+
if (state == ESP_ASP_STATE_RUNNING) {
682+
uint8_t op = rand() % 2;
683+
switch (op) {
684+
case 0: // Pause
685+
ESP_LOGW(TAG, "Player is running, trying to PAUSE it");
686+
err = esp_audio_simple_player_pause(*handle);
687+
TEST_ASSERT_EQUAL(ESP_OK, err);
688+
break;
689+
690+
case 1: // Stop
691+
ESP_LOGW(TAG, "Player is running, trying to STOP it");
692+
err = esp_audio_simple_player_stop(*handle);
693+
TEST_ASSERT_EQUAL(ESP_OK, err);
694+
break;
695+
}
696+
}
697+
}
698+
699+
ESP_LOGI(TAG, "Low priority task is done");
700+
xEventGroupSetBits(event_group, CUSTOM_LOW_PRIO_TASK_STOP_BIT);
701+
vTaskDelete(NULL);
702+
}
703+
704+
// High priority task:monitor player state and recover it if needed
705+
void high_priority_task(void *pvParameters)
706+
{
707+
ESP_LOGI(TAG, "High priority task running ...");
708+
709+
test_task_params_t *task_params = (test_task_params_t *)pvParameters;
710+
esp_asp_handle_t *handle = task_params->player_handle;
711+
EventGroupHandle_t event_group = task_params->state_event_group;
712+
713+
EventBits_t bits;
714+
TickType_t wait_timeout = 100;
715+
716+
while (*(task_params->test_flag)) {
717+
bits = xEventGroupWaitBits(event_group,
718+
STATE_STOPPED_BIT | STATE_FINISHED_BIT | STATE_PAUSED_BIT,
719+
pdTRUE, pdFALSE, portMAX_DELAY);
720+
721+
if ((bits & STATE_FINISHED_BIT) || (bits & STATE_STOPPED_BIT)) {
722+
wait_timeout = 200;
723+
xEventGroupClearBits(event_group, STATE_FINISHED_BIT | STATE_STOPPED_BIT | STATE_RUNNING_BIT);
724+
ESP_LOGW(TAG, "Player FINISHED or STOPPED, high priority begin to recover player");
725+
esp_gmf_err_t err = esp_audio_simple_player_run(*handle, "file://sdcard/alarm_44100hz_16bit_2ch_100ms.mp3", NULL);
726+
TEST_ASSERT_EQUAL(ESP_OK, err);
727+
} else if (bits & STATE_PAUSED_BIT) {
728+
wait_timeout = 100;
729+
xEventGroupClearBits(event_group, STATE_PAUSED_BIT | STATE_RUNNING_BIT);
730+
ESP_LOGW(TAG, "Player PAUSED, high priority begin to recover player");
731+
esp_gmf_err_t err = esp_audio_simple_player_resume(*handle);
732+
TEST_ASSERT_EQUAL(ESP_OK, err);
733+
}
734+
735+
EventBits_t run_bits = xEventGroupWaitBits(event_group,
736+
STATE_RUNNING_BIT,
737+
pdTRUE, pdFALSE,
738+
pdMS_TO_TICKS(wait_timeout));
739+
TEST_ASSERT_TRUE(run_bits & STATE_RUNNING_BIT);
740+
}
741+
742+
ESP_LOGI(TAG, "High priority task is done");
743+
xEventGroupSetBits(event_group, CUSTOM_HIGH_PRIO_TASK_STOP_BIT);
744+
vTaskDelete(NULL);
745+
}
746+
747+
TEST_CASE("Pause, Stop, and Run APIs for Multi-task Execution", "[Simple_Player]")
748+
{
749+
esp_log_level_set("*", ESP_LOG_INFO);
750+
ESP_GMF_MEM_SHOW(TAG);
751+
esp_gmf_app_setup_codec_dev(NULL);
752+
void *sdcard_handle = NULL;
753+
esp_gmf_app_setup_sdcard(&sdcard_handle);
754+
755+
esp_asp_cfg_t cfg = {
756+
.in.cb = NULL,
757+
.in.user_ctx = NULL,
758+
.out.cb = out_data_callback,
759+
.out.user_ctx = esp_gmf_app_get_playback_handle(),
760+
.task_prio = 5,
761+
};
762+
763+
esp_asp_handle_t handle = NULL;
764+
esp_gmf_err_t err = esp_audio_simple_player_new(&cfg, &handle);
765+
TEST_ASSERT_EQUAL(ESP_OK, err);
766+
767+
EventGroupHandle_t event_group = xEventGroupCreate();
768+
xEventGroupClearBits(event_group, 0xFFFFFF);
769+
err = esp_audio_simple_player_set_event(handle, test_event_callback, event_group);
770+
771+
test_task_params_t *params = malloc(sizeof(test_task_params_t));
772+
volatile bool test_flag = true;
773+
774+
params->player_handle = &handle;
775+
params->test_flag = &test_flag;
776+
params->state_event_group = event_group;
777+
778+
xTaskCreate(high_priority_task, "High Priority Task", 4096, (void *)params, 7, NULL);
779+
xTaskCreate(low_priority_task, "Low Priority Task", 4096, (void *)params, 6, NULL);
780+
781+
vTaskDelay(pdMS_TO_TICKS(20000));
782+
test_flag = false;
783+
784+
xEventGroupWaitBits(event_group,
785+
CUSTOM_HIGH_PRIO_TASK_STOP_BIT | CUSTOM_LOW_PRIO_TASK_STOP_BIT,
786+
pdTRUE, pdTRUE,
787+
portMAX_DELAY);
788+
ESP_LOGI(TAG, "All tasks are deleted, test finished");
789+
err = esp_audio_simple_player_stop(handle);
790+
TEST_ASSERT_EQUAL(ESP_OK, err);
791+
err = esp_audio_simple_player_destroy(handle);
792+
TEST_ASSERT_EQUAL(ESP_OK, err);
793+
esp_gmf_app_teardown_sdcard(sdcard_handle);
794+
esp_gmf_app_teardown_codec_dev();
795+
vTaskDelay(1000 / portTICK_PERIOD_MS);
796+
free(params);
797+
ESP_GMF_MEM_SHOW(TAG);
798+
}

0 commit comments

Comments
 (0)