Merge branch 'v0.20.x'

This commit is contained in:
Max Kellermann 2017-09-19 18:58:02 +02:00
commit 44bbf42a9f
5 changed files with 84 additions and 23 deletions

2
NEWS
View File

@ -12,6 +12,8 @@ ver 0.21 (not yet released)
ver 0.20.11 (not yet released) ver 0.20.11 (not yet released)
* storage * storage
- curl: support Content-Type application/xml - curl: support Content-Type application/xml
* decoder
- ffmpeg: more reliable song duration
ver 0.20.10 (2017/08/24) ver 0.20.10 (2017/08/24)
* decoder * decoder

View File

@ -2991,6 +2991,60 @@ run</programlisting>
</informaltable> </informaltable>
</section> </section>
<section id="opus_encoder">
<title><varname>opus</varname></title>
<para>
Encodes into <ulink
url="http://www.opus-codec.org/">Ogg Opus</ulink>.
</para>
<informaltable>
<tgroup cols="2">
<thead>
<row>
<entry>Setting</entry>
<entry>Description</entry>
</row>
</thead>
<tbody>
<row>
<entry>
<varname>bitrate</varname>
</entry>
<entry>
Sets the data rate in bit per second. The special
value "auto" lets <application>libopus</application>
choose a rate (which is the default), and "max" uses
the maximum possible data rate.
</entry>
</row>
<row>
<entry>
<varname>complexity</varname>
</entry>
<entry>
Sets the <ulink
url="https://wiki.xiph.org/OpusFAQ#What_is_the_complexity_of_Opus.3F">Opus
complexity</ulink>.
</entry>
</row>
<row>
<entry>
<varname>signal</varname>
</entry>
<entry>
Sets the Opus signal type. Valid values are "auto"
(the default), "voice" and "music".
</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</section>
<section id="vorbis_encoder"> <section id="vorbis_encoder">
<title><varname>vorbis</varname></title> <title><varname>vorbis</varname></title>

View File

