summaryrefslogtreecommitdiff
path: root/apps/codecs
diff options
context:
space:
mode:
authorLinus Nielsen Feltzing <linus@haxx.se>2005-07-05 08:43:36 +0000
committerLinus Nielsen Feltzing <linus@haxx.se>2005-07-05 08:43:36 +0000
commiteaf8b2d76d3f69b919ff1c3a55e7ad2f07456bd4 (patch)
tree74c9b4d7e08b2378b499d63f13c8ea70f74f8351 /apps/codecs
parenta10bb59331b5e48adf307c4538333e9a4e036db9 (diff)
downloadrockbox-eaf8b2d76d3f69b919ff1c3a55e7ad2f07456bd4.tar.gz
rockbox-eaf8b2d76d3f69b919ff1c3a55e7ad2f07456bd4.zip
Patch #1232549 by Ryan Jackson, adds seeking and comments to Vorbis playback
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7025 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/codecs')
-rw-r--r--apps/codecs/lib/xxx2wav.c6
-rw-r--r--apps/codecs/vorbis.c149
2 files changed, 125 insertions, 30 deletions
diff --git a/apps/codecs/lib/xxx2wav.c b/apps/codecs/lib/xxx2wav.c
index 1323e07475..b437ca56db 100644
--- a/apps/codecs/lib/xxx2wav.c
+++ b/apps/codecs/lib/xxx2wav.c
@@ -91,11 +91,7 @@ int memcmp(const void *s1, const void *s2, size_t n) {
91} 91}
92 92
93void* memchr(const void *s, int c, size_t n) { 93void* memchr(const void *s, int c, size_t n) {
94 /* TO DO: Implement for Tremor */ 94 return(local_rb->memchr(s,c,n));
95 (void)s;
96 (void)c;
97 (void)n;
98 return(NULL);
99} 95}
100 96
101void* memmove(const void *s1, const void *s2, size_t n) { 97void* memmove(const void *s1, const void *s2, size_t n) {
diff --git a/apps/codecs/vorbis.c b/apps/codecs/vorbis.c
index 9afeb053e1..946f2f9377 100644
--- a/apps/codecs/vorbis.c
+++ b/apps/codecs/vorbis.c
@@ -20,6 +20,7 @@
20#include "codecs.h" 20#include "codecs.h"
21 21
22#include "Tremor/ivorbisfile.h" 22#include "Tremor/ivorbisfile.h"
23#include "Tremor/ogg.h"
23#include "playback.h" 24#include "playback.h"
24#include "dsp.h" 25#include "dsp.h"
25#include "lib/codeclib.h" 26#include "lib/codeclib.h"
@@ -51,15 +52,30 @@ size_t read_handler(void *ptr, size_t size, size_t nmemb, void *datasource)
51 return rb->read_filebuf(ptr, nmemb*size); 52 return rb->read_filebuf(ptr, nmemb*size);
52} 53}
53 54
54int seek_handler(void *datasource, ogg_int64_t offset, int whence) 55int initial_seek_handler(void *datasource, ogg_int64_t offset, int whence) {
55{
56 /* We are not seekable at the moment */
57 (void)datasource; 56 (void)datasource;
58 (void)offset; 57 (void)offset;
59 (void)whence; 58 (void)whence;
60 return -1; 59 return -1;
61} 60}
62 61
62int seek_handler(void *datasource, ogg_int64_t offset, int whence)
63{
64 (void)datasource;
65
66 if ( whence == SEEK_CUR ) {
67 offset += rb->curpos;
68 } else if ( whence == SEEK_END ) {
69 offset += rb->filesize;
70 }
71
72 if (rb->seek_buffer(offset)) {
73 return 0;
74 }
75
76 return -1;
77}
78
63int close_handler(void *datasource) 79int close_handler(void *datasource)
64{ 80{
65 (void)datasource; 81 (void)datasource;
@@ -93,22 +109,26 @@ enum codec_status codec_start(struct codec_api* api)
93 long n; 109 long n;
94 int current_section; 110 int current_section;
95 int eof; 111 int eof;
112 ogg_int64_t vf_offsets[2];
113 ogg_int64_t vf_dataoffsets;
114 ogg_uint32_t vf_serialnos;
115 ogg_int64_t vf_pcmlengths[2];
116 int current_stereo_mode = -1;
96 117
97 TEST_CODEC_API(api); 118 TEST_CODEC_API(api);
98 119
99 /* if you are using a global api pointer, don't forget to copy it! 120 /* if you are using a global api pointer, don't forget to copy it!
100 otherwise you will get lovely "I04: IllInstr" errors... :-) */ 121 otherwise you will get lovely "I04: IllInstr" errors... :-) */
101 rb = api; 122 rb = api;
102 123
103#ifdef USE_IRAM 124 #ifdef USE_IRAM
104 rb->memcpy(iramstart, iramcopy, iramend-iramstart); 125 rb->memcpy(iramstart, iramcopy, iramend-iramstart);
105#endif 126 #endif
106 127
107 rb->configure(CODEC_SET_FILEBUF_LIMIT, (int *)(1024*1024*2)); 128 rb->configure(CODEC_SET_FILEBUF_LIMIT, (int *)(1024*1024*2));
108 rb->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*64)); 129 rb->configure(CODEC_SET_FILEBUF_CHUNKSIZE, (int *)(1024*64));
109 130
110 rb->configure(DSP_DITHER, (bool *)false); 131 rb->configure(DSP_DITHER, (bool *)false);
111 rb->configure(DSP_SET_STEREO_MODE, (int *)STEREO_INTERLEAVED);
112 rb->configure(DSP_SET_SAMPLE_DEPTH, (int *)(16)); 132 rb->configure(DSP_SET_SAMPLE_DEPTH, (int *)(16));
113 133
114/* We need to flush reserver memory every track load. */ 134/* We need to flush reserver memory every track load. */
@@ -129,44 +149,123 @@ enum codec_status codec_start(struct codec_api* api)
129 149
130 /* Create a decoder instance */ 150 /* Create a decoder instance */
131 callbacks.read_func=read_handler; 151 callbacks.read_func=read_handler;
132 callbacks.seek_func=seek_handler; 152 callbacks.seek_func=initial_seek_handler;
133 callbacks.tell_func=tell_handler; 153 callbacks.tell_func=tell_handler;
134 callbacks.close_func=close_handler; 154 callbacks.close_func=close_handler;
135 155
156 /* Open a non-seekable stream */
136 error=ov_open_callbacks(rb,&vf,NULL,0,callbacks); 157 error=ov_open_callbacks(rb,&vf,NULL,0,callbacks);
137 158
159 /* If the non-seekable open was successful, we need to supply the missing
160 * data to make it seekable. This is a hack, but it's reasonable since we
161 * don't want to read the whole file into the buffer before we start
162 * playing. Using Tremor's seekable open routine would cause us to do
163 * this, so we pretend not to be seekable at first. Then we fill in the
164 * missing fields of vf with 1) information in rb->id3, and 2) info
165 * obtained by Tremor in the above ov_open call.
166 *
167 * Note that this assumes there is only ONE logical Vorbis bitstream in our
168 * physical Ogg bitstream. This is verified in metadata.c, well before we
169 * get here.
170 */
171 if ( !error ) {
172 //rb->logf("no error");
173 /* FIXME Should these be dynamically allocated? */
174 vf.offsets = vf_offsets;
175 vf.dataoffsets = &vf_dataoffsets;
176 vf.serialnos = &vf_serialnos;
177 vf.pcmlengths = vf_pcmlengths;
178
179 vf.offsets[0] = 0;
180 vf.offsets[1] = rb->id3->filesize;
181 vf.dataoffsets[0] = vf.offset;
182 vf.pcmlengths[0] = 0;
183 vf.pcmlengths[1] = rb->id3->samples;
184 vf.serialnos[0] = vf.current_serialno;
185 vf.callbacks.seek_func=seek_handler;
186 vf.seekable = 1;
187 vf.offset = 58; /* length of Ogg header */
188 vf.end = rb->id3->filesize;
189 vf.ready_state = OPENED;
190 vf.links = 1;
191
192 /*if(ov_raw_seek(&vf,0)){
193 rb->logf("seek err");
194 }
195 */
196
197 } else {
198 //rb->logf("ov_open: %d", error);
199 }
200
138 vi=ov_info(&vf,-1); 201 vi=ov_info(&vf,-1);
139 202
140 if (vi==NULL) { 203 if (vi==NULL) {
141 // rb->splash(HZ*2, true, "Vorbis Error"); 204 //rb->splash(HZ*2, true, "Vorbis Error");
142 return CODEC_ERROR; 205 return CODEC_ERROR;
143 } 206 }
144 207
208 rb->configure(DSP_SET_FREQUENCY, (int *)rb->id3->frequency);
209
210 if (vi->channels == 2) {
211 if (current_stereo_mode != STEREO_INTERLEAVED) {
212 rb->configure(DSP_SET_STEREO_MODE, (int *)STEREO_INTERLEAVED);
213 current_stereo_mode = STEREO_INTERLEAVED;
214 }
215 } else if (vi->channels == 1) {
216 if (current_stereo_mode != STEREO_MONO) {
217 rb->configure(DSP_SET_STEREO_MODE, (int *)STEREO_MONO);
218 current_stereo_mode = STEREO_MONO;
219 }
220 }
221
145 eof=0; 222 eof=0;
223 rb->yield();
146 while (!eof) { 224 while (!eof) {
225 if (rb->stop_codec || rb->reload_codec)
226 break ;
227
228 if (rb->seek_time) {
229
230 if (ov_time_seek(&vf, rb->seek_time)) {
231 //rb->logf("ov_time_seek failed");
232 }
233 rb->seek_time = 0;
234 }
235
147 /* Read host-endian signed 16 bit PCM samples */ 236 /* Read host-endian signed 16 bit PCM samples */
148 n=ov_read(&vf,pcmbuf,sizeof(pcmbuf),&current_section); 237 n=ov_read(&vf,pcmbuf,sizeof(pcmbuf),&current_section);
149 238
150 if (n==0) { 239 if (n==0) {
151 eof=1; 240 eof=1;
152 } 241 } else if (n < 0) {
153 else if (n < 0) {
154 DEBUGF("Error decoding frame\n"); 242 DEBUGF("Error decoding frame\n");
155 } else { 243 } else {
156 rb->yield(); 244 while (!rb->audiobuffer_insert(pcmbuf, n)) {
157 if (rb->stop_codec || rb->reload_codec)
158 break ;
159
160 while (!rb->audiobuffer_insert(pcmbuf, n))
161 rb->yield(); 245 rb->yield();
162 246 if ( rb->seek_time ) {
163 rb->set_elapsed(ov_time_tell(&vf)); 247 /* Hmmm, a seek was requested. Throw out the
248 * buffer and go back to the top of the loop.
249 */
250 break;
251 }
252 }
253 if ( !rb->seek_time ) {
254 rb->set_elapsed(ov_time_tell(&vf));
255 rb->yield();
256 }
164 } 257 }
165 } 258 }
166
167 if (rb->request_next_track())
168 goto next_track;
169 259
260 if (rb->request_next_track()) {
261 /* Clean things up for the next track */
262 vf.dataoffsets = NULL;
263 vf.offsets = NULL;
264 vf.serialnos = NULL;
265 vf.pcmlengths = NULL;
266 ov_clear(&vf);
267 goto next_track;
268 }
269
170 return CODEC_OK; 270 return CODEC_OK;
171} 271}
172