[streaming/xcode] configurable MP3 streaming bitrate

This commit is contained in:
whatdoineed2do/Ray 2019-08-23 16:22:11 +01:00 committed by ejurgensen
parent cae790ed7e
commit 554799ebc3
10 changed files with 61 additions and 7 deletions

View File

@ -367,3 +367,16 @@ sqlite {
# but may reduce database size). Default is yes. # but may reduce database size). Default is yes.
# vacuum = yes # vacuum = yes
} }
# Streaming audio settings for remote connections (ie stream.mp3)
streaming {
# Sample rate, typically 44100 or 48000
# sample_rate = 44100
# Channels
# channels = 2
# Set the MP3 streaming bit rate (in kbps), valid options: 64 / 96 / 128 / 192 / 320
# bit_rate = 192
}

View File

@ -60,6 +60,7 @@ static cfg_opt_t sec_general[] =
#else #else
CFG_BOOL("high_resolution_clock", cfg_true, CFGF_NONE), CFG_BOOL("high_resolution_clock", cfg_true, CFGF_NONE),
#endif #endif
CFG_INT("streaming_bitrate", 192, CFGF_NONE),
// Hidden options // Hidden options
CFG_INT("db_pragma_cache_size", -1, CFGF_NONE), CFG_INT("db_pragma_cache_size", -1, CFGF_NONE),
CFG_STR("db_pragma_journal_mode", NULL, CFGF_NONE), CFG_STR("db_pragma_journal_mode", NULL, CFGF_NONE),
@ -186,6 +187,15 @@ static cfg_opt_t sec_mpd[] =
CFG_END() CFG_END()
}; };
/* streaming section structure */
static cfg_opt_t sec_streaming[] =
{
CFG_INT("sample_rate", 44100, CFGF_NONE),
CFG_INT("channels", 2, CFGF_NONE),
CFG_INT("bit_rate", 192, CFGF_NONE),
CFG_END()
};
/* Config file structure */ /* Config file structure */
static cfg_opt_t toplvl_cfg[] = static cfg_opt_t toplvl_cfg[] =
{ {
@ -198,6 +208,7 @@ static cfg_opt_t toplvl_cfg[] =
CFG_SEC("spotify", sec_spotify, CFGF_NONE), CFG_SEC("spotify", sec_spotify, CFGF_NONE),
CFG_SEC("sqlite", sec_sqlite, CFGF_NONE), CFG_SEC("sqlite", sec_sqlite, CFGF_NONE),
CFG_SEC("mpd", sec_mpd, CFGF_NONE), CFG_SEC("mpd", sec_mpd, CFGF_NONE),
CFG_SEC("streaming", sec_streaming, CFGF_NONE),
CFG_END() CFG_END()
}; };

View File

