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