浏览代码

fixed airplay

philippe44 5 年之前
父节点
当前提交
49dcfdc758

+ 3 - 0
components/raop/raop.c

@@ -459,6 +459,9 @@ static bool handle_rtsp(raop_ctx_t *ctx, int sock)
 		rtp_resp_t rtp = { 0 };
 		short unsigned tport = 0, cport = 0;
 
+		// we are about to stream, do something if needed
+		ctx->cmd_cb(RAOP_SETUP, NULL);
+
 		if ((p = strcasestr(buf, "timing_port")) != NULL) sscanf(p, "%*[^=]=%hu", &tport);
 		if ((p = strcasestr(buf, "control_port")) != NULL) sscanf(p, "%*[^=]=%hu", &cport);
 

+ 3 - 1
components/raop/raop_sink.h

@@ -11,7 +11,9 @@
 
 #include <stdint.h>
 
-typedef enum { RAOP_STREAM, RAOP_PLAY, RAOP_FLUSH, RAOP_PAUSE, RAOP_STOP, RAOP_VOLUME, RAOP_TIMING } raop_event_t ;
+#define RAOP_SAMPLE_RATE	44100
+
+typedef enum { RAOP_SETUP, RAOP_STREAM, RAOP_PLAY, RAOP_FLUSH, RAOP_PAUSE, RAOP_STOP, RAOP_VOLUME, RAOP_TIMING } raop_event_t ;
 
 typedef void (*raop_cmd_cb_t)(raop_event_t event, void *param);
 typedef void (*raop_data_cb_t)(const u8_t *data, size_t len);

+ 15 - 16
components/raop/rtp.c

@@ -70,7 +70,7 @@
 //#define __RTP_STORE
 
 // default buffer size
-#define BUFFER_FRAMES ( (120 * 88200) / (352 * 100) )
+#define BUFFER_FRAMES ( (150 * 88200) / (352 * 100) )
 #define MAX_PACKET    1408
 
 #define RTP_SYNC	(0x01)
