diff options
author | Linus Nielsen Feltzing <linus@haxx.se> | 2005-07-05 08:43:36 +0000 |
---|---|---|
committer | Linus Nielsen Feltzing <linus@haxx.se> | 2005-07-05 08:43:36 +0000 |
commit | eaf8b2d76d3f69b919ff1c3a55e7ad2f07456bd4 (patch) | |
tree | 74c9b4d7e08b2378b499d63f13c8ea70f74f8351 /apps/codecs | |
parent | a10bb59331b5e48adf307c4538333e9a4e036db9 (diff) | |
download | rockbox-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.c | 6 | ||||
-rw-r--r-- | apps/codecs/vorbis.c | 149 |
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 | ||
93 | void* memchr(const void *s, int c, size_t n) { | 93 | void* 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 | ||
101 | void* memmove(const void *s1, const void *s2, size_t n) { | 97 | void* 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 | ||
54 | int seek_handler(void *datasource, ogg_int64_t offset, int whence) | 55 | int 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 | ||
62 | int 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 | |||
63 | int close_handler(void *datasource) | 79 | int 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),¤t_section); | 237 | n=ov_read(&vf,pcmbuf,sizeof(pcmbuf),¤t_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 | |||