Add tentative raw PCM input facility. Clean up some messages.

This commit is contained in:
Mike Brady
2019-03-27 11:44:58 +00:00
4 changed files with 197 additions and 123 deletions
+17 -4
View File
@@ -1587,9 +1587,14 @@ void alsa_buffer_monitor_thread_cleanup_function(__attribute__((unused)) void
// this will return true if the DAC can return precision delay information and false if not
// if it is not yet known, it will test the output device to find out
// note -- once it has done the test, it decides -- even if the delay comes back with
// "don't know", it will take that as a "No" and remember it.
// If you want it to check again, set precision_delay_available_status to YNDK_DONT_KNOW
// first.
int precision_delay_available() {
if (precision_delay_available_status == YNDK_DONT_KNOW) {
debug(1,"alsa: precision_delay_available starting check...");
// At present, the only criterion as to whether precision delay is available
// is whether the device driver returns non-zero update timestamps
// If it does, it is considered precision delay is available
@@ -1626,9 +1631,17 @@ int precision_delay_available() {
snd_pcm_state_t state;
snd_pcm_sframes_t delay;
int ret = delay_and_status(&state, &delay, &uses_update_timestamps);
debug(1,"alsa: precision_delay_available asking for delay and status with a return status of %d, a delay of %ld and a uses_update_timestamps of %d.", ret, delay, uses_update_timestamps);
// debug(3,"alsa: precision_delay_available asking for delay and status with a return status of %d, a delay of %ld and a uses_update_timestamps of %d.", ret, delay, uses_update_timestamps);
if (ret == 0) {
precision_delay_available_status = uses_update_timestamps;
if (uses_update_timestamps == YNDK_YES) {
precision_delay_available_status = YNDK_YES;
debug(2,"alsa: precision delay timing available.");
} else {
precision_delay_available_status = YNDK_NO;
inform("Note: the alsa output device \"%s\" is not capable of precision delay timing. Could it be a virtual device?", snd_pcm_name(alsa_handle));
if (config.disable_standby_mode != disable_standby_off)
inform("Note: disable_standby_mode has been turned off because the output device is not capable of precision delay timing.");
}
}
}
}
@@ -1639,7 +1652,7 @@ void *alsa_buffer_monitor_thread_code(__attribute__((unused)) void *arg) {
int okb = -1;
while (1) {
if (okb != config.keep_dac_busy) {
debug(1,"keep_dac_busy is now \"%s\"",config.keep_dac_busy == 0 ? "no" : "yes");
debug(2,"keep_dac_busy is now \"%s\"",config.keep_dac_busy == 0 ? "no" : "yes");
okb = config.keep_dac_busy;
}
if ((config.keep_dac_busy != 0) && (alsa_device_initialised == 0)) {
+55 -54
View File
@@ -215,7 +215,46 @@ void reset_input_flow_metrics(rtsp_conn_info *conn) {
conn->initial_reference_timestamp = 0;
}
static int alac_decode(short *dest, int *destlen, uint8_t *buf, int len, rtsp_conn_info *conn) {
void unencrypted_packet_decode(unsigned char *packet, int length, short *dest, int *outsize,
int size_limit, rtsp_conn_info *conn) {
if (conn->stream.type == ast_apple_lossless) {
#ifdef CONFIG_APPLE_ALAC
if (config.use_apple_decoder) {
if (conn->decoder_in_use != 1 << decoder_apple_alac) {
debug(2, "Apple ALAC Decoder used on encrypted audio.");
conn->decoder_in_use = 1 << decoder_apple_alac;
}
apple_alac_decode_frame(packet, length, (unsigned char *)dest, outsize);
*outsize = *outsize * 4; // bring the size to bytes
} else
#endif
{
if (conn->decoder_in_use != 1 << decoder_hammerton) {
debug(2, "Hammerton Decoder used on encrypted audio.");
conn->decoder_in_use = 1 << decoder_hammerton;
}
alac_decode_frame(conn->decoder_info, packet, (unsigned char *)dest, outsize);
}
} else if (conn->stream.type == ast_uncompressed) {
int length_to_use = length;
if (length_to_use > size_limit) {
warn("unencrypted_packet_decode: uncompressed audio packet too long (size: %d bytes) to "
"process -- truncated",
length);
length_to_use = size_limit;
}
int i;
short *source = (short *)packet;
for (i = 0; i < (length_to_use / 2); i++) {
*dest = ntohs(*source);
dest++;
source++;
}
*outsize = length_to_use;
}
}
int audio_packet_decode(short *dest, int *destlen, uint8_t *buf, int len, rtsp_conn_info *conn) {
// parameters: where the decoded stuff goes, its length in samples,
// the incoming packet, the length of the incoming packet in bytes
// destlen should contain the allowed max number of samples on entry
@@ -230,7 +269,7 @@ static int alac_decode(short *dest, int *destlen, uint8_t *buf, int len, rtsp_co
assert(len <= MAX_PACKET);
int reply = 0; // everything okay
int outsize = conn->input_bytes_per_frame * (*destlen); // the size the output should be, in bytes
int toutsize = outsize;
int maximum_possible_outsize = outsize;
if (conn->stream.encrypted) {
unsigned char iv[16];
@@ -246,48 +285,16 @@ static int alac_decode(short *dest, int *destlen, uint8_t *buf, int len, rtsp_co
AES_cbc_encrypt(buf, packet, aeslen, &conn->aes, iv, AES_DECRYPT);
#endif
memcpy(packet + aeslen, buf + aeslen, len - aeslen);
#ifdef CONFIG_APPLE_ALAC
if (config.use_apple_decoder) {
if (conn->decoder_in_use != 1 << decoder_apple_alac) {
debug(2, "Apple ALAC Decoder used on encrypted audio.");
conn->decoder_in_use = 1 << decoder_apple_alac;
}
apple_alac_decode_frame(packet, len, (unsigned char *)dest, &outsize);
outsize = outsize * 4; // bring the size to bytes
} else
#endif
{
if (conn->decoder_in_use != 1 << decoder_hammerton) {
debug(2, "Hammerton Decoder used on encrypted audio.");
conn->decoder_in_use = 1 << decoder_hammerton;
}
alac_decode_frame(conn->decoder_info, packet, (unsigned char *)dest, &outsize);
}
unencrypted_packet_decode(packet, len, dest, &outsize, maximum_possible_outsize, conn);
} else {
// not encrypted
#ifdef CONFIG_APPLE_ALAC
if (config.use_apple_decoder) {
if (conn->decoder_in_use != 1 << decoder_apple_alac) {
debug(2, "Apple ALAC Decoder used on unencrypted audio.");
conn->decoder_in_use = 1 << decoder_apple_alac;
}
apple_alac_decode_frame(buf, len, (unsigned char *)dest, &outsize);
outsize = outsize * 4; // bring the size to bytes
} else
#endif
{
if (conn->decoder_in_use != 1 << decoder_hammerton) {
debug(2, "Hammerton Decoder used on unencrypted audio.");
conn->decoder_in_use = 1 << decoder_hammerton;
}
alac_decode_frame(conn->decoder_info, buf, dest, &outsize);
}
// not encrypted
unencrypted_packet_decode(buf, len, dest, &outsize, maximum_possible_outsize, conn);
}
if (outsize > toutsize) {
if (outsize > maximum_possible_outsize) {
debug(2, "Output from alac_decode larger (%d bytes, not frames) than expected (%d bytes) -- "
"truncated, but buffer overflow possible! Encrypted = %d.",
outsize, toutsize, conn->stream.encrypted);
outsize, maximum_possible_outsize, conn->stream.encrypted);
reply = -1; // output packet is the wrong size
}
@@ -299,7 +306,7 @@ static int alac_decode(short *dest, int *destlen, uint8_t *buf, int len, rtsp_co
return reply;
}
static int init_decoder(int32_t fmtp[12], rtsp_conn_info *conn) {
static int init_alac_decoder(int32_t fmtp[12], rtsp_conn_info *conn) {
// This is a guess, but the format of the fmtp looks identical to the format of an
// ALACSpecificCOnfig
@@ -380,14 +387,6 @@ static int init_decoder(int32_t fmtp[12], rtsp_conn_info *conn) {
alac_file *alac;
conn->max_frames_per_packet = fmtp[1]; // number of audio frames per packet.
conn->input_rate = fmtp[11];
conn->input_num_channels = fmtp[7];
conn->input_bit_depth = fmtp[3];
conn->input_bytes_per_frame = conn->input_num_channels * ((conn->input_bit_depth + 7) / 8);
alac = alac_create(conn->input_bit_depth,
conn->input_num_channels); // no pthread cancellation point in here
if (!alac)
@@ -555,7 +554,7 @@ void player_put_packet(seq_t seqno, uint32_t actual_timestamp, uint8_t *data, in
if (abuf) {
int datalen = conn->max_frames_per_packet;
if (alac_decode(abuf->data, &datalen, data, len, conn) == 0) {
if (audio_packet_decode(abuf->data, &datalen, data, len, conn) == 0) {
abuf->ready = 1;
abuf->length = datalen;
// abuf->timestamp = ltimestamp;
@@ -1485,7 +1484,8 @@ void player_thread_cleanup_handler(void *arg) {
conn->tbuf = NULL;
}
free_audio_buffers(conn);
terminate_decoders(conn);
if (conn->stream.type == ast_apple_lossless)
terminate_decoders(conn);
clear_reference_timestamp(conn);
conn->rtp_running = 0;
@@ -1512,10 +1512,11 @@ void *player_thread_func(void *arg) {
conn->latency = 88200;
}
init_decoder((int32_t *)&conn->stream.fmtp,
conn); // this sets up incoming rate, bit depth, channels.
// No pthread cancellation point in here
// This must be after init_decoder
if (conn->stream.type == ast_apple_lossless)
init_alac_decoder((int32_t *)&conn->stream.fmtp,
conn); // this sets up incoming rate, bit depth, channels.
// No pthread cancellation point in here
// This must be after init_alac_decoder
init_buffer(conn); // will need a corresponding deallocation. No cancellation points in here
if (conn->stream.encrypted) {
+8 -1
View File
@@ -48,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.
@@ -61,10 +61,17 @@ 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 {
+117 -64
View File
@@ -51,8 +51,8 @@
#endif
#ifdef CONFIG_MBEDTLS
#include <mbedtls/version.h>
#include <mbedtls/md5.h>
#include <mbedtls/version.h>
#endif
#ifdef CONFIG_POLARSSL
@@ -292,9 +292,8 @@ void *player_watchdog_thread_code(void *arg) {
conn->watchdog_barks++;
if (conn->watchdog_barks == 1) {
// debuglev = 3; // tell us everything.
debug(1,
"Connection %d: As Yeats almost said, \"Too long a silence / can make a stone "
"of the heart\".",
debug(1, "Connection %d: As Yeats almost said, \"Too long a silence / can make a stone "
"of the heart\".",
conn->connection_number);
conn->stop = 1;
pthread_cancel(conn->thread);
@@ -580,12 +579,12 @@ enum rtsp_read_request_response rtsp_read_request(rtsp_conn_info *conn, rtsp_mes
enum rtsp_read_request_response reply = rtsp_read_request_response_ok;
ssize_t buflen = 4096;
int release_buffer = 0; // on exit, don't deallocate the buffer if everything was okay
int release_buffer = 0; // on exit, don't deallocate the buffer if everything was okay
char *buf = malloc(buflen + 1); // add a NUL at the end
if (!buf) {
warn("rtsp_read_request: can't get a buffer.");
return(rtsp_read_request_response_error);
}
return (rtsp_read_request_response_error);
}
pthread_cleanup_push(malloc_cleanup, buf);
ssize_t nread;
ssize_t inbuf = 0;
@@ -619,6 +618,10 @@ do {
if (nread < 0) {
if (errno == EINTR)
continue;
if (errno == EAGAIN) {
debug(1, "Getting Error 11 -- EAGAIN from a blocking read!");
continue;
}
if (errno != ECONNRESET) {
char errorstring[1024];
strerror_r(errno, (char *)errorstring, sizeof(errorstring));
@@ -787,7 +790,8 @@ int msg_write_response(int fd, rtsp_message *resp) {
return -4;
}
if (reply != p - pkt) {
debug(1, "msg_write_response error -- requested bytes: %d not fully written: %d.",p - pkt, reply);
debug(1, "msg_write_response error -- requested bytes: %d not fully written: %d.", p - pkt,
reply);
return -5;
}
return 0;
@@ -842,10 +846,9 @@ void handle_options(rtsp_conn_info *conn, __attribute__((unused)) rtsp_message *
rtsp_message *resp) {
debug(3, "Connection %d: OPTIONS", conn->connection_number);
resp->respcode = 200;
msg_add_header(resp, "Public",
"ANNOUNCE, SETUP, RECORD, "
"PAUSE, FLUSH, TEARDOWN, "
"OPTIONS, GET_PARAMETER, SET_PARAMETER");
msg_add_header(resp, "Public", "ANNOUNCE, SETUP, RECORD, "
"PAUSE, FLUSH, TEARDOWN, "
"OPTIONS, GET_PARAMETER, SET_PARAMETER");
}
void handle_teardown(rtsp_conn_info *conn, __attribute__((unused)) rtsp_message *req,
@@ -986,10 +989,10 @@ void handle_setup(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *resp) {
msg_add_header(resp, "Session", "1");
resp->respcode = 200; // it all worked out okay
debug(1, "Connection %d: SETUP DACP-ID \"%s\" from %s to %s with UDP ports Control: %d, Timing: %d and Audio: %d.",
conn->connection_number,
conn->dacp_id, &conn->client_ip_string, &conn->self_ip_string,
conn->local_control_port, conn->local_timing_port,
debug(1, "Connection %d: SETUP DACP-ID \"%s\" from %s to %s with UDP ports Control: "
"%d, Timing: %d and Audio: %d.",
conn->connection_number, conn->dacp_id, &conn->client_ip_string,
&conn->self_ip_string, conn->local_control_port, conn->local_timing_port,
conn->local_audio_port);
} else {
@@ -1582,7 +1585,7 @@ static void handle_set_parameter(rtsp_conn_info *conn, rtsp_message *req, rtsp_m
char *ct = msg_get_header(req, "Content-Type");
if (ct) {
// debug(2, "SET_PARAMETER Content-Type:\"%s\".", ct);
// debug(2, "SET_PARAMETER Content-Type:\"%s\".", ct);
#ifdef CONFIG_METADATA
// It seems that the rtptime of the message is used as a kind of an ID that
@@ -1741,6 +1744,7 @@ static void handle_announce(rtsp_conn_info *conn, rtsp_message *req, rtsp_messag
}
*/
conn->stream.type = ast_unknown;
resp->respcode = 456; // 456 - Header Field Not Valid for Resource
char *pssid = NULL;
char *paesiv = NULL;
@@ -1748,6 +1752,8 @@ static void handle_announce(rtsp_conn_info *conn, rtsp_message *req, rtsp_messag
char *pfmtp = NULL;
char *pminlatency = NULL;
char *pmaxlatency = NULL;
// char *pAudioMediaInfo = NULL;
char *pUncompressedCDAudio = NULL;
char *cp = req->content;
int cp_left = req->contentlength;
char *next;
@@ -1755,27 +1761,62 @@ static void handle_announce(rtsp_conn_info *conn, rtsp_message *req, rtsp_messag
next = nextline(cp, cp_left);
cp_left -= next - cp;
if (!strncmp(cp, "o=iTunes", 7))
pssid = cp + 8;
if (!strncmp(cp, "a=rtpmap:96 L16/44100/2", strlen("a=rtpmap:96 L16/44100/2")))
pUncompressedCDAudio = cp + strlen("a=rtpmap:96 L16/44100/2");
if (!strncmp(cp, "a=fmtp:", 7))
pfmtp = cp + 7;
// if (!strncmp(cp, "m=audio", strlen("m=audio")))
// pAudioMediaInfo = cp + strlen("m=audio");
if (!strncmp(cp, "a=aesiv:", 8))
paesiv = cp + 8;
if (!strncmp(cp, "o=iTunes", strlen("o=iTunes")))
pssid = cp + strlen("o=iTunes");
if (!strncmp(cp, "a=rsaaeskey:", 12))
prsaaeskey = cp + 12;
if (!strncmp(cp, "a=fmtp:", strlen("a=fmtp:")))
pfmtp = cp + strlen("a=fmtp:");
if (!strncmp(cp, "a=min-latency:", 14))
pminlatency = cp + 14;
if (!strncmp(cp, "a=aesiv:", strlen("a=aesiv:")))
paesiv = cp + strlen("a=aesiv:");
if (!strncmp(cp, "a=max-latency:", 14))
pmaxlatency = cp + 14;
if (!strncmp(cp, "a=rsaaeskey:", strlen("a=rsaaeskey:")))
prsaaeskey = cp + strlen("a=rsaaeskey:");
if (!strncmp(cp, "a=min-latency:", strlen("a=min-latency:")))
pminlatency = cp + strlen("a=min-latency:");
if (!strncmp(cp, "a=max-latency:", strlen("a=max-latency:")))
pmaxlatency = cp + strlen("a=max-latency:");
cp = next;
}
if (pUncompressedCDAudio) {
debug(1, "An uncompressed PCM stream has been detected.");
conn->stream.type = ast_uncompressed;
conn->max_frames_per_packet = 352; // number of audio frames per packet.
conn->input_rate = 44100;
conn->input_num_channels = 2;
conn->input_bit_depth = 16;
conn->input_bytes_per_frame = conn->input_num_channels * ((conn->input_bit_depth + 7) / 8);
/*
int y = strlen(pAudioMediaInfo);
if (y > 0) {
char obf[4096];
if (y > 4096)
y = 4096;
char *p = pAudioMediaInfo;
char *obfp = obf;
int obfc;
for (obfc = 0; obfc < y; obfc++) {
snprintf(obfp, 3, "%02X", (unsigned int)*p);
p++;
obfp += 2;
};
*obfp = 0;
debug(1, "AudioMediaInfo: \"%s\".", obf);
}
*/
}
if (pssid) {
uint32_t ssid = uatoi(pssid);
debug(3, "Synchronisation Source Identifier: %08X,%u", ssid, ssid);
@@ -1799,22 +1840,6 @@ static void handle_announce(rtsp_conn_info *conn, rtsp_message *req, rtsp_messag
// debug(1,"Encrypted session requested");
}
if (!pfmtp) {
warn("FMTP params missing from the following ANNOUNCE message:");
// print each line of the request content
// the problem is that nextline has replace all returns, newlines, etc. by
// NULLs
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;
}
goto out;
}
if (conn->stream.encrypted) {
int len, keylen;
uint8_t *aesiv = base64_dec(paesiv, &len);
@@ -1837,12 +1862,41 @@ static void handle_announce(rtsp_conn_info *conn, rtsp_message *req, rtsp_messag
memcpy(conn->stream.aeskey, aeskey, 16);
free(aeskey);
}
unsigned int i;
for (i = 0; i < sizeof(conn->stream.fmtp) / sizeof(conn->stream.fmtp[0]); i++)
conn->stream.fmtp[i] = atoi(strsep(&pfmtp, " \t"));
// here we should check the sanity ot the fmtp values
// for (i = 0; i < sizeof(conn->stream.fmtp) / sizeof(conn->stream.fmtp[0]); i++)
// debug(1," fmtp[%2d] is: %10d",i,conn->stream.fmtp[i]);
if (pfmtp) {
conn->stream.type = ast_apple_lossless;
debug(1, "An ALAC stream has been detected.");
unsigned int i;
for (i = 0; i < sizeof(conn->stream.fmtp) / sizeof(conn->stream.fmtp[0]); i++)
conn->stream.fmtp[i] = atoi(strsep(&pfmtp, " \t"));
// here we should check the sanity ot the fmtp values
// for (i = 0; i < sizeof(conn->stream.fmtp) / sizeof(conn->stream.fmtp[0]); i++)
// debug(1," fmtp[%2d] is: %10d",i,conn->stream.fmtp[i]);
// set the parameters of the player (as distinct from the parameters of the decoder -- that's
// done later).
conn->max_frames_per_packet = conn->stream.fmtp[1]; // number of audio frames per packet.
conn->input_rate = conn->stream.fmtp[11];
conn->input_num_channels = conn->stream.fmtp[7];
conn->input_bit_depth = conn->stream.fmtp[3];
conn->input_bytes_per_frame = conn->input_num_channels * ((conn->input_bit_depth + 7) / 8);
}
if (conn->stream.type == ast_unknown) {
warn("Can not process the following ANNOUNCE message:");
// print each line of the request content
// the problem is that nextline has replace all returns, newlines, etc. by
// NULLs
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;
}
goto out;
}
char *hdr = msg_get_header(req, "X-Apple-Client-Name");
if (hdr) {
@@ -2038,7 +2092,7 @@ static int rtsp_auth(char **nonce, rtsp_message *req, rtsp_message *resp) {
#endif
#ifdef CONFIG_MBEDTLS
#if MBEDTLS_VERSION_MINOR >= 7
#if MBEDTLS_VERSION_MINOR >= 7
mbedtls_md5_context tctx;
mbedtls_md5_starts_ret(&tctx);
mbedtls_md5_update_ret(&tctx, (const unsigned char *)username, strlen(username));
@@ -2052,7 +2106,7 @@ static int rtsp_auth(char **nonce, rtsp_message *req, rtsp_message *resp) {
mbedtls_md5_update_ret(&tctx, (unsigned char *)":", 1);
mbedtls_md5_update_ret(&tctx, (const unsigned char *)uri, strlen(uri));
mbedtls_md5_finish_ret(&tctx, digest_mu);
#else
#else
mbedtls_md5_context tctx;
mbedtls_md5_starts(&tctx);
mbedtls_md5_update(&tctx, (const unsigned char *)username, strlen(username));
@@ -2066,7 +2120,7 @@ static int rtsp_auth(char **nonce, rtsp_message *req, rtsp_message *resp) {
mbedtls_md5_update(&tctx, (unsigned char *)":", 1);
mbedtls_md5_update(&tctx, (const unsigned char *)uri, strlen(uri));
mbedtls_md5_finish(&tctx, digest_mu);
#endif
#endif
#endif
#ifdef CONFIG_POLARSSL
@@ -2105,7 +2159,7 @@ static int rtsp_auth(char **nonce, rtsp_message *req, rtsp_message *resp) {
#endif
#ifdef CONFIG_MBEDTLS
#if MBEDTLS_VERSION_MINOR >= 7
#if MBEDTLS_VERSION_MINOR >= 7
mbedtls_md5_starts_ret(&tctx);
mbedtls_md5_update_ret(&tctx, buf, 32);
mbedtls_md5_update_ret(&tctx, (unsigned char *)":", 1);
@@ -2115,7 +2169,7 @@ static int rtsp_auth(char **nonce, rtsp_message *req, rtsp_message *resp) {
snprintf((char *)buf + 2 * i, 3, "%02x", digest_mu[i]);
mbedtls_md5_update_ret(&tctx, buf, 32);
mbedtls_md5_finish_ret(&tctx, digest_total);
#else
#else
mbedtls_md5_starts(&tctx);
mbedtls_md5_update(&tctx, buf, 32);
mbedtls_md5_update(&tctx, (unsigned char *)":", 1);
@@ -2125,7 +2179,7 @@ static int rtsp_auth(char **nonce, rtsp_message *req, rtsp_message *resp) {
snprintf((char *)buf + 2 * i, 3, "%02x", digest_mu[i]);
mbedtls_md5_update(&tctx, buf, 32);
mbedtls_md5_finish(&tctx, digest_total);
#endif
#endif
#endif
#ifdef CONFIG_POLARSSL
@@ -2194,7 +2248,8 @@ void rtsp_conversation_thread_cleanup_function(void *arg) {
// remove flow control and mutexes
int rc = pthread_mutex_destroy(&conn->volume_control_mutex);
if (rc)
debug(1, "Connection %d: error %d destroying volume_control_mutex.", conn->connection_number, rc);
debug(1, "Connection %d: error %d destroying volume_control_mutex.", conn->connection_number,
rc);
rc = pthread_cond_destroy(&conn->flowcontrol);
if (rc)
debug(1, "Connection %d: error %d destroying flow control condition variable.",
@@ -2285,9 +2340,8 @@ static void *rtsp_conversation_thread_func(void *pconn) {
if (strcmp(req->method, "OPTIONS") !=
0) // the options message is very common, so don't log it until level 3
debug_level = 2;
debug(debug_level,
"Connection %d: Received an RTSP Packet of type \"%s\":", conn->connection_number,
req->method),
debug(debug_level, "Connection %d: Received an RTSP Packet of type \"%s\":",
conn->connection_number, req->method),
debug_print_msg_headers(debug_level, req);
apple_challenge(conn->fd, req, resp);
@@ -2346,9 +2400,8 @@ static void *rtsp_conversation_thread_func(void *pconn) {
if (conn->stop == 0) {
int err = msg_write_response(conn->fd, resp);
if (err) {
debug(1,
"Connection %d: Unable to write an RTSP message response. Terminating the "
"connection.",
debug(1, "Connection %d: Unable to write an RTSP message response. Terminating the "
"connection.",
conn->connection_number);
struct linger so_linger;
so_linger.l_onoff = 1; // "true"