experimental
This commit is contained in:
+2
-1
@@ -489,7 +489,8 @@ static int init(int argc, char **argv) {
|
||||
}
|
||||
close_mixer();
|
||||
}
|
||||
pthread_cleanup_pop(1); // release the mutex
|
||||
debug_mutex_unlock(&alsa_mutex, 3); // release the mutex
|
||||
pthread_cleanup_pop(0);
|
||||
} else {
|
||||
// debug(1, "Has no mixer and thus no hardware mute.");
|
||||
}
|
||||
|
||||
@@ -58,7 +58,7 @@ void rtp_initialise(rtsp_conn_info *conn) {
|
||||
}
|
||||
|
||||
void rtp_terminate(rtsp_conn_info *conn) {
|
||||
|
||||
conn->reference_timestamp = 0;
|
||||
// destroy the timer mutex
|
||||
int rc = pthread_mutex_destroy(&conn->reference_time_mutex);
|
||||
if (rc)
|
||||
@@ -125,9 +125,15 @@ void *rtp_audio_receiver(void *arg) {
|
||||
float stat_mean = 0.0;
|
||||
float stat_M2 = 0.0;
|
||||
|
||||
int frame_count = 0;
|
||||
ssize_t nread;
|
||||
while (1) {
|
||||
nread = recv(conn->audio_socket, packet, sizeof(packet), 0);
|
||||
|
||||
frame_count++;
|
||||
if (frame_count<10)
|
||||
debug(1,"Recv'ed %d bytes. First two bytes are %02X,%02X ",nread,packet[0],packet[1]);
|
||||
else {
|
||||
|
||||
uint64_t local_time_now_fp = get_absolute_time_in_fp();
|
||||
if (time_of_previous_packet_fp) {
|
||||
@@ -167,6 +173,19 @@ void *rtp_audio_receiver(void *arg) {
|
||||
// increment last_seqno and see if it's the same as the incoming seqno
|
||||
|
||||
if (type == 0x60) { // regular audio data
|
||||
|
||||
/*
|
||||
char obf[4096];
|
||||
char *obfp = obf;
|
||||
int obfc;
|
||||
for (obfc=0;obfc<plen;obfc++) {
|
||||
snprintf(obfp, 3, "%02X", pktp[obfc]);
|
||||
obfp+=2;
|
||||
};
|
||||
*obfp=0;
|
||||
debug(1,"Audio Packet Received: \"%s\"",obf);
|
||||
*/
|
||||
|
||||
if (last_seqno == -1)
|
||||
last_seqno = seqno;
|
||||
else {
|
||||
@@ -180,6 +199,9 @@ void *rtp_audio_receiver(void *arg) {
|
||||
}
|
||||
|
||||
uint32_t actual_timestamp = ntohl(*(uint32_t *)(pktp + 4));
|
||||
|
||||
uint32_t ssid = ntohl(*(uint32_t *)(pktp + 8));
|
||||
debug(1, "Audio packet SSID: %08X,%u", ssid,ssid);
|
||||
|
||||
// if (packet[1]&0x10)
|
||||
// debug(1,"Audio packet Extension bit set.");
|
||||
@@ -207,6 +229,7 @@ void *rtp_audio_receiver(void *arg) {
|
||||
} else {
|
||||
debug(1, "Error receiving an audio packet.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -284,16 +307,13 @@ void *rtp_control_receiver(void *arg) {
|
||||
|
||||
// Best guess is that this delay is 11,025 frames.
|
||||
|
||||
// uint32_t rtlt = nctohl(&packet[4]); // raw timestamp less latency
|
||||
// uint32_t rt = nctohl(&packet[16]); // raw timestamp
|
||||
uint32_t rtlt = nctohl(&packet[4]); // raw timestamp less latency
|
||||
uint32_t rt = nctohl(&packet[16]); // raw timestamp
|
||||
|
||||
// uint32_t fl = nctohs(&packet[2]); //
|
||||
uint32_t fl = nctohs(&packet[2]); //
|
||||
|
||||
// debug(1,"Sync Packet of %d bytes received: \"%s\", flags: %d, timestamps %u and
|
||||
%u,
|
||||
giving a latency of %d frames.",plen,obf,fl,rt,rtlt,rt-rtlt);
|
||||
// debug(1,"Monotonic timestamps are: %" PRId64 " and %" PRId64 "
|
||||
respectively.",monotonic_timestamp(rt, conn),monotonic_timestamp(rtlt, conn));
|
||||
debug(1,"Sync Packet of %d bytes received: \"%s\", flags: %d, timestamps %u and %u, giving a latency of %d frames.",plen,obf,fl,rt,rtlt,rt-rtlt);
|
||||
//debug(1,"Monotonic timestamps are: %" PRId64 " and %" PRId64 " respectively.",monotonic_timestamp(rt, conn),monotonic_timestamp(rtlt, conn));
|
||||
}
|
||||
*/
|
||||
if (conn->local_to_remote_time_difference) { // need a time packet to be interchanged
|
||||
@@ -585,10 +605,10 @@ void *rtp_timing_receiver(void *arg) {
|
||||
(drand48() > config.diagnostic_drop_packet_fraction)) {
|
||||
arrival_time = get_absolute_time_in_fp();
|
||||
|
||||
// ssize_t plen = nread;
|
||||
ssize_t plen = nread;
|
||||
// debug(1,"Packet Received on Timing Port.");
|
||||
if (packet[1] == 0xd3) { // timing reply
|
||||
/*
|
||||
|
||||
char obf[4096];
|
||||
char *obfp = obf;
|
||||
int obfc;
|
||||
@@ -597,8 +617,8 @@ void *rtp_timing_receiver(void *arg) {
|
||||
obfp+=2;
|
||||
};
|
||||
*obfp=0;
|
||||
//debug(1,"Timing Packet Received: \"%s\"",obf);
|
||||
*/
|
||||
debug(1,"Timing Packet Received: \"%s\"",obf);
|
||||
|
||||
|
||||
// arrival_time = ((uint64_t)att.tv_sec<<32)+((uint64_t)att.tv_nsec<<32)/1000000000;
|
||||
// departure_time = ((uint64_t)dtt.tv_sec<<32)+((uint64_t)dtt.tv_nsec<<32)/1000000000;
|
||||
|
||||
@@ -89,7 +89,9 @@ enum rtsp_read_request_response {
|
||||
};
|
||||
|
||||
// Mike Brady's part...
|
||||
static pthread_mutex_t play_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
// always lock use this when accessing the playing conn value
|
||||
static pthread_mutex_t playing_conn_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
// every time we want to retain or release a reference count, lock it with this
|
||||
// if a reference count is read as zero, it means the it's being deallocated.
|
||||
@@ -279,8 +281,6 @@ void cancel_all_RTSP_threads(void) {
|
||||
for (i = 0; i < nconns; i++) {
|
||||
debug(1, "Connection %d: joining.", conns[i]->connection_number);
|
||||
pthread_join(conns[i]->thread, NULL);
|
||||
if (conns[i] == playing_conn)
|
||||
playing_conn = NULL;
|
||||
free(conns[i]);
|
||||
}
|
||||
}
|
||||
@@ -295,8 +295,6 @@ void cleanup_threads(void) {
|
||||
conns[i]->connection_number);
|
||||
pthread_join(conns[i]->thread, &retval);
|
||||
debug(3, "RTSP connection thread %d deleted...", conns[i]->connection_number);
|
||||
if (conns[i] == playing_conn)
|
||||
playing_conn = NULL;
|
||||
free(conns[i]);
|
||||
nconns--;
|
||||
if (nconns)
|
||||
@@ -461,7 +459,7 @@ int msg_handle_line(rtsp_message **pmsg, char *line) {
|
||||
char *sp, *p;
|
||||
sp = NULL; // this is to quieten a compiler warning
|
||||
|
||||
// debug(1, "received request: %s", line);
|
||||
debug(1, "received request: %s", line);
|
||||
|
||||
p = strtok_r(line, " ", &sp);
|
||||
if (!p)
|
||||
@@ -898,8 +896,9 @@ void handle_setup(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *resp) {
|
||||
error:
|
||||
warn("Connection %d: SETUP -- Error in setup request -- unlocking play lock.",
|
||||
conn->connection_number);
|
||||
playing_conn = NULL;
|
||||
pthread_mutex_unlock(&play_lock);
|
||||
debug_mutex_lock(&playing_conn_lock, 1000000 , 3);
|
||||
playing_conn = NULL; // this connection definitely doesn't have the play lock
|
||||
debug_mutex_unlock(&playing_conn_lock, 3);
|
||||
resp->respcode = 451; // invalid arguments
|
||||
}
|
||||
|
||||
@@ -1523,62 +1522,76 @@ static void handle_set_parameter(rtsp_conn_info *conn, rtsp_message *req, rtsp_m
|
||||
|
||||
static void handle_announce(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *resp) {
|
||||
debug(2, "Connection %d: ANNOUNCE", conn->connection_number);
|
||||
|
||||
|
||||
int have_the_player = 0;
|
||||
|
||||
// interrupt session if permitted
|
||||
if (pthread_mutex_trylock(&play_lock) == 0) {
|
||||
int should_wait = 0;
|
||||
|
||||
// try to become the current playing_conn
|
||||
|
||||
debug_mutex_lock(&playing_conn_lock, 1000000 , 3); //get it
|
||||
|
||||
if (playing_conn == NULL) {
|
||||
playing_conn = conn;
|
||||
have_the_player = 1;
|
||||
} else if ((playing_conn) &&
|
||||
(playing_conn->connection_number == conn->connection_number)) { // duplicate ANNOUNCE
|
||||
warn("Duplicate ANNOUNCE, by the look of it!");
|
||||
have_the_player = 1;
|
||||
} else {
|
||||
int should_wait = 0;
|
||||
|
||||
if (!playing_conn)
|
||||
die("Non existent playing_conn with play_lock enabled.");
|
||||
debug(1, "Connection %d: ANNOUNCE: already playing when checked by connection %d.",
|
||||
playing_conn->connection_number, conn->connection_number);
|
||||
if (playing_conn->stop) {
|
||||
debug(1, "Connetion %d: ANNOUNCE: already shutting down; waiting for it...",playing_conn->connection_number);
|
||||
} else if (playing_conn == conn) {
|
||||
have_the_player = 1;
|
||||
warn("Duplicate ANNOUNCE, by the look of it!");
|
||||
} else if (playing_conn->stop) {
|
||||
debug(1, "Connection %d: ANNOUNCE: already shutting down; waiting for it...",playing_conn->connection_number);
|
||||
should_wait = 1;
|
||||
} else if (config.allow_session_interruption == 1) {
|
||||
// some thread has the player ... ask it to relinquish the thread
|
||||
debug(1, "Connection %d: ANNOUNCE: asking playing connection %d to shut down.",
|
||||
} else if (config.allow_session_interruption == 1) {
|
||||
debug(1, "Connection %d: ANNOUNCE: asking playing connection %d to shut down.",
|
||||
conn->connection_number, playing_conn->connection_number);
|
||||
if (playing_conn == conn) {
|
||||
debug(1, "Connection %d: ANNOUNCE: asking to stop itself! Nothing done.",conn->connection_number);
|
||||
} else {
|
||||
player_stop(playing_conn);
|
||||
playing_conn->stop = 1;
|
||||
pthread_cancel(playing_conn->thread); // asking the RTSP thread to exit
|
||||
should_wait = 1;
|
||||
}
|
||||
}
|
||||
playing_conn->stop = 1;
|
||||
pthread_cancel(playing_conn->thread); // asking the RTSP thread to exit
|
||||
should_wait = 1;
|
||||
}
|
||||
debug_mutex_unlock(&playing_conn_lock, 3);
|
||||
|
||||
if (should_wait) {
|
||||
useconds_t time_remaining = 3000000;
|
||||
if (should_wait) {
|
||||
useconds_t time_remaining = 3000000;
|
||||
|
||||
while ((time_remaining > 0) && (have_the_player == 0)) {
|
||||
if (pthread_mutex_trylock(&play_lock) == 0)
|
||||
have_the_player = 1;
|
||||
else {
|
||||
while ((time_remaining > 0) && (have_the_player == 0)) {
|
||||
debug_mutex_lock(&playing_conn_lock, 1000000 , 3); //get it
|
||||
if (playing_conn == NULL) {
|
||||
playing_conn = conn;
|
||||
have_the_player = 1;
|
||||
}
|
||||
debug_mutex_unlock(&playing_conn_lock, 3);
|
||||
|
||||
if (have_the_player == 0) {
|
||||
usleep(100000);
|
||||
time_remaining -= 100000;
|
||||
}
|
||||
}
|
||||
if (have_the_player == 1) {
|
||||
debug(1, "Connection %d: ANNOUNCE got the player", conn->connection_number);
|
||||
usleep(1000000); // this is just to let everything settle a bit
|
||||
} else
|
||||
debug(1, "Connection %d: ANNOUNCE failed to get the player", conn->connection_number);
|
||||
|
||||
if (have_the_player == 1) {
|
||||
debug(1, "Connection %d: ANNOUNCE got the player", conn->connection_number);
|
||||
usleep(2000000); // this is just to let everything settle a bit
|
||||
} else {
|
||||
debug(1, "Connection %d: ANNOUNCE failed to get the player", conn->connection_number);
|
||||
}
|
||||
}
|
||||
|
||||
if (have_the_player) {
|
||||
playing_conn = conn; // the present connection is now playing
|
||||
debug(3, "RTSP conversation thread %d has acquired play lock.", conn->connection_number);
|
||||
|
||||
{
|
||||
char *cp = req->content;
|
||||
int cp_left = req->contentlength;
|
||||
while (cp_left > 1) {
|
||||
if (strlen(cp) != 0)
|
||||
warn(" %s", cp);
|
||||
cp += strlen(cp) + 1;
|
||||
cp_left -= strlen(cp) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
resp->respcode = 456; // 456 - Header Field Not Valid for Resource
|
||||
char *pssid = NULL;
|
||||
char *paesiv = NULL;
|
||||
char *prsaaeskey = NULL;
|
||||
char *pfmtp = NULL;
|
||||
@@ -1601,6 +1614,9 @@ static void handle_announce(rtsp_conn_info *conn, rtsp_message *req, rtsp_messag
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!strncmp(cp, "o=iTunes", 7))
|
||||
pssid = cp + 8;
|
||||
|
||||
if (!strncmp(cp, "a=fmtp:", 7))
|
||||
pfmtp = cp + 7;
|
||||
|
||||
@@ -1618,6 +1634,11 @@ static void handle_announce(rtsp_conn_info *conn, rtsp_message *req, rtsp_messag
|
||||
|
||||
cp = next;
|
||||
}
|
||||
|
||||
if (pssid) {
|
||||
uint32_t ssid = uatoi(pssid);
|
||||
debug(1, "Synchronisation Source Identifier: %08X,%u", ssid,ssid);
|
||||
}
|
||||
|
||||
if (pminlatency) {
|
||||
conn->minimum_latency = atoi(pminlatency);
|
||||
@@ -1719,10 +1740,11 @@ static void handle_announce(rtsp_conn_info *conn, rtsp_message *req, rtsp_messag
|
||||
|
||||
out:
|
||||
if (resp->respcode != 200 && resp->respcode != 453) {
|
||||
debug(1, "Error in handling ANNOUNCE on conversation thread %d. Unlocking the play lock.",
|
||||
debug(1, "Connection %d: Error in handling ANNOUNCE. Unlocking the play lock.",
|
||||
conn->connection_number);
|
||||
debug_mutex_lock(&playing_conn_lock, 1000000 , 3); //get it
|
||||
playing_conn = NULL;
|
||||
pthread_mutex_unlock(&play_lock);
|
||||
debug_mutex_unlock(&playing_conn_lock, 3);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1970,26 +1992,19 @@ void rtsp_conversation_thread_cleanup_function(void *arg) {
|
||||
// debug(1, "Connection %d: closing fd %d.",
|
||||
// conn->connection_number,conn->fd);
|
||||
close(conn->fd);
|
||||
usleep(1000000);
|
||||
}
|
||||
if (conn->auth_nonce) {
|
||||
free(conn->auth_nonce);
|
||||
conn->auth_nonce = NULL;
|
||||
}
|
||||
rtp_terminate(conn);
|
||||
if (playing_conn == conn) {
|
||||
debug(3, "Connection %d: Unlocking play lock.", conn->connection_number);
|
||||
playing_conn = NULL;
|
||||
pthread_mutex_unlock(&play_lock);
|
||||
}
|
||||
|
||||
|
||||
if (conn->dacp_id) {
|
||||
free(conn->dacp_id);
|
||||
conn->dacp_id = NULL;
|
||||
}
|
||||
|
||||
debug(2, "Connection %d: RTSP thread terminated.", conn->connection_number);
|
||||
conn->running = 0;
|
||||
|
||||
// remove flow control and mutexes
|
||||
int rc = pthread_cond_destroy(&conn->flowcontrol);
|
||||
if (rc)
|
||||
@@ -2001,6 +2016,16 @@ void rtsp_conversation_thread_cleanup_function(void *arg) {
|
||||
rc = pthread_mutex_destroy(&conn->flush_mutex);
|
||||
if (rc)
|
||||
debug(1, "Connection %d: error %d destroying flush_mutex.", conn->connection_number, rc);
|
||||
|
||||
debug_mutex_lock(&playing_conn_lock, 1000000 , 3); //get it
|
||||
if (playing_conn == conn) {
|
||||
debug(1, "Connection %d: Unlocking play lock.", conn->connection_number);
|
||||
playing_conn = NULL;
|
||||
}
|
||||
debug_mutex_unlock(&playing_conn_lock, 3);
|
||||
|
||||
debug(2, "Connection %d: RTSP thread terminated.", conn->connection_number);
|
||||
conn->running = 0;
|
||||
}
|
||||
|
||||
void msg_cleanup_function(void *arg) {
|
||||
@@ -2109,6 +2134,8 @@ static void *rtsp_conversation_thread_func(void *pconn) {
|
||||
int err = msg_write_response(conn->fd, resp);
|
||||
if (err) {
|
||||
debug(1, "Connection %d: Unable to write an RTSP message response. Terminating the connection.", conn->connection_number);
|
||||
if (debuglev != 0)
|
||||
debuglev = 3; // see what happens next
|
||||
conn->stop = 1;
|
||||
}
|
||||
}
|
||||
@@ -2122,9 +2149,11 @@ static void *rtsp_conversation_thread_func(void *pconn) {
|
||||
(reply == rtsp_read_request_response_read_error)) {
|
||||
if (conn->player_thread) {
|
||||
rtsp_read_request_attempt_count--;
|
||||
if (rtsp_read_request_attempt_count == 0)
|
||||
if (rtsp_read_request_attempt_count == 0) {
|
||||
tstop = 1;
|
||||
else {
|
||||
if ((reply == rtsp_read_request_response_read_error) && (debuglev != 0))
|
||||
debuglev = 3; // see what happens next
|
||||
} else {
|
||||
if (reply == rtsp_read_request_response_channel_closed)
|
||||
debug(2, "Connection %d: RTSP channel unexpectedly closed -- will try again %d time(s).",
|
||||
conn->connection_number, rtsp_read_request_attempt_count);
|
||||
|
||||
Reference in New Issue
Block a user