Working to check for divide / mod by 0's

This commit is contained in:
Mike Brady
2021-11-17 10:35:21 +00:00
parent 4729b3ea71
commit c0a3dacf30
10 changed files with 221 additions and 214 deletions
+2 -2
View File
@@ -169,11 +169,11 @@ void *activity_monitor_thread_code(void *arg) {
do {
switch (state) {
case am_inactive:
debug(2,"am_state: am_inactive");
debug(2, "am_state: am_inactive");
while (player_state != ps_active)
pthread_cond_wait(&activity_monitor_cv, &activity_monitor_mutex);
state = am_active;
debug(2,"am_state: going active");
debug(2, "am_state: going active");
break;
case am_active:
// debug(1,"am_state: am_active");
+35 -28
View File
@@ -60,7 +60,8 @@ static int play(void *buf, int samples);
static void stop(void);
static void flush(void);
int delay(long *the_delay);
int get_frames_sent_for_output(__attribute__ ((unused)) uint64_t *elapsed_time, uint64_t *frames_sent_to_dac);
int get_frames_sent_for_output(__attribute__((unused)) uint64_t *elapsed_time,
uint64_t *frames_sent_to_dac);
// int get_rate_information(uint64_t *elapsed_time, uint64_t *frames_played);
void *alsa_buffer_monitor_thread_code(void *arg);
@@ -89,8 +90,9 @@ audio_output audio_alsa = {
.flush = &flush,
.delay = &delay,
.play = &play,
.rate_info = &get_frames_sent_for_output, // will also include frames of silence sent to stop standby mode
// .rate_info = NULL,
.rate_info = &get_frames_sent_for_output, // will also include frames of silence sent to stop
// standby mode
// .rate_info = NULL,
.mute = NULL, // a function will be provided if it can, and is allowed to,
// do hardware mute
.volume = NULL, // a function will be provided if it can do hardware volume
@@ -247,7 +249,8 @@ static snd_pcm_uframes_t period_size_requested, buffer_size_requested;
static int set_period_size_request, set_buffer_size_request;
static uint64_t frames_sent_for_playing;
static int output_error_occurred; // set to true if an underrun or similar has occurred since last requested
static int output_error_occurred; // set to true if an underrun or similar has occurred since last
// requested
static void help(void) {
printf(" -d output-device set the output device, default is \"default\".\n"
@@ -432,7 +435,7 @@ int actual_open_alsa_device(int do_auto_setup) {
char errorstring[1024];
strerror_r(-ret, (char *)errorstring, sizeof(errorstring));
die("alsa: error %d (\"%s\") opening alsa device \"%s\".", ret, (char *)errorstring,
alsa_out_dev);
alsa_out_dev);
}
return ret;
}
@@ -469,14 +472,14 @@ int actual_open_alsa_device(int do_auto_setup) {
ret = snd_pcm_hw_params_set_access(alsa_handle, alsa_params, access);
if (ret < 0) {
die("audio_alsa: Access type not available for device \"%s\": %s", alsa_out_dev,
snd_strerror(ret));
snd_strerror(ret));
return ret;
}
ret = snd_pcm_hw_params_set_channels(alsa_handle, alsa_params, 2);
if (ret < 0) {
die("audio_alsa: Channels count (2) not available for device \"%s\": %s", alsa_out_dev,
snd_strerror(ret));
snd_strerror(ret));
return ret;
}
@@ -522,7 +525,7 @@ int actual_open_alsa_device(int do_auto_setup) {
sps_format_description_string(config.output_format));
} else {
die("audio_alsa: Could not automatically set the output format for device \"%s\": %s",
alsa_out_dev, snd_strerror(ret));
alsa_out_dev, snd_strerror(ret));
return ret;
}
}
@@ -532,8 +535,8 @@ int actual_open_alsa_device(int do_auto_setup) {
config.output_rate; // this is the requested rate -- it'll be changed to the actual rate
ret = snd_pcm_hw_params_set_rate_near(alsa_handle, alsa_params, &actual_sample_rate, &dir);
if (ret < 0) {
die("audio_alsa: The frame rate of %i frames per second is not available for playback: %s", config.output_rate,
snd_strerror(ret));
die("audio_alsa: The frame rate of %i frames per second is not available for playback: %s",
config.output_rate, snd_strerror(ret));
return ret;
}
} else {
@@ -552,7 +555,9 @@ int actual_open_alsa_device(int do_auto_setup) {
if (ret == 0) {
speed_found = 1;
if (actual_sample_rate != speeds[i])
die("The output DAC can not be set to %d frames per second (fps). The nearest speed available is %d fps.", speeds[i], actual_sample_rate);
die("The output DAC can not be set to %d frames per second (fps). The nearest speed "
"available is %d fps.",
speeds[i], actual_sample_rate);
} else {
i++;
}
@@ -562,7 +567,7 @@ int actual_open_alsa_device(int do_auto_setup) {
debug(1, "alsa: output speed chosen is %d.", config.output_rate);
} else {
die("audio_alsa: Could not automatically set the output rate for device \"%s\": %s",
alsa_out_dev, snd_strerror(ret));
alsa_out_dev, snd_strerror(ret));
return ret;
}
}
@@ -607,7 +612,7 @@ int actual_open_alsa_device(int do_auto_setup) {
ret = snd_pcm_hw_params(alsa_handle, alsa_params);
if (ret < 0) {
die("audio_alsa: Unable to set hw parameters for device \"%s\": %s.", alsa_out_dev,
snd_strerror(ret));
snd_strerror(ret));
return ret;
}
@@ -774,10 +779,11 @@ int actual_open_alsa_device(int do_auto_setup) {
break;
}
if (snd_pcm_hw_params_get_rate_numden(alsa_params, &uval, &uval2) == 0)
if ((snd_pcm_hw_params_get_rate_numden(alsa_params, &uval, &uval2) == 0) && (uval2 != 0))
// watch for a divide by zero too!
debug(log_level, " precise (rational) rate = %.3f frames per second (i.e. %u/%u).", uval,
uval2, ((double)uval) / uval2);
else
uval2, ((double)uval) / uval2);
else
debug(log_level, " precise (rational) rate information unavailable.");
snd_pcm_hw_params_get_period_time(alsa_params, &uval, &dir);
@@ -1283,16 +1289,16 @@ static int init(int argc, char **argv) {
warn("Invalid use_precision_timing option choice \"%s\". It should be "
"\"yes\", \"auto\" or \"no\". "
"It remains set to \"%s\".",
config.use_precision_timing == YNA_NO
? "no"
: config.use_precision_timing == YNA_AUTO ? "auto" : "yes");
config.use_precision_timing == YNA_NO ? "no"
: config.use_precision_timing == YNA_AUTO ? "auto"
: "yes");
}
}
debug(1, "alsa: disable_standby_mode is \"%s\".",
config.disable_standby_mode == disable_standby_off
? "never"
: config.disable_standby_mode == disable_standby_always ? "always" : "auto");
config.disable_standby_mode == disable_standby_off ? "never"
: config.disable_standby_mode == disable_standby_always ? "always"
: "auto");
debug(1, "alsa: disable_standby_mode_silence_threshold is %f seconds.",
config.disable_standby_mode_silence_threshold);
debug(1, "alsa: disable_standby_mode_silence_scan_interval is %f seconds.",
@@ -1624,18 +1630,19 @@ int delay(long *the_delay) {
return ret;
}
int get_frames_sent_for_output(__attribute__ ((unused)) uint64_t *elapsed_time, uint64_t *frames_sent_to_dac) {
int get_frames_sent_for_output(__attribute__((unused)) uint64_t *elapsed_time,
uint64_t *frames_sent_to_dac) {
int ret = 0;
pthread_cleanup_debug_mutex_lock(&alsa_mutex, 10000, 0);
*frames_sent_to_dac = frames_sent_for_playing;
if (alsa_handle == NULL)
ret = ENODEV;
else
else
ret = output_error_occurred; // will be zero unless an error occurred
output_error_occurred = 0; // reset it.
output_error_occurred = 0; // reset it.
debug_mutex_unlock(&alsa_mutex, 0);
pthread_cleanup_pop(0);
return ret;
return ret;
}
/*
@@ -1682,8 +1689,8 @@ int do_play(void *buf, int samples) {
stall_monitor_frame_count += samples;
frames_sent_for_playing += samples;
} else {
output_error_occurred = -ret; // note than an output error has occurred
if (ret == -EPIPE) { /* underrun */
output_error_occurred = -ret; // note than an output error has occurred
if (ret == -EPIPE) { /* underrun */
// It could be that the DAC was in the SND_PCM_STATE_XRUN state before
// sending the samples to be output. If so, it will still be in
+127 -141
View File
@@ -29,8 +29,8 @@
#include <pipewire/pipewire.h>
#include <pipewire/stream.h>
#include <spa/param/audio/layout.h>
#include <spa/param/audio/format-utils.h>
#include <spa/param/audio/layout.h>
#include <spa/utils/result.h>
#include <math.h>
@@ -61,26 +61,26 @@ struct pw_data {
} data;
static void on_core_info(__attribute__((unused)) void *userdata, const struct pw_core_info *info)
{
debug(1, "pw: remote %"PRIu32" is named \"%s\"", info->id, info->name);
static void on_core_info(__attribute__((unused)) void *userdata, const struct pw_core_info *info) {
debug(1, "pw: remote %" PRIu32 " is named \"%s\"", info->id, info->name);
}
static void on_core_error(__attribute__((unused)) void *userdata, uint32_t id, int seq, int res, const char *message)
{
warn("pw: remote error: id=%"PRIu32" seq:%d res:%d (%s): %s", id, seq, res, spa_strerror(res), message);
static void on_core_error(__attribute__((unused)) void *userdata, uint32_t id, int seq, int res,
const char *message) {
warn("pw: remote error: id=%" PRIu32 " seq:%d res:%d (%s): %s", id, seq, res, spa_strerror(res),
message);
}
static const struct pw_core_events core_events = {
PW_VERSION_CORE_EVENTS,
.info = on_core_info,
.error = on_core_error,
PW_VERSION_CORE_EVENTS,
.info = on_core_info,
.error = on_core_error,
};
static void registry_event_global(__attribute__((unused)) void *userdata, uint32_t id,
__attribute__((unused)) uint32_t permissions, const char *type, __attribute__((unused)) uint32_t version,
const struct spa_dict *props)
{
static void registry_event_global(__attribute__((unused)) void *userdata, uint32_t id,
__attribute__((unused)) uint32_t permissions, const char *type,
__attribute__((unused)) uint32_t version,
const struct spa_dict *props) {
const struct spa_dict_item *item;
const char *name, *media_class;
@@ -91,49 +91,47 @@ static void registry_event_global(__attribute__((unused)) void *userdata, uint3
if (!name || !media_class)
return;
debug(1, "pw: registry: id=%"PRIu32" type=%s name=\"%s\" media_class=\"%s\"", id, type, name, media_class);
debug(1, "pw: registry: id=%" PRIu32 " type=%s name=\"%s\" media_class=\"%s\"", id, type, name,
media_class);
spa_dict_for_each(item, props) {
debug(1, "pw: \t\t%s = \"%s\"", item->key, item->value);
}
spa_dict_for_each(item, props) { debug(1, "pw: \t\t%s = \"%s\"", item->key, item->value); }
}
}
static void registry_event_global_remove(__attribute__((unused)) void *userdata, uint32_t id)
{
debug(1, "pw: registry: remove id=%"PRIu32"", id);
static void registry_event_global_remove(__attribute__((unused)) void *userdata, uint32_t id) {
debug(1, "pw: registry: remove id=%" PRIu32 "", id);
}
static const struct pw_registry_events registry_events = {
PW_VERSION_REGISTRY_EVENTS,
.global = registry_event_global,
.global_remove = registry_event_global_remove,
PW_VERSION_REGISTRY_EVENTS,
.global = registry_event_global,
.global_remove = registry_event_global_remove,
};
static void on_state_changed(void *userdata, enum pw_stream_state old, enum pw_stream_state state, const char *error)
{
static void on_state_changed(void *userdata, enum pw_stream_state old, enum pw_stream_state state,
const char *error) {
struct pw_data *pipewire = userdata;
debug(1, "pw: stream state changed %s -> %s", pw_stream_state_as_string(old), pw_stream_state_as_string(state));
debug(1, "pw: stream state changed %s -> %s", pw_stream_state_as_string(old),
pw_stream_state_as_string(state));
if (state == PW_STREAM_STATE_STREAMING)
debug(1, "pw: stream node %"PRIu32"", pw_stream_get_node_id(pipewire->stream));
debug(1, "pw: stream node %" PRIu32 "", pw_stream_get_node_id(pipewire->stream));
if (state == PW_STREAM_STATE_ERROR)
debug(1, "pw: stream node %"PRIu32" error: %s", pw_stream_get_node_id(pipewire->stream), error);
debug(1, "pw: stream node %" PRIu32 " error: %s", pw_stream_get_node_id(pipewire->stream),
error);
pw_thread_loop_signal(pipewire->mainloop, 0);
}
static void on_process(void *userdata)
{
static void on_process(void *userdata) {
struct pw_data *pipewire = userdata;
pw_thread_loop_signal(pipewire->mainloop, 0);
}
static void on_drained(void *userdata)
{
static void on_drained(void *userdata) {
struct pw_data *pipewire = userdata;
pw_stream_set_active(pipewire->stream, false);
@@ -142,10 +140,10 @@ static void on_drained(void *userdata)
}
static const struct pw_stream_events stream_events = {
PW_VERSION_STREAM_EVENTS,
.state_changed = on_state_changed,
.process = on_process,
.drained = on_drained,
PW_VERSION_STREAM_EVENTS,
.state_changed = on_state_changed,
.process = on_process,
.drained = on_drained,
};
static void deinit() {
@@ -157,7 +155,7 @@ static void deinit() {
}
if (data.registry) {
pw_proxy_destroy((struct pw_proxy*)data.registry);
pw_proxy_destroy((struct pw_proxy *)data.registry);
data.registry = NULL;
}
@@ -182,10 +180,10 @@ static void deinit() {
}
}
static int init(__attribute__((unused)) int argc, __attribute__((unused)) char** argv) {
static int init(__attribute__((unused)) int argc, __attribute__((unused)) char **argv) {
struct pw_loop *loop;
struct pw_properties* props;
struct pw_properties *props;
// set up default values first
config.audio_backend_buffer_desired_length = 0.35;
@@ -197,13 +195,9 @@ static int init(__attribute__((unused)) int argc, __attribute__((unused)) char**
debug(1, "pw: compiled with libpipewire %s", pw_get_headers_version());
debug(1, "pw: linked with libpipewire: %s", pw_get_library_version());
data.props = pw_properties_new(
PW_KEY_MEDIA_TYPE, "Audio",
PW_KEY_MEDIA_CATEGORY, "Playback",
PW_KEY_MEDIA_ROLE, "Music",
PW_KEY_APP_NAME, "shairport-sync",
PW_KEY_NODE_NAME, "shairport-sync",
NULL);
data.props = pw_properties_new(PW_KEY_MEDIA_TYPE, "Audio", PW_KEY_MEDIA_CATEGORY, "Playback",
PW_KEY_MEDIA_ROLE, "Music", PW_KEY_APP_NAME, "shairport-sync",
PW_KEY_NODE_NAME, "shairport-sync", NULL);
if (!data.props) {
deinit();
@@ -268,77 +262,75 @@ static int init(__attribute__((unused)) int argc, __attribute__((unused)) char**
static enum spa_audio_format sps_format_to_spa_format(sps_format_t sps_format) {
switch (sps_format) {
case SPS_FORMAT_S8:
return SPA_AUDIO_FORMAT_S8;
case SPS_FORMAT_U8:
return SPA_AUDIO_FORMAT_U8;
case SPS_FORMAT_S16:
return SPA_AUDIO_FORMAT_S16;
case SPS_FORMAT_S16_LE:
return SPA_AUDIO_FORMAT_S16_LE;
case SPS_FORMAT_S16_BE:
return SPA_AUDIO_FORMAT_S16_BE;
case SPS_FORMAT_S24:
return SPA_AUDIO_FORMAT_S24_32;
case SPS_FORMAT_S24_LE:
return SPA_AUDIO_FORMAT_S24_32_LE;
case SPS_FORMAT_S24_BE:
return SPA_AUDIO_FORMAT_S24_32_BE;
case SPS_FORMAT_S24_3LE:
return SPA_AUDIO_FORMAT_S24_LE;
case SPS_FORMAT_S24_3BE:
return SPA_AUDIO_FORMAT_S24_BE;
case SPS_FORMAT_S32:
return SPA_AUDIO_FORMAT_S32;
case SPS_FORMAT_S32_LE:
return SPA_AUDIO_FORMAT_S32_LE;
case SPS_FORMAT_S32_BE:
return SPA_AUDIO_FORMAT_S32_BE;
case SPS_FORMAT_S8:
return SPA_AUDIO_FORMAT_S8;
case SPS_FORMAT_U8:
return SPA_AUDIO_FORMAT_U8;
case SPS_FORMAT_S16:
return SPA_AUDIO_FORMAT_S16;
case SPS_FORMAT_S16_LE:
return SPA_AUDIO_FORMAT_S16_LE;
case SPS_FORMAT_S16_BE:
return SPA_AUDIO_FORMAT_S16_BE;
case SPS_FORMAT_S24:
return SPA_AUDIO_FORMAT_S24_32;
case SPS_FORMAT_S24_LE:
return SPA_AUDIO_FORMAT_S24_32_LE;
case SPS_FORMAT_S24_BE:
return SPA_AUDIO_FORMAT_S24_32_BE;
case SPS_FORMAT_S24_3LE:
return SPA_AUDIO_FORMAT_S24_LE;
case SPS_FORMAT_S24_3BE:
return SPA_AUDIO_FORMAT_S24_BE;
case SPS_FORMAT_S32:
return SPA_AUDIO_FORMAT_S32;
case SPS_FORMAT_S32_LE:
return SPA_AUDIO_FORMAT_S32_LE;
case SPS_FORMAT_S32_BE:
return SPA_AUDIO_FORMAT_S32_BE;
case SPS_FORMAT_UNKNOWN:
case SPS_FORMAT_AUTO:
case SPS_FORMAT_INVALID:
default:
return SPA_AUDIO_FORMAT_S16;
case SPS_FORMAT_UNKNOWN:
case SPS_FORMAT_AUTO:
case SPS_FORMAT_INVALID:
default:
return SPA_AUDIO_FORMAT_S16;
}
}
static int spa_format_samplesize(enum spa_audio_format audio_format)
{
switch(audio_format) {
case SPA_AUDIO_FORMAT_S8:
case SPA_AUDIO_FORMAT_U8:
return 1;
case SPA_AUDIO_FORMAT_S16:
return 2;
case SPA_AUDIO_FORMAT_S24:
return 3;
case SPA_AUDIO_FORMAT_S24_32:
case SPA_AUDIO_FORMAT_S32:
return 4;
default:
die("pw: unhandled spa_audio_format: %d", audio_format);
return -1;
static int spa_format_samplesize(enum spa_audio_format audio_format) {
switch (audio_format) {
case SPA_AUDIO_FORMAT_S8:
case SPA_AUDIO_FORMAT_U8:
return 1;
case SPA_AUDIO_FORMAT_S16:
return 2;
case SPA_AUDIO_FORMAT_S24:
return 3;
case SPA_AUDIO_FORMAT_S24_32:
case SPA_AUDIO_FORMAT_S32:
return 4;
default:
die("pw: unhandled spa_audio_format: %d", audio_format);
return -1;
}
}
static const char* spa_format_to_str(enum spa_audio_format audio_format)
{
switch(audio_format) {
case SPA_AUDIO_FORMAT_U8:
return "u8";
case SPA_AUDIO_FORMAT_S8:
return "s8";
case SPA_AUDIO_FORMAT_S16:
return "s16";
case SPA_AUDIO_FORMAT_S24:
case SPA_AUDIO_FORMAT_S24_32:
return "s24";
case SPA_AUDIO_FORMAT_S32:
return "s32";
default:
die("pw: unhandled spa_audio_format: %d", audio_format);
return "(invalid)";
static const char *spa_format_to_str(enum spa_audio_format audio_format) {
switch (audio_format) {
case SPA_AUDIO_FORMAT_U8:
return "u8";
case SPA_AUDIO_FORMAT_S8:
return "s8";
case SPA_AUDIO_FORMAT_S16:
return "s16";
case SPA_AUDIO_FORMAT_S24:
case SPA_AUDIO_FORMAT_S24_32:
return "s24";
case SPA_AUDIO_FORMAT_S32:
return "s32";
default:
die("pw: unhandled spa_audio_format: %d", audio_format);
return "(invalid)";
}
}
@@ -368,13 +360,11 @@ static void start(int sample_rate, int sample_format) {
debug(1, "pw: format: %s", spa_format_to_str(data.format));
debug(1, "pw: samplesize: %d", spa_format_samplesize(data.format));
debug(1, "pw: stride: %d", data.stride);
debug(1, "pw: latency: %d samples (%.3fs)", nom, (double)nom/data.rate);
if (data.rate != 0)
debug(1, "pw: latency: %d samples (%.3fs)", nom, (double)nom / data.rate);
info = SPA_AUDIO_INFO_RAW_INIT(
.flags = SPA_AUDIO_FLAG_NONE,
.format = data.format,
.rate = data.rate,
.channels = data.channels);
info = SPA_AUDIO_INFO_RAW_INIT(.flags = SPA_AUDIO_FLAG_NONE, .format = data.format,
.rate = data.rate, .channels = data.channels);
params[0] = spa_format_audio_raw_build(&pod_builder, SPA_PARAM_EnumFormat, &info);
@@ -385,15 +375,13 @@ static void start(int sample_rate, int sample_format) {
die("pw: pw_stream_new() failed: %m");
}
debug(1, "pw: connecting stream: target_id=%"PRIu32"", PW_ID_ANY);
debug(1, "pw: connecting stream: target_id=%" PRIu32 "", PW_ID_ANY);
pw_stream_add_listener(data.stream, &data.stream_listener, &stream_events, &data);
ret = pw_stream_connect(data.stream,
PW_DIRECTION_OUTPUT,
PW_ID_ANY,
PW_STREAM_FLAG_INACTIVE | PW_STREAM_FLAG_AUTOCONNECT | PW_STREAM_FLAG_MAP_BUFFERS,
params, 1);
ret = pw_stream_connect(
data.stream, PW_DIRECTION_OUTPUT, PW_ID_ANY,
PW_STREAM_FLAG_INACTIVE | PW_STREAM_FLAG_AUTOCONNECT | PW_STREAM_FLAG_MAP_BUFFERS, params, 1);
if (ret < 0) {
deinit();
@@ -408,12 +396,12 @@ static void start(int sample_rate, int sample_format) {
debug(1, "pw: stream properties:");
pstate = NULL;
while ((key = pw_properties_iterate(props, &pstate)) != NULL &&
(val = pw_properties_get(props, key)) != NULL) {
(val = pw_properties_get(props, key)) != NULL) {
debug(1, "pw: \t%s = \"%s\"", key, val);
}
}
while(1) {
while (1) {
enum pw_stream_state stream_state = pw_stream_get_state(data.stream, NULL);
if (stream_state == PW_STREAM_STATE_PAUSED)
break;
@@ -483,19 +471,17 @@ static int play(void *buf, int samples) {
return 0;
}
audio_output audio_pw = {
.name = "pw",
.help = NULL,
.init = &init,
.deinit = &deinit,
.prepare = NULL,
.start = &start,
.stop = &stop,
.is_running = NULL,
.flush = &flush,
.delay = NULL,
.play = &play,
.volume = NULL,
.parameters = NULL,
.mute = NULL
};
audio_output audio_pw = {.name = "pw",
.help = NULL,
.init = &init,
.deinit = &deinit,
.prepare = NULL,
.start = &start,
.stop = &stop,
.is_running = NULL,
.flush = &flush,
.delay = NULL,
.play = &play,
.volume = NULL,
.parameters = NULL,
.mute = NULL};
+1 -1
View File
@@ -20,7 +20,7 @@ typedef struct {
char *name;
int (*mdns_register)(char *ap1name, char *ap2name, int port, char **txt_records,
char **secondary_txt_records);
int (*mdns_update)(char **txt_records, char **secondary_txt_records);
int (*mdns_update)(char **txt_records, char **secondary_txt_records);
void (*mdns_unregister)(void);
void (*mdns_dacp_monitor_start)();
void (*mdns_dacp_monitor_set_id)(const char *);
+1 -1
View File
@@ -1732,7 +1732,7 @@ void *player_thread_func(void *arg) {
conn->flush_rtp_timestamp = 0; // it seems this number has a special significance -- it seems to
// be used as a null operand, so we'll use it like that too
conn->fix_volume = 0x10000;
#ifdef CONFIG_AIRPLAY_2
conn->ap2_flush_requested = 0;
conn->ap2_flush_from_valid = 0;
+1 -1
View File
@@ -170,7 +170,7 @@ typedef struct {
player_watchdog_thread;
// buffers to delete on exit
signed short *tbuf;
int32_t *tbuf;
int32_t *sbuf;
char *outbuf;
+2 -2
View File
@@ -33,8 +33,8 @@
#include <string.h>
#include <sys/mman.h>
#ifdef COMPILE_FOR_FREEBSD
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/socket.h>
#endif
#define __STDC_FORMAT_MACROS
#include "common.h"
@@ -86,7 +86,7 @@ int ptp_get_clock_info(uint64_t *actual_clock_id, uint64_t *time_of_sample, uint
if (actual_clock_id != NULL)
*actual_clock_id = nqptp_data.master_clock_id;
if (time_of_sample != NULL)
*time_of_sample = nqptp_data.local_time;
*time_of_sample = nqptp_data.local_time;
if (raw_offset != NULL)
*raw_offset = nqptp_data.local_to_master_time_offset;
if (mastership_start_time != NULL)
+15 -13
View File
@@ -290,8 +290,8 @@ void *rtp_control_receiver(void *arg) {
obfp += 2;
};
*obfp = 0;
// get raw timestamp information
// I think that a good way to understand these timestamps is that
// (1) the rtlt below is the timestamp of the frame that should be playing at the
@@ -302,19 +302,19 @@ void *rtp_control_receiver(void *arg) {
// Thus, (3) the latency can be calculated by subtracting the second from the
// first.
// There must be more to it -- there something missing.
// In addition, it seems that if the value of the short represented by the second
// pair of bytes in the packet is 7
// then an extra time lag is expected to be added, presumably by
// the AirPort Express.
// 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 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 "
@@ -1564,7 +1564,8 @@ void rtp_ap2_control_handler_cleanup_handler(void *arg) {
rtsp_conn_info *conn = (rtsp_conn_info *)arg;
debug(2, "Connection %d: AP2 Control Receiver Cleanup.", conn->connection_number);
close(conn->ap2_control_socket);
debug(2, "Connection %d: UDP control port %u closed.", conn->connection_number, conn->local_ap2_control_port);
debug(2, "Connection %d: UDP control port %u closed.", conn->connection_number,
conn->local_ap2_control_port);
conn->ap2_control_socket = 0;
conn->ap2_remote_control_socket_addr_length =
0; // indicates to the control receiver thread that the socket address need to be
@@ -2030,7 +2031,8 @@ void rtp_buffered_audio_cleanup_handler(__attribute__((unused)) void *arg) {
debug(2, "Buffered Audio Receiver Cleanup Start.");
rtsp_conn_info *conn = (rtsp_conn_info *)arg;
close(conn->buffered_audio_socket);
debug(2, "Connection %d: TCP Buffered Audio port closed: %u.", conn->connection_number, conn->local_buffered_audio_port);
debug(2, "Connection %d: TCP Buffered Audio port closed: %u.", conn->connection_number,
conn->local_buffered_audio_port);
conn->buffered_audio_socket = 0;
debug(2, "Buffered Audio Receiver Cleanup Done.");
}
@@ -2119,10 +2121,10 @@ void *rtp_buffered_audio_processor(void *arg) {
// (does nothing if called twice during the course of one program execution)
// deprecated in ffmpeg 4.0 and later... but still needed in ffmpeg 3.6 / ubuntu 18
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
avcodec_register_all();
#pragma GCC diagnostic pop
#pragma GCC diagnostic pop
AVCodec *codec = avcodec_find_decoder(AV_CODEC_ID_AAC);
if (codec == NULL) {
@@ -2221,7 +2223,7 @@ void *rtp_buffered_audio_processor(void *arg) {
ssize_t data_remaining;
uint32_t seq_no; // audio packet number
// uint32_t previous_seq_no = 0;
int new_buffer_needed;
int new_buffer_needed = 0;
ssize_t nread;
int finished = 0;
+36 -24
View File
@@ -655,7 +655,8 @@ void cancel_all_RTSP_threads(airplay_stream_c stream_category, int except_this_o
debug_mutex_lock(&conns_lock, 1000000, 3);
int i;
for (i = 0; i < nconns; i++) {
if ((conns[i] != NULL) && (conns[i]->running != 0) && (conns[i]->connection_number != except_this_one) &&
if ((conns[i] != NULL) && (conns[i]->running != 0) &&
(conns[i]->connection_number != except_this_one) &&
((stream_category == unspecified_stream_category) ||
(stream_category == conns[i]->airplay_stream_category))) {
pthread_cancel(conns[i]->thread);
@@ -663,7 +664,8 @@ void cancel_all_RTSP_threads(airplay_stream_c stream_category, int except_this_o
}
}
for (i = 0; i < nconns; i++) {
if ((conns[i] != NULL) && (conns[i]->running != 0) && (conns[i]->connection_number != except_this_one) &&
if ((conns[i] != NULL) && (conns[i]->running != 0) &&
(conns[i]->connection_number != except_this_one) &&
((stream_category == unspecified_stream_category) ||
(stream_category == conns[i]->airplay_stream_category))) {
pthread_join(conns[i]->thread, NULL);
@@ -1303,7 +1305,8 @@ int msg_write_response(rtsp_conn_info *conn, rtsp_message *resp) {
char *string;
};
struct response_t responses[] = {{200, "OK"}, {400, "Bad Request"}, {403, "Unauthorized"}, {501, "Not Implemented"}};
struct response_t responses[] = {
{200, "OK"}, {400, "Bad Request"}, {403, "Unauthorized"}, {501, "Not Implemented"}};
int found = 0;
char *respcode_text = "Unauthorized";
for (i = 0; i < sizeof(responses) / sizeof(struct response_t); i++) {
@@ -1662,13 +1665,14 @@ void handle_flushbuffered(rtsp_conn_info *conn, rtsp_message *req, rtsp_message
}
void handle_setrate(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *resp) {
debug(3, "Connection %d: SETRATE %s : Content-Length %d", conn->connection_number,
req->path, req->contentlength);
debug(3, "Connection %d: SETRATE %s : Content-Length %d", conn->connection_number, req->path,
req->contentlength);
debug_log_rtsp_message(2, "SETRATE request -- unimplemented", req);
resp->respcode = 501; // Not Implemented
}
void handle_unimplemented_ap1(__attribute((unused)) rtsp_conn_info *conn, rtsp_message *req, rtsp_message *resp) {
void handle_unimplemented_ap1(__attribute((unused)) rtsp_conn_info *conn, rtsp_message *req,
rtsp_message *resp) {
debug_log_rtsp_message(1, "request not recognised for AirPlay 1 operation", req);
resp->respcode = 501;
}
@@ -1783,8 +1787,9 @@ void handle_get(__attribute((unused)) rtsp_conn_info *conn, __attribute((unused)
req->contentlength);
resp->respcode = 500;
}
void handle_post(__attribute((unused)) rtsp_conn_info *conn, __attribute((unused)) rtsp_message *req,
__attribute((unused)) rtsp_message *resp) {
void handle_post(__attribute((unused)) rtsp_conn_info *conn,
__attribute((unused)) rtsp_message *req,
__attribute((unused)) rtsp_message *resp) {
debug(1, "Connection %d: POST %s Content-Length %d", conn->connection_number, req->path,
req->contentlength);
resp->respcode = 500;
@@ -2321,7 +2326,7 @@ void teardown_phase_one(rtsp_conn_info *conn) {
// this can be called more than once on the same connection --
// by the player itself but also by the play seesion being killed
if (conn->player_thread) {
player_stop(conn); // this nulls the player_thread
player_stop(conn); // this nulls the player_thread
activity_monitor_signify_activity(0); // inactive, and should be after command_stop()
}
if (conn->session_key) {
@@ -2347,7 +2352,8 @@ void teardown_phase_two(rtsp_conn_info *conn) {
if (conn->event_socket) {
close(conn->event_socket);
conn->event_socket = 0;
debug(2, "Connection %d: closing TCP event port %u.", conn->connection_number, conn->local_event_port);
debug(2, "Connection %d: closing TCP event port %u.", conn->connection_number,
conn->local_event_port);
}
// if we are closing a PTP stream only, do this
@@ -2365,7 +2371,6 @@ void teardown_phase_two(rtsp_conn_info *conn) {
}
}
void handle_teardown_2(rtsp_conn_info *conn, __attribute__((unused)) rtsp_message *req,
rtsp_message *resp) {
@@ -2661,7 +2666,8 @@ void handle_setup_2(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *resp)
conn->connection_number, err);
}
debug(2, "Connection %d: TCP PTP event port opened: %u.", conn->connection_number, conn->local_event_port);
debug(2, "Connection %d: TCP PTP event port opened: %u.", conn->connection_number,
conn->local_event_port);
if (conn->rtp_event_thread != NULL)
debug(1, "previous rtp_event_thread allocation not freed, it seems.");
@@ -2707,7 +2713,8 @@ void handle_setup_2(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *resp)
conn->connection_number, err);
}
debug(1, "Connection %d: TCP Remote Control event port opened: %u.", conn->connection_number, conn->local_event_port);
debug(1, "Connection %d: TCP Remote Control event port opened: %u.",
conn->connection_number, conn->local_event_port);
if (conn->rtp_event_thread != NULL)
debug(1, "previous rtp_event_thread allocation not freed, it seems.");
conn->rtp_event_thread = malloc(sizeof(pthread_t));
@@ -2759,7 +2766,8 @@ void handle_setup_2(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *resp)
if (err) {
die("Error %d: could not find a UDP port to use as an ap2_control port", err);
}
debug(2, "Connection %d: UDP control port opened: %u.", conn->connection_number, conn->local_ap2_control_port);
debug(2, "Connection %d: UDP control port opened: %u.", conn->connection_number,
conn->local_ap2_control_port);
pthread_create(&conn->rtp_ap2_control_thread, NULL, &rtp_ap2_control_receiver, (void *)conn);
@@ -2829,7 +2837,8 @@ void handle_setup_2(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *resp)
if (err) {
die("Error %d: could not find a UDP port to use as a realtime_audio port", err);
}
debug(2, "Connection %d: UDP realtime audio port opened: %u.", conn->connection_number, conn->local_realtime_audio_port);
debug(2, "Connection %d: UDP realtime audio port opened: %u.", conn->connection_number,
conn->local_realtime_audio_port);
pthread_create(&conn->rtp_realtime_audio_thread, NULL, &rtp_realtime_audio_receiver,
(void *)conn);
@@ -2892,7 +2901,8 @@ void handle_setup_2(rtsp_conn_info *conn, rtsp_message *req, rtsp_message *resp)
conn->connection_number, err);
}
debug(2, "Connection %d: TCP Buffered Audio port opened: %u.", conn->connection_number, conn->local_buffered_audio_port);
debug(2, "Connection %d: TCP Buffered Audio port opened: %u.", conn->connection_number,
conn->local_buffered_audio_port);
// hack.
conn->max_frames_per_packet = 352; // number of audio frames per packet.
@@ -3117,7 +3127,8 @@ void handle_set_parameter_parameter(rtsp_conn_info *conn, rtsp_message *req,
conn->initial_airplay_volume = volume;
conn->initial_airplay_volume_set = 1;
}
} else if (strncmp(cp, "progress: ", strlen("progress: ")) == 0) { // this can be sent even when metadata is not solicited
} else if (strncmp(cp, "progress: ", strlen("progress: ")) ==
0) { // this can be sent even when metadata is not solicited
#ifdef CONFIG_METADATA
char *progress = cp + strlen("progress: ");
@@ -3126,8 +3137,7 @@ void handle_set_parameter_parameter(rtsp_conn_info *conn, rtsp_message *req,
send_ssnc_metadata('prgr', progress, strlen(progress), 1);
#endif
} else
{
} else {
debug(1, "Connection %d, unrecognised parameter: \"%s\" (%d)\n", conn->connection_number, cp,
strlen(cp));
}
@@ -3381,6 +3391,8 @@ void metadata_multicast_process(uint32_t type, uint32_t code, char *data, uint32
// ("ssnc", "chnk", packet_ix, packet_counts, packet_tag, packet_type, chunked_data)
uint32_t chunk_ix = 0;
if (config.metadata_sockmsglength == 24)
die("A divide by zero almost occurred (config.metadata_sockmsglength = 24).");
uint32_t chunk_total = length / (config.metadata_sockmsglength - 24);
if (chunk_total * (config.metadata_sockmsglength - 24) < length) {
chunk_total++;
@@ -3673,7 +3685,8 @@ void metadata_init(void) {
if (pthread_create(&metadata_thread, NULL, metadata_thread_function, NULL) != 0)
debug(1, "Failed to create metadata thread!");
if (pthread_create(&metadata_multicast_thread, NULL, metadata_multicast_thread_function, NULL) != 0)
if (pthread_create(&metadata_multicast_thread, NULL, metadata_multicast_thread_function,
NULL) != 0)
debug(1, "Failed to create metadata multicast thread!");
}
#ifdef CONFIG_METADATA_HUB
@@ -4513,8 +4526,6 @@ void rtsp_conversation_thread_cleanup_function(void *arg) {
close(conn->audio_socket);
}
if (conn->fd > 0) {
debug(3, "Connection %d terminating: closing fd %d.", conn->connection_number, conn->fd);
close(conn->fd);
@@ -4674,7 +4685,9 @@ static void *rtsp_conversation_thread_func(void *pconn) {
}
}
if (method_selected == 0) {
debug(1, "Connection %d: Unrecognised and unhandled rtsp request \"%s\". HTTP Response Code 501 (\"Not Implemented\") returned.",
debug(1,
"Connection %d: Unrecognised and unhandled rtsp request \"%s\". HTTP Response Code "
"501 (\"Not Implemented\") returned.",
conn->connection_number, req->method);
int y = req->contentlength;
@@ -4693,7 +4706,6 @@ static void *rtsp_conversation_thread_func(void *pconn) {
*obfp = 0;
debug(1, "Content: \"%s\".", obf);
}
}
}
debug(debug_level, "Connection %d: RTSP Response:", conn->connection_number);
+1 -1
View File
@@ -1920,7 +1920,7 @@ int main(int argc, char **argv) {
/* Version check should be the very first call because it
makes sure that important subsystems are initialized.
#define NEED_LIBGCRYPT_VERSION to the minimum required version. */
#define NEED_LIBGCRYPT_VERSION "1.5.4"
if (!gcry_check_version(NEED_LIBGCRYPT_VERSION)) {