diff --git a/components/raop/raop.c b/components/raop/raop.c index 4d824f7e..ffce9b46 100644 --- a/components/raop/raop.c +++ b/components/raop/raop.c @@ -57,9 +57,9 @@ typedef struct raop_ctx_s { struct in_addr peer; // IP of the iDevice (airplay sender) bool running; #ifdef WIN32 - pthread_t thread, search_thread; + pthread_t thread; #else - TaskHandle_t thread, search_thread, joiner; + TaskHandle_t thread, joiner; StaticTask_t *xTaskBuffer; StackType_t xStack[RTSP_STACK_SIZE] __attribute__ ((aligned (4))); #endif @@ -81,10 +81,11 @@ typedef struct raop_ctx_s { char DACPid[32], id[32]; struct in_addr host; u16_t port; + bool running; #ifdef WIN32 struct mDNShandle_s *handle; + pthread_t thread; #else - bool running; TaskHandle_t thread, joiner; StaticTask_t *xTaskBuffer; StackType_t xStack[SEARCH_STACK_SIZE] __attribute__ ((aligned (4)));; @@ -218,7 +219,7 @@ void raop_delete(struct raop_ctx_s *ctx) { struct sockaddr addr; socklen_t nlen = sizeof(struct sockaddr); #endif - + if (!ctx) return; #ifdef WIN32 @@ -240,7 +241,7 @@ void raop_delete(struct raop_ctx_s *ctx) { // terminate search, but do not reclaim memory of pthread if never launched if (ctx->active_remote.handle) { close_mDNS(ctx->active_remote.handle); - pthread_join(ctx->search_thread, NULL); + pthread_join(ctx->active_remote.thread, NULL); } // stop broadcasting devices @@ -515,7 +516,7 @@ static bool handle_rtsp(raop_ctx_t *ctx, int sock) #ifdef WIN32 ctx->active_remote.handle = init_mDNS(false, ctx->host); - pthread_create(&ctx->search_thread, NULL, &search_remote, ctx); + pthread_create(&ctx->active_remote.thread, NULL, &search_remote, ctx); #else ctx->active_remote.running = true; ctx->active_remote.destroy_mutex = xSemaphoreCreateMutex(); @@ -592,7 +593,7 @@ static bool handle_rtsp(raop_ctx_t *ctx, int sock) // need to make sure no search is on-going and reclaim pthread memory #ifdef WIN32 if (ctx->active_remote.handle) close_mDNS(ctx->active_remote.handle); - pthread_join(ctx->search_thread, NULL); + pthread_join(ctx->active_remote.thread, NULL); #else ctx->active_remote.joiner = xTaskGetCurrentTaskHandle(); ctx->active_remote.running = false; @@ -640,7 +641,7 @@ static bool handle_rtsp(raop_ctx_t *ctx, int sock) NULL }; - LOG_INFO("[%p]: received metadata"); + LOG_INFO("[%p]: received metadata", ctx); settings.ctx = &metadata; memset(&metadata, 0, sizeof(struct metadata_s)); if (!dmap_parse(&settings, body, len)) { @@ -686,9 +687,13 @@ void abort_rtsp(raop_ctx_t *ctx) { rtp_end(ctx->rtp); ctx->rtp = NULL; LOG_INFO("[%p]: RTP thread aborted", ctx); - } + } if (ctx->active_remote.running) { +#ifdef WIN32 + pthread_join(ctx->active_remote.thread, NULL); + close_mDNS(ctx->active_remote.handle); +#else // need to make sure no search is on-going and reclaim task memory ctx->active_remote.joiner = xTaskGetCurrentTaskHandle(); ctx->active_remote.running = false; @@ -698,8 +703,10 @@ void abort_rtsp(raop_ctx_t *ctx) { vSemaphoreDelete(ctx->active_remote.thread); heap_caps_free(ctx->active_remote.xTaskBuffer); +#endif memset(&ctx->active_remote, 0, sizeof(ctx->active_remote)); + LOG_INFO("[%p]: Remote search thread aborted", ctx); } diff --git a/components/raop/rtp.c b/components/raop/rtp.c index beccdda9..0a3b6b3f 100644 --- a/components/raop/rtp.c +++ b/components/raop/rtp.c @@ -443,25 +443,23 @@ static void buffer_put_packet(rtp_t *ctx, seq_t seqno, unsigned rtptime, bool fi 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; + // newer than expected 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) 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; } - 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 - 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); - ctx->ab_read = seqno - ctx->latency / ctx->frame_size + 1; - } - 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)].last_resend = now; - } + + // need to request re-send and adjust timing of gaps + rtp_request_resend(ctx, ctx->ab_write + 1, seqno-1); + for (now = gettime_ms(), 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)].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); abuf = ctx->audio_buffer + BUFIDX(seqno); ctx->ab_write = seqno; @@ -519,14 +517,21 @@ static void buffer_push_packet(rtp_t *ctx) { 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++; + } } else if (curframe->ready) { ctx->data_cb((const u8_t*) curframe->data, curframe->len, playtime); curframe->ready = 0; - } else if (playtime - now <= hold) { - 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++; - } else break; + } else { + break; + } ctx->ab_read++; ctx->out_frames++; @@ -637,7 +642,7 @@ static void *rtp_thread_func(void *arg) { u32_t rtp_now = ntohl(*(u32_t*)(pktp+16)); u16_t flags = ntohs(*(u16_t*)(pktp+2)); u32_t remote_gap = NTP2MS(remote - ctx->timing.remote); - + // something is wrong and if we are supposed to be NTP synced, better ask for re-sync if (remote_gap > 10000) { if (ctx->synchro.status & NTP_SYNC) rtp_request_timing(ctx);