summaryrefslogtreecommitdiff
path: root/player.h
diff options
context:
space:
mode:
Diffstat (limited to 'player.h')
-rw-r--r--player.h132
1 files changed, 96 insertions, 36 deletions
diff --git a/player.h b/player.h
index 3274d64..cb197e4 100644
--- a/player.h
+++ b/player.h
@@ -7,30 +7,32 @@
#include "config.h"
#include "definitions.h"
-#ifdef HAVE_LIBMBEDTLS
+#ifdef CONFIG_MBEDTLS
#include <mbedtls/aes.h>
#include <mbedtls/havege.h>
#endif
-#ifdef HAVE_LIBPOLARSSL
+#ifdef CONFIG_POLARSSL
#include <polarssl/aes.h>
#include <polarssl/havege.h>
#endif
-#ifdef HAVE_LIBSSL
+#ifdef CONFIG_OPENSSL
#include <openssl/aes.h>
#endif
#include "alac.h"
#include "audio.h"
-#define time_ping_history 8
+#define time_ping_history 128 // at 1 per three seconds, approximately six minutes of records
typedef struct time_ping_record {
uint64_t local_to_remote_difference;
uint64_t dispersion;
uint64_t local_time;
uint64_t remote_time;
+ int sequence_number;
+ int chosen;
} time_ping_record;
typedef uint16_t seq_t;
@@ -38,7 +40,7 @@ typedef uint16_t seq_t;
typedef struct audio_buffer_entry { // decoded audio packets
int ready;
int resend_level;
- int64_t timestamp;
+ // int64_t timestamp;
seq_t sequence_number;
uint32_t given_timestamp; // for debugging and checking
signed short *data;
@@ -46,7 +48,7 @@ typedef struct audio_buffer_entry { // decoded audio packets
} abuf_t;
// default buffer size
-// This eeds to be a power of 2 because of the way BUFIDX(seqno) works.
+// This needs to be a power of 2 because of the way BUFIDX(seqno) works.
// 512 is the minimum for normal operation -- it gives 512*352/44100 or just over 4 seconds of
// buffers.
// For at least 10 seconds, you need to go to 2048.
@@ -59,43 +61,76 @@ typedef struct audio_buffer_entry { // decoded audio packets
#define BUFFER_FRAMES 1024
+enum audio_stream_type {
+ ast_unknown,
+ ast_uncompressed, // L16/44100/2
+ ast_apple_lossless,
+} ast_type;
+
typedef struct {
int encrypted;
uint8_t aesiv[16], aeskey[16];
int32_t fmtp[12];
+ enum audio_stream_type type;
} stream_cfg;
typedef struct {
- int connection_number; // for debug ID purposes, nothing else...
- int resend_interval; // this is really just for debugging
- int AirPlayVersion; // zero if not an AirPlay session. Used to help calculate latency
- int64_t latency; // the actual latency used for this play session
- int64_t minimum_latency; // set if an a=min-latency: line appears in the ANNOUNCE message; zero
- // otherwise
- int64_t maximum_latency; // set if an a=max-latency: line appears in the ANNOUNCE message; zero
- // otherwise
+ int connection_number; // for debug ID purposes, nothing else...
+ int resend_interval; // this is really just for debugging
+ int AirPlayVersion; // zero if not an AirPlay session. Used to help calculate latency
+ uint32_t latency; // the actual latency used for this play session
+ uint32_t minimum_latency; // set if an a=min-latency: line appears in the ANNOUNCE message; zero
+ // otherwise
+ uint32_t maximum_latency; // set if an a=max-latency: line appears in the ANNOUNCE message; zero
+ // otherwise
+ int software_mute_enabled; // if we don't have a real mute that we can use
int fd;
- int authorized; // set if a password is required and has been supplied
+ int authorized; // set if a password is required and has been supplied
+ char *auth_nonce; // the session nonce, if needed
stream_cfg stream;
SOCKADDR remote, local;
- int stop;
- int running;
- pthread_t thread, timer_requester;
+ volatile int stop;
+ volatile int running;
+ volatile uint64_t watchdog_bark_time;
+ volatile int watchdog_barks; // number of times the watchdog has timed out and done something
+ int unfixable_error_reported; // set when an unfixable error command has been executed.
- // pthread_t *ptp;
- pthread_t *player_thread;
- pthread_rwlock_t player_thread_lock; // used to control access by "outsiders"
+ time_t playstart;
+ pthread_t thread, timer_requester, rtp_audio_thread, rtp_control_thread, rtp_timing_thread,
+ player_watchdog_thread;
+
+ // buffers to delete on exit
+ signed short *tbuf;
+ int32_t *sbuf;
+ char *outbuf;
+
+ // for holding the output rate information until printed out at the end of a session
+ double frame_rate;
+ int frame_rate_status;
+
+ // for holding input rate information until printed out at the end of a session
+
+ double input_frame_rate;
+ int input_frame_rate_starting_point_is_valid;
+
+ uint64_t frames_inward_measurement_start_time;
+ uint32_t frames_inward_frames_received_at_measurement_start_time;
+
+ uint64_t frames_inward_measurement_time;
+ uint32_t frames_inward_frames_received_at_measurement_time;
+ // other stuff...
+ pthread_t *player_thread;
abuf_t audio_buffer[BUFFER_FRAMES];
- int max_frames_per_packet, input_num_channels, input_bit_depth, input_rate;
+ unsigned int max_frames_per_packet, input_num_channels, input_bit_depth, input_rate;
int input_bytes_per_frame, output_bytes_per_frame, output_sample_ratio;
int max_frame_size_change;
int64_t previous_random_number;
alac_file *decoder_info;
uint64_t packet_count;
+ uint64_t packet_count_since_flush;
int connection_state_to_output;
- int player_thread_please_stop;
uint64_t first_packet_time_to_play;
int64_t time_since_play_started; // nanoseconds
// stats
@@ -105,7 +140,7 @@ typedef struct {
int32_t last_seqno_read;
// mutexes and condition variables
pthread_cond_t flowcontrol;
- pthread_mutex_t ab_mutex, flush_mutex;
+ pthread_mutex_t ab_mutex, flush_mutex, volume_control_mutex;
int fix_volume;
uint32_t timestamp_epoch, last_timestamp,
maximum_timestamp_interval; // timestamp_epoch of zero means not initialised, could start at 2
@@ -113,19 +148,19 @@ typedef struct {
int ab_buffering, ab_synced;
int64_t first_packet_timestamp;
int flush_requested;
- int64_t flush_rtp_timestamp;
+ uint32_t flush_rtp_timestamp;
uint64_t time_of_last_audio_packet;
seq_t ab_read, ab_write;
-#ifdef HAVE_LIBMBEDTLS
+#ifdef CONFIG_MBEDTLS
mbedtls_aes_context dctx;
#endif
-#ifdef HAVE_LIBPOLARSSL
+#ifdef CONFIG_POLARSSL
aes_context dctx;
#endif
-#ifdef HAVE_LIBSSL
+#ifdef CONFIG_OPENSSL
AES_KEY aes;
#endif
@@ -161,27 +196,46 @@ typedef struct {
uint16_t local_timing_port;
int64_t latency_delayed_timestamp; // this is for debugging only...
- int64_t reference_timestamp;
- uint64_t reference_timestamp_time;
+
+ // this is what connects an rtp timestamp to the remote time
+
+ uint32_t reference_timestamp;
uint64_t remote_reference_timestamp_time;
+ // used as the initials values for calculating the rate at which the source thinks it's sending
+ // frames
+ uint32_t initial_reference_timestamp;
+ uint64_t initial_reference_time;
+ double remote_frame_rate;
+
+ // the ratio of the following should give us the operating rate, nominally 44,100
+ int64_t reference_to_previous_frame_difference;
+ uint64_t reference_to_previous_time_difference;
+
// debug variables
int request_sent;
- uint8_t time_ping_count;
+ int time_ping_count;
struct time_ping_record time_pings[time_ping_history];
uint64_t departure_time; // dangerous -- this assumes that there will never be two timing
// request in flight at the same time
pthread_mutex_t reference_time_mutex;
+ pthread_mutex_t watchdog_mutex;
+ double local_to_remote_time_gradient; // if no drift, this would be exactly 1.0; likely it's
+ // slightly above or below.
+ int local_to_remote_time_gradient_sample_count; // the number of samples used to calculate the
+ // gradient
+ // add the following to the local time to get the remote time modulo 2^64
uint64_t local_to_remote_time_difference; // used to switch between local and remote clocks
+ uint64_t local_to_remote_time_difference_measurement_time; // when the above was calculated
int last_stuff_request;
- int64_t play_segment_reference_frame;
- uint64_t play_segment_reference_frame_remote_time;
+ // int64_t play_segment_reference_frame;
+ // uint64_t play_segment_reference_frame_remote_time;
int32_t buffer_occupancy; // allow it to be negative because seq_diff may be negative
int64_t session_corrections;
@@ -197,16 +251,22 @@ typedef struct {
// zero
uint32_t dacp_active_remote; // key to send to the remote controller
void *dapo_private_storage; // this is used for compatibility, if dacp stuff isn't enabled.
+
+ int enable_dither; // needed for filling silences before play actually starts
+ int64_t dac_buffer_queue_minimum_length;
} rtsp_conn_info;
+uint32_t modulo_32_offset(uint32_t from, uint32_t to);
+uint64_t modulo_64_offset(uint64_t from, uint64_t to);
+
int player_play(rtsp_conn_info *conn);
int player_stop(rtsp_conn_info *conn);
void player_volume(double f, rtsp_conn_info *conn);
void player_volume_without_notification(double f, rtsp_conn_info *conn);
-void player_flush(int64_t timestamp, rtsp_conn_info *conn);
-void player_put_packet(seq_t seqno, uint32_t actual_timestamp, int64_t timestamp, uint8_t *data,
- int len, rtsp_conn_info *conn);
+void player_flush(uint32_t timestamp, rtsp_conn_info *conn);
+void player_put_packet(seq_t seqno, uint32_t actual_timestamp, uint8_t *data, int len,
+ rtsp_conn_info *conn);
int64_t monotonic_timestamp(uint32_t timestamp,
rtsp_conn_info *conn); // add an epoch to the timestamp. The monotonic
// timestamp guaranteed to start between 2^32 2^33