@ -712,7 +712,9 @@ FfmpegDecode(DecoderClient &client, InputStream &input,
#endif #endif
const SignedSongTime total_time = const SignedSongTime total_time =
FromFfmpegTimeChecked(av_stream.duration, av_stream.time_base); av_stream.duration != (int64_t)AV_NOPTS_VALUE
? FromFfmpegTimeChecked(av_stream.duration, av_stream.time_base)
: FromFfmpegTimeChecked(format_context.duration, AV_TIME_BASE_Q);
client.Ready(audio_format, input.IsSeekable(), total_time); client.Ready(audio_format, input.IsSeekable(), total_time);
@ -842,6 +844,10 @@ FfmpegScanStream(AVFormatContext &format_context,
tag_handler_invoke_duration(handler, handler_ctx, tag_handler_invoke_duration(handler, handler_ctx,
FromFfmpegTime(stream.duration, FromFfmpegTime(stream.duration,
stream.time_base)); stream.time_base));
else if (format_context.duration != (int64_t)AV_NOPTS_VALUE)
tag_handler_invoke_duration(handler, handler_ctx,
FromFfmpegTime(format_context.duration,
AV_TIME_BASE_Q));
FfmpegScanMetadata(format_context, audio_stream, handler, handler_ctx); FfmpegScanMetadata(format_context, audio_stream, handler, handler_ctx);

View File

@ -66,16 +66,14 @@ SndioOutput::Create(EventLoop &, const ConfigBlock &block) {
static bool static bool
sndio_test_default_device() sndio_test_default_device()
{ {
struct sio_hdl *sio_hdl; auto *hdl = sio_open(SIO_DEVANY, SIO_PLAY, 0);
if (!hdl) {
sio_hdl = sio_open(SIO_DEVANY, SIO_PLAY, 0);
if (!sio_hdl) {
FormatError(sndio_output_domain, FormatError(sndio_output_domain,
"Error opening default sndio device"); "Error opening default sndio device");
return false; return false;
} }
sio_close(sio_hdl); sio_close(hdl);
return true; return true;
} }
@ -85,8 +83,8 @@ SndioOutput::Open(AudioFormat &audio_format)
struct sio_par par; struct sio_par par;
unsigned bits, rate, chans; unsigned bits, rate, chans;
sio_hdl = sio_open(device, SIO_PLAY, 0); hdl = sio_open(device, SIO_PLAY, 0);
if (!sio_hdl) if (!hdl)
throw std::runtime_error("Failed to open default sndio device"); throw std::runtime_error("Failed to open default sndio device");
switch (audio_format.format) { switch (audio_format.format) {
@ -116,9 +114,9 @@ SndioOutput::Open(AudioFormat &audio_format)
par.le = SIO_LE_NATIVE; par.le = SIO_LE_NATIVE;
par.appbufsz = rate * buffer_time / 1000; par.appbufsz = rate * buffer_time / 1000;
if (!sio_setpar(sio_hdl, &par) || if (!sio_setpar(hdl, &par) ||
!sio_getpar(sio_hdl, &par)) { !sio_getpar(hdl, &par)) {
sio_close(sio_hdl); sio_close(hdl);
throw std::runtime_error("Failed to set/get audio params"); throw std::runtime_error("Failed to set/get audio params");
} }
@ -128,21 +126,21 @@ SndioOutput::Open(AudioFormat &audio_format)
par.pchan != chans || par.pchan != chans ||
par.sig != 1 || par.sig != 1 ||
par.le != SIO_LE_NATIVE) { par.le != SIO_LE_NATIVE) {
sio_close(sio_hdl); sio_close(hdl);
throw std::runtime_error("Requested audio params cannot be satisfied"); throw std::runtime_error("Requested audio params cannot be satisfied");
} }
// Set volume after opening fresh audio stream which does // Set volume after opening fresh audio stream which does
// know nothing about previous audio streams. // know nothing about previous audio streams.
sio_setvol(sio_hdl, raw_volume); sio_setvol(hdl, raw_volume);
// sio_onvol returns 0 if no volume knob is available. // sio_onvol returns 0 if no volume knob is available.
// This is the case on raw audio devices rather than // This is the case on raw audio devices rather than
// the sndiod audio server. // the sndiod audio server.
if (sio_onvol(sio_hdl, VolumeCallback, this) == 0) if (sio_onvol(hdl, VolumeCallback, this) == 0)
raw_volume = -1; raw_volume = -1;
if (!sio_start(sio_hdl)) { if (!sio_start(hdl)) {
sio_close(sio_hdl); sio_close(hdl);
throw std::runtime_error("Failed to start audio device"); throw std::runtime_error("Failed to start audio device");
} }
} }
@ -150,7 +148,7 @@ SndioOutput::Open(AudioFormat &audio_format)
void void
SndioOutput::Close() noexcept SndioOutput::Close() noexcept
{ {
sio_close(sio_hdl); sio_close(hdl);
} }
size_t size_t
@ -158,15 +156,16 @@ SndioOutput::Play(const void *chunk, size_t size)
{ {
size_t n; size_t n;
n = sio_write(sio_hdl, chunk, size); n = sio_write(hdl, chunk, size);
if (n == 0 && sio_eof(sio_hdl) != 0) if (n == 0 && sio_eof(hdl) != 0)
throw std::runtime_error("sndio write failed"); throw std::runtime_error("sndio write failed");
return n; return n;
} }
void void
SndioOutput::SetVolume(unsigned int volume) { SndioOutput::SetVolume(unsigned int volume)
sio_setvol(sio_hdl, volume * SIO_MAXVOL / 100); {
sio_setvol(hdl, volume * SIO_MAXVOL / 100);
} }
static inline unsigned int static inline unsigned int

View File

@ -30,7 +30,7 @@ class SndioOutput final : AudioOutput {
MixerListener *listener = nullptr; MixerListener *listener = nullptr;
const char *const device; const char *const device;
const unsigned buffer_time; /* in ms */ const unsigned buffer_time; /* in ms */
struct sio_hdl *sio_hdl; struct sio_hdl *hdl;
int raw_volume; int raw_volume;
public: public: