mirror of
https://github.com/sle118/squeezelite-esp32.git
synced 2026-01-27 12:50:49 +03:00
add opus codec (i2s default IO changed!)
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
# "main" pseudo-component makefile.
|
||||
#
|
||||
# (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.)
|
||||
CFLAGS += -O3 -DLINKALL -DLOOPBACK -DNO_FAAD -DRESAMPLE16 -DEMBEDDED -DTREMOR_ONLY -DBYTES_PER_FRAME=4 \
|
||||
CFLAGS += -O3 -DLINKALL -DLOOPBACK -DTAS575x -DNO_FAAD -DRESAMPLE16 -DEMBEDDED -DTREMOR_ONLY -DBYTES_PER_FRAME=4 \
|
||||
-I$(COMPONENT_PATH)/../codecs/inc \
|
||||
-I$(COMPONENT_PATH)/../codecs/inc/mad \
|
||||
-I$(COMPONENT_PATH)/../codecs/inc/alac \
|
||||
@@ -10,7 +10,9 @@ CFLAGS += -O3 -DLINKALL -DLOOPBACK -DNO_FAAD -DRESAMPLE16 -DEMBEDDED -DTREMOR_ON
|
||||
-I$(COMPONENT_PATH)/../codecs/inc/vorbis \
|
||||
-I$(COMPONENT_PATH)/../codecs/inc/soxr \
|
||||
-I$(COMPONENT_PATH)/../codecs/inc/resample16 \
|
||||
-I$(COMPONENT_PATH)/../tools
|
||||
-I$(COMPONENT_PATH)/../tools \
|
||||
-I$(COMPONENT_PATH)/../codecs/inc/opus \
|
||||
-I$(COMPONENT_PATH)/../codecs/inc/opusfile
|
||||
|
||||
# -I$(COMPONENT_PATH)/../codecs/inc/faad2
|
||||
|
||||
|
||||
@@ -180,6 +180,9 @@ void decode_init(log_level level, const char *include_codecs, const char *exclud
|
||||
|
||||
if (!strstr(exclude_codecs, "ogg") && (!include_codecs || (order_codecs = strstr(include_codecs, "ogg"))))
|
||||
sort_codecs((include_codecs ? order_codecs - include_codecs : i), register_vorbis());
|
||||
|
||||
if (!strstr(exclude_codecs, "ops") && (!include_codecs || (order_codecs = strstr(include_codecs, "ops"))))
|
||||
sort_codecs((include_codecs ? order_codecs - include_codecs : i), register_opus());
|
||||
|
||||
if (!strstr(exclude_codecs, "flac") && (!include_codecs || (order_codecs = strstr(include_codecs, "flac"))))
|
||||
sort_codecs((include_codecs ? order_codecs - include_codecs : i), register_flac());
|
||||
|
||||
@@ -218,6 +218,9 @@ static void usage(const char *argv0) {
|
||||
#if USE_SSL
|
||||
" SSL"
|
||||
#endif
|
||||
#if NO_SSLSYM
|
||||
" NO_SSLSYM"
|
||||
#endif
|
||||
#if LINKALL
|
||||
" LINKALL"
|
||||
#endif
|
||||
@@ -702,7 +705,7 @@ int main(int argc, char **argv) {
|
||||
signal(SIGHUP, sighandler);
|
||||
#endif
|
||||
|
||||
#if USE_SSL && !LINKALL
|
||||
#if USE_SSL && !LINKALL && !NO_SSLSYM
|
||||
ssl_loaded = load_ssl_symbols();
|
||||
#endif
|
||||
|
||||
@@ -837,7 +840,7 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if USE_SSL && !LINKALL
|
||||
#if USE_SSL && !LINKALL && !NO_SSLSYM
|
||||
free_ssl_symbols();
|
||||
#endif
|
||||
|
||||
|
||||
317
components/squeezelite/opus.c
Normal file
317
components/squeezelite/opus.c
Normal file
@@ -0,0 +1,317 @@
|
||||
/*
|
||||
* Squeezelite - lightweight headless squeezebox emulator
|
||||
*
|
||||
* (c) Adrian Smith 2012-2015, triode1@btinternet.com
|
||||
* Ralph Irving 2015-2017, ralph_irving@hotmail.com
|
||||
* Philippe 2018-2019, philippe_44@outlook.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "squeezelite.h"
|
||||
|
||||
/*
|
||||
* with some low-end CPU, the decode call takes a fair bit of time and if the outputbuf is locked during that
|
||||
* period, the output_thread (or equivalent) will be locked although there is plenty of samples available.
|
||||
* Normally, with PRIO_INHERIT, that thread should increase decoder priority and get the lock quickly but it
|
||||
* seems that when the streambuf has plenty of data, the decode thread grabs the CPU to much, even it the output
|
||||
* thread has a higher priority. Using an interim buffer where opus decoder writes the output is not great from
|
||||
* an efficiency (one extra memory copy) point of view, but it allows the lock to not be kept for too long
|
||||
*/
|
||||
#define FRAME_BUF 2048
|
||||
|
||||
#if BYTES_PER_FRAME == 4
|
||||
#define ALIGN(n) (n)
|
||||
#else
|
||||
#define ALIGN(n) (n << 16)
|
||||
#endif
|
||||
|
||||
#include <opusfile.h>
|
||||
|
||||
struct opus {
|
||||
struct OggOpusFile *of;
|
||||
bool opened;
|
||||
#if FRAME_BUF
|
||||
u8_t *write_buf;
|
||||
#endif
|
||||
#if !LINKALL
|
||||
// opus symbols to be dynamically loaded
|
||||
void (*op_free)(OggOpusFile *_of);
|
||||
int (*op_read)(OggOpusFile *_of, opus_int16 *_pcm, int _buf_size, int *_li);
|
||||
const OpusHead* (*op_head)(OggOpusFile *_of, int _li);
|
||||
OggOpusFile* (*op_open_callbacks) (void *_source, OpusFileCallbacks *_cb, unsigned char *_initial_data, size_t _initial_bytes, int *_error);
|
||||
#endif
|
||||
};
|
||||
|
||||
static struct opus *u;
|
||||
|
||||
extern log_level loglevel;
|
||||
|
||||
extern struct buffer *streambuf;
|
||||
extern struct buffer *outputbuf;
|
||||
extern struct streamstate stream;
|
||||
extern struct outputstate output;
|
||||
extern struct decodestate decode;
|
||||
extern struct processstate process;
|
||||
|
||||
#define LOCK_S mutex_lock(streambuf->mutex)
|
||||
#define UNLOCK_S mutex_unlock(streambuf->mutex)
|
||||
#define LOCK_O mutex_lock(outputbuf->mutex)
|
||||
#define UNLOCK_O mutex_unlock(outputbuf->mutex)
|
||||
#if PROCESS
|
||||
#define LOCK_O_direct if (decode.direct) mutex_lock(outputbuf->mutex)
|
||||
#define UNLOCK_O_direct if (decode.direct) mutex_unlock(outputbuf->mutex)
|
||||
#define LOCK_O_not_direct if (!decode.direct) mutex_lock(outputbuf->mutex)
|
||||
#define UNLOCK_O_not_direct if (!decode.direct) mutex_unlock(outputbuf->mutex)
|
||||
#define IF_DIRECT(x) if (decode.direct) { x }
|
||||
#define IF_PROCESS(x) if (!decode.direct) { x }
|
||||
#else
|
||||
#define LOCK_O_direct mutex_lock(outputbuf->mutex)
|
||||
#define UNLOCK_O_direct mutex_unlock(outputbuf->mutex)
|
||||
#define LOCK_O_not_direct
|
||||
#define UNLOCK_O_not_direct
|
||||
#define IF_DIRECT(x) { x }
|
||||
#define IF_PROCESS(x)
|
||||
#endif
|
||||
|
||||
#if LINKALL
|
||||
#define OP(h, fn, ...) (op_ ## fn)(__VA_ARGS__)
|
||||
#else
|
||||
#define OP(h, fn, ...) (h)->op_ ## fn(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
// called with mutex locked within vorbis_decode to avoid locking O before S
|
||||
static int _read_cb(void *datasource, char *ptr, int size) {
|
||||
size_t bytes;
|
||||
|
||||
LOCK_S;
|
||||
|
||||
bytes = min(_buf_used(streambuf), _buf_cont_read(streambuf));
|
||||
bytes = min(bytes, size);
|
||||
|
||||
memcpy(ptr, streambuf->readp, bytes);
|
||||
_buf_inc_readp(streambuf, bytes);
|
||||
|
||||
UNLOCK_S;
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
static decode_state opus_decompress(void) {
|
||||
frames_t frames;
|
||||
int n;
|
||||
static int channels;
|
||||
u8_t *write_buf;
|
||||
|
||||
LOCK_S;
|
||||
|
||||
if (stream.state <= DISCONNECT && !_buf_used(streambuf)) {
|
||||
UNLOCK_S;
|
||||
return DECODE_COMPLETE;
|
||||
}
|
||||
|
||||
UNLOCK_S;
|
||||
|
||||
if (decode.new_stream) {
|
||||
struct OpusFileCallbacks cbs;
|
||||
const struct OpusHead *info;
|
||||
int err;
|
||||
|
||||
cbs.read = (op_read_func) _read_cb;
|
||||
cbs.seek = NULL; cbs.tell = NULL; cbs.close = NULL;
|
||||
|
||||
if ((u->of = OP(u, open_callbacks, streambuf, &cbs, NULL, 0, &err)) == NULL) {
|
||||
LOG_WARN("open_callbacks error: %d", err);
|
||||
return DECODE_COMPLETE;
|
||||
}
|
||||
|
||||
u->opened = true;
|
||||
info = OP(u, head, u->of, -1);
|
||||
|
||||
LOCK_O;
|
||||
output.next_sample_rate = 48000;
|
||||
IF_DSD( output.next_fmt = PCM; )
|
||||
output.track_start = outputbuf->writep;
|
||||
if (output.fade_mode) _checkfade(true);
|
||||
decode.new_stream = false;
|
||||
UNLOCK_O;
|
||||
|
||||
channels = info->channel_count;
|
||||
|
||||
LOG_INFO("setting track_start");
|
||||
}
|
||||
|
||||
#if !FRAME_BUF
|
||||
LOCK_O_direct;
|
||||
#endif
|
||||
|
||||
#if FRAME_BUF
|
||||
IF_DIRECT(
|
||||
frames = min(_buf_space(outputbuf), _buf_cont_write(outputbuf)) / BYTES_PER_FRAME;
|
||||
write_buf = u->write_buf;
|
||||
);
|
||||
#else
|
||||
IF_DIRECT(
|
||||
frames = min(_buf_space(outputbuf), _buf_cont_write(outputbuf)) / BYTES_PER_FRAME;
|
||||
write_buf = outputbuf->writep;
|
||||
);
|
||||
#endif
|
||||
IF_PROCESS(
|
||||
frames = process.max_in_frames;
|
||||
write_buf = process.inbuf;
|
||||
);
|
||||
|
||||
#if FRAME_BUF
|
||||
frames = min(frames, FRAME_BUF);
|
||||
#endif
|
||||
|
||||
// write the decoded frames into outputbuf then unpack them (they are 16 bits)
|
||||
n = OP(u, read, u->of, (opus_int16*) write_buf, frames * channels, NULL);
|
||||
|
||||
#if FRAME_BUF
|
||||
LOCK_O_direct;
|
||||
#endif
|
||||
|
||||
if (n > 0) {
|
||||
frames_t count;
|
||||
s16_t *iptr;
|
||||
ISAMPLE_T *optr;
|
||||
|
||||
frames = n;
|
||||
count = frames * channels;
|
||||
|
||||
iptr = (s16_t *)write_buf + count;
|
||||
optr = (ISAMPLE_T *) outputbuf->writep + frames * 2;
|
||||
|
||||
if (channels == 2) {
|
||||
#if BYTES_PER_FRAME == 4
|
||||
memcpy(outputbuf->writep, write_buf, frames * BYTES_PER_FRAME);
|
||||
#else
|
||||
while (count--) {
|
||||
*--optr = *--iptr << 16;
|
||||
}
|
||||
#endif
|
||||
} else if (channels == 1) {
|
||||
while (count--) {
|
||||
*--optr = ALIGN(*--iptr);
|
||||
*--optr = ALIGN(*iptr);
|
||||
}
|
||||
}
|
||||
|
||||
IF_DIRECT(
|
||||
_buf_inc_writep(outputbuf, frames * BYTES_PER_FRAME);
|
||||
);
|
||||
IF_PROCESS(
|
||||
process.in_frames = frames;
|
||||
);
|
||||
|
||||
LOG_SDEBUG("wrote %u frames", frames);
|
||||
|
||||
} else if (n == 0) {
|
||||
|
||||
LOG_INFO("end of stream");
|
||||
UNLOCK_O_direct;
|
||||
return DECODE_COMPLETE;
|
||||
|
||||
} else if (n == OP_HOLE) {
|
||||
|
||||
// recoverable hole in stream, seen when skipping
|
||||
LOG_DEBUG("hole in stream");
|
||||
|
||||
} else {
|
||||
|
||||
LOG_INFO("op_read error: %d", n);
|
||||
UNLOCK_O_direct;
|
||||
return DECODE_COMPLETE;
|
||||
}
|
||||
|
||||
UNLOCK_O_direct;
|
||||
|
||||
return DECODE_RUNNING;
|
||||
}
|
||||
|
||||
|
||||
static void opus_open(u8_t size, u8_t rate, u8_t chan, u8_t endianness) {
|
||||
if (!u->of) {
|
||||
#if FRAME_BUF
|
||||
u->write_buf = malloc(FRAME_BUF * BYTES_PER_FRAME);
|
||||
#endif
|
||||
}
|
||||
u->opened = false;
|
||||
}
|
||||
|
||||
static void opus_close(void) {
|
||||
u->opened = false;
|
||||
OP(u, free, u->of);
|
||||
#if FRAME_BUF
|
||||
free(u->write_buf);
|
||||
u->write_buf = NULL;
|
||||
#endif
|
||||
u->of = NULL;
|
||||
}
|
||||
|
||||
static bool load_opus(void) {
|
||||
#if !LINKALL
|
||||
void *handle = dlopen(LIBOPUS, RTLD_NOW);
|
||||
char *err;
|
||||
|
||||
if (!handle) {
|
||||
LOG_INFO("dlerror: %s", dlerror());
|
||||
return false;
|
||||
}
|
||||
|
||||
u->op_free = dlsym(handle, "op_free");
|
||||
u->op_read = dlsym(handle, "op_read");
|
||||
u->op_head = dlsym(handle, "op_head");
|
||||
u->op_open_callbacks = dlsym(handle, "op_open_callbacks");
|
||||
|
||||
if ((err = dlerror()) != NULL) {
|
||||
LOG_INFO("dlerror: %s", err);
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG_INFO("loaded "LIBOPUS);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct codec *register_opus(void) {
|
||||
static struct codec ret = {
|
||||
'u', // id
|
||||
"ops", // types
|
||||
4096, // min read
|
||||
20480, // min space
|
||||
opus_open, // open
|
||||
opus_close, // close
|
||||
opus_decompress, // decode
|
||||
};
|
||||
|
||||
u = malloc(sizeof(struct opus));
|
||||
if (!u) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
u->of = NULL;
|
||||
u->opened = false;
|
||||
|
||||
if (!load_opus()) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
LOG_INFO("using opus to decode ops");
|
||||
return &ret;
|
||||
}
|
||||
|
||||
@@ -387,7 +387,7 @@ void output_init_common(log_level level, const char *device, unsigned output_buf
|
||||
output.supported_rates[i] = rates[i];
|
||||
}
|
||||
}
|
||||
else
|
||||
else {
|
||||
#else
|
||||
{
|
||||
#endif
|
||||
|
||||
@@ -131,9 +131,9 @@ static const struct tas575x_cmd_s tas575x_init_sequence[] = {
|
||||
|
||||
static const i2c_config_t i2c_config = {
|
||||
.mode = I2C_MODE_MASTER,
|
||||
.sda_io_num = 19,
|
||||
.sda_io_num = 27,
|
||||
.sda_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.scl_io_num = 18,
|
||||
.scl_io_num = 26,
|
||||
.scl_pullup_en = GPIO_PULLUP_ENABLE,
|
||||
.master.clk_speed = 100000,
|
||||
};
|
||||
|
||||
@@ -122,7 +122,7 @@ static void sendHELO(bool reconnect, const char *fixed_cap, const char *var_cap,
|
||||
struct HELO_packet pkt;
|
||||
|
||||
#if USE_SSL
|
||||
#if !LINKALL
|
||||
#if !LINKALL && !NO_SSLSYM
|
||||
if (ssl_loaded) base_cap = SSL_CAP "," BASE_CAP;
|
||||
else base_cap = BASE_CAP;
|
||||
#endif
|
||||
@@ -769,11 +769,6 @@ in_addr_t discover_server(char *default_server) {
|
||||
char *buf;
|
||||
struct pollfd pollinfo;
|
||||
unsigned port;
|
||||
int attempts = 0;
|
||||
|
||||
#if EMBEDDED
|
||||
attempts = 5;
|
||||
#endif
|
||||
|
||||
int disc_sock = socket(AF_INET, SOCK_DGRAM, 0);
|
||||
|
||||
@@ -810,7 +805,7 @@ in_addr_t discover_server(char *default_server) {
|
||||
server_addr(default_server, &s.sin_addr.s_addr, &port);
|
||||
}
|
||||
|
||||
} while (s.sin_addr.s_addr == 0 && running && (!attempts || --attempts));
|
||||
} while (s.sin_addr.s_addr == 0 && running);
|
||||
|
||||
closesocket(disc_sock);
|
||||
|
||||
@@ -895,7 +890,7 @@ void slimproto(log_level level, char *server, u8_t mac[6], const char *name, con
|
||||
|
||||
new_server = 0;
|
||||
|
||||
while (running && slimproto_ip) {
|
||||
while (running) {
|
||||
|
||||
if (new_server) {
|
||||
previous_server = slimproto_ip;
|
||||
|
||||
@@ -180,6 +180,12 @@
|
||||
#define USE_SSL 0
|
||||
#endif
|
||||
|
||||
#if defined (NO_SSLSYM)
|
||||
#undef NO_SSLSYM
|
||||
#define NO_SSLSYM 1
|
||||
#else
|
||||
#define NO_SSLSYM 0
|
||||
#endif
|
||||
|
||||
#if !LINKALL
|
||||
|
||||
@@ -190,6 +196,7 @@
|
||||
#define LIBMAD "libmad.so.0"
|
||||
#define LIBMPG "libmpg123.so.0"
|
||||
#define LIBVORBIS "libvorbisfile.so.3"
|
||||
#define LIBOPUS "libopusfile.so.0"
|
||||
#define LIBTREMOR "libvorbisidec.so.1"
|
||||
#define LIBFAAD "libfaad.so.2"
|
||||
#define LIBAVUTIL "libavutil.so.%d"
|
||||
@@ -205,6 +212,7 @@
|
||||
#define LIBMPG "libmpg123.0.dylib"
|
||||
#define LIBVORBIS "libvorbisfile.3.dylib"
|
||||
#define LIBTREMOR "libvorbisidec.1.dylib"
|
||||
#define LIBOPUS "libopusfile.0.dylib"
|
||||
#define LIBFAAD "libfaad.2.dylib"
|
||||
#define LIBAVUTIL "libavutil.%d.dylib"
|
||||
#define LIBAVCODEC "libavcodec.%d.dylib"
|
||||
@@ -217,6 +225,7 @@
|
||||
#define LIBMAD "libmad-0.dll"
|
||||
#define LIBMPG "libmpg123-0.dll"
|
||||
#define LIBVORBIS "libvorbisfile.dll"
|
||||
#define LIBOPUS "libopusfile-0.dll"
|
||||
#define LIBTREMOR "libvorbisidec.dll"
|
||||
#define LIBFAAD "libfaad2.dll"
|
||||
#define LIBAVUTIL "avutil-%d.dll"
|
||||
@@ -226,15 +235,17 @@
|
||||
#endif
|
||||
|
||||
#if FREEBSD
|
||||
#define LIBFLAC "libFLAC.so.11"
|
||||
#define LIBMAD "libmad.so.2"
|
||||
#define LIBFLAC "libFLAC.so.8"
|
||||
#define LIBMAD "libmad.so.0"
|
||||
#define LIBMPG "libmpg123.so.0"
|
||||
#define LIBVORBIS "libvorbisfile.so.6"
|
||||
#define LIBVORBIS "libvorbisfile.so.3"
|
||||
#define LIBTREMOR "libvorbisidec.so.1"
|
||||
#define LIBOPUS "libopusfile.so.1"
|
||||
#define LIBFAAD "libfaad.so.2"
|
||||
#define LIBAVUTIL "libavutil.so.%d"
|
||||
#define LIBAVCODEC "libavcodec.so.%d"
|
||||
#define LIBAVFORMAT "libavformat.so.%d"
|
||||
#define LIBSOXR "libsoxr.so.0"
|
||||
#endif
|
||||
|
||||
#endif // !LINKALL
|
||||
@@ -773,6 +784,7 @@ struct codec *register_helixaac(void);
|
||||
struct codec *register_dsd(void);
|
||||
struct codec *register_alac(void);
|
||||
struct codec *register_ff(const char *codec);
|
||||
struct codec *register_opus(void);
|
||||
|
||||
//gpio.c
|
||||
#if GPIO
|
||||
@@ -799,7 +811,7 @@ void ir_close(void);
|
||||
#endif
|
||||
|
||||
// sslsym.c
|
||||
#if USE_SSL && !LINKALL
|
||||
#if USE_SSL && !LINKALL && !NO_SSLSYM
|
||||
bool load_ssl_symbols(void);
|
||||
void free_ssl_symbols(void);
|
||||
bool ssl_loaded;
|
||||
|
||||
@@ -377,7 +377,7 @@ void stream_init(log_level level, unsigned stream_buf_size) {
|
||||
}
|
||||
|
||||
#if USE_SSL
|
||||
#if !LINKALL
|
||||
#if !LINKALL && !NO_SSLSYM
|
||||
if (ssl_loaded) {
|
||||
#endif
|
||||
SSL_library_init();
|
||||
@@ -387,7 +387,7 @@ void stream_init(log_level level, unsigned stream_buf_size) {
|
||||
exit(0);
|
||||
}
|
||||
SSL_CTX_set_options(SSLctx, SSL_OP_NO_SSLv2);
|
||||
#if !LINKALL
|
||||
#if !LINKALL && !NO_SSLSYM
|
||||
}
|
||||
#endif
|
||||
ssl = NULL;
|
||||
|
||||
@@ -113,15 +113,15 @@ static size_t _read_cb(void *ptr, size_t size, size_t nmemb, void *datasource) {
|
||||
size_t bytes;
|
||||
|
||||
LOCK_S;
|
||||
|
||||
|
||||
bytes = min(_buf_used(streambuf), _buf_cont_read(streambuf));
|
||||
bytes = min(bytes, size * nmemb);
|
||||
|
||||
memcpy(ptr, streambuf->readp, bytes);
|
||||
_buf_inc_readp(streambuf, bytes);
|
||||
|
||||
|
||||
UNLOCK_S;
|
||||
|
||||
|
||||
return bytes / size;
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ static decode_state vorbis_decode(void) {
|
||||
u8_t *write_buf;
|
||||
|
||||
LOCK_S;
|
||||
|
||||
|
||||
if (stream.state <= DISCONNECT && !_buf_used(streambuf)) {
|
||||
UNLOCK_S;
|
||||
return DECODE_COMPLETE;
|
||||
@@ -151,7 +151,7 @@ static decode_state vorbis_decode(void) {
|
||||
struct vorbis_info *info;
|
||||
|
||||
cbs.read_func = _read_cb;
|
||||
|
||||
|
||||
if (TREMOR(v)) {
|
||||
cbs.seek_func = _seek_cb; cbs.close_func = _close_cb; cbs.tell_func = _tell_cb;
|
||||
} else {
|
||||
@@ -162,13 +162,13 @@ static decode_state vorbis_decode(void) {
|
||||
LOG_WARN("open_callbacks error: %d", err);
|
||||
return DECODE_COMPLETE;
|
||||
}
|
||||
|
||||
|
||||
v->opened = true;
|
||||
info = OV(v, info, v->vf, -1);
|
||||
|
||||
|
||||
LOG_INFO("setting track_start");
|
||||
LOCK_O;
|
||||
output.next_sample_rate = decode_newstream(info->rate, output.supported_rates);
|
||||
output.next_sample_rate = decode_newstream(info->rate, output.supported_rates);
|
||||
IF_DSD( output.next_fmt = PCM; )
|
||||
output.track_start = outputbuf->writep;
|
||||
if (output.fade_mode) _checkfade(true);
|
||||
@@ -186,15 +186,18 @@ static decode_state vorbis_decode(void) {
|
||||
#if !FRAME_BUF
|
||||
LOCK_O_direct;
|
||||
#endif
|
||||
|
||||
|
||||
#if FRAME_BUF
|
||||
IF_DIRECT(
|
||||
frames = min(_buf_space(outputbuf), _buf_cont_write(outputbuf)) / BYTES_PER_FRAME;
|
||||
#if FRAME_BUF
|
||||
write_buf = v->write_buf;
|
||||
#else
|
||||
write_buf = outputbuf->writep;
|
||||
#endif
|
||||
);
|
||||
#else
|
||||
IF_DIRECT(
|
||||
frames = min(_buf_space(outputbuf), _buf_cont_write(outputbuf)) / BYTES_PER_FRAME;
|
||||
write_buf = outputbuf->writep;
|
||||
);
|
||||
#endif
|
||||
IF_PROCESS(
|
||||
frames = process.max_in_frames;
|
||||
write_buf = process.inbuf;
|
||||
@@ -244,7 +247,7 @@ static decode_state vorbis_decode(void) {
|
||||
while (count--) {
|
||||
*--optr = *--iptr << 16;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
} else if (channels == 1) {
|
||||
while (count--) {
|
||||
*--optr = ALIGN(*--iptr);
|
||||
@@ -271,7 +274,7 @@ static decode_state vorbis_decode(void) {
|
||||
|
||||
// recoverable hole in stream, seen when skipping
|
||||
LOG_DEBUG("hole in stream");
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
LOG_INFO("ov_read error: %d", n);
|
||||
|
||||
Reference in New Issue
Block a user