Merge stability changes to develoment branch and its convolution additions
This commit is contained in:
@@ -24,7 +24,7 @@ typedef struct {
|
||||
// "sr=44100", "vn=3", "txtvers=1", config.password ? "pw=true" : "pw=false"
|
||||
|
||||
#define MDNS_RECORD_WITH_METADATA \
|
||||
"sf=0x4", "fv=76400.10", "am=AirPort4,107", "vs=105.1", "tp=TCP,UDP", "vn=65537", \
|
||||
"sf=0x4", "fv=76400.10", "am=ShairportSync", "vs=105.1", "tp=TCP,UDP", "vn=65537", \
|
||||
METADATA_EXPRESSION, "ss=16", "sr=44100", "da=true", "sv=false", "et=0,1", "ek=1", "cn=0,1", \
|
||||
"ch=2", "txtvers=1", config.password ? "pw=true" : "pw=false"
|
||||
|
||||
@@ -35,7 +35,7 @@ typedef struct {
|
||||
// "txtvers=1", config.password ? "pw=true" : "pw=false"
|
||||
|
||||
#define MDNS_RECORD_WITHOUT_METADATA \
|
||||
"sf=0x4", "fv=76400.10", "am=AirPort4,107", "vs=105.1", "tp=TCP,UDP", "vn=65537", "ss=16", \
|
||||
"sf=0x4", "fv=76400.10", "am=ShairportSync", "vs=105.1", "tp=TCP,UDP", "vn=65537", "ss=16", \
|
||||
"sr=44100", "da=true", "sv=false", "et=0,1", "ek=1", "cn=0,1", "ch=2", "txtvers=1", \
|
||||
config.password ? "pw=true" : "pw=false"
|
||||
|
||||
|
||||
@@ -1,7 +1,38 @@
|
||||
#ifndef _PLAYER_H
|
||||
#define _PLAYER_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#ifdef HAVE_LIBMBEDTLS
|
||||
#include <mbedtls/aes.h>
|
||||
#include <mbedtls/havege.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBPOLARSSL
|
||||
#include <polarssl/aes.h>
|
||||
#include <polarssl/havege.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_LIBSSL
|
||||
#include <openssl/aes.h>
|
||||
#endif
|
||||
|
||||
#include "audio.h"
|
||||
#include "alac.h"
|
||||
|
||||
typedef uint16_t seq_t;
|
||||
|
||||
typedef struct audio_buffer_entry { // decoded audio packets
|
||||
int ready;
|
||||
int64_t timestamp;
|
||||
seq_t sequence_number;
|
||||
signed short *data;
|
||||
int length; // the length of the decoded data
|
||||
} abuf_t;
|
||||
|
||||
// default buffer size
|
||||
// needs to be a power of 2 because of the way BUFIDX(seqno) works
|
||||
#define BUFFER_FRAMES 512
|
||||
|
||||
typedef struct {
|
||||
int encrypted;
|
||||
@@ -9,20 +40,68 @@ typedef struct {
|
||||
int32_t fmtp[12];
|
||||
} stream_cfg;
|
||||
|
||||
typedef uint16_t seq_t;
|
||||
typedef struct {
|
||||
int fd;
|
||||
int authorized; // set if a password is required and has been supplied
|
||||
stream_cfg stream;
|
||||
SOCKADDR remote, local;
|
||||
int stop;
|
||||
int running;
|
||||
pthread_t thread;
|
||||
pthread_t player_thread;
|
||||
|
||||
// wrapped number between two seq_t.
|
||||
int32_t seq_diff(seq_t a, seq_t b);
|
||||
abuf_t audio_buffer[BUFFER_FRAMES];
|
||||
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;
|
||||
uint32_t please_stop;
|
||||
uint64_t packet_count;
|
||||
int shutdown_requested;
|
||||
int connection_state_to_output;
|
||||
int player_thread_please_stop;
|
||||
int64_t first_packet_time_to_play, time_since_play_started; // nanoseconds
|
||||
// stats
|
||||
uint64_t missing_packets, late_packets, too_late_packets, resend_requests;
|
||||
int decoder_in_use;
|
||||
// debug variables
|
||||
int32_t last_seqno_read;
|
||||
// mutexes and condition variables
|
||||
pthread_cond_t flowcontrol;
|
||||
pthread_mutex_t ab_mutex,flush_mutex;
|
||||
pthread_mutex_t vol_mutex;
|
||||
int fix_volume;
|
||||
uint32_t timestamp_epoch, last_timestamp, maximum_timestamp_interval; // timestamp_epoch of zero means not initialised, could start at 2
|
||||
// or 1.
|
||||
int ab_buffering,ab_synced;
|
||||
int64_t first_packet_timestamp;
|
||||
int flush_requested;
|
||||
int64_t flush_rtp_timestamp;
|
||||
uint64_t time_of_last_audio_packet;
|
||||
seq_t ab_read, ab_write;
|
||||
|
||||
int player_play(stream_cfg *cfg, pthread_t *thread);
|
||||
void player_stop(pthread_t *thread);
|
||||
#ifdef HAVE_LIBMBEDTLS
|
||||
mbedtls_aes_context dctx;
|
||||
#endif
|
||||
|
||||
void player_volume(double f);
|
||||
void player_flush(int64_t timestamp);
|
||||
#ifdef HAVE_LIBPOLARSSL
|
||||
aes_context dctx;
|
||||
#endif
|
||||
|
||||
void player_put_packet(seq_t seqno, int64_t timestamp, uint8_t *data, int len);
|
||||
#ifdef HAVE_LIBSSL
|
||||
AES_KEY aes;
|
||||
#endif
|
||||
} rtsp_conn_info;
|
||||
|
||||
int64_t monotonic_timestamp(uint32_t timestamp); // add an epoch to the timestamp. The monotonic
|
||||
int player_play(pthread_t *thread, rtsp_conn_info* conn);
|
||||
void player_stop(pthread_t *thread, rtsp_conn_info* conn);
|
||||
|
||||
void player_volume(double f, rtsp_conn_info* conn);
|
||||
void player_flush(int64_t timestamp, rtsp_conn_info* conn);
|
||||
void player_put_packet(seq_t seqno, int64_t 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
|
||||
// frames and continue up to 2^64 frames
|
||||
// which is about 2*10^8 * 1,000 seconds at 384,000 frames per second -- about 2 trillion seconds.
|
||||
|
||||
@@ -98,7 +98,7 @@ void *rtp_audio_receiver(void *arg) {
|
||||
debug(2, "Audio receiver -- Server RTP thread starting.");
|
||||
|
||||
// we inherit the signal mask (SIGUSR1)
|
||||
struct inter_threads_record *itr = arg;
|
||||
rtsp_conn_info *conn = arg;
|
||||
|
||||
int32_t last_seqno = -1;
|
||||
uint8_t packet[2048], *pktp;
|
||||
@@ -114,7 +114,7 @@ void *rtp_audio_receiver(void *arg) {
|
||||
float stat_M2 = 0.0;
|
||||
|
||||
ssize_t nread;
|
||||
while (itr->please_stop == 0) {
|
||||
while (conn->please_stop == 0) {
|
||||
nread = recv(audio_socket, packet, sizeof(packet), 0);
|
||||
|
||||
uint64_t local_time_now_fp = get_absolute_time_in_fp();
|
||||
@@ -129,7 +129,7 @@ void *rtp_audio_receiver(void *arg) {
|
||||
stat_mean += stat_delta / stat_n;
|
||||
stat_M2 += stat_delta * (time_interval_us - stat_mean);
|
||||
if (stat_n % 2500 == 0) {
|
||||
debug(2, "Packet reception interval stats: mean, standard deviation and max for the last "
|
||||
debug(3, "Packet reception interval stats: mean, standard deviation and max for the last "
|
||||
"2,500 packets in microseconds: %10.1f, %10.1f, %10.1f.",
|
||||
stat_mean, sqrtf(stat_M2 / (stat_n - 1)), longest_packet_time_interval_us);
|
||||
stat_n = 0;
|
||||
@@ -164,7 +164,7 @@ void *rtp_audio_receiver(void *arg) {
|
||||
// debug(3, "RTP: Packets out of sequence: expected: %d, got %d.", last_seqno, seqno);
|
||||
last_seqno = seqno; // reset warning...
|
||||
}
|
||||
int64_t timestamp = monotonic_timestamp(ntohl(*(unsigned long *)(pktp + 4)));
|
||||
int64_t timestamp = monotonic_timestamp(ntohl(*(unsigned long *)(pktp + 4)),conn);
|
||||
|
||||
// if (packet[1]&0x10)
|
||||
// debug(1,"Audio packet Extension bit set.");
|
||||
@@ -174,7 +174,7 @@ void *rtp_audio_receiver(void *arg) {
|
||||
|
||||
// check if packet contains enough content to be reasonable
|
||||
if (plen >= 16) {
|
||||
player_put_packet(seqno, timestamp, pktp, plen);
|
||||
player_put_packet(seqno, timestamp, pktp, plen,conn);
|
||||
continue;
|
||||
}
|
||||
if (type == 0x56 && seqno == 0) {
|
||||
@@ -197,7 +197,7 @@ void *rtp_control_receiver(void *arg) {
|
||||
// we inherit the signal mask (SIGUSR1)
|
||||
|
||||
debug(2, "Control receiver -- Server RTP thread starting.");
|
||||
struct inter_threads_record *itr = arg;
|
||||
rtsp_conn_info *conn = arg;
|
||||
|
||||
reference_timestamp = 0; // nothing valid received yet
|
||||
uint8_t packet[2048], *pktp;
|
||||
@@ -205,7 +205,7 @@ void *rtp_control_receiver(void *arg) {
|
||||
uint64_t remote_time_of_sync, local_time_now, remote_time_now;
|
||||
int64_t sync_rtp_timestamp, rtp_timestamp_less_latency;
|
||||
ssize_t nread;
|
||||
while (itr->please_stop == 0) {
|
||||
while (conn->please_stop == 0) {
|
||||
nread = recv(control_socket, packet, sizeof(packet), 0);
|
||||
local_time_now = get_absolute_time_in_fp();
|
||||
// clock_gettime(CLOCK_MONOTONIC,&tn);
|
||||
@@ -234,8 +234,8 @@ void *rtp_control_receiver(void *arg) {
|
||||
|
||||
// debug(1,"Remote Sync Time: %0llx.",remote_time_of_sync);
|
||||
|
||||
rtp_timestamp_less_latency = monotonic_timestamp(ntohl(*((uint32_t *)&packet[4])));
|
||||
sync_rtp_timestamp = monotonic_timestamp(ntohl(*((uint32_t *)&packet[16])));
|
||||
rtp_timestamp_less_latency = monotonic_timestamp(ntohl(*((uint32_t *)&packet[4])),conn);
|
||||
sync_rtp_timestamp = monotonic_timestamp(ntohl(*((uint32_t *)&packet[16])),conn);
|
||||
|
||||
if (config.use_negotiated_latencies) {
|
||||
int64_t la = sync_rtp_timestamp - rtp_timestamp_less_latency + 11025;
|
||||
@@ -274,14 +274,14 @@ void *rtp_control_receiver(void *arg) {
|
||||
plen -= 4;
|
||||
seq_t seqno = ntohs(*(unsigned short *)(pktp + 2));
|
||||
|
||||
int64_t timestamp = monotonic_timestamp(ntohl(*(unsigned long *)(pktp + 4)));
|
||||
int64_t timestamp = monotonic_timestamp(ntohl(*(unsigned long *)(pktp + 4)),conn);
|
||||
|
||||
pktp += 12;
|
||||
plen -= 12;
|
||||
|
||||
// check if packet contains enough content to be reasonable
|
||||
if (plen >= 16) {
|
||||
player_put_packet(seqno, timestamp, pktp, plen);
|
||||
player_put_packet(seqno, timestamp, pktp, plen, conn);
|
||||
continue;
|
||||
} else {
|
||||
debug(1, "Too-short retransmitted audio packet received in control port, ignored.");
|
||||
@@ -356,7 +356,7 @@ void *rtp_timing_receiver(void *arg) {
|
||||
debug(2, "Timing receiver -- Server RTP thread starting.");
|
||||
// we inherit the signal mask (SIGUSR1)
|
||||
|
||||
struct inter_threads_record *itr = arg;
|
||||
rtsp_conn_info *conn = arg;
|
||||
|
||||
uint8_t packet[2048], *pktp;
|
||||
ssize_t nread;
|
||||
@@ -374,7 +374,7 @@ void *rtp_timing_receiver(void *arg) {
|
||||
uint64_t first_local_to_remote_time_difference = 0;
|
||||
uint64_t first_local_to_remote_time_difference_time;
|
||||
uint64_t l2rtd = 0;
|
||||
while (itr->please_stop == 0) {
|
||||
while (conn->please_stop == 0) {
|
||||
nread = recv(timing_socket, packet, sizeof(packet), 0);
|
||||
arrival_time = get_absolute_time_in_fp();
|
||||
// clock_gettime(CLOCK_MONOTONIC,&att);
|
||||
|
||||
@@ -5,8 +5,6 @@
|
||||
|
||||
#include "player.h"
|
||||
|
||||
typedef struct inter_threads_record { uint32_t please_stop; } inter_threads_record;
|
||||
|
||||
void *rtp_audio_receiver(void *arg);
|
||||
void *rtp_control_receiver(void *arg);
|
||||
void *rtp_timing_receiver(void *arg);
|
||||
|
||||
@@ -90,17 +90,6 @@ static pthread_mutex_t reference_counter_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
// static int please_shutdown = 0;
|
||||
// static pthread_t playing_thread = 0;
|
||||
|
||||
typedef struct {
|
||||
int fd;
|
||||
int authorized; // set is a password is required and has been supplied
|
||||
stream_cfg stream;
|
||||
SOCKADDR remote, local;
|
||||
int stop;
|
||||
int running;
|
||||
pthread_t thread;
|
||||
pthread_t player_thread;
|
||||
} rtsp_conn_info;
|
||||
|
||||
static rtsp_conn_info *playing_conn =
|
||||
NULL; // the data structure representing the connection that has the player.
|
||||
static rtsp_conn_info **conns = NULL;
|
||||
@@ -654,7 +643,7 @@ static void handle_record(rtsp_conn_info *conn, rtsp_message *req, rtsp_message
|
||||
rtptime = uatoi(p + 1); // unsigned integer -- up to 2^32-1
|
||||
rtptime--;
|
||||
// debug(1,"RTSP Flush Requested by handle_record: %u.",rtptime);
|
||||
player_flush(rtptime);
|
||||
player_flush(rtptime,conn);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -695,7 +684,7 @@ static void handle_flush(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *
|
||||
}
|
||||
}
|
||||
// debug(1,"RTSP Flush Requested: %u.",rtptime);
|
||||
player_flush(rtptime);
|
||||
player_flush(rtptime,conn);
|
||||
resp->respcode = 200;
|
||||
}
|
||||
|
||||
@@ -819,7 +808,7 @@ static void handle_setup(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *
|
||||
strcat(hdr, q); // should unsplice the timing port entry
|
||||
}
|
||||
|
||||
player_play(&conn->stream, &conn->player_thread); // the thread better be 0
|
||||
player_play(&conn->player_thread,conn); // the thread better be 0
|
||||
|
||||
char *resphdr = alloca(200);
|
||||
*resphdr = 0;
|
||||
@@ -859,7 +848,7 @@ static void handle_set_parameter_parameter(rtsp_conn_info *conn, rtsp_message *r
|
||||
float volume = atof(cp + 8);
|
||||
if (config.ignore_volume_control == 0) {
|
||||
debug(2, "volume: %f\n", volume);
|
||||
player_volume(volume);
|
||||
player_volume(volume,conn);
|
||||
}
|
||||
#ifdef CONFIG_METADATA
|
||||
else { // if ignore volume is on...
|
||||
@@ -1764,7 +1753,7 @@ static void *rtsp_conversation_thread_func(void *pconn) {
|
||||
|
||||
debug(1, "Closing down RTSP conversation thread...");
|
||||
if (rtsp_playing()) {
|
||||
player_stop(&conn->player_thread); // might be less noisy doing this first
|
||||
player_stop(&conn->player_thread,conn); // might be less noisy doing this first
|
||||
rtp_shutdown();
|
||||
// usleep(400000); // let an angel pass...
|
||||
pthread_mutex_unlock(&play_lock);
|
||||
|
||||
Reference in New Issue
Block a user