Add tentative raw PCM input facility. Clean up some messages.
This commit is contained in:
+17
-4
@@ -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)) {
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user