@ -1034,7 +1034,7 @@ httpd_request_parse(struct evhttp_request *req, struct httpd_uri_parsed *uri_par
void void
httpd_stream_file(struct evhttp_request *req, int id) httpd_stream_file(struct evhttp_request *req, int id)
{ {
struct media_quality quality = { HTTPD_STREAM_SAMPLE_RATE, HTTPD_STREAM_BPS, HTTPD_STREAM_CHANNELS }; struct media_quality quality = { HTTPD_STREAM_SAMPLE_RATE, HTTPD_STREAM_BPS, HTTPD_STREAM_CHANNELS, 0 };
struct media_file_info *mfi; struct media_file_info *mfi;
struct stream_ctx *st; struct stream_ctx *st;
void (*stream_cb)(int fd, short event, void *arg); void (*stream_cb)(int fd, short event, void *arg);

View File

@ -52,6 +52,8 @@ extern struct event_base *evbase_httpd;
#define STREAMING_MP3_SAMPLE_RATE 44100 #define STREAMING_MP3_SAMPLE_RATE 44100
#define STREAMING_MP3_BPS 16 #define STREAMING_MP3_BPS 16
#define STREAMING_MP3_CHANNELS 2 #define STREAMING_MP3_CHANNELS 2
#define STREAMING_MP3_BIT_RATE 192000
static int streaming_mp3_bit_rate = STREAMING_MP3_BIT_RATE;
// Linked list of mp3 streaming requests // Linked list of mp3 streaming requests
@ -182,7 +184,7 @@ streaming_end(void)
static void static void
streaming_meta_cb(evutil_socket_t fd, short event, void *arg) streaming_meta_cb(evutil_socket_t fd, short event, void *arg)
{ {
struct media_quality mp3_quality = { STREAMING_MP3_SAMPLE_RATE, STREAMING_MP3_BPS, STREAMING_MP3_CHANNELS }; struct media_quality mp3_quality = { STREAMING_MP3_SAMPLE_RATE, STREAMING_MP3_BPS, STREAMING_MP3_CHANNELS, streaming_mp3_bit_rate };
struct media_quality quality; struct media_quality quality;
struct decode_ctx *decode_ctx; struct decode_ctx *decode_ctx;
int ret; int ret;
@ -204,6 +206,9 @@ streaming_meta_cb(evutil_socket_t fd, short event, void *arg)
if (!decode_ctx) if (!decode_ctx)
goto error; goto error;
if (quality.bit_rate)
mp3_quality.bit_rate = quality.bit_rate;
streaming_encode_ctx = transcode_encode_setup(XCODE_MP3, &mp3_quality, decode_ctx, NULL, 0, 0); streaming_encode_ctx = transcode_encode_setup(XCODE_MP3, &mp3_quality, decode_ctx, NULL, 0, 0);
transcode_decode_cleanup(&decode_ctx); transcode_decode_cleanup(&decode_ctx);
if (!streaming_encode_ctx) if (!streaming_encode_ctx)
@ -618,6 +623,23 @@ streaming_init(void)
{ {
int ret; int ret;
streaming_mp3_bit_rate = cfg_getint(cfg_getsec(cfg, "streaming"), "bit_rate");
switch (streaming_mp3_bit_rate)
{
case 64:
case 96:
case 128:
case 192:
case 320:
streaming_mp3_bit_rate *= 1000;
break;
default:
DPRINTF(E_WARN, L_STREAMING, "streaming bit_rate=%d not 128/192/320, defaulting\n", streaming_mp3_bit_rate);
streaming_mp3_bit_rate = STREAMING_MP3_BIT_RATE;
}
DPRINTF(E_INFO, L_STREAMING, "streaming bit_rate=%d\n", streaming_mp3_bit_rate);
pthread_mutex_init(&streaming_sessions_lck, NULL); pthread_mutex_init(&streaming_sessions_lck, NULL);
// Non-blocking because otherwise httpd and player thread may deadlock // Non-blocking because otherwise httpd and player thread may deadlock

View File

@ -31,6 +31,7 @@ struct media_quality {
int sample_rate; int sample_rate;
int bits_per_sample; int bits_per_sample;
int channels; int channels;
int bit_rate;
}; };
struct onekeyval { struct onekeyval {

View File

@ -140,7 +140,7 @@ static int alsa_latency_history_size;
// We will try to play the music with the source quality, but if the card // We will try to play the music with the source quality, but if the card
// doesn't support that we resample to the fallback quality // doesn't support that we resample to the fallback quality
static struct media_quality alsa_fallback_quality = { 44100, 16, 2 }; static struct media_quality alsa_fallback_quality = { 44100, 16, 2, 0 };
static struct media_quality alsa_last_quality; static struct media_quality alsa_last_quality;

View File

@ -446,7 +446,7 @@ static struct cast_session *cast_sessions;
static struct cast_master_session *cast_master_session; static struct cast_master_session *cast_master_session;
//static struct timeval heartbeat_timeout = { HEARTBEAT_TIMEOUT, 0 }; //static struct timeval heartbeat_timeout = { HEARTBEAT_TIMEOUT, 0 };
static struct timeval reply_timeout = { REPLY_TIMEOUT, 0 }; static struct timeval reply_timeout = { REPLY_TIMEOUT, 0 };
static struct media_quality cast_quality_default = { CAST_QUALITY_SAMPLE_RATE_DEFAULT, CAST_QUALITY_BITS_PER_SAMPLE_DEFAULT, CAST_QUALITY_CHANNELS_DEFAULT }; static struct media_quality cast_quality_default = { CAST_QUALITY_SAMPLE_RATE_DEFAULT, CAST_QUALITY_BITS_PER_SAMPLE_DEFAULT, CAST_QUALITY_CHANNELS_DEFAULT, 0 };
/* ------------------------------- MISC HELPERS ----------------------------- */ /* ------------------------------- MISC HELPERS ----------------------------- */

View File

@ -61,7 +61,7 @@ struct fifo_buffer
static struct fifo_buffer buffer; static struct fifo_buffer buffer;
static struct media_quality fifo_quality = { 44100, 16, 2 }; static struct media_quality fifo_quality = { 44100, 16, 2, 0 };
static void static void

View File

@ -86,7 +86,7 @@ static struct pulse_session *sessions;
static uint32_t pulse_known_devices[PULSE_MAX_DEVICES]; static uint32_t pulse_known_devices[PULSE_MAX_DEVICES];
static struct media_quality pulse_last_quality; static struct media_quality pulse_last_quality;
static struct media_quality pulse_fallback_quality = { 44100, 16, 2 }; static struct media_quality pulse_fallback_quality = { 44100, 16, 2, 0 };
// Converts from 0 - 100 to Pulseaudio's scale // Converts from 0 - 100 to Pulseaudio's scale
static inline pa_volume_t static inline pa_volume_t

View File

@ -79,6 +79,7 @@ struct settings_ctx
int sample_rate; int sample_rate;
uint64_t channel_layout; uint64_t channel_layout;
int channels; int channels;
int bit_rate;
enum AVSampleFormat sample_format; enum AVSampleFormat sample_format;
bool wavheader; bool wavheader;
bool icy; bool icy;
@ -262,6 +263,11 @@ init_settings(struct settings_ctx *settings, enum transcode_profile profile, str
settings->channel_layout = av_get_default_channel_layout(quality->channels); settings->channel_layout = av_get_default_channel_layout(quality->channels);
} }
if (quality && quality->bit_rate)
{
settings->bit_rate = quality->bit_rate;
}
if (quality && quality->bits_per_sample && (quality->bits_per_sample != 8 * av_get_bytes_per_sample(settings->sample_format))) if (quality && quality->bits_per_sample && (quality->bits_per_sample != 8 * av_get_bytes_per_sample(settings->sample_format)))
{ {
DPRINTF(E_LOG, L_XCODE, "Bug! Mismatch between profile and media quality\n"); DPRINTF(E_LOG, L_XCODE, "Bug! Mismatch between profile and media quality\n");
@ -281,6 +287,7 @@ stream_settings_set(struct stream_ctx *s, struct settings_ctx *settings, enum AV
s->codec->channels = settings->channels; s->codec->channels = settings->channels;
s->codec->sample_fmt = settings->sample_format; s->codec->sample_fmt = settings->sample_format;
s->codec->time_base = (AVRational){1, settings->sample_rate}; s->codec->time_base = (AVRational){1, settings->sample_rate};
s->codec->bit_rate = settings->bit_rate;
} }
else if (type == AVMEDIA_TYPE_VIDEO) else if (type == AVMEDIA_TYPE_VIDEO)
{ {
@ -731,7 +738,7 @@ open_decoder(unsigned int *stream_index, struct decode_ctx *ctx, enum AVMediaTyp
if ((*stream_index < 0) || (!decoder)) if ((*stream_index < 0) || (!decoder))
{ {
if (!ctx->settings.silent) if (!ctx->settings.silent)
DPRINTF(E_LOG, L_XCODE, "No stream data or decoder for stream #%d\n", *stream_index); DPRINTF(E_LOG, L_XCODE, "No stream data or decoder for stream #%d\n", *stream_index);
return NULL; return NULL;
} }