音频管道播放暂停时。有的时候不能暂停
Posted: Mon Jul 20, 2020 2:31 am
使用音乐管道播放音乐是暂停有的时候会失败
log
暂停命令发送出来了。但等待命令执行不成功。暂停失败
这个任务一直卡在 if (audio_element_process_running(el) != ESP_OK)这里面读rb,
而不能执行 if (audio_event_iface_waiting_cmd_msg(el->iface_event) != ESP_OK) {//读取之前发送的暂停命令。暂停失败。
只有这下一个恢复命令把之前的音频元素运行了,之前的音频元素写入数据了了。当前音频元素读取数据后。再读cmd.而读取出来的是之前队列中已经存在的暂停命令。
if (audio_element_process_running(el) != ESP_OK)一直卡在读取数据中。
以上是有个人见解不知道对不对。
但解决的方法一直没找到 。暂停老是音频元素暂停失败。
有大神能指导一下吗
log
Code: Select all
[0;32mI (5821) MUSIC: el_state:2[0m
[0;32mI (5821) MUSIC: [ * ] Pausing audio pipeline[0m//按暂停
[0;32mI (5841) MUSIC: Audio event 8 from file element[0m
[0;32mI (5841) MUSIC: AEL_STATUS_STATE_PAUSED[0m
[0;32mI (5841) AUDIO_ELEMENT: [file] AEL_MSG_CMD_PAUSE[0m
[0;32mI (5841) STAGEFRIGHTMP3_DECODER: Closed[0m
[0;32mI (5841) MUSIC: Audio event 8 from mp3 element[0m
[0;32mI (5851) MUSIC: AEL_STATUS_STATE_PAUSED[0m
[0;32mI (5851) AUDIO_ELEMENT: [mp3] AEL_MSG_CMD_PAUSE[0m
//这个时候后面应该会有[filter]的暂停命令。但这个命令丢失了
[0;32mI (9861) MUSIC: el_state:3[0m
[0;32mI (9861) MUSIC: [ * ] Resuming audio pipeline[0m//按恢复按键
[0;32mI (9861) AUDIO_ELEMENT: [mp3] AEL_MSG_CMD_RESUME,state:3[0m
[0;32mI (9861) STAGEFRIGHTMP3_DECODER: MP3 opened[0m
[0;32mI (9861) MUSIC: Audio event 9 from mp3 element[0m
[0;32mI (9871) MUSIC: Audio event 8 from raw element[0m
[0;32mI (9871) MUSIC: AEL_STATUS_STATE_RUNNING[0m
[0;32mI (9881) MUSIC: Audio event 8 from mp3 element[0m
[0;32mI (9881) MUSIC: AEL_STATUS_STATE_RUNNING[0m
[0;32mI (9901) MUSIC: Audio event 8 from filter element[0m
[0;32mI (9901) MUSIC: AEL_STATUS_STATE_PAUSED[0m
[0;32mI (9901) AUDIO_ELEMENT: [filter] AEL_MSG_CMD_PAUSE[0m //这个是之前的暂停命令。而在恢复中执行了,后面系统就乱了
[0;32mI (9901) AUDIO_ELEMENT: [file] AEL_MSG_CMD_RESUME,state:3[0m
[0;32mI (9911) FATFS_STREAM: File size is 1883189 byte,pos:94208[0m
[0;32mI (9921) MUSIC: Audio event 8 from file element[0m
[0;32mI (9921) MUSIC: AEL_STATUS_STATE_RUNNING[0m
Code: Select all
esp_err_t audio_element_pause(audio_element_handle_t el)
{
if (!el->task_run) {
ESP_LOGW(TAG, "[%s] Element has not create when AUDIO_ELEMENT_PAUSE", el->tag);
return ESP_FAIL;
}
if ((el->state >= AEL_STATE_PAUSED)) {
audio_element_force_set_state(el, AEL_STATE_PAUSED);
ESP_LOGD(TAG, "[%s] Element already paused, state:%d", el->tag, el->state);
return ESP_OK;
}
xEventGroupClearBits(el->state_event, PAUSED_BIT);
if (el->task_stack <= 0) {
el->is_running = false;
audio_element_force_set_state(el, AEL_STATE_PAUSED);
return ESP_OK;
}
if (audio_element_cmd_send(el, AEL_MSG_CMD_PAUSE) != ESP_OK) {
ESP_LOGE(TAG, "[%s] Element send cmd error when AUDIO_ELEMENT_PAUSE", el->tag);
return ESP_FAIL;
}
EventBits_t uxBits = xEventGroupWaitBits(el->state_event, PAUSED_BIT, false, true, DEFAULT_MAX_WAIT_TIME);
esp_err_t ret = ESP_FAIL;
if (uxBits & PAUSED_BIT) { //这个不成立。AEL_MSG_CMD_PAUSE命令发送了,
ret = ESP_OK;
}
return ret;
}
而不能执行 if (audio_event_iface_waiting_cmd_msg(el->iface_event) != ESP_OK) {//读取之前发送的暂停命令。暂停失败。
只有这下一个恢复命令把之前的音频元素运行了,之前的音频元素写入数据了了。当前音频元素读取数据后。再读cmd.而读取出来的是之前队列中已经存在的暂停命令。
Code: Select all
void audio_element_task(void *pv)
{
audio_element_handle_t el = (audio_element_handle_t)pv;
el->task_run = true;
xEventGroupSetBits(el->state_event, TASK_CREATED_BIT);
audio_element_force_set_state(el, AEL_STATE_INIT);
audio_event_iface_set_cmd_waiting_timeout(el->iface_event, portMAX_DELAY);
if (el->buf_size > 0) {
el->buf = audio_malloc(el->buf_size);
AUDIO_MEM_CHECK(TAG, el->buf, {
el->task_run = false;
ESP_LOGE(TAG, "[%s] Error malloc element buffer", el->tag);
});
}
xEventGroupClearBits(el->state_event, STOPPED_BIT);
while (el->task_run) {
if (audio_event_iface_waiting_cmd_msg(el->iface_event) != ESP_OK) {//
xEventGroupSetBits(el->state_event, STOPPED_BIT);
break;
}
if (audio_element_process_running(el) != ESP_OK) { //之前的音频元素暂停了,ringbuffer里面没有数据时,当前音频过犹不及在中取不出数据。一前在等待取数据。不能去执行audio_event_iface_waiting_cmd_msg,不能执行暂停命令了
// continue;。
}
}
if (el->is_open && el->close) {
ESP_LOGD(TAG, "[%s] el closed", el->tag);
el->close(el);
el->is_open = false;
}
audio_free(el->buf);
ESP_LOGD(TAG, "[%s] el task deleted,%d", el->tag, uxTaskGetStackHighWaterMark(NULL));
el->stopping = false;
el->task_run = false;
xEventGroupSetBits(el->state_event, TASK_DESTROYED_BIT);
vTaskDelete(NULL);
}
Code: Select all
int rb_read(ringbuf_handle_t rb, char *buf, int buf_len, TickType_t ticks_to_wait)
{
int read_size = 0;
int total_read_size = 0;
int ret_val = 0;
if (rb == NULL) {
return RB_FAIL;
}
while (buf_len) {
//take buffer lock
if (rb_block(rb->lock, portMAX_DELAY) != pdTRUE) {
ret_val = RB_TIMEOUT;
goto read_err;
}
if (rb->fill_cnt < buf_len) {
read_size = rb->fill_cnt;
/**
* When non-multiple of 4(word size) bytes are written to I2S, there is noise.
* Below is the kind of workaround to read only in multiple of 4. Avoids noise when rb is read in small chunks.
* Note that, when we have buf_len bytes available in rb, we still read those irrespective of if it's multiple of 4.
*/
read_size = read_size & 0xfffffffc;
if ((read_size == 0) && rb->is_done_write) {
read_size = rb->fill_cnt;
}
} else {
read_size = buf_len;
}
if (read_size == 0) { //一直卡在这个。因为之前的音频元素已经暂停了。一直等待也不能把数据读出来
//no data to read, release thread block to allow other threads to write data
rb_release(rb->lock);
if (rb->is_done_write) {
ret_val = RB_DONE;
goto read_err;
}
if (rb->abort_read) {
ret_val = RB_ABORT;
goto read_err;
}
if (rb->unblock_reader_flag) {
//reader_unblock is nothing but forced timeout
ret_val = RB_TIMEOUT;
goto read_err;
}
rb_release(rb->can_write);
//wait till some data available to read
if (rb_block(rb->can_read, ticks_to_wait) != pdTRUE) {
ret_val = RB_TIMEOUT;
goto read_err;
}
continue;
}
if ((rb->p_r + read_size) > (rb->p_o + rb->size)) {
int rlen1 = rb->p_o + rb->size - rb->p_r;
int rlen2 = read_size - rlen1;
if (buf) {
memcpy(buf, rb->p_r, rlen1);
memcpy(buf + rlen1, rb->p_o, rlen2);
}
rb->p_r = rb->p_o + rlen2;
} else {
if (buf) {
memcpy(buf, rb->p_r, read_size);
}
rb->p_r = rb->p_r + read_size;
}
buf_len -= read_size;
rb->fill_cnt -= read_size;
total_read_size += read_size;
buf += read_size;
rb_release(rb->lock);
if (buf_len == 0) {
break;
}
}
read_err:
if (total_read_size > 0) {
rb_release(rb->can_write);
}
if ((ret_val == RB_FAIL) ||
(ret_val == RB_ABORT)) {
total_read_size = ret_val;
}
rb->unblock_reader_flag = false; /* We are anyway unblocking the reader */
return total_read_size > 0 ? total_read_size : ret_val;
}
但解决的方法一直没找到 。暂停老是音频元素暂停失败。
有大神能指导一下吗