@@ -126,7 +126,6 @@ typedef struct rtp_s {
 	int latency;			// rtp hold depth in samples
 	u32_t resent_req, resent_rec;	// total resent + recovered frames
 	u32_t silent_frames;	// total silence frames
-	u32_t filled_frames;    // silence frames in current silence episode
 	u32_t discarded;
 	abuf_t audio_buffer[BUFFER_FRAMES];
 	seq_t ab_read, ab_write;
@@ -141,7 +140,6 @@ typedef struct rtp_s {
 	bool playing;
 	raop_data_cb_t data_cb;
 	raop_cmd_cb_t cmd_cb;
-u16_t syncS, syncN;
 } rtp_t;
 
 
@@ -239,7 +237,7 @@ rtp_resp_t rtp_init(struct in_addr host, int latency, char *aeskey, char *aesiv,
 	while ((arg = strsep(&fmtpstr, " \t")) != NULL) fmtp[i++] = atoi(arg);
 
 	ctx->frame_size = fmtp[1];
-	ctx->frame_duration = (ctx->frame_size * 1000) / 44100;
+	ctx->frame_duration = (ctx->frame_size * 1000) / RAOP_SAMPLE_RATE;
 
 	// alac decoder
 	ctx->alac_codec = alac_init(fmtp);
@@ -461,14 +459,14 @@ static void buffer_put_packet(rtp_t *ctx, seq_t seqno, unsigned rtptime, bool fi
 		abuf->ready = 1;
 		// this is the local rtptime when this frame is expected to play
 		abuf->rtptime = rtptime;
+		buffer_push_packet(ctx);
+
 #ifdef __RTP_STORE
 		fwrite(data, len, 1, ctx->rtpIN);
 		fwrite(abuf->data, abuf->len, 1, ctx->rtpOUT);
 #endif
 	}
 
-	buffer_push_packet(ctx);
-
 	pthread_mutex_unlock(&ctx->ab_mutex);
 }
 
@@ -476,7 +474,7 @@ static void buffer_put_packet(rtp_t *ctx, seq_t seqno, unsigned rtptime, bool fi
 // push as many frames as possible through callback
 static void buffer_push_packet(rtp_t *ctx) {
 	abuf_t *curframe = NULL;
-	u32_t now, playtime, hold = max((ctx->latency * 1000) / (8 * 44100), 100);
+	u32_t now, playtime, hold = max((ctx->latency * 1000) / (8 * RAOP_SAMPLE_RATE), 100);
 	int i;
 
 	// not ready to play yet
@@ -489,10 +487,10 @@ static void buffer_push_packet(rtp_t *ctx) {
 	do {
 
 		curframe = ctx->audio_buffer + BUFIDX(ctx->ab_read);
-		playtime = ctx->synchro.time + (((s32_t)(curframe->rtptime - ctx->synchro.rtp)) * 10) / 441;
+		playtime = ctx->synchro.time + (((s32_t)(curframe->rtptime - ctx->synchro.rtp)) * 1000) / RAOP_SAMPLE_RATE;
 
 		if (now > playtime) {
-			LOG_INFO("[%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++;
 		} else if (curframe->ready) {
 			ctx->data_cb((const u8_t*) curframe->data, curframe->len);
@@ -506,12 +504,13 @@ static void buffer_push_packet(rtp_t *ctx) {
 		ctx->ab_read++;
 		ctx->out_frames++;
 
-	} while (ctx->ab_write - ctx->ab_read + 1 > 0);
+	// need to be promoted to a signed int *before* addition
+	} while ((s16_t) (ctx->ab_write - ctx->ab_read) + 1 > 0);
 
 	if (ctx->out_frames > 1000) {
-		LOG_INFO("[%p]: drain [level:%hd gap:%d] [W:%hu R:%hu] [R:%u S:%u F:%u D:%u] (head in %u ms) ",
+		LOG_INFO("[%p]: drain [level:%hd head:%d ms] [W:%hu R:%hu] [req:%u sil:%u dis:%u]",
 				ctx, ctx->ab_write - ctx->ab_read, playtime - now, ctx->ab_write, ctx->ab_read,
-				ctx->resent_req, ctx->silent_frames, ctx->filled_frames, ctx->discarded, playtime - now);
+				ctx->resent_req, ctx->silent_frames, ctx->discarded);
 		ctx->out_frames = 0;
 	}
 
@@ -614,7 +613,7 @@ static void *rtp_thread_func(void *arg) {
 				pthread_mutex_lock(&ctx->ab_mutex);
 
 				// re-align timestamp and expected local playback time (and magic 11025 latency)
-				if (!ctx->latency) ctx->latency = rtp_now - rtp_now_latency + 11025;
+				ctx->latency = rtp_now - rtp_now_latency + 11025;
 				ctx->synchro.rtp = rtp_now - ctx->latency;
 				ctx->synchro.time = ctx->timing.local + (u32_t) NTP2MS(remote - ctx->timing.remote);
 
@@ -628,8 +627,8 @@ static void *rtp_thread_func(void *arg) {
 
 				pthread_mutex_unlock(&ctx->ab_mutex);
 
-				LOG_DEBUG("[%p]: sync packet rtp_latency:%u rtp:%u remote ntp:%Lx, local time %u (now:%u)",
-						  ctx, rtp_now_latency, rtp_now, remote, ctx->synchro.time, gettime_ms());
+				LOG_DEBUG("[%p]: sync packet latency:%d rtp_latency:%u rtp:%u remote ntp:%llx, local time:%u local rtp:%u (now:%u)",
+						  ctx, ctx->latency, rtp_now_latency, rtp_now, remote, ctx->synchro.time, ctx->synchro.rtp, gettime_ms());
 
 				if (!count--) {
 					rtp_request_timing(ctx);
@@ -670,7 +669,7 @@ static void *rtp_thread_func(void *arg) {
 				// now we are synced on NTP (mutex not needed)
 				ctx->synchro.status |= NTP_SYNC;
 
-				LOG_DEBUG("[%p]: Timing references local:%Lu, remote:%Lx (delta:%Ld, sum:%Ld, adjust:%Ld, gaps:%d)",
+				LOG_DEBUG("[%p]: Timing references local:%llu, remote:%llx (delta:%lld, sum:%lld, adjust:%lld, gaps:%d)",
 						  ctx, ctx->timing.local, ctx->timing.remote);
 
 				break;

+ 1 - 0
components/squeezelite/buffer.c

@@ -83,6 +83,7 @@ void buf_adjust(struct buffer *buf, size_t mod) {
 
 // called with mutex locked to resize, does not retain contents, reverts to original size if fails
 void _buf_resize(struct buffer *buf, size_t size) {
+	if (size == buf->size) return;
 	free(buf->buf);
 	buf->buf = malloc(size);
 	if (!buf->buf) {

+ 12 - 5
components/squeezelite/decode_external.c

@@ -34,6 +34,8 @@ extern struct buffer *outputbuf;
 // this is the only system-wide loglevel variable
 extern log_level loglevel;
 
+#define RAOP_OUTPUT_SIZE (RAOP_SAMPLE_RATE * 2 * 2 * 2 * 1.2)
+
 static raop_event_t	raop_state;
 static bool raop_expect_stop = false;
 static struct {
@@ -165,29 +167,34 @@ void raop_sink_cmd_handler(raop_event_t event, void *param)
 			
 			raop_sync.total += *(s32_t*) param;
 			raop_sync.count++;
-			raop_sync.msplayed = now - output.updated + ((u64_t) (output.frames_played_dmp - output.device_frames) * 1000) / 44100;
+			raop_sync.msplayed = now - output.updated + ((u64_t) (output.frames_played_dmp - output.device_frames) * 1000) / RAOP_SAMPLE_RATE;
 			error = raop_sync.msplayed - (now - raop_sync.start_time);
-		
+			
+			LOG_INFO("now:%u updated:%u played_dmp:%u device:%u", now, output.updated, output.frames_played_dmp, output.device_frames);
 			LOG_INFO("backend played %u, desired %u, (delta:%d raop:%d)", raop_sync.msplayed, now - raop_sync.start_time, error, raop_sync.total / raop_sync.count);
 			
 			if (error < -10) {
-				output.skip_frames = (abs(error) * 44100) / 1000;
+				output.skip_frames = (abs(error) * RAOP_SAMPLE_RATE) / 1000;
 				output.state = OUTPUT_SKIP_FRAMES;					
 				LOG_INFO("skipping %u frames", output.skip_frames);
 			} else if (error > 10) {
-				output.pause_frames = (abs(error) * 44100) / 1000;
+				output.pause_frames = (abs(error) * RAOP_SAMPLE_RATE) / 1000;
 				output.state = OUTPUT_PAUSE_FRAMES;
 				LOG_INFO("pausing for %u frames", output.pause_frames);
 			}
 						
 			break;
 		}
+		case RAOP_SETUP:
+			_buf_resize(outputbuf, RAOP_OUTPUT_SIZE);
+			LOG_INFO("resizing buffer %u", outputbuf->size);
+			break;
 		case RAOP_STREAM:
 			LOG_INFO("Stream", NULL);
 			raop_state = event;
 			raop_sync.total = raop_sync.count = 0;			
 			output.external = true;
-			output.next_sample_rate = 44100;
+			output.next_sample_rate = RAOP_SAMPLE_RATE;
 			output.state = OUTPUT_STOPPED;
 			break;
 		case RAOP_STOP:

+ 1 - 0
components/squeezelite/output.c

@@ -347,6 +347,7 @@ void output_init_common(log_level level, const char *device, unsigned output_buf
 	loglevel = level;
 
 	output_buf_size = output_buf_size - (output_buf_size % BYTES_PER_FRAME);
+	output.init_size = output_buf_size;
 	LOG_DEBUG("outputbuf size: %u", output_buf_size);
 
 	buf_init(outputbuf, output_buf_size);

+ 4 - 1
components/squeezelite/slimproto.c

@@ -371,7 +371,10 @@ static void process_strm(u8_t *pkt, int len) {
 			sendSTAT("STMc", 0);
 			sentSTMu = sentSTMo = sentSTMl = false;
 			LOCK_O;
-			output.external = false;
+			if (output.external) {
+				output.external = false;
+				_buf_resize(outputbuf, output.init_size);
+			}	
 			output.threshold = strm->output_threshold;
 			output.next_replay_gain = unpackN(&strm->replay_gain);
 			output.fade_mode = strm->transition_type - '0';

+ 1 - 0
components/squeezelite/squeezelite.h

@@ -656,6 +656,7 @@ struct outputstate {
 	output_format format;
 	const char *device;
 	bool external;
+	u32_t init_size;
 #if ALSA
 	unsigned buffer;
 	unsigned period;