Skip to content

Commit 43ec90d

Browse files
committed
CodecVorbis extend logging
1 parent 81d83bb commit 43ec90d

File tree

2 files changed

+139
-51
lines changed

2 files changed

+139
-51
lines changed
Lines changed: 135 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
11
#pragma once
2-
#include "AudioToolsConfig.h"
32
#include "AudioTools/AudioCodecs/AudioCodecsBase.h"
3+
#include "AudioToolsConfig.h"
44
#include "vorbis-tremor.h"
55

66
// #include "AudioTools/AudioCodecs/ContainerOgg.h"
77
// #include "ivorbiscodec.h"
88
// #include "ivorbisfile.h"
99

10-
1110
namespace audio_tools {
1211

1312
#ifndef VARBIS_MAX_READ_SIZE
14-
# define VARBIS_MAX_READ_SIZE 1024
13+
#define VARBIS_MAX_READ_SIZE 1024
1514
#endif
1615

1716
#define VORBIS_HEADER_OPEN_LIMIT 1024
@@ -25,7 +24,7 @@ namespace audio_tools {
2524
* @copyright GPLv3
2625
*/
2726
class VorbisDecoder : public StreamingDecoder {
28-
public:
27+
public:
2928
VorbisDecoder() = default;
3029

3130
/// Destroy the VorbisDecoder object
@@ -39,27 +38,41 @@ class VorbisDecoder : public StreamingDecoder {
3938
bool begin() override {
4039
LOGI("begin");
4140

41+
// Ensure we start with clean state
42+
if (active) {
43+
LOGW("Decoder already active, calling end() first");
44+
end();
45+
}
46+
4247
callbacks.read_func = read_func;
4348
callbacks.seek_func = seek_func;
4449
callbacks.close_func = nullptr;
4550
callbacks.tell_func = tell_func;
4651

47-
if (p_input->available()>=VORBIS_HEADER_OPEN_LIMIT){
48-
ovOpen();
52+
assert(p_input != nullptr);
53+
if (p_input->available() < VORBIS_HEADER_OPEN_LIMIT) {
54+
delay(delay_wait_for_data_ms);
4955
}
56+
LOGI("available: %d", p_input->available());
5057

51-
active = true;
52-
is_first = true;
53-
return true;
58+
is_ov_open = ovOpen();
59+
LOGI("ovOpen result: %d", is_ov_open);
60+
61+
active = is_ov_open;
62+
return is_ov_open;
5463
}
5564

5665
/// Releases the reserved memory
5766
void end() override {
5867
LOGI("end");
68+
if (is_ov_open && active) {
69+
ov_clear(&file);
70+
LOGI("ov_clear completed");
71+
}
5972
is_ov_open = false;
6073
is_first = true;
61-
if (active) ov_clear(&file);
6274
active = false;
75+
pcm.clear(); // Free the PCM buffer
6376
}
6477

6578
/// Provides the last available MP3FrameInfo
@@ -69,50 +82,62 @@ class VorbisDecoder : public StreamingDecoder {
6982
virtual operator bool() override { return active; }
7083

7184
virtual bool copy() override {
72-
// wait for data
73-
if (is_first){
74-
// wait for some data
75-
if(p_input->available() < VORBIS_HEADER_OPEN_LIMIT){
76-
delay(500);
77-
// LOGW("Not enough data available: %d", p_input->available());
78-
// return false;
79-
}
80-
LOGI("available: %d", p_input->available());
81-
is_first = false;
82-
}
85+
TRACED();
8386

8487
// open if not already done
85-
if (!is_ov_open){
88+
if (!is_ov_open) {
8689
if (!ovOpen()) {
87-
LOGE("not open");
90+
LOGE("Failed to open Vorbis stream");
8891
return false;
8992
}
9093
}
9194

92-
if(pcm.data()==nullptr){
93-
LOGE("Not enough memory");
95+
// Defensive checks before calling Vorbis functions
96+
if (pcm.data() == nullptr) {
97+
LOGE("PCM buffer is null - memory allocation failed");
98+
return false;
99+
}
100+
101+
if (pcm.size() == 0) {
102+
LOGE("PCM buffer size is 0");
103+
return false;
104+
}
105+
106+
// Additional sanity check for the file structure
107+
if (!active) {
108+
LOGE("Decoder is not active");
94109
return false;
95110
}
96111

97-
// convert to pcm
112+
LOGD("ov_read: buffer size %d", pcm.size());
113+
bitstream = 0;
114+
115+
// Call ov_read with additional error checking
98116
long result = ov_read(&file, (char *)pcm.data(), pcm.size(), &bitstream);
99-
LOGI("copy: %ld", result);
117+
LOGI("copy result: %d", (int)result);
118+
100119
if (result > 0) {
101120
AudioInfo current = currentInfo();
102121
if (current != cfg) {
103122
cfg = current;
104123
cfg.logInfo();
105124
notifyAudioChange(cfg);
106125
}
107-
p_print->write(pcm.data(), result);
126+
127+
if (p_print != nullptr) {
128+
p_print->write(pcm.data(), result);
129+
} else {
130+
LOGE("Output stream is null");
131+
return false;
132+
}
108133
delay(1);
109134
return true;
110135
} else {
111-
if (result==0 || result==-3){
136+
if (result == 0 || result == -3) {
112137
// data interruption
113-
LOGD("copy: %ld - %s", result, readError(result));
138+
LOGD("copy: %d - %s", (int)result, readError(result));
114139
} else {
115-
LOGE("copy: %ld - %s", result, readError(result));
140+
LOGE("copy: %d - %s", (int)result, readError(result));
116141
}
117142
delay(delay_on_no_data_ms);
118143
return false;
@@ -123,54 +148,83 @@ class VorbisDecoder : public StreamingDecoder {
123148
const char *mime() override { return "audio/vorbis+ogg"; }
124149

125150
/// Defines the delay when there is no data
126-
void setDelayOnNoData(size_t delay) { delay_on_no_data_ms = delay; }
151+
void setDelayOnNoData(size_t delay) { delay_on_no_data_ms = delay; }
152+
153+
/// Defines the delay to wait if there is not enough data to open the decoder
154+
void setWaitForData(size_t wait) { delay_wait_for_data_ms = wait; }
127155

128156
/// Defines the default read size
129-
void setReadSize(size_t size) { max_read_size = size; }
157+
void setReadSize(size_t size) {
158+
max_read_size = size;
159+
// Ensure we don't set an unreasonably large size
160+
if (max_read_size > 8192) {
161+
LOGW("Read size %zu is very large, consider smaller buffer",
162+
max_read_size);
163+
}
164+
}
130165

131-
protected:
166+
protected:
132167
AudioInfo cfg;
133-
Vector<uint8_t> pcm;
168+
Vector<uint8_t> pcm{0};
134169
OggVorbis_File file;
135170
ov_callbacks callbacks;
136-
int bitstream;
171+
int bitstream = 0;
137172
size_t delay_on_no_data_ms = 100;
173+
size_t delay_wait_for_data_ms = 500;
138174
size_t max_read_size = VARBIS_MAX_READ_SIZE;
139175
bool active = false;
140176
bool is_first = true;
141177
bool is_ov_open = false;
142178

143-
bool ovOpen(){
179+
bool ovOpen() {
144180
pcm.resize(max_read_size);
181+
checkMemory(true);
145182
int rc = ov_open_callbacks(this, &file, nullptr, 0, callbacks);
146-
if (rc<0){
147-
LOGE("ov_open_callbacks: %d", rc);
183+
if (rc < 0) {
184+
LOGE("ov_open_callbacks failed with error %d: %s", rc, getOpenError(rc));
148185
} else {
186+
LOGI("ov_open_callbacks succeeded");
149187
is_ov_open = true;
150188
}
189+
checkMemory(true);
151190
return is_ov_open;
152191
}
153192

154193
AudioInfo currentInfo() {
155194
AudioInfo result;
195+
if (!is_ov_open) {
196+
LOGE("Cannot get audio info - stream not open");
197+
return result;
198+
}
199+
156200
vorbis_info *info = ov_info(&file, -1);
201+
if (info == nullptr) {
202+
LOGE("ov_info returned null pointer");
203+
return result;
204+
}
205+
157206
result.sample_rate = info->rate;
158207
result.channels = info->channels;
159208
result.bits_per_sample = 16;
209+
210+
LOGD("Audio info - rate: %d, channels: %d", info->rate, info->channels);
160211
return result;
161212
}
162213

163214
virtual size_t readBytes(uint8_t *data, size_t len) override {
164-
size_t read_size = min(len,(size_t)max_read_size);
215+
size_t read_size = min(len, (size_t)max_read_size);
165216
size_t result = p_input->readBytes((uint8_t *)data, read_size);
166-
LOGD("readBytes: %zu",result);
217+
LOGD("readBytes: %zu", result);
167218
return result;
168219
}
169220

170221
static size_t read_func(void *ptr, size_t size, size_t nmemb,
171222
void *datasource) {
172223
VorbisDecoder *self = (VorbisDecoder *)datasource;
173-
return self->readBytes((uint8_t *)ptr, size * nmemb);
224+
assert(datasource != nullptr);
225+
size_t result = self->readBytes((uint8_t *)ptr, size * nmemb);
226+
LOGD("read_func: %d -> %d", size * nmemb, (int)result);
227+
return result;
174228
}
175229

176230
static int seek_func(void *datasource, ogg_int64_t offset, int whence) {
@@ -189,22 +243,54 @@ class VorbisDecoder : public StreamingDecoder {
189243
// return 0;
190244
// }
191245

192-
const char* readError(long error){
193-
if (error>=0){
246+
const char *readError(long error) {
247+
if (error >= 0) {
194248
return "OK";
195249
}
196-
switch(error){
250+
switch (error) {
197251
case OV_HOLE:
198252
return "Interruption in the data";
199253
case OV_EBADLINK:
200-
return "Invalid stream section ";
254+
return "Invalid stream section";
255+
case OV_EREAD:
256+
return "Read error";
257+
case OV_EFAULT:
258+
return "Internal fault";
259+
case OV_EIMPL:
260+
return "Unimplemented feature";
201261
case OV_EINVAL:
202-
return "Invalid header";
262+
return "Invalid argument";
263+
case OV_ENOTVORBIS:
264+
return "Not a Vorbis file";
265+
case OV_EBADHEADER:
266+
return "Invalid Vorbis header";
267+
case OV_EVERSION:
268+
return "Vorbis version mismatch";
269+
case OV_ENOSEEK:
270+
return "Stream not seekable";
203271
default:
204-
return "N/A";
272+
return "Unknown error";
205273
}
206274
}
207275

276+
const char *getOpenError(int error) {
277+
switch (error) {
278+
case 0:
279+
return "Success";
280+
case OV_EREAD:
281+
return "Read from media error";
282+
case OV_ENOTVORBIS:
283+
return "Not Vorbis data";
284+
case OV_EVERSION:
285+
return "Vorbis version mismatch";
286+
case OV_EBADHEADER:
287+
return "Invalid Vorbis bitstream header";
288+
case OV_EFAULT:
289+
return "Internal logic fault";
290+
default:
291+
return "Unknown open error";
292+
}
293+
}
208294
};
209295

210-
} // namespace audio_tools
296+
} // namespace audio_tools

src/AudioTools/AudioCodecs/StreamingDecoder.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -413,8 +413,6 @@ class MultiStreamingDecoder : public StreamingDecoder {
413413
*/
414414
void setInput(Stream& inStream) {
415415
StreamingDecoder::setInput(inStream);
416-
// in some cases we use the buffered stream as input
417-
buffered_stream.setStream(inStream);
418416
}
419417

420418
/**
@@ -578,6 +576,7 @@ class MultiStreamingDecoder : public StreamingDecoder {
578576
}
579577

580578
// Initialize the selected decoder and mark it as active
579+
LOGI("available: %d", p_data_source->available());
581580
assert(p_data_source != nullptr);
582581
actual_decoder.decoder->setInput(*p_data_source);
583582
actual_decoder.decoder->clearNotifyAudioChange();
@@ -779,6 +778,9 @@ class MultiStreamingDecoder : public StreamingDecoder {
779778
} else {
780779
// Option 2: Auto-detect MIME type by analyzing stream content
781780
// Redirect the decoder to use the buffered stream
781+
// we use the buffered stream as input
782+
assert(p_input != nullptr);
783+
buffered_stream.setStream(*p_input);
782784
buffered_stream.resize(DEFAULT_BUFFER_SIZE);
783785
p_data_source = &buffered_stream;
784786

0 commit comments

Comments
 (0)