Codebase list squeezelite / 9702efa
Support for vorbis decode - via libvorbisfile or libvorbisidec (tremor) Reduce memory footprint slightly for non loaded codecs by reducing use of golobal/static vars Adrian Smith 11 years ago
8 changed file(s) with 366 addition(s) and 123 deletion(s). Raw diff Collapse all Expand all
00 CFLAGS = -Wall -fPIC -O2
1 LDFLAGS = -lasound -lpthread
1 LDFLAGS = -lasound -lpthread -ldl -lrt
22
33 all: squeezelite
44
5 squeezelite: main.o slimproto.o utils.o output.o buffer.o stream.o decode.o flac.o pcm.o mad.o
6 $(CC) $(CFLAGS) main.o slimproto.o utils.o output.o buffer.o stream.o decode.o flac.o pcm.o mad.o -o squeezelite $(LDFLAGS)
5 squeezelite: main.o slimproto.o utils.o output.o buffer.o stream.o decode.o flac.o pcm.o mad.o vorbis.o
6 $(CC) $(CFLAGS) main.o slimproto.o utils.o output.o buffer.o stream.o decode.o flac.o pcm.o mad.o vorbis.o $(LDFLAGS) -o squeezelite
77
88 main.o: main.c squeezelite.h
99 $(CC) $(CFLAGS) -c main.c -o main.o
3535 mad.o: mad.c squeezelite.h
3636 $(CC) $(CFLAGS) -c mad.c -o mad.o
3737
38 vorbis.o: vorbis.c squeezelite.h
39 $(CC) $(CFLAGS) -c vorbis.c -o vorbis.o
40
8888 LOG_INFO("init decode");
8989
9090 // register codecs
91 if (!opt || !strcmp(opt, "flac")) codecs[0] = register_flac();
92 if (!opt || !strcmp(opt, "pcm")) codecs[1] = register_pcm();
93 if (!opt || !strcmp(opt, "mp3")) codecs[2] = register_mad();
91 // alc,wma,wmap,wmal,aac,spt,ogg,ogf,flc,aif,pcm,mp3
92 if (!opt || !strcmp(opt, "ogg")) codecs[0] = register_vorbis();
93 if (!opt || !strcmp(opt, "flac")) codecs[1] = register_flac();
94 if (!opt || !strcmp(opt, "pcm")) codecs[2] = register_pcm();
95 if (!opt || !strcmp(opt, "mp3")) codecs[3] = register_mad();
9496
9597 pthread_attr_t attr;
9698 pthread_attr_init(&attr);
2222 #include <FLAC/stream_decoder.h>
2323 #include <dlfcn.h>
2424
25 #define LIBFLAC "libFLAC.so.8"
26
2527 // FLAC symbols to be dynamically loaded
26 FLAC_API const char **f__StreamDecoderErrorStatusString;
27 FLAC_API const char **f__StreamDecoderStateString;
28 FLAC_API FLAC__StreamDecoder * (* f__stream_decoder_new)(void);
29 FLAC_API FLAC__bool (* f__stream_decoder_reset)(FLAC__StreamDecoder *decoder);
30 FLAC_API void (* f__stream_decoder_delete)(FLAC__StreamDecoder *decoder);
31 FLAC_API FLAC__StreamDecoderInitStatus (* f__stream_decoder_init_stream)(
32 FLAC__StreamDecoder *decoder,
33 FLAC__StreamDecoderReadCallback read_callback,
34 FLAC__StreamDecoderSeekCallback seek_callback,
35 FLAC__StreamDecoderTellCallback tell_callback,
36 FLAC__StreamDecoderLengthCallback length_callback,
37 FLAC__StreamDecoderEofCallback eof_callback,
38 FLAC__StreamDecoderWriteCallback write_callback,
39 FLAC__StreamDecoderMetadataCallback metadata_callback,
40 FLAC__StreamDecoderErrorCallback error_callback,
41 void *client_data
42 );
43 FLAC_API FLAC__bool (* f__stream_decoder_process_single)(FLAC__StreamDecoder *decoder);
44 FLAC_API FLAC__StreamDecoderState (* f__stream_decoder_get_state)(const FLAC__StreamDecoder *decoder);
45 // end of FLAC symbols
28 struct flac {
29 FLAC__StreamDecoder *decoder;
30 FLAC_API const char **FLAC__StreamDecoderErrorStatusString;
31 FLAC_API const char **FLAC__StreamDecoderStateString;
32 FLAC_API FLAC__StreamDecoder * (* FLAC__stream_decoder_new)(void);
33 FLAC_API FLAC__bool (* FLAC__stream_decoder_reset)(FLAC__StreamDecoder *decoder);
34 FLAC_API void (* FLAC__stream_decoder_delete)(FLAC__StreamDecoder *decoder);
35 FLAC_API FLAC__StreamDecoderInitStatus (* FLAC__stream_decoder_init_stream)(
36 FLAC__StreamDecoder *decoder,
37 FLAC__StreamDecoderReadCallback read_callback,
38 FLAC__StreamDecoderSeekCallback seek_callback,
39 FLAC__StreamDecoderTellCallback tell_callback,
40 FLAC__StreamDecoderLengthCallback length_callback,
41 FLAC__StreamDecoderEofCallback eof_callback,
42 FLAC__StreamDecoderWriteCallback write_callback,
43 FLAC__StreamDecoderMetadataCallback metadata_callback,
44 FLAC__StreamDecoderErrorCallback error_callback,
45 void *client_data
46 );
47 FLAC_API FLAC__bool (* FLAC__stream_decoder_process_single)(FLAC__StreamDecoder *decoder);
48 FLAC_API FLAC__StreamDecoderState (* FLAC__stream_decoder_get_state)(const FLAC__StreamDecoder *decoder);
49 };
50
51 static struct flac *f;
4652
4753 extern log_level loglevel;
4854
5056 extern struct buffer *outputbuf;
5157 extern struct streamstate stream;
5258 extern struct outputstate output;
53
54 struct decodestate decode;
59 extern struct decodestate decode;
5560
5661 #define LOCK_S pthread_mutex_lock(&streambuf->mutex)
5762 #define UNLOCK_S pthread_mutex_unlock(&streambuf->mutex)
5964 #define UNLOCK_O pthread_mutex_unlock(&outputbuf->mutex)
6065
6166 typedef u_int32_t frames_t;
62
63
64 static FLAC__StreamDecoder *decoder = NULL;
6567
6668 static FLAC__StreamDecoderReadStatus read_cb(const FLAC__StreamDecoder *decoder, FLAC__byte buffer[], size_t *want, void *client_data) {
6769 LOCK_S;
128130 }
129131
130132 static void error_cb(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data) {
131 LOG_INFO("flac error: %s", f__StreamDecoderErrorStatusString[status]);
133 LOG_INFO("flac error: %s", f->FLAC__StreamDecoderErrorStatusString[status]);
132134 }
133135
134136 static void flac_open(u8_t sample_size, u8_t sample_rate, u8_t channels, u8_t endianness) {
135 if (decoder) {
136 f__stream_decoder_reset(decoder);
137 if (f->decoder) {
138 f->FLAC__stream_decoder_reset(f->decoder);
137139 } else {
138 decoder = f__stream_decoder_new();
139 }
140 f__stream_decoder_init_stream(decoder, &read_cb, NULL, NULL, NULL, NULL, &write_cb, NULL, &error_cb, NULL);
140 f->decoder = f->FLAC__stream_decoder_new();
141 }
142 f->FLAC__stream_decoder_init_stream(f->decoder, &read_cb, NULL, NULL, NULL, NULL, &write_cb, NULL, &error_cb, NULL);
141143 }
142144
143145 static void flac_close(void) {
144 f__stream_decoder_delete(decoder);
145 decoder = NULL;
146 f->FLAC__stream_decoder_delete(f->decoder);
147 f->decoder = NULL;
146148 }
147149
148150 static void flac_decode(void) {
149 if (!f__stream_decoder_process_single(decoder)) {
150 FLAC__StreamDecoderState state = f__stream_decoder_get_state(decoder);
151 LOG_ERROR("flac error: %s", f__StreamDecoderStateString[state]);
151 if (!f->FLAC__stream_decoder_process_single(f->decoder)) {
152 FLAC__StreamDecoderState state = f->FLAC__stream_decoder_get_state(f->decoder);
153 LOG_ERROR("flac error: %s", f->FLAC__StreamDecoderStateString[state]);
152154 };
153155 }
154156
155157 static bool load_flac() {
156 void *handle = dlopen("libFLAC.so.8", RTLD_NOW);
158 void *handle = dlopen(LIBFLAC, RTLD_NOW);
157159 if (!handle) {
158160 LOG_WARN("dlerror: %s", dlerror());
159161 return false;
160162 }
161
162 f__StreamDecoderErrorStatusString = dlsym(handle, "FLAC__StreamDecoderErrorStatusString");
163 f__StreamDecoderStateString = dlsym(handle, "FLAC__StreamDecoderStateString");
164
165 f__stream_decoder_new = dlsym(handle, "FLAC__stream_decoder_new");
166 f__stream_decoder_reset = dlsym(handle, "FLAC__stream_decoder_reset");
167 f__stream_decoder_delete = dlsym(handle, "FLAC__stream_decoder_delete");
168
169 f__stream_decoder_init_stream = dlsym(handle, "FLAC__stream_decoder_init_stream");
170 f__stream_decoder_process_single = dlsym(handle, "FLAC__stream_decoder_process_single");
171 f__stream_decoder_get_state = dlsym(handle, "FLAC__stream_decoder_get_state");
163
164 f = malloc(sizeof(struct flac));
165
166 f->decoder = NULL;
167 f->FLAC__StreamDecoderErrorStatusString = dlsym(handle, "FLAC__StreamDecoderErrorStatusString");
168 f->FLAC__StreamDecoderStateString = dlsym(handle, "FLAC__StreamDecoderStateString");
169 f->FLAC__stream_decoder_new = dlsym(handle, "FLAC__stream_decoder_new");
170 f->FLAC__stream_decoder_reset = dlsym(handle, "FLAC__stream_decoder_reset");
171 f->FLAC__stream_decoder_delete = dlsym(handle, "FLAC__stream_decoder_delete");
172 f->FLAC__stream_decoder_init_stream = dlsym(handle, "FLAC__stream_decoder_init_stream");
173 f->FLAC__stream_decoder_process_single = dlsym(handle, "FLAC__stream_decoder_process_single");
174 f->FLAC__stream_decoder_get_state = dlsym(handle, "FLAC__stream_decoder_get_state");
172175
173176 char *err;
174177 if ((err = dlerror()) != NULL) {
176179 return false;
177180 }
178181
179 LOG_INFO("loaded libFLAC");
182 LOG_INFO("loaded "LIBFLAC);
180183 return true;
181184 }
182185
+70
-63
mad.c less more
2222 #include <mad.h>
2323 #include <dlfcn.h>
2424
25 // mad symbols to be dynamically loaded
26 void (* m_stream_init)(struct mad_stream *);
27 void (* m_frame_init)(struct mad_frame *);
28 void (* m_synth_init)(struct mad_synth *);
29 void (* m_frame_finish)(struct mad_frame *);
30 void (* m_stream_finish)(struct mad_stream *);
31 void (* m_stream_buffer)(struct mad_stream *, unsigned char const *, unsigned long);
32 int (* m_frame_decode)(struct mad_frame *, struct mad_stream *);
33 void (* m_synth_frame)(struct mad_synth *, struct mad_frame const *);
34 char const *(* m_stream_errorstr)(struct mad_stream const *);
35 // end of mad symbols
25 #define READBUF_SIZE 2048 // local buffer used by decoder: FIXME merge with any other decoders needing one?
26
27 #define LIBMAD "libmad.so.0"
28
29 struct mad {
30 u8_t *readbuf;
31 unsigned readbuf_len;
32 struct mad_stream stream;
33 struct mad_frame frame;
34 struct mad_synth synth;
35 // mad symbols to be dynamically loaded
36 void (* mad_stream_init)(struct mad_stream *);
37 void (* mad_frame_init)(struct mad_frame *);
38 void (* mad_synth_init)(struct mad_synth *);
39 void (* mad_frame_finish)(struct mad_frame *);
40 void (* mad_stream_finish)(struct mad_stream *);
41 void (* mad_stream_buffer)(struct mad_stream *, unsigned char const *, unsigned long);
42 int (* mad_frame_decode)(struct mad_frame *, struct mad_stream *);
43 void (* mad_synth_frame)(struct mad_synth *, struct mad_frame const *);
44 char const *(* mad_stream_errorstr)(struct mad_stream const *);
45 };
46
47 static struct mad *m;
3648
3749 extern log_level loglevel;
3850
4052 extern struct buffer *outputbuf;
4153 extern struct streamstate stream;
4254 extern struct outputstate output;
43
44 struct decodestate decode;
55 extern struct decodestate decode;
4556
4657 #define LOCK_S pthread_mutex_lock(&streambuf->mutex)
4758 #define UNLOCK_S pthread_mutex_unlock(&streambuf->mutex)
4859 #define LOCK_O pthread_mutex_lock(&outputbuf->mutex)
4960 #define UNLOCK_O pthread_mutex_unlock(&outputbuf->mutex)
50
51 #define READBUF_SIZE 2048
52
53 static struct mad_stream mad_stream;
54 static struct mad_frame mad_frame;
55 static struct mad_synth mad_synth;
56 static u8_t readbuf[READBUF_SIZE + MAD_BUFFER_GUARD];
57 static unsigned readbuf_len;
5861
5962 // based on libmad minimad.c scale
6063 static inline u32_t scale(mad_fixed_t sample) {
7275 LOCK_S;
7376 size_t bytes = min(_buf_used(streambuf), _buf_cont_read(streambuf));
7477
75 if (mad_stream.next_frame && readbuf_len) {
76 readbuf_len -= mad_stream.next_frame - readbuf;
77 memmove(readbuf, mad_stream.next_frame, readbuf_len);
78 }
79
80 bytes = min(bytes, READBUF_SIZE - readbuf_len);
81 memcpy(readbuf + readbuf_len, streambuf->readp, bytes);
82 readbuf_len += bytes;
78 if (m->stream.next_frame && m->readbuf_len) {
79 m->readbuf_len -= m->stream.next_frame - m->readbuf;
80 memmove(m->readbuf, m->stream.next_frame, m->readbuf_len);
81 }
82
83 bytes = min(bytes, READBUF_SIZE - m->readbuf_len);
84 memcpy(m->readbuf + m->readbuf_len, streambuf->readp, bytes);
85 m->readbuf_len += bytes;
8386 _buf_inc_readp(streambuf, bytes);
8487
8588 if (stream.state <= DISCONNECT && _buf_used(streambuf) == 0) {
86 memset(readbuf + readbuf_len, 0, MAD_BUFFER_GUARD);
87 readbuf_len += MAD_BUFFER_GUARD;
89 memset(m->readbuf + m->readbuf_len, 0, MAD_BUFFER_GUARD);
90 m->readbuf_len += MAD_BUFFER_GUARD;
8891 }
8992 UNLOCK_S;
9093
91 m_stream_buffer(&mad_stream, readbuf, readbuf_len);
94 m->mad_stream_buffer(&m->stream, m->readbuf, m->readbuf_len);
9295
9396 while (true) {
9497
95 if (m_frame_decode(&mad_frame, &mad_stream) == -1) {
96 if (mad_stream.error == MAD_ERROR_BUFLEN) {
98 if (m->mad_frame_decode(&m->frame, &m->stream) == -1) {
99 if (m->stream.error == MAD_ERROR_BUFLEN) {
97100 return;
98101 }
99 if (!MAD_RECOVERABLE(mad_stream.error)) {
100 LOG_WARN("mad_frame_decode error: %s", m_stream_errorstr(&mad_stream));
102 if (!MAD_RECOVERABLE(m->stream.error)) {
103 LOG_WARN("mad_frame_decode error: %s", m->mad_stream_errorstr(&m->stream));
101104 LOG_INFO("unrecoverable - stopping decoder");
102105 LOCK_O;
103106 decode.state = DECODE_COMPLETE;
104107 UNLOCK_O;
105108 } else {
106 LOG_DEBUG("mad_frame_decode error: %s", m_stream_errorstr(&mad_stream));
109 LOG_DEBUG("mad_frame_decode error: %s", m->mad_stream_errorstr(&m->stream));
107110 }
108111 return;
109112 };
110113
111 m_synth_frame(&mad_synth, &mad_frame);
114 m->mad_synth_frame(&m->synth, &m->frame);
112115
113116 LOCK_O;
114117
115118 if (decode.new_stream) {
116119 LOG_INFO("setting track_start");
117 output.next_sample_rate = mad_synth.pcm.samplerate;
120 output.next_sample_rate = m->synth.pcm.samplerate;
118121 output.track_start = outputbuf->writep;
119122 decode.new_stream = false;
120123 }
121124
122 if (mad_synth.pcm.length > _buf_space(outputbuf) / BYTES_PER_FRAME) {
125 if (m->synth.pcm.length > _buf_space(outputbuf) / BYTES_PER_FRAME) {
123126 LOG_WARN("too many samples - dropping samples");
124 mad_synth.pcm.length = _buf_space(outputbuf) / BYTES_PER_FRAME;
127 m->synth.pcm.length = _buf_space(outputbuf) / BYTES_PER_FRAME;
125128 }
126129
127 size_t frames = mad_synth.pcm.length;
128 s32_t *iptrl = mad_synth.pcm.samples[0];
129 s32_t *iptrr = mad_synth.pcm.samples[ mad_synth.pcm.channels - 1 ];
130 size_t frames = m->synth.pcm.length;
131 s32_t *iptrl = m->synth.pcm.samples[0];
132 s32_t *iptrr = m->synth.pcm.samples[ m->synth.pcm.channels - 1 ];
130133
131134 while (frames > 0) {
132135 size_t f = min(frames, _buf_cont_write(outputbuf) / BYTES_PER_FRAME);
140143 _buf_inc_writep(outputbuf, f * BYTES_PER_FRAME);
141144 }
142145
143 LOG_SDEBUG("write %u frames", mad_synth.pcm.length);
146 LOG_SDEBUG("write %u frames", m->synth.pcm.length);
144147
145148 UNLOCK_O;
146149 }
147150 }
148151
149152 static void mad_open(u8_t size, u8_t rate, u8_t chan, u8_t endianness) {
150 readbuf_len = 0;
151 m_stream_init(&mad_stream);
152 m_frame_init(&mad_frame);
153 m_synth_init(&mad_synth);
153 m->readbuf_len = 0;
154 m->mad_stream_init(&m->stream);
155 m->mad_frame_init(&m->frame);
156 m->mad_synth_init(&m->synth);
154157 }
155158
156159 static void mad_close(void) {
157 mad_synth_finish(&mad_synth);
158 m_frame_finish(&mad_frame);
159 m_stream_finish(&mad_stream);
160 mad_synth_finish(&m->synth);
161 m->mad_frame_finish(&m->frame);
162 m->mad_stream_finish(&m->stream);
160163 }
161164
162165 static bool load_mad() {
163 void *handle = dlopen("libmad.so.0", RTLD_NOW);
166 void *handle = dlopen(LIBMAD, RTLD_NOW);
164167 if (!handle) {
165168 LOG_WARN("dlerror: %s", dlerror());
166169 return false;
167170 }
168171
169 m_stream_init = dlsym(handle, "mad_stream_init");
170 m_frame_init = dlsym(handle, "mad_frame_init");
171 m_synth_init = dlsym(handle, "mad_synth_init");
172 m_frame_finish = dlsym(handle, "mad_frame_finish");
173 m_stream_finish = dlsym(handle, "mad_stream_finish");
174 m_stream_buffer = dlsym(handle, "mad_stream_buffer");
175 m_frame_decode = dlsym(handle, "mad_frame_decode");
176 m_synth_frame = dlsym(handle, "mad_synth_frame");
177 m_stream_errorstr = dlsym(handle, "mad_stream_errorstr");
172 m = malloc(sizeof(struct mad));
173 m->readbuf = malloc(READBUF_SIZE + MAD_BUFFER_GUARD);
174
175 m->readbuf_len = 0;
176 m->mad_stream_init = dlsym(handle, "mad_stream_init");
177 m->mad_frame_init = dlsym(handle, "mad_frame_init");
178 m->mad_synth_init = dlsym(handle, "mad_synth_init");
179 m->mad_frame_finish = dlsym(handle, "mad_frame_finish");
180 m->mad_stream_finish = dlsym(handle, "mad_stream_finish");
181 m->mad_stream_buffer = dlsym(handle, "mad_stream_buffer");
182 m->mad_frame_decode = dlsym(handle, "mad_frame_decode");
183 m->mad_synth_frame = dlsym(handle, "mad_synth_frame");
184 m->mad_stream_errorstr = dlsym(handle, "mad_stream_errorstr");
178185
179186 char *err;
180187 if ((err = dlerror()) != NULL) {
182189 return false;
183190 }
184191
185 LOG_INFO("loaded libmad");
192 LOG_INFO("loaded "LIBMAD);
186193 return true;
187194 }
188195
626626 loglevel = level;
627627
628628 LOG_INFO("init output");
629
630 output_buf_size = output_buf_size - (output_buf_size % BYTES_PER_FRAME);
629631 LOG_DEBUG("outputbuf size: %u", output_buf_size);
630632
631633 buf_init(outputbuf, output_buf_size);
2525 extern struct buffer *outputbuf;
2626 extern struct streamstate stream;
2727 extern struct outputstate output;
28
29 struct decodestate decode;
28 extern struct decodestate decode;
3029
3130 #define LOCK_S pthread_mutex_lock(&streambuf->mutex)
3231 #define UNLOCK_S pthread_mutex_unlock(&streambuf->mutex)
128127 struct codec *register_pcm(void) {
129128 static struct codec ret = {
130129 .id = 'p',
131 .types = "pcm,aif",
130 .types = "aif,pcm",
132131 .open = pcm_open,
133132 .close = pcm_close,
134133 .decode= pcm_decode,
4242 #define MAX_HEADER 2048
4343
4444 #define STREAM_THREAD_STACK_SIZE (PTHREAD_STACK_MIN * 4)
45 #define DECODE_THREAD_STACK_SIZE (PTHREAD_STACK_MIN * 4)
45 #define DECODE_THREAD_STACK_SIZE (PTHREAD_STACK_MIN * 8)
4646 #define OUTPUT_THREAD_STACK_SIZE (PTHREAD_STACK_MIN * 4)
4747
4848 #define ALSA_BUFFER_TIME 20000
100100 void buf_destroy(struct buffer *buf);
101101
102102 // slimproto.c
103 void slimproto(log_level level, const char *addr, u8_t mac[6]);
103 void slimproto(log_level level, const char *addr, u8_t mac[6], const char *name);
104104 void wake_controller(void);
105105
106106 // stream.c
185185 struct codec *register_flac(void);
186186 struct codec *register_pcm(void);
187187 struct codec *register_mad(void);
188 struct codec *register_vorbis(void);
0 /*
1 * Squeezelite - lightweight headless squeezeplay emulator for linux
2 *
3 * (c) Adrian Smith 2012, triode1@btinternet.com
4 *
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20 #include "squeezelite.h"
21
22 // automatically select between floating point (preferred) and fixed point libraries:
23 #define LIBVORBIS "libvorbisfile.so.3"
24 #define LIBTREMOR "libvorbisidec.so.1"
25
26 // NOTE: works with Tremor version here: http://svn.xiph.org/trunk/Tremor, not vorbisidec.1.0.2 currently in ubuntu
27
28 // we take common definations from <vorbis/vorbisfile.h> even though we can use tremor at run time
29 // tremor's OggVorbis_File struct is normally smaller so this is ok, but padding added to malloc in case it is bigger
30 #define OV_EXCLUDE_STATIC_CALLBACKS
31
32 #include <vorbis/vorbisfile.h>
33 #include <dlfcn.h>
34
35 struct vorbis {
36 OggVorbis_File *vf;
37 // vorbis symbols to be dynamically loaded - from either vorbisfile or vorbisidec (tremor) version of library
38 vorbis_info *(* ov_info)(OggVorbis_File *vf, int link);
39 int (* ov_clear)(OggVorbis_File *vf);
40 long (* ov_read)(OggVorbis_File *vf, char *buffer, int length, int bigendianp, int word, int sgned, int *bitstream);
41 long (* ov_read_tremor)(OggVorbis_File *vf, char *buffer, int length, int *bitstream);
42 int (* ov_open_callbacks)(void *datasource, OggVorbis_File *vf, const char *initial, long ibytes, ov_callbacks callbacks);
43 };
44
45 static struct vorbis *v;
46
47 extern log_level loglevel;
48
49 extern struct buffer *streambuf;
50 extern struct buffer *outputbuf;
51 extern struct streamstate stream;
52 extern struct outputstate output;
53 extern struct decodestate decode;
54
55 #define LOCK_S pthread_mutex_lock(&streambuf->mutex)
56 #define UNLOCK_S pthread_mutex_unlock(&streambuf->mutex)
57 #define LOCK_O pthread_mutex_lock(&outputbuf->mutex)
58 #define UNLOCK_O pthread_mutex_unlock(&outputbuf->mutex)
59
60 typedef u_int32_t frames_t;
61
62 static size_t _read(void *ptr, size_t size, size_t nmemb, void *datasource) {
63 LOCK_S;
64 size_t bytes = min(_buf_used(streambuf), _buf_cont_read(streambuf));
65 bytes = min(bytes, size * nmemb);
66
67 memcpy(ptr, streambuf->readp, bytes);
68 _buf_inc_readp(streambuf, bytes);
69 UNLOCK_S;
70
71 return bytes / size;
72 }
73
74 // these are needed for older versions of tremor, later versions and libvorbis allow NULL to be used
75 static int _seek(void *datasource, ogg_int64_t offset, int whence) { return -1; }
76 static int _close(void *datasource) { return 0; }
77 static long _tell(void *datasource) { return 0; }
78
79 static void vorbis_decode(void) {
80 static int channels;
81
82 LOCK_O;
83
84 if (decode.new_stream) {
85 ov_callbacks cbs = { .read_func = _read, .seek_func = NULL, .close_func = NULL, .tell_func = NULL };
86 if (v->ov_read_tremor) {
87 cbs.seek_func = _seek; cbs.close_func = _close; cbs.tell_func = _tell;
88 }
89
90 int err;
91 if ((err = v->ov_open_callbacks(streambuf, v->vf, NULL, 0, cbs)) < 0) {
92 LOG_WARN("open_callbacks error: %d", err);
93 decode.state = DECODE_COMPLETE;
94 UNLOCK_O;
95 return;
96 }
97
98 struct vorbis_info *info = v->ov_info(v->vf, -1);
99
100 LOG_INFO("setting track_start");
101 output.next_sample_rate = info->rate;
102 output.track_start = outputbuf->writep;
103 decode.new_stream = false;
104
105 channels = info->channels;
106
107 if (channels > 2) {
108 LOG_WARN("too many channels: %d", channels);
109 decode.state = DECODE_COMPLETE;
110 UNLOCK_O;
111 return;
112 }
113 }
114
115 frames_t frames = min(_buf_space(outputbuf), _buf_cont_write(outputbuf)) / BYTES_PER_FRAME;
116 int bytes = frames * 2 * channels; // samples returned are 16 bits
117
118 int stream, n;
119 // write the decoded frames into outputbuf even though they are 16 bits per sample, then unpack them
120 if (v->ov_read) {
121 n = v->ov_read(v->vf, (char *)outputbuf->writep, bytes, 0, 2, 1, &stream);
122 } else {
123 n = v->ov_read_tremor(v->vf, (char *)outputbuf->writep, bytes, &stream);
124 }
125
126 if (n > 0) {
127
128 frames = n / 2 / channels;
129 frames_t count = frames * channels;
130
131 // work backward to unpack samples to 4 bytes per sample
132 s16_t *iptr = (s16_t *)outputbuf->writep + count;
133 s32_t *optr = (s32_t *)outputbuf->writep + frames * 2;
134
135 if (channels == 2) {
136 while (count--) {
137 *--optr = *--iptr << 16;
138 }
139 } else if (channels == 1) {
140 while (count--) {
141 *--optr = *--iptr << 16;
142 *--optr = *iptr << 16;
143 }
144 }
145
146 _buf_inc_writep(outputbuf, frames * BYTES_PER_FRAME);
147
148 LOG_SDEBUG("wrote %u frames", frames);
149
150 } else if (n == 0) {
151
152 LOG_INFO("end of stream");
153 decode.state = DECODE_COMPLETE;
154
155 } else {
156
157 LOG_INFO("ov_read error: %d", n);
158 decode.state = DECODE_COMPLETE;
159 }
160
161 UNLOCK_O;
162 }
163
164 static void vorbis_open(u8_t size, u8_t rate, u8_t chan, u8_t endianness) {
165 if (!v->vf) {
166 v->vf = malloc(sizeof(OggVorbis_File) + 128); // add some padding as struct size may be larger
167 } else {
168 v->ov_clear(v->vf);
169 }
170 }
171
172 static void vorbis_close(void) {
173 v->ov_clear(v->vf);
174 free(v->vf);
175 v->vf = NULL;
176 }
177
178 static bool load_vorbis() {
179 bool tremor = false;
180 void *handle = dlopen(LIBVORBIS, RTLD_NOW);
181 if (!handle) {
182 handle = dlopen(LIBTREMOR, RTLD_NOW);
183 if (handle) {
184 tremor = true;
185 } else {
186 LOG_WARN("dlerror: %s", dlerror());
187 return false;
188 }
189 }
190
191 v = malloc(sizeof(struct vorbis));
192 v->vf = NULL;
193 v->ov_read = tremor ? NULL : dlsym(handle, "ov_read");
194 v->ov_read_tremor = tremor ? dlsym(handle, "ov_read") : NULL;
195 v->ov_info = dlsym(handle, "ov_info");
196 v->ov_clear = dlsym(handle, "ov_clear");
197 v->ov_open_callbacks = dlsym(handle, "ov_open_callbacks");
198
199 char *err;
200 if ((err = dlerror()) != NULL) {
201 LOG_WARN("dlerror: %s", err);
202 return false;
203 }
204
205 LOG_INFO("loaded %s", tremor ? LIBTREMOR : LIBVORBIS);
206 return true;
207 }
208
209 struct codec *register_vorbis(void) {
210 static struct codec ret = {
211 .id = 'o',
212 .types = "ogg",
213 .open = vorbis_open,
214 .close = vorbis_close,
215 .decode= vorbis_decode,
216 .min_space = 20480,
217 .min_read_bytes = 2048,
218 };
219
220 if (!load_vorbis()) {
221 return NULL;
222 }
223
224 return &ret;
225 }