]>
Commit | Line | Data |
---|---|---|
cf8401db JL |
1 | /* |
2 | * Apple RTP protocol handler. This file is part of Shairport. | |
3 | * Copyright (c) James Laird 2013 | |
89340f20 | 4 | * Copyright (c) Mike Brady 2014 -- 2019 |
cf8401db JL |
5 | * All rights reserved. |
6 | * | |
7 | * Permission is hereby granted, free of charge, to any person | |
8 | * obtaining a copy of this software and associated documentation | |
9 | * files (the "Software"), to deal in the Software without | |
10 | * restriction, including without limitation the rights to use, | |
11 | * copy, modify, merge, publish, distribute, sublicense, and/or | |
12 | * sell copies of the Software, and to permit persons to whom the | |
13 | * Software is furnished to do so, subject to the following conditions: | |
14 | * | |
15 | * The above copyright notice and this permission notice shall be | |
16 | * included in all copies or substantial portions of the Software. | |
17 | * | |
18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
19 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES | |
20 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
21 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT | |
22 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, | |
23 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | |
24 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | |
25 | * OTHER DEALINGS IN THE SOFTWARE. | |
26 | */ | |
27 | ||
8bf83c14 MB |
28 | #include "rtp.h" |
29 | #include "common.h" | |
30 | #include "player.h" | |
31 | #include "rtsp.h" | |
2cded85d | 32 | #include <arpa/inet.h> |
064bd293 | 33 | #include <errno.h> |
3198ec42 | 34 | #include <fcntl.h> |
8bf83c14 | 35 | #include <inttypes.h> |
064bd293 MB |
36 | #include <math.h> |
37 | #include <memory.h> | |
a2fb5d21 | 38 | #include <netdb.h> |
064bd293 MB |
39 | #include <netinet/in.h> |
40 | #include <pthread.h> | |
7bf5d4d6 | 41 | #include <stdio.h> |
d9c9009f | 42 | #include <stdlib.h> |
064bd293 MB |
43 | #include <sys/socket.h> |
44 | #include <sys/types.h> | |
45 | #include <time.h> | |
46 | #include <unistd.h> | |
8a73d597 MB |
47 | #ifdef CONFIG_AIRPLAY_2 |
48 | #include "ptp-utilities.h" | |
49 | #include <libavcodec/avcodec.h> | |
50 | #include <libavformat/avformat.h> | |
51 | #include <libavutil/opt.h> | |
52 | #include <libswresample/swresample.h> | |
53 | #include <sodium.h> | |
54 | #endif | |
55 | ||
f5eceff6 | 56 | struct Nvll { |
ca562872 MB |
57 | char *name; |
58 | double value; | |
59 | struct Nvll *next; | |
f5eceff6 MB |
60 | }; |
61 | ||
62 | typedef struct Nvll nvll; | |
63 | ||
3870195c MB |
64 | uint64_t local_to_remote_time_jitter; |
65 | uint64_t local_to_remote_time_jitter_count; | |
73bf006c | 66 | |
8a73d597 MB |
67 | typedef struct { |
68 | int closed; | |
69 | int error_code; | |
70 | int sock_fd; | |
71 | char *buffer; | |
72 | char *toq; | |
73 | char *eoq; | |
74 | size_t buffer_max_size; | |
75 | size_t buffer_occupancy; | |
76 | pthread_mutex_t mutex; | |
77 | pthread_cond_t not_empty_cv; | |
78 | pthread_cond_t not_full_cv; | |
79 | } buffered_tcp_desc; | |
80 | ||
c37f5113 MB |
81 | void check64conversion(const char *prompt, const uint8_t *source, uint64_t value) { |
82 | char converted_value[128]; | |
a382ac66 MB |
83 | sprintf(converted_value, "%" PRIx64 "", value); |
84 | ||
c37f5113 MB |
85 | char obf[32]; |
86 | char *obfp = obf; | |
87 | int obfc; | |
88 | int suppress_zeroes = 1; | |
a382ac66 MB |
89 | for (obfc = 0; obfc < 8; obfc++) { |
90 | if ((suppress_zeroes == 0) || (source[obfc] != 0)) { | |
c37f5113 MB |
91 | if (suppress_zeroes != 0) { |
92 | if (source[obfc] < 0x10) { | |
e07c202b | 93 | snprintf(obfp, 3, "%1x", source[obfc]); |
a382ac66 | 94 | obfp += 1; |
c37f5113 | 95 | } else { |
a382ac66 MB |
96 | snprintf(obfp, 3, "%02x", source[obfc]); |
97 | obfp += 2; | |
c37f5113 MB |
98 | } |
99 | } else { | |
100 | snprintf(obfp, 3, "%02x", source[obfc]); | |
a382ac66 | 101 | obfp += 2; |
c37f5113 MB |
102 | } |
103 | suppress_zeroes = 0; | |
104 | } | |
105 | }; | |
a382ac66 MB |
106 | *obfp = 0; |
107 | if (strcmp(converted_value, obf) != 0) { | |
108 | debug(1, "%s check64conversion error converting \"%s\" to %" PRIx64 ".", prompt, obf, value); | |
c37f5113 MB |
109 | } |
110 | } | |
111 | ||
112 | void check32conversion(const char *prompt, const uint8_t *source, uint32_t value) { | |
113 | char converted_value[128]; | |
a382ac66 MB |
114 | sprintf(converted_value, "%" PRIx32 "", value); |
115 | ||
c37f5113 MB |
116 | char obf[32]; |
117 | char *obfp = obf; | |
118 | int obfc; | |
119 | int suppress_zeroes = 1; | |
a382ac66 MB |
120 | for (obfc = 0; obfc < 4; obfc++) { |
121 | if ((suppress_zeroes == 0) || (source[obfc] != 0)) { | |
c37f5113 MB |
122 | if (suppress_zeroes != 0) { |
123 | if (source[obfc] < 0x10) { | |
e07c202b | 124 | snprintf(obfp, 3, "%1x", source[obfc]); |
a382ac66 | 125 | obfp += 1; |
c37f5113 | 126 | } else { |
a382ac66 MB |
127 | snprintf(obfp, 3, "%02x", source[obfc]); |
128 | obfp += 2; | |
c37f5113 MB |
129 | } |
130 | } else { | |
131 | snprintf(obfp, 3, "%02x", source[obfc]); | |
a382ac66 | 132 | obfp += 2; |
c37f5113 MB |
133 | } |
134 | suppress_zeroes = 0; | |
135 | } | |
136 | }; | |
a382ac66 MB |
137 | *obfp = 0; |
138 | if (strcmp(converted_value, obf) != 0) { | |
139 | debug(1, "%s check32conversion error converting \"%s\" to %" PRIx32 ".", prompt, obf, value); | |
c37f5113 MB |
140 | } |
141 | } | |
142 | ||
e513e533 | 143 | void rtp_initialise(rtsp_conn_info *conn) { |
40289ca6 | 144 | conn->rtp_time_of_last_resend_request_error_ns = 0; |
f3d85bc7 | 145 | conn->rtp_running = 0; |
e513e533 | 146 | // initialise the timer mutex |
e4d5570e MB |
147 | int rc = pthread_mutex_init(&conn->reference_time_mutex, NULL); |
148 | if (rc) | |
149 | debug(1, "Error initialising reference_time_mutex."); | |
e4d5570e MB |
150 | } |
151 | ||
e513e533 | 152 | void rtp_terminate(rtsp_conn_info *conn) { |
8a73d597 | 153 | conn->anchor_rtptime = 0; |
e513e533 | 154 | // destroy the timer mutex |
e4d5570e MB |
155 | int rc = pthread_mutex_destroy(&conn->reference_time_mutex); |
156 | if (rc) | |
157 | debug(1, "Error destroying reference_time_mutex variable."); | |
158 | } | |
159 | ||
3870195c MB |
160 | uint64_t local_to_remote_time_difference_now(rtsp_conn_info *conn) { |
161 | // this is an attempt to compensate for clock drift since the last time ping that was used | |
162 | // so, if we have a non-zero clock drift, we will calculate the drift there would | |
163 | // be from the time of the last time ping | |
5141e2f5 | 164 | uint64_t time_since_last_local_to_remote_time_difference_measurement = |
40289ca6 MB |
165 | get_absolute_time_in_ns() - conn->local_to_remote_time_difference_measurement_time; |
166 | ||
167 | uint64_t result = conn->local_to_remote_time_difference; | |
168 | if (conn->local_to_remote_time_gradient >= 1.0) { | |
54d761ff MB |
169 | result = conn->local_to_remote_time_difference + |
170 | (uint64_t)((conn->local_to_remote_time_gradient - 1.0) * | |
171 | time_since_last_local_to_remote_time_difference_measurement); | |
40289ca6 | 172 | } else { |
54d761ff MB |
173 | result = conn->local_to_remote_time_difference - |
174 | (uint64_t)((1.0 - conn->local_to_remote_time_gradient) * | |
175 | time_since_last_local_to_remote_time_difference_measurement); | |
40289ca6 MB |
176 | } |
177 | return result; | |
3870195c MB |
178 | } |
179 | ||
0eac2b9c MB |
180 | void rtp_audio_receiver_cleanup_handler(__attribute__((unused)) void *arg) { |
181 | debug(3, "Audio Receiver Cleanup Done."); | |
7d0eb379 | 182 | } |
87a0475c | 183 | |
7d0eb379 | 184 | void *rtp_audio_receiver(void *arg) { |
953ad8ac | 185 | debug(3, "rtp_audio_receiver start"); |
7d0eb379 | 186 | pthread_cleanup_push(rtp_audio_receiver_cleanup_handler, arg); |
e513e533 | 187 | rtsp_conn_info *conn = (rtsp_conn_info *)arg; |
21fb39d2 | 188 | |
87a0475c MB |
189 | int32_t last_seqno = -1; |
190 | uint8_t packet[2048], *pktp; | |
191 | ||
32427423 | 192 | uint64_t time_of_previous_packet_ns = 0; |
c235dc30 | 193 | float longest_packet_time_interval_us = 0.0; |
064bd293 MB |
194 | |
195 | // mean and variance calculations from "online_variance" algorithm at | |
196 | // https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Online_algorithm | |
197 | ||
c235dc30 MB |
198 | int32_t stat_n = 0; |
199 | float stat_mean = 0.0; | |
200 | float stat_M2 = 0.0; | |
064bd293 | 201 | |
87a0475c | 202 | ssize_t nread; |
7d0eb379 | 203 | while (1) { |
04cb1d09 | 204 | nread = recv(conn->audio_socket, packet, sizeof(packet), 0); |
064bd293 | 205 | |
32427423 MB |
206 | uint64_t local_time_now_ns = get_absolute_time_in_ns(); |
207 | if (time_of_previous_packet_ns) { | |
54d761ff | 208 | float time_interval_us = (local_time_now_ns - time_of_previous_packet_ns) * 0.001; |
32427423 | 209 | time_of_previous_packet_ns = local_time_now_ns; |
064bd293 MB |
210 | if (time_interval_us > longest_packet_time_interval_us) |
211 | longest_packet_time_interval_us = time_interval_us; | |
212 | stat_n += 1; | |
c235dc30 | 213 | float stat_delta = time_interval_us - stat_mean; |
064bd293 MB |
214 | stat_mean += stat_delta / stat_n; |
215 | stat_M2 += stat_delta * (time_interval_us - stat_mean); | |
14bfba27 | 216 | if ((stat_n != 1) && (stat_n % 2500 == 0)) { |
54d761ff MB |
217 | debug(2, |
218 | "Packet reception interval stats: mean, standard deviation and max for the last " | |
219 | "2,500 packets in microseconds: %10.1f, %10.1f, %10.1f.", | |
064bd293 | 220 | stat_mean, sqrtf(stat_M2 / (stat_n - 1)), longest_packet_time_interval_us); |
c235dc30 MB |
221 | stat_n = 0; |
222 | stat_mean = 0.0; | |
223 | stat_M2 = 0.0; | |
32427423 | 224 | time_of_previous_packet_ns = 0; |
c235dc30 MB |
225 | longest_packet_time_interval_us = 0.0; |
226 | } | |
227 | } else { | |
32427423 | 228 | time_of_previous_packet_ns = local_time_now_ns; |
c235dc30 MB |
229 | } |
230 | ||
e76a6366 MB |
231 | if (nread >= 0) { |
232 | ssize_t plen = nread; | |
233 | uint8_t type = packet[1] & ~0x80; | |
234 | if (type == 0x60 || type == 0x56) { // audio data / resend | |
235 | pktp = packet; | |
236 | if (type == 0x56) { | |
237 | pktp += 4; | |
238 | plen -= 4; | |
239 | } | |
240 | seq_t seqno = ntohs(*(uint16_t *)(pktp + 2)); | |
241 | // increment last_seqno and see if it's the same as the incoming seqno | |
242 | ||
243 | if (type == 0x60) { // regular audio data | |
998e7cea MB |
244 | |
245 | /* | |
3709ac81 MB |
246 | char obf[4096]; |
247 | char *obfp = obf; | |
248 | int obfc; | |
249 | for (obfc=0;obfc<plen;obfc++) { | |
250 | snprintf(obfp, 3, "%02X", pktp[obfc]); | |
251 | obfp+=2; | |
252 | }; | |
253 | *obfp=0; | |
254 | debug(1,"Audio Packet Received: \"%s\"",obf); | |
998e7cea MB |
255 | */ |
256 | ||
e76a6366 MB |
257 | if (last_seqno == -1) |
258 | last_seqno = seqno; | |
259 | else { | |
260 | last_seqno = (last_seqno + 1) & 0xffff; | |
261 | // if (seqno != last_seqno) | |
262 | // debug(3, "RTP: Packets out of sequence: expected: %d, got %d.", last_seqno, seqno); | |
263 | last_seqno = seqno; // reset warning... | |
264 | } | |
265 | } else { | |
3e72bb21 | 266 | debug(3, "Audio Receiver -- Retransmitted Audio Data Packet %u received.", seqno); |
c40d1ad5 | 267 | } |
d9c9009f | 268 | |
49d5486d | 269 | uint32_t actual_timestamp = ntohl(*(uint32_t *)(pktp + 4)); |
998e7cea | 270 | |
093bf1dd MB |
271 | // uint32_t ssid = ntohl(*(uint32_t *)(pktp + 8)); |
272 | // debug(1, "Audio packet SSID: %08X,%u", ssid,ssid); | |
87a0475c | 273 | |
e76a6366 MB |
274 | // if (packet[1]&0x10) |
275 | // debug(1,"Audio packet Extension bit set."); | |
87a0475c | 276 | |
e76a6366 MB |
277 | pktp += 12; |
278 | plen -= 12; | |
87a0475c | 279 | |
e76a6366 MB |
280 | // check if packet contains enough content to be reasonable |
281 | if (plen >= 16) { | |
282 | if ((config.diagnostic_drop_packet_fraction == 0.0) || | |
283 | (drand48() > config.diagnostic_drop_packet_fraction)) | |
bdfb1c6e | 284 | player_put_packet(1, seqno, actual_timestamp, pktp, plen, |
8a73d597 | 285 | conn); // the '1' means is original format |
e76a6366 | 286 | else |
3e72bb21 | 287 | debug(3, "Dropping audio packet %u to simulate a bad connection.", seqno); |
e76a6366 MB |
288 | continue; |
289 | } | |
290 | if (type == 0x56 && seqno == 0) { | |
291 | debug(2, "resend-related request packet received, ignoring."); | |
292 | continue; | |
293 | } | |
294 | debug(1, "Audio receiver -- Unknown RTP packet of type 0x%02X length %d seqno %d", type, | |
295 | nread, seqno); | |
87a0475c | 296 | } |
e76a6366 MB |
297 | warn("Audio receiver -- Unknown RTP packet of type 0x%02X length %d.", type, nread); |
298 | } else { | |
8a73d597 MB |
299 | char em[1024]; |
300 | strerror_r(errno, em, sizeof(em)); | |
301 | debug(1, "Error %d receiving an audio packet: \"%s\".", errno, em); | |
a2fb5d21 | 302 | } |
87a0475c | 303 | } |
a2fb5d21 | 304 | |
7d0eb379 | 305 | /* |
0a29b612 | 306 | debug(3, "Audio receiver -- Server RTP thread interrupted. terminating."); |
04cb1d09 | 307 | close(conn->audio_socket); |
7d0eb379 | 308 | */ |
8a5a29e2 | 309 | |
7d0eb379 MB |
310 | debug(1, "Audio receiver thread \"normal\" exit -- this can't happen. Hah!"); |
311 | pthread_cleanup_pop(0); // don't execute anything here. | |
312 | debug(2, "Audio receiver thread exit."); | |
313 | pthread_exit(NULL); | |
314 | } | |
a2fb5d21 | 315 | |
0eac2b9c | 316 | void rtp_control_handler_cleanup_handler(__attribute__((unused)) void *arg) { |
04c7f845 | 317 | debug(2, "Control Receiver Cleanup Done."); |
a2fb5d21 JL |
318 | } |
319 | ||
e513e533 | 320 | void *rtp_control_receiver(void *arg) { |
953ad8ac | 321 | debug(2, "rtp_control_receiver start"); |
7d0eb379 | 322 | pthread_cleanup_push(rtp_control_handler_cleanup_handler, arg); |
e513e533 | 323 | rtsp_conn_info *conn = (rtsp_conn_info *)arg; |
21fb39d2 | 324 | |
8a73d597 | 325 | conn->anchor_rtptime = 0; // nothing valid received yet |
7bc6d088 | 326 | uint8_t packet[2048], *pktp; |
07e46565 MB |
327 | // struct timespec tn; |
328 | uint64_t remote_time_of_sync; | |
de071aef | 329 | uint32_t sync_rtp_timestamp; |
87a0475c | 330 | ssize_t nread; |
7d0eb379 | 331 | while (1) { |
04cb1d09 | 332 | nread = recv(conn->control_socket, packet, sizeof(packet), 0); |
fd880056 MB |
333 | if (conn->rtsp_link_is_idle == 0) { |
334 | if (nread >= 0) { | |
335 | if ((config.diagnostic_drop_packet_fraction == 0.0) || | |
336 | (drand48() > config.diagnostic_drop_packet_fraction)) { | |
87a0475c | 337 | |
fd880056 MB |
338 | ssize_t plen = nread; |
339 | if (packet[1] == 0xd4) { // sync data | |
340 | // clang-format off | |
341 | /* | |
342 | // the following stanza is for debugging only -- normally commented out. | |
343 | { | |
344 | char obf[4096]; | |
345 | char *obfp = obf; | |
346 | int obfc; | |
347 | for (obfc = 0; obfc < plen; obfc++) { | |
348 | snprintf(obfp, 3, "%02X", packet[obfc]); | |
349 | obfp += 2; | |
350 | }; | |
351 | *obfp = 0; | |
352 | ||
353 | ||
354 | // get raw timestamp information | |
355 | // I think that a good way to understand these timestamps is that | |
356 | // (1) the rtlt below is the timestamp of the frame that should be playing at the | |
357 | // client-time specified in the packet if there was no delay | |
358 | // and (2) that the rt below is the timestamp of the frame that should be playing | |
359 | // at the client-time specified in the packet on this device taking account of | |
360 | // the delay | |
361 | // Thus, (3) the latency can be calculated by subtracting the second from the | |
362 | // first. | |
363 | // There must be more to it -- there something missing. | |
364 | ||
365 | // In addition, it seems that if the value of the short represented by the second | |
366 | // pair of bytes in the packet is 7 | |
367 | // then an extra time lag is expected to be added, presumably by | |
368 | // the AirPort Express. | |
369 | ||
370 | // Best guess is that this delay is 11,025 frames. | |
371 | ||
372 | uint32_t rtlt = nctohl(&packet[4]); // raw timestamp less latency | |
373 | uint32_t rt = nctohl(&packet[16]); // raw timestamp | |
374 | ||
375 | uint32_t fl = nctohs(&packet[2]); // | |
376 | ||
377 | debug(1,"Sync Packet of %d bytes received: \"%s\", flags: %d, timestamps %u and %u, | |
378 | giving a latency of %d frames.",plen,obf,fl,rt,rtlt,rt-rtlt); | |
379 | //debug(1,"Monotonic timestamps are: %" PRId64 " and %" PRId64 " | |
380 | respectively.",monotonic_timestamp(rt, conn),monotonic_timestamp(rtlt, conn)); | |
381 | } | |
382 | */ | |
383 | // clang-format off | |
384 | if (conn->local_to_remote_time_difference) { // need a time packet to be interchanged | |
385 | // first... | |
386 | uint64_t ps, pn; | |
e76a6366 | 387 | |
fd880056 MB |
388 | ps = nctohl(&packet[8]); |
389 | ps = ps * 1000000000; // this many nanoseconds from the whole seconds | |
390 | pn = nctohl(&packet[12]); | |
391 | pn = pn * 1000000000; | |
392 | pn = pn >> 32; // this many nanoseconds from the fractional part | |
393 | remote_time_of_sync = ps + pn; | |
e76a6366 | 394 | |
fd880056 | 395 | // debug(1,"Remote Sync Time: " PRIu64 "",remote_time_of_sync); |
e76a6366 | 396 | |
fd880056 MB |
397 | sync_rtp_timestamp = nctohl(&packet[16]); |
398 | uint32_t rtp_timestamp_less_latency = nctohl(&packet[4]); | |
e76a6366 | 399 | |
fd880056 | 400 | // debug(1,"Sync timestamp is %u.",ntohl(*((uint32_t *)&packet[16]))); |
21e1e12c | 401 | |
fd880056 MB |
402 | if (config.userSuppliedLatency) { |
403 | if (config.userSuppliedLatency != conn->latency) { | |
404 | debug(1, "Using the user-supplied latency: %" PRIu32 ".", | |
405 | config.userSuppliedLatency); | |
406 | } | |
407 | conn->latency = config.userSuppliedLatency; | |
408 | } else { | |
e76a6366 | 409 | |
fd880056 MB |
410 | // It seems that the second pair of bytes in the packet indicate whether a fixed |
411 | // delay of 11,025 frames should be added -- iTunes set this field to 7 and | |
412 | // AirPlay sets it to 4. | |
e76a6366 | 413 | |
fd880056 | 414 | // However, on older versions of AirPlay, the 11,025 frames seem to be necessary too |
e0a4e5cd | 415 | |
fd880056 MB |
416 | // The value of 11,025 (0.25 seconds) is a guess based on the "Audio-Latency" |
417 | // parameter | |
418 | // returned by an AE. | |
e76a6366 | 419 | |
fd880056 MB |
420 | // Sigh, it would be nice to have a published protocol... |
421 | ||
422 | uint16_t flags = nctohs(&packet[2]); | |
423 | uint32_t la = sync_rtp_timestamp - rtp_timestamp_less_latency; // note, this might | |
424 | // loop around in | |
425 | // modulo. Not sure if | |
426 | // you'll get an error! | |
427 | // debug(1, "Latency from the sync packet is %" PRIu32 " frames.", la); | |
428 | ||
429 | if ((flags == 7) || ((conn->AirPlayVersion > 0) && (conn->AirPlayVersion <= 353)) || | |
430 | ((conn->AirPlayVersion > 0) && (conn->AirPlayVersion >= 371))) { | |
431 | la += config.fixedLatencyOffset; | |
432 | // debug(1, "Latency offset by %" PRIu32" frames due to the source flags and version | |
433 | // giving a latency of %" PRIu32 " frames.", config.fixedLatencyOffset, la); | |
434 | } | |
435 | if ((conn->maximum_latency) && (conn->maximum_latency < la)) | |
436 | la = conn->maximum_latency; | |
437 | if ((conn->minimum_latency) && (conn->minimum_latency > la)) | |
438 | la = conn->minimum_latency; | |
439 | ||
440 | const uint32_t max_frames = ((3 * BUFFER_FRAMES * 352) / 4) - 11025; | |
441 | ||
442 | if (la > max_frames) { | |
443 | warn("An out-of-range latency request of %" PRIu32 | |
444 | " frames was ignored. Must be %" PRIu32 | |
445 | " frames or less (44,100 frames per second). " | |
446 | "Latency remains at %" PRIu32 " frames.", | |
447 | la, max_frames, conn->latency); | |
448 | } else { | |
449 | ||
450 | // here we have the latency but it does not yet account for the | |
451 | // audio_backend_latency_offset | |
452 | int32_t latency_offset = | |
453 | (int32_t)(config.audio_backend_latency_offset * conn->input_rate); | |
454 | ||
455 | // debug(1,"latency offset is %" PRId32 ", input rate is %u", latency_offset, | |
456 | // conn->input_rate); | |
457 | int32_t adjusted_latency = latency_offset + (int32_t)la; | |
458 | if ((adjusted_latency < 0) || | |
459 | (adjusted_latency > | |
460 | (int32_t)(conn->max_frames_per_packet * | |
461 | (BUFFER_FRAMES - config.minimum_free_buffer_headroom)))) | |
462 | warn("audio_backend_latency_offset out of range -- ignored."); | |
463 | else | |
464 | la = adjusted_latency; | |
465 | ||
466 | if (la != conn->latency) { | |
467 | conn->latency = la; | |
468 | debug(2, | |
469 | "New latency: %" PRIu32 ", sync latency: %" PRIu32 | |
470 | ", minimum latency: %" PRIu32 ", maximum " | |
471 | "latency: %" PRIu32 ", fixed offset: %" PRIu32 | |
472 | ", audio_backend_latency_offset: %f.", | |
473 | conn->latency, sync_rtp_timestamp - rtp_timestamp_less_latency, | |
474 | conn->minimum_latency, conn->maximum_latency, config.fixedLatencyOffset, | |
475 | config.audio_backend_latency_offset); | |
476 | } | |
e76a6366 MB |
477 | } |
478 | } | |
e0aa75a8 | 479 | |
fd880056 | 480 | // here, we apply the latency to the sync_rtp_timestamp |
a8caa0f9 | 481 | |
fd880056 | 482 | sync_rtp_timestamp = sync_rtp_timestamp - conn->latency; |
a8caa0f9 | 483 | |
fd880056 | 484 | debug_mutex_lock(&conn->reference_time_mutex, 1000, 0); |
5141e2f5 | 485 | |
fd880056 MB |
486 | if (conn->initial_reference_time == 0) { |
487 | if (conn->packet_count_since_flush > 0) { | |
488 | conn->initial_reference_time = remote_time_of_sync; | |
489 | conn->initial_reference_timestamp = sync_rtp_timestamp; | |
490 | } | |
51913573 | 491 | } else { |
fd880056 MB |
492 | uint64_t remote_frame_time_interval = |
493 | conn->anchor_time - | |
494 | conn->initial_reference_time; // here, this should never be zero | |
495 | if (remote_frame_time_interval) { | |
496 | conn->remote_frame_rate = | |
497 | (1.0E9 * (conn->anchor_rtptime - conn->initial_reference_timestamp)) / | |
498 | remote_frame_time_interval; | |
499 | } else { | |
500 | conn->remote_frame_rate = 0.0; // use as a flag. | |
501 | } | |
51913573 | 502 | } |
e76a6366 | 503 | |
fd880056 MB |
504 | // this is for debugging |
505 | uint64_t old_remote_reference_time = conn->anchor_time; | |
506 | uint32_t old_reference_timestamp = conn->anchor_rtptime; | |
507 | // int64_t old_latency_delayed_timestamp = conn->latency_delayed_timestamp; | |
508 | if (conn->anchor_remote_info_is_valid != 0) { | |
509 | int64_t time_difference = remote_time_of_sync - conn->anchor_time; | |
510 | int32_t frame_difference = sync_rtp_timestamp - conn->anchor_rtptime; | |
511 | double time_difference_in_frames = (1.0 * time_difference * conn->input_rate) / 1000000000; | |
512 | double frame_change = frame_difference - time_difference_in_frames; | |
513 | debug(2,"AP1 control thread: set_ntp_anchor_info: rtptime: %" PRIu32 ", networktime: %" PRIx64 ", frame adjustment: %7.3f.", sync_rtp_timestamp, remote_time_of_sync, frame_change); | |
514 | } else { | |
515 | debug(2,"AP1 control thread: set_ntp_anchor_info: rtptime: %" PRIu32 ", networktime: %" PRIx64 ".", sync_rtp_timestamp, remote_time_of_sync); | |
516 | } | |
8bf83c14 | 517 | |
fd880056 MB |
518 | conn->anchor_time = remote_time_of_sync; |
519 | // conn->reference_timestamp_time = | |
520 | // remote_time_of_sync - local_to_remote_time_difference_now(conn); | |
521 | conn->anchor_rtptime = sync_rtp_timestamp; | |
522 | conn->anchor_remote_info_is_valid = 1; | |
523 | ||
524 | ||
525 | conn->latency_delayed_timestamp = rtp_timestamp_less_latency; | |
526 | debug_mutex_unlock(&conn->reference_time_mutex, 0); | |
527 | ||
528 | conn->reference_to_previous_time_difference = | |
529 | remote_time_of_sync - old_remote_reference_time; | |
530 | if (old_reference_timestamp == 0) | |
531 | conn->reference_to_previous_frame_difference = 0; | |
532 | else | |
533 | conn->reference_to_previous_frame_difference = | |
534 | sync_rtp_timestamp - old_reference_timestamp; | |
535 | } else { | |
536 | debug(2, "Sync packet received before we got a timing packet back."); | |
537 | } | |
538 | } else if (packet[1] == 0xd6) { // resent audio data in the control path -- whaale only? | |
539 | pktp = packet + 4; | |
540 | plen -= 4; | |
541 | seq_t seqno = ntohs(*(uint16_t *)(pktp + 2)); | |
542 | debug(3, "Control Receiver -- Retransmitted Audio Data Packet %u received.", seqno); | |
543 | ||
544 | uint32_t actual_timestamp = ntohl(*(uint32_t *)(pktp + 4)); | |
545 | ||
546 | pktp += 12; | |
547 | plen -= 12; | |
548 | ||
549 | // check if packet contains enough content to be reasonable | |
550 | if (plen >= 16) { | |
551 | player_put_packet(1, seqno, actual_timestamp, pktp, plen, | |
552 | conn); // the '1' means is original format | |
553 | continue; | |
554 | } else { | |
555 | debug(3, "Too-short retransmitted audio packet received in control port, ignored."); | |
556 | } | |
557 | } else | |
558 | debug(1, "Control Receiver -- Unknown RTP packet of type 0x%02X length %d, ignored.", | |
559 | packet[1], nread); | |
560 | } else { | |
561 | debug(3, "Control Receiver -- dropping a packet to simulate a bad network."); | |
562 | } | |
7bc6d088 | 563 | } else { |
8a73d597 | 564 | |
fd880056 MB |
565 | char em[1024]; |
566 | strerror_r(errno, em, sizeof(em)); | |
567 | debug(1, "Control Receiver -- error %d receiving a packet: \"%s\".", errno, em); | |
568 | } | |
e76a6366 | 569 | } |
87a0475c | 570 | } |
7d0eb379 MB |
571 | debug(1, "Control RTP thread \"normal\" exit -- this can't happen. Hah!"); |
572 | pthread_cleanup_pop(0); // don't execute anything here. | |
573 | debug(2, "Control RTP thread exit."); | |
574 | pthread_exit(NULL); | |
f3800e46 MB |
575 | } |
576 | ||
3b4654df MB |
577 | void rtp_timing_sender_cleanup_handler(void *arg) { |
578 | rtsp_conn_info *conn = (rtsp_conn_info *)arg; | |
579 | debug(3, "Connection %d: Timing Sender Cleanup.", conn->connection_number); | |
580 | } | |
581 | ||
21fb39d2 | 582 | void *rtp_timing_sender(void *arg) { |
953ad8ac | 583 | debug(2, "rtp_timing_sender start"); |
3b4654df | 584 | pthread_cleanup_push(rtp_timing_sender_cleanup_handler, arg); |
e513e533 | 585 | rtsp_conn_info *conn = (rtsp_conn_info *)arg; |
87a0475c | 586 | struct timing_request { |
f3800e46 MB |
587 | char leader; |
588 | char type; | |
589 | uint16_t seqno; | |
590 | uint32_t filler; | |
87a0475c | 591 | uint64_t origin, receive, transmit; |
f3800e46 | 592 | }; |
87a0475c MB |
593 | |
594 | uint64_t request_number = 0; | |
595 | ||
596 | struct timing_request req; // *not* a standard RTCP NACK | |
597 | ||
f3800e46 | 598 | req.leader = 0x80; |
87a0475c | 599 | req.type = 0xd2; // Timing request |
f3800e46 | 600 | req.filler = 0; |
87a0475c MB |
601 | req.seqno = htons(7); |
602 | ||
672c84c7 | 603 | conn->time_ping_count = 0; |
7d0eb379 | 604 | while (1) { |
fd880056 MB |
605 | if (conn->rtsp_link_is_idle == 0) { |
606 | if (conn->udp_clock_sender_is_initialised == 0) { | |
607 | request_number = 0; | |
608 | conn->udp_clock_sender_is_initialised = 1; | |
609 | debug(2,"AP1 clock sender thread: initialised."); | |
610 | } | |
611 | // debug(1,"Send a timing request"); | |
f3800e46 | 612 | |
fd880056 MB |
613 | if (!conn->rtp_running) |
614 | debug(1, "rtp_timing_sender called without active stream in RTSP conversation thread %d!", | |
615 | conn->connection_number); | |
f3800e46 | 616 | |
fd880056 | 617 | // debug(1, "Requesting ntp timestamp exchange."); |
f3800e46 | 618 | |
fd880056 MB |
619 | req.filler = 0; |
620 | req.origin = req.receive = req.transmit = 0; | |
f3800e46 | 621 | |
fd880056 MB |
622 | conn->departure_time = get_absolute_time_in_ns(); |
623 | socklen_t msgsize = sizeof(struct sockaddr_in); | |
624 | #ifdef AF_INET6 | |
625 | if (conn->rtp_client_timing_socket.SAFAMILY == AF_INET6) { | |
626 | msgsize = sizeof(struct sockaddr_in6); | |
627 | } | |
628 | #endif | |
629 | if ((config.diagnostic_drop_packet_fraction == 0.0) || | |
630 | (drand48() > config.diagnostic_drop_packet_fraction)) { | |
631 | if (sendto(conn->timing_socket, &req, sizeof(req), 0, | |
632 | (struct sockaddr *)&conn->rtp_client_timing_socket, msgsize) == -1) { | |
633 | char em[1024]; | |
634 | strerror_r(errno, em, sizeof(em)); | |
635 | debug(1, "Error %d using send-to to the timing socket: \"%s\".", errno, em); | |
636 | } | |
637 | } else { | |
638 | debug(3, "Timing Sender Thread -- dropping outgoing packet to simulate bad network."); | |
deb9f4b8 | 639 | } |
deb9f4b8 | 640 | |
fd880056 | 641 | request_number++; |
a0bb2993 | 642 | |
fd880056 MB |
643 | if (request_number <= 3) |
644 | usleep(300000); // these are thread cancellation points | |
645 | else | |
646 | usleep(3000000); | |
647 | } else { | |
648 | usleep(100000); // wait until sleep is over | |
649 | } | |
f3800e46 | 650 | } |
499fae97 | 651 | debug(3, "rtp_timing_sender thread interrupted. This should never happen."); |
3b4654df | 652 | pthread_cleanup_pop(0); // don't execute anything here. |
7d0eb379 MB |
653 | pthread_exit(NULL); |
654 | } | |
655 | ||
7d0eb379 MB |
656 | void rtp_timing_receiver_cleanup_handler(void *arg) { |
657 | rtsp_conn_info *conn = (rtsp_conn_info *)arg; | |
f5eceff6 MB |
658 | debug(3, "Timing Receiver Cleanup."); |
659 | // walk down the list of DACP / gradient pairs, if any | |
660 | nvll *gradients = config.gradients; | |
661 | if (conn->dacp_id) | |
ca562872 MB |
662 | while ((gradients) && (strcasecmp((const char *)&conn->client_ip_string, gradients->name) != 0)) |
663 | gradients = gradients->next; | |
f5eceff6 | 664 | |
ca562872 MB |
665 | // if gradients comes out of this non-null, it is pointing to the DACP and it's last-known |
666 | // gradient | |
f5eceff6 | 667 | if (gradients) { |
ca562872 MB |
668 | gradients->value = conn->local_to_remote_time_gradient; |
669 | // debug(1,"Updating a drift of %.2f ppm for \"%s\".", (conn->local_to_remote_time_gradient | |
670 | // - 1.0)*1000000, gradients->name); | |
f5eceff6 | 671 | } else { |
ca562872 MB |
672 | nvll *new_entry = (nvll *)malloc(sizeof(nvll)); |
673 | if (new_entry) { | |
674 | new_entry->name = strdup((const char *)&conn->client_ip_string); | |
675 | new_entry->value = conn->local_to_remote_time_gradient; | |
676 | new_entry->next = config.gradients; | |
677 | config.gradients = new_entry; | |
678 | // debug(1,"Setting a new drift of %.2f ppm for \"%s\".", (conn->local_to_remote_time_gradient | |
679 | // - 1.0)*1000000, new_entry->name); | |
680 | } | |
f5eceff6 MB |
681 | } |
682 | ||
c318796e | 683 | debug(3, "Cancel Timing Requester."); |
6d087255 | 684 | pthread_cancel(conn->timer_requester); |
0eac2b9c MB |
685 | int oldState; |
686 | pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldState); | |
ca45d2ec | 687 | debug(3, "Join Timing Requester."); |
6d087255 | 688 | pthread_join(conn->timer_requester, NULL); |
499fae97 | 689 | debug(3, "Timing Receiver Cleanup Successful."); |
3b4654df | 690 | pthread_setcancelstate(oldState, NULL); |
f3800e46 MB |
691 | } |
692 | ||
21fb39d2 | 693 | void *rtp_timing_receiver(void *arg) { |
953ad8ac | 694 | debug(3, "rtp_timing_receiver start"); |
7d0eb379 | 695 | pthread_cleanup_push(rtp_timing_receiver_cleanup_handler, arg); |
e513e533 | 696 | rtsp_conn_info *conn = (rtsp_conn_info *)arg; |
21fb39d2 | 697 | |
07e46565 | 698 | uint8_t packet[2048]; |
87a0475c | 699 | ssize_t nread; |
6d087255 | 700 | pthread_create(&conn->timer_requester, NULL, &rtp_timing_sender, arg); |
87a0475c | 701 | // struct timespec att; |
07e46565 | 702 | uint64_t distant_receive_time, distant_transmit_time, arrival_time, return_time; |
3870195c MB |
703 | local_to_remote_time_jitter = 0; |
704 | local_to_remote_time_jitter_count = 0; | |
064bd293 | 705 | |
e3722d93 | 706 | uint64_t first_local_to_remote_time_difference = 0; |
0517a233 | 707 | |
0517a233 | 708 | conn->local_to_remote_time_gradient = 1.0; // initial value. |
f5eceff6 MB |
709 | // walk down the list of DACP / gradient pairs, if any |
710 | nvll *gradients = config.gradients; | |
ca562872 MB |
711 | while ((gradients) && (strcasecmp((const char *)&conn->client_ip_string, gradients->name) != 0)) |
712 | gradients = gradients->next; | |
f5eceff6 MB |
713 | |
714 | // if gradients comes out of this non-null, it is pointing to the IP and it's last-known gradient | |
715 | if (gradients) { | |
ca562872 MB |
716 | conn->local_to_remote_time_gradient = gradients->value; |
717 | // debug(1,"Using a stored drift of %.2f ppm for \"%s\".", (conn->local_to_remote_time_gradient | |
718 | // - 1.0)*1000000, gradients->name); | |
f5eceff6 | 719 | } |
0517a233 | 720 | |
92074c2b MB |
721 | // calculate diffusion factor |
722 | ||
723 | // at the end of the array of time pings, the diffusion factor | |
724 | // must be diffusion_expansion_factor | |
725 | // this, at each step, the diffusion multiplication constant must | |
726 | // be the nth root of diffusion_expansion_factor | |
727 | // where n is the number of elements in the array | |
728 | ||
ca562872 MB |
729 | const double diffusion_expansion_factor = 10; |
730 | double log_of_multiplier = log10(diffusion_expansion_factor) / time_ping_history; | |
731 | double multiplier = pow(10, log_of_multiplier); | |
92074c2b | 732 | uint64_t dispersion_factor = (uint64_t)(multiplier * 100); |
14bfba27 MB |
733 | if (dispersion_factor == 0) |
734 | die("dispersion factor is zero!"); | |
f5eceff6 | 735 | // debug(1,"dispersion factor is %" PRIu64 ".", dispersion_factor); |
92074c2b | 736 | |
07e46565 MB |
737 | // uint64_t first_local_to_remote_time_difference_time; |
738 | // uint64_t l2rtd = 0; | |
3870195c | 739 | int sequence_number = 0; |
5141e2f5 | 740 | |
3870195c MB |
741 | // for getting mean and sd of return times |
742 | int32_t stat_n = 0; | |
743 | double stat_mean = 0.0; | |
de8df934 | 744 | // double stat_M2 = 0.0; |
3870195c | 745 | |
7d0eb379 | 746 | while (1) { |
04cb1d09 | 747 | nread = recv(conn->timing_socket, packet, sizeof(packet), 0); |
fd880056 MB |
748 | if (conn->rtsp_link_is_idle == 0) { |
749 | if (conn->udp_clock_is_initialised == 0) { | |
750 | debug(2,"AP1 clock receiver thread: initialised."); | |
751 | local_to_remote_time_jitter = 0; | |
752 | local_to_remote_time_jitter_count = 0; | |
87a0475c | 753 | |
fd880056 | 754 | first_local_to_remote_time_difference = 0; |
87a0475c | 755 | |
fd880056 MB |
756 | sequence_number = 0; |
757 | stat_n = 0; | |
758 | stat_mean = 0.0; | |
759 | conn->udp_clock_is_initialised = 1; | |
760 | } | |
761 | if (nread >= 0) { | |
762 | if ((config.diagnostic_drop_packet_fraction == 0.0) || | |
763 | (drand48() > config.diagnostic_drop_packet_fraction)) { | |
764 | arrival_time = get_absolute_time_in_ns(); | |
765 | ||
766 | // ssize_t plen = nread; | |
767 | // debug(1,"Packet Received on Timing Port."); | |
768 | if (packet[1] == 0xd3) { // timing reply | |
769 | ||
770 | return_time = arrival_time - conn->departure_time; | |
771 | debug(2, "clock synchronisation request: return time is %8.3f milliseconds.", | |
772 | 0.000001 * return_time); | |
773 | ||
774 | if (return_time < 200000000) { // must be less than 0.2 seconds | |
775 | // distant_receive_time = | |
776 | // ((uint64_t)ntohl(*((uint32_t*)&packet[16])))<<32+ntohl(*((uint32_t*)&packet[20])); | |
777 | ||
778 | uint64_t ps, pn; | |
779 | ||
780 | ps = nctohl(&packet[16]); | |
781 | ps = ps * 1000000000; // this many nanoseconds from the whole seconds | |
782 | pn = nctohl(&packet[20]); | |
783 | pn = pn * 1000000000; | |
784 | pn = pn >> 32; // this many nanoseconds from the fractional part | |
785 | distant_receive_time = ps + pn; | |
786 | ||
787 | // distant_transmit_time = | |
788 | // ((uint64_t)ntohl(*((uint32_t*)&packet[24])))<<32+ntohl(*((uint32_t*)&packet[28])); | |
789 | ||
790 | ps = nctohl(&packet[24]); | |
791 | ps = ps * 1000000000; // this many nanoseconds from the whole seconds | |
792 | pn = nctohl(&packet[28]); | |
793 | pn = pn * 1000000000; | |
794 | pn = pn >> 32; // this many nanoseconds from the fractional part | |
795 | distant_transmit_time = ps + pn; | |
796 | ||
797 | uint64_t remote_processing_time = 0; | |
798 | ||
799 | if (distant_transmit_time >= distant_receive_time) | |
800 | remote_processing_time = distant_transmit_time - distant_receive_time; | |
801 | else { | |
802 | debug(1, "Yikes: distant_transmit_time is before distant_receive_time; remote " | |
803 | "processing time set to zero."); | |
deb9f4b8 | 804 | } |
fd880056 MB |
805 | // debug(1,"Return trip time: %" PRIu64 " nS, remote processing time: %" PRIu64 " |
806 | // nS.",return_time, remote_processing_time); | |
deb9f4b8 | 807 | |
fd880056 MB |
808 | if (remote_processing_time < return_time) |
809 | return_time -= remote_processing_time; | |
810 | else | |
811 | debug(1, "Remote processing time greater than return time -- ignored."); | |
812 | ||
813 | int cc; | |
814 | // debug(1, "time ping history is %d entries.", time_ping_history); | |
815 | for (cc = time_ping_history - 1; cc > 0; cc--) { | |
816 | conn->time_pings[cc] = conn->time_pings[cc - 1]; | |
817 | // if ((conn->time_ping_count) && (conn->time_ping_count < 10)) | |
818 | // conn->time_pings[cc].dispersion = | |
819 | // conn->time_pings[cc].dispersion * pow(2.14, | |
820 | // 1.0/conn->time_ping_count); | |
821 | if (conn->time_pings[cc].dispersion > UINT64_MAX / dispersion_factor) | |
822 | debug(1, "dispersion factor is too large at %" PRIu64 "."); | |
823 | else | |
824 | conn->time_pings[cc].dispersion = | |
825 | (conn->time_pings[cc].dispersion * dispersion_factor) / | |
826 | 100; // make the dispersions 'age' by this rational factor | |
827 | } | |
828 | // these are used for doing a least squares calculation to get the drift | |
829 | conn->time_pings[0].local_time = arrival_time; | |
830 | conn->time_pings[0].remote_time = distant_transmit_time + return_time / 2; | |
831 | conn->time_pings[0].sequence_number = sequence_number++; | |
832 | conn->time_pings[0].chosen = 0; | |
833 | conn->time_pings[0].dispersion = return_time; | |
834 | if (conn->time_ping_count < time_ping_history) | |
835 | conn->time_ping_count++; | |
836 | ||
837 | // here, calculate the mean and standard deviation of the return times | |
838 | ||
839 | // mean and variance calculations from "online_variance" algorithm at | |
840 | // https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Online_algorithm | |
841 | ||
842 | stat_n += 1; | |
843 | double stat_delta = return_time - stat_mean; | |
844 | stat_mean += stat_delta / stat_n; | |
845 | // stat_M2 += stat_delta * (return_time - stat_mean); | |
846 | // debug(1, "Timing packet return time stats: current, mean and standard deviation over | |
847 | // %d packets: %.1f, %.1f, %.1f (nanoseconds).", | |
848 | // stat_n,return_time,stat_mean, sqrtf(stat_M2 / (stat_n - 1))); | |
849 | ||
850 | // here, pick the record with the least dispersion, and record that it's been chosen | |
851 | ||
852 | // uint64_t local_time_chosen = arrival_time; | |
853 | // uint64_t remote_time_chosen = distant_transmit_time; | |
854 | // now pick the timestamp with the lowest dispersion | |
855 | uint64_t rt = conn->time_pings[0].remote_time; | |
856 | uint64_t lt = conn->time_pings[0].local_time; | |
857 | uint64_t tld = conn->time_pings[0].dispersion; | |
858 | int chosen = 0; | |
859 | for (cc = 1; cc < conn->time_ping_count; cc++) | |
860 | if (conn->time_pings[cc].dispersion < tld) { | |
861 | chosen = cc; | |
862 | rt = conn->time_pings[cc].remote_time; | |
863 | lt = conn->time_pings[cc].local_time; | |
864 | tld = conn->time_pings[cc].dispersion; | |
865 | // local_time_chosen = conn->time_pings[cc].local_time; | |
866 | // remote_time_chosen = conn->time_pings[cc].remote_time; | |
867 | } | |
868 | // debug(1,"Record %d has the lowest dispersion with %0.2f us | |
869 | // dispersion.",chosen,1.0*((tld * 1000000) >> 32)); | |
870 | conn->time_pings[chosen].chosen = 1; // record the fact that it has been used for timing | |
deb9f4b8 | 871 | |
fd880056 MB |
872 | conn->local_to_remote_time_difference = |
873 | rt - lt; // make this the new local-to-remote-time-difference | |
874 | conn->local_to_remote_time_difference_measurement_time = lt; // done at this time. | |
e76a6366 | 875 | |
fd880056 MB |
876 | if (first_local_to_remote_time_difference == 0) { |
877 | first_local_to_remote_time_difference = conn->local_to_remote_time_difference; | |
878 | // first_local_to_remote_time_difference_time = get_absolute_time_in_fp(); | |
3870195c | 879 | } |
fd880056 MB |
880 | |
881 | // here, let's try to use the timing pings that were selected because of their short | |
882 | // return times to | |
883 | // estimate a figure for drift between the local clock (x) and the remote clock (y) | |
884 | ||
885 | // if we plug in a local interval, we will get back what that is in remote time | |
886 | ||
887 | // calculate the line of best fit for relating the local time and the remote time | |
888 | // we will calculate the slope, which is the drift | |
889 | // see https://www.varsitytutors.com/hotmath/hotmath_help/topics/line-of-best-fit | |
890 | ||
891 | uint64_t y_bar = 0; // remote timestamp average | |
892 | uint64_t x_bar = 0; // local timestamp average | |
893 | int sample_count = 0; | |
894 | ||
895 | // approximate time in seconds to let the system settle down | |
896 | const int settling_time = 60; | |
897 | // number of points to have for calculating a valid drift | |
898 | const int sample_point_minimum = 8; | |
d5197081 MB |
899 | for (cc = 0; cc < conn->time_ping_count; cc++) |
900 | if ((conn->time_pings[cc].chosen) && | |
fd880056 MB |
901 | (conn->time_pings[cc].sequence_number > |
902 | (settling_time / 3))) { // wait for a approximate settling time | |
903 | // have to scale them down so that the sum, possibly over | |
904 | // every term in the array, doesn't overflow | |
905 | y_bar += (conn->time_pings[cc].remote_time >> time_ping_history_power_of_two); | |
906 | x_bar += (conn->time_pings[cc].local_time >> time_ping_history_power_of_two); | |
907 | sample_count++; | |
908 | } | |
909 | conn->local_to_remote_time_gradient_sample_count = sample_count; | |
910 | if (sample_count > sample_point_minimum) { | |
911 | y_bar = y_bar / sample_count; | |
912 | x_bar = x_bar / sample_count; | |
913 | ||
914 | int64_t xid, yid; | |
915 | double mtl, mbl; | |
916 | mtl = 0; | |
917 | mbl = 0; | |
918 | for (cc = 0; cc < conn->time_ping_count; cc++) | |
919 | if ((conn->time_pings[cc].chosen) && | |
920 | (conn->time_pings[cc].sequence_number > (settling_time / 3))) { | |
921 | ||
922 | uint64_t slt = conn->time_pings[cc].local_time >> time_ping_history_power_of_two; | |
923 | if (slt > x_bar) | |
924 | xid = slt - x_bar; | |
925 | else | |
926 | xid = -(x_bar - slt); | |
d5197081 | 927 | |
fd880056 MB |
928 | uint64_t srt = conn->time_pings[cc].remote_time >> time_ping_history_power_of_two; |
929 | if (srt > y_bar) | |
930 | yid = srt - y_bar; | |
931 | else | |
932 | yid = -(y_bar - srt); | |
d5197081 | 933 | |
fd880056 MB |
934 | mtl = mtl + (1.0 * xid) * yid; |
935 | mbl = mbl + (1.0 * xid) * xid; | |
936 | } | |
937 | if (mbl) | |
938 | conn->local_to_remote_time_gradient = mtl / mbl; | |
939 | else { | |
940 | // conn->local_to_remote_time_gradient = 1.0; | |
941 | debug(1, "mbl is zero. Drift remains at %.2f ppm.", | |
942 | (conn->local_to_remote_time_gradient - 1.0) * 1000000); | |
d5197081 | 943 | } |
9f9b36c0 | 944 | |
fd880056 MB |
945 | // scale the numbers back up |
946 | uint64_t ybf = y_bar << time_ping_history_power_of_two; | |
947 | uint64_t xbf = x_bar << time_ping_history_power_of_two; | |
9f9b36c0 | 948 | |
fd880056 MB |
949 | conn->local_to_remote_time_difference = |
950 | ybf - xbf; // make this the new local-to-remote-time-difference | |
951 | conn->local_to_remote_time_difference_measurement_time = xbf; | |
9f9b36c0 | 952 | |
fd880056 MB |
953 | } else { |
954 | debug(3, "not enough samples to estimate drift -- remaining at %.2f ppm.", | |
955 | (conn->local_to_remote_time_gradient - 1.0) * 1000000); | |
956 | // conn->local_to_remote_time_gradient = 1.0; | |
957 | } | |
958 | // debug(1,"local to remote time gradient is %12.2f ppm, based on %d | |
959 | // samples.",conn->local_to_remote_time_gradient*1000000,sample_count); | |
960 | // debug(1,"ntp set offset and measurement time"); // iin PTP terms, this is the local-to-network offset and the local measurement time | |
e76a6366 | 961 | } else { |
fd880056 MB |
962 | debug(1, |
963 | "Time ping turnaround time: %" PRIu64 | |
964 | " ns -- it looks like a timing ping was lost.", | |
965 | return_time); | |
e76a6366 | 966 | } |
28a671b2 | 967 | } else { |
fd880056 | 968 | debug(1, "Timing port -- Unknown RTP packet of type 0x%02X length %d.", packet[1], nread); |
28a671b2 | 969 | } |
f3800e46 | 970 | } else { |
fd880056 | 971 | debug(3, "Timing Receiver Thread -- dropping incoming packet to simulate a bad network."); |
87a0475c | 972 | } |
fb5c4f30 | 973 | } else { |
fd880056 | 974 | debug(1, "Timing receiver -- error receiving a packet."); |
e513e533 | 975 | } |
f3800e46 | 976 | } |
87a0475c | 977 | } |
f3800e46 | 978 | |
7d0eb379 MB |
979 | debug(1, "Timing Receiver RTP thread \"normal\" exit -- this can't happen. Hah!"); |
980 | pthread_cleanup_pop(0); // don't execute anything here. | |
981 | debug(2, "Timing Receiver RTP thread exit."); | |
982 | pthread_exit(NULL); | |
f3800e46 MB |
983 | } |
984 | ||
665a53a8 MB |
985 | void rtp_setup(SOCKADDR *local, SOCKADDR *remote, uint16_t cport, uint16_t tport, |
986 | rtsp_conn_info *conn) { | |
064bd293 | 987 | |
5028cd1f MB |
988 | // this gets the local and remote ip numbers (and ports used for the TCD stuff) |
989 | // we use the local stuff to specify the address we are coming from and | |
990 | // we use the remote stuff to specify where we're goint to | |
064bd293 | 991 | |
f3d85bc7 | 992 | if (conn->rtp_running) |
665a53a8 MB |
993 | warn("rtp_setup has been called with al already-active stream -- ignored. Possible duplicate " |
994 | "SETUP call?"); | |
995 | else { | |
a2fb5d21 | 996 | |
3e72bb21 | 997 | debug(3, "rtp_setup: cport=%d tport=%d.", cport, tport); |
87a0475c | 998 | |
665a53a8 MB |
999 | // print out what we know about the client |
1000 | void *client_addr = NULL, *self_addr = NULL; | |
1001 | // int client_port, self_port; | |
1002 | // char client_port_str[64]; | |
1003 | // char self_addr_str[64]; | |
064bd293 | 1004 | |
665a53a8 MB |
1005 | conn->connection_ip_family = |
1006 | remote->SAFAMILY; // keep information about the kind of ip of the client | |
064bd293 | 1007 | |
a2fb5d21 | 1008 | #ifdef AF_INET6 |
665a53a8 MB |
1009 | if (conn->connection_ip_family == AF_INET6) { |
1010 | struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)remote; | |
1011 | client_addr = &(sa6->sin6_addr); | |
1012 | // client_port = ntohs(sa6->sin6_port); | |
1013 | sa6 = (struct sockaddr_in6 *)local; | |
1014 | self_addr = &(sa6->sin6_addr); | |
1015 | // self_port = ntohs(sa6->sin6_port); | |
1016 | conn->self_scope_id = sa6->sin6_scope_id; | |
1017 | } | |
a2fb5d21 | 1018 | #endif |
665a53a8 MB |
1019 | if (conn->connection_ip_family == AF_INET) { |
1020 | struct sockaddr_in *sa4 = (struct sockaddr_in *)remote; | |
1021 | client_addr = &(sa4->sin_addr); | |
1022 | // client_port = ntohs(sa4->sin_port); | |
1023 | sa4 = (struct sockaddr_in *)local; | |
1024 | self_addr = &(sa4->sin_addr); | |
1025 | // self_port = ntohs(sa4->sin_port); | |
1026 | } | |
1fd794af | 1027 | |
665a53a8 MB |
1028 | inet_ntop(conn->connection_ip_family, client_addr, conn->client_ip_string, |
1029 | sizeof(conn->client_ip_string)); | |
1030 | inet_ntop(conn->connection_ip_family, self_addr, conn->self_ip_string, | |
1031 | sizeof(conn->self_ip_string)); | |
1fd794af | 1032 | |
18b37ea2 MB |
1033 | debug(2, "Connection %d: SETUP -- Connection from %s to self at %s.", conn->connection_number, |
1034 | conn->client_ip_string, conn->self_ip_string); | |
87a0475c | 1035 | |
665a53a8 MB |
1036 | // set up a the record of the remote's control socket |
1037 | struct addrinfo hints; | |
1038 | struct addrinfo *servinfo; | |
87a0475c | 1039 | |
665a53a8 MB |
1040 | memset(&conn->rtp_client_control_socket, 0, sizeof(conn->rtp_client_control_socket)); |
1041 | memset(&hints, 0, sizeof hints); | |
1042 | hints.ai_family = conn->connection_ip_family; | |
1043 | hints.ai_socktype = SOCK_DGRAM; | |
1044 | char portstr[20]; | |
1045 | snprintf(portstr, 20, "%d", cport); | |
1046 | if (getaddrinfo(conn->client_ip_string, portstr, &hints, &servinfo) != 0) | |
1047 | die("Can't get address of client's control port"); | |
f3800e46 | 1048 | |
f3800e46 | 1049 | #ifdef AF_INET6 |
665a53a8 MB |
1050 | if (servinfo->ai_family == AF_INET6) { |
1051 | memcpy(&conn->rtp_client_control_socket, servinfo->ai_addr, sizeof(struct sockaddr_in6)); | |
1052 | // ensure the scope id matches that of remote. this is needed for link-local addresses. | |
1053 | struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)&conn->rtp_client_control_socket; | |
1054 | sa6->sin6_scope_id = conn->self_scope_id; | |
1055 | } else | |
f3800e46 | 1056 | #endif |
665a53a8 MB |
1057 | memcpy(&conn->rtp_client_control_socket, servinfo->ai_addr, sizeof(struct sockaddr_in)); |
1058 | freeaddrinfo(servinfo); | |
1059 | ||
1060 | // set up a the record of the remote's timing socket | |
1061 | memset(&conn->rtp_client_timing_socket, 0, sizeof(conn->rtp_client_timing_socket)); | |
1062 | memset(&hints, 0, sizeof hints); | |
1063 | hints.ai_family = conn->connection_ip_family; | |
1064 | hints.ai_socktype = SOCK_DGRAM; | |
1065 | snprintf(portstr, 20, "%d", tport); | |
1066 | if (getaddrinfo(conn->client_ip_string, portstr, &hints, &servinfo) != 0) | |
1067 | die("Can't get address of client's timing port"); | |
2cded85d | 1068 | #ifdef AF_INET6 |
665a53a8 MB |
1069 | if (servinfo->ai_family == AF_INET6) { |
1070 | memcpy(&conn->rtp_client_timing_socket, servinfo->ai_addr, sizeof(struct sockaddr_in6)); | |
1071 | // ensure the scope id matches that of remote. this is needed for link-local addresses. | |
1072 | struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)&conn->rtp_client_timing_socket; | |
1073 | sa6->sin6_scope_id = conn->self_scope_id; | |
1074 | } else | |
2cded85d | 1075 | #endif |
665a53a8 MB |
1076 | memcpy(&conn->rtp_client_timing_socket, servinfo->ai_addr, sizeof(struct sockaddr_in)); |
1077 | freeaddrinfo(servinfo); | |
87a0475c | 1078 | |
665a53a8 MB |
1079 | // now, we open three sockets -- one for the audio stream, one for the timing and one for the |
1080 | // control | |
1081 | conn->remote_control_port = cport; | |
1082 | conn->remote_timing_port = tport; | |
87a0475c | 1083 | |
8a73d597 | 1084 | conn->local_control_port = bind_UDP_port(conn->connection_ip_family, conn->self_ip_string, |
a68f28ac | 1085 | conn->self_scope_id, &conn->control_socket); |
8a73d597 | 1086 | conn->local_timing_port = bind_UDP_port(conn->connection_ip_family, conn->self_ip_string, |
a68f28ac | 1087 | conn->self_scope_id, &conn->timing_socket); |
8a73d597 | 1088 | conn->local_audio_port = bind_UDP_port(conn->connection_ip_family, conn->self_ip_string, |
a68f28ac | 1089 | conn->self_scope_id, &conn->audio_socket); |
87a0475c | 1090 | |
3e72bb21 | 1091 | debug(3, "listening for audio, control and timing on ports %d, %d, %d.", conn->local_audio_port, |
665a53a8 | 1092 | conn->local_control_port, conn->local_timing_port); |
87a0475c | 1093 | |
8a73d597 | 1094 | conn->anchor_rtptime = 0; |
87a0475c | 1095 | |
665a53a8 MB |
1096 | conn->request_sent = 0; |
1097 | conn->rtp_running = 1; | |
665a53a8 | 1098 | } |
f3800e46 MB |
1099 | } |
1100 | ||
8a73d597 | 1101 | void reset_ntp_anchor_info(rtsp_conn_info *conn) { |
18b37ea2 | 1102 | debug_mutex_lock(&conn->reference_time_mutex, 1000, 1); |
fd880056 | 1103 | conn->anchor_remote_info_is_valid = 0; |
8a73d597 MB |
1104 | conn->anchor_rtptime = 0; |
1105 | conn->anchor_time = 0; | |
93f41059 | 1106 | debug_mutex_unlock(&conn->reference_time_mutex, 3); |
a2fb5d21 JL |
1107 | } |
1108 | ||
fd880056 MB |
1109 | int have_ntp_timing_information(rtsp_conn_info *conn) { |
1110 | if (conn->anchor_remote_info_is_valid != 0) | |
3870195c | 1111 | return 1; |
fd880056 MB |
1112 | else |
1113 | return 0; | |
8a73d597 MB |
1114 | } |
1115 | ||
d2dba7cd | 1116 | // the timestamp is a timestamp calculated at the input rate |
78f1cd61 MB |
1117 | // the reference timestamps are denominated in terms of the input rate |
1118 | ||
8a73d597 | 1119 | int frame_to_ntp_local_time(uint32_t timestamp, uint64_t *time, rtsp_conn_info *conn) { |
fd880056 MB |
1120 | // a zero result is good |
1121 | if (conn->anchor_remote_info_is_valid == 0) | |
1122 | debug(1,"no anchor information"); | |
eaa98ea7 | 1123 | debug_mutex_lock(&conn->reference_time_mutex, 1000, 0); |
fd880056 MB |
1124 | int result = -1; |
1125 | if (conn->anchor_remote_info_is_valid != 0) { | |
1126 | uint64_t remote_time_of_timestamp; | |
1127 | int32_t timestamp_interval = timestamp - conn->anchor_rtptime; | |
1128 | int64_t timestamp_interval_time = timestamp_interval; | |
1129 | timestamp_interval_time = timestamp_interval_time * 1000000000; | |
1130 | timestamp_interval_time = | |
1131 | timestamp_interval_time / 44100; // this is the nominal time, based on the | |
1132 | // fps specified between current and | |
1133 | // previous sync frame. | |
1134 | remote_time_of_timestamp = | |
1135 | conn->anchor_time + timestamp_interval_time; // based on the reference timestamp time | |
1136 | // plus the time interval calculated based | |
1137 | // on the specified fps. | |
1138 | if (time != NULL) | |
1139 | *time = remote_time_of_timestamp - local_to_remote_time_difference_now(conn); | |
1140 | result = 0; | |
1141 | } | |
eaa98ea7 | 1142 | debug_mutex_unlock(&conn->reference_time_mutex, 0); |
3870195c MB |
1143 | return result; |
1144 | } | |
1145 | ||
8a73d597 | 1146 | int local_ntp_time_to_frame(uint64_t time, uint32_t *frame, rtsp_conn_info *conn) { |
fd880056 | 1147 | // a zero result is good |
eaa98ea7 | 1148 | debug_mutex_lock(&conn->reference_time_mutex, 1000, 0); |
fd880056 MB |
1149 | int result = -1; |
1150 | if (conn->anchor_remote_info_is_valid != 0) { | |
1151 | // first, get from [local] time to remote time. | |
1152 | uint64_t remote_time = time + local_to_remote_time_difference_now(conn); | |
1153 | // next, get the remote time interval from the remote_time to the reference time | |
1154 | // here, we calculate the time interval, in terms of remote time | |
1155 | int64_t offset = remote_time - conn->anchor_time; | |
1156 | // now, convert the remote time interval into frames using the frame rate we have observed or | |
1157 | // which has been nominated | |
1158 | int64_t frame_interval = 0; | |
1159 | frame_interval = (offset * 44100) / 1000000000; | |
1160 | int32_t frame_interval_32 = frame_interval; | |
1161 | uint32_t new_frame = conn->anchor_rtptime + frame_interval_32; | |
1162 | // debug(1,"frame is %u.", new_frame); | |
1163 | if (frame != NULL) | |
1164 | *frame = new_frame; | |
1165 | result = 0; | |
1166 | } | |
8a73d597 MB |
1167 | debug_mutex_unlock(&conn->reference_time_mutex, 0); |
1168 | return result; | |
1169 | } | |
1170 | ||
bdfb1c6e MB |
1171 | void rtp_request_resend(seq_t first, uint32_t count, rtsp_conn_info *conn) { |
1172 | // debug(1, "rtp_request_resend of %u packets from sequence number %u.", count, first); | |
1173 | if (conn->rtp_running) { | |
1174 | // if (!request_sent) { | |
1175 | // debug(2, "requesting resend of %d packets starting at %u.", count, first); | |
1176 | // request_sent = 1; | |
1177 | //} | |
1178 | ||
1179 | char req[8]; // *not* a standard RTCP NACK | |
1180 | req[0] = 0x80; | |
1181 | #ifdef CONFIG_AIRPLAY_2 | |
04c0d976 | 1182 | if (conn->airplay_type == ap_2) { |
6a130621 MB |
1183 | if (conn->ap2_remote_control_socket_addr_length == 0) { |
1184 | debug(2, "No remote socket -- skipping the resend"); | |
1185 | return; // hack | |
1186 | } | |
1187 | req[1] = 0xD5; // Airplay 2 'resend' | |
04c0d976 MB |
1188 | } else { |
1189 | #endif | |
6a130621 | 1190 | req[1] = (char)0x55 | (char)0x80; // Apple 'resend' |
04c0d976 | 1191 | #ifdef CONFIG_AIRPLAY_2 |
6a130621 | 1192 | } |
bdfb1c6e MB |
1193 | #endif |
1194 | *(unsigned short *)(req + 2) = htons(1); // our sequence number | |
1195 | *(unsigned short *)(req + 4) = htons(first); // missed seqnum | |
1196 | *(unsigned short *)(req + 6) = htons(count); // count | |
04c0d976 | 1197 | |
bdfb1c6e MB |
1198 | uint64_t time_of_sending_ns = get_absolute_time_in_ns(); |
1199 | uint64_t resend_error_backoff_time = 300000000; // 0.3 seconds | |
1200 | if ((conn->rtp_time_of_last_resend_request_error_ns == 0) || | |
1201 | ((time_of_sending_ns - conn->rtp_time_of_last_resend_request_error_ns) > | |
1202 | resend_error_backoff_time)) { | |
1203 | if ((config.diagnostic_drop_packet_fraction == 0.0) || | |
1204 | (drand48() > config.diagnostic_drop_packet_fraction)) { | |
1205 | // put a time limit on the sendto | |
1206 | ||
1207 | struct timeval timeout; | |
1208 | timeout.tv_sec = 0; | |
1209 | timeout.tv_usec = 100000; | |
04c0d976 | 1210 | int response; |
bdfb1c6e | 1211 | #ifdef CONFIG_AIRPLAY_2 |
6a130621 MB |
1212 | if (conn->airplay_type == ap_2) { |
1213 | if (setsockopt(conn->ap2_control_socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, | |
1214 | sizeof(timeout)) < 0) | |
1215 | debug(1, "Can't set timeout on resend request socket."); | |
1216 | response = sendto(conn->ap2_control_socket, req, sizeof(req), 0, | |
1217 | (struct sockaddr *)&conn->ap2_remote_control_socket_addr, | |
1218 | conn->ap2_remote_control_socket_addr_length); | |
1219 | } else { | |
04c0d976 | 1220 | #endif |
6a130621 MB |
1221 | if (setsockopt(conn->control_socket, SOL_SOCKET, SO_SNDTIMEO, (char *)&timeout, |
1222 | sizeof(timeout)) < 0) | |
1223 | debug(1, "Can't set timeout on resend request socket."); | |
1224 | socklen_t msgsize = sizeof(struct sockaddr_in); | |
04c0d976 | 1225 | #ifdef AF_INET6 |
6a130621 MB |
1226 | if (conn->rtp_client_control_socket.SAFAMILY == AF_INET6) { |
1227 | msgsize = sizeof(struct sockaddr_in6); | |
1228 | } | |
04c0d976 | 1229 | #endif |
6a130621 MB |
1230 | response = sendto(conn->control_socket, req, sizeof(req), 0, |
1231 | (struct sockaddr *)&conn->rtp_client_control_socket, msgsize); | |
bdfb1c6e | 1232 | |
04c0d976 | 1233 | #ifdef CONFIG_AIRPLAY_2 |
6a130621 | 1234 | } |
bdfb1c6e | 1235 | #endif |
04c0d976 | 1236 | if (response == -1) { |
bdfb1c6e MB |
1237 | char em[1024]; |
1238 | strerror_r(errno, em, sizeof(em)); | |
1239 | debug(2, "Error %d using sendto to request a resend: \"%s\".", errno, em); | |
1240 | conn->rtp_time_of_last_resend_request_error_ns = time_of_sending_ns; | |
1241 | } else { | |
1242 | conn->rtp_time_of_last_resend_request_error_ns = 0; | |
1243 | } | |
1244 | ||
1245 | } else { | |
1246 | debug(3, "Dropping resend request packet to simulate a bad network. Backing off for 0.3 " | |
1247 | "second."); | |
1248 | conn->rtp_time_of_last_resend_request_error_ns = time_of_sending_ns; | |
1249 | } | |
1250 | } else { | |
1251 | debug(1, | |
1252 | "Suppressing a resend request due to a resend sendto error in the last 0.3 seconds."); | |
1253 | } | |
1254 | } else { | |
1255 | // if (!request_sent) { | |
1256 | debug(2, "rtp_request_resend called without active stream!"); | |
1257 | // request_sent = 1; | |
1258 | //} | |
1259 | } | |
1260 | } | |
1261 | ||
6760bab4 | 1262 | #ifdef CONFIG_AIRPLAY_2 |
bdfb1c6e | 1263 | |
8a73d597 | 1264 | void set_ptp_anchor_info(rtsp_conn_info *conn, uint64_t clock_id, uint32_t rtptime, |
a68f28ac | 1265 | uint64_t networktime) { |
3cc1ec6a MB |
1266 | if ((conn->anchor_clock != 0) && (conn->anchor_clock == clock_id) && (conn->anchor_remote_info_is_valid != 0)) { |
1267 | // check change in timing | |
1268 | int64_t time_difference = networktime - conn->anchor_time; | |
1269 | int32_t frame_difference = rtptime - conn->anchor_rtptime; | |
1270 | double time_difference_in_frames = (1.0 * time_difference * conn->input_rate) / 1000000000; | |
1271 | double frame_change = frame_difference - time_difference_in_frames; | |
1272 | debug(2,"set_ptp_anchor_info: clock: %" PRIx64 ", rtptime: %" PRIu32 ", networktime: %" PRIx64 ", frame adjustment: %7.3f.", clock_id, rtptime, networktime, frame_change); | |
1273 | } else { | |
1274 | debug(2,"set_ptp_anchor_info: clock: %" PRIx64 ", rtptime: %" PRIu32 ", networktime: %" PRIx64 ".", clock_id, rtptime, networktime); | |
1275 | } | |
26ce13d5 | 1276 | if (conn->anchor_clock != clock_id) { |
3b4a21f0 | 1277 | debug(2, "Connection %d: Set Anchor Clock: %" PRIx64 ".", conn->connection_number, clock_id); |
26ce13d5 | 1278 | } |
a109b587 MB |
1279 | // debug(1,"set anchor info clock: %" PRIx64", rtptime: %u, networktime: %" PRIx64 ".", clock_id, |
1280 | // rtptime, networktime); | |
ac515bbf MB |
1281 | |
1282 | // if the clock is the same but any details change, and if the last_anchor_info has not been | |
1283 | // valid for some minimum time (and thus may not be reliable), we need to invalidate | |
1284 | // last_anchor_info | |
1285 | ||
deeabbfb | 1286 | if ((conn->airplay_stream_type == buffered_stream) && (conn->ap2_play_enabled != 0) && |
c5dafbd2 MB |
1287 | ((clock_id != conn->anchor_clock) || (conn->anchor_rtptime != rtptime) || |
1288 | (conn->anchor_time != networktime))) { | |
1289 | uint64_t master_clock_id = 0; | |
861455f7 | 1290 | ptp_get_clock_info(&master_clock_id, NULL, NULL, NULL); |
c5dafbd2 MB |
1291 | debug(1, |
1292 | "Connection %d: Note: anchor parameters have changed. Old clock: %" PRIx64 | |
1293 | ", rtptime: %u, networktime: %" PRIu64 ". New clock: %" PRIx64 | |
1294 | ", rtptime: %u, networktime: %" PRIu64 ". Current master clock: %" PRIx64 ".", | |
1295 | conn->connection_number, conn->anchor_clock, conn->anchor_rtptime, conn->anchor_time, | |
1296 | clock_id, rtptime, networktime, master_clock_id); | |
1297 | } | |
1298 | ||
ac515bbf MB |
1299 | if ((clock_id == conn->anchor_clock) && |
1300 | ((conn->anchor_rtptime != rtptime) || (conn->anchor_time != networktime))) { | |
1301 | uint64_t time_now = get_absolute_time_in_ns(); | |
1302 | int64_t last_anchor_validity_duration = time_now - conn->last_anchor_validity_start_time; | |
1303 | if (last_anchor_validity_duration < 5000000000) { | |
c5dafbd2 MB |
1304 | if (conn->airplay_stream_type == buffered_stream) |
1305 | debug(1, | |
1306 | "Connection %d: Note: anchor parameters have changed before clock %" PRIx64 | |
1307 | " has stabilised.", | |
1308 | conn->connection_number, clock_id); | |
ac515bbf MB |
1309 | conn->last_anchor_info_is_valid = 0; |
1310 | } | |
1311 | } | |
c5dafbd2 | 1312 | |
8a73d597 | 1313 | conn->anchor_remote_info_is_valid = 1; |
c5dafbd2 MB |
1314 | |
1315 | // these can be modified if the master clock changes over time | |
8a73d597 MB |
1316 | conn->anchor_rtptime = rtptime; |
1317 | conn->anchor_time = networktime; | |
1318 | conn->anchor_clock = clock_id; | |
1319 | } | |
1320 | ||
1321 | void reset_ptp_anchor_info(rtsp_conn_info *conn) { | |
1322 | debug(2, "Connection %d: Clear anchor information.", conn->connection_number); | |
1323 | conn->last_anchor_info_is_valid = 0; | |
1324 | conn->anchor_remote_info_is_valid = 0; | |
1325 | } | |
1326 | ||
ce49f3a9 | 1327 | int long_time_notifcation_done = 0; |
b19dd9e9 | 1328 | |
8a73d597 | 1329 | int get_ptp_anchor_local_time_info(rtsp_conn_info *conn, uint32_t *anchorRTP, |
a68f28ac | 1330 | uint64_t *anchorLocalTime) { |
fd880056 MB |
1331 | int response = clock_not_valid; |
1332 | uint64_t actual_clock_id; | |
1333 | if (conn->rtsp_link_is_idle == 0) { | |
1334 | uint64_t actual_time_of_sample, actual_offset, start_of_mastership; | |
1335 | response = ptp_get_clock_info(&actual_clock_id, &actual_time_of_sample, &actual_offset, | |
1336 | &start_of_mastership); | |
1337 | if (response == clock_ok) { | |
1338 | uint64_t time_now = get_absolute_time_in_ns(); | |
1339 | int64_t time_since_sample = time_now - actual_time_of_sample; | |
1340 | if (time_since_sample > 300000000000) { | |
1341 | if (long_time_notifcation_done == 0) { | |
1342 | debug(1, "The last PTP timing sample is pretty old: %f seconds.", | |
1343 | 0.000000001 * time_since_sample); | |
1344 | long_time_notifcation_done = 1; | |
1345 | } | |
1346 | } else if ((time_since_sample < 2000000000) && (long_time_notifcation_done != 0)) { | |
1347 | debug(1, "The last PTP timing sample is no longer too old: %f seconds.", | |
4090b2d8 | 1348 | 0.000000001 * time_since_sample); |
fd880056 | 1349 | long_time_notifcation_done = 0; |
ce49f3a9 | 1350 | } |
ce49f3a9 | 1351 | |
fd880056 MB |
1352 | if (conn->anchor_remote_info_is_valid != |
1353 | 0) { // i.e. if we have anchor clock ID and anchor time / rtptime | |
637c8132 | 1354 | |
fd880056 MB |
1355 | if (actual_clock_id == conn->anchor_clock) { |
1356 | conn->last_anchor_rtptime = conn->anchor_rtptime; | |
1357 | conn->last_anchor_local_time = conn->anchor_time - actual_offset; | |
1358 | conn->last_anchor_time_of_update = time_now; | |
1359 | if (conn->last_anchor_info_is_valid == 0) | |
1360 | conn->last_anchor_validity_start_time = start_of_mastership; | |
1361 | conn->last_anchor_info_is_valid = 1; | |
1362 | } else { | |
1363 | debug(3, "Current master clock %" PRIx64 " and anchor_clock %" PRIx64 " are different", | |
1364 | actual_clock_id, conn->anchor_clock); | |
1365 | // the anchor clock and the actual clock are different | |
8a2756b7 | 1366 | |
fd880056 | 1367 | if (conn->last_anchor_info_is_valid != 0) { |
623b760b | 1368 | |
fd880056 MB |
1369 | int64_t time_since_last_update = |
1370 | get_absolute_time_in_ns() - conn->last_anchor_time_of_update; | |
1371 | if (time_since_last_update > 5000000000) { | |
1372 | int64_t duration_of_mastership = time_now - start_of_mastership; | |
1373 | debug(2, | |
1374 | "Connection %d: Master clock has changed to %" PRIx64 | |
1375 | ". History: %.3f milliseconds.", | |
1376 | conn->connection_number, actual_clock_id, 0.000001 * duration_of_mastership); | |
623b760b | 1377 | |
fd880056 MB |
1378 | // Now, the thing is that while the anchor clock and master clock for a |
1379 | // buffered session start off the same, | |
1380 | // the master clock can change without the anchor clock changing. | |
1381 | // SPS gives the new master clock time to settle down and then | |
1382 | // calculates the appropriate offset to it by | |
1383 | // calculating back from the local anchor information and the new clock's | |
1384 | // advertised offset. | |
1385 | ||
1386 | conn->anchor_time = conn->last_anchor_local_time + actual_offset; | |
1387 | conn->anchor_clock = actual_clock_id; | |
623b760b | 1388 | |
fd880056 | 1389 | } |
623b760b | 1390 | |
fd880056 MB |
1391 | } else { |
1392 | response = clock_not_valid; // no current clock information and no previous clock info | |
1393 | } | |
8a73d597 | 1394 | } |
fd880056 MB |
1395 | } else { |
1396 | // debug(1, "anchor_remote_info_is_valid not valid"); | |
1397 | response = clock_no_anchor_info; // no anchor information | |
8a73d597 | 1398 | } |
8a73d597 | 1399 | } |
04c7f845 MB |
1400 | } |
1401 | ||
1402 | // here, check and update the clock status | |
1403 | if ((clock_status_t)response != conn->clock_status) { | |
1404 | switch (response) { | |
1405 | case clock_ok: | |
3b4a21f0 | 1406 | debug(2, "Connection %d: NQPTP master clock %" PRIx64 ".", conn->connection_number, |
e41795f4 | 1407 | actual_clock_id); |
04c7f845 | 1408 | break; |
637c8132 | 1409 | case clock_not_ready: |
a109b587 MB |
1410 | debug(2, "Connection %d: NQPTP master clock %" PRIx64 " is available but not ready.", |
1411 | conn->connection_number, actual_clock_id); | |
637c8132 | 1412 | break; |
04c7f845 MB |
1413 | case clock_service_unavailable: |
1414 | debug(1, "Connection %d: NQPTP clock is not available.", conn->connection_number); | |
1415 | warn("Can't access the NQPTP clock. Is NQPTP running?"); | |
1416 | break; | |
1417 | case clock_access_error: | |
3b4a21f0 | 1418 | debug(2, "Connection %d: Error accessing the NQPTP clock interface.", |
04c7f845 MB |
1419 | conn->connection_number); |
1420 | break; | |
1421 | case clock_data_unavailable: | |
1422 | debug(1, "Connection %d: Can not access NQPTP clock information.", conn->connection_number); | |
1423 | break; | |
1424 | case clock_no_master: | |
a109b587 | 1425 | debug(2, "Connection %d: No NQPTP master clock.", conn->connection_number); |
04c7f845 MB |
1426 | break; |
1427 | case clock_no_anchor_info: | |
3b4a21f0 | 1428 | debug(2, "Connection %d: Awaiting clock anchor information.", conn->connection_number); |
04c7f845 MB |
1429 | break; |
1430 | case clock_version_mismatch: | |
3b4a21f0 | 1431 | debug(2, "Connection %d: NQPTP clock interface mismatch.", conn->connection_number); |
04c7f845 MB |
1432 | warn("This version of Shairport Sync is not compatible with the installed version of NQPTP. " |
1433 | "Please update."); | |
1434 | break; | |
1435 | case clock_not_synchronised: | |
1436 | debug(1, "Connection %d: NQPTP clock is not synchronised.", conn->connection_number); | |
1437 | break; | |
1438 | case clock_not_valid: | |
fd880056 | 1439 | debug(2, "Connection %d: NQPTP clock information is not valid.", conn->connection_number); |
04c7f845 MB |
1440 | break; |
1441 | default: | |
f6a9f634 | 1442 | debug(1, "Connection %d: NQPTP clock reports an unrecognised status: %u.", |
04c7f845 MB |
1443 | conn->connection_number, response); |
1444 | break; | |
1445 | } | |
1446 | conn->clock_status = response; | |
8a73d597 | 1447 | } |
e41795f4 | 1448 | |
26ce13d5 | 1449 | if (conn->last_anchor_info_is_valid != 0) { |
2180c714 | 1450 | if (anchorRTP != NULL) |
26ce13d5 | 1451 | *anchorRTP = conn->last_anchor_rtptime; |
2180c714 | 1452 | if (anchorLocalTime != NULL) |
26ce13d5 | 1453 | *anchorLocalTime = conn->last_anchor_local_time; |
2180c714 | 1454 | } |
703717a5 | 1455 | |
8a73d597 MB |
1456 | return response; |
1457 | } | |
1458 | ||
8a73d597 | 1459 | int have_ptp_timing_information(rtsp_conn_info *conn) { |
04c7f845 | 1460 | if (get_ptp_anchor_local_time_info(conn, NULL, NULL) == clock_ok) |
8a73d597 | 1461 | return 1; |
9fd4a397 | 1462 | else |
8a73d597 MB |
1463 | return 0; |
1464 | } | |
1465 | ||
8a73d597 MB |
1466 | int frame_to_ptp_local_time(uint32_t timestamp, uint64_t *time, rtsp_conn_info *conn) { |
1467 | int result = -1; | |
ad3412f5 MB |
1468 | uint32_t anchor_rtptime = 0; |
1469 | uint64_t anchor_local_time = 0; | |
04c7f845 | 1470 | if (get_ptp_anchor_local_time_info(conn, &anchor_rtptime, &anchor_local_time) == clock_ok) { |
8a73d597 MB |
1471 | int32_t frame_difference = timestamp - anchor_rtptime; |
1472 | int64_t time_difference = frame_difference; | |
1473 | time_difference = time_difference * 1000000000; | |
14bfba27 MB |
1474 | if (conn->input_rate == 0) |
1475 | die("conn->input_rate is zero!"); | |
8a73d597 MB |
1476 | time_difference = time_difference / conn->input_rate; |
1477 | uint64_t ltime = anchor_local_time + time_difference; | |
1478 | *time = ltime; | |
1479 | result = 0; | |
3870195c | 1480 | } else { |
fd880056 | 1481 | debug(3, "frame_to_ptp_local_time can't get anchor local time information"); |
8a73d597 MB |
1482 | } |
1483 | return result; | |
1484 | } | |
1485 | ||
8a73d597 MB |
1486 | int local_ptp_time_to_frame(uint64_t time, uint32_t *frame, rtsp_conn_info *conn) { |
1487 | int result = -1; | |
ad3412f5 MB |
1488 | uint32_t anchor_rtptime = 0; |
1489 | uint64_t anchor_local_time = 0; | |
04c7f845 | 1490 | if (get_ptp_anchor_local_time_info(conn, &anchor_rtptime, &anchor_local_time) == clock_ok) { |
8a73d597 MB |
1491 | int64_t time_difference = time - anchor_local_time; |
1492 | int64_t frame_difference = time_difference; | |
1493 | frame_difference = frame_difference * conn->input_rate; // but this is by 10^9 | |
1494 | frame_difference = frame_difference / 1000000000; | |
1495 | int32_t fd32 = frame_difference; | |
1496 | uint32_t lframe = anchor_rtptime + fd32; | |
1497 | *frame = lframe; | |
1498 | result = 0; | |
1499 | } else { | |
fd880056 | 1500 | debug(3, "local_ptp_time_to_frame can't get anchor local time information"); |
3870195c | 1501 | } |
3870195c | 1502 | return result; |
a2fb5d21 JL |
1503 | } |
1504 | ||
fb151915 MB |
1505 | void rtp_data_receiver_cleanup_handler(void *arg) { |
1506 | rtsp_conn_info *conn = (rtsp_conn_info *)arg; | |
1507 | debug(2, "Connection %d: AP2 Data Receiver Cleanup.", conn->connection_number); | |
1508 | } | |
1509 | ||
1510 | void *rtp_data_receiver(void *arg) { | |
1511 | rtsp_conn_info *conn = (rtsp_conn_info *)arg; | |
f551274a MB |
1512 | if (conn->airplay_stream_category == remote_control_stream) |
1513 | debug(1, "Connection %d (RC): AP2 Data Receiver started", conn->connection_number); | |
1514 | else | |
1515 | debug(1, "Connection %d: AP2 Data Receiver started", conn->connection_number); | |
1516 | ||
fb151915 MB |
1517 | pthread_cleanup_push(rtp_data_receiver_cleanup_handler, arg); |
1518 | ||
1519 | listen(conn->data_socket, 5); | |
1520 | ||
1521 | uint8_t packet[4096]; | |
1522 | ssize_t nread; | |
1523 | SOCKADDR remote_addr; | |
1524 | memset(&remote_addr, 0, sizeof(remote_addr)); | |
1525 | socklen_t addr_size = sizeof(remote_addr); | |
1526 | ||
1527 | int fd = accept(conn->data_socket, (struct sockaddr *)&remote_addr, &addr_size); | |
1528 | debug(1, | |
1529 | "Connection %d: rtp_data_receiver accepted a connection on socket %d and moved to a new " | |
1530 | "socket %d.", | |
1531 | conn->connection_number, conn->data_socket, fd); | |
1532 | intptr_t pfd = fd; | |
1533 | pthread_cleanup_push(socket_cleanup, (void *)pfd); | |
1534 | int finished = 0; | |
1535 | do { | |
1536 | nread = recv(fd, packet, sizeof(packet), 0); | |
1537 | ||
1538 | if (nread < 0) { | |
1539 | char errorstring[1024]; | |
1540 | strerror_r(errno, (char *)errorstring, sizeof(errorstring)); | |
1541 | debug(1, "Connection %d: error in ap2 rtp_data_receiver %d: \"%s\". Could not recv a packet.", | |
1542 | conn->connection_number, errno, errorstring); | |
1543 | // if ((config.diagnostic_drop_packet_fraction == 0.0) || | |
1544 | // (drand48() > config.diagnostic_drop_packet_fraction)) { | |
1545 | } else if (nread > 0) { | |
1546 | ||
1547 | // ssize_t plen = nread; | |
1548 | debug(1, "Connection %d: Packet Received on Data Port.", conn->connection_number); | |
1549 | // } else { | |
1550 | // debug(3, "Event Receiver Thread -- dropping incoming packet to simulate a bad network."); | |
1551 | // } | |
1552 | } else { | |
1553 | finished = 1; | |
1554 | } | |
1555 | } while (finished == 0); | |
1556 | pthread_cleanup_pop(1); // close the socket | |
1557 | pthread_cleanup_pop(1); // do the cleanup | |
1558 | debug(2, "Connection %d: AP2 Data Receiver RTP thread \"normal\" exit.", conn->connection_number); | |
1559 | pthread_exit(NULL); | |
1560 | } | |
1561 | ||
8a73d597 MB |
1562 | void rtp_event_receiver_cleanup_handler(void *arg) { |
1563 | rtsp_conn_info *conn = (rtsp_conn_info *)arg; | |
829ea399 | 1564 | debug(2, "Connection %d: AP2 Event Receiver Cleanup.", conn->connection_number); |
8a73d597 MB |
1565 | } |
1566 | ||
1567 | void *rtp_event_receiver(void *arg) { | |
8a73d597 | 1568 | rtsp_conn_info *conn = (rtsp_conn_info *)arg; |
f551274a | 1569 | if (conn->airplay_stream_category == remote_control_stream) |
524a8a12 | 1570 | debug(2, "Connection %d (RC): AP2 Event Receiver started", conn->connection_number); |
f551274a | 1571 | else |
524a8a12 | 1572 | debug(2, "Connection %d: AP2 Event Receiver started", conn->connection_number); |
8a73d597 MB |
1573 | pthread_cleanup_push(rtp_event_receiver_cleanup_handler, arg); |
1574 | ||
65c6975e | 1575 | // listen(conn->event_socket, 5); // this is now done in the handle_setup_2 code |
8a73d597 MB |
1576 | |
1577 | uint8_t packet[4096]; | |
1578 | ssize_t nread; | |
1579 | SOCKADDR remote_addr; | |
1580 | memset(&remote_addr, 0, sizeof(remote_addr)); | |
1581 | socklen_t addr_size = sizeof(remote_addr); | |
1582 | ||
1583 | int fd = accept(conn->event_socket, (struct sockaddr *)&remote_addr, &addr_size); | |
fb151915 MB |
1584 | debug(2, |
1585 | "Connection %d: rtp_event_receiver accepted a connection on socket %d and moved to a new " | |
1586 | "socket %d.", | |
1587 | conn->connection_number, conn->event_socket, fd); | |
e925e196 MB |
1588 | intptr_t pfd = fd; |
1589 | pthread_cleanup_push(socket_cleanup, (void *)pfd); | |
8a73d597 MB |
1590 | int finished = 0; |
1591 | do { | |
1592 | nread = recv(fd, packet, sizeof(packet), 0); | |
1593 | ||
1594 | if (nread < 0) { | |
1595 | char errorstring[1024]; | |
1596 | strerror_r(errno, (char *)errorstring, sizeof(errorstring)); | |
04c7f845 MB |
1597 | debug(1, |
1598 | "Connection %d: error in ap2 rtp_event_receiver %d: \"%s\". Could not recv a packet.", | |
1599 | conn->connection_number, errno, errorstring); | |
8a73d597 MB |
1600 | // if ((config.diagnostic_drop_packet_fraction == 0.0) || |
1601 | // (drand48() > config.diagnostic_drop_packet_fraction)) { | |
1602 | } else if (nread > 0) { | |
1603 | ||
1604 | // ssize_t plen = nread; | |
fb151915 | 1605 | debug(1, "Connection %d: Packet Received on Event Port.", conn->connection_number); |
8a73d597 | 1606 | if (packet[1] == 0xD7) { |
04c7f845 MB |
1607 | debug(1, |
1608 | "Connection %d: AP2 Event Receiver -- Time Announce RTP packet of type 0x%02X length " | |
1609 | "%d received.", | |
1610 | conn->connection_number, packet[1], nread); | |
8a73d597 | 1611 | } else { |
04c7f845 MB |
1612 | debug(1, |
1613 | "Connection %d: AP2 Event Receiver -- Unknown RTP packet of type 0x%02X length %d " | |
1614 | "received.", | |
1615 | conn->connection_number, packet[1], nread); | |
8a73d597 MB |
1616 | } |
1617 | // } else { | |
1618 | // debug(3, "Event Receiver Thread -- dropping incoming packet to simulate a bad network."); | |
1619 | // } | |
1620 | } else { | |
1621 | finished = 1; | |
1622 | } | |
1623 | } while (finished == 0); | |
8a73d597 | 1624 | pthread_cleanup_pop(1); // close the socket |
8a73d597 | 1625 | pthread_cleanup_pop(1); // do the cleanup |
3f779949 MB |
1626 | debug(2, "Connection %d: AP2 Event Receiver RTP thread \"normal\" exit.", |
1627 | conn->connection_number); | |
8a73d597 MB |
1628 | pthread_exit(NULL); |
1629 | } | |
1630 | ||
1631 | void rtp_ap2_control_handler_cleanup_handler(void *arg) { | |
1632 | rtsp_conn_info *conn = (rtsp_conn_info *)arg; | |
1633 | debug(2, "Connection %d: AP2 Control Receiver Cleanup.", conn->connection_number); | |
829ea399 | 1634 | close(conn->ap2_control_socket); |
c0a3dacf MB |
1635 | debug(2, "Connection %d: UDP control port %u closed.", conn->connection_number, |
1636 | conn->local_ap2_control_port); | |
829ea399 MB |
1637 | conn->ap2_control_socket = 0; |
1638 | conn->ap2_remote_control_socket_addr_length = | |
1639 | 0; // indicates to the control receiver thread that the socket address need to be | |
1640 | // recreated (needed for resend requests in the realtime mode) | |
8a73d597 MB |
1641 | } |
1642 | ||
1643 | int32_t decipher_player_put_packet(uint8_t *ciphered_audio_alt, ssize_t nread, | |
1644 | rtsp_conn_info *conn) { | |
1645 | ||
1646 | // this deciphers the packet -- it doesn't decode it from ALAC | |
1647 | uint16_t sequence_number = 0; | |
1648 | ||
1649 | // if the packet is too small, don't go ahead. | |
1650 | // it must contain an uint16_t sequence number and eight bytes of AAD followed by the | |
1651 | // ciphertext and then followed by an eight-byte nonce. Thus it must be greater than 18 | |
1652 | if (nread > 18) { | |
1653 | ||
1654 | memcpy(&sequence_number, ciphered_audio_alt, sizeof(uint16_t)); | |
1655 | sequence_number = ntohs(sequence_number); | |
1656 | ||
1657 | uint32_t timestamp; | |
1658 | memcpy(×tamp, ciphered_audio_alt + sizeof(uint16_t), sizeof(uint32_t)); | |
1659 | timestamp = ntohl(timestamp); | |
1660 | ||
1661 | /* | |
1662 | uint32_t ssrc; | |
1663 | memcpy(&ssrc, packet+8, sizeof(uint32_t)); | |
1664 | ssrc = ntohl(ssrc); | |
1665 | */ | |
1666 | ||
1667 | // debug(1, "Realtime Audio Receiver Packet received. Version: %u, Padding: %u, Extension: | |
1668 | // %u, Csrc Count: %u, Marker: %u, Payload Type: %u, Sequence Number: %u, Timestamp: %u, | |
1669 | // SSRC: %u.", version, padding, extension, csrc_count, marker, payload_type, | |
1670 | // sequence_number, timestamp, ssrc); | |
1046a076 MB |
1671 | |
1672 | if (conn->session_key != NULL) { | |
1673 | unsigned char nonce[12]; | |
1674 | memset(nonce, 0, sizeof(nonce)); | |
1675 | memcpy(nonce + 4, ciphered_audio_alt + nread - 8, | |
1676 | 8); // front-pad the 8-byte nonce received to get the 12-byte nonce expected | |
1677 | ||
1678 | // https://libsodium.gitbook.io/doc/secret-key_cryptography/aead/chacha20-poly1305/ietf_chacha20-poly1305_construction | |
1679 | // Note: the eight-byte nonce must be front-padded out to 12 bytes. | |
1680 | ||
1681 | unsigned char m[4096]; | |
1682 | unsigned long long new_payload_length = 0; | |
1683 | int response = crypto_aead_chacha20poly1305_ietf_decrypt( | |
1684 | m, // m | |
1685 | &new_payload_length, // mlen_p | |
1686 | NULL, // nsec, | |
1687 | ciphered_audio_alt + | |
1688 | 10, // the ciphertext starts 10 bytes in and is followed by the MAC tag, | |
1689 | nread - (8 + 10), // clen -- the last 8 bytes are the nonce | |
1690 | ciphered_audio_alt + 2, // authenticated additional data | |
1691 | 8, // authenticated additional data length | |
1692 | nonce, | |
1693 | conn->session_key); // *k | |
1694 | if (response != 0) { | |
1695 | debug(1, "Error decrypting an audio packet."); | |
1696 | } | |
1697 | // now pass it in to the regular processing chain | |
1698 | ||
1699 | unsigned long long max_int = INT_MAX; // put in the right format | |
1700 | if (new_payload_length > max_int) | |
1701 | debug(1, "Madly long payload length!"); | |
1702 | int plen = new_payload_length; // | |
1703 | // debug(1," Write packet to buffer %d, timestamp %u.", sequence_number, timestamp); | |
1704 | player_put_packet(1, sequence_number, timestamp, m, plen, | |
1705 | conn); // the '1' means is original format | |
1706 | } else { | |
1707 | debug(2, "No session key, so the audio packet can not be deciphered -- skipped."); | |
8a73d597 | 1708 | } |
8a73d597 MB |
1709 | return sequence_number; |
1710 | } else { | |
1711 | debug(1, "packet was too small -- ignored"); | |
1712 | return -1; | |
1713 | } | |
1714 | } | |
1715 | ||
1716 | void *rtp_ap2_control_receiver(void *arg) { | |
1717 | pthread_cleanup_push(rtp_ap2_control_handler_cleanup_handler, arg); | |
1718 | rtsp_conn_info *conn = (rtsp_conn_info *)arg; | |
1719 | uint8_t packet[4096]; | |
1720 | ssize_t nread; | |
829ea399 | 1721 | int keep_going = 1; |
703717a5 MB |
1722 | uint64_t start_time = get_absolute_time_in_ns(); |
1723 | uint64_t packet_number = 0; | |
829ea399 | 1724 | while (keep_going) { |
8a73d597 MB |
1725 | SOCKADDR from_sock_addr; |
1726 | socklen_t from_sock_addr_length = sizeof(SOCKADDR); | |
1727 | memset(&from_sock_addr, 0, sizeof(SOCKADDR)); | |
3cc1ec6a | 1728 | |
8a73d597 MB |
1729 | nread = recvfrom(conn->ap2_control_socket, packet, sizeof(packet), 0, |
1730 | (struct sockaddr *)&from_sock_addr, &from_sock_addr_length); | |
703717a5 | 1731 | uint64_t time_now = get_absolute_time_in_ns(); |
703717a5 | 1732 | int64_t time_since_start = time_now - start_time; |
a617e607 | 1733 | |
fd880056 MB |
1734 | if (conn->rtsp_link_is_idle == 0) { |
1735 | if (conn->udp_clock_is_initialised == 0) { | |
1736 | packet_number = 0; | |
1737 | conn->udp_clock_is_initialised = 1; | |
1738 | debug(1,"AP2 Realtime Clock receiver initialised."); | |
1739 | } | |
1740 | ||
1741 | // debug(1,"Connection %d: AP2 Control Packet received.", conn->connection_number); | |
703717a5 | 1742 | |
fd880056 MB |
1743 | if (nread >= 28) { // must have at least 28 bytes for the timing information |
1744 | if ((time_since_start < 2000000) && ((packet[0] & 0x10) == 0)) { | |
1745 | debug(1, | |
1746 | "Dropping what looks like a (non-sentinel) packet left over from a previous session " | |
1747 | "at %f ms.", | |
1748 | 0.000001 * time_since_start); | |
1749 | } else { | |
1750 | packet_number++; | |
1751 | // debug(1,"AP2 Packet %" PRIu64 ".", packet_number); | |
8a73d597 | 1752 | |
fd880056 MB |
1753 | if (packet_number == 1) { |
1754 | if ((packet[0] & 0x10) != 0) { | |
1755 | debug(2, "First packet is a sentinel packet."); | |
1756 | } else { | |
1757 | debug(2, "First packet is a not a sentinel packet!"); | |
1758 | } | |
deb11654 | 1759 | } |
fd880056 MB |
1760 | // debug(1,"rtp_ap2_control_receiver coded: %u, %u", packet[0], packet[1]); |
1761 | // you might want to set this higher to specify how many initial timings to ignore | |
1762 | if (packet_number >= 1) { | |
1763 | if ((config.diagnostic_drop_packet_fraction == 0.0) || | |
1764 | (drand48() > config.diagnostic_drop_packet_fraction)) { | |
1765 | // store the from_sock_addr if we haven't already done so | |
1766 | // v remember to zero this when you're finished! | |
1767 | if (conn->ap2_remote_control_socket_addr_length == 0) { | |
1768 | memcpy(&conn->ap2_remote_control_socket_addr, &from_sock_addr, from_sock_addr_length); | |
1769 | conn->ap2_remote_control_socket_addr_length = from_sock_addr_length; | |
1770 | } | |
1771 | switch (packet[1]) { | |
1772 | case 215: // code 215, effectively an anchoring announcement | |
1773 | { | |
1774 | // struct timespec tnr; | |
1775 | // clock_gettime(CLOCK_REALTIME, &tnr); | |
1776 | // uint64_t local_realtime_now = timespec_to_ns(&tnr); | |
1777 | ||
1778 | /* | |
1779 | char obf[4096]; | |
1780 | char *obfp = obf; | |
1781 | int obfc; | |
1782 | for (obfc=0;obfc<nread;obfc++) { | |
1783 | snprintf(obfp, 3, "%02X", packet[obfc]); | |
1784 | obfp+=2; | |
1785 | }; | |
1786 | *obfp=0; | |
1787 | debug(1,"AP2 Timing Control Received: \"%s\"",obf); | |
1788 | */ | |
1789 | ||
1790 | uint64_t remote_packet_time_ns = nctoh64(packet + 8); | |
1791 | check64conversion("remote_packet_time_ns", packet + 8, remote_packet_time_ns); | |
1792 | uint64_t clock_id = nctoh64(packet + 20); | |
1793 | check64conversion("clock_id", packet + 20, clock_id); | |
1794 | ||
1795 | // debug(1, "we have clock_id: %" PRIx64 ".", clock_id); | |
1796 | // debug(1,"remote_packet_time_ns: %" PRIx64 ", local_realtime_now_ns: %" PRIx64 ".", | |
1797 | // remote_packet_time_ns, local_realtime_now); | |
1798 | uint32_t frame_1 = | |
1799 | nctohl(packet + 4); // this seems to be the frame with latency of 77165 included | |
1800 | check32conversion("frame_1", packet + 4, frame_1); | |
1801 | uint32_t frame_2 = nctohl(packet + 16); // this seems to be the frame the time refers to | |
1802 | check32conversion("frame_2", packet + 16, frame_2); | |
1803 | // this just updates the anchor information contained in the packet | |
1804 | // the frame and its remote time | |
1805 | // add in the audio_backend_latency_offset; | |
1806 | int32_t notified_latency = frame_2 - frame_1; | |
1807 | if (notified_latency != 77175) | |
1808 | debug(1, "Notified latency is %d frames.", notified_latency); | |
1809 | int32_t added_latency = | |
1810 | (int32_t)(config.audio_backend_latency_offset * conn->input_rate); | |
1811 | // the actual latency is the notified latency plus the fixed latency + the added latency | |
1812 | ||
1813 | int32_t net_latency = | |
1814 | notified_latency + 11035 + | |
1815 | added_latency; // this is the latency between incoming frames and the DAC | |
1816 | net_latency = net_latency - | |
1817 | (int32_t)(config.audio_backend_buffer_desired_length * conn->input_rate); | |
1818 | // debug(1, "Net latency is %d frames.", net_latency); | |
1819 | ||
1820 | if (net_latency <= 0) { | |
1821 | if (conn->latency_warning_issued == 0) { | |
1822 | warn("The stream latency (%f seconds) it too short to accommodate an offset of %f " | |
1823 | "seconds and a backend buffer of %f seconds.", | |
1824 | ((notified_latency + 11035) * 1.0) / conn->input_rate, | |
1825 | config.audio_backend_latency_offset, | |
1826 | config.audio_backend_buffer_desired_length); | |
1827 | warn("(FYI the stream latency needed would be %f seconds.)", | |
1828 | config.audio_backend_buffer_desired_length - | |
1829 | config.audio_backend_latency_offset); | |
1830 | conn->latency_warning_issued = 1; | |
1831 | } | |
1832 | conn->latency = notified_latency + 11035; | |
1833 | } else { | |
1834 | conn->latency = notified_latency + 11035 + added_latency; | |
1835 | } | |
deb11654 | 1836 | |
fd880056 MB |
1837 | set_ptp_anchor_info(conn, clock_id, frame_1 - 11035 - added_latency, |
1838 | remote_packet_time_ns); | |
1839 | if (conn->anchor_clock != clock_id) { | |
1840 | debug(2, "Connection %d: Change Anchor Clock: %" PRIx64 ".", conn->connection_number, | |
1841 | clock_id); | |
deb11654 | 1842 | } |
8a73d597 | 1843 | |
fd880056 MB |
1844 | } break; |
1845 | case 0xd6: | |
1846 | // six bytes in is the sequence number at the start of the encrypted audio packet | |
1847 | // returns the sequence number but we're not really interested | |
1848 | decipher_player_put_packet(packet + 6, nread - 6, conn); | |
1849 | break; | |
1850 | default: { | |
1851 | char *packet_in_hex_cstring = | |
1852 | debug_malloc_hex_cstring(packet, nread); // remember to free this afterwards | |
1853 | debug( | |
1854 | 1, | |
1855 | "AP2 Control Receiver Packet of first byte 0x%02X, type 0x%02X length %d received: " | |
1856 | "\"%s\".", | |
1857 | packet[0], packet[1], nread, packet_in_hex_cstring); | |
1858 | free(packet_in_hex_cstring); | |
1859 | } break; | |
8a2756b7 | 1860 | } |
fd880056 MB |
1861 | } else { |
1862 | debug(1, "AP2 Control Receiver -- dropping a packet."); | |
1863 | } | |
deb11654 | 1864 | } |
3cc1ec6a | 1865 | } |
fd880056 MB |
1866 | } else { |
1867 | if (nread == -1) { | |
1868 | if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { | |
1869 | if (conn->airplay_stream_type == realtime_stream) { | |
1870 | debug(1, "Connection %d: no control packets for the last 7 seconds -- resetting anchor info", conn->connection_number); | |
1871 | reset_ptp_anchor_info(conn); | |
1872 | packet_number = 0; // start over in allowing the packet to set anchor information | |
1873 | } | |
1874 | } else { | |
1875 | debug(2, "Connection %d: AP2 Control Receiver -- error %d receiving a packet.", conn->connection_number, errno); | |
a617e607 MB |
1876 | } |
1877 | } else { | |
fd880056 | 1878 | debug(2, "Connection %d: AP2 Control Receiver -- malformed packet, %d bytes long.", conn->connection_number, nread); |
3cc1ec6a | 1879 | } |
3cc1ec6a | 1880 | } |
8a73d597 MB |
1881 | } |
1882 | } | |
1883 | debug(1, "AP2 Control RTP thread \"normal\" exit -- this can't happen. Hah!"); | |
829ea399 | 1884 | pthread_cleanup_pop(1); |
8a73d597 MB |
1885 | debug(1, "AP2 Control RTP thread exit."); |
1886 | pthread_exit(NULL); | |
1887 | } | |
1888 | ||
1889 | void rtp_realtime_audio_cleanup_handler(__attribute__((unused)) void *arg) { | |
829ea399 | 1890 | debug(2, "Realtime Audio Receiver Cleanup Start."); |
5c418702 | 1891 | rtsp_conn_info *conn = (rtsp_conn_info *)arg; |
8a73d597 | 1892 | close(conn->realtime_audio_socket); |
56bef8e7 | 1893 | debug(2, "Connection %d: closing realtime audio port %u", conn->local_realtime_audio_port); |
8a73d597 | 1894 | conn->realtime_audio_socket = 0; |
829ea399 | 1895 | debug(2, "Realtime Audio Receiver Cleanup Done."); |
8a73d597 MB |
1896 | } |
1897 | ||
1898 | void *rtp_realtime_audio_receiver(void *arg) { | |
1899 | pthread_cleanup_push(rtp_realtime_audio_cleanup_handler, arg); | |
1900 | rtsp_conn_info *conn = (rtsp_conn_info *)arg; | |
1901 | uint8_t packet[4096]; | |
1902 | int32_t last_seqno = -1; | |
1903 | ssize_t nread; | |
1904 | while (1) { | |
1905 | nread = recv(conn->realtime_audio_socket, packet, sizeof(packet), 0); | |
1906 | ||
1907 | if (nread > 36) { // 36 is the 12-byte header and and 24-byte footer | |
1908 | if ((config.diagnostic_drop_packet_fraction == 0.0) || | |
1909 | (drand48() > config.diagnostic_drop_packet_fraction)) { | |
1910 | ||
1911 | /* | |
1912 | char *packet_in_hex_cstring = | |
1913 | debug_malloc_hex_cstring(packet, nread); // remember to free this afterwards | |
1914 | debug(1, "Audio Receiver Packet of type 0x%02X length %d received: \"%s\".", | |
1915 | packet[1], nread, packet_in_hex_cstring); | |
1916 | free(packet_in_hex_cstring); | |
1917 | */ | |
1918 | ||
1919 | /* | |
1920 | // debug(1, "Realtime Audio Receiver Packet of type 0x%02X length %d received.", packet[1], | |
1921 | nread); | |
1922 | // now get hold of its various bits and pieces | |
1923 | uint8_t version = (packet[0] & 0b11000000) >> 6; | |
1924 | uint8_t padding = (packet[0] & 0b00100000) >> 5; | |
1925 | uint8_t extension = (packet[0] & 0b00010000) >> 4; | |
1926 | uint8_t csrc_count = packet[0] & 0b00001111; | |
1927 | uint8_t marker = (packet[1] & 0b1000000) >> 7; | |
1928 | uint8_t payload_type = packet[1] & 0b01111111; | |
1929 | */ | |
3cc1ec6a MB |
1930 | // if (have_ptp_timing_information(conn)) { |
1931 | if (1) { | |
8a73d597 MB |
1932 | int32_t seqno = decipher_player_put_packet(packet + 2, nread - 2, conn); |
1933 | if (seqno >= 0) { | |
1934 | if (last_seqno == -1) { | |
1935 | last_seqno = seqno; | |
1936 | } else { | |
1937 | last_seqno = (last_seqno + 1) & 0xffff; | |
1938 | // if (seqno != last_seqno) | |
1939 | // debug(3, "RTP: Packets out of sequence: expected: %d, got %d.", last_seqno, seqno); | |
1940 | last_seqno = seqno; // reset warning... | |
1941 | } | |
1942 | } else { | |
1943 | debug(1, "Realtime Audio Receiver -- bad packet dropped."); | |
1944 | } | |
3cc1ec6a | 1945 | } |
8a73d597 MB |
1946 | } else { |
1947 | debug(3, "Realtime Audio Receiver -- dropping a packet."); | |
1948 | } | |
1949 | } else { | |
1950 | debug(1, "Realtime Audio Receiver -- error receiving a packet."); | |
1951 | } | |
1952 | } | |
1953 | pthread_cleanup_pop(0); // don't execute anything here. | |
1954 | pthread_exit(NULL); | |
1955 | } | |
1956 | ||
a382ac66 MB |
1957 | ssize_t buffered_read(buffered_tcp_desc *descriptor, void *buf, size_t count, |
1958 | size_t *bytes_remaining) { | |
e925e196 | 1959 | ssize_t response = -1; |
8a73d597 MB |
1960 | if (pthread_mutex_lock(&descriptor->mutex) != 0) |
1961 | debug(1, "problem with mutex"); | |
1962 | pthread_cleanup_push(mutex_unlock, (void *)&descriptor->mutex); | |
e925e196 | 1963 | if (descriptor->closed == 0) { |
08afa822 MB |
1964 | if ((descriptor->buffer_occupancy == 0) && (descriptor->error_code == 0)) { |
1965 | if (count == 2) | |
1966 | debug(2, "buffered_read: waiting for %u bytes (okay at start of a track).", count); | |
1967 | else | |
8a2756b7 | 1968 | debug(2, "buffered_read: waiting for %u bytes.", count); |
a382ac66 | 1969 | } |
8a73d597 MB |
1970 | while ((descriptor->buffer_occupancy == 0) && (descriptor->error_code == 0)) { |
1971 | if (pthread_cond_wait(&descriptor->not_empty_cv, &descriptor->mutex)) | |
1972 | debug(1, "Error waiting for buffered read"); | |
1973 | } | |
1974 | } | |
1975 | if (descriptor->buffer_occupancy != 0) { | |
1976 | ssize_t bytes_to_move = count; | |
1977 | ||
08afa822 | 1978 | if (descriptor->buffer_occupancy < count) { |
8a73d597 | 1979 | bytes_to_move = descriptor->buffer_occupancy; |
08afa822 | 1980 | } |
8a73d597 MB |
1981 | |
1982 | ssize_t top_gap = descriptor->buffer + descriptor->buffer_max_size - descriptor->toq; | |
1983 | if (top_gap < bytes_to_move) | |
1984 | bytes_to_move = top_gap; | |
1985 | ||
1986 | memcpy(buf, descriptor->toq, bytes_to_move); | |
1987 | descriptor->toq += bytes_to_move; | |
1988 | if (descriptor->toq == descriptor->buffer + descriptor->buffer_max_size) | |
1989 | descriptor->toq = descriptor->buffer; | |
1990 | descriptor->buffer_occupancy -= bytes_to_move; | |
08afa822 MB |
1991 | if (bytes_remaining != NULL) |
1992 | *bytes_remaining = descriptor->buffer_occupancy; | |
8a73d597 MB |
1993 | response = bytes_to_move; |
1994 | if (pthread_cond_signal(&descriptor->not_full_cv)) | |
1995 | debug(1, "Error signalling"); | |
1996 | } else if (descriptor->error_code) { | |
1997 | errno = descriptor->error_code; | |
1998 | response = -1; | |
1999 | } else if (descriptor->closed != 0) { | |
2000 | response = 0; | |
2001 | } | |
2002 | ||
2003 | pthread_cleanup_pop(1); // release the mutex | |
2004 | return response; | |
2005 | } | |
2006 | ||
829ea399 | 2007 | #define STANDARD_PACKET_SIZE 4096 |
8a73d597 MB |
2008 | |
2009 | void buffered_tcp_reader_cleanup_handler(__attribute__((unused)) void *arg) { | |
04c7f845 | 2010 | debug(2, "Buffered TCP Reader Thread Exit via Cleanup."); |
8a73d597 MB |
2011 | } |
2012 | ||
2013 | void *buffered_tcp_reader(void *arg) { | |
2014 | pthread_cleanup_push(buffered_tcp_reader_cleanup_handler, NULL); | |
2015 | buffered_tcp_desc *descriptor = (buffered_tcp_desc *)arg; | |
2016 | ||
65c6975e MB |
2017 | // listen(descriptor->sock_fd, 5); // this is done in the handle_setup_2 code to ensure it's open |
2018 | // when the client hears about it... | |
8a73d597 MB |
2019 | ssize_t nread; |
2020 | SOCKADDR remote_addr; | |
2021 | memset(&remote_addr, 0, sizeof(remote_addr)); | |
2022 | socklen_t addr_size = sizeof(remote_addr); | |
2023 | int finished = 0; | |
2024 | int fd = accept(descriptor->sock_fd, (struct sockaddr *)&remote_addr, &addr_size); | |
e925e196 MB |
2025 | intptr_t pfd = fd; |
2026 | pthread_cleanup_push(socket_cleanup, (void *)pfd); | |
8a73d597 MB |
2027 | |
2028 | do { | |
2029 | if (pthread_mutex_lock(&descriptor->mutex) != 0) | |
2030 | debug(1, "problem with mutex"); | |
2031 | pthread_cleanup_push(mutex_unlock, (void *)&descriptor->mutex); | |
2032 | while ((descriptor->buffer_occupancy == descriptor->buffer_max_size) || | |
2033 | (descriptor->error_code != 0) || (descriptor->closed != 0)) { | |
2034 | if (pthread_cond_wait(&descriptor->not_full_cv, &descriptor->mutex)) | |
2035 | debug(1, "Error waiting for buffered read"); | |
2036 | } | |
2037 | pthread_cleanup_pop(1); // release the mutex | |
2038 | ||
2039 | // now we know it is not full, so go ahead and try to read some more into it | |
2040 | ||
2041 | // wrap | |
2042 | if ((size_t)(descriptor->eoq - descriptor->buffer) == descriptor->buffer_max_size) | |
2043 | descriptor->eoq = descriptor->buffer; | |
2044 | ||
2045 | // figure out how much to ask for | |
2046 | size_t bytes_to_request = STANDARD_PACKET_SIZE; | |
2047 | size_t free_space = descriptor->buffer_max_size - descriptor->buffer_occupancy; | |
2048 | if (bytes_to_request > free_space) | |
2049 | bytes_to_request = free_space; // don't ask for more than will fit | |
2050 | ||
2051 | size_t gap_to_end_of_buffer = | |
2052 | descriptor->buffer + descriptor->buffer_max_size - descriptor->eoq; | |
2053 | if (gap_to_end_of_buffer < bytes_to_request) | |
2054 | bytes_to_request = | |
2055 | gap_to_end_of_buffer; // only ask for what will fill to the top of the buffer | |
2056 | ||
2057 | // do the read | |
2058 | // debug(1, "Request buffered read of up to %d bytes.", bytes_to_request); | |
2059 | nread = recv(fd, descriptor->eoq, bytes_to_request, 0); | |
65c6975e | 2060 | // debug(1, "Received %d bytes for a buffer size of %d bytes.",nread, descriptor->buffer_occupancy + nread); |
8a73d597 MB |
2061 | if (pthread_mutex_lock(&descriptor->mutex) != 0) |
2062 | debug(1, "problem with not empty mutex"); | |
2063 | pthread_cleanup_push(mutex_unlock, (void *)&descriptor->mutex); | |
2064 | if (nread < 0) { | |
2065 | char errorstring[1024]; | |
2066 | strerror_r(errno, (char *)errorstring, sizeof(errorstring)); | |
a382ac66 MB |
2067 | debug(1, "error in buffered_tcp_reader %d: \"%s\". Could not recv a packet.", errno, |
2068 | errorstring); | |
8a73d597 MB |
2069 | descriptor->error_code = errno; |
2070 | } else if (nread == 0) { | |
2071 | descriptor->closed = 1; | |
2072 | } else if (nread > 0) { | |
2073 | descriptor->eoq += nread; | |
2074 | descriptor->buffer_occupancy += nread; | |
2075 | } else { | |
2076 | debug(1, "buffered audio port closed!"); | |
2077 | } | |
2078 | // signal if we got data or an error or the file closed | |
2079 | if (pthread_cond_signal(&descriptor->not_empty_cv)) | |
2080 | debug(1, "Error signalling"); | |
2081 | pthread_cleanup_pop(1); // release the mutex | |
2082 | } while (finished == 0); | |
2083 | ||
2084 | debug(1, "Buffered TCP Reader Thread Exit \"Normal\" Exit Begin."); | |
2085 | pthread_cleanup_pop(1); // close the socket | |
2086 | pthread_cleanup_pop(1); // cleanup | |
2087 | debug(1, "Buffered TCP Reader Thread Exit \"Normal\" Exit -- Shouldn't happen!."); | |
2088 | pthread_exit(NULL); | |
2089 | } | |
2090 | ||
2091 | void avcodec_alloc_context3_cleanup_handler(void *arg) { | |
2092 | debug(3, "avcodec_alloc_context3_cleanup_handler"); | |
2093 | AVCodecContext *codec_context = arg; | |
2094 | av_free(codec_context); | |
2095 | } | |
2096 | ||
2097 | void avcodec_open2_cleanup_handler(void *arg) { | |
2098 | debug(3, "avcodec_open2_cleanup_handler"); | |
2099 | AVCodecContext *codec_context = arg; | |
2100 | avcodec_close(codec_context); | |
2101 | } | |
2102 | ||
2103 | void av_parser_init_cleanup_handler(void *arg) { | |
2104 | debug(3, "av_parser_init_cleanup_handler"); | |
2105 | AVCodecParserContext *codec_parser_context = arg; | |
2106 | av_parser_close(codec_parser_context); | |
2107 | } | |
2108 | ||
2109 | void swr_alloc_cleanup_handler(void *arg) { | |
2110 | debug(3, "swr_alloc_cleanup_handler"); | |
2111 | SwrContext **swr = arg; | |
2112 | swr_free(swr); | |
2113 | } | |
2114 | ||
2115 | void av_packet_alloc_cleanup_handler(void *arg) { | |
2116 | debug(3, "av_packet_alloc_cleanup_handler"); | |
2117 | AVPacket **pkt = arg; | |
2118 | av_packet_free(pkt); | |
2119 | } | |
2120 | ||
2121 | // this will read a block of the size specified to the buffer | |
2122 | // and will return either with the block or on error | |
a382ac66 MB |
2123 | ssize_t lread_sized_block(buffered_tcp_desc *descriptor, void *buf, size_t count, |
2124 | size_t *bytes_remaining) { | |
8a73d597 MB |
2125 | ssize_t response, nread; |
2126 | size_t inbuf = 0; // bytes already in the buffer | |
2127 | int keep_trying = 1; | |
2128 | ||
2129 | do { | |
08afa822 | 2130 | nread = buffered_read(descriptor, buf + inbuf, count - inbuf, bytes_remaining); |
8a73d597 MB |
2131 | if (nread == 0) { |
2132 | // a blocking read that returns zero means eof -- implies connection closed | |
2133 | debug(3, "read_sized_block connection closed."); | |
2134 | keep_trying = 0; | |
2135 | } else if (nread < 0) { | |
2136 | if (errno == EAGAIN) { | |
2137 | debug(1, "read_sized_block getting Error 11 -- EAGAIN from a blocking read!"); | |
2138 | } | |
2139 | if ((errno != ECONNRESET) && (errno != EAGAIN) && (errno != EINTR)) { | |
2140 | char errorstring[1024]; | |
2141 | strerror_r(errno, (char *)errorstring, sizeof(errorstring)); | |
2142 | debug(1, "read_sized_block read error %d: \"%s\".", errno, (char *)errorstring); | |
2143 | keep_trying = 0; | |
2144 | } | |
2145 | } else { | |
2146 | inbuf += (size_t)nread; | |
2147 | } | |
2148 | } while ((keep_trying != 0) && (inbuf < count)); | |
2149 | if (nread <= 0) | |
2150 | response = nread; | |
2151 | else | |
2152 | response = inbuf; | |
2153 | return response; | |
2154 | } | |
2155 | ||
2156 | // From | |
2157 | // https://stackoverflow.com/questions/18862715/how-to-generate-the-aac-adts-elementary-stream-with-android-mediacodec | |
2158 | // with thanks! | |
2159 | /** | |
2160 | * Add ADTS header at the beginning of each and every AAC packet. | |
2161 | * This is needed as MediaCodec encoder generates a packet of raw | |
2162 | * AAC data. | |
2163 | * | |
2164 | * Note the packetLen must count in the ADTS header itself. | |
2165 | **/ | |
2166 | void addADTStoPacket(uint8_t *packet, int packetLen) { | |
2167 | int profile = 2; // AAC LC | |
2168 | // 39=MediaCodecInfo.CodecProfileLevel.AACObjectELD; | |
2169 | int freqIdx = 4; // 44.1KHz | |
2170 | int chanCfg = 2; // CPE | |
2171 | ||
2172 | // fill in ADTS data | |
2173 | packet[0] = 0xFF; | |
2174 | packet[1] = 0xF9; | |
2175 | packet[2] = ((profile - 1) << 6) + (freqIdx << 2) + (chanCfg >> 2); | |
2176 | packet[3] = ((chanCfg & 3) << 6) + (packetLen >> 11); | |
2177 | packet[4] = (packetLen & 0x7FF) >> 3; | |
2178 | packet[5] = ((packetLen & 7) << 5) + 0x1F; | |
2179 | packet[6] = 0xFC; | |
2180 | } | |
2181 | ||
2182 | void rtp_buffered_audio_cleanup_handler(__attribute__((unused)) void *arg) { | |
04c7f845 | 2183 | debug(2, "Buffered Audio Receiver Cleanup Start."); |
8a73d597 MB |
2184 | rtsp_conn_info *conn = (rtsp_conn_info *)arg; |
2185 | close(conn->buffered_audio_socket); | |
c0a3dacf MB |
2186 | debug(2, "Connection %d: TCP Buffered Audio port closed: %u.", conn->connection_number, |
2187 | conn->local_buffered_audio_port); | |
8a73d597 | 2188 | conn->buffered_audio_socket = 0; |
04c7f845 | 2189 | debug(2, "Buffered Audio Receiver Cleanup Done."); |
8a73d597 MB |
2190 | } |
2191 | ||
a109b587 MB |
2192 | // not used right now, but potentially useful for understanding flush requests |
2193 | void display_flush_requests(int activeOnly, uint32_t currentSeq, uint32_t currentTS, | |
2194 | rtsp_conn_info *conn) { | |
2195 | if (conn->flush_requests == NULL) { | |
2196 | if (activeOnly == 0) | |
2197 | debug(1, "No flush requests."); | |
2198 | } else { | |
2199 | flush_request_t *t = conn->flush_requests; | |
2200 | do { | |
2201 | if (t->flushNow) { | |
2202 | debug(1, "immediate flush to untilSeq: %u, untilTS: %u.", t->flushUntilSeq, | |
2203 | t->flushUntilTS); | |
2204 | } else { | |
2205 | if (activeOnly == 0) | |
2206 | debug(1, "fromSeq: %u, fromTS: %u, to untilSeq: %u, untilTS: %u.", t->flushFromSeq, | |
2207 | t->flushFromTS, t->flushUntilSeq, t->flushUntilTS); | |
2208 | else if ((activeOnly == 1) && | |
2209 | (currentSeq >= | |
2210 | (t->flushFromSeq - | |
2211 | 1))) // the -1 is because you might have to trim the end of the previous block | |
2212 | debug(1, | |
2213 | "fromSeq: %u, fromTS: %u, to untilSeq: %u, untilTS: %u, with currentSeq: %u, " | |
2214 | "currentTS: %u.", | |
2215 | t->flushFromSeq, t->flushFromTS, t->flushUntilSeq, t->flushUntilTS, currentSeq, | |
2216 | currentTS); | |
2217 | } | |
2218 | t = t->next; | |
2219 | } while (t != NULL); | |
2220 | } | |
2221 | } | |
2222 | ||
8a73d597 MB |
2223 | void *rtp_buffered_audio_processor(void *arg) { |
2224 | rtsp_conn_info *conn = (rtsp_conn_info *)arg; | |
2225 | pthread_cleanup_push(rtp_buffered_audio_cleanup_handler, arg); | |
2226 | ||
2227 | pthread_t *buffered_reader_thread = malloc(sizeof(pthread_t)); | |
2228 | if (buffered_reader_thread == NULL) | |
2229 | debug(1, "cannot allocate a buffered_reader_thread!"); | |
2230 | memset(buffered_reader_thread, 0, sizeof(pthread_t)); | |
2231 | pthread_cleanup_push(malloc_cleanup, buffered_reader_thread); | |
2232 | ||
2233 | buffered_tcp_desc *buffered_audio = malloc(sizeof(buffered_tcp_desc)); | |
2234 | if (buffered_audio == NULL) | |
2235 | debug(1, "cannot allocate a buffered_tcp_desc!"); | |
2236 | // initialise the descriptor | |
2237 | memset(buffered_audio, 0, sizeof(buffered_tcp_desc)); | |
2238 | pthread_cleanup_push(malloc_cleanup, buffered_audio); | |
2239 | ||
2240 | if (pthread_mutex_init(&buffered_audio->mutex, NULL)) | |
2241 | debug(1, "Connection %d: error %d initialising buffered_audio mutex.", conn->connection_number, | |
2242 | errno); | |
2243 | pthread_cleanup_push(mutex_cleanup, &buffered_audio->mutex); | |
2244 | ||
2245 | if (pthread_cond_init(&buffered_audio->not_empty_cv, NULL)) | |
2246 | die("Connection %d: error %d initialising not_empty cv.", conn->connection_number, errno); | |
2247 | pthread_cleanup_push(cv_cleanup, &buffered_audio->not_empty_cv); | |
2248 | ||
2249 | if (pthread_cond_init(&buffered_audio->not_full_cv, NULL)) | |
2250 | die("Connection %d: error %d initialising not_full cv.", conn->connection_number, errno); | |
2251 | pthread_cleanup_push(cv_cleanup, &buffered_audio->not_full_cv); | |
2252 | ||
2253 | // initialise the buffer data structure | |
2254 | buffered_audio->buffer_max_size = conn->ap2_audio_buffer_size; | |
2255 | buffered_audio->buffer = malloc(conn->ap2_audio_buffer_size); | |
2256 | if (buffered_audio->buffer == NULL) | |
2257 | debug(1, "cannot allocate an audio buffer of %u bytes!", buffered_audio->buffer_max_size); | |
2258 | pthread_cleanup_push(malloc_cleanup, buffered_audio->buffer); | |
2259 | ||
2260 | // pthread_mutex_lock(&conn->buffered_audio_mutex); | |
2261 | buffered_audio->toq = buffered_audio->buffer; | |
2262 | buffered_audio->eoq = buffered_audio->buffer; | |
2263 | ||
2264 | buffered_audio->sock_fd = conn->buffered_audio_socket; | |
2265 | ||
2266 | pthread_create(buffered_reader_thread, NULL, &buffered_tcp_reader, buffered_audio); | |
2267 | pthread_cleanup_push(thread_cleanup, buffered_reader_thread); | |
2268 | ||
2269 | // ideas and some code from https://rodic.fr/blog/libavcodec-tutorial-decode-audio-file/ | |
2270 | // with thanks | |
2271 | ||
3d9d9757 | 2272 | const AVCodec *codec = avcodec_find_decoder(AV_CODEC_ID_AAC); |
8a73d597 MB |
2273 | if (codec == NULL) { |
2274 | debug(1, "Can't find an AAC decoder!"); | |
2275 | } | |
2276 | ||
2277 | AVCodecContext *codec_context = avcodec_alloc_context3(codec); | |
2278 | if (codec_context == NULL) { | |
2279 | debug(1, "Could not allocate audio codec context!"); | |
2280 | } | |
2281 | // push a deallocator -- av_free(codec_context) | |
2282 | pthread_cleanup_push(avcodec_alloc_context3_cleanup_handler, codec_context); | |
2283 | ||
2284 | if (avcodec_open2(codec_context, codec, NULL) < 0) { | |
2285 | debug(1, "Could not open a codec into the audio codec context"); | |
2286 | } | |
2287 | // push a closer -- avcodec_close(codec_context); | |
2288 | pthread_cleanup_push(avcodec_open2_cleanup_handler, codec_context); | |
2289 | ||
2290 | AVCodecParserContext *codec_parser_context = av_parser_init(codec->id); | |
2291 | if (codec_parser_context == NULL) { | |
2292 | debug(1, "Can't initialise a parser context!"); | |
2293 | } | |
2294 | // push a closer -- av_parser_close(codec_parser_context); | |
2295 | pthread_cleanup_push(av_parser_init_cleanup_handler, codec_parser_context); | |
a1dabd79 | 2296 | |
8a73d597 MB |
2297 | AVPacket *pkt = av_packet_alloc(); |
2298 | if (pkt == NULL) { | |
2299 | debug(1, "Can't allocate an AV packet"); | |
2300 | } | |
2301 | // push a deallocator -- av_packet_free(pkt); | |
2302 | pthread_cleanup_push(av_packet_alloc_cleanup_handler, &pkt); | |
2303 | ||
2304 | AVFrame *decoded_frame = NULL; | |
2305 | int dst_linesize; | |
2306 | int dst_bufsize; | |
2307 | ||
ad3412f5 | 2308 | // Prepare software resampler to convert floating point (?) |
8a73d597 MB |
2309 | SwrContext *swr = swr_alloc(); |
2310 | if (swr == NULL) { | |
2311 | debug(1, "can not allocate a swr context"); | |
2312 | } | |
2313 | // push a deallocator -- av_packet_free(pkt); | |
2314 | pthread_cleanup_push(swr_alloc_cleanup_handler, &swr); | |
2315 | ||
2316 | av_opt_set_int(swr, "in_channel_layout", AV_CH_LAYOUT_STEREO, 0); | |
2317 | av_opt_set_int(swr, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0); | |
f6a9f634 | 2318 | av_opt_set_int(swr, "in_sample_rate", conn->input_rate, 0); |
4090b2d8 MB |
2319 | av_opt_set_int(swr, "out_sample_rate", conn->input_rate, |
2320 | 0); // must match or the timing will be wrong` | |
8a73d597 | 2321 | av_opt_set_sample_fmt(swr, "in_sample_fmt", AV_SAMPLE_FMT_FLTP, 0); |
d4ea91aa MB |
2322 | |
2323 | enum AVSampleFormat av_format; | |
2324 | switch (config.output_format) { | |
c5dafbd2 MB |
2325 | case SPS_FORMAT_S32: |
2326 | case SPS_FORMAT_S32_LE: | |
2327 | case SPS_FORMAT_S32_BE: | |
2328 | case SPS_FORMAT_S24: | |
2329 | case SPS_FORMAT_S24_LE: | |
2330 | case SPS_FORMAT_S24_BE: | |
2331 | case SPS_FORMAT_S24_3LE: | |
2332 | case SPS_FORMAT_S24_3BE: | |
2333 | av_format = AV_SAMPLE_FMT_S32; | |
2334 | conn->input_bytes_per_frame = 8; // the output from the decoder will be input to the player | |
2335 | conn->input_bit_depth = 32; | |
7a26139c | 2336 | debug(2, "32-bit output format chosen"); |
c5dafbd2 MB |
2337 | break; |
2338 | case SPS_FORMAT_S16: | |
2339 | case SPS_FORMAT_S16_LE: | |
2340 | case SPS_FORMAT_S16_BE: | |
2341 | av_format = AV_SAMPLE_FMT_S16; | |
2342 | conn->input_bytes_per_frame = 4; | |
2343 | conn->input_bit_depth = 16; | |
2344 | break; | |
2345 | case SPS_FORMAT_U8: | |
2346 | av_format = AV_SAMPLE_FMT_U8; | |
2347 | conn->input_bytes_per_frame = 2; | |
2348 | conn->input_bit_depth = 8; | |
2349 | break; | |
2350 | default: | |
2351 | debug(1, "Unsupported DAC output format %u. AV_SAMPLE_FMT_S16 decoding chosen. Good luck!", | |
2352 | config.output_format); | |
2353 | av_format = AV_SAMPLE_FMT_S16; | |
2354 | conn->input_bytes_per_frame = 4; // the output from the decoder will be input to the player | |
2355 | conn->input_bit_depth = 16; | |
2356 | break; | |
d4ea91aa MB |
2357 | }; |
2358 | ||
2359 | av_opt_set_sample_fmt(swr, "out_sample_fmt", av_format, 0); | |
8a73d597 MB |
2360 | swr_init(swr); |
2361 | ||
2362 | uint8_t packet[16 * 1024]; | |
2363 | unsigned char m[16 * 1024]; // leave the first 7 bytes blank to make room for the ADTS | |
2364 | uint8_t *pcm_audio = NULL; // the S16 output | |
2365 | unsigned char *data_to_process; | |
2366 | ssize_t data_remaining; | |
174556f0 | 2367 | uint32_t seq_no = 0; // audio packet number. Initialised to avoid a "possibly uninitialised" warning. |
c433e2e8 | 2368 | uint32_t previous_seq_no = 0; |
c0a3dacf | 2369 | int new_buffer_needed = 0; |
8a73d597 MB |
2370 | ssize_t nread; |
2371 | ||
2372 | int finished = 0; | |
c5dafbd2 | 2373 | int pcm_buffer_size = (1024 + 352) * conn->input_bytes_per_frame; |
8a73d597 MB |
2374 | uint8_t pcm_buffer[pcm_buffer_size]; |
2375 | ||
2376 | int pcm_buffer_occupancy = 0; | |
2377 | int pcm_buffer_read_point = 0; // offset to where the next buffer should come from | |
2378 | uint32_t pcm_buffer_read_point_rtptime = 0; | |
c433e2e8 | 2379 | uint32_t pcm_buffer_read_point_rtptime_offset = 0; // hack |
b19dd9e9 | 2380 | uint32_t expected_pcm_buffer_read_point_rtptime = 0; |
8a73d597 MB |
2381 | |
2382 | uint64_t blocks_read = 0; | |
c433e2e8 | 2383 | uint64_t blocks_read_in_sequence = 0; // since the start of this sequence -- reset by start or flush |
8a73d597 | 2384 | int flush_requested = 0; |
cae9492d | 2385 | uint32_t expected_timestamp = 0; |
b19dd9e9 | 2386 | int expected_timesamp_is_reasonable = 0; |
174556f0 | 2387 | uint32_t timestamp = 0; // initialised to avoid a "possibly uninitialised" warning. |
c433e2e8 | 2388 | int packets_played_in_this_sequence = 0; |
2ea28c06 | 2389 | int play_enabled = 0; |
174556f0 | 2390 | uint32_t flush_from_timestamp = 0; // initialised to avoid a "possibly uninitialised" warning. |
8a2756b7 | 2391 | double requested_lead_time = 0.0; // normal lead time minimum -- maybe it should be about 0.1 |
70821f81 | 2392 | |
0b21373c | 2393 | // wait until our timing information is valid |
70821f81 | 2394 | |
0b21373c MB |
2395 | // debug(1,"rtp_buffered_audio_processor ready."); |
2396 | while (have_ptp_timing_information(conn) == 0) | |
2397 | usleep(1000); | |
70821f81 MB |
2398 | |
2399 | reset_buffer(conn); // in case there is any garbage in the player | |
7a26139c | 2400 | // int not_first_time_out = 0; |
14bfba27 MB |
2401 | |
2402 | // quick check of parameters | |
2403 | if (conn->input_bytes_per_frame == 0) | |
2404 | die("conn->input_bytes_per_frame is zero!"); | |
8a73d597 | 2405 | do { |
2ea28c06 | 2406 | int flush_is_delayed = 0; |
8a73d597 | 2407 | int flush_newly_requested = 0; |
9cf4ef03 | 2408 | int flush_newly_complete = 0; |
2ea28c06 | 2409 | int play_newly_stopped = 0; |
8a73d597 | 2410 | // are we in in flush mode, or just about to leave it? |
08afa822 | 2411 | debug_mutex_lock(&conn->flush_mutex, 25000, 1); // 25 ms is a long time to wait! |
e258cca3 | 2412 | uint32_t flushUntilSeq = conn->ap2_flush_until_sequence_number; |
c37ee454 | 2413 | uint32_t flushUntilTS = conn->ap2_flush_until_rtp_timestamp; |
e258cca3 MB |
2414 | |
2415 | int flush_request_active = 0; | |
8a73d597 | 2416 | if (conn->ap2_flush_requested) { |
a109b587 | 2417 | if (conn->ap2_flush_from_valid == 0) { // i.e. a flush from right now |
e258cca3 | 2418 | flush_request_active = 1; |
9cf4ef03 | 2419 | flush_is_delayed = 0; |
e258cca3 | 2420 | } else { |
7c68f97d | 2421 | flush_is_delayed = 1; |
7c68f97d | 2422 | flush_from_timestamp = conn->ap2_flush_from_rtp_timestamp; |
e258cca3 MB |
2423 | int32_t blocks_to_start_of_flush = conn->ap2_flush_from_sequence_number - seq_no; |
2424 | if (blocks_to_start_of_flush <= 0) { | |
2425 | flush_request_active = 1; | |
e258cca3 MB |
2426 | } |
2427 | } | |
2428 | } | |
2429 | // if we are in flush mode | |
2430 | if (flush_request_active) { | |
8a73d597 MB |
2431 | if (flush_requested == 0) { |
2432 | // here, a flush has been newly requested | |
7c68f97d | 2433 | |
a109b587 | 2434 | debug(2, "Flush requested."); |
e258cca3 | 2435 | if (conn->ap2_flush_from_valid) { |
a109b587 MB |
2436 | debug(2, " fromTS: %u", conn->ap2_flush_from_rtp_timestamp); |
2437 | debug(2, " fromSeq: %u", conn->ap2_flush_from_sequence_number); | |
2438 | debug(2, "--"); | |
e258cca3 | 2439 | } |
a109b587 MB |
2440 | debug(2, " untilTS: %u", conn->ap2_flush_until_rtp_timestamp); |
2441 | debug(2, " untilSeq: %u", conn->ap2_flush_until_sequence_number); | |
2442 | debug(2, "--"); | |
2443 | debug(2, " currentTS_Start: %u", pcm_buffer_read_point_rtptime); | |
2444 | uint32_t fib = (pcm_buffer_occupancy - pcm_buffer_read_point) / 4; | |
2445 | debug(2, " framesInBuffer: %u", fib); | |
2446 | uint32_t endTS = fib + pcm_buffer_read_point_rtptime; | |
2447 | debug(2, " currentTS_End: %u", endTS); // a frame occupies 4 bytes | |
2448 | debug(2, " currentSeq: %u", seq_no); | |
2449 | ||
2450 | flush_newly_requested = 1; | |
8a73d597 | 2451 | } |
2986b282 MB |
2452 | // blocks_read to ensure seq_no is valid |
2453 | if ((blocks_read != 0) && (seq_no >= flushUntilSeq)) { | |
2454 | // we have reached or overshot the flushUntilSeq block | |
a109b587 | 2455 | if (flushUntilSeq != seq_no) |
4090b2d8 MB |
2456 | debug(2, |
2457 | "flush request ended with flushUntilSeq %u overshot at %u, flushUntilTS: %u, " | |
2458 | "incoming timestamp: %u.", | |
2459 | flushUntilSeq, seq_no, flushUntilTS, timestamp); | |
c37ee454 | 2460 | else |
4090b2d8 | 2461 | debug(2, |
cae9492d | 2462 | "flush request ended with seqNo = flushUntilSeq at %u, flushUntilTS: %u, incoming timestamp: %u", |
4090b2d8 | 2463 | flushUntilSeq, flushUntilTS, timestamp); |
8a73d597 | 2464 | conn->ap2_flush_requested = 0; |
e258cca3 | 2465 | flush_request_active = 0; |
2986b282 | 2466 | flush_newly_requested = 0; |
8a73d597 MB |
2467 | } |
2468 | } | |
c433e2e8 MB |
2469 | |
2470 | // flush_requested = conn->ap2_flush_requested; | |
2471 | if ((play_enabled) && (conn->ap2_play_enabled == 0)) { | |
2472 | play_newly_stopped = 1; | |
2473 | debug(2,"Play stopped."); | |
2474 | pcm_buffer_read_point_rtptime_offset = 0; | |
2475 | blocks_read_in_sequence = 0; // This may be set to 1 by a flush, so don't zero it during start. | |
2476 | packets_played_in_this_sequence = 0; | |
2477 | pcm_buffer_occupancy = 0; | |
2478 | pcm_buffer_read_point = 0; | |
2479 | } | |
2480 | ||
2481 | if ((play_enabled == 0) && (conn->ap2_play_enabled != 0)) { | |
2482 | // play newly started | |
2483 | debug(2,"Play started."); | |
2484 | } | |
2485 | ||
2486 | ||
2487 | ||
cae9492d | 2488 | if ((flush_requested) && (flush_request_active == 0)) { |
c433e2e8 MB |
2489 | if (play_enabled) |
2490 | debug(1,"Flush completed while play_enabled is true."); | |
9cf4ef03 | 2491 | flush_newly_complete = 1; |
c433e2e8 | 2492 | blocks_read_in_sequence = 1; // the last block always (?) becomes the first block after the flush |
cae9492d | 2493 | } |
e258cca3 | 2494 | flush_requested = flush_request_active; |
c433e2e8 | 2495 | |
2ea28c06 | 2496 | play_enabled = conn->ap2_play_enabled; |
c433e2e8 | 2497 | |
8a73d597 MB |
2498 | debug_mutex_unlock(&conn->flush_mutex, 3); |
2499 | ||
2500 | // do this outside the flush mutex | |
9cf4ef03 | 2501 | if (flush_newly_complete) { |
a109b587 | 2502 | debug(2, "Flush Complete."); |
9cf4ef03 | 2503 | } |
2ea28c06 MB |
2504 | |
2505 | if (play_newly_stopped != 0) | |
2506 | reset_buffer(conn); // stop play ASAP | |
2507 | ||
8a73d597 | 2508 | if (flush_newly_requested) { |
2ea28c06 MB |
2509 | reset_buffer(conn); |
2510 | ||
9cf4ef03 | 2511 | if (flush_is_delayed == 0) { |
a109b587 MB |
2512 | debug(2, "Immediate Buffered Audio Flush Started."); |
2513 | // player_full_flush(conn); | |
c433e2e8 | 2514 | packets_played_in_this_sequence = 0; |
9cf4ef03 MB |
2515 | pcm_buffer_occupancy = 0; |
2516 | pcm_buffer_read_point = 0; | |
2517 | } else { | |
a109b587 | 2518 | debug(2, "Delayed Buffered Audio Flush Started."); |
c433e2e8 | 2519 | packets_played_in_this_sequence = 0; |
7c68f97d MB |
2520 | pcm_buffer_occupancy = 0; |
2521 | pcm_buffer_read_point = 0; | |
9cf4ef03 | 2522 | } |
c433e2e8 | 2523 | pcm_buffer_read_point_rtptime_offset = 0; |
8a73d597 MB |
2524 | } |
2525 | ||
2526 | // now, if a flush is not requested, we can do the normal stuff | |
2527 | if (flush_requested == 0) { | |
2528 | // is there space in the player thread's buffer system? | |
2529 | unsigned int player_buffer_size, player_buffer_occupancy; | |
2530 | get_audio_buffer_size_and_occupancy(&player_buffer_size, &player_buffer_occupancy, conn); | |
4090b2d8 MB |
2531 | // debug(1,"player buffer size and occupancy: %u and %u", player_buffer_size, |
2532 | // player_buffer_occupancy); | |
2533 | if (player_buffer_occupancy > ((requested_lead_time + 0.4) * conn->input_rate / | |
2534 | 352)) { // must be greater than the lead time. | |
8a73d597 | 2535 | // if there is enough stuff in the player's buffer, sleep for a while and try again |
8a2756b7 | 2536 | debug(3, "sleep while full"); |
a1dabd79 | 2537 | usleep(20000); // wait for a while |
8a73d597 | 2538 | } else { |
d4ea91aa | 2539 | if ((pcm_buffer_occupancy - pcm_buffer_read_point) >= (352 * conn->input_bytes_per_frame)) { |
8a73d597 MB |
2540 | new_buffer_needed = 0; |
2541 | // send a frame to the player if allowed | |
7a26139c | 2542 | // it it's way too late, it probably means that a new anchor time is needed |
8a73d597 MB |
2543 | |
2544 | /* | |
2545 | uint32_t at_rtp = conn->reference_timestamp; | |
2546 | at_rtp = | |
2547 | at_rtp - (44100 * 10); // allow it to start a few seconds late, but not | |
2548 | madly late int rtp_diff = pcm_buffer_read_point_rtptime - at_rtp; | |
2549 | */ | |
2550 | ||
77e70e49 | 2551 | if ((play_enabled) && (have_ptp_timing_information(conn) != 0)) { |
8a73d597 MB |
2552 | uint64_t buffer_should_be_time; |
2553 | if (frame_to_local_time(pcm_buffer_read_point_rtptime, &buffer_should_be_time, conn) == | |
2554 | 0) { | |
2555 | int64_t lead_time = buffer_should_be_time - get_absolute_time_in_ns(); | |
ad3412f5 MB |
2556 | |
2557 | // it seems that some garbage blocks can be left after the flush, so | |
2558 | // only accept them if they have sensible lead times | |
8a2756b7 | 2559 | if ((lead_time < (int64_t)30000000000L) && (lead_time >= 0)) { |
4090b2d8 | 2560 | // if it's the very first block (thus no priming needed) |
c433e2e8 | 2561 | //if ((blocks_read == 1) || (blocks_read_in_sequence > 3)) { |
1dc481c3 | 2562 | if ((lead_time >= (int64_t)(requested_lead_time * 1000000000L)) || |
c433e2e8 MB |
2563 | (packets_played_in_this_sequence != 0)) { |
2564 | if (packets_played_in_this_sequence == 0) | |
4090b2d8 MB |
2565 | debug(2, |
2566 | "Connection %d: buffered audio starting frame: %u, lead time: %f " | |
2567 | "seconds.", | |
2568 | conn->connection_number, pcm_buffer_read_point_rtptime, | |
2569 | 0.000000001 * lead_time); | |
2570 | // else { | |
2571 | // if (expected_rtptime != pcm_buffer_read_point_rtptime) | |
2572 | // debug(1,"actual rtptime is %u, expected rtptime is %u.", | |
2573 | // pcm_buffer_read_point_rtptime, expected_rtptime); | |
2574 | //} | |
2575 | // expected_rtptime = pcm_buffer_read_point_rtptime + 352; | |
2576 | ||
2577 | // this is a diagnostic for introducing a timing error that will force the | |
2578 | // processing chain to resync | |
2579 | // clang-format off | |
7a26139c MB |
2580 | /* |
2581 | if ((not_first_time_out == 0) && (blocks_read >= 20)) { | |
2582 | int timing_error = 150; | |
2583 | debug(1, "Connection %d: Introduce a timing error of %d milliseconds.", | |
2584 | conn->connection_number, timing_error); | |
2585 | if (timing_error >= 0) | |
2586 | pcm_buffer_read_point_rtptime += (conn->input_rate * timing_error) / 1000; | |
2587 | else | |
2588 | pcm_buffer_read_point_rtptime -= (conn->input_rate * (-timing_error)) / 1000; | |
2589 | not_first_time_out = 1; | |
2590 | } | |
2591 | */ | |
7dc077e2 MB |
2592 | // clang-format on |
2593 | ||
2594 | // debug(1,"block timestamp: %u, packet timestamp: %u.", timestamp, | |
2595 | // pcm_buffer_read_point_rtptime); | |
2596 | ||
2597 | int32_t timestamp_difference = | |
2598 | pcm_buffer_read_point_rtptime - expected_pcm_buffer_read_point_rtptime; | |
2599 | ; | |
2600 | if (packets_played_in_this_sequence != 0) { | |
2601 | if (timestamp_difference != 0) | |
2602 | debug( | |
2603 | 2, | |
2604 | "Unexpected time difference between packets -- actual: %u, expected: %u, " | |
2605 | "difference: %d. Packets played: %d. Blocks played since flush: %d. ", | |
2606 | pcm_buffer_read_point_rtptime, expected_pcm_buffer_read_point_rtptime, | |
2607 | timestamp_difference, packets_played_in_this_sequence, | |
2608 | blocks_read_in_sequence); | |
2609 | } | |
7a26139c | 2610 | |
7dc077e2 MB |
2611 | // Very specific code to get around an apparent bug in AirPlay 2 from iOS 16 / |
2612 | // Ventura 13.0 It seems that the timestamp goes backwards by 2112 frames not | |
2613 | // later than the 65th packet of 352 frames (64 * 352 = 22528 frames which is | |
2614 | // exactly 22 blocks) So, if that happens, we'll add 2112 to the timstamp passed | |
2615 | // to the player | |
2616 | ||
2617 | if ((timestamp_difference == -2112) && (packets_played_in_this_sequence <= 64)) { | |
2618 | debug(1, | |
2619 | "iOS 16.0 discontinuity detected with %d packets played in this " | |
2620 | "sequence. Nothing done.", | |
2621 | packets_played_in_this_sequence); | |
2622 | // pcm_buffer_read_point_rtptime_offset = 2112; // this pretends the timestamps | |
2623 | // after the discontinuity are 2112 frames later, but this just delays | |
2624 | // everything by 2112 frames, pushing stuff out of sync, and i think you can | |
2625 | // hear it. | |
2626 | } | |
cae9492d | 2627 | |
7dc077e2 MB |
2628 | // if it's not the very first block of AAC, but is from the first few blocks of a |
2629 | // new AAC sequence, it will contain noisy transients, so replace it with silence. | |
2630 | if ((blocks_read_in_sequence <= 2) && (blocks_read_in_sequence != blocks_read)) { | |
2631 | // debug(1,"Muting packet %u from block %u to avoid AAC transients because it's | |
2632 | // not from a true starting block. Blocks_read is %" PRIu64 ". | |
2633 | // blocks_read_in_sequence is %" PRIu64 ".", pcm_buffer_read_point_rtptime, | |
2634 | // timestamp, blocks_read, blocks_read_in_sequence); | |
2635 | conn->previous_random_number = generate_zero_frames( | |
2636 | (char *)(pcm_buffer + pcm_buffer_read_point), 352, config.output_format, | |
2637 | conn->enable_dither, conn->previous_random_number); | |
4090b2d8 | 2638 | } |
7dc077e2 MB |
2639 | |
2640 | player_put_packet( | |
2641 | 0, 0, pcm_buffer_read_point_rtptime + pcm_buffer_read_point_rtptime_offset, | |
2642 | pcm_buffer + pcm_buffer_read_point, 352, conn); | |
2643 | packets_played_in_this_sequence++; | |
2644 | expected_pcm_buffer_read_point_rtptime = pcm_buffer_read_point_rtptime + 352; | |
2645 | } | |
cae9492d | 2646 | // } |
c37ee454 | 2647 | } else { |
c433e2e8 | 2648 | debug(3, |
4090b2d8 | 2649 | "Dropping packet %u from block %u with out-of-range lead_time: %.3f seconds.", |
1dc481c3 | 2650 | pcm_buffer_read_point_rtptime, seq_no, 0.000000001 * lead_time); |
7dc077e2 | 2651 | expected_pcm_buffer_read_point_rtptime = pcm_buffer_read_point_rtptime + 352; |
c37ee454 | 2652 | } |
8a73d597 MB |
2653 | |
2654 | pcm_buffer_read_point_rtptime += 352; | |
d4ea91aa | 2655 | pcm_buffer_read_point += 352 * conn->input_bytes_per_frame; |
f6a9f634 | 2656 | } else { |
4090b2d8 | 2657 | debug(1, "frame to local time error"); |
8a73d597 | 2658 | } |
8a73d597 | 2659 | } else { |
8a2756b7 | 2660 | debug(3, "sleep until demand"); |
a1dabd79 | 2661 | usleep(20000); // wait before asking if play is enabled again |
8a73d597 MB |
2662 | } |
2663 | } else { | |
7dc077e2 MB |
2664 | // debug(1,"new buffer needed for buffer starting at %u because pcm_buffer_read_point |
2665 | // (frames) is %u and pcm_buffer_occupancy (frames) is %u.", | |
2666 | // pcm_buffer_read_point_rtptime, pcm_buffer_read_point/conn->input_bytes_per_frame, | |
cae9492d | 2667 | // pcm_buffer_occupancy/conn->input_bytes_per_frame); |
8a73d597 MB |
2668 | new_buffer_needed = 1; |
2669 | if (pcm_buffer_read_point != 0) { | |
2670 | // debug(1,"pcm_buffer_read_point (frames): %u, pcm_buffer_occupancy (frames): %u", | |
7dc077e2 MB |
2671 | // pcm_buffer_read_point/conn->input_bytes_per_frame, |
2672 | // pcm_buffer_occupancy/conn->input_bytes_per_frame); // if there is anything to move | |
2673 | // down | |
c5dafbd2 | 2674 | // to the front of the buffer, do it now; |
8a73d597 MB |
2675 | if ((pcm_buffer_occupancy - pcm_buffer_read_point) > 0) { |
2676 | // move the remaining frames down to the start of the buffer | |
2677 | // debug(1,"move the remaining frames down to the start of the pcm_buffer"); | |
2678 | memcpy(pcm_buffer, pcm_buffer + pcm_buffer_read_point, | |
2679 | pcm_buffer_occupancy - pcm_buffer_read_point); | |
2680 | pcm_buffer_occupancy = pcm_buffer_occupancy - pcm_buffer_read_point; | |
2681 | } else { | |
2682 | // debug(1,"nothing to move to the front of the buffer"); | |
2683 | pcm_buffer_occupancy = 0; | |
2684 | } | |
2685 | pcm_buffer_read_point = 0; | |
2686 | } | |
2687 | } | |
2688 | } | |
2689 | } | |
2690 | if ((flush_requested) || (new_buffer_needed)) { | |
2691 | ||
2692 | // debug(1,"pcm_buffer_read_point (frames): %u, pcm_buffer_occupancy (frames): %u", | |
7dc077e2 MB |
2693 | // pcm_buffer_read_point/conn->input_bytes_per_frame, |
2694 | // pcm_buffer_occupancy/conn->input_bytes_per_frame); ok, so here we know we need material | |
2695 | // from the sender do we will get in a packet of audio | |
8a73d597 MB |
2696 | uint16_t data_len; |
2697 | // here we read from the buffer that our thread has been reading | |
08afa822 | 2698 | size_t bytes_remaining_in_buffer; |
a382ac66 MB |
2699 | nread = lread_sized_block(buffered_audio, &data_len, sizeof(data_len), |
2700 | &bytes_remaining_in_buffer); | |
2701 | if ((conn->ap2_audio_buffer_minimum_size < 0) || | |
2702 | (bytes_remaining_in_buffer < (size_t)conn->ap2_audio_buffer_minimum_size)) | |
08afa822 | 2703 | conn->ap2_audio_buffer_minimum_size = bytes_remaining_in_buffer; |
8a73d597 MB |
2704 | if (nread < 0) { |
2705 | char errorstring[1024]; | |
2706 | strerror_r(errno, (char *)errorstring, sizeof(errorstring)); | |
2707 | debug(1, "error in rtp_buffered_audio_processor %d: \"%s\". Could not recv a data_len .", | |
2708 | errno, errorstring); | |
2709 | // if ((config.diagnostic_drop_packet_fraction == 0.0) || | |
2710 | // (drand48() > config.diagnostic_drop_packet_fraction)) { | |
2711 | } | |
2712 | data_len = ntohs(data_len); | |
2713 | // debug(1,"buffered audio packet of size %u detected.", data_len - 2); | |
08afa822 | 2714 | nread = lread_sized_block(buffered_audio, packet, data_len - 2, &bytes_remaining_in_buffer); |
a382ac66 MB |
2715 | if ((conn->ap2_audio_buffer_minimum_size < 0) || |
2716 | (bytes_remaining_in_buffer < (size_t)conn->ap2_audio_buffer_minimum_size)) | |
08afa822 | 2717 | conn->ap2_audio_buffer_minimum_size = bytes_remaining_in_buffer; |
8a73d597 MB |
2718 | // debug(1, "buffered audio packet of size %u received.", nread); |
2719 | if (nread < 0) { | |
2720 | char errorstring[1024]; | |
2721 | strerror_r(errno, (char *)errorstring, sizeof(errorstring)); | |
2722 | debug(1, "error in rtp_buffered_audio_processor %d: \"%s\". Could not recv a data packet.", | |
2723 | errno, errorstring); | |
8a73d597 MB |
2724 | } else if (nread > 0) { |
2725 | blocks_read++; // note, this doesn't mean they are valid audio blocks | |
c433e2e8 | 2726 | blocks_read_in_sequence++; |
8a73d597 MB |
2727 | // debug(1, "Realtime Audio Receiver Packet of length %d received.", nread); |
2728 | // now get hold of its various bits and pieces | |
2729 | /* | |
2730 | uint8_t version = (packet[0] & 0b11000000) >> 6; | |
2731 | uint8_t padding = (packet[0] & 0b00100000) >> 5; | |
2732 | uint8_t extension = (packet[0] & 0b00010000) >> 4; | |
2733 | uint8_t csrc_count = packet[0] & 0b00001111; | |
2734 | */ | |
c433e2e8 MB |
2735 | previous_seq_no = seq_no; |
2736 | previous_seq_no++; | |
8a73d597 | 2737 | seq_no = packet[1] * (1 << 16) + packet[2] * (1 << 8) + packet[3]; |
c433e2e8 | 2738 | if (previous_seq_no != seq_no) { |
7dc077e2 MB |
2739 | debug(2, "block sequence number changed from expected %u to actual %u.", previous_seq_no, |
2740 | seq_no); | |
c433e2e8 | 2741 | } |
c37ee454 | 2742 | timestamp = nctohl(&packet[4]); |
cae9492d | 2743 | // debug(1,"New block timestamp: %u.", timestamp); |
b19dd9e9 | 2744 | int32_t timestamp_difference = timestamp - expected_timestamp; |
7dc077e2 MB |
2745 | if ((timestamp_difference != 0) && (expected_timesamp_is_reasonable != 0)) |
2746 | debug(2, | |
2747 | "Block with unexpected timestamp. Expected: %u, got: %u, difference: %d, " | |
2748 | "blocks_read_in_sequence: %" PRIu64 ".", | |
2749 | expected_timestamp, timestamp, timestamp_difference, blocks_read_in_sequence); | |
cae9492d | 2750 | expected_timestamp = timestamp; |
b19dd9e9 | 2751 | expected_timesamp_is_reasonable = 0; // must be validated each time by decoding the frame |
cae9492d | 2752 | |
e258cca3 | 2753 | // debug(1, "immediately: block %u, rtptime %u", seq_no, timestamp); |
8a73d597 MB |
2754 | // uint32_t ssrc = nctohl(&packet[8]); |
2755 | // uint8_t marker = 0; | |
2756 | // uint8_t payload_type = 0; | |
2757 | ||
2986b282 | 2758 | // previous_seq_no = seq_no; |
8a73d597 MB |
2759 | |
2760 | // at this point, we can check if we can to flush this packet -- we won't have | |
2761 | // to decipher it first | |
2762 | // debug(1,"seq_no %u, timestamp %u", seq_no, timestamp); | |
2763 | ||
0b21373c MB |
2764 | uint64_t local_should_be_time = 0; |
2765 | int have_time_information = frame_to_local_time(timestamp, &local_should_be_time, conn); | |
2766 | int64_t local_lead_time = 0; | |
2767 | int64_t requested_lead_time_ns = (int64_t)(requested_lead_time * 1000000000); | |
424c376b | 2768 | // requested_lead_time_ns = (int64_t)(-300000000); |
a382ac66 MB |
2769 | // debug(1,"requested_lead_time_ns is actually %f milliseconds.", requested_lead_time_ns * |
2770 | // 1E-6); | |
70821f81 | 2771 | int outdated = 0; |
8a2756b7 | 2772 | int too_soon_after_connection = 0; |
0b21373c | 2773 | if (have_time_information == 0) { |
8a2756b7 MB |
2774 | int64_t play_time_since_connection = local_should_be_time - conn->connection_start_time; |
2775 | int64_t time_since_connection = get_absolute_time_in_ns() - conn->connection_start_time; | |
8a2756b7 MB |
2776 | too_soon_after_connection = |
2777 | ((play_time_since_connection < 2000000000) && (time_since_connection < 2000000000)); | |
2778 | if (too_soon_after_connection) | |
6556a79d MB |
2779 | debug(3, |
2780 | "time_since_connection is %f milliseconds. play_time_since_connection is %f " | |
2781 | "milliseconds. lead_time is %f milliseconds. too_soon_after_connection is %d.", | |
2782 | time_since_connection * 1E-6, play_time_since_connection * 1E-6, | |
2783 | (play_time_since_connection - time_since_connection) * 1E-6, | |
2784 | too_soon_after_connection); | |
0b21373c | 2785 | local_lead_time = local_should_be_time - get_absolute_time_in_ns(); |
a382ac66 | 2786 | // debug(1,"local_lead_time is actually %f milliseconds.", local_lead_time * 1E-6); |
0b21373c MB |
2787 | outdated = (local_lead_time < requested_lead_time_ns); |
2788 | // if (outdated != 0) | |
70821f81 MB |
2789 | // debug(1,"Frame is outdated %d if lead_time %" PRId64 " is less than requested lead time |
2790 | // %" PRId64 " ns.", outdated, local_lead_time, requested_lead_time_ns); | |
0b21373c | 2791 | } else { |
8a2756b7 | 2792 | debug(3, "Timing information not valid"); |
0b21373c | 2793 | } |
0b21373c | 2794 | |
7c68f97d | 2795 | if ((flush_requested) && (seq_no >= flushUntilSeq)) { |
0b21373c | 2796 | if ((have_time_information == 0) && (play_enabled)) { |
a109b587 MB |
2797 | // play enabled will be off when this is a full flush and the anchor information is not |
2798 | // valid | |
0b21373c | 2799 | debug(2, |
4090b2d8 MB |
2800 | "flush completed to seq: %u, flushUntilTS; %u with rtptime: %u, lead time: " |
2801 | "0x%" PRIx64 " nanoseconds, i.e. %f sec.", | |
0b21373c | 2802 | seq_no, flushUntilTS, timestamp, local_lead_time, local_lead_time * 0.000000001); |
2ea28c06 | 2803 | } else { |
a109b587 | 2804 | debug(2, "flush completed to seq: %u with rtptime: %u.", seq_no, timestamp); |
2ea28c06 | 2805 | } |
7c68f97d | 2806 | } |
8a73d597 | 2807 | |
70821f81 MB |
2808 | // if we are here because of a flush request, it must be the case that |
2809 | // flushing the pcm buffer wasn't enough, as the request would have been turned off by now | |
2810 | // so we better indicate that the pcm buffer is empty and its contents invalid | |
8a73d597 | 2811 | |
8a2756b7 MB |
2812 | // also, if the incoming frame is outdated, set pcm_buffer_occupancy to 0; |
2813 | if ((flush_requested) || (outdated) || (too_soon_after_connection)) { | |
70821f81 MB |
2814 | pcm_buffer_occupancy = 0; |
2815 | } | |
2816 | ||
2817 | // decode the block and add it to or put it in the pcm buffer | |
8a73d597 | 2818 | |
70821f81 MB |
2819 | if (pcm_buffer_occupancy == 0) { |
2820 | // they should match and the read point should be zero | |
2821 | // if ((blocks_read != 0) && (pcm_buffer_read_point_rtptime != timestamp)) { | |
2822 | // debug(2, "set pcm_buffer_read_point_rtptime from %u to %u.", | |
2823 | // pcm_buffer_read_point_rtptime, timestamp); | |
2824 | pcm_buffer_read_point_rtptime = timestamp; | |
2825 | pcm_buffer_read_point = 0; | |
2826 | //} | |
2827 | } | |
0b21373c | 2828 | |
8a2756b7 MB |
2829 | if ((((flush_requested != 0) && (seq_no == flushUntilSeq)) || |
2830 | ((flush_requested == 0) && (new_buffer_needed))) && | |
2831 | (too_soon_after_connection == 0)) { | |
8a73d597 | 2832 | unsigned long long new_payload_length = 0; |
1046a076 MB |
2833 | int response = -1; // guess that there is a problem |
2834 | if (conn->session_key != NULL) { | |
2835 | unsigned char nonce[12]; | |
2836 | memset(nonce, 0, sizeof(nonce)); | |
2837 | memcpy(nonce + 4, packet + nread - 8, | |
2838 | 8); // front-pad the 8-byte nonce received to get the 12-byte nonce expected | |
2839 | ||
2840 | // https://libsodium.gitbook.io/doc/secret-key_cryptography/aead/chacha20-poly1305/ietf_chacha20-poly1305_construction | |
2841 | // Note: the eight-byte nonce must be front-padded out to 12 bytes. | |
e8b8c6ed | 2842 | |
1046a076 MB |
2843 | response = crypto_aead_chacha20poly1305_ietf_decrypt( |
2844 | m + 7, // m | |
2845 | &new_payload_length, // mlen_p | |
2846 | NULL, // nsec, | |
e8b8c6ed | 2847 | packet + 12, // the ciphertext starts 12 bytes in and is followed by the MAC tag, |
1046a076 MB |
2848 | nread - (8 + 12), // clen -- the last 8 bytes are the nonce |
2849 | packet + 4, // authenticated additional data | |
2850 | 8, // authenticated additional data length | |
2851 | nonce, | |
2852 | conn->session_key); // *k | |
2853 | if (response != 0) | |
2854 | debug(1, "Error decrypting audio packet %u -- packet length %d.", seq_no, nread); | |
8a73d597 | 2855 | } else { |
1046a076 MB |
2856 | debug(2, "No session key, so the audio packet can not be deciphered -- skipped."); |
2857 | } | |
2858 | if (response == 0) { | |
8a73d597 MB |
2859 | // now pass it in to the regular processing chain |
2860 | ||
2861 | unsigned long long max_int = INT_MAX; // put in the right format | |
2862 | if (new_payload_length > max_int) | |
2863 | debug(1, "Madly long payload length!"); | |
2864 | int payload_length = new_payload_length; // change from long long to int | |
2865 | int aac_packet_length = payload_length + 7; | |
2866 | ||
2867 | // now, fill in the 7-byte ADTS information, which seems to be needed by the decoder | |
2868 | // we made room for it in the front of the buffer | |
2869 | ||
2870 | addADTStoPacket(m, aac_packet_length); | |
2871 | ||
2872 | // now we are ready to send this to the decoder | |
2873 | ||
2874 | data_to_process = m; | |
2875 | data_remaining = aac_packet_length; | |
2876 | int ret = 0; | |
2877 | // there can be more than one av packet (? terminology) in a block | |
0b21373c | 2878 | int frame_within_block = 0; |
8a73d597 MB |
2879 | while (data_remaining > 0) { |
2880 | if (decoded_frame == NULL) { | |
2881 | decoded_frame = av_frame_alloc(); | |
2882 | if (decoded_frame == NULL) | |
2883 | debug(1, "could not allocate av_frame"); | |
2884 | } else { | |
2885 | ret = av_parser_parse2(codec_parser_context, codec_context, &pkt->data, &pkt->size, | |
2886 | data_to_process, data_remaining, AV_NOPTS_VALUE, | |
2887 | AV_NOPTS_VALUE, 0); | |
2888 | if (ret < 0) { | |
2889 | debug(1, "error while parsing deciphered audio packet."); | |
2890 | } else { | |
0b21373c | 2891 | frame_within_block++; |
8a73d597 MB |
2892 | data_to_process += ret; |
2893 | data_remaining -= ret; | |
2894 | // debug(1, "frame found"); | |
2895 | // now pass each packet to be decoded | |
2896 | if (pkt->size) { | |
70821f81 | 2897 | // if (0) { |
0b21373c | 2898 | if (pkt->size <= 7) { // no idea about this... |
3de7e9a5 | 2899 | debug(2, "malformed AAC packet skipped."); |
0b21373c | 2900 | } else { |
70821f81 MB |
2901 | ret = avcodec_send_packet(codec_context, pkt); |
2902 | ||
2903 | if (ret < 0) { | |
2904 | debug(1, | |
2905 | "error sending frame %d of size %d to decoder, blocks_read: %u, " | |
c433e2e8 MB |
2906 | "blocks_read_in_sequence: %u.", |
2907 | frame_within_block, pkt->size, blocks_read, blocks_read_in_sequence); | |
70821f81 MB |
2908 | } else { |
2909 | while (ret >= 0) { | |
2910 | ret = avcodec_receive_frame(codec_context, decoded_frame); | |
2911 | if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) | |
2912 | break; | |
2913 | else if (ret < 0) { | |
2914 | debug(1, "error %d during decoding", ret); | |
8a73d597 | 2915 | } else { |
17414f57 | 2916 | #if LIBAVUTIL_VERSION_MAJOR >= 57 |
b7d9c22d MB |
2917 | av_samples_alloc(&pcm_audio, &dst_linesize, |
2918 | codec_context->ch_layout.nb_channels, | |
17414f57 MB |
2919 | decoded_frame->nb_samples, av_format, 1); |
2920 | #else | |
70821f81 MB |
2921 | av_samples_alloc(&pcm_audio, &dst_linesize, codec_context->channels, |
2922 | decoded_frame->nb_samples, av_format, 1); | |
17414f57 | 2923 | #endif |
70821f81 MB |
2924 | // remember to free pcm_audio |
2925 | ret = swr_convert(swr, &pcm_audio, decoded_frame->nb_samples, | |
2926 | (const uint8_t **)decoded_frame->extended_data, | |
2927 | decoded_frame->nb_samples); | |
17414f57 MB |
2928 | #if LIBAVUTIL_VERSION_MAJOR >= 57 |
2929 | dst_bufsize = av_samples_get_buffer_size( | |
b7d9c22d MB |
2930 | &dst_linesize, codec_context->ch_layout.nb_channels, ret, av_format, |
2931 | 1); | |
17414f57 | 2932 | #else |
70821f81 MB |
2933 | dst_bufsize = av_samples_get_buffer_size( |
2934 | &dst_linesize, codec_context->channels, ret, av_format, 1); | |
17414f57 MB |
2935 | #endif |
2936 | ||
70821f81 MB |
2937 | // debug(1,"generated %d bytes of PCM", dst_bufsize); |
2938 | // copy the PCM audio into the PCM buffer. | |
2939 | // make sure it's big enough first | |
2940 | ||
2941 | // also, check it if needs to be truncated but to an impending delayed | |
2942 | // flush_is_delayed | |
2943 | if (flush_is_delayed) { | |
2944 | // see if the flush_from_timestamp is in the buffer | |
2945 | int32_t samples_remaining = | |
2946 | (flush_from_timestamp - pcm_buffer_read_point_rtptime); | |
2947 | if ((samples_remaining > 0) && | |
2948 | ((samples_remaining * conn->input_bytes_per_frame) < | |
2949 | dst_bufsize)) { | |
2950 | debug(2, | |
2951 | "samples remaining before flush: %d, number of samples %d. " | |
2952 | "flushFromTS: %u, pcm_buffer_read_point_rtptime: %u.", | |
2953 | samples_remaining, dst_bufsize / conn->input_bytes_per_frame, | |
2954 | flush_from_timestamp, pcm_buffer_read_point_rtptime); | |
2955 | dst_bufsize = samples_remaining * conn->input_bytes_per_frame; | |
2956 | } | |
2957 | } | |
2958 | if ((pcm_buffer_size - pcm_buffer_occupancy) < dst_bufsize) { | |
2959 | debug(1, | |
2960 | "pcm_buffer_read_point (frames): %u, pcm_buffer_occupancy " | |
2961 | "(frames): %u", | |
2962 | pcm_buffer_read_point / conn->input_bytes_per_frame, | |
2963 | pcm_buffer_occupancy / conn->input_bytes_per_frame); | |
2964 | pcm_buffer_size = dst_bufsize + pcm_buffer_occupancy; | |
2965 | debug(1, "fatal error! pcm buffer too small at %d bytes.", | |
2966 | pcm_buffer_size); | |
2967 | } else { | |
2968 | memcpy(pcm_buffer + pcm_buffer_occupancy, pcm_audio, dst_bufsize); | |
7dc077e2 | 2969 | expected_timestamp += (dst_bufsize / conn->input_bytes_per_frame); |
b19dd9e9 | 2970 | expected_timesamp_is_reasonable = 1; |
70821f81 | 2971 | pcm_buffer_occupancy += dst_bufsize; |
7dc077e2 MB |
2972 | // debug(1,"frames added: pcm_buffer_read_point (frames): %u, |
2973 | // pcm_buffer_occupancy (frames): %u", | |
2974 | // pcm_buffer_read_point/conn->input_bytes_per_frame, | |
2975 | // pcm_buffer_occupancy/conn->input_bytes_per_frame); | |
2976 | } | |
70821f81 MB |
2977 | // debug(1,"decoded %d samples", decoded_frame->nb_samples); |
2978 | // memcpy(sampleBuffer,outputBuffer16,dst_bufsize); | |
2979 | av_freep(&pcm_audio); | |
8a73d597 | 2980 | } |
8a73d597 MB |
2981 | } |
2982 | } | |
2983 | } | |
2984 | } | |
2985 | } | |
2986 | if (decoded_frame == NULL) | |
2987 | debug(1, "decoded_frame is NULL"); | |
2988 | if (decoded_frame != NULL) | |
2989 | av_frame_free(&decoded_frame); | |
2990 | } | |
2991 | } | |
2992 | ||
2993 | // revert the state of cancellability | |
2994 | } | |
8a2756b7 MB |
2995 | } else { |
2996 | debug(3, "Dropping block %u with timestamp %u.", seq_no, timestamp); | |
8a73d597 MB |
2997 | } |
2998 | } else { | |
2999 | // nread is 0 -- the port has been closed | |
3c278493 | 3000 | debug(2, "buffered audio port closed!"); |
8a73d597 MB |
3001 | finished = 1; |
3002 | } | |
3003 | } | |
3004 | ||
3005 | } while (finished == 0); | |
3c278493 | 3006 | debug(2, "Buffered Audio Receiver RTP thread \"normal\" exit."); |
8a73d597 MB |
3007 | pthread_cleanup_pop(1); // deallocate the swr |
3008 | pthread_cleanup_pop(1); // deallocate the av_packet | |
3009 | pthread_cleanup_pop(1); // av_parser_init_cleanup_handler | |
3010 | pthread_cleanup_pop(1); // avcodec_open2_cleanup_handler | |
3011 | pthread_cleanup_pop(1); // avcodec_alloc_context3_cleanup_handler | |
3012 | pthread_cleanup_pop(1); // thread creation | |
3013 | pthread_cleanup_pop(1); // buffer malloc | |
3014 | pthread_cleanup_pop(1); // not_full_cv | |
3015 | pthread_cleanup_pop(1); // not_empty_cv | |
3016 | pthread_cleanup_pop(1); // mutex | |
3017 | pthread_cleanup_pop(1); // descriptor malloc | |
3018 | pthread_cleanup_pop(1); // pthread_t malloc | |
3019 | pthread_cleanup_pop(1); // do the cleanup. | |
3020 | pthread_exit(NULL); | |
3021 | } | |
829ea399 | 3022 | |
91b85a02 | 3023 | int frame_to_local_time(uint32_t timestamp, uint64_t *time, rtsp_conn_info *conn) { |
c2940eb2 MB |
3024 | if (conn->timing_type == ts_ptp) |
3025 | return frame_to_ptp_local_time(timestamp, time, conn); | |
3026 | else | |
3027 | return frame_to_ntp_local_time(timestamp, time, conn); | |
91b85a02 | 3028 | } |
8a73d597 | 3029 | |
91b85a02 | 3030 | int local_time_to_frame(uint64_t time, uint32_t *frame, rtsp_conn_info *conn) { |
c2940eb2 MB |
3031 | if (conn->timing_type == ts_ptp) |
3032 | return local_ptp_time_to_frame(time, frame, conn); | |
3033 | else | |
3034 | return local_ntp_time_to_frame(time, frame, conn); | |
91b85a02 MB |
3035 | } |
3036 | ||
c2940eb2 MB |
3037 | void reset_anchor_info(rtsp_conn_info *conn) { |
3038 | if (conn->timing_type == ts_ptp) | |
3039 | reset_ptp_anchor_info(conn); | |
3040 | else | |
3041 | reset_ntp_anchor_info(conn); | |
3042 | } | |
91b85a02 MB |
3043 | |
3044 | int have_timestamp_timing_information(rtsp_conn_info *conn) { | |
c2940eb2 MB |
3045 | if (conn->timing_type == ts_ptp) |
3046 | return have_ptp_timing_information(conn); | |
3047 | else | |
fd880056 | 3048 | return have_ntp_timing_information(conn); |
91b85a02 MB |
3049 | } |
3050 | ||
3051 | #else | |
c2940eb2 | 3052 | |
91b85a02 MB |
3053 | int frame_to_local_time(uint32_t timestamp, uint64_t *time, rtsp_conn_info *conn) { |
3054 | return frame_to_ntp_local_time(timestamp, time, conn); | |
3055 | } | |
3056 | ||
3057 | int local_time_to_frame(uint64_t time, uint32_t *frame, rtsp_conn_info *conn) { | |
3058 | return local_ntp_time_to_frame(time, frame, conn); | |
3059 | } | |
3060 | ||
a68f28ac | 3061 | void reset_anchor_info(rtsp_conn_info *conn) { reset_ntp_anchor_info(conn); } |
91b85a02 MB |
3062 | |
3063 | int have_timestamp_timing_information(rtsp_conn_info *conn) { | |
fd880056 | 3064 | return have_ntp_timing_information(conn); |
91b85a02 | 3065 | } |
8a73d597 | 3066 | #endif |