Ancient AirPlay issue fixed - release

This commit is contained in:
philippe44
2020-03-01 15:49:52 -08:00
parent 1ed815466a
commit b2d90d36c1
2 changed files with 39 additions and 27 deletions

View File

@@ -57,9 +57,9 @@ typedef struct raop_ctx_s {
struct in_addr peer; // IP of the iDevice (airplay sender) struct in_addr peer; // IP of the iDevice (airplay sender)
bool running; bool running;
#ifdef WIN32 #ifdef WIN32
pthread_t thread, search_thread; pthread_t thread;
#else #else
TaskHandle_t thread, search_thread, joiner; TaskHandle_t thread, joiner;
StaticTask_t *xTaskBuffer; StaticTask_t *xTaskBuffer;
StackType_t xStack[RTSP_STACK_SIZE] __attribute__ ((aligned (4))); StackType_t xStack[RTSP_STACK_SIZE] __attribute__ ((aligned (4)));
#endif #endif
@@ -81,10 +81,11 @@ typedef struct raop_ctx_s {
char DACPid[32], id[32]; char DACPid[32], id[32];
struct in_addr host; struct in_addr host;
u16_t port; u16_t port;
bool running;
#ifdef WIN32 #ifdef WIN32
struct mDNShandle_s *handle; struct mDNShandle_s *handle;
pthread_t thread;
#else #else
bool running;
TaskHandle_t thread, joiner; TaskHandle_t thread, joiner;
StaticTask_t *xTaskBuffer; StaticTask_t *xTaskBuffer;
StackType_t xStack[SEARCH_STACK_SIZE] __attribute__ ((aligned (4)));; StackType_t xStack[SEARCH_STACK_SIZE] __attribute__ ((aligned (4)));;
@@ -240,7 +241,7 @@ void raop_delete(struct raop_ctx_s *ctx) {
rtp_end(ctx->rtp); rtp_end(ctx->rtp);
shutdown(ctx->sock, SD_BOTH); shutdown(ctx->sock, SD_BOTH);
closesocket(ctx->sock); closesocket(ctx->sock);
// terminate search, but do not reclaim memory of pthread if never launched // terminate search, but do not reclaim memory of pthread if never launched
@@ -515,7 +516,7 @@ static bool handle_rtsp(raop_ctx_t *ctx, int sock)
NFREE(p); NFREE(p);
} }
// on announce, search remote // on announce, search remote
if ((buf = kd_lookup(headers, "DACP-ID")) != NULL) strcpy(ctx->active_remote.DACPid, buf); if ((buf = kd_lookup(headers, "DACP-ID")) != NULL) strcpy(ctx->active_remote.DACPid, buf);
if ((buf = kd_lookup(headers, "Active-Remote")) != NULL) strcpy(ctx->active_remote.id, buf); if ((buf = kd_lookup(headers, "Active-Remote")) != NULL) strcpy(ctx->active_remote.id, buf);
@@ -592,7 +593,7 @@ static bool handle_rtsp(raop_ctx_t *ctx, int sock)
} else if (!strcmp(method, "TEARDOWN")) { } else if (!strcmp(method, "TEARDOWN")) {
rtp_end(ctx->rtp); rtp_end(ctx->rtp);
ctx->rtp = NULL; ctx->rtp = NULL;
// need to make sure no search is on-going and reclaim pthread memory // need to make sure no search is on-going and reclaim pthread memory
@@ -640,7 +641,7 @@ static bool handle_rtsp(raop_ctx_t *ctx, int sock)
LOG_INFO("[%p]: SET PARAMETER progress %d/%u %s", ctx, current, stop, p); LOG_INFO("[%p]: SET PARAMETER progress %d/%u %s", ctx, current, stop, p);
success = ctx->cmd_cb(RAOP_PROGRESS, max(current, 0), stop); success = ctx->cmd_cb(RAOP_PROGRESS, max(current, 0), stop);
} else if (body && ((p = kd_lookup(headers, "Content-Type")) != NULL) && !strcasecmp(p, "application/x-dmap-tagged")) { } else if (body && ((p = kd_lookup(headers, "Content-Type")) != NULL) && !strcasecmp(p, "application/x-dmap-tagged")) {
struct metadata_s metadata; struct metadata_s metadata;
dmap_settings settings = { dmap_settings settings = {
NULL, NULL, NULL, NULL, NULL, NULL, NULL, on_dmap_string, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, on_dmap_string, NULL,
NULL NULL
@@ -689,6 +690,10 @@ void abort_rtsp(raop_ctx_t *ctx) {
void abort_rtsp(raop_ctx_t *ctx) { void abort_rtsp(raop_ctx_t *ctx) {
// first stop RTP process // first stop RTP process
if (ctx->rtp) { if (ctx->rtp) {
rtp_end(ctx->rtp);
ctx->rtp = NULL;
LOG_INFO("[%p]: RTP thread aborted", ctx);
}
if (ctx->active_remote.running) { if (ctx->active_remote.running) {
#ifdef WIN32 #ifdef WIN32
@@ -698,8 +703,10 @@ void abort_rtsp(raop_ctx_t *ctx) {
// need to make sure no search is on-going and reclaim task memory // need to make sure no search is on-going and reclaim task memory
ctx->active_remote.joiner = xTaskGetCurrentTaskHandle(); ctx->active_remote.joiner = xTaskGetCurrentTaskHandle();
ctx->active_remote.running = false; ctx->active_remote.running = false;
xSemaphoreTake(ctx->active_remote.destroy_mutex, portMAX_DELAY); xSemaphoreTake(ctx->active_remote.destroy_mutex, portMAX_DELAY);
vTaskDelete(ctx->active_remote.thread); vTaskDelete(ctx->active_remote.thread);
vSemaphoreDelete(ctx->active_remote.thread);
heap_caps_free(ctx->active_remote.xTaskBuffer); heap_caps_free(ctx->active_remote.xTaskBuffer);
#endif #endif

View File

@@ -443,25 +443,23 @@ static void buffer_put_packet(rtp_t *ctx, seq_t seqno, unsigned rtptime, bool fi
abuf = ctx->audio_buffer + BUFIDX(seqno); abuf = ctx->audio_buffer + BUFIDX(seqno);
ctx->ab_write = seqno; ctx->ab_write = seqno;
LOG_SDEBUG("packet expected seqno:%hu rtptime:%u (W:%hu R:%hu)", seqno, rtptime, ctx->ab_write, ctx->ab_read); LOG_SDEBUG("packet expected seqno:%hu rtptime:%u (W:%hu R:%hu)", seqno, rtptime, ctx->ab_write, ctx->ab_read);
} else if (seq_order(ctx->ab_write, seqno)) {
seq_t i;
u32_t now; u32_t now;
// newer than expected // newer than expected
if (ctx->latency && seq_order(ctx->latency / ctx->frame_size, seqno - ctx->ab_write - 1)) { if (ctx->latency && seq_order(ctx->latency / ctx->frame_size, seqno - ctx->ab_write - 1)) {
// only get rtp latency-1 frames back (last one is seqno) // only get rtp latency-1 frames back (last one is seqno)
LOG_WARN("[%p] too many missing frames %hu seq: %hu, (W:%hu R:%hu)", ctx, seqno - ctx->ab_write - 1, seqno, ctx->ab_write, ctx->ab_read); LOG_WARN("[%p] too many missing frames %hu seq: %hu, (W:%hu R:%hu)", ctx, seqno - ctx->ab_write - 1, seqno, ctx->ab_write, ctx->ab_read);
ctx->ab_write = seqno - ctx->latency / ctx->frame_size; ctx->ab_write = seqno - ctx->latency / ctx->frame_size;
} }
if (ctx->latency && seq_order(ctx->latency / ctx->frame_size, seqno - ctx->ab_read)) {
// if ab_read is lagging more than http latency, advance it // need to request re-send and adjust timing of gaps
LOG_WARN("[%p] on hold for too long %hu (W:%hu R:%hu)", ctx, seqno - ctx->ab_read + 1, ctx->ab_write, ctx->ab_read); rtp_request_resend(ctx, ctx->ab_write + 1, seqno-1);
ctx->ab_read = seqno - ctx->latency / ctx->frame_size + 1; for (now = gettime_ms(), i = ctx->ab_write + 1; seq_order(i, seqno); i++) {
}
if (rtp_request_resend(ctx, ctx->ab_write + 1, seqno-1)) {
seq_t i;
u32_t now = gettime_ms();
for (i = ctx->ab_write + 1; seq_order(i, seqno); i++) {
ctx->audio_buffer[BUFIDX(i)].rtptime = rtptime - (seqno-i)*ctx->frame_size;
ctx->audio_buffer[BUFIDX(i)].rtptime = rtptime - (seqno-i)*ctx->frame_size; ctx->audio_buffer[BUFIDX(i)].rtptime = rtptime - (seqno-i)*ctx->frame_size;
ctx->audio_buffer[BUFIDX(i)].last_resend = now;
} }
LOG_DEBUG("[%p]: packet newer seqno:%hu rtptime:%u (W:%hu R:%hu)", ctx, seqno, rtptime, ctx->ab_write, ctx->ab_read); LOG_DEBUG("[%p]: packet newer seqno:%hu rtptime:%u (W:%hu R:%hu)", ctx, seqno, rtptime, ctx->ab_write, ctx->ab_read);
@@ -519,14 +517,21 @@ static void buffer_push_packet(rtp_t *ctx) {
if (now > playtime) { if (now > playtime) {
LOG_DEBUG("[%p]: discarded frame now:%u missed by:%d (W:%hu R:%hu)", ctx, now, now - playtime, ctx->ab_write, ctx->ab_read); LOG_DEBUG("[%p]: discarded frame now:%u missed by:%d (W:%hu R:%hu)", ctx, now, now - playtime, ctx->ab_write, ctx->ab_read);
ctx->discarded++;
curframe->ready = 0;
} else if (playtime - now <= hold) {
if (curframe->ready) {
ctx->data_cb((const u8_t*) curframe->data, curframe->len, playtime);
curframe->ready = 0;
} else {
LOG_DEBUG("[%p]: created zero frame (W:%hu R:%hu)", ctx, ctx->ab_write, ctx->ab_read);
ctx->data_cb(silence_frame, ctx->frame_size * 4, playtime);
ctx->silent_frames++; ctx->silent_frames++;
} }
} else if (curframe->ready) { } else if (curframe->ready) {
ctx->data_cb((const u8_t*) curframe->data, curframe->len, playtime); ctx->data_cb((const u8_t*) curframe->data, curframe->len, playtime);
curframe->ready = 0; curframe->ready = 0;
} else if (playtime - now <= hold) { } else {
LOG_DEBUG("[%p]: created zero frame (W:%hu R:%hu)", ctx, ctx->ab_write, ctx->ab_read);
ctx->data_cb(silence_frame, ctx->frame_size * 4, playtime);
break; break;
} }