diff options
Diffstat (limited to 'apps/codecs')
39 files changed, 1384 insertions, 1500 deletions
diff --git a/apps/codecs/a52.c b/apps/codecs/a52.c index 00fdeea309..4cd293e37f 100644 --- a/apps/codecs/a52.c +++ b/apps/codecs/a52.c | |||
@@ -116,27 +116,31 @@ static void a52_decode_data(uint8_t *start, uint8_t *end) | |||
116 | } | 116 | } |
117 | 117 | ||
118 | /* this is the codec entry point */ | 118 | /* this is the codec entry point */ |
119 | enum codec_status codec_main(void) | 119 | enum codec_status codec_main(enum codec_entry_call_reason reason) |
120 | { | ||
121 | if (reason == CODEC_LOAD) { | ||
122 | /* Generic codec initialisation */ | ||
123 | ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); | ||
124 | ci->configure(DSP_SET_SAMPLE_DEPTH, 28); | ||
125 | } | ||
126 | else if (reason == CODEC_UNLOAD) { | ||
127 | if (state) | ||
128 | a52_free(state); | ||
129 | } | ||
130 | |||
131 | return CODEC_OK; | ||
132 | } | ||
133 | |||
134 | /* this is called for each file to process */ | ||
135 | enum codec_status codec_run(void) | ||
120 | { | 136 | { |
121 | size_t n; | 137 | size_t n; |
122 | unsigned char *filebuf; | 138 | unsigned char *filebuf; |
123 | int sample_loc; | 139 | int sample_loc; |
124 | int retval; | 140 | intptr_t param; |
125 | 141 | ||
126 | /* Generic codec initialisation */ | 142 | if (codec_init()) |
127 | ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); | 143 | return CODEC_ERROR; |
128 | ci->configure(DSP_SET_SAMPLE_DEPTH, 28); | ||
129 | |||
130 | next_track: | ||
131 | retval = CODEC_OK; | ||
132 | |||
133 | if (codec_init()) { | ||
134 | retval = CODEC_ERROR; | ||
135 | goto exit; | ||
136 | } | ||
137 | |||
138 | if (codec_wait_taginfo() != 0) | ||
139 | goto request_next_track; | ||
140 | 144 | ||
141 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); | 145 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); |
142 | codec_set_replaygain(ci->id3); | 146 | codec_set_replaygain(ci->id3); |
@@ -153,15 +157,18 @@ next_track: | |||
153 | } | 157 | } |
154 | } | 158 | } |
155 | else { | 159 | else { |
160 | ci->seek_buffer(ci->id3->first_frame_offset); | ||
156 | samplesdone = 0; | 161 | samplesdone = 0; |
157 | } | 162 | } |
158 | 163 | ||
159 | while (1) { | 164 | while (1) { |
160 | if (ci->stop_codec || ci->new_track) | 165 | enum codec_command_action action = ci->get_command(¶m); |
166 | |||
167 | if (action == CODEC_ACTION_HALT) | ||
161 | break; | 168 | break; |
162 | 169 | ||
163 | if (ci->seek_time) { | 170 | if (action == CODEC_ACTION_SEEK_TIME) { |
164 | sample_loc = (ci->seek_time - 1)/1000 * ci->id3->frequency; | 171 | sample_loc = param/1000 * ci->id3->frequency; |
165 | 172 | ||
166 | if (ci->seek_buffer((sample_loc/A52_SAMPLESPERFRAME)*ci->id3->bytesperframe)) { | 173 | if (ci->seek_buffer((sample_loc/A52_SAMPLESPERFRAME)*ci->id3->bytesperframe)) { |
167 | samplesdone = sample_loc; | 174 | samplesdone = sample_loc; |
@@ -179,11 +186,5 @@ next_track: | |||
179 | ci->advance_buffer(n); | 186 | ci->advance_buffer(n); |
180 | } | 187 | } |
181 | 188 | ||
182 | request_next_track: | 189 | return CODEC_OK; |
183 | if (ci->request_next_track()) | ||
184 | goto next_track; | ||
185 | |||
186 | exit: | ||
187 | a52_free(state); | ||
188 | return retval; | ||
189 | } | 190 | } |
diff --git a/apps/codecs/a52_rm.c b/apps/codecs/a52_rm.c index f5e4923292..c1930aa7b4 100644 --- a/apps/codecs/a52_rm.c +++ b/apps/codecs/a52_rm.c | |||
@@ -124,36 +124,44 @@ static void a52_decode_data(uint8_t *start, uint8_t *end) | |||
124 | } | 124 | } |
125 | } | 125 | } |
126 | 126 | ||
127 | |||
128 | /* this is the codec entry point */ | 127 | /* this is the codec entry point */ |
129 | enum codec_status codec_main(void) | 128 | enum codec_status codec_main(enum codec_entry_call_reason reason) |
129 | { | ||
130 | if (reason == CODEC_LOAD) { | ||
131 | /* Generic codec initialisation */ | ||
132 | ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); | ||
133 | ci->configure(DSP_SET_SAMPLE_DEPTH, 28); | ||
134 | } | ||
135 | else if (reason == CODEC_UNLOAD) { | ||
136 | if (state) | ||
137 | a52_free(state); | ||
138 | } | ||
139 | |||
140 | return CODEC_OK; | ||
141 | } | ||
142 | |||
143 | /* this is called for each file to process */ | ||
144 | enum codec_status codec_run(void) | ||
130 | { | 145 | { |
131 | size_t n; | 146 | size_t n; |
132 | uint8_t *filebuf; | 147 | uint8_t *filebuf; |
133 | int retval, consumed, packet_offset; | 148 | int consumed, packet_offset; |
134 | int playback_on = -1; | 149 | int playback_on = -1; |
135 | size_t resume_offset; | 150 | size_t resume_offset; |
136 | 151 | intptr_t param; | |
137 | /* Generic codec initialisation */ | 152 | enum codec_command_action action = CODEC_ACTION_NULL; |
138 | ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); | ||
139 | ci->configure(DSP_SET_SAMPLE_DEPTH, 28); | ||
140 | |||
141 | next_track: | ||
142 | retval = CODEC_OK; | ||
143 | 153 | ||
144 | if (codec_init()) { | 154 | if (codec_init()) { |
145 | retval = CODEC_ERROR; | 155 | return CODEC_ERROR; |
146 | goto exit; | ||
147 | } | 156 | } |
148 | 157 | ||
149 | if (codec_wait_taginfo() != 0) | ||
150 | goto request_next_track; | ||
151 | |||
152 | resume_offset = ci->id3->offset; | 158 | resume_offset = ci->id3->offset; |
153 | 159 | ||
154 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); | 160 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); |
155 | codec_set_replaygain(ci->id3); | 161 | codec_set_replaygain(ci->id3); |
156 | 162 | ||
163 | ci->seek_buffer(ci->id3->first_frame_offset); | ||
164 | |||
157 | /* Intializations */ | 165 | /* Intializations */ |
158 | state = a52_init(0); | 166 | state = a52_init(0); |
159 | ci->memset(&rmctx,0,sizeof(RMContext)); | 167 | ci->memset(&rmctx,0,sizeof(RMContext)); |
@@ -165,26 +173,34 @@ next_track: | |||
165 | resume_offset -= rmctx.data_offset + DATA_HEADER_SIZE; | 173 | resume_offset -= rmctx.data_offset + DATA_HEADER_SIZE; |
166 | /* put number of subpackets to skip in resume_offset */ | 174 | /* put number of subpackets to skip in resume_offset */ |
167 | resume_offset /= (rmctx.block_align + PACKET_HEADER_SIZE); | 175 | resume_offset /= (rmctx.block_align + PACKET_HEADER_SIZE); |
168 | ci->seek_time = (int)resume_offset * ((rmctx.block_align * 8 * 1000)/rmctx.bit_rate); | 176 | param = (int)resume_offset * ((rmctx.block_align * 8 * 1000)/rmctx.bit_rate); |
177 | action = CODEC_ACTION_SEEK_TIME; | ||
178 | } | ||
179 | else { | ||
180 | /* Seek to the first packet */ | ||
181 | ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE ); | ||
169 | } | 182 | } |
170 | |||
171 | /* Seek to the first packet */ | ||
172 | ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE ); | ||
173 | 183 | ||
174 | /* The main decoding loop */ | 184 | /* The main decoding loop */ |
175 | while((unsigned)rmctx.audio_pkt_cnt < rmctx.nb_packets) { | 185 | while((unsigned)rmctx.audio_pkt_cnt < rmctx.nb_packets) { |
176 | ci->yield(); | 186 | if (action == CODEC_ACTION_NULL) |
177 | if (ci->stop_codec || ci->new_track) | 187 | action = ci->get_command(¶m); |
188 | |||
189 | if (action == CODEC_ACTION_HALT) | ||
178 | break; | 190 | break; |
179 | 191 | ||
180 | if (ci->seek_time) { | 192 | if (action == CODEC_ACTION_SEEK_TIME) { |
181 | packet_offset = ci->seek_time / ((rmctx.block_align*8*1000)/rmctx.bit_rate); | 193 | packet_offset = param / ((rmctx.block_align*8*1000)/rmctx.bit_rate); |
182 | ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + packet_offset*(rmctx.block_align + PACKET_HEADER_SIZE)); | 194 | ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + |
195 | packet_offset*(rmctx.block_align + PACKET_HEADER_SIZE)); | ||
183 | rmctx.audio_pkt_cnt = packet_offset; | 196 | rmctx.audio_pkt_cnt = packet_offset; |
184 | samplesdone = (rmctx.sample_rate/1000 * ci->seek_time); | 197 | samplesdone = (rmctx.sample_rate/1000 * param); |
198 | ci->set_elapsed(samplesdone/(frequency/1000)); | ||
185 | ci->seek_complete(); | 199 | ci->seek_complete(); |
186 | } | 200 | } |
187 | 201 | ||
202 | action = CODEC_ACTION_NULL; | ||
203 | |||
188 | filebuf = ci->request_buffer(&n, rmctx.block_align + PACKET_HEADER_SIZE); | 204 | filebuf = ci->request_buffer(&n, rmctx.block_align + PACKET_HEADER_SIZE); |
189 | consumed = rm_get_packet(&filebuf, &rmctx, &pkt); | 205 | consumed = rm_get_packet(&filebuf, &rmctx, &pkt); |
190 | 206 | ||
@@ -195,8 +211,7 @@ next_track: | |||
195 | return CODEC_ERROR; | 211 | return CODEC_ERROR; |
196 | } | 212 | } |
197 | else { | 213 | else { |
198 | retval = CODEC_OK; | 214 | break; |
199 | goto exit; | ||
200 | } | 215 | } |
201 | } | 216 | } |
202 | 217 | ||
@@ -205,11 +220,5 @@ next_track: | |||
205 | ci->advance_buffer(pkt.length); | 220 | ci->advance_buffer(pkt.length); |
206 | } | 221 | } |
207 | 222 | ||
208 | request_next_track: | 223 | return CODEC_OK; |
209 | if (ci->request_next_track()) | ||
210 | goto next_track; | ||
211 | |||
212 | exit: | ||
213 | a52_free(state); | ||
214 | return retval; | ||
215 | } | 224 | } |
diff --git a/apps/codecs/aac.c b/apps/codecs/aac.c index 5638dc49a9..90cf0438ce 100644 --- a/apps/codecs/aac.c +++ b/apps/codecs/aac.c | |||
@@ -33,7 +33,19 @@ CODEC_HEADER | |||
33 | #define FAAD_BYTE_BUFFER_SIZE (2048-12) | 33 | #define FAAD_BYTE_BUFFER_SIZE (2048-12) |
34 | 34 | ||
35 | /* this is the codec entry point */ | 35 | /* this is the codec entry point */ |
36 | enum codec_status codec_main(void) | 36 | enum codec_status codec_main(enum codec_entry_call_reason reason) |
37 | { | ||
38 | if (reason == CODEC_LOAD) { | ||
39 | /* Generic codec initialisation */ | ||
40 | ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); | ||
41 | ci->configure(DSP_SET_SAMPLE_DEPTH, 29); | ||
42 | } | ||
43 | |||
44 | return CODEC_OK; | ||
45 | } | ||
46 | |||
47 | /* this is called for each file to process */ | ||
48 | enum codec_status codec_run(void) | ||
37 | { | 49 | { |
38 | /* Note that when dealing with QuickTime/MPEG4 files, terminology is | 50 | /* Note that when dealing with QuickTime/MPEG4 files, terminology is |
39 | * a bit confusing. Files with sound are split up in chunks, where | 51 | * a bit confusing. Files with sound are split up in chunks, where |
@@ -59,25 +71,15 @@ enum codec_status codec_main(void) | |||
59 | uint32_t sbr_fac = 1; | 71 | uint32_t sbr_fac = 1; |
60 | unsigned char c = 0; | 72 | unsigned char c = 0; |
61 | void *ret; | 73 | void *ret; |
62 | 74 | intptr_t param; | |
63 | /* Generic codec initialisation */ | ||
64 | ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); | ||
65 | ci->configure(DSP_SET_SAMPLE_DEPTH, 29); | ||
66 | |||
67 | next_track: | ||
68 | err = CODEC_OK; | ||
69 | 75 | ||
70 | /* Clean and initialize decoder structures */ | 76 | /* Clean and initialize decoder structures */ |
71 | memset(&demux_res , 0, sizeof(demux_res)); | 77 | memset(&demux_res , 0, sizeof(demux_res)); |
72 | if (codec_init()) { | 78 | if (codec_init()) { |
73 | LOGF("FAAD: Codec init error\n"); | 79 | LOGF("FAAD: Codec init error\n"); |
74 | err = CODEC_ERROR; | 80 | return CODEC_ERROR; |
75 | goto exit; | ||
76 | } | 81 | } |
77 | 82 | ||
78 | if (codec_wait_taginfo() != 0) | ||
79 | goto done; | ||
80 | |||
81 | file_offset = ci->id3->offset; | 83 | file_offset = ci->id3->offset; |
82 | 84 | ||
83 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); | 85 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); |
@@ -85,12 +87,13 @@ next_track: | |||
85 | 87 | ||
86 | stream_create(&input_stream,ci); | 88 | stream_create(&input_stream,ci); |
87 | 89 | ||
90 | ci->seek_buffer(ci->id3->first_frame_offset); | ||
91 | |||
88 | /* if qtmovie_read returns successfully, the stream is up to | 92 | /* if qtmovie_read returns successfully, the stream is up to |
89 | * the movie data, which can be used directly by the decoder */ | 93 | * the movie data, which can be used directly by the decoder */ |
90 | if (!qtmovie_read(&input_stream, &demux_res)) { | 94 | if (!qtmovie_read(&input_stream, &demux_res)) { |
91 | LOGF("FAAD: File init error\n"); | 95 | LOGF("FAAD: File init error\n"); |
92 | err = CODEC_ERROR; | 96 | return CODEC_ERROR; |
93 | goto done; | ||
94 | } | 97 | } |
95 | 98 | ||
96 | /* initialise the sound converter */ | 99 | /* initialise the sound converter */ |
@@ -98,8 +101,7 @@ next_track: | |||
98 | 101 | ||
99 | if (!decoder) { | 102 | if (!decoder) { |
100 | LOGF("FAAD: Decode open error\n"); | 103 | LOGF("FAAD: Decode open error\n"); |
101 | err = CODEC_ERROR; | 104 | return CODEC_ERROR; |
102 | goto done; | ||
103 | } | 105 | } |
104 | 106 | ||
105 | NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration(decoder); | 107 | NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration(decoder); |
@@ -109,8 +111,7 @@ next_track: | |||
109 | err = NeAACDecInit2(decoder, demux_res.codecdata, demux_res.codecdata_len, &s, &c); | 111 | err = NeAACDecInit2(decoder, demux_res.codecdata, demux_res.codecdata_len, &s, &c); |
110 | if (err) { | 112 | if (err) { |
111 | LOGF("FAAD: DecInit: %d, %d\n", err, decoder->object_type); | 113 | LOGF("FAAD: DecInit: %d, %d\n", err, decoder->object_type); |
112 | err = CODEC_ERROR; | 114 | return CODEC_ERROR; |
113 | goto done; | ||
114 | } | 115 | } |
115 | 116 | ||
116 | #ifdef SBR_DEC | 117 | #ifdef SBR_DEC |
@@ -150,20 +151,19 @@ next_track: | |||
150 | 151 | ||
151 | /* The main decoding loop */ | 152 | /* The main decoding loop */ |
152 | while (i < demux_res.num_sample_byte_sizes) { | 153 | while (i < demux_res.num_sample_byte_sizes) { |
153 | ci->yield(); | 154 | enum codec_command_action action = ci->get_command(¶m); |
154 | 155 | ||
155 | if (ci->stop_codec || ci->new_track) { | 156 | if (action == CODEC_ACTION_HALT) |
156 | break; | 157 | break; |
157 | } | ||
158 | 158 | ||
159 | /* Deal with any pending seek requests */ | 159 | /* Deal with any pending seek requests */ |
160 | if (ci->seek_time) { | 160 | if (action == CODEC_ACTION_SEEK_TIME) { |
161 | /* Seek to the desired time position. Important: When seeking in SBR | 161 | /* Seek to the desired time position. Important: When seeking in SBR |
162 | * upsampling files the seek_time must be divided by 2 when calling | 162 | * upsampling files the seek_time must be divided by 2 when calling |
163 | * m4a_seek and the resulting sound_samples_done must be expanded | 163 | * m4a_seek and the resulting sound_samples_done must be expanded |
164 | * by a factor 2. This is done via using sbr_fac. */ | 164 | * by a factor 2. This is done via using sbr_fac. */ |
165 | if (m4a_seek(&demux_res, &input_stream, | 165 | if (m4a_seek(&demux_res, &input_stream, |
166 | ((ci->seek_time-1)/10/sbr_fac)*(ci->id3->frequency/100), | 166 | (param/10/sbr_fac)*(ci->id3->frequency/100), |
167 | &sound_samples_done, (int*) &i)) { | 167 | &sound_samples_done, (int*) &i)) { |
168 | sound_samples_done *= sbr_fac; | 168 | sound_samples_done *= sbr_fac; |
169 | elapsed_time = (sound_samples_done * 10) / (ci->id3->frequency / 100); | 169 | elapsed_time = (sound_samples_done * 10) / (ci->id3->frequency / 100); |
@@ -194,8 +194,7 @@ next_track: | |||
194 | else if (file_offset == 0) | 194 | else if (file_offset == 0) |
195 | { | 195 | { |
196 | LOGF("AAC: get_sample_offset error\n"); | 196 | LOGF("AAC: get_sample_offset error\n"); |
197 | err = CODEC_ERROR; | 197 | return CODEC_ERROR; |
198 | goto done; | ||
199 | } | 198 | } |
200 | 199 | ||
201 | /* Request the required number of bytes from the input buffer */ | 200 | /* Request the required number of bytes from the input buffer */ |
@@ -207,8 +206,7 @@ next_track: | |||
207 | /* NeAACDecDecode may sometimes return NULL without setting error. */ | 206 | /* NeAACDecDecode may sometimes return NULL without setting error. */ |
208 | if (ret == NULL || frame_info.error > 0) { | 207 | if (ret == NULL || frame_info.error > 0) { |
209 | LOGF("FAAD: decode error '%s'\n", NeAACDecGetErrorMessage(frame_info.error)); | 208 | LOGF("FAAD: decode error '%s'\n", NeAACDecGetErrorMessage(frame_info.error)); |
210 | err = CODEC_ERROR; | 209 | return CODEC_ERROR; |
211 | goto done; | ||
212 | } | 210 | } |
213 | 211 | ||
214 | /* Advance codec buffer (no need to call set_offset because of this) */ | 212 | /* Advance codec buffer (no need to call set_offset because of this) */ |
@@ -251,12 +249,6 @@ next_track: | |||
251 | i++; | 249 | i++; |
252 | } | 250 | } |
253 | 251 | ||
254 | done: | ||
255 | LOGF("AAC: Decoded %lu samples\n", (unsigned long)sound_samples_done); | 252 | LOGF("AAC: Decoded %lu samples\n", (unsigned long)sound_samples_done); |
256 | 253 | return CODEC_OK; | |
257 | if (ci->request_next_track()) | ||
258 | goto next_track; | ||
259 | |||
260 | exit: | ||
261 | return err; | ||
262 | } | 254 | } |
diff --git a/apps/codecs/adx.c b/apps/codecs/adx.c index 832b94797b..a1b57fce58 100644 --- a/apps/codecs/adx.c +++ b/apps/codecs/adx.c | |||
@@ -45,7 +45,19 @@ static const long cutoff = 500; | |||
45 | static int16_t samples[WAV_CHUNK_SIZE] IBSS_ATTR; | 45 | static int16_t samples[WAV_CHUNK_SIZE] IBSS_ATTR; |
46 | 46 | ||
47 | /* this is the codec entry point */ | 47 | /* this is the codec entry point */ |
48 | enum codec_status codec_main(void) | 48 | enum codec_status codec_main(enum codec_entry_call_reason reason) |
49 | { | ||
50 | if (reason == CODEC_LOAD) { | ||
51 | /* Generic codec initialisation */ | ||
52 | /* we only render 16 bits */ | ||
53 | ci->configure(DSP_SET_SAMPLE_DEPTH, 16); | ||
54 | } | ||
55 | |||
56 | return CODEC_OK; | ||
57 | } | ||
58 | |||
59 | /* this is called for each file to process */ | ||
60 | enum codec_status codec_run(void) | ||
49 | { | 61 | { |
50 | int channels; | 62 | int channels; |
51 | int sampleswritten, i; | 63 | int sampleswritten, i; |
@@ -62,12 +74,8 @@ enum codec_status codec_main(void) | |||
62 | off_t chanstart, bufoff; | 74 | off_t chanstart, bufoff; |
63 | /*long coef1=0x7298L,coef2=-0x3350L;*/ | 75 | /*long coef1=0x7298L,coef2=-0x3350L;*/ |
64 | long coef1, coef2; | 76 | long coef1, coef2; |
77 | intptr_t param; | ||
65 | 78 | ||
66 | /* Generic codec initialisation */ | ||
67 | /* we only render 16 bits */ | ||
68 | ci->configure(DSP_SET_SAMPLE_DEPTH, 16); | ||
69 | |||
70 | next_track: | ||
71 | DEBUGF("ADX: next_track\n"); | 79 | DEBUGF("ADX: next_track\n"); |
72 | if (codec_init()) { | 80 | if (codec_init()) { |
73 | return CODEC_ERROR; | 81 | return CODEC_ERROR; |
@@ -77,10 +85,6 @@ next_track: | |||
77 | /* init history */ | 85 | /* init history */ |
78 | ch1_1=ch1_2=ch2_1=ch2_2=0; | 86 | ch1_1=ch1_2=ch2_1=ch2_2=0; |
79 | 87 | ||
80 | /* wait for track info to load */ | ||
81 | if (codec_wait_taginfo() != 0) | ||
82 | goto request_next_track; | ||
83 | |||
84 | codec_set_replaygain(ci->id3); | 88 | codec_set_replaygain(ci->id3); |
85 | 89 | ||
86 | /* Get header */ | 90 | /* Get header */ |
@@ -226,10 +230,10 @@ next_track: | |||
226 | /* The main decoder loop */ | 230 | /* The main decoder loop */ |
227 | 231 | ||
228 | while (!endofstream) { | 232 | while (!endofstream) { |
229 | ci->yield(); | 233 | enum codec_command_action action = ci->get_command(¶m); |
230 | if (ci->stop_codec || ci->new_track) { | 234 | |
235 | if (action == CODEC_ACTION_HALT) | ||
231 | break; | 236 | break; |
232 | } | ||
233 | 237 | ||
234 | /* do we need to loop? */ | 238 | /* do we need to loop? */ |
235 | if (bufoff > end_adr-18*channels && looping) { | 239 | if (bufoff > end_adr-18*channels && looping) { |
@@ -254,17 +258,17 @@ next_track: | |||
254 | } | 258 | } |
255 | 259 | ||
256 | /* do we need to seek? */ | 260 | /* do we need to seek? */ |
257 | if (ci->seek_time) { | 261 | if (action == CODEC_ACTION_SEEK_TIME) { |
258 | uint32_t newpos; | 262 | uint32_t newpos; |
259 | 263 | ||
260 | DEBUGF("ADX: seek to %ldms\n",ci->seek_time); | 264 | DEBUGF("ADX: seek to %ldms\n", (long)param); |
261 | 265 | ||
262 | endofstream = 0; | 266 | endofstream = 0; |
263 | loop_count = 0; | 267 | loop_count = 0; |
264 | fade_count = -1; /* disable fade */ | 268 | fade_count = -1; /* disable fade */ |
265 | fade_frames = 1; | 269 | fade_frames = 1; |
266 | 270 | ||
267 | newpos = (((uint64_t)avgbytespersec*(ci->seek_time - 1)) | 271 | newpos = (((uint64_t)avgbytespersec*param) |
268 | / (1000LL*18*channels))*(18*channels); | 272 | / (1000LL*18*channels))*(18*channels); |
269 | bufoff = chanstart + newpos; | 273 | bufoff = chanstart + newpos; |
270 | while (bufoff > end_adr-18*channels) { | 274 | while (bufoff > end_adr-18*channels) { |
@@ -385,9 +389,5 @@ next_track: | |||
385 | 1000LL/avgbytespersec); | 389 | 1000LL/avgbytespersec); |
386 | } | 390 | } |
387 | 391 | ||
388 | request_next_track: | ||
389 | if (ci->request_next_track()) | ||
390 | goto next_track; | ||
391 | |||
392 | return CODEC_OK; | 392 | return CODEC_OK; |
393 | } | 393 | } |
diff --git a/apps/codecs/aiff.c b/apps/codecs/aiff.c index d4cf8660dd..3fc137eaeb 100644 --- a/apps/codecs/aiff.c +++ b/apps/codecs/aiff.c | |||
@@ -61,9 +61,20 @@ static const struct pcm_codec *get_codec(uint32_t formattag) | |||
61 | return NULL; | 61 | return NULL; |
62 | } | 62 | } |
63 | 63 | ||
64 | enum codec_status codec_main(void) | 64 | /* this is the codec entry point */ |
65 | enum codec_status codec_main(enum codec_entry_call_reason reason) | ||
66 | { | ||
67 | if (reason == CODEC_LOAD) { | ||
68 | /* Generic codec initialisation */ | ||
69 | ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1); | ||
70 | } | ||
71 | |||
72 | return CODEC_OK; | ||
73 | } | ||
74 | |||
75 | /* this is called for each file to process */ | ||
76 | enum codec_status codec_run(void) | ||
65 | { | 77 | { |
66 | int status; | ||
67 | struct pcm_format format; | 78 | struct pcm_format format; |
68 | uint32_t bytesdone, decodedsamples; | 79 | uint32_t bytesdone, decodedsamples; |
69 | uint32_t num_sample_frames = 0; | 80 | uint32_t num_sample_frames = 0; |
@@ -77,38 +88,28 @@ enum codec_status codec_main(void) | |||
77 | bool is_aifc = false; | 88 | bool is_aifc = false; |
78 | const struct pcm_codec *codec; | 89 | const struct pcm_codec *codec; |
79 | uint32_t size; | 90 | uint32_t size; |
80 | 91 | intptr_t param; | |
81 | /* Generic codec initialisation */ | ||
82 | ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1); | ||
83 | |||
84 | next_track: | ||
85 | status = CODEC_OK; | ||
86 | 92 | ||
87 | if (codec_init()) { | 93 | if (codec_init()) { |
88 | status = CODEC_ERROR; | 94 | return CODEC_ERROR; |
89 | goto exit; | ||
90 | } | 95 | } |
91 | 96 | ||
92 | if (codec_wait_taginfo() != 0) | ||
93 | goto done; | ||
94 | |||
95 | codec_set_replaygain(ci->id3); | 97 | codec_set_replaygain(ci->id3); |
96 | 98 | ||
97 | /* Need to save offset for later use (cleared indirectly by advance_buffer) */ | 99 | /* Need to save offset for later use (cleared indirectly by advance_buffer) */ |
98 | bytesdone = ci->id3->offset; | 100 | bytesdone = ci->id3->offset; |
99 | 101 | ||
100 | /* assume the AIFF header is less than 1024 bytes */ | 102 | /* assume the AIFF header is less than 1024 bytes */ |
103 | ci->seek_buffer(0); | ||
101 | buf = ci->request_buffer(&n, 1024); | 104 | buf = ci->request_buffer(&n, 1024); |
102 | if (n < 54) { | 105 | if (n < 54) { |
103 | status = CODEC_ERROR; | 106 | return CODEC_ERROR; |
104 | goto done; | ||
105 | } | 107 | } |
106 | 108 | ||
107 | if (memcmp(buf, "FORM", 4) != 0) | 109 | if (memcmp(buf, "FORM", 4) != 0) |
108 | { | 110 | { |
109 | DEBUGF("CODEC_ERROR: does not aiff format %4.4s\n", (char*)&buf[0]); | 111 | DEBUGF("CODEC_ERROR: does not aiff format %4.4s\n", (char*)&buf[0]); |
110 | status = CODEC_ERROR; | 112 | return CODEC_ERROR; |
111 | goto done; | ||
112 | } | 113 | } |
113 | if (memcmp(&buf[8], "AIFF", 4) == 0) | 114 | if (memcmp(&buf[8], "AIFF", 4) == 0) |
114 | is_aifc = false; | 115 | is_aifc = false; |
@@ -117,8 +118,7 @@ next_track: | |||
117 | else | 118 | else |
118 | { | 119 | { |
119 | DEBUGF("CODEC_ERROR: does not aiff format %4.4s\n", (char*)&buf[8]); | 120 | DEBUGF("CODEC_ERROR: does not aiff format %4.4s\n", (char*)&buf[8]); |
120 | status = CODEC_ERROR; | 121 | return CODEC_ERROR; |
121 | goto done; | ||
122 | } | 122 | } |
123 | 123 | ||
124 | buf += 12; | 124 | buf += 12; |
@@ -141,8 +141,7 @@ next_track: | |||
141 | { | 141 | { |
142 | DEBUGF("CODEC_ERROR: 'COMM' chunk size=%lu < %d\n", | 142 | DEBUGF("CODEC_ERROR: 'COMM' chunk size=%lu < %d\n", |
143 | (unsigned long)size, (is_aifc)?22:18); | 143 | (unsigned long)size, (is_aifc)?22:18); |
144 | status = CODEC_ERROR; | 144 | return CODEC_ERROR; |
145 | goto done; | ||
146 | } | 145 | } |
147 | /* num_channels */ | 146 | /* num_channels */ |
148 | format.channels = ((buf[8]<<8)|buf[9]); | 147 | format.channels = ((buf[8]<<8)|buf[9]); |
@@ -154,8 +153,7 @@ next_track: | |||
154 | /* sample_rate (don't use last 4 bytes, only integer fs) */ | 153 | /* sample_rate (don't use last 4 bytes, only integer fs) */ |
155 | if (buf[16] != 0x40) { | 154 | if (buf[16] != 0x40) { |
156 | DEBUGF("CODEC_ERROR: weird sampling rate (no @)\n"); | 155 | DEBUGF("CODEC_ERROR: weird sampling rate (no @)\n"); |
157 | status = CODEC_ERROR; | 156 | return CODEC_ERROR; |
158 | goto done; | ||
159 | } | 157 | } |
160 | format.samplespersec = ((buf[18]<<24)|(buf[19]<<16)|(buf[20]<<8)|buf[21])+1; | 158 | format.samplespersec = ((buf[18]<<24)|(buf[19]<<16)|(buf[20]<<8)|buf[21])+1; |
161 | format.samplespersec >>= (16 + 14 - buf[17]); | 159 | format.samplespersec >>= (16 + 14 - buf[17]); |
@@ -181,8 +179,7 @@ next_track: | |||
181 | } else if (memcmp(buf, "SSND", 4)==0) { | 179 | } else if (memcmp(buf, "SSND", 4)==0) { |
182 | if (format.bitspersample == 0) { | 180 | if (format.bitspersample == 0) { |
183 | DEBUGF("CODEC_ERROR: unsupported chunk order\n"); | 181 | DEBUGF("CODEC_ERROR: unsupported chunk order\n"); |
184 | status = CODEC_ERROR; | 182 | return CODEC_ERROR; |
185 | goto done; | ||
186 | } | 183 | } |
187 | /* offset2snd */ | 184 | /* offset2snd */ |
188 | offset2snd = (buf[8]<<24)|(buf[9]<<16)|(buf[10]<<8)|buf[11]; | 185 | offset2snd = (buf[8]<<24)|(buf[9]<<16)|(buf[10]<<8)|buf[11]; |
@@ -205,21 +202,18 @@ next_track: | |||
205 | buf += size; | 202 | buf += size; |
206 | if (n < size) { | 203 | if (n < size) { |
207 | DEBUGF("CODEC_ERROR: AIFF header size > 1024\n"); | 204 | DEBUGF("CODEC_ERROR: AIFF header size > 1024\n"); |
208 | status = CODEC_ERROR; | 205 | return CODEC_ERROR; |
209 | goto done; | ||
210 | } | 206 | } |
211 | n -= size; | 207 | n -= size; |
212 | } /* while 'SSND' */ | 208 | } /* while 'SSND' */ |
213 | 209 | ||
214 | if (format.channels == 0) { | 210 | if (format.channels == 0) { |
215 | DEBUGF("CODEC_ERROR: 'COMM' chunk not found or 0-channels file\n"); | 211 | DEBUGF("CODEC_ERROR: 'COMM' chunk not found or 0-channels file\n"); |
216 | status = CODEC_ERROR; | 212 | return CODEC_ERROR; |
217 | goto done; | ||
218 | } | 213 | } |
219 | if (format.numbytes == 0) { | 214 | if (format.numbytes == 0) { |
220 | DEBUGF("CODEC_ERROR: 'SSND' chunk not found or has zero length\n"); | 215 | DEBUGF("CODEC_ERROR: 'SSND' chunk not found or has zero length\n"); |
221 | status = CODEC_ERROR; | 216 | return CODEC_ERROR; |
222 | goto done; | ||
223 | } | 217 | } |
224 | 218 | ||
225 | codec = get_codec(format.formattag); | 219 | codec = get_codec(format.formattag); |
@@ -227,14 +221,12 @@ next_track: | |||
227 | { | 221 | { |
228 | DEBUGF("CODEC_ERROR: AIFC does not support compressionType: 0x%x\n", | 222 | DEBUGF("CODEC_ERROR: AIFC does not support compressionType: 0x%x\n", |
229 | (unsigned int)format.formattag); | 223 | (unsigned int)format.formattag); |
230 | status = CODEC_ERROR; | 224 | return CODEC_ERROR; |
231 | goto done; | ||
232 | } | 225 | } |
233 | 226 | ||
234 | if (!codec->set_format(&format)) | 227 | if (!codec->set_format(&format)) |
235 | { | 228 | { |
236 | status = CODEC_ERROR; | 229 | return CODEC_ERROR; |
237 | goto done; | ||
238 | } | 230 | } |
239 | 231 | ||
240 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); | 232 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); |
@@ -245,21 +237,18 @@ next_track: | |||
245 | ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); | 237 | ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); |
246 | } else { | 238 | } else { |
247 | DEBUGF("CODEC_ERROR: more than 2 channels unsupported\n"); | 239 | DEBUGF("CODEC_ERROR: more than 2 channels unsupported\n"); |
248 | status = CODEC_ERROR; | 240 | return CODEC_ERROR; |
249 | goto done; | ||
250 | } | 241 | } |
251 | 242 | ||
252 | if (format.samplesperblock == 0) | 243 | if (format.samplesperblock == 0) |
253 | { | 244 | { |
254 | DEBUGF("CODEC_ERROR: samplesperblock is 0\n"); | 245 | DEBUGF("CODEC_ERROR: samplesperblock is 0\n"); |
255 | status = CODEC_ERROR; | 246 | return CODEC_ERROR; |
256 | goto done; | ||
257 | } | 247 | } |
258 | if (format.blockalign == 0) | 248 | if (format.blockalign == 0) |
259 | { | 249 | { |
260 | DEBUGF("CODEC_ERROR: blockalign is 0\n"); | 250 | DEBUGF("CODEC_ERROR: blockalign is 0\n"); |
261 | status = CODEC_ERROR; | 251 | return CODEC_ERROR; |
262 | goto done; | ||
263 | } | 252 | } |
264 | 253 | ||
265 | /* check chunksize */ | 254 | /* check chunksize */ |
@@ -269,8 +258,7 @@ next_track: | |||
269 | if (format.chunksize == 0) | 258 | if (format.chunksize == 0) |
270 | { | 259 | { |
271 | DEBUGF("CODEC_ERROR: chunksize is 0\n"); | 260 | DEBUGF("CODEC_ERROR: chunksize is 0\n"); |
272 | status = CODEC_ERROR; | 261 | return CODEC_ERROR; |
273 | goto done; | ||
274 | } | 262 | } |
275 | 263 | ||
276 | firstblockposn = 1024 - n; | 264 | firstblockposn = 1024 - n; |
@@ -283,13 +271,13 @@ next_track: | |||
283 | PCM_SEEK_POS, NULL); | 271 | PCM_SEEK_POS, NULL); |
284 | 272 | ||
285 | if (newpos->pos > format.numbytes) | 273 | if (newpos->pos > format.numbytes) |
286 | goto done; | 274 | return CODEC_OK; |
275 | |||
287 | if (ci->seek_buffer(firstblockposn + newpos->pos)) | 276 | if (ci->seek_buffer(firstblockposn + newpos->pos)) |
288 | { | 277 | { |
289 | bytesdone = newpos->pos; | 278 | bytesdone = newpos->pos; |
290 | decodedsamples = newpos->samples; | 279 | decodedsamples = newpos->samples; |
291 | } | 280 | } |
292 | ci->seek_complete(); | ||
293 | } else { | 281 | } else { |
294 | /* already where we need to be */ | 282 | /* already where we need to be */ |
295 | bytesdone = 0; | 283 | bytesdone = 0; |
@@ -299,21 +287,29 @@ next_track: | |||
299 | endofstream = 0; | 287 | endofstream = 0; |
300 | 288 | ||
301 | while (!endofstream) { | 289 | while (!endofstream) { |
302 | ci->yield(); | 290 | enum codec_command_action action = ci->get_command(¶m); |
303 | if (ci->stop_codec || ci->new_track) | 291 | |
292 | if (action == CODEC_ACTION_HALT) | ||
304 | break; | 293 | break; |
305 | 294 | ||
306 | if (ci->seek_time) { | 295 | if (action == CODEC_ACTION_SEEK_TIME) { |
307 | /* 3rd args(read_buffer) is unnecessary in the format which AIFF supports. */ | 296 | /* 3rd args(read_buffer) is unnecessary in the format which AIFF supports. */ |
308 | struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, PCM_SEEK_TIME, NULL); | 297 | struct pcm_pos *newpos = codec->get_seek_pos(param, PCM_SEEK_TIME, NULL); |
309 | 298 | ||
310 | if (newpos->pos > format.numbytes) | 299 | if (newpos->pos > format.numbytes) |
300 | { | ||
301 | ci->set_elapsed(ci->id3->length); | ||
302 | ci->seek_complete(); | ||
311 | break; | 303 | break; |
304 | } | ||
305 | |||
312 | if (ci->seek_buffer(firstblockposn + newpos->pos)) | 306 | if (ci->seek_buffer(firstblockposn + newpos->pos)) |
313 | { | 307 | { |
314 | bytesdone = newpos->pos; | 308 | bytesdone = newpos->pos; |
315 | decodedsamples = newpos->samples; | 309 | decodedsamples = newpos->samples; |
316 | } | 310 | } |
311 | |||
312 | ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); | ||
317 | ci->seek_complete(); | 313 | ci->seek_complete(); |
318 | } | 314 | } |
319 | aifbuf = (uint8_t *)ci->request_buffer(&n, format.chunksize); | 315 | aifbuf = (uint8_t *)ci->request_buffer(&n, format.chunksize); |
@@ -326,11 +322,10 @@ next_track: | |||
326 | endofstream = 1; | 322 | endofstream = 1; |
327 | } | 323 | } |
328 | 324 | ||
329 | status = codec->decode(aifbuf, n, samples, &bufcount); | 325 | if (codec->decode(aifbuf, n, samples, &bufcount) == CODEC_ERROR) |
330 | if (status == CODEC_ERROR) | ||
331 | { | 326 | { |
332 | DEBUGF("codec error\n"); | 327 | DEBUGF("codec error\n"); |
333 | goto done; | 328 | return CODEC_ERROR; |
334 | } | 329 | } |
335 | 330 | ||
336 | ci->pcmbuf_insert(samples, NULL, bufcount); | 331 | ci->pcmbuf_insert(samples, NULL, bufcount); |
@@ -343,13 +338,6 @@ next_track: | |||
343 | 338 | ||
344 | ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); | 339 | ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); |
345 | } | 340 | } |
346 | status = CODEC_OK; | ||
347 | |||
348 | done: | ||
349 | if (ci->request_next_track()) | ||
350 | goto next_track; | ||
351 | 341 | ||
352 | exit: | 342 | return CODEC_OK; |
353 | return status; | ||
354 | } | 343 | } |
355 | |||
diff --git a/apps/codecs/aiff_enc.c b/apps/codecs/aiff_enc.c index 69496f70ac..fc44196eb0 100644 --- a/apps/codecs/aiff_enc.c +++ b/apps/codecs/aiff_enc.c | |||
@@ -359,40 +359,42 @@ static bool init_encoder(void) | |||
359 | return true; | 359 | return true; |
360 | } /* init_encoder */ | 360 | } /* init_encoder */ |
361 | 361 | ||
362 | /* main codec entry point */ | 362 | /* this is the codec entry point */ |
363 | enum codec_status codec_main(void) | 363 | enum codec_status codec_main(enum codec_entry_call_reason reason) |
364 | { | 364 | { |
365 | if (!init_encoder()) | 365 | if (reason == CODEC_LOAD) { |
366 | return CODEC_ERROR; | 366 | if (!init_encoder()) |
367 | return CODEC_ERROR; | ||
368 | } | ||
369 | else if (reason == CODEC_UNLOAD) { | ||
370 | /* reset parameters to initial state */ | ||
371 | ci->enc_set_parameters(NULL); | ||
372 | } | ||
367 | 373 | ||
374 | return CODEC_OK; | ||
375 | } | ||
376 | |||
377 | /* this is called for each file to process */ | ||
378 | enum codec_status codec_run(void) | ||
379 | { | ||
368 | /* main encoding loop */ | 380 | /* main encoding loop */ |
369 | while(!ci->stop_codec) | 381 | while (ci->get_command(NULL) != CODEC_ACTION_HALT) |
370 | { | 382 | { |
371 | uint32_t *src; | 383 | uint32_t *src = (uint32_t *)ci->enc_get_pcm_data(PCM_CHUNK_SIZE); |
384 | struct enc_chunk_hdr *chunk; | ||
372 | 385 | ||
373 | while ((src = (uint32_t *)ci->enc_get_pcm_data(PCM_CHUNK_SIZE)) != NULL) | 386 | if (src == NULL) |
374 | { | 387 | continue; |
375 | struct enc_chunk_hdr *chunk; | ||
376 | |||
377 | if (ci->stop_codec) | ||
378 | break; | ||
379 | 388 | ||
380 | chunk = ci->enc_get_chunk(); | 389 | chunk = ci->enc_get_chunk(); |
381 | chunk->enc_size = enc_size; | 390 | chunk->enc_size = enc_size; |
382 | chunk->num_pcm = PCM_SAMP_PER_CHUNK; | 391 | chunk->num_pcm = PCM_SAMP_PER_CHUNK; |
383 | chunk->enc_data = ENC_CHUNK_SKIP_HDR(chunk->enc_data, chunk); | 392 | chunk->enc_data = ENC_CHUNK_SKIP_HDR(chunk->enc_data, chunk); |
384 | 393 | ||
385 | chunk_to_aiff_format(src, (uint32_t *)chunk->enc_data); | 394 | chunk_to_aiff_format(src, (uint32_t *)chunk->enc_data); |
386 | |||
387 | ci->enc_finish_chunk(); | ||
388 | ci->yield(); | ||
389 | } | ||
390 | 395 | ||
391 | ci->yield(); | 396 | ci->enc_finish_chunk(); |
392 | } | 397 | } |
393 | 398 | ||
394 | /* reset parameters to initial state */ | ||
395 | ci->enc_set_parameters(NULL); | ||
396 | |||
397 | return CODEC_OK; | 399 | return CODEC_OK; |
398 | } /* codec_start */ | 400 | } |
diff --git a/apps/codecs/alac.c b/apps/codecs/alac.c index cd9129a278..82bda264c3 100644 --- a/apps/codecs/alac.c +++ b/apps/codecs/alac.c | |||
@@ -32,116 +32,114 @@ CODEC_HEADER | |||
32 | static int32_t outputbuffer[ALAC_MAX_CHANNELS][ALAC_BLOCKSIZE] IBSS_ATTR; | 32 | static int32_t outputbuffer[ALAC_MAX_CHANNELS][ALAC_BLOCKSIZE] IBSS_ATTR; |
33 | 33 | ||
34 | /* this is the codec entry point */ | 34 | /* this is the codec entry point */ |
35 | enum codec_status codec_main(void) | 35 | enum codec_status codec_main(enum codec_entry_call_reason reason) |
36 | { | 36 | { |
37 | size_t n; | 37 | if (reason == CODEC_LOAD) { |
38 | demux_res_t demux_res; | 38 | /* Generic codec initialisation */ |
39 | stream_t input_stream; | 39 | ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); |
40 | uint32_t samplesdone; | 40 | ci->configure(DSP_SET_SAMPLE_DEPTH, ALAC_OUTPUT_DEPTH-1); |
41 | uint32_t elapsedtime; | 41 | } |
42 | int samplesdecoded; | ||
43 | unsigned int i; | ||
44 | unsigned char* buffer; | ||
45 | alac_file alac; | ||
46 | int retval; | ||
47 | |||
48 | /* Generic codec initialisation */ | ||
49 | ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); | ||
50 | ci->configure(DSP_SET_SAMPLE_DEPTH, ALAC_OUTPUT_DEPTH-1); | ||
51 | |||
52 | next_track: | ||
53 | retval = CODEC_OK; | ||
54 | |||
55 | /* Clean and initialize decoder structures */ | ||
56 | memset(&demux_res , 0, sizeof(demux_res)); | ||
57 | if (codec_init()) { | ||
58 | LOGF("ALAC: Error initialising codec\n"); | ||
59 | retval = CODEC_ERROR; | ||
60 | goto exit; | ||
61 | } | ||
62 | |||
63 | if (codec_wait_taginfo() != 0) | ||
64 | goto done; | ||
65 | |||
66 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); | ||
67 | codec_set_replaygain(ci->id3); | ||
68 | 42 | ||
69 | stream_create(&input_stream,ci); | 43 | return CODEC_OK; |
44 | } | ||
70 | 45 | ||
71 | /* Read from ci->id3->offset before calling qtmovie_read. */ | 46 | /* this is called for each file to process */ |
72 | samplesdone = (uint32_t)(((uint64_t)(ci->id3->offset) * ci->id3->frequency) / | 47 | enum codec_status codec_run(void) |
73 | (ci->id3->bitrate*128)); | 48 | { |
74 | 49 | size_t n; | |
75 | /* if qtmovie_read returns successfully, the stream is up to | 50 | demux_res_t demux_res; |
76 | * the movie data, which can be used directly by the decoder */ | 51 | stream_t input_stream; |
77 | if (!qtmovie_read(&input_stream, &demux_res)) { | 52 | uint32_t samplesdone; |
78 | LOGF("ALAC: Error initialising file\n"); | 53 | uint32_t elapsedtime = 0; |
79 | retval = CODEC_ERROR; | 54 | int samplesdecoded; |
80 | goto done; | 55 | unsigned int i; |
81 | } | 56 | unsigned char* buffer; |
82 | 57 | alac_file alac; | |
83 | /* initialise the sound converter */ | 58 | intptr_t param; |
84 | create_alac(demux_res.sound_sample_size, demux_res.num_channels,&alac); | 59 | |
85 | alac_set_info(&alac, demux_res.codecdata); | 60 | /* Clean and initialize decoder structures */ |
86 | 61 | memset(&demux_res , 0, sizeof(demux_res)); | |
87 | /* Set i for first frame, seek to desired sample position for resuming. */ | 62 | if (codec_init()) { |
88 | i=0; | 63 | LOGF("ALAC: Error initialising codec\n"); |
89 | if (samplesdone > 0) { | 64 | return CODEC_ERROR; |
90 | if (m4a_seek(&demux_res, &input_stream, samplesdone, | ||
91 | &samplesdone, (int*) &i)) { | ||
92 | elapsedtime = (samplesdone * 10) / (ci->id3->frequency / 100); | ||
93 | ci->set_elapsed(elapsedtime); | ||
94 | } else { | ||
95 | samplesdone = 0; | ||
96 | } | 65 | } |
97 | } | ||
98 | 66 | ||
99 | /* The main decoding loop */ | 67 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); |
100 | while (i < demux_res.num_sample_byte_sizes) { | 68 | codec_set_replaygain(ci->id3); |
101 | ci->yield(); | 69 | |
102 | if (ci->stop_codec || ci->new_track) { | 70 | ci->seek_buffer(0); |
103 | break; | 71 | |
72 | stream_create(&input_stream,ci); | ||
73 | |||
74 | /* Read from ci->id3->offset before calling qtmovie_read. */ | ||
75 | samplesdone = (uint32_t)(((uint64_t)(ci->id3->offset) * ci->id3->frequency) / | ||
76 | (ci->id3->bitrate*128)); | ||
77 | |||
78 | /* if qtmovie_read returns successfully, the stream is up to | ||
79 | * the movie data, which can be used directly by the decoder */ | ||
80 | if (!qtmovie_read(&input_stream, &demux_res)) { | ||
81 | LOGF("ALAC: Error initialising file\n"); | ||
82 | return CODEC_ERROR; | ||
104 | } | 83 | } |
105 | 84 | ||
106 | /* Deal with any pending seek requests */ | 85 | /* initialise the sound converter */ |
107 | if (ci->seek_time) { | 86 | create_alac(demux_res.sound_sample_size, demux_res.num_channels,&alac); |
108 | if (m4a_seek(&demux_res, &input_stream, | 87 | alac_set_info(&alac, demux_res.codecdata); |
109 | ((ci->seek_time-1)/10) * (ci->id3->frequency/100), | 88 | |
110 | &samplesdone, (int *)&i)) { | 89 | /* Set i for first frame, seek to desired sample position for resuming. */ |
111 | elapsedtime=(samplesdone*10)/(ci->id3->frequency/100); | 90 | i=0; |
112 | ci->set_elapsed(elapsedtime); | 91 | if (samplesdone > 0) { |
113 | } | 92 | if (m4a_seek(&demux_res, &input_stream, samplesdone, |
114 | ci->seek_complete(); | 93 | &samplesdone, (int*) &i)) { |
94 | elapsedtime = (samplesdone * 10) / (ci->id3->frequency / 100); | ||
95 | ci->set_elapsed(elapsedtime); | ||
96 | } else { | ||
97 | samplesdone = 0; | ||
98 | } | ||
115 | } | 99 | } |
116 | 100 | ||
117 | /* Request the required number of bytes from the input buffer */ | 101 | /* The main decoding loop */ |
118 | buffer=ci->request_buffer(&n, ALAC_BYTE_BUFFER_SIZE); | 102 | while (i < demux_res.num_sample_byte_sizes) { |
103 | enum codec_command_action action = ci->get_command(¶m); | ||
104 | |||
105 | if (action == CODEC_ACTION_HALT) | ||
106 | break; | ||
119 | 107 | ||
120 | /* Decode one block - returned samples will be host-endian */ | 108 | /* Request the required number of bytes from the input buffer */ |
121 | ci->yield(); | 109 | buffer=ci->request_buffer(&n, ALAC_BYTE_BUFFER_SIZE); |
122 | samplesdecoded=alac_decode_frame(&alac, buffer, outputbuffer, ci->yield); | ||
123 | 110 | ||
124 | /* Advance codec buffer by amount of consumed bytes */ | 111 | /* Deal with any pending seek requests */ |
125 | ci->advance_buffer(alac.bytes_consumed); | 112 | if (action == CODEC_ACTION_SEEK_TIME) { |
113 | if (m4a_seek(&demux_res, &input_stream, | ||
114 | (param/10) * (ci->id3->frequency/100), | ||
115 | &samplesdone, (int *)&i)) { | ||
116 | elapsedtime=(samplesdone*10)/(ci->id3->frequency/100); | ||
117 | } | ||
118 | ci->set_elapsed(elapsedtime); | ||
119 | ci->seek_complete(); | ||
120 | } | ||
126 | 121 | ||
127 | /* Output the audio */ | 122 | /* Request the required number of bytes from the input buffer */ |
128 | ci->yield(); | 123 | buffer=ci->request_buffer(&n, ALAC_BYTE_BUFFER_SIZE); |
129 | ci->pcmbuf_insert(outputbuffer[0], outputbuffer[1], samplesdecoded); | ||
130 | 124 | ||
131 | /* Update the elapsed-time indicator */ | 125 | /* Decode one block - returned samples will be host-endian */ |
132 | samplesdone+=samplesdecoded; | 126 | samplesdecoded=alac_decode_frame(&alac, buffer, outputbuffer, ci->yield); |
133 | elapsedtime=(samplesdone*10)/(ci->id3->frequency/100); | 127 | ci->yield(); |
134 | ci->set_elapsed(elapsedtime); | ||
135 | 128 | ||
136 | i++; | 129 | /* Advance codec buffer by amount of consumed bytes */ |
137 | } | 130 | ci->advance_buffer(alac.bytes_consumed); |
138 | 131 | ||
139 | done: | 132 | /* Output the audio */ |
140 | LOGF("ALAC: Decoded %lu samples\n",(unsigned long)samplesdone); | 133 | ci->pcmbuf_insert(outputbuffer[0], outputbuffer[1], samplesdecoded); |
141 | 134 | ||
142 | if (ci->request_next_track()) | 135 | /* Update the elapsed-time indicator */ |
143 | goto next_track; | 136 | samplesdone+=samplesdecoded; |
137 | elapsedtime=(samplesdone*10)/(ci->id3->frequency/100); | ||
138 | ci->set_elapsed(elapsedtime); | ||
139 | |||
140 | i++; | ||
141 | } | ||
144 | 142 | ||
145 | exit: | 143 | LOGF("ALAC: Decoded %lu samples\n",(unsigned long)samplesdone); |
146 | return retval; | 144 | return CODEC_OK; |
147 | } | 145 | } |
diff --git a/apps/codecs/ape.c b/apps/codecs/ape.c index 11d973ab26..8f95a01ec7 100644 --- a/apps/codecs/ape.c +++ b/apps/codecs/ape.c | |||
@@ -127,13 +127,23 @@ static void ape_resume(struct ape_ctx_t* ape_ctx, size_t resume_offset, | |||
127 | } | 127 | } |
128 | 128 | ||
129 | /* this is the codec entry point */ | 129 | /* this is the codec entry point */ |
130 | enum codec_status codec_main(void) | 130 | enum codec_status codec_main(enum codec_entry_call_reason reason) |
131 | { | ||
132 | if (reason == CODEC_LOAD) { | ||
133 | /* Generic codec initialisation */ | ||
134 | ci->configure(DSP_SET_SAMPLE_DEPTH, APE_OUTPUT_DEPTH-1); | ||
135 | } | ||
136 | |||
137 | return CODEC_OK; | ||
138 | } | ||
139 | |||
140 | /* this is called for each file to process */ | ||
141 | enum codec_status codec_run(void) | ||
131 | { | 142 | { |
132 | struct ape_ctx_t ape_ctx; | 143 | struct ape_ctx_t ape_ctx; |
133 | uint32_t samplesdone; | 144 | uint32_t samplesdone; |
134 | uint32_t elapsedtime; | 145 | uint32_t elapsedtime; |
135 | size_t bytesleft; | 146 | size_t bytesleft; |
136 | int retval; | ||
137 | 147 | ||
138 | uint32_t currentframe; | 148 | uint32_t currentframe; |
139 | uint32_t newfilepos; | 149 | uint32_t newfilepos; |
@@ -145,33 +155,24 @@ enum codec_status codec_main(void) | |||
145 | int res; | 155 | int res; |
146 | int firstbyte; | 156 | int firstbyte; |
147 | size_t resume_offset; | 157 | size_t resume_offset; |
148 | 158 | intptr_t param; | |
149 | /* Generic codec initialisation */ | ||
150 | ci->configure(DSP_SET_SAMPLE_DEPTH, APE_OUTPUT_DEPTH-1); | ||
151 | |||
152 | next_track: | ||
153 | retval = CODEC_OK; | ||
154 | 159 | ||
155 | if (codec_init()) { | 160 | if (codec_init()) { |
156 | LOGF("APE: Error initialising codec\n"); | 161 | LOGF("APE: Error initialising codec\n"); |
157 | retval = CODEC_ERROR; | 162 | return CODEC_ERROR; |
158 | goto exit; | ||
159 | } | 163 | } |
160 | 164 | ||
161 | if (codec_wait_taginfo() != 0) | ||
162 | goto done; | ||
163 | |||
164 | /* Remember the resume position - when the codec is opened, the | 165 | /* Remember the resume position - when the codec is opened, the |
165 | playback engine will reset it. */ | 166 | playback engine will reset it. */ |
166 | resume_offset = ci->id3->offset; | 167 | resume_offset = ci->id3->offset; |
167 | 168 | ||
169 | ci->seek_buffer(0); | ||
168 | inbuffer = ci->request_buffer(&bytesleft, INPUT_CHUNKSIZE); | 170 | inbuffer = ci->request_buffer(&bytesleft, INPUT_CHUNKSIZE); |
169 | 171 | ||
170 | /* Read the file headers to populate the ape_ctx struct */ | 172 | /* Read the file headers to populate the ape_ctx struct */ |
171 | if (ape_parseheaderbuf(inbuffer,&ape_ctx) < 0) { | 173 | if (ape_parseheaderbuf(inbuffer,&ape_ctx) < 0) { |
172 | LOGF("APE: Error reading header\n"); | 174 | LOGF("APE: Error reading header\n"); |
173 | retval = CODEC_ERROR; | 175 | return CODEC_ERROR; |
174 | goto exit; | ||
175 | } | 176 | } |
176 | 177 | ||
177 | /* Initialise the seektable for this file */ | 178 | /* Initialise the seektable for this file */ |
@@ -243,16 +244,16 @@ frame_start: | |||
243 | /* Decode the frame a chunk at a time */ | 244 | /* Decode the frame a chunk at a time */ |
244 | while (nblocks > 0) | 245 | while (nblocks > 0) |
245 | { | 246 | { |
246 | ci->yield(); | 247 | enum codec_command_action action = ci->get_command(¶m); |
247 | if (ci->stop_codec || ci->new_track) { | 248 | |
249 | if (action == CODEC_ACTION_HALT) | ||
248 | goto done; | 250 | goto done; |
249 | } | ||
250 | 251 | ||
251 | /* Deal with any pending seek requests */ | 252 | /* Deal with any pending seek requests */ |
252 | if (ci->seek_time) | 253 | if (action == CODEC_ACTION_SEEK_TIME) |
253 | { | 254 | { |
254 | if (ape_calc_seekpos(&ape_ctx, | 255 | if (ape_calc_seekpos(&ape_ctx, |
255 | ((ci->seek_time-1)/10) * (ci->id3->frequency/100), | 256 | (param/10) * (ci->id3->frequency/100), |
256 | ¤tframe, | 257 | ¤tframe, |
257 | &newfilepos, | 258 | &newfilepos, |
258 | &samplestoskip)) | 259 | &samplestoskip)) |
@@ -266,9 +267,12 @@ frame_start: | |||
266 | ci->seek_buffer(newfilepos); | 267 | ci->seek_buffer(newfilepos); |
267 | inbuffer = ci->request_buffer(&bytesleft, INPUT_CHUNKSIZE); | 268 | inbuffer = ci->request_buffer(&bytesleft, INPUT_CHUNKSIZE); |
268 | 269 | ||
270 | elapsedtime = (samplesdone*10)/(ape_ctx.samplerate/100); | ||
271 | ci->set_elapsed(elapsedtime); | ||
269 | ci->seek_complete(); | 272 | ci->seek_complete(); |
270 | goto frame_start; /* Sorry... */ | 273 | goto frame_start; /* Sorry... */ |
271 | } | 274 | } |
275 | |||
272 | ci->seek_complete(); | 276 | ci->seek_complete(); |
273 | } | 277 | } |
274 | 278 | ||
@@ -281,8 +285,7 @@ frame_start: | |||
281 | { | 285 | { |
282 | /* Frame decoding error, abort */ | 286 | /* Frame decoding error, abort */ |
283 | LOGF("APE: Frame %lu, error %d\n",(unsigned long)currentframe,res); | 287 | LOGF("APE: Frame %lu, error %d\n",(unsigned long)currentframe,res); |
284 | retval = CODEC_ERROR; | 288 | return CODEC_ERROR; |
285 | goto done; | ||
286 | } | 289 | } |
287 | 290 | ||
288 | ci->yield(); | 291 | ci->yield(); |
@@ -320,10 +323,5 @@ frame_start: | |||
320 | 323 | ||
321 | done: | 324 | done: |
322 | LOGF("APE: Decoded %lu samples\n",(unsigned long)samplesdone); | 325 | LOGF("APE: Decoded %lu samples\n",(unsigned long)samplesdone); |
323 | 326 | return CODEC_OK; | |
324 | if (ci->request_next_track()) | ||
325 | goto next_track; | ||
326 | |||
327 | exit: | ||
328 | return retval; | ||
329 | } | 327 | } |
diff --git a/apps/codecs/asap.c b/apps/codecs/asap.c index 9447c738d2..f12dc6a0c5 100644 --- a/apps/codecs/asap.c +++ b/apps/codecs/asap.c | |||
@@ -29,24 +29,21 @@ CODEC_HEADER | |||
29 | static byte samples[CHUNK_SIZE] IBSS_ATTR; /* The sample buffer */ | 29 | static byte samples[CHUNK_SIZE] IBSS_ATTR; /* The sample buffer */ |
30 | static ASAP_State asap; /* asap codec state */ | 30 | static ASAP_State asap; /* asap codec state */ |
31 | 31 | ||
32 | /* this is the codec entry point */ | 32 | /* this is called for each file to process */ |
33 | enum codec_status codec_main(void) | 33 | enum codec_status codec_run(void) |
34 | { | 34 | { |
35 | int n_bytes; | 35 | int n_bytes; |
36 | int song; | 36 | int song; |
37 | int duration; | 37 | int duration; |
38 | char* module; | 38 | char* module; |
39 | int bytesPerSample =2; | 39 | int bytesPerSample =2; |
40 | intptr_t param; | ||
40 | 41 | ||
41 | next_track: | ||
42 | if (codec_init()) { | 42 | if (codec_init()) { |
43 | DEBUGF("codec init failed\n"); | 43 | DEBUGF("codec init failed\n"); |
44 | return CODEC_ERROR; | 44 | return CODEC_ERROR; |
45 | } | 45 | } |
46 | 46 | ||
47 | if (codec_wait_taginfo() != 0) | ||
48 | goto request_next_track; | ||
49 | |||
50 | codec_set_replaygain(ci->id3); | 47 | codec_set_replaygain(ci->id3); |
51 | 48 | ||
52 | int bytes_done =0; | 49 | int bytes_done =0; |
@@ -97,19 +94,20 @@ next_track: | |||
97 | 94 | ||
98 | /* The main decoder loop */ | 95 | /* The main decoder loop */ |
99 | while (1) { | 96 | while (1) { |
100 | ci->yield(); | 97 | enum codec_command_action action = ci->get_command(¶m); |
101 | if (ci->stop_codec || ci->new_track) | 98 | |
99 | if (action == CODEC_ACTION_HALT) | ||
102 | break; | 100 | break; |
103 | 101 | ||
104 | if (ci->seek_time) { | 102 | if (action == CODEC_ACTION_SEEK_TIME) { |
105 | /* New time is ready in ci->seek_time */ | 103 | /* New time is ready in param */ |
106 | 104 | ||
107 | /* seek to pos */ | 105 | /* seek to pos */ |
108 | ASAP_Seek(&asap,ci->seek_time); | 106 | ASAP_Seek(&asap,param); |
109 | /* update elapsed */ | ||
110 | ci->set_elapsed(ci->seek_time); | ||
111 | /* update bytes_done */ | 107 | /* update bytes_done */ |
112 | bytes_done = ci->seek_time*44.1*2; | 108 | bytes_done = param*44.1*2; |
109 | /* update elapsed */ | ||
110 | ci->set_elapsed((bytes_done / 2) / 44.1); | ||
113 | /* seek ready */ | 111 | /* seek ready */ |
114 | ci->seek_complete(); | 112 | ci->seek_complete(); |
115 | } | 113 | } |
@@ -129,10 +127,6 @@ next_track: | |||
129 | if(n_bytes != sizeof(samples)) | 127 | if(n_bytes != sizeof(samples)) |
130 | break; | 128 | break; |
131 | } | 129 | } |
132 | |||
133 | request_next_track: | ||
134 | if (ci->request_next_track()) | ||
135 | goto next_track; | ||
136 | 130 | ||
137 | return CODEC_OK; | 131 | return CODEC_OK; |
138 | } | 132 | } |
diff --git a/apps/codecs/atrac3_oma.c b/apps/codecs/atrac3_oma.c index 73f3ad29fd..ab24783368 100644 --- a/apps/codecs/atrac3_oma.c +++ b/apps/codecs/atrac3_oma.c | |||
@@ -33,24 +33,22 @@ CODEC_HEADER | |||
33 | 33 | ||
34 | static ATRAC3Context q IBSS_ATTR; | 34 | static ATRAC3Context q IBSS_ATTR; |
35 | 35 | ||
36 | /* this is the codec entry point */ | 36 | /* this is called for each file to process */ |
37 | enum codec_status codec_main(void) | 37 | enum codec_status codec_run(void) |
38 | { | 38 | { |
39 | static size_t buff_size; | 39 | static size_t buff_size; |
40 | int datasize, res, frame_counter, total_frames, seek_frame_offset; | 40 | int datasize, res, frame_counter, total_frames, seek_frame_offset; |
41 | uint8_t *bit_buffer; | 41 | uint8_t *bit_buffer; |
42 | int elapsed = 0; | 42 | int elapsed = 0; |
43 | size_t resume_offset; | 43 | size_t resume_offset; |
44 | intptr_t param; | ||
45 | enum codec_command_action action = CODEC_ACTION_NULL; | ||
44 | 46 | ||
45 | next_track: | ||
46 | if (codec_init()) { | 47 | if (codec_init()) { |
47 | DEBUGF("codec init failed\n"); | 48 | DEBUGF("codec init failed\n"); |
48 | return CODEC_ERROR; | 49 | return CODEC_ERROR; |
49 | } | 50 | } |
50 | 51 | ||
51 | if (codec_wait_taginfo() != 0) | ||
52 | goto done; | ||
53 | |||
54 | resume_offset = ci->id3->offset; | 52 | resume_offset = ci->id3->offset; |
55 | 53 | ||
56 | codec_set_replaygain(ci->id3); | 54 | codec_set_replaygain(ci->id3); |
@@ -60,84 +58,88 @@ next_track: | |||
60 | ci->configure(DSP_SET_SAMPLE_DEPTH, 17); /* Remark: atrac3 uses s15.0 by default, s15.2 was hacked. */ | 58 | ci->configure(DSP_SET_SAMPLE_DEPTH, 17); /* Remark: atrac3 uses s15.0 by default, s15.2 was hacked. */ |
61 | ci->configure(DSP_SET_STEREO_MODE, ci->id3->channels == 1 ? | 59 | ci->configure(DSP_SET_STEREO_MODE, ci->id3->channels == 1 ? |
62 | STEREO_MONO : STEREO_NONINTERLEAVED); | 60 | STEREO_MONO : STEREO_NONINTERLEAVED); |
63 | 61 | ||
64 | res =atrac3_decode_init(&q, ci->id3); | 62 | ci->seek_buffer(0); |
63 | |||
64 | res = atrac3_decode_init(&q, ci->id3); | ||
65 | if(res < 0) { | 65 | if(res < 0) { |
66 | DEBUGF("failed to initialize OMA atrac decoder\n"); | 66 | DEBUGF("failed to initialize OMA atrac decoder\n"); |
67 | return CODEC_ERROR; | 67 | return CODEC_ERROR; |
68 | } | 68 | } |
69 | 69 | ||
70 | total_frames = (ci->id3->filesize - ci->id3->first_frame_offset) / FRAMESIZE; | ||
71 | frame_counter = 0; | ||
72 | |||
70 | /* check for a mid-track resume and force a seek time accordingly */ | 73 | /* check for a mid-track resume and force a seek time accordingly */ |
71 | if(resume_offset > ci->id3->first_frame_offset) { | 74 | if(resume_offset > ci->id3->first_frame_offset) { |
72 | resume_offset -= ci->id3->first_frame_offset; | 75 | resume_offset -= ci->id3->first_frame_offset; |
73 | /* calculate resume_offset in frames */ | 76 | /* calculate resume_offset in frames */ |
74 | resume_offset = (int)resume_offset / FRAMESIZE; | 77 | resume_offset = (int)resume_offset / FRAMESIZE; |
75 | ci->seek_time = (int)resume_offset * ((FRAMESIZE * 8)/BITRATE); | 78 | param = (int)resume_offset * ((FRAMESIZE * 8)/BITRATE); |
79 | action = CODEC_ACTION_SEEK_TIME; | ||
80 | } | ||
81 | else { | ||
82 | ci->set_elapsed(0); | ||
83 | ci->seek_buffer(ci->id3->first_frame_offset); | ||
76 | } | 84 | } |
77 | total_frames = (ci->id3->filesize - ci->id3->first_frame_offset) / FRAMESIZE; | ||
78 | frame_counter = 0; | ||
79 | |||
80 | ci->set_elapsed(0); | ||
81 | ci->seek_buffer(0); | ||
82 | ci->advance_buffer(ci->id3->first_frame_offset); | ||
83 | 85 | ||
84 | /* The main decoder loop */ | 86 | /* The main decoder loop */ |
85 | seek_start : | ||
86 | while(frame_counter < total_frames) | 87 | while(frame_counter < total_frames) |
87 | { | 88 | { |
89 | if (action == CODEC_ACTION_NULL) | ||
90 | action = ci->get_command(¶m); | ||
91 | |||
92 | if (action == CODEC_ACTION_HALT) | ||
93 | break; | ||
94 | |||
88 | bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, FRAMESIZE); | 95 | bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, FRAMESIZE); |
89 | 96 | ||
90 | ci->yield(); | 97 | if (action == CODEC_ACTION_SEEK_TIME) { |
91 | if (ci->stop_codec || ci->new_track) | 98 | /* Do not allow seeking beyond the file's length */ |
92 | goto done; | 99 | if ((unsigned) param > ci->id3->length) { |
93 | 100 | ci->set_elapsed(ci->id3->length); | |
94 | if (ci->seek_time) { | 101 | ci->seek_complete(); |
95 | ci->set_elapsed(ci->seek_time); | 102 | break; |
96 | 103 | } | |
97 | /* Do not allow seeking beyond the file's length */ | 104 | |
98 | if ((unsigned) ci->seek_time > ci->id3->length) { | 105 | /* Seek to the start of the track */ |
99 | ci->seek_complete(); | 106 | if (param == 0) { |
100 | goto done; | 107 | elapsed = 0; |
101 | } | 108 | ci->set_elapsed(0); |
102 | 109 | ci->seek_buffer(ci->id3->first_frame_offset); | |
103 | /* Seek to the start of the track */ | 110 | ci->seek_complete(); |
104 | if (ci->seek_time == 1) { | 111 | action = CODEC_ACTION_NULL; |
105 | ci->set_elapsed(0); | 112 | continue; |
106 | ci->seek_complete(); | 113 | } |
107 | ci->seek_buffer(ci->id3->first_frame_offset); | 114 | |
108 | elapsed = 0; | 115 | seek_frame_offset = (param * BITRATE) / (8 * FRAMESIZE); |
109 | goto seek_start; | 116 | frame_counter = seek_frame_offset; |
110 | } | 117 | ci->seek_buffer(ci->id3->first_frame_offset + seek_frame_offset* FRAMESIZE); |
111 | seek_frame_offset = (ci->seek_time * BITRATE) / (8 * FRAMESIZE); | 118 | bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, FRAMESIZE); |
112 | frame_counter = seek_frame_offset; | 119 | elapsed = param; |
113 | ci->seek_buffer(ci->id3->first_frame_offset + seek_frame_offset* FRAMESIZE); | ||
114 | bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, FRAMESIZE); | ||
115 | elapsed = ci->seek_time; | ||
116 | |||
117 | ci->set_elapsed(elapsed); | ||
118 | ci->seek_complete(); | ||
119 | } | ||
120 | |||
121 | res = atrac3_decode_frame(FRAMESIZE, &q, &datasize, bit_buffer, FRAMESIZE); | ||
122 | |||
123 | if(res != (int)FRAMESIZE) { | ||
124 | DEBUGF("codec error\n"); | ||
125 | return CODEC_ERROR; | ||
126 | } | ||
127 | |||
128 | if(datasize) | ||
129 | ci->pcmbuf_insert(q.outSamples, q.outSamples + 1024, q.samples_per_frame / ci->id3->channels); | ||
130 | |||
131 | elapsed += (FRAMESIZE * 8) / BITRATE; | ||
132 | ci->set_elapsed(elapsed); | 120 | ci->set_elapsed(elapsed); |
133 | 121 | ci->seek_complete(); | |
134 | ci->advance_buffer(FRAMESIZE); | 122 | } |
135 | frame_counter++; | 123 | |
136 | } | 124 | action = CODEC_ACTION_NULL; |
137 | 125 | ||
138 | done: | 126 | res = atrac3_decode_frame(FRAMESIZE, &q, &datasize, bit_buffer, FRAMESIZE); |
139 | if (ci->request_next_track()) | 127 | |
140 | goto next_track; | 128 | if(res != (int)FRAMESIZE) { |
129 | DEBUGF("codec error\n"); | ||
130 | return CODEC_ERROR; | ||
131 | } | ||
132 | |||
133 | if(datasize) | ||
134 | ci->pcmbuf_insert(q.outSamples, q.outSamples + 1024, | ||
135 | q.samples_per_frame / ci->id3->channels); | ||
136 | |||
137 | elapsed += (FRAMESIZE * 8) / BITRATE; | ||
138 | ci->set_elapsed(elapsed); | ||
139 | |||
140 | ci->advance_buffer(FRAMESIZE); | ||
141 | frame_counter++; | ||
142 | } | ||
141 | 143 | ||
142 | return CODEC_OK; | 144 | return CODEC_OK; |
143 | } | 145 | } |
diff --git a/apps/codecs/atrac3_rm.c b/apps/codecs/atrac3_rm.c index 6a77d24283..1322e917ed 100644 --- a/apps/codecs/atrac3_rm.c +++ b/apps/codecs/atrac3_rm.c | |||
@@ -41,9 +41,9 @@ static void init_rm(RMContext *rmctx) | |||
41 | memcpy(ci->id3->id3v2buf, (char*)rmctx->codec_extradata, rmctx->extradata_size*sizeof(char)); | 41 | memcpy(ci->id3->id3v2buf, (char*)rmctx->codec_extradata, rmctx->extradata_size*sizeof(char)); |
42 | } | 42 | } |
43 | 43 | ||
44 | /* this is the codec entry point */ | 44 | /* this is called for each file to process */ |
45 | enum codec_status codec_main(void) | 45 | enum codec_status codec_run(void) |
46 | { | 46 | { |
47 | static size_t buff_size; | 47 | static size_t buff_size; |
48 | int datasize, res, consumed, i, time_offset; | 48 | int datasize, res, consumed, i, time_offset; |
49 | uint8_t *bit_buffer; | 49 | uint8_t *bit_buffer; |
@@ -52,16 +52,14 @@ enum codec_status codec_main(void) | |||
52 | int scrambling_unit_size, num_units, elapsed = 0; | 52 | int scrambling_unit_size, num_units, elapsed = 0; |
53 | int playback_on = -1; | 53 | int playback_on = -1; |
54 | size_t resume_offset; | 54 | size_t resume_offset; |
55 | intptr_t param; | ||
56 | enum codec_command_action action = CODEC_ACTION_NULL; | ||
55 | 57 | ||
56 | next_track: | ||
57 | if (codec_init()) { | 58 | if (codec_init()) { |
58 | DEBUGF("codec init failed\n"); | 59 | DEBUGF("codec init failed\n"); |
59 | return CODEC_ERROR; | 60 | return CODEC_ERROR; |
60 | } | 61 | } |
61 | 62 | ||
62 | if (codec_wait_taginfo() != 0) | ||
63 | goto done; | ||
64 | |||
65 | resume_offset = ci->id3->offset; | 63 | resume_offset = ci->id3->offset; |
66 | 64 | ||
67 | codec_set_replaygain(ci->id3); | 65 | codec_set_replaygain(ci->id3); |
@@ -69,6 +67,7 @@ next_track: | |||
69 | ci->memset(&pkt,0,sizeof(RMPacket)); | 67 | ci->memset(&pkt,0,sizeof(RMPacket)); |
70 | ci->memset(&q,0,sizeof(ATRAC3Context)); | 68 | ci->memset(&q,0,sizeof(ATRAC3Context)); |
71 | 69 | ||
70 | ci->seek_buffer(0); | ||
72 | init_rm(&rmctx); | 71 | init_rm(&rmctx); |
73 | 72 | ||
74 | ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency); | 73 | ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency); |
@@ -84,22 +83,25 @@ next_track: | |||
84 | h = rmctx.sub_packet_h; | 83 | h = rmctx.sub_packet_h; |
85 | scrambling_unit_size = h*fs; | 84 | scrambling_unit_size = h*fs; |
86 | 85 | ||
87 | res =atrac3_decode_init(&q, ci->id3); | 86 | res = atrac3_decode_init(&q, ci->id3); |
88 | if(res < 0) { | 87 | if(res < 0) { |
89 | DEBUGF("failed to initialize RM atrac decoder\n"); | 88 | DEBUGF("failed to initialize RM atrac decoder\n"); |
90 | return CODEC_ERROR; | 89 | return CODEC_ERROR; |
91 | } | 90 | } |
92 | 91 | ||
93 | /* check for a mid-track resume and force a seek time accordingly */ | 92 | /* check for a mid-track resume and force a seek time accordingly */ |
94 | if(resume_offset > rmctx.data_offset + DATA_HEADER_SIZE) { | 93 | if(resume_offset > rmctx.data_offset + DATA_HEADER_SIZE) { |
95 | resume_offset -= rmctx.data_offset + DATA_HEADER_SIZE; | 94 | resume_offset -= rmctx.data_offset + DATA_HEADER_SIZE; |
96 | num_units = (int)resume_offset / scrambling_unit_size; | 95 | num_units = (int)resume_offset / scrambling_unit_size; |
97 | /* put number of subpackets to skip in resume_offset */ | 96 | /* put number of subpackets to skip in resume_offset */ |
98 | resume_offset /= (sps + PACKET_HEADER_SIZE); | 97 | resume_offset /= (sps + PACKET_HEADER_SIZE); |
99 | ci->seek_time = (int)resume_offset * ((sps * 8 * 1000)/rmctx.bit_rate); | 98 | param = (int)resume_offset * ((sps * 8 * 1000)/rmctx.bit_rate); |
99 | action = CODEC_ACTION_SEEK_TIME; | ||
100 | } | 100 | } |
101 | 101 | else { | |
102 | ci->set_elapsed(0); | 102 | ci->set_elapsed(0); |
103 | } | ||
104 | |||
103 | ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE); | 105 | ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE); |
104 | 106 | ||
105 | /* The main decoder loop */ | 107 | /* The main decoder loop */ |
@@ -115,22 +117,23 @@ seek_start : | |||
115 | return CODEC_ERROR; | 117 | return CODEC_ERROR; |
116 | } | 118 | } |
117 | else | 119 | else |
118 | goto done; | 120 | return CODEC_OK; |
119 | } | 121 | } |
120 | 122 | ||
121 | for(i = 0; i < rmctx.audio_pkt_cnt*(fs/sps) ; i++) | 123 | for(i = 0; i < rmctx.audio_pkt_cnt*(fs/sps) ; i++) |
122 | { | 124 | { |
123 | ci->yield(); | 125 | if (action == CODEC_ACTION_NULL) |
124 | if (ci->stop_codec || ci->new_track) | 126 | action = ci->get_command(¶m); |
125 | goto done; | ||
126 | 127 | ||
127 | if (ci->seek_time) { | 128 | if (action == CODEC_ACTION_HALT) |
128 | ci->set_elapsed(ci->seek_time); | 129 | return CODEC_OK; |
129 | 130 | ||
131 | if (action == CODEC_ACTION_SEEK_TIME) { | ||
130 | /* Do not allow seeking beyond the file's length */ | 132 | /* Do not allow seeking beyond the file's length */ |
131 | if ((unsigned) ci->seek_time > ci->id3->length) { | 133 | if ((unsigned) param > ci->id3->length) { |
134 | ci->set_elapsed(ci->id3->length); | ||
132 | ci->seek_complete(); | 135 | ci->seek_complete(); |
133 | goto done; | 136 | return CODEC_OK; |
134 | } | 137 | } |
135 | 138 | ||
136 | ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE); | 139 | ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE); |
@@ -139,12 +142,13 @@ seek_start : | |||
139 | rmctx.frame_number = 0; | 142 | rmctx.frame_number = 0; |
140 | 143 | ||
141 | /* Seek to the start of the track */ | 144 | /* Seek to the start of the track */ |
142 | if (ci->seek_time == 1) { | 145 | if (param == 0) { |
143 | ci->set_elapsed(0); | 146 | ci->set_elapsed(0); |
144 | ci->seek_complete(); | 147 | ci->seek_complete(); |
148 | action = CODEC_ACTION_NULL; | ||
145 | goto seek_start; | 149 | goto seek_start; |
146 | } | 150 | } |
147 | num_units = ((ci->seek_time)/(sps*1000*8/rmctx.bit_rate))/(h*(fs/sps)); | 151 | num_units = (param/(sps*1000*8/rmctx.bit_rate))/(h*(fs/sps)); |
148 | ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + consumed * num_units); | 152 | ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + consumed * num_units); |
149 | bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size); | 153 | bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size); |
150 | consumed = rm_get_packet(&bit_buffer, &rmctx, &pkt); | 154 | consumed = rm_get_packet(&bit_buffer, &rmctx, &pkt); |
@@ -155,12 +159,12 @@ seek_start : | |||
155 | return CODEC_ERROR; | 159 | return CODEC_ERROR; |
156 | } | 160 | } |
157 | else | 161 | else |
158 | goto done; | 162 | return CODEC_OK; |
159 | } | 163 | } |
160 | 164 | ||
161 | packet_count = rmctx.nb_packets - rmctx.audio_pkt_cnt * num_units; | 165 | packet_count = rmctx.nb_packets - rmctx.audio_pkt_cnt * num_units; |
162 | rmctx.frame_number = ((ci->seek_time)/(sps*1000*8/rmctx.bit_rate)); | 166 | rmctx.frame_number = (param/(sps*1000*8/rmctx.bit_rate)); |
163 | while(rmctx.audiotimestamp > (unsigned) ci->seek_time) { | 167 | while(rmctx.audiotimestamp > (unsigned) param) { |
164 | rmctx.audio_pkt_cnt = 0; | 168 | rmctx.audio_pkt_cnt = 0; |
165 | ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + consumed * (num_units-1)); | 169 | ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + consumed * (num_units-1)); |
166 | bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size); | 170 | bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size); |
@@ -168,16 +172,19 @@ seek_start : | |||
168 | packet_count += rmctx.audio_pkt_cnt; | 172 | packet_count += rmctx.audio_pkt_cnt; |
169 | num_units--; | 173 | num_units--; |
170 | } | 174 | } |
171 | time_offset = ci->seek_time - rmctx.audiotimestamp; | 175 | time_offset = param - rmctx.audiotimestamp; |
172 | i = (time_offset/((sps * 8 * 1000)/rmctx.bit_rate)); | 176 | i = (time_offset/((sps * 8 * 1000)/rmctx.bit_rate)); |
173 | elapsed = rmctx.audiotimestamp+(1000*8*sps/rmctx.bit_rate)*i; | 177 | elapsed = rmctx.audiotimestamp+(1000*8*sps/rmctx.bit_rate)*i; |
174 | ci->set_elapsed(elapsed); | 178 | ci->set_elapsed(elapsed); |
175 | ci->seek_complete(); | 179 | ci->seek_complete(); |
176 | } | 180 | } |
181 | |||
182 | action = CODEC_ACTION_NULL; | ||
183 | |||
177 | if(pkt.length) | 184 | if(pkt.length) |
178 | res = atrac3_decode_frame(rmctx.block_align, &q, &datasize, pkt.frames[i], rmctx.block_align); | 185 | res = atrac3_decode_frame(rmctx.block_align, &q, &datasize, pkt.frames[i], rmctx.block_align); |
179 | else /* indicates that there are no remaining frames */ | 186 | else /* indicates that there are no remaining frames */ |
180 | goto done; | 187 | return CODEC_OK; |
181 | 188 | ||
182 | if(res != rmctx.block_align) { | 189 | if(res != rmctx.block_align) { |
183 | DEBUGF("codec error\n"); | 190 | DEBUGF("codec error\n"); |
@@ -196,9 +203,5 @@ seek_start : | |||
196 | ci->advance_buffer(consumed); | 203 | ci->advance_buffer(consumed); |
197 | } | 204 | } |
198 | 205 | ||
199 | done : | 206 | return CODEC_OK; |
200 | if (ci->request_next_track()) | ||
201 | goto next_track; | ||
202 | |||
203 | return CODEC_OK; | ||
204 | } | 207 | } |
diff --git a/apps/codecs/au.c b/apps/codecs/au.c index 3f9436c9e7..e06f931cf9 100644 --- a/apps/codecs/au.c +++ b/apps/codecs/au.c | |||
@@ -106,9 +106,19 @@ static int convert_au_format(unsigned int encoding, struct pcm_format *fmt) | |||
106 | } | 106 | } |
107 | 107 | ||
108 | /* this is the codec entry point */ | 108 | /* this is the codec entry point */ |
109 | enum codec_status codec_main(void) | 109 | enum codec_status codec_main(enum codec_entry_call_reason reason) |
110 | { | ||
111 | if (reason == CODEC_LOAD) { | ||
112 | /* Generic codec initialisation */ | ||
113 | ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1); | ||
114 | } | ||
115 | |||
116 | return CODEC_OK; | ||
117 | } | ||
118 | |||
119 | /* this is called for each file to process */ | ||
120 | enum codec_status codec_run(void) | ||
110 | { | 121 | { |
111 | int status; | ||
112 | struct pcm_format format; | 122 | struct pcm_format format; |
113 | uint32_t bytesdone, decodedsamples; | 123 | uint32_t bytesdone, decodedsamples; |
114 | size_t n; | 124 | size_t n; |
@@ -119,22 +129,13 @@ enum codec_status codec_main(void) | |||
119 | off_t firstblockposn; /* position of the first block in file */ | 129 | off_t firstblockposn; /* position of the first block in file */ |
120 | const struct pcm_codec *codec; | 130 | const struct pcm_codec *codec; |
121 | int offset = 0; | 131 | int offset = 0; |
122 | 132 | intptr_t param; | |
123 | /* Generic codec initialisation */ | 133 | |
124 | ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1); | ||
125 | |||
126 | next_track: | ||
127 | status = CODEC_OK; | ||
128 | |||
129 | if (codec_init()) { | 134 | if (codec_init()) { |
130 | DEBUGF("codec_init() error\n"); | 135 | DEBUGF("codec_init() error\n"); |
131 | status = CODEC_ERROR; | 136 | return CODEC_ERROR; |
132 | goto exit; | ||
133 | } | 137 | } |
134 | 138 | ||
135 | if (codec_wait_taginfo() != 0) | ||
136 | goto done; | ||
137 | |||
138 | codec_set_replaygain(ci->id3); | 139 | codec_set_replaygain(ci->id3); |
139 | 140 | ||
140 | /* Need to save offset for later use (cleared indirectly by advance_buffer) */ | 141 | /* Need to save offset for later use (cleared indirectly by advance_buffer) */ |
@@ -145,6 +146,7 @@ next_track: | |||
145 | format.is_little_endian = false; | 146 | format.is_little_endian = false; |
146 | 147 | ||
147 | /* set format */ | 148 | /* set format */ |
149 | ci->seek_buffer(0); | ||
148 | buf = ci->request_buffer(&n, 24); | 150 | buf = ci->request_buffer(&n, 24); |
149 | if (n < 24 || (memcmp(buf, ".snd", 4) != 0)) | 151 | if (n < 24 || (memcmp(buf, ".snd", 4) != 0)) |
150 | { | 152 | { |
@@ -170,8 +172,7 @@ next_track: | |||
170 | if (offset < 24) | 172 | if (offset < 24) |
171 | { | 173 | { |
172 | DEBUGF("CODEC_ERROR: sun audio offset size is small: %d\n", offset); | 174 | DEBUGF("CODEC_ERROR: sun audio offset size is small: %d\n", offset); |
173 | status = CODEC_ERROR; | 175 | return CODEC_ERROR; |
174 | goto done; | ||
175 | } | 176 | } |
176 | /* data size */ | 177 | /* data size */ |
177 | format.numbytes = get_be32(buf + 8); | 178 | format.numbytes = get_be32(buf + 8); |
@@ -182,8 +183,7 @@ next_track: | |||
182 | if (format.formattag == AU_FORMAT_UNSUPPORT) | 183 | if (format.formattag == AU_FORMAT_UNSUPPORT) |
183 | { | 184 | { |
184 | DEBUGF("CODEC_ERROR: sun audio unsupport format: %d\n", get_be32(buf + 12)); | 185 | DEBUGF("CODEC_ERROR: sun audio unsupport format: %d\n", get_be32(buf + 12)); |
185 | status = CODEC_ERROR; | 186 | return CODEC_ERROR; |
186 | goto done; | ||
187 | } | 187 | } |
188 | /* skip sample rate */ | 188 | /* skip sample rate */ |
189 | format.channels = get_be32(buf + 20); | 189 | format.channels = get_be32(buf + 20); |
@@ -202,20 +202,17 @@ next_track: | |||
202 | if (!codec) | 202 | if (!codec) |
203 | { | 203 | { |
204 | DEBUGF("CODEC_ERROR: unsupport sun audio format: %x\n", (int)format.formattag); | 204 | DEBUGF("CODEC_ERROR: unsupport sun audio format: %x\n", (int)format.formattag); |
205 | status = CODEC_ERROR; | 205 | return CODEC_ERROR; |
206 | goto done; | ||
207 | } | 206 | } |
208 | 207 | ||
209 | if (!codec->set_format(&format)) | 208 | if (!codec->set_format(&format)) |
210 | { | 209 | { |
211 | status = CODEC_ERROR; | 210 | return CODEC_ERROR; |
212 | goto done; | ||
213 | } | 211 | } |
214 | 212 | ||
215 | if (format.numbytes == 0) { | 213 | if (format.numbytes == 0) { |
216 | DEBUGF("CODEC_ERROR: data size is 0\n"); | 214 | DEBUGF("CODEC_ERROR: data size is 0\n"); |
217 | status = CODEC_ERROR; | 215 | return CODEC_ERROR; |
218 | goto done; | ||
219 | } | 216 | } |
220 | 217 | ||
221 | /* check chunksize */ | 218 | /* check chunksize */ |
@@ -225,8 +222,7 @@ next_track: | |||
225 | if (format.chunksize == 0) | 222 | if (format.chunksize == 0) |
226 | { | 223 | { |
227 | DEBUGF("CODEC_ERROR: chunksize is 0\n"); | 224 | DEBUGF("CODEC_ERROR: chunksize is 0\n"); |
228 | status = CODEC_ERROR; | 225 | return CODEC_ERROR; |
229 | goto done; | ||
230 | } | 226 | } |
231 | 227 | ||
232 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); | 228 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); |
@@ -236,8 +232,7 @@ next_track: | |||
236 | ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); | 232 | ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); |
237 | } else { | 233 | } else { |
238 | DEBUGF("CODEC_ERROR: more than 2 channels\n"); | 234 | DEBUGF("CODEC_ERROR: more than 2 channels\n"); |
239 | status = CODEC_ERROR; | 235 | return CODEC_ERROR; |
240 | goto done; | ||
241 | } | 236 | } |
242 | 237 | ||
243 | /* make sure we're at the correct offset */ | 238 | /* make sure we're at the correct offset */ |
@@ -253,7 +248,6 @@ next_track: | |||
253 | bytesdone = newpos->pos; | 248 | bytesdone = newpos->pos; |
254 | decodedsamples = newpos->samples; | 249 | decodedsamples = newpos->samples; |
255 | } | 250 | } |
256 | ci->seek_complete(); | ||
257 | } else { | 251 | } else { |
258 | /* already where we need to be */ | 252 | /* already where we need to be */ |
259 | bytesdone = 0; | 253 | bytesdone = 0; |
@@ -263,22 +257,29 @@ next_track: | |||
263 | endofstream = 0; | 257 | endofstream = 0; |
264 | 258 | ||
265 | while (!endofstream) { | 259 | while (!endofstream) { |
266 | ci->yield(); | 260 | enum codec_command_action action = ci->get_command(¶m); |
267 | if (ci->stop_codec || ci->new_track) { | 261 | |
262 | if (action == CODEC_ACTION_HALT) | ||
268 | break; | 263 | break; |
269 | } | ||
270 | 264 | ||
271 | if (ci->seek_time) { | 265 | if (action == CODEC_ACTION_SEEK_TIME) { |
272 | /* 3rd args(read_buffer) is unnecessary in the format which Sun Audio supports. */ | 266 | /* 3rd args(read_buffer) is unnecessary in the format which Sun Audio supports. */ |
273 | struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, PCM_SEEK_TIME, NULL); | 267 | struct pcm_pos *newpos = codec->get_seek_pos(param, PCM_SEEK_TIME, NULL); |
274 | 268 | ||
275 | if (newpos->pos > format.numbytes) | 269 | if (newpos->pos > format.numbytes) |
270 | { | ||
271 | ci->set_elapsed(ci->id3->length); | ||
272 | ci->seek_complete(); | ||
276 | break; | 273 | break; |
274 | } | ||
275 | |||
277 | if (ci->seek_buffer(firstblockposn + newpos->pos)) | 276 | if (ci->seek_buffer(firstblockposn + newpos->pos)) |
278 | { | 277 | { |
279 | bytesdone = newpos->pos; | 278 | bytesdone = newpos->pos; |
280 | decodedsamples = newpos->samples; | 279 | decodedsamples = newpos->samples; |
281 | } | 280 | } |
281 | |||
282 | ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); | ||
282 | ci->seek_complete(); | 283 | ci->seek_complete(); |
283 | } | 284 | } |
284 | 285 | ||
@@ -290,11 +291,10 @@ next_track: | |||
290 | endofstream = 1; | 291 | endofstream = 1; |
291 | } | 292 | } |
292 | 293 | ||
293 | status = codec->decode(aubuf, n, samples, &bufcount); | 294 | if (codec->decode(aubuf, n, samples, &bufcount) == CODEC_ERROR) |
294 | if (status == CODEC_ERROR) | ||
295 | { | 295 | { |
296 | DEBUGF("codec error\n"); | 296 | DEBUGF("codec error\n"); |
297 | goto done; | 297 | return CODEC_ERROR; |
298 | } | 298 | } |
299 | 299 | ||
300 | ci->pcmbuf_insert(samples, NULL, bufcount); | 300 | ci->pcmbuf_insert(samples, NULL, bufcount); |
@@ -308,9 +308,5 @@ next_track: | |||
308 | } | 308 | } |
309 | 309 | ||
310 | done: | 310 | done: |
311 | if (ci->request_next_track()) | 311 | return CODEC_OK; |
312 | goto next_track; | ||
313 | |||
314 | exit: | ||
315 | return status; | ||
316 | } | 312 | } |
diff --git a/apps/codecs/codec_crt0.c b/apps/codecs/codec_crt0.c index cf14e460ec..33876272c6 100644 --- a/apps/codecs/codec_crt0.c +++ b/apps/codecs/codec_crt0.c | |||
@@ -27,39 +27,45 @@ struct codec_api *ci DATA_ATTR; | |||
27 | extern unsigned char plugin_bss_start[]; | 27 | extern unsigned char plugin_bss_start[]; |
28 | extern unsigned char plugin_end_addr[]; | 28 | extern unsigned char plugin_end_addr[]; |
29 | 29 | ||
30 | extern enum codec_status codec_main(void); | 30 | extern enum codec_status codec_main(enum codec_entry_call_reason reason); |
31 | 31 | ||
32 | /* stub, the entry point is called via its reference in __header to | 32 | /* stub, the entry point is called via its reference in __header to |
33 | * avoid warning with certain compilers */ | 33 | * avoid warning with certain compilers */ |
34 | int _start(void) {return 0;} | 34 | int _start(void) {return 0;} |
35 | 35 | ||
36 | enum codec_status codec_start(void) | 36 | enum codec_status codec_start(enum codec_entry_call_reason reason) |
37 | { | 37 | { |
38 | #if (CONFIG_PLATFORM & PLATFORM_NATIVE) | 38 | #if (CONFIG_PLATFORM & PLATFORM_NATIVE) |
39 | #ifdef USE_IRAM | 39 | if (reason == CODEC_LOAD) |
40 | extern char iramcopy[], iramstart[], iramend[], iedata[], iend[]; | ||
41 | size_t iram_size = iramend - iramstart; | ||
42 | size_t ibss_size = iend - iedata; | ||
43 | if (iram_size > 0 || ibss_size > 0) | ||
44 | { | 40 | { |
45 | ci->memcpy(iramstart, iramcopy, iram_size); | 41 | #ifdef USE_IRAM |
46 | ci->memset(iedata, 0, ibss_size); | 42 | extern char iramcopy[], iramstart[], iramend[], iedata[], iend[]; |
47 | /* make the icache (if it exists) up to date with the new code */ | 43 | size_t iram_size = iramend - iramstart; |
44 | size_t ibss_size = iend - iedata; | ||
45 | if (iram_size > 0 || ibss_size > 0) | ||
46 | { | ||
47 | ci->memcpy(iramstart, iramcopy, iram_size); | ||
48 | ci->memset(iedata, 0, ibss_size); | ||
49 | /* make the icache (if it exists) up to date with the new code */ | ||
50 | ci->cpucache_invalidate(); | ||
51 | /* barrier to prevent reordering iram copy and BSS clearing, | ||
52 | * because the BSS segment alias the IRAM copy. | ||
53 | */ | ||
54 | asm volatile ("" ::: "memory"); | ||
55 | } | ||
56 | #endif /* PLUGIN_USE_IRAM */ | ||
57 | ci->memset(plugin_bss_start, 0, plugin_end_addr - plugin_bss_start); | ||
58 | /* Some parts of bss may be used via a no-cache alias (at least | ||
59 | * portalplayer has this). If we don't clear the cache, those aliases | ||
60 | * may read garbage */ | ||
48 | ci->cpucache_invalidate(); | 61 | ci->cpucache_invalidate(); |
49 | /* barrier to prevent reordering iram copy and BSS clearing, | ||
50 | * because the BSS segment alias the IRAM copy. | ||
51 | */ | ||
52 | asm volatile ("" ::: "memory"); | ||
53 | } | 62 | } |
54 | #endif /* PLUGIN_USE_IRAM */ | 63 | #endif /* CONFIG_PLATFORM */ |
55 | ci->memset(plugin_bss_start, 0, plugin_end_addr - plugin_bss_start); | ||
56 | /* Some parts of bss may be used via a no-cache alias (at least | ||
57 | * portalplayer has this). If we don't clear the cache, those aliases | ||
58 | * may read garbage */ | ||
59 | ci->cpucache_invalidate(); | ||
60 | #endif | ||
61 | 64 | ||
62 | return codec_main(); | 65 | /* Note: If for any reason codec_main would not be called with CODEC_LOAD |
66 | * because the above code failed then it must not be ever be called with | ||
67 | * any other value and some strategy to avoid doing so must be conceived */ | ||
68 | return codec_main(reason); | ||
63 | } | 69 | } |
64 | 70 | ||
65 | #if defined(CPU_ARM) && (CONFIG_PLATFORM & PLATFORM_NATIVE) | 71 | #if defined(CPU_ARM) && (CONFIG_PLATFORM & PLATFORM_NATIVE) |
diff --git a/apps/codecs/cook.c b/apps/codecs/cook.c index 015618986c..a6b4a1153e 100644 --- a/apps/codecs/cook.c +++ b/apps/codecs/cook.c | |||
@@ -38,9 +38,9 @@ static void init_rm(RMContext *rmctx) | |||
38 | memcpy(rmctx, (void*)(( (intptr_t)ci->id3->id3v2buf + 3 ) &~ 3), sizeof(RMContext)); | 38 | memcpy(rmctx, (void*)(( (intptr_t)ci->id3->id3v2buf + 3 ) &~ 3), sizeof(RMContext)); |
39 | } | 39 | } |
40 | 40 | ||
41 | /* this is the codec entry point */ | 41 | /* this is called for each file to process */ |
42 | enum codec_status codec_main(void) | 42 | enum codec_status codec_run(void) |
43 | { | 43 | { |
44 | static size_t buff_size; | 44 | static size_t buff_size; |
45 | int datasize, res, consumed, i, time_offset; | 45 | int datasize, res, consumed, i, time_offset; |
46 | uint8_t *bit_buffer; | 46 | uint8_t *bit_buffer; |
@@ -48,16 +48,14 @@ enum codec_status codec_main(void) | |||
48 | uint32_t packet_count; | 48 | uint32_t packet_count; |
49 | int scrambling_unit_size, num_units; | 49 | int scrambling_unit_size, num_units; |
50 | size_t resume_offset; | 50 | size_t resume_offset; |
51 | intptr_t param = 0; | ||
52 | enum codec_command_action action = CODEC_ACTION_NULL; | ||
51 | 53 | ||
52 | next_track: | ||
53 | if (codec_init()) { | 54 | if (codec_init()) { |
54 | DEBUGF("codec init failed\n"); | 55 | DEBUGF("codec init failed\n"); |
55 | return CODEC_ERROR; | 56 | return CODEC_ERROR; |
56 | } | 57 | } |
57 | 58 | ||
58 | if (codec_wait_taginfo() != 0) | ||
59 | goto done; | ||
60 | |||
61 | resume_offset = ci->id3->offset; | 59 | resume_offset = ci->id3->offset; |
62 | 60 | ||
63 | codec_set_replaygain(ci->id3); | 61 | codec_set_replaygain(ci->id3); |
@@ -65,6 +63,8 @@ next_track: | |||
65 | ci->memset(&pkt,0,sizeof(RMPacket)); | 63 | ci->memset(&pkt,0,sizeof(RMPacket)); |
66 | ci->memset(&q,0,sizeof(COOKContext)); | 64 | ci->memset(&q,0,sizeof(COOKContext)); |
67 | 65 | ||
66 | ci->seek_buffer(0); | ||
67 | |||
68 | init_rm(&rmctx); | 68 | init_rm(&rmctx); |
69 | 69 | ||
70 | ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency); | 70 | ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency); |
@@ -87,20 +87,21 @@ next_track: | |||
87 | DEBUGF("failed to initialize cook decoder\n"); | 87 | DEBUGF("failed to initialize cook decoder\n"); |
88 | return CODEC_ERROR; | 88 | return CODEC_ERROR; |
89 | } | 89 | } |
90 | 90 | ||
91 | /* check for a mid-track resume and force a seek time accordingly */ | 91 | /* check for a mid-track resume and force a seek time accordingly */ |
92 | if(resume_offset > rmctx.data_offset + DATA_HEADER_SIZE) { | 92 | if(resume_offset > rmctx.data_offset + DATA_HEADER_SIZE) { |
93 | resume_offset -= rmctx.data_offset + DATA_HEADER_SIZE; | 93 | resume_offset -= rmctx.data_offset + DATA_HEADER_SIZE; |
94 | num_units = (int)resume_offset / scrambling_unit_size; | 94 | num_units = (int)resume_offset / scrambling_unit_size; |
95 | /* put number of subpackets to skip in resume_offset */ | 95 | /* put number of subpackets to skip in resume_offset */ |
96 | resume_offset /= (sps + PACKET_HEADER_SIZE); | 96 | resume_offset /= (sps + PACKET_HEADER_SIZE); |
97 | ci->seek_time = (int)resume_offset * ((sps * 8 * 1000)/rmctx.bit_rate); | 97 | param = (int)resume_offset * ((sps * 8 * 1000)/rmctx.bit_rate); |
98 | action = CODEC_ACTION_SEEK_TIME; | ||
98 | } | 99 | } |
99 | 100 | ||
100 | ci->set_elapsed(0); | 101 | ci->set_elapsed(0); |
101 | ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE); | 102 | ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE); |
102 | 103 | ||
103 | /* The main decoder loop */ | 104 | /* The main decoder loop */ |
104 | seek_start : | 105 | seek_start : |
105 | while(packet_count) | 106 | while(packet_count) |
106 | { | 107 | { |
@@ -112,18 +113,19 @@ seek_start : | |||
112 | } | 113 | } |
113 | 114 | ||
114 | for(i = 0; i < rmctx.audio_pkt_cnt*(fs/sps) ; i++) | 115 | for(i = 0; i < rmctx.audio_pkt_cnt*(fs/sps) ; i++) |
115 | { | 116 | { |
116 | ci->yield(); | 117 | if (action == CODEC_ACTION_NULL) |
117 | if (ci->stop_codec || ci->new_track) | 118 | action = ci->get_command(¶m); |
118 | goto done; | ||
119 | 119 | ||
120 | if (ci->seek_time) { | 120 | if (action == CODEC_ACTION_HALT) |
121 | ci->set_elapsed(ci->seek_time); | 121 | return CODEC_OK; |
122 | 122 | ||
123 | if (action == CODEC_ACTION_SEEK_TIME) { | ||
123 | /* Do not allow seeking beyond the file's length */ | 124 | /* Do not allow seeking beyond the file's length */ |
124 | if ((unsigned) ci->seek_time > ci->id3->length) { | 125 | if ((unsigned) param > ci->id3->length) { |
126 | ci->set_elapsed(ci->id3->length); | ||
125 | ci->seek_complete(); | 127 | ci->seek_complete(); |
126 | goto done; | 128 | return CODEC_OK; |
127 | } | 129 | } |
128 | 130 | ||
129 | ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE); | 131 | ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE); |
@@ -132,22 +134,24 @@ seek_start : | |||
132 | rmctx.frame_number = 0; | 134 | rmctx.frame_number = 0; |
133 | 135 | ||
134 | /* Seek to the start of the track */ | 136 | /* Seek to the start of the track */ |
135 | if (ci->seek_time == 1) { | 137 | if (param == 0) { |
136 | ci->set_elapsed(0); | 138 | ci->set_elapsed(0); |
137 | ci->seek_complete(); | 139 | ci->seek_complete(); |
140 | action = CODEC_ACTION_NULL; | ||
138 | goto seek_start; | 141 | goto seek_start; |
139 | } | 142 | } |
140 | num_units = ((ci->seek_time)/(sps*1000*8/rmctx.bit_rate))/(h*(fs/sps)); | 143 | num_units = (param/(sps*1000*8/rmctx.bit_rate))/(h*(fs/sps)); |
141 | ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + consumed * num_units); | 144 | ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + consumed * num_units); |
142 | bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size); | 145 | bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size); |
143 | consumed = rm_get_packet(&bit_buffer, &rmctx, &pkt); | 146 | consumed = rm_get_packet(&bit_buffer, &rmctx, &pkt); |
144 | if(consumed < 0) { | 147 | if(consumed < 0) { |
145 | DEBUGF("rm_get_packet failed\n"); | 148 | DEBUGF("rm_get_packet failed\n"); |
146 | return CODEC_ERROR; | 149 | ci->seek_complete(); |
150 | return CODEC_ERROR; | ||
147 | } | 151 | } |
148 | packet_count = rmctx.nb_packets - rmctx.audio_pkt_cnt * num_units; | 152 | packet_count = rmctx.nb_packets - rmctx.audio_pkt_cnt * num_units; |
149 | rmctx.frame_number = ((ci->seek_time)/(sps*1000*8/rmctx.bit_rate)); | 153 | rmctx.frame_number = (param/(sps*1000*8/rmctx.bit_rate)); |
150 | while(rmctx.audiotimestamp > (unsigned) ci->seek_time) { | 154 | while(rmctx.audiotimestamp > (unsigned) param) { |
151 | rmctx.audio_pkt_cnt = 0; | 155 | rmctx.audio_pkt_cnt = 0; |
152 | ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + consumed * (num_units-1)); | 156 | ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + consumed * (num_units-1)); |
153 | bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size); | 157 | bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size); |
@@ -155,11 +159,14 @@ seek_start : | |||
155 | packet_count += rmctx.audio_pkt_cnt; | 159 | packet_count += rmctx.audio_pkt_cnt; |
156 | num_units--; | 160 | num_units--; |
157 | } | 161 | } |
158 | time_offset = ci->seek_time - rmctx.audiotimestamp; | 162 | time_offset = param - rmctx.audiotimestamp; |
159 | i = (time_offset/((sps * 8 * 1000)/rmctx.bit_rate)); | 163 | i = (time_offset/((sps * 8 * 1000)/rmctx.bit_rate)); |
160 | ci->set_elapsed(rmctx.audiotimestamp+(1000*8*sps/rmctx.bit_rate)*i); | 164 | ci->set_elapsed(rmctx.audiotimestamp+(1000*8*sps/rmctx.bit_rate)*i); |
161 | ci->seek_complete(); | 165 | ci->seek_complete(); |
162 | } | 166 | } |
167 | |||
168 | action = CODEC_ACTION_NULL; | ||
169 | |||
163 | res = cook_decode_frame(&rmctx,&q, rm_outbuf, &datasize, pkt.frames[i], rmctx.block_align); | 170 | res = cook_decode_frame(&rmctx,&q, rm_outbuf, &datasize, pkt.frames[i], rmctx.block_align); |
164 | rmctx.frame_number++; | 171 | rmctx.frame_number++; |
165 | 172 | ||
@@ -181,9 +188,5 @@ seek_start : | |||
181 | ci->advance_buffer(consumed); | 188 | ci->advance_buffer(consumed); |
182 | } | 189 | } |
183 | 190 | ||
184 | done : | 191 | return CODEC_OK; |
185 | if (ci->request_next_track()) | ||
186 | goto next_track; | ||
187 | |||
188 | return CODEC_OK; | ||
189 | } | 192 | } |
diff --git a/apps/codecs/flac.c b/apps/codecs/flac.c index 89d14b98a7..a5521b584f 100644 --- a/apps/codecs/flac.c +++ b/apps/codecs/flac.c | |||
@@ -418,40 +418,40 @@ static bool flac_seek_offset(FLACContext* fc, uint32_t offset) { | |||
418 | } | 418 | } |
419 | 419 | ||
420 | /* this is the codec entry point */ | 420 | /* this is the codec entry point */ |
421 | enum codec_status codec_main(void) | 421 | enum codec_status codec_main(enum codec_entry_call_reason reason) |
422 | { | ||
423 | if (reason == CODEC_LOAD) { | ||
424 | /* Generic codec initialisation */ | ||
425 | ci->configure(DSP_SET_SAMPLE_DEPTH, FLAC_OUTPUT_DEPTH-1); | ||
426 | } | ||
427 | |||
428 | return CODEC_OK; | ||
429 | } | ||
430 | |||
431 | /* this is called for each file to process */ | ||
432 | enum codec_status codec_run(void) | ||
422 | { | 433 | { |
423 | int8_t *buf; | 434 | int8_t *buf; |
424 | FLACContext fc; | 435 | FLACContext fc; |
425 | uint32_t samplesdone = 0; | 436 | uint32_t samplesdone; |
426 | uint32_t elapsedtime; | 437 | uint32_t elapsedtime; |
427 | size_t bytesleft; | 438 | size_t bytesleft; |
428 | int consumed; | 439 | int consumed; |
429 | int res; | 440 | int res; |
430 | int frame; | 441 | int frame; |
431 | int retval; | 442 | intptr_t param; |
432 | |||
433 | /* Generic codec initialisation */ | ||
434 | ci->configure(DSP_SET_SAMPLE_DEPTH, FLAC_OUTPUT_DEPTH-1); | ||
435 | 443 | ||
436 | next_track: | ||
437 | retval = CODEC_OK; | ||
438 | |||
439 | if (codec_init()) { | 444 | if (codec_init()) { |
440 | LOGF("FLAC: Error initialising codec\n"); | 445 | LOGF("FLAC: Error initialising codec\n"); |
441 | retval = CODEC_ERROR; | 446 | return CODEC_ERROR; |
442 | goto exit; | ||
443 | } | 447 | } |
444 | 448 | ||
445 | if (codec_wait_taginfo() != 0) | ||
446 | goto done; | ||
447 | |||
448 | /* Need to save offset for later use (cleared indirectly by flac_init) */ | 449 | /* Need to save offset for later use (cleared indirectly by flac_init) */ |
449 | samplesdone = ci->id3->offset; | 450 | samplesdone = ci->id3->offset; |
450 | 451 | ||
451 | if (!flac_init(&fc,ci->id3->first_frame_offset)) { | 452 | if (!flac_init(&fc,ci->id3->first_frame_offset)) { |
452 | LOGF("FLAC: Error initialising codec\n"); | 453 | LOGF("FLAC: Error initialising codec\n"); |
453 | retval = CODEC_ERROR; | 454 | return CODEC_ERROR; |
454 | goto done; | ||
455 | } | 455 | } |
456 | 456 | ||
457 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); | 457 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); |
@@ -459,35 +459,34 @@ next_track: | |||
459 | STEREO_MONO : STEREO_NONINTERLEAVED); | 459 | STEREO_MONO : STEREO_NONINTERLEAVED); |
460 | codec_set_replaygain(ci->id3); | 460 | codec_set_replaygain(ci->id3); |
461 | 461 | ||
462 | if (samplesdone) { | 462 | flac_seek_offset(&fc, samplesdone); |
463 | flac_seek_offset(&fc, samplesdone); | 463 | samplesdone=0; |
464 | samplesdone=0; | ||
465 | } | ||
466 | 464 | ||
467 | /* The main decoding loop */ | 465 | /* The main decoding loop */ |
468 | frame=0; | 466 | frame=0; |
469 | buf = ci->request_buffer(&bytesleft, MAX_FRAMESIZE); | 467 | buf = ci->request_buffer(&bytesleft, MAX_FRAMESIZE); |
470 | while (bytesleft) { | 468 | while (bytesleft) { |
471 | ci->yield(); | 469 | enum codec_command_action action = ci->get_command(¶m); |
472 | if (ci->stop_codec || ci->new_track) { | 470 | |
471 | if (action == CODEC_ACTION_HALT) | ||
473 | break; | 472 | break; |
474 | } | ||
475 | 473 | ||
476 | /* Deal with any pending seek requests */ | 474 | /* Deal with any pending seek requests */ |
477 | if (ci->seek_time) { | 475 | if (action == CODEC_ACTION_SEEK_TIME) { |
478 | if (flac_seek(&fc,(uint32_t)(((uint64_t)(ci->seek_time-1) | 476 | if (flac_seek(&fc,(uint32_t)(((uint64_t)param |
479 | *ci->id3->frequency)/1000))) { | 477 | *ci->id3->frequency)/1000))) { |
480 | /* Refill the input buffer */ | 478 | /* Refill the input buffer */ |
481 | buf = ci->request_buffer(&bytesleft, MAX_FRAMESIZE); | 479 | buf = ci->request_buffer(&bytesleft, MAX_FRAMESIZE); |
482 | } | 480 | } |
481 | |||
482 | ci->set_elapsed(param); | ||
483 | ci->seek_complete(); | 483 | ci->seek_complete(); |
484 | } | 484 | } |
485 | 485 | ||
486 | if((res=flac_decode_frame(&fc,decoded0,decoded1,buf, | 486 | if((res=flac_decode_frame(&fc,decoded0,decoded1,buf, |
487 | bytesleft,ci->yield)) < 0) { | 487 | bytesleft,ci->yield)) < 0) { |
488 | LOGF("FLAC: Frame %d, error %d\n",frame,res); | 488 | LOGF("FLAC: Frame %d, error %d\n",frame,res); |
489 | retval = CODEC_ERROR; | 489 | return CODEC_ERROR; |
490 | goto done; | ||
491 | } | 490 | } |
492 | consumed=fc.gb.index/8; | 491 | consumed=fc.gb.index/8; |
493 | frame++; | 492 | frame++; |
@@ -507,14 +506,7 @@ next_track: | |||
507 | 506 | ||
508 | buf = ci->request_buffer(&bytesleft, MAX_FRAMESIZE); | 507 | buf = ci->request_buffer(&bytesleft, MAX_FRAMESIZE); |
509 | } | 508 | } |
510 | retval = CODEC_OK; | ||
511 | 509 | ||
512 | done: | ||
513 | LOGF("FLAC: Decoded %lu samples\n",(unsigned long)samplesdone); | 510 | LOGF("FLAC: Decoded %lu samples\n",(unsigned long)samplesdone); |
514 | 511 | return CODEC_OK; | |
515 | if (ci->request_next_track()) | ||
516 | goto next_track; | ||
517 | |||
518 | exit: | ||
519 | return retval; | ||
520 | } | 512 | } |
diff --git a/apps/codecs/lib/codeclib.c b/apps/codecs/lib/codeclib.c index af0894c498..443c0bbdcf 100644 --- a/apps/codecs/lib/codeclib.c +++ b/apps/codecs/lib/codeclib.c | |||
@@ -33,6 +33,16 @@ unsigned char* mp3buf; // The actual MP3 buffer from Rockbox | |||
33 | unsigned char* mallocbuf; // 512K from the start of MP3 buffer | 33 | unsigned char* mallocbuf; // 512K from the start of MP3 buffer |
34 | unsigned char* filebuf; // The rest of the MP3 buffer | 34 | unsigned char* filebuf; // The rest of the MP3 buffer |
35 | 35 | ||
36 | /* this is the default codec entry point for when nothing needs to be done | ||
37 | on load or unload */ | ||
38 | enum codec_status __attribute__((weak)) | ||
39 | codec_main(enum codec_entry_call_reason reason) | ||
40 | { | ||
41 | /* Nothing to do */ | ||
42 | return CODEC_OK; | ||
43 | (void)reason; | ||
44 | } | ||
45 | |||
36 | int codec_init(void) | 46 | int codec_init(void) |
37 | { | 47 | { |
38 | mem_ptr = 0; | 48 | mem_ptr = 0; |
@@ -41,7 +51,7 @@ int codec_init(void) | |||
41 | return 0; | 51 | return 0; |
42 | } | 52 | } |
43 | 53 | ||
44 | void codec_set_replaygain(struct mp3entry* id3) | 54 | void codec_set_replaygain(const struct mp3entry *id3) |
45 | { | 55 | { |
46 | ci->configure(DSP_SET_TRACK_GAIN, id3->track_gain); | 56 | ci->configure(DSP_SET_TRACK_GAIN, id3->track_gain); |
47 | ci->configure(DSP_SET_ALBUM_GAIN, id3->album_gain); | 57 | ci->configure(DSP_SET_ALBUM_GAIN, id3->album_gain); |
@@ -49,19 +59,6 @@ void codec_set_replaygain(struct mp3entry* id3) | |||
49 | ci->configure(DSP_SET_ALBUM_PEAK, id3->album_peak); | 59 | ci->configure(DSP_SET_ALBUM_PEAK, id3->album_peak); |
50 | } | 60 | } |
51 | 61 | ||
52 | /* Note: codec really needs its own private metdata copy for the current | ||
53 | track being processed in order to be stable. */ | ||
54 | int codec_wait_taginfo(void) | ||
55 | { | ||
56 | while (!*ci->taginfo_ready && !ci->stop_codec && !ci->new_track) | ||
57 | ci->sleep(0); | ||
58 | if (ci->stop_codec) | ||
59 | return -1; | ||
60 | if (ci->new_track) | ||
61 | return 1; | ||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | /* Various "helper functions" common to all the xxx2wav decoder plugins */ | 62 | /* Various "helper functions" common to all the xxx2wav decoder plugins */ |
66 | 63 | ||
67 | 64 | ||
diff --git a/apps/codecs/lib/codeclib.h b/apps/codecs/lib/codeclib.h index 41b466ed1f..30091c5333 100644 --- a/apps/codecs/lib/codeclib.h +++ b/apps/codecs/lib/codeclib.h | |||
@@ -156,8 +156,7 @@ static inline unsigned int bs_generic(unsigned int v, int mode) | |||
156 | /* Various codec helper functions */ | 156 | /* Various codec helper functions */ |
157 | 157 | ||
158 | int codec_init(void); | 158 | int codec_init(void); |
159 | void codec_set_replaygain(struct mp3entry* id3); | 159 | void codec_set_replaygain(const struct mp3entry *id3); |
160 | int codec_wait_taginfo(void); /* 0 = success */ | ||
161 | 160 | ||
162 | #ifdef RB_PROFILE | 161 | #ifdef RB_PROFILE |
163 | void __cyg_profile_func_enter(void *this_fn, void *call_site) | 162 | void __cyg_profile_func_enter(void *this_fn, void *call_site) |
diff --git a/apps/codecs/mod.c b/apps/codecs/mod.c index 4ace721a1e..3dfaac663f 100644 --- a/apps/codecs/mod.c +++ b/apps/codecs/mod.c | |||
@@ -1218,47 +1218,37 @@ void synthrender(int32_t *renderbuffer, int samplecount) | |||
1218 | } | 1218 | } |
1219 | } | 1219 | } |
1220 | 1220 | ||
1221 | /* this is the codec entry point */ | ||
1222 | enum codec_status codec_main(enum codec_entry_call_reason reason) | ||
1223 | { | ||
1224 | if (reason == CODEC_LOAD) { | ||
1225 | /* Make use of 44.1khz */ | ||
1226 | ci->configure(DSP_SET_FREQUENCY, 44100); | ||
1227 | /* Sample depth is 28 bit host endian */ | ||
1228 | ci->configure(DSP_SET_SAMPLE_DEPTH, 28); | ||
1229 | /* Stereo output */ | ||
1230 | ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED); | ||
1231 | } | ||
1232 | |||
1233 | return CODEC_OK; | ||
1234 | } | ||
1221 | 1235 | ||
1222 | enum codec_status codec_main(void) | 1236 | /* this is called for each file to process */ |
1237 | enum codec_status codec_run(void) | ||
1223 | { | 1238 | { |
1224 | size_t n; | 1239 | size_t n; |
1225 | unsigned char *modfile; | 1240 | unsigned char *modfile; |
1226 | int old_patterntableposition; | 1241 | int old_patterntableposition; |
1227 | |||
1228 | int bytesdone; | 1242 | int bytesdone; |
1243 | intptr_t param; | ||
1229 | 1244 | ||
1230 | next_track: | ||
1231 | if (codec_init()) { | 1245 | if (codec_init()) { |
1232 | return CODEC_ERROR; | 1246 | return CODEC_ERROR; |
1233 | } | 1247 | } |
1234 | 1248 | ||
1235 | if (codec_wait_taginfo() != 0) | ||
1236 | goto request_next_track; | ||
1237 | |||
1238 | codec_set_replaygain(ci->id3); | 1249 | codec_set_replaygain(ci->id3); |
1239 | 1250 | ||
1240 | /* Load MOD file */ | 1251 | /* Load MOD file */ |
1241 | /* | ||
1242 | * This is the save way | ||
1243 | |||
1244 | size_t bytesfree; | ||
1245 | unsigned int filesize; | ||
1246 | |||
1247 | p = modfile; | ||
1248 | bytesfree=sizeof(modfile); | ||
1249 | while ((n = ci->read_filebuf(p, bytesfree)) > 0) { | ||
1250 | p += n; | ||
1251 | bytesfree -= n; | ||
1252 | if (bytesfree == 0) | ||
1253 | return CODEC_ERROR; | ||
1254 | } | ||
1255 | filesize = p-modfile; | ||
1256 | |||
1257 | if (filesize == 0) | ||
1258 | return CODEC_ERROR; | ||
1259 | */ | ||
1260 | |||
1261 | /* Directly use mod in buffer */ | ||
1262 | ci->seek_buffer(0); | 1252 | ci->seek_buffer(0); |
1263 | modfile = ci->request_buffer(&n, ci->filesize); | 1253 | modfile = ci->request_buffer(&n, ci->filesize); |
1264 | if (!modfile || n < (size_t)ci->filesize) { | 1254 | if (!modfile || n < (size_t)ci->filesize) { |
@@ -1268,27 +1258,22 @@ next_track: | |||
1268 | initmodplayer(); | 1258 | initmodplayer(); |
1269 | loadmod(modfile); | 1259 | loadmod(modfile); |
1270 | 1260 | ||
1271 | /* Make use of 44.1khz */ | ||
1272 | ci->configure(DSP_SET_FREQUENCY, 44100); | ||
1273 | /* Sample depth is 28 bit host endian */ | ||
1274 | ci->configure(DSP_SET_SAMPLE_DEPTH, 28); | ||
1275 | /* Stereo output */ | ||
1276 | ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED); | ||
1277 | |||
1278 | /* The main decoder loop */ | 1261 | /* The main decoder loop */ |
1279 | ci->set_elapsed(0); | 1262 | ci->set_elapsed(0); |
1280 | bytesdone = 0; | 1263 | bytesdone = 0; |
1281 | old_patterntableposition = 0; | 1264 | old_patterntableposition = 0; |
1282 | 1265 | ||
1283 | while (1) { | 1266 | while (1) { |
1284 | ci->yield(); | 1267 | enum codec_command_action action = ci->get_command(¶m); |
1285 | if (ci->stop_codec || ci->new_track) | 1268 | |
1269 | if (action == CODEC_ACTION_HALT) | ||
1286 | break; | 1270 | break; |
1287 | 1271 | ||
1288 | if (ci->seek_time) { | 1272 | if (action == CODEC_ACTION_SEEK_TIME) { |
1289 | /* New time is ready in ci->seek_time */ | 1273 | /* New time is ready in param */ |
1290 | modplayer.patterntableposition = ci->seek_time/1000; | 1274 | modplayer.patterntableposition = param/1000; |
1291 | modplayer.currentline = 0; | 1275 | modplayer.currentline = 0; |
1276 | ci->set_elapsed(modplayer.patterntableposition*1000+500); | ||
1292 | ci->seek_complete(); | 1277 | ci->seek_complete(); |
1293 | } | 1278 | } |
1294 | 1279 | ||
@@ -1305,9 +1290,5 @@ next_track: | |||
1305 | 1290 | ||
1306 | } | 1291 | } |
1307 | 1292 | ||
1308 | request_next_track: | ||
1309 | if (ci->request_next_track()) | ||
1310 | goto next_track; | ||
1311 | |||
1312 | return CODEC_OK; | 1293 | return CODEC_OK; |
1313 | } | 1294 | } |
diff --git a/apps/codecs/mp3_enc.c b/apps/codecs/mp3_enc.c index e7893fd14a..2f5528f74c 100644 --- a/apps/codecs/mp3_enc.c +++ b/apps/codecs/mp3_enc.c | |||
@@ -2584,45 +2584,46 @@ static bool enc_init(void) | |||
2584 | return true; | 2584 | return true; |
2585 | } /* enc_init */ | 2585 | } /* enc_init */ |
2586 | 2586 | ||
2587 | enum codec_status codec_main(void) | 2587 | /* this is the codec entry point */ |
2588 | enum codec_status codec_main(enum codec_entry_call_reason reason) | ||
2588 | { | 2589 | { |
2589 | /* Generic codec initialisation */ | 2590 | if (reason == CODEC_LOAD) { |
2590 | if (!enc_init()) | 2591 | if (!enc_init()) |
2591 | return CODEC_ERROR; | 2592 | return CODEC_ERROR; |
2593 | } | ||
2594 | else if (reason == CODEC_UNLOAD) { | ||
2595 | /* reset parameters to initial state */ | ||
2596 | ci->enc_set_parameters(NULL); | ||
2597 | } | ||
2598 | |||
2599 | return CODEC_OK; | ||
2600 | } | ||
2592 | 2601 | ||
2602 | /* this is called for each file to process */ | ||
2603 | enum codec_status codec_run(void) | ||
2604 | { | ||
2593 | /* main encoding loop */ | 2605 | /* main encoding loop */ |
2594 | while (!ci->stop_codec) | 2606 | while(ci->get_command(NULL) != CODEC_ACTION_HALT) |
2595 | { | 2607 | { |
2596 | char *buffer; | 2608 | char *buffer = buffer = ci->enc_get_pcm_data(pcm_chunk_size); |
2597 | 2609 | struct enc_chunk_hdr *chunk; | |
2598 | while ((buffer = ci->enc_get_pcm_data(pcm_chunk_size)) != NULL) | ||
2599 | { | ||
2600 | struct enc_chunk_hdr *chunk; | ||
2601 | |||
2602 | if (ci->stop_codec) | ||
2603 | break; | ||
2604 | 2610 | ||
2605 | chunk = ci->enc_get_chunk(); | 2611 | if(buffer == NULL) |
2606 | chunk->enc_data = ENC_CHUNK_SKIP_HDR(chunk->enc_data, chunk); | 2612 | continue; |
2607 | 2613 | ||
2608 | encode_frame(buffer, chunk); | 2614 | chunk = ci->enc_get_chunk(); |
2615 | chunk->enc_data = ENC_CHUNK_SKIP_HDR(chunk->enc_data, chunk); | ||
2609 | 2616 | ||
2610 | if (chunk->num_pcm < samp_per_frame) | 2617 | encode_frame(buffer, chunk); |
2611 | { | ||
2612 | ci->enc_unget_pcm_data(pcm_chunk_size - chunk->num_pcm*4); | ||
2613 | chunk->num_pcm = samp_per_frame; | ||
2614 | } | ||
2615 | 2618 | ||
2616 | ci->enc_finish_chunk(); | 2619 | if (chunk->num_pcm < samp_per_frame) |
2617 | 2620 | { | |
2618 | ci->yield(); | 2621 | ci->enc_unget_pcm_data(pcm_chunk_size - chunk->num_pcm*4); |
2622 | chunk->num_pcm = samp_per_frame; | ||
2619 | } | 2623 | } |
2620 | 2624 | ||
2621 | ci->yield(); | 2625 | ci->enc_finish_chunk(); |
2622 | } | 2626 | } |
2623 | 2627 | ||
2624 | /* reset parameters to initial state */ | ||
2625 | ci->enc_set_parameters(NULL); | ||
2626 | |||
2627 | return CODEC_OK; | 2628 | return CODEC_OK; |
2628 | } /* codec_start */ | 2629 | } |
diff --git a/apps/codecs/mpa.c b/apps/codecs/mpa.c index 4b49775029..c9e2131450 100644 --- a/apps/codecs/mpa.c +++ b/apps/codecs/mpa.c | |||
@@ -268,8 +268,8 @@ static bool mad_synth_thread_create(void) | |||
268 | 268 | ||
269 | static void mad_synth_thread_quit(void) | 269 | static void mad_synth_thread_quit(void) |
270 | { | 270 | { |
271 | /*mop up COP thread*/ | 271 | /* mop up COP thread */ |
272 | die=1; | 272 | die = 1; |
273 | ci->semaphore_release(&synth_pending_sem); | 273 | ci->semaphore_release(&synth_pending_sem); |
274 | ci->thread_wait(mad_synth_thread_id); | 274 | ci->thread_wait(mad_synth_thread_id); |
275 | ci->cpucache_invalidate(); | 275 | ci->cpucache_invalidate(); |
@@ -299,9 +299,30 @@ static inline void mad_synth_thread_unwait_pcm(void) | |||
299 | #endif /* MPA_SYNTH_ON_COP */ | 299 | #endif /* MPA_SYNTH_ON_COP */ |
300 | 300 | ||
301 | /* this is the codec entry point */ | 301 | /* this is the codec entry point */ |
302 | enum codec_status codec_main(void) | 302 | enum codec_status codec_main(enum codec_entry_call_reason reason) |
303 | { | ||
304 | if (reason == CODEC_LOAD) { | ||
305 | /* Create a decoder instance */ | ||
306 | if (codec_init()) | ||
307 | return CODEC_ERROR; | ||
308 | |||
309 | ci->configure(DSP_SET_SAMPLE_DEPTH, MAD_F_FRACBITS); | ||
310 | |||
311 | /* does nothing on 1 processor systems except return true */ | ||
312 | if(!mad_synth_thread_create()) | ||
313 | return CODEC_ERROR; | ||
314 | } | ||
315 | else if (reason == CODEC_UNLOAD) { | ||
316 | /* mop up COP thread - MT only */ | ||
317 | mad_synth_thread_quit(); | ||
318 | } | ||
319 | |||
320 | return CODEC_OK; | ||
321 | } | ||
322 | |||
323 | /* this is called for each file to process */ | ||
324 | enum codec_status codec_run(void) | ||
303 | { | 325 | { |
304 | int status; | ||
305 | size_t size; | 326 | size_t size; |
306 | int file_end; | 327 | int file_end; |
307 | int samples_to_skip; /* samples to skip in total for this file (at start) */ | 328 | int samples_to_skip; /* samples to skip in total for this file (at start) */ |
@@ -312,27 +333,12 @@ enum codec_status codec_main(void) | |||
312 | unsigned long current_frequency = 0; | 333 | unsigned long current_frequency = 0; |
313 | int framelength; | 334 | int framelength; |
314 | int padding = MAD_BUFFER_GUARD; /* to help mad decode the last frame */ | 335 | int padding = MAD_BUFFER_GUARD; /* to help mad decode the last frame */ |
315 | 336 | intptr_t param; | |
316 | if (codec_init()) | ||
317 | return CODEC_ERROR; | ||
318 | |||
319 | /* Create a decoder instance */ | ||
320 | |||
321 | ci->configure(DSP_SET_SAMPLE_DEPTH, MAD_F_FRACBITS); | ||
322 | |||
323 | /*does nothing on 1 processor systems except return true*/ | ||
324 | if(!mad_synth_thread_create()) | ||
325 | return CODEC_ERROR; | ||
326 | |||
327 | next_track: | ||
328 | status = CODEC_OK; | ||
329 | 337 | ||
330 | /* Reinitializing seems to be necessary to avoid playback quircks when seeking. */ | 338 | /* Reinitializing seems to be necessary to avoid playback quircks when seeking. */ |
331 | init_mad(); | 339 | init_mad(); |
332 | 340 | ||
333 | file_end = 0; | 341 | file_end = 0; |
334 | if (codec_wait_taginfo() != 0) | ||
335 | goto request_next_track; | ||
336 | 342 | ||
337 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); | 343 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); |
338 | current_frequency = ci->id3->frequency; | 344 | current_frequency = ci->id3->frequency; |
@@ -379,29 +385,35 @@ next_track: | |||
379 | 385 | ||
380 | /* This is the decoding loop. */ | 386 | /* This is the decoding loop. */ |
381 | while (1) { | 387 | while (1) { |
382 | ci->yield(); | 388 | enum codec_command_action action = ci->get_command(¶m); |
383 | if (ci->stop_codec || ci->new_track) | 389 | |
390 | if (action == CODEC_ACTION_HALT) | ||
384 | break; | 391 | break; |
385 | 392 | ||
386 | if (ci->seek_time) { | 393 | if (action == CODEC_ACTION_SEEK_TIME) { |
387 | int newpos; | 394 | int newpos; |
388 | 395 | ||
389 | /*make sure the synth thread is idle before seeking - MT only*/ | 396 | /*make sure the synth thread is idle before seeking - MT only*/ |
390 | mad_synth_thread_wait_pcm(); | 397 | mad_synth_thread_wait_pcm(); |
391 | mad_synth_thread_unwait_pcm(); | 398 | mad_synth_thread_unwait_pcm(); |
392 | 399 | ||
393 | samplesdone = ((int64_t)(ci->seek_time-1))*current_frequency/1000; | 400 | samplesdone = ((int64_t)param)*current_frequency/1000; |
394 | 401 | ||
395 | if (ci->seek_time-1 == 0) { | 402 | if (param == 0) { |
396 | newpos = ci->id3->first_frame_offset; | 403 | newpos = ci->id3->first_frame_offset; |
397 | samples_to_skip = start_skip; | 404 | samples_to_skip = start_skip; |
398 | } else { | 405 | } else { |
399 | newpos = get_file_pos(ci->seek_time-1); | 406 | newpos = get_file_pos(param); |
400 | samples_to_skip = 0; | 407 | samples_to_skip = 0; |
401 | } | 408 | } |
402 | 409 | ||
403 | if (!ci->seek_buffer(newpos)) | 410 | if (!ci->seek_buffer(newpos)) |
411 | { | ||
412 | ci->seek_complete(); | ||
404 | break; | 413 | break; |
414 | } | ||
415 | |||
416 | ci->set_elapsed((samplesdone * 1000) / current_frequency); | ||
405 | ci->seek_complete(); | 417 | ci->seek_complete(); |
406 | init_mad(); | 418 | init_mad(); |
407 | framelength = 0; | 419 | framelength = 0; |
@@ -435,8 +447,7 @@ next_track: | |||
435 | continue; | 447 | continue; |
436 | } else { | 448 | } else { |
437 | /* Some other unrecoverable error */ | 449 | /* Some other unrecoverable error */ |
438 | status = CODEC_ERROR; | 450 | return CODEC_ERROR; |
439 | break; | ||
440 | } | 451 | } |
441 | } | 452 | } |
442 | 453 | ||
@@ -504,12 +515,5 @@ next_track: | |||
504 | framelength - stop_skip); | 515 | framelength - stop_skip); |
505 | } | 516 | } |
506 | 517 | ||
507 | request_next_track: | 518 | return CODEC_OK; |
508 | if (ci->request_next_track()) | ||
509 | goto next_track; | ||
510 | |||
511 | /*mop up COP thread - MT only*/ | ||
512 | mad_synth_thread_quit(); | ||
513 | |||
514 | return status; | ||
515 | } | 519 | } |
diff --git a/apps/codecs/mpc.c b/apps/codecs/mpc.c index 187c37e597..bbe2d9943b 100644 --- a/apps/codecs/mpc.c +++ b/apps/codecs/mpc.c | |||
@@ -52,8 +52,20 @@ static mpc_int32_t get_size_impl(mpc_reader *reader) | |||
52 | return ci->filesize; | 52 | return ci->filesize; |
53 | } | 53 | } |
54 | 54 | ||
55 | /* This is the codec entry point. */ | 55 | /* this is the codec entry point */ |
56 | enum codec_status codec_main(void) | 56 | enum codec_status codec_main(enum codec_entry_call_reason reason) |
57 | { | ||
58 | if (reason == CODEC_LOAD) { | ||
59 | /* musepack's sample representation is 18.14 | ||
60 | * DSP_SET_SAMPLE_DEPTH = 14 (FRACT) + 16 (NATIVE) - 1 (SIGN) = 29 */ | ||
61 | ci->configure(DSP_SET_SAMPLE_DEPTH, 29); | ||
62 | } | ||
63 | |||
64 | return CODEC_OK; | ||
65 | } | ||
66 | |||
67 | /* this is called for each file to process */ | ||
68 | enum codec_status codec_run(void) | ||
57 | { | 69 | { |
58 | mpc_int64_t samplesdone; | 70 | mpc_int64_t samplesdone; |
59 | uint32_t frequency; /* 0.1 kHz accuracy */ | 71 | uint32_t frequency; /* 0.1 kHz accuracy */ |
@@ -64,39 +76,27 @@ enum codec_status codec_main(void) | |||
64 | mpc_streaminfo info; | 76 | mpc_streaminfo info; |
65 | mpc_frame_info frame; | 77 | mpc_frame_info frame; |
66 | mpc_demux *demux = NULL; | 78 | mpc_demux *demux = NULL; |
67 | int retval; | 79 | intptr_t param; |
68 | 80 | ||
69 | frame.buffer = sample_buffer; | 81 | frame.buffer = sample_buffer; |
70 | 82 | ||
71 | /* musepack's sample representation is 18.14 | ||
72 | * DSP_SET_SAMPLE_DEPTH = 14 (FRACT) + 16 (NATIVE) - 1 (SIGN) = 29 */ | ||
73 | ci->configure(DSP_SET_SAMPLE_DEPTH, 29); | ||
74 | |||
75 | /* Create a decoder instance */ | 83 | /* Create a decoder instance */ |
76 | reader.read = read_impl; | 84 | reader.read = read_impl; |
77 | reader.seek = seek_impl; | 85 | reader.seek = seek_impl; |
78 | reader.tell = tell_impl; | 86 | reader.tell = tell_impl; |
79 | reader.get_size = get_size_impl; | 87 | reader.get_size = get_size_impl; |
80 | 88 | ||
81 | next_track: | ||
82 | retval = CODEC_OK; | ||
83 | |||
84 | if (codec_init()) | 89 | if (codec_init()) |
85 | { | 90 | return CODEC_ERROR; |
86 | retval = CODEC_ERROR; | ||
87 | goto exit; | ||
88 | } | ||
89 | 91 | ||
90 | if (codec_wait_taginfo() != 0) | 92 | /* Prep position */ |
91 | goto done; | 93 | ci->seek_buffer(0); |
92 | 94 | ||
93 | /* Initialize demux/decoder. */ | 95 | /* Initialize demux/decoder. */ |
94 | demux = mpc_demux_init(&reader); | 96 | demux = mpc_demux_init(&reader); |
95 | if (NULL == demux) | 97 | if (NULL == demux) |
96 | { | 98 | return CODEC_ERROR; |
97 | retval = CODEC_ERROR; | 99 | |
98 | goto done; | ||
99 | } | ||
100 | /* Read file's streaminfo data. */ | 100 | /* Read file's streaminfo data. */ |
101 | mpc_demux_get_info(demux, &info); | 101 | mpc_demux_get_info(demux, &info); |
102 | 102 | ||
@@ -117,11 +117,8 @@ next_track: | |||
117 | ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); | 117 | ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); |
118 | else if (info.channels == 1) | 118 | else if (info.channels == 1) |
119 | ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); | 119 | ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); |
120 | else | 120 | else |
121 | { | 121 | return CODEC_ERROR; |
122 | retval = CODEC_ERROR; | ||
123 | goto done; | ||
124 | } | ||
125 | 122 | ||
126 | codec_set_replaygain(ci->id3); | 123 | codec_set_replaygain(ci->id3); |
127 | 124 | ||
@@ -142,21 +139,24 @@ next_track: | |||
142 | /* This is the decoding loop. */ | 139 | /* This is the decoding loop. */ |
143 | do | 140 | do |
144 | { | 141 | { |
142 | enum codec_command_action action = ci->get_command(¶m); | ||
143 | |||
144 | if (action == CODEC_ACTION_HALT) | ||
145 | return CODEC_OK; | ||
146 | |||
145 | /* Complete seek handler. */ | 147 | /* Complete seek handler. */ |
146 | if (ci->seek_time) | 148 | if (action == CODEC_ACTION_SEEK_TIME) |
147 | { | 149 | { |
148 | mpc_int64_t new_offset = ((ci->seek_time - 1)/10)*frequency; | 150 | mpc_int64_t new_offset = (param/10)*frequency; |
149 | if (mpc_demux_seek_sample(demux, new_offset) == MPC_STATUS_OK) | 151 | if (mpc_demux_seek_sample(demux, new_offset) == MPC_STATUS_OK) |
150 | { | 152 | { |
151 | samplesdone = new_offset; | 153 | samplesdone = new_offset; |
152 | ci->set_elapsed(ci->seek_time); | ||
153 | } | 154 | } |
155 | |||
156 | elapsed_time = (samplesdone*10)/frequency; | ||
157 | ci->set_elapsed(elapsed_time); | ||
154 | ci->seek_complete(); | 158 | ci->seek_complete(); |
155 | } | 159 | } |
156 | |||
157 | /* Stop or skip occured, exit decoding loop. */ | ||
158 | if (ci->stop_codec || ci->new_track) | ||
159 | break; | ||
160 | 160 | ||
161 | /* Decode one frame. */ | 161 | /* Decode one frame. */ |
162 | status = mpc_demux_decode(demux, &frame); | 162 | status = mpc_demux_decode(demux, &frame); |
@@ -164,8 +164,7 @@ next_track: | |||
164 | if (frame.bits == -1) | 164 | if (frame.bits == -1) |
165 | { | 165 | { |
166 | /* Decoding error, exit decoding loop. */ | 166 | /* Decoding error, exit decoding loop. */ |
167 | retval = (status == MPC_STATUS_OK) ? CODEC_OK : CODEC_ERROR; | 167 | return (status == MPC_STATUS_OK) ? CODEC_OK : CODEC_ERROR; |
168 | goto done; | ||
169 | } | 168 | } |
170 | else | 169 | else |
171 | { | 170 | { |
@@ -181,11 +180,4 @@ next_track: | |||
181 | ci->set_offset( (samplesdone * byterate)/(frequency*100) ); | 180 | ci->set_offset( (samplesdone * byterate)/(frequency*100) ); |
182 | } | 181 | } |
183 | } while (true); | 182 | } while (true); |
184 | |||
185 | done: | ||
186 | if (ci->request_next_track()) | ||
187 | goto next_track; | ||
188 | |||
189 | exit: | ||
190 | return retval; | ||
191 | } | 183 | } |
diff --git a/apps/codecs/nsf.c b/apps/codecs/nsf.c index 2f37da81d2..72f6974214 100644 --- a/apps/codecs/nsf.c +++ b/apps/codecs/nsf.c | |||
@@ -4307,46 +4307,44 @@ static void set_codec_track(int t, int d) { | |||
4307 | nSilenceTrackMS=5000; | 4307 | nSilenceTrackMS=5000; |
4308 | SetFadeTime(track,track+fade, fNSFPlaybackSpeed,def); | 4308 | SetFadeTime(track,track+fade, fNSFPlaybackSpeed,def); |
4309 | } | 4309 | } |
4310 | ci->id3->elapsed=d*1000; /* d is track no to display */ | 4310 | ci->set_elapsed(d*1000); /* d is track no to display */ |
4311 | } | 4311 | } |
4312 | 4312 | ||
4313 | /** Operational info **/ | ||
4314 | static int track = 0; | ||
4315 | static char last_path[MAX_PATH]; | ||
4316 | static int dontresettrack = 0; | ||
4317 | |||
4313 | /* this is the codec entry point */ | 4318 | /* this is the codec entry point */ |
4314 | enum codec_status codec_main(void) | 4319 | enum codec_status codec_main(enum codec_entry_call_reason reason) |
4320 | { | ||
4321 | if (reason == CODEC_LOAD) { | ||
4322 | /* we only render 16 bits, 44.1KHz, Stereo */ | ||
4323 | ci->configure(DSP_SET_SAMPLE_DEPTH, 16); | ||
4324 | ci->configure(DSP_SET_FREQUENCY, 44100); | ||
4325 | ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); | ||
4326 | |||
4327 | RebuildOutputTables(); | ||
4328 | } | ||
4329 | |||
4330 | return CODEC_OK; | ||
4331 | } | ||
4332 | |||
4333 | /* this is called for each file to process */ | ||
4334 | enum codec_status codec_run(void) | ||
4315 | { | 4335 | { |
4316 | int written; | 4336 | int written; |
4317 | uint8_t *buf; | 4337 | uint8_t *buf; |
4318 | size_t n; | 4338 | size_t n; |
4319 | int endofstream; /* end of stream flag */ | 4339 | int endofstream; /* end of stream flag */ |
4320 | int track; | 4340 | int usingplaylist = 0; |
4321 | int dontresettrack; | ||
4322 | char last_path[MAX_PATH]; | ||
4323 | int usingplaylist; | ||
4324 | |||
4325 | /* we only render 16 bits */ | ||
4326 | ci->configure(DSP_SET_SAMPLE_DEPTH, 16); | ||
4327 | |||
4328 | ci->configure(DSP_SET_FREQUENCY, 44100); | ||
4329 | ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); | ||
4330 | |||
4331 | RebuildOutputTables(); | ||
4332 | |||
4333 | dontresettrack=0; | ||
4334 | last_path[0]='\0'; | ||
4335 | track=0; | ||
4336 | 4341 | ||
4337 | next_track: | ||
4338 | usingplaylist=0; | ||
4339 | DEBUGF("NSF: next_track\n"); | 4342 | DEBUGF("NSF: next_track\n"); |
4340 | if (codec_init()) { | 4343 | if (codec_init()) { |
4341 | return CODEC_ERROR; | 4344 | return CODEC_ERROR; |
4342 | } | 4345 | } |
4343 | DEBUGF("NSF: after init\n"); | 4346 | DEBUGF("NSF: after init\n"); |
4344 | 4347 | ||
4345 | |||
4346 | /* wait for track info to load */ | ||
4347 | if (codec_wait_taginfo() != 0) | ||
4348 | goto request_next_track; | ||
4349 | |||
4350 | codec_set_replaygain(ci->id3); | 4348 | codec_set_replaygain(ci->id3); |
4351 | 4349 | ||
4352 | /* Read the entire file */ | 4350 | /* Read the entire file */ |
@@ -4408,22 +4406,27 @@ init_nsf: | |||
4408 | reset_profile_timers(); | 4406 | reset_profile_timers(); |
4409 | 4407 | ||
4410 | while (!endofstream) { | 4408 | while (!endofstream) { |
4409 | intptr_t param; | ||
4410 | enum codec_command_action action = ci->get_command(¶m); | ||
4411 | 4411 | ||
4412 | ci->yield(); | 4412 | if (action == CODEC_ACTION_HALT) |
4413 | if (ci->stop_codec || ci->new_track) { | ||
4414 | break; | 4413 | break; |
4415 | } | ||
4416 | 4414 | ||
4417 | if (ci->seek_time >0) { | 4415 | if (action == CODEC_ACTION_SEEK_TIME) { |
4418 | track=ci->seek_time/1000; | 4416 | if (param > 0) { |
4419 | if (usingplaylist) { | 4417 | track=param/1000; |
4420 | if (track>=nPlaylistSize) break; | 4418 | if (usingplaylist) { |
4421 | } else { | 4419 | if (track>=nPlaylistSize) break; |
4422 | if (track>=nTrackCount) break; | 4420 | } else { |
4421 | if (track>=nTrackCount) break; | ||
4422 | } | ||
4423 | dontresettrack=1; | ||
4424 | ci->seek_complete(); | ||
4425 | goto init_nsf; | ||
4426 | } | ||
4427 | else { | ||
4428 | ci->seek_complete(); | ||
4423 | } | 4429 | } |
4424 | ci->seek_complete(); | ||
4425 | dontresettrack=1; | ||
4426 | goto init_nsf; | ||
4427 | } | 4430 | } |
4428 | 4431 | ||
4429 | ENTER_TIMER(total); | 4432 | ENTER_TIMER(total); |
@@ -4449,22 +4452,17 @@ init_nsf: | |||
4449 | 4452 | ||
4450 | print_timers(last_path,track); | 4453 | print_timers(last_path,track); |
4451 | 4454 | ||
4452 | request_next_track: | ||
4453 | if (ci->request_next_track()) { | ||
4454 | if (ci->global_settings->repeat_mode==REPEAT_ONE) { | 4455 | if (ci->global_settings->repeat_mode==REPEAT_ONE) { |
4455 | /* in repeat one mode just advance to the next track */ | 4456 | /* in repeat one mode just advance to the next track */ |
4456 | track++; | 4457 | track++; |
4457 | if (track>=nTrackCount) track=0; | 4458 | if (track>=nTrackCount) track=0; |
4458 | dontresettrack=1; | 4459 | dontresettrack=1; |
4459 | /* at this point we can't tell if another file has been selected */ | 4460 | /* at this point we can't tell if another file has been selected */ |
4460 | goto next_track; | ||
4461 | } else { | 4461 | } else { |
4462 | /* otherwise do a proper load of the next file */ | 4462 | /* otherwise do a proper load of the next file */ |
4463 | dontresettrack=0; | 4463 | dontresettrack=0; |
4464 | last_path[0]='\0'; | 4464 | last_path[0]='\0'; |
4465 | } | 4465 | } |
4466 | goto next_track; /* when we fall through here we'll reload the file */ | ||
4467 | } | ||
4468 | 4466 | ||
4469 | return CODEC_OK; | 4467 | return CODEC_OK; |
4470 | } | 4468 | } |
diff --git a/apps/codecs/raac.c b/apps/codecs/raac.c index b322ae7df3..4b73f41462 100644 --- a/apps/codecs/raac.c +++ b/apps/codecs/raac.c | |||
@@ -35,8 +35,21 @@ static void init_rm(RMContext *rmctx) | |||
35 | 35 | ||
36 | static RMContext rmctx; | 36 | static RMContext rmctx; |
37 | static RMPacket pkt; | 37 | static RMPacket pkt; |
38 | |||
38 | /* this is the codec entry point */ | 39 | /* this is the codec entry point */ |
39 | enum codec_status codec_main(void) | 40 | enum codec_status codec_main(enum codec_entry_call_reason reason) |
41 | { | ||
42 | if (reason == CODEC_LOAD) { | ||
43 | /* Generic codec initialisation */ | ||
44 | ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); | ||
45 | ci->configure(DSP_SET_SAMPLE_DEPTH, 29); | ||
46 | } | ||
47 | |||
48 | return CODEC_OK; | ||
49 | } | ||
50 | |||
51 | /* this is called for each file to process */ | ||
52 | enum codec_status codec_run(void) | ||
40 | { | 53 | { |
41 | static NeAACDecFrameInfo frame_info; | 54 | static NeAACDecFrameInfo frame_info; |
42 | NeAACDecHandle decoder; | 55 | NeAACDecHandle decoder; |
@@ -49,26 +62,21 @@ enum codec_status codec_main(void) | |||
49 | unsigned char c = 0; /* channels */ | 62 | unsigned char c = 0; /* channels */ |
50 | int playback_on = -1; | 63 | int playback_on = -1; |
51 | size_t resume_offset; | 64 | size_t resume_offset; |
52 | 65 | intptr_t param; | |
53 | /* Generic codec initialisation */ | 66 | enum codec_command_action action = CODEC_ACTION_NULL; |
54 | ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); | ||
55 | ci->configure(DSP_SET_SAMPLE_DEPTH, 29); | ||
56 | |||
57 | next_track: | ||
58 | err = CODEC_OK; | ||
59 | 67 | ||
60 | if (codec_init()) { | 68 | if (codec_init()) { |
61 | DEBUGF("FAAD: Codec init error\n"); | 69 | DEBUGF("FAAD: Codec init error\n"); |
62 | return CODEC_ERROR; | 70 | return CODEC_ERROR; |
63 | } | 71 | } |
64 | 72 | ||
65 | if (codec_wait_taginfo() != 0) | ||
66 | goto done; | ||
67 | |||
68 | resume_offset = ci->id3->offset; | 73 | resume_offset = ci->id3->offset; |
69 | 74 | ||
70 | ci->memset(&rmctx,0,sizeof(RMContext)); | 75 | ci->memset(&rmctx,0,sizeof(RMContext)); |
71 | ci->memset(&pkt,0,sizeof(RMPacket)); | 76 | ci->memset(&pkt,0,sizeof(RMPacket)); |
77 | |||
78 | ci->seek_buffer(0); | ||
79 | |||
72 | init_rm(&rmctx); | 80 | init_rm(&rmctx); |
73 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); | 81 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); |
74 | codec_set_replaygain(ci->id3); | 82 | codec_set_replaygain(ci->id3); |
@@ -78,9 +86,9 @@ next_track: | |||
78 | 86 | ||
79 | if (!decoder) { | 87 | if (!decoder) { |
80 | DEBUGF("FAAD: Decode open error\n"); | 88 | DEBUGF("FAAD: Decode open error\n"); |
81 | err = CODEC_ERROR; | 89 | return CODEC_ERROR; |
82 | goto done; | 90 | } |
83 | } | 91 | |
84 | NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration(decoder); | 92 | NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration(decoder); |
85 | conf->outputFormat = FAAD_FMT_16BIT; /* irrelevant, we don't convert */ | 93 | conf->outputFormat = FAAD_FMT_16BIT; /* irrelevant, we don't convert */ |
86 | NeAACDecSetConfiguration(decoder, conf); | 94 | NeAACDecSetConfiguration(decoder, conf); |
@@ -91,8 +99,7 @@ next_track: | |||
91 | 99 | ||
92 | if (err) { | 100 | if (err) { |
93 | DEBUGF("FAAD: DecInit: %d, %d\n", err, decoder->object_type); | 101 | DEBUGF("FAAD: DecInit: %d, %d\n", err, decoder->object_type); |
94 | err = CODEC_ERROR; | 102 | return CODEC_ERROR; |
95 | goto done; | ||
96 | } | 103 | } |
97 | 104 | ||
98 | /* check for a mid-track resume and force a seek time accordingly */ | 105 | /* check for a mid-track resume and force a seek time accordingly */ |
@@ -100,36 +107,38 @@ next_track: | |||
100 | resume_offset -= rmctx.data_offset + DATA_HEADER_SIZE; | 107 | resume_offset -= rmctx.data_offset + DATA_HEADER_SIZE; |
101 | /* put number of subpackets to skip in resume_offset */ | 108 | /* put number of subpackets to skip in resume_offset */ |
102 | resume_offset /= (rmctx.block_align + PACKET_HEADER_SIZE); | 109 | resume_offset /= (rmctx.block_align + PACKET_HEADER_SIZE); |
103 | ci->seek_time = (int)resume_offset * ((rmctx.block_align * 8 * 1000)/rmctx.bit_rate); | 110 | param = (int)resume_offset * ((rmctx.block_align * 8 * 1000)/rmctx.bit_rate); |
111 | action = CODEC_ACTION_SEEK_TIME; | ||
104 | } | 112 | } |
105 | 113 | ||
106 | ci->id3->frequency = s; | 114 | ci->id3->frequency = s; /* FIXME: Won't get it to the UI */ |
107 | ci->set_elapsed(0); | 115 | ci->set_elapsed(0); |
108 | ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE); | 116 | ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE); |
109 | 117 | ||
110 | /* The main decoding loop */ | 118 | /* The main decoding loop */ |
111 | seek_start: | ||
112 | while (1) { | 119 | while (1) { |
113 | ci->yield(); | 120 | if (action == CODEC_ACTION_NULL) |
114 | if (ci->stop_codec || ci->new_track) { | 121 | action = ci->get_command(¶m); |
122 | |||
123 | if (action == CODEC_ACTION_HALT) | ||
115 | break; | 124 | break; |
116 | } | ||
117 | 125 | ||
118 | if (ci->seek_time) { | 126 | if (action == CODEC_ACTION_SEEK_TIME) { |
119 | |||
120 | /* Do not allow seeking beyond the file's length */ | 127 | /* Do not allow seeking beyond the file's length */ |
121 | if ((unsigned) ci->seek_time > ci->id3->length) { | 128 | if ((unsigned) param > ci->id3->length) { |
129 | ci->set_elapsed(ci->id3->length); | ||
122 | ci->seek_complete(); | 130 | ci->seek_complete(); |
123 | goto done; | 131 | break; |
124 | } | 132 | } |
125 | 133 | ||
126 | ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE); | 134 | ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE); |
127 | 135 | ||
128 | /* Seek to the start of the track */ | 136 | /* Seek to the start of the track */ |
129 | if (ci->seek_time == 1) { | 137 | if (param == 0) { |
130 | ci->set_elapsed(0); | 138 | ci->set_elapsed(0); |
131 | ci->seek_complete(); | 139 | ci->seek_complete(); |
132 | goto seek_start; | 140 | action = CODEC_ACTION_NULL; |
141 | continue; | ||
133 | } | 142 | } |
134 | 143 | ||
135 | skipped = 0; | 144 | skipped = 0; |
@@ -141,21 +150,30 @@ seek_start: | |||
141 | if(playback_on == -1) { | 150 | if(playback_on == -1) { |
142 | /* Error only if packet-parsing failed and playback hadn't started */ | 151 | /* Error only if packet-parsing failed and playback hadn't started */ |
143 | DEBUGF("rm_get_packet failed\n"); | 152 | DEBUGF("rm_get_packet failed\n"); |
153 | ci->seek_complete(); | ||
144 | return CODEC_ERROR; | 154 | return CODEC_ERROR; |
145 | } | 155 | } |
146 | else | 156 | else { |
147 | goto done; | 157 | ci->seek_complete(); |
158 | return CODEC_OK; | ||
159 | } | ||
148 | } | 160 | } |
149 | skipped += pkt.length; | 161 | skipped += pkt.length; |
150 | if(pkt.timestamp > (unsigned)ci->seek_time) break; | 162 | |
163 | if(pkt.timestamp > (unsigned)param) | ||
164 | break; | ||
165 | |||
151 | ci->advance_buffer(pkt.length); | 166 | ci->advance_buffer(pkt.length); |
152 | } | 167 | } |
153 | ci->seek_buffer(pkt_offset + rmctx.data_offset + DATA_HEADER_SIZE); | 168 | ci->seek_buffer(pkt_offset + rmctx.data_offset + DATA_HEADER_SIZE); |
154 | buffer = ci->request_buffer(&n,rmctx.audio_framesize + 1000); | 169 | buffer = ci->request_buffer(&n,rmctx.audio_framesize + 1000); |
155 | NeAACDecPostSeekReset(decoder, decoder->frame); | 170 | NeAACDecPostSeekReset(decoder, decoder->frame); |
171 | ci->set_elapsed(pkt.timestamp); | ||
156 | ci->seek_complete(); | 172 | ci->seek_complete(); |
157 | } | 173 | } |
158 | 174 | ||
175 | action = CODEC_ACTION_NULL; | ||
176 | |||
159 | /* Request the required number of bytes from the input buffer */ | 177 | /* Request the required number of bytes from the input buffer */ |
160 | buffer=ci->request_buffer(&n,rmctx.audio_framesize + 1000); | 178 | buffer=ci->request_buffer(&n,rmctx.audio_framesize + 1000); |
161 | consumed = rm_get_packet(&buffer, &rmctx, &pkt); | 179 | consumed = rm_get_packet(&buffer, &rmctx, &pkt); |
@@ -167,20 +185,20 @@ seek_start: | |||
167 | return CODEC_ERROR; | 185 | return CODEC_ERROR; |
168 | } | 186 | } |
169 | else | 187 | else |
170 | goto done; | 188 | break; |
171 | } | 189 | } |
172 | 190 | ||
173 | playback_on = 1; | 191 | playback_on = 1; |
174 | if (pkt.timestamp >= ci->id3->length) | 192 | if (pkt.timestamp >= ci->id3->length) |
175 | goto done; | 193 | break; |
194 | |||
176 | /* Decode one block - returned samples will be host-endian */ | 195 | /* Decode one block - returned samples will be host-endian */ |
177 | for(i = 0; i < rmctx.sub_packet_cnt; i++) { | 196 | for(i = 0; i < rmctx.sub_packet_cnt; i++) { |
178 | ret = NeAACDecDecode(decoder, &frame_info, buffer, rmctx.sub_packet_lengths[i]); | 197 | ret = NeAACDecDecode(decoder, &frame_info, buffer, rmctx.sub_packet_lengths[i]); |
179 | buffer += rmctx.sub_packet_lengths[i]; | 198 | buffer += rmctx.sub_packet_lengths[i]; |
180 | if (frame_info.error > 0) { | 199 | if (frame_info.error > 0) { |
181 | DEBUGF("FAAD: decode error '%s'\n", NeAACDecGetErrorMessage(frame_info.error)); | 200 | DEBUGF("FAAD: decode error '%s'\n", NeAACDecGetErrorMessage(frame_info.error)); |
182 | err = CODEC_ERROR; | 201 | return CODEC_ERROR; |
183 | goto exit; | ||
184 | } | 202 | } |
185 | ci->pcmbuf_insert(decoder->time_out[0], | 203 | ci->pcmbuf_insert(decoder->time_out[0], |
186 | decoder->time_out[1], | 204 | decoder->time_out[1], |
@@ -191,11 +209,5 @@ seek_start: | |||
191 | ci->advance_buffer(pkt.length); | 209 | ci->advance_buffer(pkt.length); |
192 | } | 210 | } |
193 | 211 | ||
194 | done: | 212 | return CODEC_OK; |
195 | if (ci->request_next_track()) | ||
196 | goto next_track; | ||
197 | |||
198 | exit: | ||
199 | return err; | ||
200 | } | 213 | } |
201 | |||
diff --git a/apps/codecs/shorten.c b/apps/codecs/shorten.c index 83a9c34da8..db66991679 100644 --- a/apps/codecs/shorten.c +++ b/apps/codecs/shorten.c | |||
@@ -37,7 +37,19 @@ static int32_t offset1[MAX_OFFSET_SIZE] IBSS_ATTR; | |||
37 | static int8_t ibuf[MAX_BUFFER_SIZE] IBSS_ATTR; | 37 | static int8_t ibuf[MAX_BUFFER_SIZE] IBSS_ATTR; |
38 | 38 | ||
39 | /* this is the codec entry point */ | 39 | /* this is the codec entry point */ |
40 | enum codec_status codec_main(void) | 40 | enum codec_status codec_main(enum codec_entry_call_reason reason) |
41 | { | ||
42 | if (reason == CODEC_LOAD) { | ||
43 | /* Generic codec initialisation */ | ||
44 | ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); | ||
45 | ci->configure(DSP_SET_SAMPLE_DEPTH, SHN_OUTPUT_DEPTH-1); | ||
46 | } | ||
47 | |||
48 | return CODEC_OK; | ||
49 | } | ||
50 | |||
51 | /* this is called for each file to process */ | ||
52 | enum codec_status codec_run(void) | ||
41 | { | 53 | { |
42 | ShortenContext sc; | 54 | ShortenContext sc; |
43 | uint32_t samplesdone; | 55 | uint32_t samplesdone; |
@@ -45,21 +57,14 @@ enum codec_status codec_main(void) | |||
45 | int8_t *buf; | 57 | int8_t *buf; |
46 | int consumed, res, nsamples; | 58 | int consumed, res, nsamples; |
47 | size_t bytesleft; | 59 | size_t bytesleft; |
60 | intptr_t param; | ||
48 | 61 | ||
49 | /* Generic codec initialisation */ | ||
50 | ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); | ||
51 | ci->configure(DSP_SET_SAMPLE_DEPTH, SHN_OUTPUT_DEPTH-1); | ||
52 | |||
53 | next_track: | ||
54 | /* Codec initialization */ | 62 | /* Codec initialization */ |
55 | if (codec_init()) { | 63 | if (codec_init()) { |
56 | LOGF("Shorten: codec_init error\n"); | 64 | LOGF("Shorten: codec_init error\n"); |
57 | return CODEC_ERROR; | 65 | return CODEC_ERROR; |
58 | } | 66 | } |
59 | 67 | ||
60 | if (codec_wait_taginfo() != 0) | ||
61 | goto request_next_track; | ||
62 | |||
63 | codec_set_replaygain(ci->id3); | 68 | codec_set_replaygain(ci->id3); |
64 | 69 | ||
65 | /* Shorten decoder initialization */ | 70 | /* Shorten decoder initialization */ |
@@ -103,14 +108,15 @@ seek_start: | |||
103 | samplesdone = 0; | 108 | samplesdone = 0; |
104 | buf = ci->request_buffer(&bytesleft, MAX_BUFFER_SIZE); | 109 | buf = ci->request_buffer(&bytesleft, MAX_BUFFER_SIZE); |
105 | while (bytesleft) { | 110 | while (bytesleft) { |
106 | ci->yield(); | 111 | enum codec_command_action action = ci->get_command(¶m); |
107 | if (ci->stop_codec || ci->new_track) { | 112 | |
113 | if (action == CODEC_ACTION_HALT) | ||
108 | break; | 114 | break; |
109 | } | ||
110 | 115 | ||
111 | /* Seek to start of track */ | 116 | /* Seek to start of track */ |
112 | if (ci->seek_time == 1) { | 117 | if (action == CODEC_ACTION_SEEK_TIME) { |
113 | if (ci->seek_buffer(sc.header_bits/8 + ci->id3->first_frame_offset)) { | 118 | if (param == 0 && |
119 | ci->seek_buffer(sc.header_bits/8 + ci->id3->first_frame_offset)) { | ||
114 | sc.bitindex = sc.header_bits - 8*(sc.header_bits/8); | 120 | sc.bitindex = sc.header_bits - 8*(sc.header_bits/8); |
115 | ci->set_elapsed(0); | 121 | ci->set_elapsed(0); |
116 | ci->seek_complete(); | 122 | ci->seek_complete(); |
@@ -128,7 +134,7 @@ seek_start: | |||
128 | if (res == FN_ERROR) { | 134 | if (res == FN_ERROR) { |
129 | LOGF("Shorten: shorten_decode_frames error (%lu)\n", | 135 | LOGF("Shorten: shorten_decode_frames error (%lu)\n", |
130 | (unsigned long)samplesdone); | 136 | (unsigned long)samplesdone); |
131 | break; | 137 | return CODEC_ERROR; |
132 | } else { | 138 | } else { |
133 | /* Insert decoded samples in pcmbuf */ | 139 | /* Insert decoded samples in pcmbuf */ |
134 | if (nsamples) { | 140 | if (nsamples) { |
@@ -153,9 +159,5 @@ seek_start: | |||
153 | sc.bitindex = sc.gb.index - 8*consumed; | 159 | sc.bitindex = sc.gb.index - 8*consumed; |
154 | } | 160 | } |
155 | 161 | ||
156 | request_next_track: | ||
157 | if (ci->request_next_track()) | ||
158 | goto next_track; | ||
159 | |||
160 | return CODEC_OK; | 162 | return CODEC_OK; |
161 | } | 163 | } |
diff --git a/apps/codecs/sid.c b/apps/codecs/sid.c index 52c1289fff..0edbabe0b6 100644 --- a/apps/codecs/sid.c +++ b/apps/codecs/sid.c | |||
@@ -1203,34 +1203,47 @@ unsigned short LoadSIDFromMemory(void *pSidData, unsigned short *load_addr, | |||
1203 | return *load_addr; | 1203 | return *load_addr; |
1204 | } | 1204 | } |
1205 | 1205 | ||
1206 | static int nSamplesRendered = 0; | ||
1207 | static int nSamplesPerCall = 882; /* This is PAL SID single speed (44100/50Hz) */ | ||
1208 | static int nSamplesToRender = 0; | ||
1206 | 1209 | ||
1207 | enum codec_status codec_main(void) | 1210 | /* this is the codec entry point */ |
1211 | enum codec_status codec_main(enum codec_entry_call_reason reason) | ||
1208 | { | 1212 | { |
1209 | unsigned int filesize; | 1213 | if (reason == CODEC_LOAD) { |
1214 | /* Make use of 44.1khz */ | ||
1215 | ci->configure(DSP_SWITCH_FREQUENCY, 44100); | ||
1216 | /* Sample depth is 28 bit host endian */ | ||
1217 | ci->configure(DSP_SET_SAMPLE_DEPTH, 28); | ||
1218 | /* Mono output */ | ||
1219 | ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); | ||
1220 | } | ||
1221 | |||
1222 | return CODEC_OK; | ||
1223 | } | ||
1210 | 1224 | ||
1225 | /* this is called for each file to process */ | ||
1226 | enum codec_status codec_run(void) | ||
1227 | { | ||
1228 | unsigned int filesize; | ||
1211 | unsigned short load_addr, init_addr, play_addr; | 1229 | unsigned short load_addr, init_addr, play_addr; |
1212 | unsigned char subSongsMax, subSong, song_speed; | 1230 | unsigned char subSongsMax, subSong, song_speed; |
1231 | intptr_t param; | ||
1213 | 1232 | ||
1214 | int nSamplesRendered = 0; | ||
1215 | int nSamplesPerCall = 882; /* This is PAL SID single speed (44100/50Hz) */ | ||
1216 | int nSamplesToRender = 0; | ||
1217 | |||
1218 | next_track: | ||
1219 | if (codec_init()) { | 1233 | if (codec_init()) { |
1220 | return CODEC_ERROR; | 1234 | return CODEC_ERROR; |
1221 | } | 1235 | } |
1222 | 1236 | ||
1223 | if (codec_wait_taginfo() != 0) | ||
1224 | goto request_next_track; | ||
1225 | |||
1226 | codec_set_replaygain(ci->id3); | 1237 | codec_set_replaygain(ci->id3); |
1227 | 1238 | ||
1228 | /* Load SID file the read_filebuf callback will return the full requested | 1239 | /* Load SID file the read_filebuf callback will return the full requested |
1229 | * size if at all possible, so there is no need to loop */ | 1240 | * size if at all possible, so there is no need to loop */ |
1241 | ci->seek_buffer(0); | ||
1230 | filesize = ci->read_filebuf(sidfile, sizeof(sidfile)); | 1242 | filesize = ci->read_filebuf(sidfile, sizeof(sidfile)); |
1231 | 1243 | ||
1232 | if (filesize == 0) | 1244 | if (filesize == 0) { |
1233 | return CODEC_ERROR; | 1245 | return CODEC_ERROR; |
1246 | } | ||
1234 | 1247 | ||
1235 | c64Init(44100); | 1248 | c64Init(44100); |
1236 | LoadSIDFromMemory(sidfile, &load_addr, &init_addr, &play_addr, | 1249 | LoadSIDFromMemory(sidfile, &load_addr, &init_addr, &play_addr, |
@@ -1239,37 +1252,30 @@ next_track: | |||
1239 | cpuJSR(init_addr, subSong); /* Start the song initialize */ | 1252 | cpuJSR(init_addr, subSong); /* Start the song initialize */ |
1240 | 1253 | ||
1241 | 1254 | ||
1242 | /* Make use of 44.1khz */ | ||
1243 | ci->configure(DSP_SWITCH_FREQUENCY, 44100); | ||
1244 | /* Sample depth is 28 bit host endian */ | ||
1245 | ci->configure(DSP_SET_SAMPLE_DEPTH, 28); | ||
1246 | /* Mono output */ | ||
1247 | ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); | ||
1248 | |||
1249 | |||
1250 | /* Set the elapsed time to the current subsong (in seconds) */ | 1255 | /* Set the elapsed time to the current subsong (in seconds) */ |
1251 | ci->set_elapsed(subSong*1000); | 1256 | ci->set_elapsed(subSong*1000); |
1252 | 1257 | ||
1253 | /* The main decoder loop */ | 1258 | /* The main decoder loop */ |
1254 | while (1) { | 1259 | while (1) { |
1255 | ci->yield(); | 1260 | enum codec_command_action action = ci->get_command(¶m); |
1256 | if (ci->stop_codec || ci->new_track) | 1261 | |
1262 | if (action == CODEC_ACTION_HALT) | ||
1257 | break; | 1263 | break; |
1258 | 1264 | ||
1259 | if (ci->seek_time) { | 1265 | if (action == CODEC_ACTION_SEEK_TIME) { |
1260 | /* New time is ready in ci->seek_time */ | 1266 | /* New time is ready in param */ |
1261 | 1267 | ||
1262 | /* Start playing from scratch */ | 1268 | /* Start playing from scratch */ |
1263 | c64Init(44100); | 1269 | c64Init(44100); |
1264 | LoadSIDFromMemory(sidfile, &load_addr, &init_addr, &play_addr, &subSongsMax, &subSong, &song_speed, filesize); | 1270 | LoadSIDFromMemory(sidfile, &load_addr, &init_addr, &play_addr, |
1265 | sidPoke(24, 15); /* Turn on full volume */ | 1271 | &subSongsMax, &subSong, &song_speed, filesize); |
1266 | subSong = ci->seek_time / 1000; /* Now use the current seek time in seconds as subsong */ | 1272 | sidPoke(24, 15); /* Turn on full volume */ |
1267 | cpuJSR(init_addr, subSong); /* Start the song initialize */ | 1273 | subSong = param / 1000; /* Now use the current seek time in seconds as subsong */ |
1268 | nSamplesToRender = 0; /* Start the rendering from scratch */ | 1274 | cpuJSR(init_addr, subSong); /* Start the song initialize */ |
1269 | 1275 | nSamplesToRender = 0; /* Start the rendering from scratch */ | |
1270 | ci->seek_complete(); | ||
1271 | 1276 | ||
1272 | /* Set the elapsed time to the current subsong (in seconds) */ | 1277 | /* Set the elapsed time to the current subsong (in seconds) */ |
1278 | ci->seek_complete(); | ||
1273 | ci->set_elapsed(subSong*1000); | 1279 | ci->set_elapsed(subSong*1000); |
1274 | } | 1280 | } |
1275 | 1281 | ||
@@ -1306,9 +1312,5 @@ next_track: | |||
1306 | ci->pcmbuf_insert(samples, NULL, CHUNK_SIZE); | 1312 | ci->pcmbuf_insert(samples, NULL, CHUNK_SIZE); |
1307 | } | 1313 | } |
1308 | 1314 | ||
1309 | request_next_track: | ||
1310 | if (ci->request_next_track()) | ||
1311 | goto next_track; | ||
1312 | |||
1313 | return CODEC_OK; | 1315 | return CODEC_OK; |
1314 | } | 1316 | } |
diff --git a/apps/codecs/smaf.c b/apps/codecs/smaf.c index 3e8a41387d..9211daa9aa 100644 --- a/apps/codecs/smaf.c +++ b/apps/codecs/smaf.c | |||
@@ -332,9 +332,20 @@ static uint8_t *read_buffer(size_t *realsize) | |||
332 | return buffer; | 332 | return buffer; |
333 | } | 333 | } |
334 | 334 | ||
335 | enum codec_status codec_main(void) | 335 | /* this is the codec entry point */ |
336 | enum codec_status codec_main(enum codec_entry_call_reason reason) | ||
337 | { | ||
338 | if (reason == CODEC_LOAD) { | ||
339 | /* Generic codec initialisation */ | ||
340 | ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1); | ||
341 | } | ||
342 | |||
343 | return CODEC_OK; | ||
344 | } | ||
345 | |||
346 | /* this is called for each file to process */ | ||
347 | enum codec_status codec_run(void) | ||
336 | { | 348 | { |
337 | int status; | ||
338 | uint32_t decodedsamples; | 349 | uint32_t decodedsamples; |
339 | size_t n; | 350 | size_t n; |
340 | int bufcount; | 351 | int bufcount; |
@@ -342,20 +353,10 @@ enum codec_status codec_main(void) | |||
342 | uint8_t *smafbuf; | 353 | uint8_t *smafbuf; |
343 | off_t firstblockposn; /* position of the first block in file */ | 354 | off_t firstblockposn; /* position of the first block in file */ |
344 | const struct pcm_codec *codec; | 355 | const struct pcm_codec *codec; |
345 | 356 | intptr_t param; | |
346 | /* Generic codec initialisation */ | ||
347 | ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1); | ||
348 | 357 | ||
349 | next_track: | 358 | if (codec_init()) |
350 | status = CODEC_OK; | 359 | return CODEC_ERROR; |
351 | |||
352 | if (codec_init()) { | ||
353 | status = CODEC_ERROR; | ||
354 | goto exit; | ||
355 | } | ||
356 | |||
357 | if (codec_wait_taginfo() != 0) | ||
358 | goto done; | ||
359 | 360 | ||
360 | codec_set_replaygain(ci->id3); | 361 | codec_set_replaygain(ci->id3); |
361 | 362 | ||
@@ -365,24 +366,22 @@ next_track: | |||
365 | decodedsamples = 0; | 366 | decodedsamples = 0; |
366 | codec = 0; | 367 | codec = 0; |
367 | 368 | ||
369 | ci->seek_buffer(0); | ||
368 | if (!parse_header(&format, &firstblockposn)) | 370 | if (!parse_header(&format, &firstblockposn)) |
369 | { | 371 | { |
370 | status = CODEC_ERROR; | 372 | return CODEC_ERROR; |
371 | goto done; | ||
372 | } | 373 | } |
373 | 374 | ||
374 | codec = get_codec(format.formattag); | 375 | codec = get_codec(format.formattag); |
375 | if (codec == 0) | 376 | if (codec == 0) |
376 | { | 377 | { |
377 | DEBUGF("CODEC_ERROR: unsupport audio format: 0x%x\n", (int)format.formattag); | 378 | DEBUGF("CODEC_ERROR: unsupport audio format: 0x%x\n", (int)format.formattag); |
378 | status = CODEC_ERROR; | 379 | return CODEC_ERROR; |
379 | goto done; | ||
380 | } | 380 | } |
381 | 381 | ||
382 | if (!codec->set_format(&format)) | 382 | if (!codec->set_format(&format)) |
383 | { | 383 | { |
384 | status = CODEC_ERROR; | 384 | return CODEC_ERROR; |
385 | goto done; | ||
386 | } | 385 | } |
387 | 386 | ||
388 | /* check chunksize */ | 387 | /* check chunksize */ |
@@ -392,8 +391,7 @@ next_track: | |||
392 | if (format.chunksize == 0) | 391 | if (format.chunksize == 0) |
393 | { | 392 | { |
394 | DEBUGF("CODEC_ERROR: chunksize is 0\n"); | 393 | DEBUGF("CODEC_ERROR: chunksize is 0\n"); |
395 | status = CODEC_ERROR; | 394 | return CODEC_ERROR; |
396 | goto done; | ||
397 | } | 395 | } |
398 | 396 | ||
399 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); | 397 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); |
@@ -404,12 +402,10 @@ next_track: | |||
404 | ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); | 402 | ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); |
405 | } else { | 403 | } else { |
406 | DEBUGF("CODEC_ERROR: more than 2 channels unsupported\n"); | 404 | DEBUGF("CODEC_ERROR: more than 2 channels unsupported\n"); |
407 | status = CODEC_ERROR; | 405 | return CODEC_ERROR; |
408 | goto done; | ||
409 | } | 406 | } |
410 | 407 | ||
411 | ci->seek_buffer(firstblockposn); | 408 | ci->seek_buffer(firstblockposn); |
412 | ci->seek_complete(); | ||
413 | 409 | ||
414 | /* make sure we're at the correct offset */ | 410 | /* make sure we're at the correct offset */ |
415 | if (bytesdone > (uint32_t) firstblockposn) | 411 | if (bytesdone > (uint32_t) firstblockposn) |
@@ -419,13 +415,13 @@ next_track: | |||
419 | PCM_SEEK_POS, &read_buffer); | 415 | PCM_SEEK_POS, &read_buffer); |
420 | 416 | ||
421 | if (newpos->pos > format.numbytes) | 417 | if (newpos->pos > format.numbytes) |
422 | goto done; | 418 | return CODEC_OK; |
419 | |||
423 | if (ci->seek_buffer(firstblockposn + newpos->pos)) | 420 | if (ci->seek_buffer(firstblockposn + newpos->pos)) |
424 | { | 421 | { |
425 | bytesdone = newpos->pos; | 422 | bytesdone = newpos->pos; |
426 | decodedsamples = newpos->samples; | 423 | decodedsamples = newpos->samples; |
427 | } | 424 | } |
428 | ci->seek_complete(); | ||
429 | } | 425 | } |
430 | else | 426 | else |
431 | { | 427 | { |
@@ -437,23 +433,32 @@ next_track: | |||
437 | endofstream = 0; | 433 | endofstream = 0; |
438 | 434 | ||
439 | while (!endofstream) { | 435 | while (!endofstream) { |
440 | ci->yield(); | 436 | enum codec_command_action action = ci->get_command(¶m); |
441 | if (ci->stop_codec || ci->new_track) | 437 | |
438 | if (action == CODEC_ACTION_HALT) | ||
442 | break; | 439 | break; |
443 | 440 | ||
444 | if (ci->seek_time) { | 441 | if (action == CODEC_ACTION_SEEK_TIME) { |
445 | struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, PCM_SEEK_TIME, | 442 | struct pcm_pos *newpos = codec->get_seek_pos(param, PCM_SEEK_TIME, |
446 | &read_buffer); | 443 | &read_buffer); |
447 | 444 | ||
448 | if (newpos->pos > format.numbytes) | 445 | if (newpos->pos > format.numbytes) |
446 | { | ||
447 | ci->set_elapsed(ci->id3->length); | ||
448 | ci->seek_complete(); | ||
449 | break; | 449 | break; |
450 | } | ||
451 | |||
450 | if (ci->seek_buffer(firstblockposn + newpos->pos)) | 452 | if (ci->seek_buffer(firstblockposn + newpos->pos)) |
451 | { | 453 | { |
452 | bytesdone = newpos->pos; | 454 | bytesdone = newpos->pos; |
453 | decodedsamples = newpos->samples; | 455 | decodedsamples = newpos->samples; |
454 | } | 456 | } |
457 | |||
458 | ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); | ||
455 | ci->seek_complete(); | 459 | ci->seek_complete(); |
456 | } | 460 | } |
461 | |||
457 | smafbuf = (uint8_t *)ci->request_buffer(&n, format.chunksize); | 462 | smafbuf = (uint8_t *)ci->request_buffer(&n, format.chunksize); |
458 | 463 | ||
459 | if (n == 0) | 464 | if (n == 0) |
@@ -464,11 +469,10 @@ next_track: | |||
464 | endofstream = 1; | 469 | endofstream = 1; |
465 | } | 470 | } |
466 | 471 | ||
467 | status = codec->decode(smafbuf, n, samples, &bufcount); | 472 | if (codec->decode(smafbuf, n, samples, &bufcount) == CODEC_ERROR) |
468 | if (status == CODEC_ERROR) | ||
469 | { | 473 | { |
470 | DEBUGF("codec error\n"); | 474 | DEBUGF("codec error\n"); |
471 | goto done; | 475 | return CODEC_ERROR; |
472 | } | 476 | } |
473 | 477 | ||
474 | ci->pcmbuf_insert(samples, NULL, bufcount); | 478 | ci->pcmbuf_insert(samples, NULL, bufcount); |
@@ -482,11 +486,5 @@ next_track: | |||
482 | ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); | 486 | ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); |
483 | } | 487 | } |
484 | 488 | ||
485 | done: | 489 | return CODEC_OK; |
486 | if (ci->request_next_track()) | ||
487 | goto next_track; | ||
488 | |||
489 | exit: | ||
490 | return status; | ||
491 | } | 490 | } |
492 | |||
diff --git a/apps/codecs/spc.c b/apps/codecs/spc.c index 4db2878964..1b49761810 100644 --- a/apps/codecs/spc.c +++ b/apps/codecs/spc.c | |||
@@ -260,14 +260,6 @@ static inline void samples_release_rdbuf(void) | |||
260 | static inline int32_t * samples_get_rdbuf(void) | 260 | static inline int32_t * samples_get_rdbuf(void) |
261 | { | 261 | { |
262 | ci->semaphore_wait(&sample_queue.emu_sem_head, TIMEOUT_BLOCK); | 262 | ci->semaphore_wait(&sample_queue.emu_sem_head, TIMEOUT_BLOCK); |
263 | |||
264 | if (ci->stop_codec || ci->new_track) | ||
265 | { | ||
266 | /* Told to stop. Buffer must be released. */ | ||
267 | samples_release_rdbuf(); | ||
268 | return NULL; | ||
269 | } | ||
270 | |||
271 | return sample_queue.wav_chunk[sample_queue.head & WAV_CHUNK_MASK].audio; | 263 | return sample_queue.wav_chunk[sample_queue.head & WAV_CHUNK_MASK].audio; |
272 | } | 264 | } |
273 | 265 | ||
@@ -390,11 +382,10 @@ static inline void spc_emu_quit(void) | |||
390 | } | 382 | } |
391 | } | 383 | } |
392 | 384 | ||
393 | static inline bool spc_play_get_samples(int32_t **samples) | 385 | static inline int32_t * spc_play_get_samples(void) |
394 | { | 386 | { |
395 | /* obtain filled samples buffer */ | 387 | /* obtain filled samples buffer */ |
396 | *samples = samples_get_rdbuf(); | 388 | return samples_get_rdbuf(); |
397 | return *samples != NULL; | ||
398 | } | 389 | } |
399 | 390 | ||
400 | static inline void spc_play_send_samples(int32_t *samples) | 391 | static inline void spc_play_send_samples(int32_t *samples) |
@@ -433,15 +424,14 @@ static inline void spc_play_send_samples(int32_t *samples) | |||
433 | #define spc_emu_quit() | 424 | #define spc_emu_quit() |
434 | #define samples_release_rdbuf() | 425 | #define samples_release_rdbuf() |
435 | 426 | ||
436 | static inline bool spc_play_get_samples(int32_t **samples) | 427 | static inline int32_t * spc_play_get_samples(void) |
437 | { | 428 | { |
438 | ENTER_TIMER(render); | 429 | ENTER_TIMER(render); |
439 | /* fill samples buffer */ | 430 | /* fill samples buffer */ |
440 | if ( SPC_play(&spc_emu,WAV_CHUNK_SIZE*2,wav_chunk) ) | 431 | if ( SPC_play(&spc_emu,WAV_CHUNK_SIZE*2,wav_chunk) ) |
441 | assert( false ); | 432 | assert( false ); |
442 | EXIT_TIMER(render); | 433 | EXIT_TIMER(render); |
443 | *samples = wav_chunk; | 434 | return wav_chunk; |
444 | return true; | ||
445 | } | 435 | } |
446 | #endif /* SPC_DUAL_CORE */ | 436 | #endif /* SPC_DUAL_CORE */ |
447 | 437 | ||
@@ -454,6 +444,7 @@ static int play_track( void ) | |||
454 | unsigned long fadeendsample = (ID666.length+ID666.fade)*(long long) SAMPLE_RATE/1000; | 444 | unsigned long fadeendsample = (ID666.length+ID666.fade)*(long long) SAMPLE_RATE/1000; |
455 | int fadedec = 0; | 445 | int fadedec = 0; |
456 | int fadevol = 0x7fffffffl; | 446 | int fadevol = 0x7fffffffl; |
447 | intptr_t param; | ||
457 | 448 | ||
458 | if (fadeendsample>fadestartsample) | 449 | if (fadeendsample>fadestartsample) |
459 | fadedec=0x7fffffffl/(fadeendsample-fadestartsample)+1; | 450 | fadedec=0x7fffffffl/(fadeendsample-fadestartsample)+1; |
@@ -462,25 +453,26 @@ static int play_track( void ) | |||
462 | 453 | ||
463 | while ( 1 ) | 454 | while ( 1 ) |
464 | { | 455 | { |
465 | ci->yield(); | 456 | enum codec_command_action action = ci->get_command(¶m); |
466 | if (ci->stop_codec || ci->new_track) { | 457 | |
458 | if (action == CODEC_ACTION_HALT) | ||
467 | break; | 459 | break; |
468 | } | ||
469 | 460 | ||
470 | if (ci->seek_time) { | 461 | if (action == CODEC_ACTION_SEEK_TIME) { |
471 | int curtime = sampleswritten*1000LL/SAMPLE_RATE; | 462 | int curtime = sampleswritten*1000LL/SAMPLE_RATE; |
472 | DEBUGF("seek to %ld\ncurrently at %d\n",ci->seek_time,curtime); | 463 | DEBUGF("seek to %ld\ncurrently at %d\n", (long)param, curtime); |
473 | if (ci->seek_time < curtime) { | 464 | if (param < curtime) { |
474 | DEBUGF("seek backwards = reset\n"); | 465 | DEBUGF("seek backwards = reset\n"); |
466 | ci->set_elapsed(0); | ||
475 | ci->seek_complete(); | 467 | ci->seek_complete(); |
476 | return 1; | 468 | return 1; |
477 | } | 469 | } |
470 | |||
471 | ci->set_elapsed(curtime); | ||
478 | ci->seek_complete(); | 472 | ci->seek_complete(); |
479 | } | 473 | } |
480 | 474 | ||
481 | int32_t *samples; | 475 | int32_t *samples = spc_play_get_samples(); |
482 | if (!spc_play_get_samples(&samples)) | ||
483 | break; | ||
484 | 476 | ||
485 | sampleswritten += WAV_CHUNK_SIZE; | 477 | sampleswritten += WAV_CHUNK_SIZE; |
486 | 478 | ||
@@ -532,67 +524,61 @@ static int play_track( void ) | |||
532 | } | 524 | } |
533 | 525 | ||
534 | /* this is the codec entry point */ | 526 | /* this is the codec entry point */ |
535 | enum codec_status codec_main(void) | 527 | enum codec_status codec_main(enum codec_entry_call_reason reason) |
536 | { | 528 | { |
537 | enum codec_status stat = CODEC_ERROR; | 529 | if (reason == CODEC_LOAD) { |
538 | 530 | if (!spc_emu_start()) | |
539 | if (!spc_emu_start()) | 531 | return CODEC_ERROR; |
540 | goto codec_quit; | ||
541 | |||
542 | do | ||
543 | { | ||
544 | DEBUGF("SPC: next_track\n"); | ||
545 | if (codec_init()) { | ||
546 | goto codec_quit; | ||
547 | } | ||
548 | DEBUGF("SPC: after init\n"); | ||
549 | 532 | ||
550 | ci->configure(DSP_SET_SAMPLE_DEPTH, 24); | 533 | ci->configure(DSP_SET_SAMPLE_DEPTH, 24); |
551 | ci->configure(DSP_SET_FREQUENCY, SAMPLE_RATE); | 534 | ci->configure(DSP_SET_FREQUENCY, SAMPLE_RATE); |
552 | ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); | 535 | ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED); |
536 | } | ||
537 | else if (reason == CODEC_UNLOAD) { | ||
538 | spc_emu_quit(); | ||
539 | } | ||
553 | 540 | ||
554 | /* wait for track info to load */ | 541 | return CODEC_OK; |
555 | if (codec_wait_taginfo() != 0) | 542 | } |
556 | continue; | ||
557 | |||
558 | codec_set_replaygain(ci->id3); | ||
559 | 543 | ||
560 | /* Read the entire file */ | 544 | /* this is called for each file to process */ |
561 | DEBUGF("SPC: request initial buffer\n"); | 545 | enum codec_status codec_run(void) |
562 | ci->seek_buffer(0); | 546 | { |
563 | size_t buffersize; | 547 | DEBUGF("SPC: next_track\n"); |
564 | uint8_t* buffer = ci->request_buffer(&buffersize, ci->filesize); | 548 | if (codec_init()) |
565 | if (!buffer) { | 549 | return CODEC_ERROR; |
566 | goto codec_quit; | 550 | DEBUGF("SPC: after init\n"); |
551 | |||
552 | codec_set_replaygain(ci->id3); | ||
553 | |||
554 | /* Read the entire file */ | ||
555 | DEBUGF("SPC: request initial buffer\n"); | ||
556 | ci->seek_buffer(0); | ||
557 | size_t buffersize; | ||
558 | uint8_t* buffer = ci->request_buffer(&buffersize, ci->filesize); | ||
559 | if (!buffer) | ||
560 | return CODEC_ERROR; | ||
561 | |||
562 | DEBUGF("SPC: read size = 0x%lx\n",(unsigned long)buffersize); | ||
563 | do | ||
564 | { | ||
565 | if (load_spc_buffer(buffer, buffersize)) { | ||
566 | DEBUGF("SPC load failure\n"); | ||
567 | return CODEC_ERROR; | ||
567 | } | 568 | } |
568 | 569 | ||
569 | DEBUGF("SPC: read size = 0x%lx\n",(unsigned long)buffersize); | 570 | LoadID666(buffer+0x2e); |
570 | do | ||
571 | { | ||
572 | if (load_spc_buffer(buffer, buffersize)) { | ||
573 | DEBUGF("SPC load failure\n"); | ||
574 | goto codec_quit; | ||
575 | } | ||
576 | |||
577 | LoadID666(buffer+0x2e); | ||
578 | 571 | ||
579 | if (ci->global_settings->repeat_mode!=REPEAT_ONE && ID666.length==0) { | 572 | if (ci->global_settings->repeat_mode!=REPEAT_ONE && ID666.length==0) { |
580 | ID666.length=3*60*1000; /* 3 minutes */ | 573 | ID666.length=3*60*1000; /* 3 minutes */ |
581 | ID666.fade=5*1000; /* 5 seconds */ | 574 | ID666.fade=5*1000; /* 5 seconds */ |
582 | } | ||
583 | |||
584 | reset_profile_timers(); | ||
585 | } | 575 | } |
586 | while ( play_track() ); | ||
587 | 576 | ||
588 | print_timers(ci->id3->path); | 577 | reset_profile_timers(); |
589 | } | 578 | } |
590 | while ( ci->request_next_track() ); | 579 | while ( play_track() ); |
591 | 580 | ||
592 | stat = CODEC_OK; | 581 | print_timers(ci->id3->path); |
593 | 582 | ||
594 | codec_quit: | 583 | return CODEC_OK; |
595 | spc_emu_quit(); | ||
596 | |||
597 | return stat; | ||
598 | } | 584 | } |
diff --git a/apps/codecs/speex.c b/apps/codecs/speex.c index 7a1efa9753..e394efc3d5 100644 --- a/apps/codecs/speex.c +++ b/apps/codecs/speex.c | |||
@@ -367,11 +367,12 @@ static void *process_header(spx_ogg_packet *op, | |||
367 | return st; | 367 | return st; |
368 | } | 368 | } |
369 | 369 | ||
370 | /* this is the codec entry point */ | 370 | /* this is called for each file to process */ |
371 | enum codec_status codec_main(void) | 371 | enum codec_status codec_run(void) |
372 | { | 372 | { |
373 | int error = CODEC_ERROR; | ||
374 | |||
373 | SpeexBits bits; | 375 | SpeexBits bits; |
374 | int error; | ||
375 | int eof = 0; | 376 | int eof = 0; |
376 | spx_ogg_sync_state oy; | 377 | spx_ogg_sync_state oy; |
377 | spx_ogg_page og; | 378 | spx_ogg_page og; |
@@ -383,7 +384,7 @@ enum codec_status codec_main(void) | |||
383 | int eos = 0; | 384 | int eos = 0; |
384 | SpeexStereoState *stereo; | 385 | SpeexStereoState *stereo; |
385 | int channels = -1; | 386 | int channels = -1; |
386 | int rate = 0, samplerate = 0; | 387 | int samplerate = 0; |
387 | int extra_headers = 0; | 388 | int extra_headers = 0; |
388 | int stream_init = 0; | 389 | int stream_init = 0; |
389 | int page_nb_packets, frame_size, packet_count = 0; | 390 | int page_nb_packets, frame_size, packet_count = 0; |
@@ -392,26 +393,22 @@ enum codec_status codec_main(void) | |||
392 | unsigned long strtoffset = 0; | 393 | unsigned long strtoffset = 0; |
393 | void *st = NULL; | 394 | void *st = NULL; |
394 | int j = 0; | 395 | int j = 0; |
396 | intptr_t param; | ||
395 | 397 | ||
396 | memset(&bits, 0, sizeof(bits)); | 398 | memset(&bits, 0, sizeof(bits)); |
397 | memset(&oy, 0, sizeof(oy)); | 399 | memset(&oy, 0, sizeof(oy)); |
398 | 400 | ||
399 | /* Ogg handling still uses mallocs, so reset the malloc buffer per track */ | 401 | /* Ogg handling still uses mallocs, so reset the malloc buffer per track */ |
400 | next_track: | ||
401 | error = CODEC_OK; | ||
402 | |||
403 | if (codec_init()) { | 402 | if (codec_init()) { |
404 | error = CODEC_ERROR; | ||
405 | goto exit; | 403 | goto exit; |
406 | } | 404 | } |
407 | 405 | ||
406 | ci->seek_buffer(0); | ||
407 | |||
408 | stereo = speex_stereo_state_init(); | 408 | stereo = speex_stereo_state_init(); |
409 | spx_ogg_sync_init(&oy); | 409 | spx_ogg_sync_init(&oy); |
410 | spx_ogg_alloc_buffer(&oy,2*CHUNKSIZE); | 410 | spx_ogg_alloc_buffer(&oy,2*CHUNKSIZE); |
411 | 411 | ||
412 | if (codec_wait_taginfo() != 0) | ||
413 | goto done; | ||
414 | |||
415 | strtoffset = ci->id3->offset; | 412 | strtoffset = ci->id3->offset; |
416 | 413 | ||
417 | samplerate = ci->id3->frequency; | 414 | samplerate = ci->id3->frequency; |
@@ -419,30 +416,32 @@ next_track: | |||
419 | 416 | ||
420 | eof = 0; | 417 | eof = 0; |
421 | while (!eof) { | 418 | while (!eof) { |
422 | ci->yield(); | 419 | enum codec_command_action action = ci->get_command(¶m); |
423 | if (ci->stop_codec || ci->new_track) | 420 | |
421 | if (action == CODEC_ACTION_HALT) | ||
424 | break; | 422 | break; |
425 | 423 | ||
426 | /*seek (seeks to the page before the position) */ | 424 | /*seek (seeks to the page before the position) */ |
427 | if (ci->seek_time) { | 425 | if (action == CODEC_ACTION_SEEK_TIME) { |
428 | if(samplerate!=0&&packet_count>1){ | 426 | if(samplerate!=0&&packet_count>1){ |
429 | LOGF("Speex seek page:%lld,%lld,%ld,%lld,%d\n", | 427 | LOGF("Speex seek page:%lld,%lld,%ld,%lld,%d\n", |
430 | ((spx_int64_t)ci->seek_time/1000) * | 428 | ((spx_int64_t)param/1000) * |
431 | (spx_int64_t)samplerate, | 429 | (spx_int64_t)samplerate, |
432 | page_granule, ci->seek_time, | 430 | page_granule, param, |
433 | (page_granule/samplerate)*1000, samplerate); | 431 | (page_granule/samplerate)*1000, samplerate); |
434 | 432 | ||
435 | speex_seek_page_granule(((spx_int64_t)ci->seek_time/1000) * | 433 | speex_seek_page_granule(((spx_int64_t)param/1000) * |
436 | (spx_int64_t)samplerate, | 434 | (spx_int64_t)samplerate, |
437 | page_granule, &oy, headerssize); | 435 | page_granule, &oy, headerssize); |
438 | ci->seek_complete(); | ||
439 | } | 436 | } |
437 | |||
438 | ci->set_elapsed(param); | ||
439 | ci->seek_complete(); | ||
440 | } | 440 | } |
441 | 441 | ||
442 | next_page: | 442 | next_page: |
443 | /*Get the ogg buffer for writing*/ | 443 | /*Get the ogg buffer for writing*/ |
444 | if(get_more_data(&oy)<1){/*read error*/ | 444 | if(get_more_data(&oy)<1){/*read error*/ |
445 | error=CODEC_ERROR; | ||
446 | goto done; | 445 | goto done; |
447 | } | 446 | } |
448 | 447 | ||
@@ -477,8 +476,7 @@ next_page: | |||
477 | nframes=1; | 476 | nframes=1; |
478 | 477 | ||
479 | if (!st){ | 478 | if (!st){ |
480 | error=CODEC_ERROR; | 479 | goto done; |
481 | goto exit; | ||
482 | } | 480 | } |
483 | 481 | ||
484 | ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency); | 482 | ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency); |
@@ -557,31 +555,18 @@ next_page: | |||
557 | } | 555 | } |
558 | 556 | ||
559 | done: | 557 | done: |
560 | if (ci->request_next_track()) { | 558 | /* Clean things up for the next track */ |
561 | 559 | speex_bits_destroy(&bits); | |
562 | /* Clean things up for the next track */ | ||
563 | 560 | ||
561 | if (st) | ||
564 | if (st) | 562 | if (st) |
565 | speex_decoder_destroy(st); | 563 | speex_decoder_destroy(st); |
566 | 564 | ||
567 | if (stream_init == 1) | ||
568 | spx_ogg_stream_reset(&os); | ||
569 | |||
570 | spx_ogg_sync_reset(&oy); | ||
571 | |||
572 | cur_granule = stream_init = rate = samplerate = headerssize | ||
573 | = packet_count = eos = 0; | ||
574 | |||
575 | goto next_track; | ||
576 | } | ||
577 | |||
578 | exit: | ||
579 | speex_bits_destroy(&bits); | ||
580 | |||
581 | if (stream_init) | 565 | if (stream_init) |
582 | spx_ogg_stream_destroy(&os); | 566 | spx_ogg_stream_destroy(&os); |
583 | 567 | ||
584 | spx_ogg_sync_destroy(&oy); | 568 | spx_ogg_sync_destroy(&oy); |
585 | 569 | ||
570 | exit: | ||
586 | return error; | 571 | return error; |
587 | } | 572 | } |
diff --git a/apps/codecs/tta.c b/apps/codecs/tta.c index 1d0846ea61..c75f2b0a57 100644 --- a/apps/codecs/tta.c +++ b/apps/codecs/tta.c | |||
@@ -34,36 +34,36 @@ CODEC_HEADER | |||
34 | static int32_t samples[PCM_BUFFER_LENGTH * 2] IBSS_ATTR; | 34 | static int32_t samples[PCM_BUFFER_LENGTH * 2] IBSS_ATTR; |
35 | 35 | ||
36 | /* this is the codec entry point */ | 36 | /* this is the codec entry point */ |
37 | enum codec_status codec_main(void) | 37 | enum codec_status codec_main(enum codec_entry_call_reason reason) |
38 | { | ||
39 | if (reason == CODEC_LOAD) { | ||
40 | /* Generic codec initialisation */ | ||
41 | ci->configure(DSP_SET_SAMPLE_DEPTH, TTA_OUTPUT_DEPTH - 1); | ||
42 | } | ||
43 | |||
44 | return CODEC_OK; | ||
45 | } | ||
46 | |||
47 | /* this is called for each file to process */ | ||
48 | enum codec_status codec_run(void) | ||
38 | { | 49 | { |
39 | tta_info info; | 50 | tta_info info; |
40 | int status; | ||
41 | unsigned int decodedsamples; | 51 | unsigned int decodedsamples; |
42 | int endofstream; | 52 | int endofstream; |
43 | int new_pos = 0; | 53 | int new_pos = 0; |
44 | int sample_count; | 54 | int sample_count; |
45 | 55 | intptr_t param; | |
46 | /* Generic codec initialisation */ | ||
47 | ci->configure(DSP_SET_SAMPLE_DEPTH, TTA_OUTPUT_DEPTH - 1); | ||
48 | 56 | ||
49 | next_track: | ||
50 | status = CODEC_OK; | ||
51 | |||
52 | if (codec_init()) | 57 | if (codec_init()) |
53 | { | 58 | { |
54 | DEBUGF("codec_init() error\n"); | 59 | DEBUGF("codec_init() error\n"); |
55 | status = CODEC_ERROR; | 60 | return CODEC_ERROR; |
56 | goto exit; | ||
57 | } | 61 | } |
58 | 62 | ||
59 | if (codec_wait_taginfo() != 0) | 63 | ci->seek_buffer(0); |
60 | goto done; | ||
61 | 64 | ||
62 | if (set_tta_info(&info) < 0 || player_init(&info) < 0) | 65 | if (set_tta_info(&info) < 0 || player_init(&info) < 0) |
63 | { | 66 | return CODEC_ERROR; |
64 | status = CODEC_ERROR; | ||
65 | goto exit; | ||
66 | } | ||
67 | 67 | ||
68 | codec_set_replaygain(ci->id3); | 68 | codec_set_replaygain(ci->id3); |
69 | 69 | ||
@@ -74,8 +74,8 @@ next_track: | |||
74 | ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); | 74 | ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); |
75 | } else { | 75 | } else { |
76 | DEBUGF("CODEC_ERROR: more than 2 channels\n"); | 76 | DEBUGF("CODEC_ERROR: more than 2 channels\n"); |
77 | status = CODEC_ERROR; | 77 | player_stop(); |
78 | goto done; | 78 | return CODEC_ERROR; |
79 | } | 79 | } |
80 | 80 | ||
81 | /* The main decoder loop */ | 81 | /* The main decoder loop */ |
@@ -88,31 +88,31 @@ next_track: | |||
88 | new_pos = set_position(ci->id3->offset, TTA_SEEK_POS); | 88 | new_pos = set_position(ci->id3->offset, TTA_SEEK_POS); |
89 | if (new_pos >= 0) | 89 | if (new_pos >= 0) |
90 | decodedsamples = new_pos; | 90 | decodedsamples = new_pos; |
91 | ci->seek_complete(); | ||
92 | } | 91 | } |
93 | 92 | ||
94 | while (!endofstream) | 93 | while (!endofstream) |
95 | { | 94 | { |
96 | ci->yield(); | 95 | enum codec_command_action action = ci->get_command(¶m); |
97 | if (ci->stop_codec || ci->new_track) | 96 | |
97 | if (action == CODEC_ACTION_HALT) | ||
98 | break; | 98 | break; |
99 | 99 | ||
100 | if (ci->seek_time) | 100 | if (action == CODEC_ACTION_SEEK_TIME) |
101 | { | 101 | { |
102 | new_pos = set_position(ci->seek_time / SEEK_STEP, TTA_SEEK_TIME); | 102 | new_pos = set_position(param / SEEK_STEP, TTA_SEEK_TIME); |
103 | if (new_pos >= 0) | 103 | if (new_pos >= 0) |
104 | { | 104 | { |
105 | decodedsamples = new_pos; | 105 | decodedsamples = new_pos; |
106 | ci->seek_complete(); | ||
107 | } | 106 | } |
107 | |||
108 | ci->set_elapsed((uint64_t)info.LENGTH * 1000 * decodedsamples / info.DATALENGTH); | ||
109 | ci->seek_complete(); | ||
108 | } | 110 | } |
109 | 111 | ||
110 | sample_count = get_samples(samples); | 112 | sample_count = get_samples(samples); |
111 | if (sample_count < 0) | 113 | if (sample_count < 0) |
112 | { | ||
113 | status = CODEC_ERROR; | ||
114 | break; | 114 | break; |
115 | } | 115 | |
116 | ci->pcmbuf_insert(samples, NULL, sample_count); | 116 | ci->pcmbuf_insert(samples, NULL, sample_count); |
117 | decodedsamples += sample_count; | 117 | decodedsamples += sample_count; |
118 | if (decodedsamples >= info.DATALENGTH) | 118 | if (decodedsamples >= info.DATALENGTH) |
@@ -120,11 +120,6 @@ next_track: | |||
120 | ci->set_elapsed((uint64_t)info.LENGTH * 1000 * decodedsamples / info.DATALENGTH); | 120 | ci->set_elapsed((uint64_t)info.LENGTH * 1000 * decodedsamples / info.DATALENGTH); |
121 | } | 121 | } |
122 | 122 | ||
123 | done: | ||
124 | player_stop(); | 123 | player_stop(); |
125 | if (ci->request_next_track()) | 124 | return CODEC_OK; |
126 | goto next_track; | ||
127 | |||
128 | exit: | ||
129 | return status; | ||
130 | } | 125 | } |
diff --git a/apps/codecs/vorbis.c b/apps/codecs/vorbis.c index 0a36a37c8b..e02d459262 100644 --- a/apps/codecs/vorbis.c +++ b/apps/codecs/vorbis.c | |||
@@ -104,14 +104,25 @@ static bool vorbis_set_codec_parameters(OggVorbis_File *vf) | |||
104 | } | 104 | } |
105 | 105 | ||
106 | /* this is the codec entry point */ | 106 | /* this is the codec entry point */ |
107 | enum codec_status codec_main(void) | 107 | enum codec_status codec_main(enum codec_entry_call_reason reason) |
108 | { | ||
109 | if (reason == CODEC_LOAD) { | ||
110 | if (codec_init()) | ||
111 | return CODEC_ERROR; | ||
112 | ci->configure(DSP_SET_SAMPLE_DEPTH, 24); | ||
113 | } | ||
114 | |||
115 | return CODEC_OK; | ||
116 | } | ||
117 | |||
118 | /* this is called for each file to process */ | ||
119 | enum codec_status codec_run(void) | ||
108 | { | 120 | { |
109 | ov_callbacks callbacks; | 121 | ov_callbacks callbacks; |
110 | OggVorbis_File vf; | 122 | OggVorbis_File vf; |
111 | ogg_int32_t **pcm; | 123 | ogg_int32_t **pcm; |
112 | 124 | ||
113 | bool initialized = false; /* First init done? */ | 125 | int error = CODEC_ERROR; |
114 | int error; | ||
115 | long n; | 126 | long n; |
116 | int current_section; | 127 | int current_section; |
117 | int previous_section; | 128 | int previous_section; |
@@ -120,36 +131,24 @@ enum codec_status codec_main(void) | |||
120 | ogg_int64_t vf_dataoffsets; | 131 | ogg_int64_t vf_dataoffsets; |
121 | ogg_uint32_t vf_serialnos; | 132 | ogg_uint32_t vf_serialnos; |
122 | ogg_int64_t vf_pcmlengths[2]; | 133 | ogg_int64_t vf_pcmlengths[2]; |
123 | 134 | intptr_t param; | |
124 | ci->configure(DSP_SET_SAMPLE_DEPTH, 24); | ||
125 | |||
126 | if (codec_init()) { | ||
127 | error = CODEC_ERROR; | ||
128 | goto exit; | ||
129 | } | ||
130 | 135 | ||
131 | #if defined(CPU_ARM) || defined(CPU_COLDFIRE) || defined(CPU_MIPS) | 136 | #if defined(CPU_ARM) || defined(CPU_COLDFIRE) || defined(CPU_MIPS) |
132 | if (setjmp(rb_jump_buf) != 0) { | 137 | if (setjmp(rb_jump_buf) != 0) { |
133 | /* malloc failed; skip to next track */ | 138 | /* malloc failed; finish with this track */ |
134 | error = CODEC_ERROR; | ||
135 | goto done; | 139 | goto done; |
136 | } | 140 | } |
137 | #endif | 141 | #endif |
138 | |||
139 | next_track: | ||
140 | error = CODEC_OK; | ||
141 | |||
142 | ogg_malloc_init(); | 142 | ogg_malloc_init(); |
143 | 143 | ||
144 | if (codec_wait_taginfo() != 0) | ||
145 | goto done; | ||
146 | |||
147 | /* Create a decoder instance */ | 144 | /* Create a decoder instance */ |
148 | callbacks.read_func = read_handler; | 145 | callbacks.read_func = read_handler; |
149 | callbacks.seek_func = initial_seek_handler; | 146 | callbacks.seek_func = initial_seek_handler; |
150 | callbacks.tell_func = tell_handler; | 147 | callbacks.tell_func = tell_handler; |
151 | callbacks.close_func = close_handler; | 148 | callbacks.close_func = close_handler; |
152 | 149 | ||
150 | ci->seek_buffer(0); | ||
151 | |||
153 | /* Open a non-seekable stream */ | 152 | /* Open a non-seekable stream */ |
154 | error = ov_open_callbacks(ci, &vf, NULL, 0, callbacks); | 153 | error = ov_open_callbacks(ci, &vf, NULL, 0, callbacks); |
155 | 154 | ||
@@ -186,15 +185,13 @@ next_track: | |||
186 | vf.end = ci->id3->filesize; | 185 | vf.end = ci->id3->filesize; |
187 | vf.ready_state = OPENED; | 186 | vf.ready_state = OPENED; |
188 | vf.links = 1; | 187 | vf.links = 1; |
189 | initialized = true; | ||
190 | } else { | 188 | } else { |
191 | DEBUGF("Vorbis: ov_open failed: %d\n", error); | 189 | DEBUGF("Vorbis: ov_open failed: %d\n", error); |
192 | error = CODEC_ERROR; | ||
193 | goto done; | 190 | goto done; |
194 | } | 191 | } |
195 | 192 | ||
196 | if (ci->id3->offset) { | 193 | if (ci->id3->offset) { |
197 | ci->advance_buffer(ci->id3->offset); | 194 | ci->seek_buffer(ci->id3->offset); |
198 | ov_raw_seek(&vf, ci->id3->offset); | 195 | ov_raw_seek(&vf, ci->id3->offset); |
199 | ci->set_elapsed(ov_time_tell(&vf)); | 196 | ci->set_elapsed(ov_time_tell(&vf)); |
200 | ci->set_offset(ov_raw_tell(&vf)); | 197 | ci->set_offset(ov_raw_tell(&vf)); |
@@ -203,14 +200,17 @@ next_track: | |||
203 | previous_section = -1; | 200 | previous_section = -1; |
204 | eof = 0; | 201 | eof = 0; |
205 | while (!eof) { | 202 | while (!eof) { |
206 | ci->yield(); | 203 | enum codec_command_action action = ci->get_command(¶m); |
207 | if (ci->stop_codec || ci->new_track) | 204 | |
205 | if (action == CODEC_ACTION_HALT) | ||
208 | break; | 206 | break; |
209 | 207 | ||
210 | if (ci->seek_time) { | 208 | if (action == CODEC_ACTION_SEEK_TIME) { |
211 | if (ov_time_seek(&vf, ci->seek_time - 1)) { | 209 | if (ov_time_seek(&vf, param)) { |
212 | //ci->logf("ov_time_seek failed"); | 210 | //ci->logf("ov_time_seek failed"); |
213 | } | 211 | } |
212 | |||
213 | ci->set_elapsed(ov_time_tell(&vf)); | ||
214 | ci->seek_complete(); | 214 | ci->seek_complete(); |
215 | } | 215 | } |
216 | 216 | ||
@@ -220,7 +220,6 @@ next_track: | |||
220 | /* Change DSP and buffer settings for this bitstream */ | 220 | /* Change DSP and buffer settings for this bitstream */ |
221 | if (current_section != previous_section) { | 221 | if (current_section != previous_section) { |
222 | if (!vorbis_set_codec_parameters(&vf)) { | 222 | if (!vorbis_set_codec_parameters(&vf)) { |
223 | error = CODEC_ERROR; | ||
224 | goto done; | 223 | goto done; |
225 | } else { | 224 | } else { |
226 | previous_section = current_section; | 225 | previous_section = current_section; |
@@ -238,6 +237,7 @@ next_track: | |||
238 | } | 237 | } |
239 | } | 238 | } |
240 | 239 | ||
240 | error = CODEC_OK; | ||
241 | done: | 241 | done: |
242 | #if 0 /* defined(SIMULATOR) */ | 242 | #if 0 /* defined(SIMULATOR) */ |
243 | { | 243 | { |
@@ -249,18 +249,12 @@ done: | |||
249 | #endif | 249 | #endif |
250 | ogg_malloc_destroy(); | 250 | ogg_malloc_destroy(); |
251 | 251 | ||
252 | if (ci->request_next_track()) { | 252 | /* Clean things up for the next track */ |
253 | if (!initialized) | 253 | vf.dataoffsets = NULL; |
254 | goto next_track; | 254 | vf.offsets = NULL; |
255 | /* Clean things up for the next track */ | 255 | vf.serialnos = NULL; |
256 | vf.dataoffsets = NULL; | 256 | vf.pcmlengths = NULL; |
257 | vf.offsets = NULL; | 257 | ov_clear(&vf); |
258 | vf.serialnos = NULL; | 258 | |
259 | vf.pcmlengths = NULL; | ||
260 | ov_clear(&vf); | ||
261 | goto next_track; | ||
262 | } | ||
263 | |||
264 | exit: | ||
265 | return error; | 259 | return error; |
266 | } | 260 | } |
diff --git a/apps/codecs/vox.c b/apps/codecs/vox.c index c7f39342c3..bf274c6917 100644 --- a/apps/codecs/vox.c +++ b/apps/codecs/vox.c | |||
@@ -44,9 +44,19 @@ static uint8_t *read_buffer(size_t *realsize) | |||
44 | } | 44 | } |
45 | 45 | ||
46 | /* this is the codec entry point */ | 46 | /* this is the codec entry point */ |
47 | enum codec_status codec_main(void) | 47 | enum codec_status codec_main(enum codec_entry_call_reason reason) |
48 | { | ||
49 | if (reason == CODEC_LOAD) { | ||
50 | /* Generic codec initialisation */ | ||
51 | ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1); | ||
52 | } | ||
53 | |||
54 | return CODEC_OK; | ||
55 | } | ||
56 | |||
57 | /* this is called for each file to process */ | ||
58 | enum codec_status codec_run(void) | ||
48 | { | 59 | { |
49 | int status; | ||
50 | uint32_t decodedsamples; | 60 | uint32_t decodedsamples; |
51 | size_t n; | 61 | size_t n; |
52 | int bufcount; | 62 | int bufcount; |
@@ -54,26 +64,18 @@ enum codec_status codec_main(void) | |||
54 | uint8_t *voxbuf; | 64 | uint8_t *voxbuf; |
55 | off_t firstblockposn = 0; /* position of the first block in file */ | 65 | off_t firstblockposn = 0; /* position of the first block in file */ |
56 | const struct pcm_codec *codec; | 66 | const struct pcm_codec *codec; |
57 | 67 | intptr_t param; | |
58 | /* Generic codec initialisation */ | ||
59 | ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1); | ||
60 | |||
61 | next_track: | ||
62 | status = CODEC_OK; | ||
63 | 68 | ||
64 | if (codec_init()) { | 69 | if (codec_init()) { |
65 | DEBUGF("codec_init() error\n"); | 70 | DEBUGF("codec_init() error\n"); |
66 | status = CODEC_ERROR; | 71 | return CODEC_ERROR; |
67 | goto exit; | ||
68 | } | 72 | } |
69 | 73 | ||
70 | if (codec_wait_taginfo() != 0) | ||
71 | goto done; | ||
72 | |||
73 | codec_set_replaygain(ci->id3); | 74 | codec_set_replaygain(ci->id3); |
74 | 75 | ||
75 | /* Need to save offset for later use (cleared indirectly by advance_buffer) */ | 76 | /* Need to save offset for later use (cleared indirectly by advance_buffer) */ |
76 | bytesdone = ci->id3->offset; | 77 | bytesdone = ci->id3->offset; |
78 | ci->seek_buffer(0); | ||
77 | 79 | ||
78 | ci->memset(&format, 0, sizeof(struct pcm_format)); | 80 | ci->memset(&format, 0, sizeof(struct pcm_format)); |
79 | 81 | ||
@@ -96,20 +98,16 @@ next_track: | |||
96 | if (!codec) | 98 | if (!codec) |
97 | { | 99 | { |
98 | DEBUGF("CODEC_ERROR: dialogic oki adpcm codec does not load.\n"); | 100 | DEBUGF("CODEC_ERROR: dialogic oki adpcm codec does not load.\n"); |
99 | status = CODEC_ERROR; | 101 | return CODEC_ERROR; |
100 | goto done; | ||
101 | } | 102 | } |
102 | 103 | ||
103 | if (!codec->set_format(&format)) | 104 | if (!codec->set_format(&format)) { |
104 | { | 105 | return CODEC_ERROR; |
105 | status = CODEC_ERROR; | ||
106 | goto done; | ||
107 | } | 106 | } |
108 | 107 | ||
109 | if (format.numbytes == 0) { | 108 | if (format.numbytes == 0) { |
110 | DEBUGF("CODEC_ERROR: data size is 0\n"); | 109 | DEBUGF("CODEC_ERROR: data size is 0\n"); |
111 | status = CODEC_ERROR; | 110 | return CODEC_ERROR; |
112 | goto done; | ||
113 | } | 111 | } |
114 | 112 | ||
115 | /* check chunksize */ | 113 | /* check chunksize */ |
@@ -118,8 +116,7 @@ next_track: | |||
118 | if (format.chunksize == 0) | 116 | if (format.chunksize == 0) |
119 | { | 117 | { |
120 | DEBUGF("CODEC_ERROR: chunksize is 0\n"); | 118 | DEBUGF("CODEC_ERROR: chunksize is 0\n"); |
121 | status = CODEC_ERROR; | 119 | return CODEC_ERROR; |
122 | goto done; | ||
123 | } | 120 | } |
124 | 121 | ||
125 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); | 122 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); |
@@ -131,14 +128,14 @@ next_track: | |||
131 | struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn, | 128 | struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn, |
132 | PCM_SEEK_POS, &read_buffer); | 129 | PCM_SEEK_POS, &read_buffer); |
133 | 130 | ||
134 | if (newpos->pos > format.numbytes) | 131 | if (newpos->pos > format.numbytes) { |
135 | goto done; | 132 | return CODEC_OK; |
133 | } | ||
136 | if (ci->seek_buffer(firstblockposn + newpos->pos)) | 134 | if (ci->seek_buffer(firstblockposn + newpos->pos)) |
137 | { | 135 | { |
138 | bytesdone = newpos->pos; | 136 | bytesdone = newpos->pos; |
139 | decodedsamples = newpos->samples; | 137 | decodedsamples = newpos->samples; |
140 | } | 138 | } |
141 | ci->seek_complete(); | ||
142 | } else { | 139 | } else { |
143 | /* already where we need to be */ | 140 | /* already where we need to be */ |
144 | bytesdone = 0; | 141 | bytesdone = 0; |
@@ -148,22 +145,29 @@ next_track: | |||
148 | endofstream = 0; | 145 | endofstream = 0; |
149 | 146 | ||
150 | while (!endofstream) { | 147 | while (!endofstream) { |
151 | ci->yield(); | 148 | enum codec_command_action action = ci->get_command(¶m); |
152 | if (ci->stop_codec || ci->new_track) { | 149 | |
150 | if (action == CODEC_ACTION_HALT) | ||
153 | break; | 151 | break; |
154 | } | ||
155 | 152 | ||
156 | if (ci->seek_time) { | 153 | if (action == CODEC_ACTION_SEEK_TIME) { |
157 | struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, PCM_SEEK_TIME, | 154 | struct pcm_pos *newpos = codec->get_seek_pos(param, PCM_SEEK_TIME, |
158 | &read_buffer); | 155 | &read_buffer); |
159 | 156 | ||
160 | if (newpos->pos > format.numbytes) | 157 | if (newpos->pos > format.numbytes) |
158 | { | ||
159 | ci->set_elapsed(ci->id3->length); | ||
160 | ci->seek_complete(); | ||
161 | break; | 161 | break; |
162 | } | ||
163 | |||
162 | if (ci->seek_buffer(firstblockposn + newpos->pos)) | 164 | if (ci->seek_buffer(firstblockposn + newpos->pos)) |
163 | { | 165 | { |
164 | bytesdone = newpos->pos; | 166 | bytesdone = newpos->pos; |
165 | decodedsamples = newpos->samples; | 167 | decodedsamples = newpos->samples; |
166 | } | 168 | } |
169 | |||
170 | ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); | ||
167 | ci->seek_complete(); | 171 | ci->seek_complete(); |
168 | } | 172 | } |
169 | 173 | ||
@@ -175,11 +179,10 @@ next_track: | |||
175 | endofstream = 1; | 179 | endofstream = 1; |
176 | } | 180 | } |
177 | 181 | ||
178 | status = codec->decode(voxbuf, n, samples, &bufcount); | 182 | if (codec->decode(voxbuf, n, samples, &bufcount) == CODEC_ERROR) |
179 | if (status == CODEC_ERROR) | ||
180 | { | 183 | { |
181 | DEBUGF("codec error\n"); | 184 | DEBUGF("codec error\n"); |
182 | goto done; | 185 | return CODEC_ERROR; |
183 | } | 186 | } |
184 | 187 | ||
185 | ci->pcmbuf_insert(samples, NULL, bufcount); | 188 | ci->pcmbuf_insert(samples, NULL, bufcount); |
@@ -192,10 +195,5 @@ next_track: | |||
192 | ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); | 195 | ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); |
193 | } | 196 | } |
194 | 197 | ||
195 | done: | 198 | return CODEC_OK; |
196 | if (ci->request_next_track()) | ||
197 | goto next_track; | ||
198 | |||
199 | exit: | ||
200 | return status; | ||
201 | } | 199 | } |
diff --git a/apps/codecs/wav.c b/apps/codecs/wav.c index e179470f27..42bcc7081f 100644 --- a/apps/codecs/wav.c +++ b/apps/codecs/wav.c | |||
@@ -151,9 +151,19 @@ static uint8_t *read_buffer(size_t *realsize) | |||
151 | } | 151 | } |
152 | 152 | ||
153 | /* this is the codec entry point */ | 153 | /* this is the codec entry point */ |
154 | enum codec_status codec_main(void) | 154 | enum codec_status codec_main(enum codec_entry_call_reason reason) |
155 | { | ||
156 | if (reason == CODEC_LOAD) { | ||
157 | /* Generic codec initialisation */ | ||
158 | ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1); | ||
159 | } | ||
160 | |||
161 | return CODEC_OK; | ||
162 | } | ||
163 | |||
164 | /* this is called for each file to process */ | ||
165 | enum codec_status codec_run(void) | ||
155 | { | 166 | { |
156 | int status; | ||
157 | uint32_t decodedsamples; | 167 | uint32_t decodedsamples; |
158 | size_t n; | 168 | size_t n; |
159 | int bufcount; | 169 | int bufcount; |
@@ -163,38 +173,28 @@ enum codec_status codec_main(void) | |||
163 | off_t firstblockposn; /* position of the first block in file */ | 173 | off_t firstblockposn; /* position of the first block in file */ |
164 | const struct pcm_codec *codec; | 174 | const struct pcm_codec *codec; |
165 | uint32_t size; | 175 | uint32_t size; |
166 | 176 | intptr_t param; | |
167 | /* Generic codec initialisation */ | ||
168 | ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1); | ||
169 | |||
170 | next_track: | ||
171 | status = CODEC_OK; | ||
172 | 177 | ||
173 | if (codec_init()) { | 178 | if (codec_init()) { |
174 | DEBUGF("codec_init() error\n"); | 179 | DEBUGF("codec_init() error\n"); |
175 | status = CODEC_ERROR; | 180 | return CODEC_ERROR; |
176 | goto exit; | ||
177 | } | 181 | } |
178 | 182 | ||
179 | if (codec_wait_taginfo() != 0) | ||
180 | goto done; | ||
181 | |||
182 | codec_set_replaygain(ci->id3); | 183 | codec_set_replaygain(ci->id3); |
183 | 184 | ||
184 | /* Need to save offset for later use (cleared indirectly by advance_buffer) */ | 185 | /* Need to save offset for later use (cleared indirectly by advance_buffer) */ |
185 | bytesdone = ci->id3->offset; | 186 | bytesdone = ci->id3->offset; |
186 | 187 | ||
187 | /* get RIFF chunk header */ | 188 | /* get RIFF chunk header */ |
189 | ci->seek_buffer(0); | ||
188 | buf = ci->request_buffer(&n, 12); | 190 | buf = ci->request_buffer(&n, 12); |
189 | if (n < 12) { | 191 | if (n < 12) { |
190 | DEBUGF("request_buffer error\n"); | 192 | DEBUGF("request_buffer error\n"); |
191 | status = CODEC_ERROR; | 193 | return CODEC_ERROR; |
192 | goto done; | ||
193 | } | 194 | } |
194 | if ((memcmp(buf, "RIFF", 4) != 0) || (memcmp(&buf[8], "WAVE", 4) != 0)) { | 195 | if ((memcmp(buf, "RIFF", 4) != 0) || (memcmp(&buf[8], "WAVE", 4) != 0)) { |
195 | DEBUGF("CODEC_ERROR: missing riff header\n"); | 196 | DEBUGF("CODEC_ERROR: missing riff header\n"); |
196 | status = CODEC_ERROR; | 197 | return CODEC_ERROR; |
197 | goto done; | ||
198 | } | 198 | } |
199 | 199 | ||
200 | /* advance to first WAVE chunk */ | 200 | /* advance to first WAVE chunk */ |
@@ -215,8 +215,7 @@ next_track: | |||
215 | if (n < 8) { | 215 | if (n < 8) { |
216 | DEBUGF("data chunk request_buffer error\n"); | 216 | DEBUGF("data chunk request_buffer error\n"); |
217 | /* no more chunks, 'data' chunk must not have been found */ | 217 | /* no more chunks, 'data' chunk must not have been found */ |
218 | status = CODEC_ERROR; | 218 | return CODEC_ERROR; |
219 | goto done; | ||
220 | } | 219 | } |
221 | 220 | ||
222 | /* chunkSize */ | 221 | /* chunkSize */ |
@@ -225,8 +224,7 @@ next_track: | |||
225 | if (size < 16) { | 224 | if (size < 16) { |
226 | DEBUGF("CODEC_ERROR: 'fmt ' chunk size=%lu < 16\n", | 225 | DEBUGF("CODEC_ERROR: 'fmt ' chunk size=%lu < 16\n", |
227 | (unsigned long)size); | 226 | (unsigned long)size); |
228 | status = CODEC_ERROR; | 227 | return CODEC_ERROR; |
229 | goto done; | ||
230 | } | 228 | } |
231 | /* wFormatTag */ | 229 | /* wFormatTag */ |
232 | format.formattag=buf[8]|(buf[9]<<8); | 230 | format.formattag=buf[8]|(buf[9]<<8); |
@@ -256,8 +254,7 @@ next_track: | |||
256 | if (format.size < 22) { | 254 | if (format.size < 22) { |
257 | DEBUGF("CODEC_ERROR: WAVE_FORMAT_EXTENSIBLE is " | 255 | DEBUGF("CODEC_ERROR: WAVE_FORMAT_EXTENSIBLE is " |
258 | "missing extension\n"); | 256 | "missing extension\n"); |
259 | status = CODEC_ERROR; | 257 | return CODEC_ERROR; |
260 | goto done; | ||
261 | } | 258 | } |
262 | /* wValidBitsPerSample */ | 259 | /* wValidBitsPerSample */ |
263 | format.bitspersample = buf[26]|(buf[27]<<8); | 260 | format.bitspersample = buf[26]|(buf[27]<<8); |
@@ -273,8 +270,7 @@ next_track: | |||
273 | { | 270 | { |
274 | if (!set_msadpcm_coeffs(buf)) | 271 | if (!set_msadpcm_coeffs(buf)) |
275 | { | 272 | { |
276 | status = CODEC_ERROR; | 273 | return CODEC_ERROR; |
277 | goto done; | ||
278 | } | 274 | } |
279 | } | 275 | } |
280 | 276 | ||
@@ -284,8 +280,7 @@ next_track: | |||
284 | { | 280 | { |
285 | DEBUGF("CODEC_ERROR: unsupported wave format 0x%x\n", | 281 | DEBUGF("CODEC_ERROR: unsupported wave format 0x%x\n", |
286 | (unsigned int) format.formattag); | 282 | (unsigned int) format.formattag); |
287 | status = CODEC_ERROR; | 283 | return CODEC_ERROR; |
288 | goto done; | ||
289 | } | 284 | } |
290 | 285 | ||
291 | /* riff 8bit linear pcm is unsigned */ | 286 | /* riff 8bit linear pcm is unsigned */ |
@@ -295,8 +290,7 @@ next_track: | |||
295 | /* set format, parse codec specific tag, check format, and calculate chunk size */ | 290 | /* set format, parse codec specific tag, check format, and calculate chunk size */ |
296 | if (!codec->set_format(&format)) | 291 | if (!codec->set_format(&format)) |
297 | { | 292 | { |
298 | status = CODEC_ERROR; | 293 | return CODEC_ERROR; |
299 | goto done; | ||
300 | } | 294 | } |
301 | } else if (memcmp(buf, "data", 4) == 0) { | 295 | } else if (memcmp(buf, "data", 4) == 0) { |
302 | format.numbytes = size; | 296 | format.numbytes = size; |
@@ -324,31 +318,26 @@ next_track: | |||
324 | if (!codec) | 318 | if (!codec) |
325 | { | 319 | { |
326 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found\n"); | 320 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found\n"); |
327 | status = CODEC_ERROR; | 321 | return CODEC_ERROR; |
328 | goto done; | ||
329 | } | 322 | } |
330 | 323 | ||
331 | /* common format check */ | 324 | /* common format check */ |
332 | if (format.channels == 0) { | 325 | if (format.channels == 0) { |
333 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-channels file\n"); | 326 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-channels file\n"); |
334 | status = CODEC_ERROR; | 327 | return CODEC_ERROR; |
335 | goto done; | ||
336 | } | 328 | } |
337 | if (format.samplesperblock == 0) { | 329 | if (format.samplesperblock == 0) { |
338 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-wSamplesPerBlock file\n"); | 330 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-wSamplesPerBlock file\n"); |
339 | status = CODEC_ERROR; | 331 | return CODEC_ERROR; |
340 | goto done; | ||
341 | } | 332 | } |
342 | if (format.blockalign == 0) | 333 | if (format.blockalign == 0) |
343 | { | 334 | { |
344 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-blockalign file\n"); | 335 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-blockalign file\n"); |
345 | status = CODEC_ERROR; | 336 | return CODEC_ERROR; |
346 | goto done; | ||
347 | } | 337 | } |
348 | if (format.numbytes == 0) { | 338 | if (format.numbytes == 0) { |
349 | DEBUGF("CODEC_ERROR: 'data' chunk not found or has zero-length\n"); | 339 | DEBUGF("CODEC_ERROR: 'data' chunk not found or has zero-length\n"); |
350 | status = CODEC_ERROR; | 340 | return CODEC_ERROR; |
351 | goto done; | ||
352 | } | 341 | } |
353 | 342 | ||
354 | /* check chunksize */ | 343 | /* check chunksize */ |
@@ -358,8 +347,7 @@ next_track: | |||
358 | if (format.chunksize == 0) | 347 | if (format.chunksize == 0) |
359 | { | 348 | { |
360 | DEBUGF("CODEC_ERROR: chunksize is 0\n"); | 349 | DEBUGF("CODEC_ERROR: chunksize is 0\n"); |
361 | status = CODEC_ERROR; | 350 | return CODEC_ERROR; |
362 | goto done; | ||
363 | } | 351 | } |
364 | 352 | ||
365 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); | 353 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); |
@@ -369,8 +357,7 @@ next_track: | |||
369 | ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); | 357 | ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); |
370 | } else { | 358 | } else { |
371 | DEBUGF("CODEC_ERROR: more than 2 channels\n"); | 359 | DEBUGF("CODEC_ERROR: more than 2 channels\n"); |
372 | status = CODEC_ERROR; | 360 | return CODEC_ERROR; |
373 | goto done; | ||
374 | } | 361 | } |
375 | 362 | ||
376 | /* make sure we're at the correct offset */ | 363 | /* make sure we're at the correct offset */ |
@@ -380,13 +367,12 @@ next_track: | |||
380 | PCM_SEEK_POS, &read_buffer); | 367 | PCM_SEEK_POS, &read_buffer); |
381 | 368 | ||
382 | if (newpos->pos > format.numbytes) | 369 | if (newpos->pos > format.numbytes) |
383 | goto done; | 370 | return CODEC_OK; |
384 | if (ci->seek_buffer(firstblockposn + newpos->pos)) | 371 | if (ci->seek_buffer(firstblockposn + newpos->pos)) |
385 | { | 372 | { |
386 | bytesdone = newpos->pos; | 373 | bytesdone = newpos->pos; |
387 | decodedsamples = newpos->samples; | 374 | decodedsamples = newpos->samples; |
388 | } | 375 | } |
389 | ci->seek_complete(); | ||
390 | } else { | 376 | } else { |
391 | /* already where we need to be */ | 377 | /* already where we need to be */ |
392 | bytesdone = 0; | 378 | bytesdone = 0; |
@@ -396,22 +382,28 @@ next_track: | |||
396 | endofstream = 0; | 382 | endofstream = 0; |
397 | 383 | ||
398 | while (!endofstream) { | 384 | while (!endofstream) { |
399 | ci->yield(); | 385 | enum codec_command_action action = ci->get_command(¶m); |
400 | if (ci->stop_codec || ci->new_track) { | 386 | |
387 | if (action == CODEC_ACTION_HALT) | ||
401 | break; | 388 | break; |
402 | } | ||
403 | 389 | ||
404 | if (ci->seek_time) { | 390 | if (action == CODEC_ACTION_SEEK_TIME) { |
405 | struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, PCM_SEEK_TIME, | 391 | struct pcm_pos *newpos = codec->get_seek_pos(param, PCM_SEEK_TIME, |
406 | &read_buffer); | 392 | &read_buffer); |
407 | |||
408 | if (newpos->pos > format.numbytes) | 393 | if (newpos->pos > format.numbytes) |
394 | { | ||
395 | ci->set_elapsed(ci->id3->length); | ||
396 | ci->seek_complete(); | ||
409 | break; | 397 | break; |
398 | } | ||
399 | |||
410 | if (ci->seek_buffer(firstblockposn + newpos->pos)) | 400 | if (ci->seek_buffer(firstblockposn + newpos->pos)) |
411 | { | 401 | { |
412 | bytesdone = newpos->pos; | 402 | bytesdone = newpos->pos; |
413 | decodedsamples = newpos->samples; | 403 | decodedsamples = newpos->samples; |
414 | } | 404 | } |
405 | |||
406 | ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); | ||
415 | ci->seek_complete(); | 407 | ci->seek_complete(); |
416 | } | 408 | } |
417 | 409 | ||
@@ -423,11 +415,10 @@ next_track: | |||
423 | endofstream = 1; | 415 | endofstream = 1; |
424 | } | 416 | } |
425 | 417 | ||
426 | status = codec->decode(wavbuf, n, samples, &bufcount); | 418 | if (codec->decode(wavbuf, n, samples, &bufcount) == CODEC_ERROR) |
427 | if (status == CODEC_ERROR) | ||
428 | { | 419 | { |
429 | DEBUGF("codec error\n"); | 420 | DEBUGF("codec error\n"); |
430 | goto done; | 421 | return CODEC_ERROR; |
431 | } | 422 | } |
432 | 423 | ||
433 | ci->pcmbuf_insert(samples, NULL, bufcount); | 424 | ci->pcmbuf_insert(samples, NULL, bufcount); |
@@ -440,10 +431,5 @@ next_track: | |||
440 | ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); | 431 | ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); |
441 | } | 432 | } |
442 | 433 | ||
443 | done: | 434 | return CODEC_OK; |
444 | if (ci->request_next_track()) | ||
445 | goto next_track; | ||
446 | |||
447 | exit: | ||
448 | return status; | ||
449 | } | 435 | } |
diff --git a/apps/codecs/wav64.c b/apps/codecs/wav64.c index 9dbdab8368..c763e6f7f0 100644 --- a/apps/codecs/wav64.c +++ b/apps/codecs/wav64.c | |||
@@ -159,9 +159,19 @@ static uint8_t *read_buffer(size_t *realsize) | |||
159 | } | 159 | } |
160 | 160 | ||
161 | /* this is the codec entry point */ | 161 | /* this is the codec entry point */ |
162 | enum codec_status codec_main(void) | 162 | enum codec_status codec_main(enum codec_entry_call_reason reason) |
163 | { | ||
164 | if (reason == CODEC_LOAD) { | ||
165 | /* Generic codec initialisation */ | ||
166 | ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1); | ||
167 | } | ||
168 | |||
169 | return CODEC_OK; | ||
170 | } | ||
171 | |||
172 | /* this is called for each file to process */ | ||
173 | enum codec_status codec_run(void) | ||
163 | { | 174 | { |
164 | int status; | ||
165 | uint32_t decodedsamples; | 175 | uint32_t decodedsamples; |
166 | size_t n; | 176 | size_t n; |
167 | int bufcount; | 177 | int bufcount; |
@@ -171,39 +181,29 @@ enum codec_status codec_main(void) | |||
171 | off_t firstblockposn; /* position of the first block in file */ | 181 | off_t firstblockposn; /* position of the first block in file */ |
172 | const struct pcm_codec *codec; | 182 | const struct pcm_codec *codec; |
173 | uint64_t size; | 183 | uint64_t size; |
174 | 184 | intptr_t param; | |
175 | /* Generic codec initialisation */ | ||
176 | ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1); | ||
177 | |||
178 | next_track: | ||
179 | status = CODEC_OK; | ||
180 | 185 | ||
181 | if (codec_init()) { | 186 | if (codec_init()) { |
182 | DEBUGF("codec_init() error\n"); | 187 | DEBUGF("codec_init() error\n"); |
183 | status = CODEC_ERROR; | 188 | return CODEC_ERROR; |
184 | goto exit; | ||
185 | } | 189 | } |
186 | 190 | ||
187 | if (codec_wait_taginfo() != 0) | ||
188 | goto done; | ||
189 | |||
190 | codec_set_replaygain(ci->id3); | 191 | codec_set_replaygain(ci->id3); |
191 | 192 | ||
192 | /* Need to save offset for later use (cleared indirectly by advance_buffer) */ | 193 | /* Need to save offset for later use (cleared indirectly by advance_buffer) */ |
193 | bytesdone = ci->id3->offset; | 194 | bytesdone = ci->id3->offset; |
194 | 195 | ||
195 | /* get RIFF chunk header */ | 196 | /* get RIFF chunk header */ |
197 | ci->seek_buffer(0); | ||
196 | buf = ci->request_buffer(&n, 40); | 198 | buf = ci->request_buffer(&n, 40); |
197 | if (n < 40) { | 199 | if (n < 40) { |
198 | DEBUGF("request_buffer error\n"); | 200 | DEBUGF("request_buffer error\n"); |
199 | status = CODEC_ERROR; | 201 | return CODEC_ERROR; |
200 | goto done; | ||
201 | } | 202 | } |
202 | if ((memcmp(buf , WAVE64_GUID_RIFF, 16) != 0) || | 203 | if ((memcmp(buf , WAVE64_GUID_RIFF, 16) != 0) || |
203 | (memcmp(buf+24, WAVE64_GUID_WAVE, 16) != 0)) | 204 | (memcmp(buf+24, WAVE64_GUID_WAVE, 16) != 0)) |
204 | { | 205 | { |
205 | status = CODEC_ERROR; | 206 | return CODEC_ERROR; |
206 | goto done; | ||
207 | } | 207 | } |
208 | 208 | ||
209 | /* advance to first WAVE chunk */ | 209 | /* advance to first WAVE chunk */ |
@@ -224,8 +224,7 @@ next_track: | |||
224 | if (n < 8) { | 224 | if (n < 8) { |
225 | DEBUGF("data chunk request_buffer error\n"); | 225 | DEBUGF("data chunk request_buffer error\n"); |
226 | /* no more chunks, 'data' chunk must not have been found */ | 226 | /* no more chunks, 'data' chunk must not have been found */ |
227 | status = CODEC_ERROR; | 227 | return CODEC_ERROR; |
228 | goto done; | ||
229 | } | 228 | } |
230 | 229 | ||
231 | /* chunkSize */ | 230 | /* chunkSize */ |
@@ -233,8 +232,7 @@ next_track: | |||
233 | if (memcmp(buf, WAVE64_GUID_FMT, 16) == 0) { | 232 | if (memcmp(buf, WAVE64_GUID_FMT, 16) == 0) { |
234 | if (size < 16) { | 233 | if (size < 16) { |
235 | DEBUGF("CODEC_ERROR: 'fmt ' chunk size=%d < 16\n", (int)size); | 234 | DEBUGF("CODEC_ERROR: 'fmt ' chunk size=%d < 16\n", (int)size); |
236 | status = CODEC_ERROR; | 235 | return CODEC_ERROR; |
237 | goto done; | ||
238 | } | 236 | } |
239 | /* wFormatTag */ | 237 | /* wFormatTag */ |
240 | format.formattag=buf[24]|(buf[25]<<8); | 238 | format.formattag=buf[24]|(buf[25]<<8); |
@@ -263,8 +261,7 @@ next_track: | |||
263 | if (format.size < 22) { | 261 | if (format.size < 22) { |
264 | DEBUGF("CODEC_ERROR: WAVE_FORMAT_EXTENSIBLE is " | 262 | DEBUGF("CODEC_ERROR: WAVE_FORMAT_EXTENSIBLE is " |
265 | "missing extension\n"); | 263 | "missing extension\n"); |
266 | status = CODEC_ERROR; | 264 | return CODEC_ERROR; |
267 | goto done; | ||
268 | } | 265 | } |
269 | /* wValidBitsPerSample */ | 266 | /* wValidBitsPerSample */ |
270 | format.bitspersample = buf[42]|(buf[43]<<8); | 267 | format.bitspersample = buf[42]|(buf[43]<<8); |
@@ -279,10 +276,7 @@ next_track: | |||
279 | if (format.formattag == WAVE_FORMAT_ADPCM) | 276 | if (format.formattag == WAVE_FORMAT_ADPCM) |
280 | { | 277 | { |
281 | if (!set_msadpcm_coeffs(buf)) | 278 | if (!set_msadpcm_coeffs(buf)) |
282 | { | 279 | return CODEC_ERROR; |
283 | status = CODEC_ERROR; | ||
284 | goto done; | ||
285 | } | ||
286 | } | 280 | } |
287 | 281 | ||
288 | /* get codec */ | 282 | /* get codec */ |
@@ -291,8 +285,7 @@ next_track: | |||
291 | { | 285 | { |
292 | DEBUGF("CODEC_ERROR: unsupported wave format 0x%x\n", | 286 | DEBUGF("CODEC_ERROR: unsupported wave format 0x%x\n", |
293 | (unsigned int) format.formattag); | 287 | (unsigned int) format.formattag); |
294 | status = CODEC_ERROR; | 288 | return CODEC_ERROR; |
295 | goto done; | ||
296 | } | 289 | } |
297 | 290 | ||
298 | /* riff 8bit linear pcm is unsigned */ | 291 | /* riff 8bit linear pcm is unsigned */ |
@@ -301,10 +294,7 @@ next_track: | |||
301 | 294 | ||
302 | /* check format, and calculate chunk size */ | 295 | /* check format, and calculate chunk size */ |
303 | if (!codec->set_format(&format)) | 296 | if (!codec->set_format(&format)) |
304 | { | 297 | return CODEC_ERROR; |
305 | status = CODEC_ERROR; | ||
306 | goto done; | ||
307 | } | ||
308 | } else if (memcmp(buf, WAVE64_GUID_DATA, 16) == 0) { | 298 | } else if (memcmp(buf, WAVE64_GUID_DATA, 16) == 0) { |
309 | format.numbytes = size; | 299 | format.numbytes = size; |
310 | /* advance to start of data */ | 300 | /* advance to start of data */ |
@@ -330,31 +320,26 @@ next_track: | |||
330 | if (!codec) | 320 | if (!codec) |
331 | { | 321 | { |
332 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found\n"); | 322 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found\n"); |
333 | status = CODEC_ERROR; | 323 | return CODEC_ERROR; |
334 | goto done; | ||
335 | } | 324 | } |
336 | 325 | ||
337 | /* common format check */ | 326 | /* common format check */ |
338 | if (format.channels == 0) { | 327 | if (format.channels == 0) { |
339 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-channels file\n"); | 328 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-channels file\n"); |
340 | status = CODEC_ERROR; | 329 | return CODEC_ERROR; |
341 | goto done; | ||
342 | } | 330 | } |
343 | if (format.samplesperblock == 0) { | 331 | if (format.samplesperblock == 0) { |
344 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-wSamplesPerBlock file\n"); | 332 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-wSamplesPerBlock file\n"); |
345 | status = CODEC_ERROR; | 333 | return CODEC_ERROR; |
346 | goto done; | ||
347 | } | 334 | } |
348 | if (format.blockalign == 0) | 335 | if (format.blockalign == 0) |
349 | { | 336 | { |
350 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-blockalign file\n"); | 337 | DEBUGF("CODEC_ERROR: 'fmt ' chunk not found or 0-blockalign file\n"); |
351 | status = CODEC_ERROR; | 338 | return CODEC_ERROR; |
352 | goto done; | ||
353 | } | 339 | } |
354 | if (format.numbytes == 0) { | 340 | if (format.numbytes == 0) { |
355 | DEBUGF("CODEC_ERROR: 'data' chunk not found or has zero-length\n"); | 341 | DEBUGF("CODEC_ERROR: 'data' chunk not found or has zero-length\n"); |
356 | status = CODEC_ERROR; | 342 | return CODEC_ERROR; |
357 | goto done; | ||
358 | } | 343 | } |
359 | 344 | ||
360 | /* check chunksize */ | 345 | /* check chunksize */ |
@@ -364,8 +349,7 @@ next_track: | |||
364 | if (format.chunksize == 0) | 349 | if (format.chunksize == 0) |
365 | { | 350 | { |
366 | DEBUGF("CODEC_ERROR: chunksize is 0\n"); | 351 | DEBUGF("CODEC_ERROR: chunksize is 0\n"); |
367 | status = CODEC_ERROR; | 352 | return CODEC_ERROR; |
368 | goto done; | ||
369 | } | 353 | } |
370 | 354 | ||
371 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); | 355 | ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency); |
@@ -375,8 +359,7 @@ next_track: | |||
375 | ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); | 359 | ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO); |
376 | } else { | 360 | } else { |
377 | DEBUGF("CODEC_ERROR: more than 2 channels\n"); | 361 | DEBUGF("CODEC_ERROR: more than 2 channels\n"); |
378 | status = CODEC_ERROR; | 362 | return CODEC_ERROR; |
379 | goto done; | ||
380 | } | 363 | } |
381 | 364 | ||
382 | /* make sure we're at the correct offset */ | 365 | /* make sure we're at the correct offset */ |
@@ -385,14 +368,14 @@ next_track: | |||
385 | struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn, | 368 | struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn, |
386 | PCM_SEEK_POS, &read_buffer); | 369 | PCM_SEEK_POS, &read_buffer); |
387 | 370 | ||
388 | if (newpos->pos > format.numbytes) | 371 | if (newpos->pos > format.numbytes) { |
389 | goto done; | 372 | return CODEC_OK; |
373 | } | ||
390 | if (ci->seek_buffer(firstblockposn + newpos->pos)) | 374 | if (ci->seek_buffer(firstblockposn + newpos->pos)) |
391 | { | 375 | { |
392 | bytesdone = newpos->pos; | 376 | bytesdone = newpos->pos; |
393 | decodedsamples = newpos->samples; | 377 | decodedsamples = newpos->samples; |
394 | } | 378 | } |
395 | ci->seek_complete(); | ||
396 | } else { | 379 | } else { |
397 | /* already where we need to be */ | 380 | /* already where we need to be */ |
398 | bytesdone = 0; | 381 | bytesdone = 0; |
@@ -402,22 +385,29 @@ next_track: | |||
402 | endofstream = 0; | 385 | endofstream = 0; |
403 | 386 | ||
404 | while (!endofstream) { | 387 | while (!endofstream) { |
405 | ci->yield(); | 388 | enum codec_command_action action = ci->get_command(¶m); |
406 | if (ci->stop_codec || ci->new_track) { | 389 | |
390 | if (action == CODEC_ACTION_HALT) | ||
407 | break; | 391 | break; |
408 | } | ||
409 | 392 | ||
410 | if (ci->seek_time) { | 393 | if (action == CODEC_ACTION_SEEK_TIME) { |
411 | struct pcm_pos *newpos = codec->get_seek_pos(ci->seek_time, PCM_SEEK_TIME, | 394 | struct pcm_pos *newpos = codec->get_seek_pos(param, PCM_SEEK_TIME, |
412 | &read_buffer); | 395 | &read_buffer); |
413 | 396 | ||
414 | if (newpos->pos > format.numbytes) | 397 | if (newpos->pos > format.numbytes) |
398 | { | ||
399 | ci->set_elapsed(ci->id3->length); | ||
400 | ci->seek_complete(); | ||
415 | break; | 401 | break; |
402 | } | ||
403 | |||
416 | if (ci->seek_buffer(firstblockposn + newpos->pos)) | 404 | if (ci->seek_buffer(firstblockposn + newpos->pos)) |
417 | { | 405 | { |
418 | bytesdone = newpos->pos; | 406 | bytesdone = newpos->pos; |
419 | decodedsamples = newpos->samples; | 407 | decodedsamples = newpos->samples; |
420 | } | 408 | } |
409 | |||
410 | ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); | ||
421 | ci->seek_complete(); | 411 | ci->seek_complete(); |
422 | } | 412 | } |
423 | 413 | ||
@@ -429,11 +419,10 @@ next_track: | |||
429 | endofstream = 1; | 419 | endofstream = 1; |
430 | } | 420 | } |
431 | 421 | ||
432 | status = codec->decode(wavbuf, n, samples, &bufcount); | 422 | if (codec->decode(wavbuf, n, samples, &bufcount) == CODEC_ERROR) |
433 | if (status == CODEC_ERROR) | ||
434 | { | 423 | { |
435 | DEBUGF("codec error\n"); | 424 | DEBUGF("codec error\n"); |
436 | goto done; | 425 | return CODEC_ERROR; |
437 | } | 426 | } |
438 | 427 | ||
439 | ci->pcmbuf_insert(samples, NULL, bufcount); | 428 | ci->pcmbuf_insert(samples, NULL, bufcount); |
@@ -445,12 +434,6 @@ next_track: | |||
445 | endofstream = 1; | 434 | endofstream = 1; |
446 | ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); | 435 | ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency); |
447 | } | 436 | } |
448 | status = CODEC_OK; | ||
449 | |||
450 | done: | ||
451 | if (ci->request_next_track()) | ||
452 | goto next_track; | ||
453 | 437 | ||
454 | exit: | 438 | return CODEC_OK; |
455 | return status; | ||
456 | } | 439 | } |
diff --git a/apps/codecs/wav_enc.c b/apps/codecs/wav_enc.c index ef1a88ec23..e4afeaf93c 100644 --- a/apps/codecs/wav_enc.c +++ b/apps/codecs/wav_enc.c | |||
@@ -345,40 +345,42 @@ static bool init_encoder(void) | |||
345 | return true; | 345 | return true; |
346 | } /* init_encoder */ | 346 | } /* init_encoder */ |
347 | 347 | ||
348 | /* main codec entry point */ | 348 | /* this is the codec entry point */ |
349 | enum codec_status codec_main(void) | 349 | enum codec_status codec_main(enum codec_entry_call_reason reason) |
350 | { | 350 | { |
351 | if (!init_encoder()) | 351 | if (reason == CODEC_LOAD) { |
352 | return CODEC_ERROR; | 352 | if (!init_encoder()) |
353 | return CODEC_ERROR; | ||
354 | } | ||
355 | else if (reason == CODEC_UNLOAD) { | ||
356 | /* reset parameters to initial state */ | ||
357 | ci->enc_set_parameters(NULL); | ||
358 | } | ||
353 | 359 | ||
360 | return CODEC_OK; | ||
361 | } | ||
362 | |||
363 | /* this is called for each file to process */ | ||
364 | enum codec_status codec_run(void) | ||
365 | { | ||
354 | /* main encoding loop */ | 366 | /* main encoding loop */ |
355 | while(!ci->stop_codec) | 367 | while(ci->get_command(NULL) != CODEC_ACTION_HALT) |
356 | { | 368 | { |
357 | uint32_t *src; | 369 | uint32_t *src = (uint32_t *)ci->enc_get_pcm_data(PCM_CHUNK_SIZE); |
370 | struct enc_chunk_hdr *chunk; | ||
358 | 371 | ||
359 | while ((src = (uint32_t *)ci->enc_get_pcm_data(PCM_CHUNK_SIZE)) != NULL) | 372 | if(src == NULL) |
360 | { | 373 | continue; |
361 | struct enc_chunk_hdr *chunk; | ||
362 | |||
363 | if (ci->stop_codec) | ||
364 | break; | ||
365 | 374 | ||
366 | chunk = ci->enc_get_chunk(); | 375 | chunk = ci->enc_get_chunk(); |
367 | chunk->enc_size = enc_size; | 376 | chunk->enc_size = enc_size; |
368 | chunk->num_pcm = PCM_SAMP_PER_CHUNK; | 377 | chunk->num_pcm = PCM_SAMP_PER_CHUNK; |
369 | chunk->enc_data = ENC_CHUNK_SKIP_HDR(chunk->enc_data, chunk); | 378 | chunk->enc_data = ENC_CHUNK_SKIP_HDR(chunk->enc_data, chunk); |
370 | 379 | ||
371 | chunk_to_wav_format(src, (uint32_t *)chunk->enc_data); | 380 | chunk_to_wav_format(src, (uint32_t *)chunk->enc_data); |
372 | 381 | ||
373 | ci->enc_finish_chunk(); | 382 | ci->enc_finish_chunk(); |
374 | ci->yield(); | ||
375 | } | ||
376 | |||
377 | ci->yield(); | ||
378 | } | 383 | } |
379 | 384 | ||
380 | /* reset parameters to initial state */ | ||
381 | ci->enc_set_parameters(NULL); | ||
382 | |||
383 | return CODEC_OK; | 385 | return CODEC_OK; |
384 | } /* codec_start */ | 386 | } |
diff --git a/apps/codecs/wavpack.c b/apps/codecs/wavpack.c index d27a9fb621..ccb9f41190 100644 --- a/apps/codecs/wavpack.c +++ b/apps/codecs/wavpack.c | |||
@@ -31,39 +31,39 @@ static int32_t temp_buffer [BUFFER_SIZE] IBSS_ATTR; | |||
31 | static int32_t read_callback (void *buffer, int32_t bytes) | 31 | static int32_t read_callback (void *buffer, int32_t bytes) |
32 | { | 32 | { |
33 | int32_t retval = ci->read_filebuf (buffer, bytes); | 33 | int32_t retval = ci->read_filebuf (buffer, bytes); |
34 | ci->id3->offset = ci->curpos; | 34 | ci->set_offset(ci->curpos); |
35 | return retval; | 35 | return retval; |
36 | } | 36 | } |
37 | 37 | ||
38 | /* this is the codec entry point */ | 38 | /* this is the codec entry point */ |
39 | enum codec_status codec_main(void) | 39 | enum codec_status codec_main(enum codec_entry_call_reason reason) |
40 | { | ||
41 | if (reason == CODEC_LOAD) { | ||
42 | /* Generic codec initialisation */ | ||
43 | ci->configure(DSP_SET_SAMPLE_DEPTH, 28); | ||
44 | } | ||
45 | |||
46 | return CODEC_OK; | ||
47 | } | ||
48 | |||
49 | /* this is called for each file to process */ | ||
50 | enum codec_status codec_run(void) | ||
40 | { | 51 | { |
41 | WavpackContext *wpc; | 52 | WavpackContext *wpc; |
42 | char error [80]; | 53 | char error [80]; |
43 | int bps, nchans, sr_100; | 54 | int bps, nchans, sr_100; |
44 | int retval; | 55 | intptr_t param; |
45 | 56 | ||
46 | /* Generic codec initialisation */ | 57 | if (codec_init()) |
47 | ci->configure(DSP_SET_SAMPLE_DEPTH, 28); | 58 | return CODEC_ERROR; |
48 | 59 | ||
49 | next_track: | 60 | ci->seek_buffer (ci->id3->offset); |
50 | retval = CODEC_OK; | ||
51 | 61 | ||
52 | if (codec_init()) { | ||
53 | retval = CODEC_ERROR; | ||
54 | goto exit; | ||
55 | } | ||
56 | |||
57 | if (codec_wait_taginfo() != 0) | ||
58 | goto done; | ||
59 | |||
60 | /* Create a decoder instance */ | 62 | /* Create a decoder instance */ |
61 | wpc = WavpackOpenFileInput (read_callback, error); | 63 | wpc = WavpackOpenFileInput (read_callback, error); |
62 | 64 | ||
63 | if (!wpc) { | 65 | if (!wpc) |
64 | retval = CODEC_ERROR; | 66 | return CODEC_ERROR; |
65 | goto done; | ||
66 | } | ||
67 | 67 | ||
68 | ci->configure(DSP_SWITCH_FREQUENCY, WavpackGetSampleRate (wpc)); | 68 | ci->configure(DSP_SWITCH_FREQUENCY, WavpackGetSampleRate (wpc)); |
69 | codec_set_replaygain(ci->id3); | 69 | codec_set_replaygain(ci->id3); |
@@ -77,56 +77,48 @@ next_track: | |||
77 | /* The main decoder loop */ | 77 | /* The main decoder loop */ |
78 | 78 | ||
79 | while (1) { | 79 | while (1) { |
80 | int32_t nsamples; | 80 | int32_t nsamples; |
81 | enum codec_command_action action = ci->get_command(¶m); | ||
82 | |||
83 | if (action == CODEC_ACTION_HALT) | ||
84 | break; | ||
81 | 85 | ||
82 | if (ci->seek_time && ci->taginfo_ready && ci->id3->length) { | 86 | if (action == CODEC_ACTION_SEEK_TIME) { |
83 | ci->seek_time--; | ||
84 | int curpos_ms = WavpackGetSampleIndex (wpc) / sr_100 * 10; | 87 | int curpos_ms = WavpackGetSampleIndex (wpc) / sr_100 * 10; |
85 | int n, d, skip; | 88 | int n, d, skip; |
86 | 89 | ||
87 | if (ci->seek_time > curpos_ms) { | 90 | if (param > curpos_ms) { |
88 | n = ci->seek_time - curpos_ms; | 91 | n = param - curpos_ms; |
89 | d = ci->id3->length - curpos_ms; | 92 | d = ci->id3->length - curpos_ms; |
90 | skip = (int)((int64_t)(ci->filesize - ci->curpos) * n / d); | 93 | skip = (int)((int64_t)(ci->filesize - ci->curpos) * n / d); |
91 | ci->seek_buffer (ci->curpos + skip); | 94 | ci->seek_buffer (ci->curpos + skip); |
92 | } | 95 | } |
93 | else { | 96 | else if (curpos_ms != 0) { |
94 | n = curpos_ms - ci->seek_time; | 97 | n = curpos_ms - param; |
95 | d = curpos_ms; | 98 | d = curpos_ms; |
96 | skip = (int)((int64_t) ci->curpos * n / d); | 99 | skip = (int)((int64_t) ci->curpos * n / d); |
97 | ci->seek_buffer (ci->curpos - skip); | 100 | ci->seek_buffer (ci->curpos - skip); |
98 | } | 101 | } |
99 | 102 | ||
100 | wpc = WavpackOpenFileInput (read_callback, error); | 103 | wpc = WavpackOpenFileInput (read_callback, error); |
101 | ci->seek_complete(); | ||
102 | |||
103 | if (!wpc) | 104 | if (!wpc) |
105 | { | ||
106 | ci->seek_complete(); | ||
104 | break; | 107 | break; |
108 | } | ||
105 | 109 | ||
106 | ci->set_elapsed (WavpackGetSampleIndex (wpc) / sr_100 * 10); | 110 | ci->set_elapsed (WavpackGetSampleIndex (wpc) / sr_100 * 10); |
107 | ci->yield (); | 111 | ci->seek_complete(); |
108 | } | 112 | } |
109 | 113 | ||
110 | nsamples = WavpackUnpackSamples (wpc, temp_buffer, BUFFER_SIZE / nchans); | 114 | nsamples = WavpackUnpackSamples (wpc, temp_buffer, BUFFER_SIZE / nchans); |
111 | 115 | ||
112 | if (!nsamples || ci->stop_codec || ci->new_track) | 116 | if (!nsamples) |
113 | break; | ||
114 | |||
115 | ci->yield (); | ||
116 | |||
117 | if (ci->stop_codec || ci->new_track) | ||
118 | break; | 117 | break; |
119 | 118 | ||
120 | ci->pcmbuf_insert (temp_buffer, NULL, nsamples); | 119 | ci->pcmbuf_insert (temp_buffer, NULL, nsamples); |
121 | |||
122 | ci->set_elapsed (WavpackGetSampleIndex (wpc) / sr_100 * 10); | 120 | ci->set_elapsed (WavpackGetSampleIndex (wpc) / sr_100 * 10); |
123 | ci->yield (); | ||
124 | } | 121 | } |
125 | 122 | ||
126 | done: | 123 | return CODEC_OK; |
127 | if (ci->request_next_track()) | ||
128 | goto next_track; | ||
129 | |||
130 | exit: | ||
131 | return retval; | ||
132 | } | 124 | } |
diff --git a/apps/codecs/wavpack_enc.c b/apps/codecs/wavpack_enc.c index d908e284be..730cf0734b 100644 --- a/apps/codecs/wavpack_enc.c +++ b/apps/codecs/wavpack_enc.c | |||
@@ -389,77 +389,79 @@ static bool init_encoder(void) | |||
389 | return true; | 389 | return true; |
390 | } /* init_encoder */ | 390 | } /* init_encoder */ |
391 | 391 | ||
392 | enum codec_status codec_main(void) | 392 | /* this is the codec entry point */ |
393 | enum codec_status codec_main(enum codec_entry_call_reason reason) | ||
393 | { | 394 | { |
394 | /* initialize params and config */ | 395 | if (reason == CODEC_LOAD) { |
395 | if (!init_encoder()) | 396 | /* initialize params and config */ |
396 | return CODEC_ERROR; | 397 | if (!init_encoder()) |
398 | return CODEC_ERROR; | ||
399 | } | ||
400 | else if (reason == CODEC_UNLOAD) { | ||
401 | /* reset parameters to initial state */ | ||
402 | ci->enc_set_parameters(NULL); | ||
403 | } | ||
397 | 404 | ||
405 | return CODEC_OK; | ||
406 | } | ||
407 | |||
408 | /* this is called for each file to process */ | ||
409 | enum codec_status codec_run(void) | ||
410 | { | ||
398 | /* main encoding loop */ | 411 | /* main encoding loop */ |
399 | while(!ci->stop_codec) | 412 | while(ci->get_command(NULL) != CODEC_ACTION_HALT) |
400 | { | 413 | { |
401 | uint8_t *src; | 414 | uint8_t *src = (uint8_t *)ci->enc_get_pcm_data(PCM_CHUNK_SIZE); |
415 | struct enc_chunk_hdr *chunk; | ||
416 | bool abort_chunk; | ||
417 | uint8_t *dst; | ||
418 | uint8_t *src_end; | ||
402 | 419 | ||
403 | while ((src = ci->enc_get_pcm_data(PCM_CHUNK_SIZE)) != NULL) | 420 | if(src == NULL) |
404 | { | 421 | continue; |
405 | struct enc_chunk_hdr *chunk; | ||
406 | bool abort_chunk; | ||
407 | uint8_t *dst; | ||
408 | uint8_t *src_end; | ||
409 | |||
410 | if(ci->stop_codec) | ||
411 | break; | ||
412 | |||
413 | abort_chunk = true; | ||
414 | 422 | ||
415 | chunk = ci->enc_get_chunk(); | 423 | chunk = ci->enc_get_chunk(); |
416 | 424 | ||
417 | /* reset counts and pointer */ | 425 | /* reset counts and pointer */ |
418 | chunk->enc_size = 0; | 426 | chunk->enc_size = 0; |
419 | chunk->num_pcm = 0; | 427 | chunk->num_pcm = 0; |
420 | chunk->enc_data = NULL; | 428 | chunk->enc_data = NULL; |
421 | 429 | ||
422 | dst = ENC_CHUNK_SKIP_HDR(dst, chunk); | 430 | dst = ENC_CHUNK_SKIP_HDR(dst, chunk); |
423 | 431 | ||
424 | WavpackStartBlock(wpc, dst, dst + data_size); | 432 | WavpackStartBlock(wpc, dst, dst + data_size); |
425 | 433 | ||
426 | chunk_to_int32((uint32_t*)src); | 434 | chunk_to_int32((uint32_t*)src); |
427 | src = input_buffer; | 435 | src = input_buffer; |
428 | src_end = src + input_size; | 436 | src_end = src + input_size; |
429 | 437 | ||
430 | /* encode chunk in four steps yielding between each */ | 438 | /* encode chunk in four steps yielding between each */ |
431 | do | 439 | do |
440 | { | ||
441 | abort_chunk = true; | ||
442 | if (WavpackPackSamples(wpc, (int32_t *)src, | ||
443 | PCM_SAMP_PER_CHUNK/4)) | ||
432 | { | 444 | { |
433 | if (WavpackPackSamples(wpc, (int32_t *)src, | 445 | chunk->num_pcm += PCM_SAMP_PER_CHUNK/4; |
434 | PCM_SAMP_PER_CHUNK/4)) | 446 | ci->yield(); |
435 | { | 447 | /* could've been stopped in some way */ |
436 | chunk->num_pcm += PCM_SAMP_PER_CHUNK/4; | 448 | abort_chunk = chunk->flags & CHUNKF_ABORT; |
437 | ci->yield(); | ||
438 | /* could've been stopped in some way */ | ||
439 | abort_chunk = ci->stop_codec || | ||
440 | (chunk->flags & CHUNKF_ABORT); | ||
441 | } | ||
442 | |||
443 | src += input_step; | ||
444 | } | 449 | } |
445 | while (!abort_chunk && src < src_end); | ||
446 | 450 | ||
447 | if (!abort_chunk) | 451 | src += input_step; |
448 | { | ||
449 | chunk->enc_data = dst; | ||
450 | if (chunk->num_pcm < PCM_SAMP_PER_CHUNK) | ||
451 | ci->enc_unget_pcm_data(PCM_CHUNK_SIZE - chunk->num_pcm*4); | ||
452 | /* finish the chunk and store chunk size info */ | ||
453 | chunk->enc_size = WavpackFinishBlock(wpc); | ||
454 | ci->enc_finish_chunk(); | ||
455 | } | ||
456 | } | 452 | } |
453 | while (!abort_chunk && src < src_end); | ||
457 | 454 | ||
458 | ci->yield(); | 455 | if (!abort_chunk) |
456 | { | ||
457 | chunk->enc_data = dst; | ||
458 | if (chunk->num_pcm < PCM_SAMP_PER_CHUNK) | ||
459 | ci->enc_unget_pcm_data(PCM_CHUNK_SIZE - chunk->num_pcm*4); | ||
460 | /* finish the chunk and store chunk size info */ | ||
461 | chunk->enc_size = WavpackFinishBlock(wpc); | ||
462 | ci->enc_finish_chunk(); | ||
463 | } | ||
459 | } | 464 | } |
460 | 465 | ||
461 | /* reset parameters to initial state */ | ||
462 | ci->enc_set_parameters(NULL); | ||
463 | |||
464 | return CODEC_OK; | 466 | return CODEC_OK; |
465 | } /* codec_start */ | 467 | } |
diff --git a/apps/codecs/wma.c b/apps/codecs/wma.c index 1b46813444..c327fafb5a 100644 --- a/apps/codecs/wma.c +++ b/apps/codecs/wma.c | |||
@@ -29,53 +29,52 @@ CODEC_HEADER | |||
29 | static WMADecodeContext wmadec; | 29 | static WMADecodeContext wmadec; |
30 | 30 | ||
31 | /* this is the codec entry point */ | 31 | /* this is the codec entry point */ |
32 | enum codec_status codec_main(void) | 32 | enum codec_status codec_main(enum codec_entry_call_reason reason) |
33 | { | ||
34 | if (reason == CODEC_LOAD) { | ||
35 | /* Generic codec initialisation */ | ||
36 | ci->configure(DSP_SET_SAMPLE_DEPTH, 29); | ||
37 | } | ||
38 | |||
39 | return CODEC_OK; | ||
40 | } | ||
41 | |||
42 | /* this is called for each file to process */ | ||
43 | enum codec_status codec_run(void) | ||
33 | { | 44 | { |
34 | uint32_t elapsedtime; | 45 | uint32_t elapsedtime; |
35 | int retval; | ||
36 | asf_waveformatex_t wfx; | 46 | asf_waveformatex_t wfx; |
37 | size_t resume_offset; | 47 | size_t resume_offset; |
38 | int i; | 48 | int i; |
39 | int wmares, res; | 49 | int wmares; |
50 | int res = 0; | ||
40 | uint8_t* audiobuf; | 51 | uint8_t* audiobuf; |
41 | int audiobufsize; | 52 | int audiobufsize; |
42 | int packetlength = 0; | 53 | int packetlength = 0; |
43 | int errcount = 0; | 54 | int errcount = 0; |
44 | 55 | intptr_t param; | |
45 | /* Generic codec initialisation */ | ||
46 | ci->configure(DSP_SET_SAMPLE_DEPTH, 29); | ||
47 | |||
48 | next_track: | ||
49 | retval = CODEC_OK; | ||
50 | 56 | ||
51 | /* Proper reset of the decoder context. */ | 57 | /* Proper reset of the decoder context. */ |
52 | memset(&wmadec, 0, sizeof(wmadec)); | 58 | memset(&wmadec, 0, sizeof(wmadec)); |
53 | 59 | ||
54 | /* Wait for the metadata to be read */ | ||
55 | if (codec_wait_taginfo() != 0) | ||
56 | goto done; | ||
57 | |||
58 | /* Remember the resume position - when the codec is opened, the | 60 | /* Remember the resume position - when the codec is opened, the |
59 | playback engine will reset it. */ | 61 | playback engine will reset it. */ |
60 | resume_offset = ci->id3->offset; | 62 | resume_offset = ci->id3->offset; |
61 | 63 | ||
62 | restart_track: | 64 | restart_track: |
63 | retval = CODEC_OK; | ||
64 | |||
65 | if (codec_init()) { | 65 | if (codec_init()) { |
66 | LOGF("WMA: Error initialising codec\n"); | 66 | LOGF("WMA: Error initialising codec\n"); |
67 | retval = CODEC_ERROR; | 67 | return CODEC_ERROR; |
68 | goto exit; | ||
69 | } | 68 | } |
70 | 69 | ||
71 | /* Copy the format metadata we've stored in the id3 TOC field. This | 70 | /* Copy the format metadata we've stored in the id3 TOC field. This |
72 | saves us from parsing it again here. */ | 71 | saves us from parsing it again here. */ |
73 | memcpy(&wfx, ci->id3->toc, sizeof(wfx)); | 72 | memcpy(&wfx, ci->id3->toc, sizeof(wfx)); |
74 | 73 | ||
74 | ci->seek_buffer(ci->id3->first_frame_offset); | ||
75 | if (wma_decode_init(&wmadec,&wfx) < 0) { | 75 | if (wma_decode_init(&wmadec,&wfx) < 0) { |
76 | LOGF("WMA: Unsupported or corrupt file\n"); | 76 | LOGF("WMA: Unsupported or corrupt file\n"); |
77 | retval = CODEC_ERROR; | 77 | return CODEC_ERROR; |
78 | goto exit; | ||
79 | } | 78 | } |
80 | 79 | ||
81 | if (resume_offset > ci->id3->first_frame_offset) | 80 | if (resume_offset > ci->id3->first_frame_offset) |
@@ -101,34 +100,35 @@ restart_track: | |||
101 | codec_set_replaygain(ci->id3); | 100 | codec_set_replaygain(ci->id3); |
102 | 101 | ||
103 | /* The main decoding loop */ | 102 | /* The main decoding loop */ |
104 | |||
105 | res = 1; | ||
106 | while (res >= 0) | 103 | while (res >= 0) |
107 | { | 104 | { |
108 | ci->yield(); | 105 | enum codec_command_action action = ci->get_command(¶m); |
109 | if (ci->stop_codec || ci->new_track) { | 106 | |
110 | goto done; | 107 | if (action == CODEC_ACTION_HALT) |
111 | } | 108 | break; |
112 | 109 | ||
113 | /* Deal with any pending seek requests */ | 110 | /* Deal with any pending seek requests */ |
114 | if (ci->seek_time){ | 111 | if (action == CODEC_ACTION_SEEK_TIME) { |
115 | 112 | ||
116 | if (ci->seek_time == 1) { | 113 | if (param == 0) { |
114 | ci->set_elapsed(0); | ||
117 | ci->seek_complete(); | 115 | ci->seek_complete(); |
118 | goto restart_track; /* Pretend you never saw this... */ | 116 | goto restart_track; /* Pretend you never saw this... */ |
119 | } | 117 | } |
120 | 118 | ||
121 | elapsedtime = asf_seek(ci->seek_time, &wfx); | 119 | elapsedtime = asf_seek(param, &wfx); |
122 | if (elapsedtime < 1){ | 120 | if (elapsedtime < 1){ |
121 | ci->set_elapsed(0); | ||
123 | ci->seek_complete(); | 122 | ci->seek_complete(); |
124 | goto next_track; | 123 | break; |
125 | } | 124 | } |
126 | /*DEBUGF("Seek returned %d\n", (int)elapsedtime);*/ | 125 | /*DEBUGF("Seek returned %d\n", (int)elapsedtime);*/ |
127 | ci->set_elapsed(elapsedtime); | ||
128 | 126 | ||
129 | /*flush the wma decoder state*/ | 127 | /*flush the wma decoder state*/ |
130 | wmadec.last_superframe_len = 0; | 128 | wmadec.last_superframe_len = 0; |
131 | wmadec.last_bitoffset = 0; | 129 | wmadec.last_bitoffset = 0; |
130 | |||
131 | ci->set_elapsed(elapsedtime); | ||
132 | ci->seek_complete(); | 132 | ci->seek_complete(); |
133 | } | 133 | } |
134 | errcount = 0; | 134 | errcount = 0; |
@@ -140,10 +140,15 @@ new_packet: | |||
140 | * times. If we succeed, the error counter will be reset. | 140 | * times. If we succeed, the error counter will be reset. |
141 | */ | 141 | */ |
142 | 142 | ||
143 | if (res == ASF_ERROR_EOF) { | ||
144 | /* File ended - not an error */ | ||
145 | break; | ||
146 | } | ||
147 | |||
143 | errcount++; | 148 | errcount++; |
144 | DEBUGF("read_packet error %d, errcount %d\n",wmares, errcount); | 149 | DEBUGF("read_packet error %d, errcount %d\n",wmares, errcount); |
145 | if (errcount > 5) { | 150 | if (errcount > 5) { |
146 | goto done; | 151 | return CODEC_ERROR; |
147 | } else { | 152 | } else { |
148 | ci->advance_buffer(packetlength); | 153 | ci->advance_buffer(packetlength); |
149 | goto new_packet; | 154 | goto new_packet; |
@@ -163,7 +168,7 @@ new_packet: | |||
163 | errcount++; | 168 | errcount++; |
164 | DEBUGF("WMA decode error %d, errcount %d\n",wmares, errcount); | 169 | DEBUGF("WMA decode error %d, errcount %d\n",wmares, errcount); |
165 | if (errcount > 5) { | 170 | if (errcount > 5) { |
166 | goto done; | 171 | return CODEC_ERROR; |
167 | } else { | 172 | } else { |
168 | ci->advance_buffer(packetlength); | 173 | ci->advance_buffer(packetlength); |
169 | goto new_packet; | 174 | goto new_packet; |
@@ -173,18 +178,12 @@ new_packet: | |||
173 | elapsedtime += (wmares*10)/(wfx.rate/100); | 178 | elapsedtime += (wmares*10)/(wfx.rate/100); |
174 | ci->set_elapsed(elapsedtime); | 179 | ci->set_elapsed(elapsedtime); |
175 | } | 180 | } |
176 | ci->yield(); | ||
177 | } | 181 | } |
178 | } | 182 | } |
179 | 183 | ||
180 | ci->advance_buffer(packetlength); | 184 | ci->advance_buffer(packetlength); |
181 | } | 185 | } |
182 | 186 | ||
183 | done: | ||
184 | /*LOGF("WMA: Decoded %ld samples\n",elapsedtime*wfx.rate/1000);*/ | 187 | /*LOGF("WMA: Decoded %ld samples\n",elapsedtime*wfx.rate/1000);*/ |
185 | 188 | return CODEC_OK; | |
186 | if (ci->request_next_track()) | ||
187 | goto next_track; | ||
188 | exit: | ||
189 | return retval; | ||
190 | } | 189 | } |
diff --git a/apps/codecs/wmapro.c b/apps/codecs/wmapro.c index c02dddeeb3..b6a8e47f25 100644 --- a/apps/codecs/wmapro.c +++ b/apps/codecs/wmapro.c | |||
@@ -27,11 +27,22 @@ CODEC_HEADER | |||
27 | 27 | ||
28 | int32_t *dec[2]; /* pointers to the output buffers in WMAProDecodeCtx in wmaprodec.c */ | 28 | int32_t *dec[2]; /* pointers to the output buffers in WMAProDecodeCtx in wmaprodec.c */ |
29 | 29 | ||
30 | |||
30 | /* this is the codec entry point */ | 31 | /* this is the codec entry point */ |
31 | enum codec_status codec_main(void) | 32 | enum codec_status codec_main(enum codec_entry_call_reason reason) |
33 | { | ||
34 | if (reason == CODEC_LOAD) { | ||
35 | /* Generic codec initialisation */ | ||
36 | ci->configure(DSP_SET_SAMPLE_DEPTH, WMAPRO_DSP_SAMPLE_DEPTH); | ||
37 | } | ||
38 | |||
39 | return CODEC_OK; | ||
40 | } | ||
41 | |||
42 | /* this is called for each file to process */ | ||
43 | enum codec_status codec_run(void) | ||
32 | { | 44 | { |
33 | uint32_t elapsedtime; | 45 | uint32_t elapsedtime; |
34 | int retval; | ||
35 | asf_waveformatex_t wfx; /* Holds the stream properties */ | 46 | asf_waveformatex_t wfx; /* Holds the stream properties */ |
36 | size_t resume_offset; | 47 | size_t resume_offset; |
37 | int res; /* Return values from asf_read_packet() and decode_packet() */ | 48 | int res; /* Return values from asf_read_packet() and decode_packet() */ |
@@ -42,28 +53,15 @@ enum codec_status codec_main(void) | |||
42 | int pktcnt = 0; /* Count of the packets played */ | 53 | int pktcnt = 0; /* Count of the packets played */ |
43 | uint8_t *data; /* Pointer to decoder input buffer */ | 54 | uint8_t *data; /* Pointer to decoder input buffer */ |
44 | int size; /* Size of the input frame to the decoder */ | 55 | int size; /* Size of the input frame to the decoder */ |
45 | 56 | intptr_t param; | |
46 | /* Generic codec initialisation */ | ||
47 | ci->configure(DSP_SET_SAMPLE_DEPTH, WMAPRO_DSP_SAMPLE_DEPTH); | ||
48 | |||
49 | |||
50 | next_track: | ||
51 | retval = CODEC_OK; | ||
52 | |||
53 | /* Wait for the metadata to be read */ | ||
54 | if (codec_wait_taginfo() != 0) | ||
55 | goto done; | ||
56 | 57 | ||
57 | /* Remember the resume position */ | 58 | /* Remember the resume position */ |
58 | resume_offset = ci->id3->offset; | 59 | resume_offset = ci->id3->offset; |
59 | 60 | ||
60 | restart_track: | 61 | restart_track: |
61 | retval = CODEC_OK; | ||
62 | |||
63 | if (codec_init()) { | 62 | if (codec_init()) { |
64 | LOGF("(WMA PRO) Error: Error initialising codec\n"); | 63 | LOGF("(WMA PRO) Error: Error initialising codec\n"); |
65 | retval = CODEC_ERROR; | 64 | return CODEC_ERROR; |
66 | goto done; | ||
67 | } | 65 | } |
68 | 66 | ||
69 | /* Copy the format metadata we've stored in the id3 TOC field. This | 67 | /* Copy the format metadata we've stored in the id3 TOC field. This |
@@ -77,8 +75,7 @@ restart_track: | |||
77 | 75 | ||
78 | if (decode_init(&wfx) < 0) { | 76 | if (decode_init(&wfx) < 0) { |
79 | LOGF("(WMA PRO) Error: Unsupported or corrupt file\n"); | 77 | LOGF("(WMA PRO) Error: Unsupported or corrupt file\n"); |
80 | retval = CODEC_ERROR; | 78 | return CODEC_ERROR; |
81 | goto done; | ||
82 | } | 79 | } |
83 | 80 | ||
84 | /* Now advance the file position to the first frame */ | 81 | /* Now advance the file position to the first frame */ |
@@ -91,23 +88,24 @@ restart_track: | |||
91 | 88 | ||
92 | while (pktcnt < wfx.numpackets) | 89 | while (pktcnt < wfx.numpackets) |
93 | { | 90 | { |
94 | ci->yield(); | 91 | enum codec_command_action action = ci->get_command(¶m); |
95 | if (ci->stop_codec || ci->new_track) { | 92 | |
96 | goto done; | 93 | if (action == CODEC_ACTION_HALT) |
97 | } | 94 | break; |
98 | |||
99 | /* Deal with any pending seek requests */ | ||
100 | if (ci->seek_time){ | ||
101 | 95 | ||
102 | if (ci->seek_time == 1) { | 96 | /* Deal with any pending seek requests */ |
97 | if (action == CODEC_ACTION_SEEK_TIME) { | ||
98 | if (param == 0) { | ||
99 | ci->set_elapsed(0); | ||
103 | ci->seek_complete(); | 100 | ci->seek_complete(); |
104 | goto restart_track; /* Pretend you never saw this... */ | 101 | goto restart_track; /* Pretend you never saw this... */ |
105 | } | 102 | } |
106 | 103 | ||
107 | elapsedtime = asf_seek(ci->seek_time, &wfx); | 104 | elapsedtime = asf_seek(param, &wfx); |
108 | if (elapsedtime < 1){ | 105 | if (elapsedtime < 1){ |
106 | ci->set_elapsed(0); | ||
109 | ci->seek_complete(); | 107 | ci->seek_complete(); |
110 | goto next_track; | 108 | break; |
111 | } | 109 | } |
112 | 110 | ||
113 | ci->set_elapsed(elapsedtime); | 111 | ci->set_elapsed(elapsedtime); |
@@ -117,8 +115,8 @@ restart_track: | |||
117 | res = asf_read_packet(&audiobuf, &audiobufsize, &packetlength, &wfx); | 115 | res = asf_read_packet(&audiobuf, &audiobufsize, &packetlength, &wfx); |
118 | 116 | ||
119 | if (res < 0) { | 117 | if (res < 0) { |
120 | LOGF("(WMA PRO) Warning: asf_read_packet returned %d", res); | 118 | LOGF("(WMA PRO) Warning: asf_read_packet returned %d", res); |
121 | goto done; | 119 | return CODEC_ERROR; |
122 | } else { | 120 | } else { |
123 | data = audiobuf; | 121 | data = audiobuf; |
124 | size = audiobufsize; | 122 | size = audiobufsize; |
@@ -132,7 +130,7 @@ restart_track: | |||
132 | res = decode_packet(&wfx, dec, &outlen, data, size); | 130 | res = decode_packet(&wfx, dec, &outlen, data, size); |
133 | if(res < 0) { | 131 | if(res < 0) { |
134 | LOGF("(WMA PRO) Error: decode_packet returned %d", res); | 132 | LOGF("(WMA PRO) Error: decode_packet returned %d", res); |
135 | goto done; | 133 | return CODEC_ERROR; |
136 | } | 134 | } |
137 | data += res; | 135 | data += res; |
138 | size -= res; | 136 | size -= res; |
@@ -152,10 +150,6 @@ restart_track: | |||
152 | ci->advance_buffer(packetlength); | 150 | ci->advance_buffer(packetlength); |
153 | } | 151 | } |
154 | 152 | ||
155 | done: | 153 | return CODEC_OK; |
156 | if (ci->request_next_track()) | ||
157 | goto next_track; | ||
158 | |||
159 | return retval; | ||
160 | } | 154 | } |
161 | 155 | ||
diff --git a/apps/codecs/wmavoice.c b/apps/codecs/wmavoice.c index ddf66828f1..64c8cd1692 100644 --- a/apps/codecs/wmavoice.c +++ b/apps/codecs/wmavoice.c | |||
@@ -52,10 +52,20 @@ static void init_codec_ctx(AVCodecContext *avctx, asf_waveformatex_t *wfx) | |||
52 | } | 52 | } |
53 | 53 | ||
54 | /* this is the codec entry point */ | 54 | /* this is the codec entry point */ |
55 | enum codec_status codec_main(void) | 55 | enum codec_status codec_main(enum codec_entry_call_reason reason) |
56 | { | ||
57 | if (reason == CODEC_LOAD) { | ||
58 | /* Generic codec initialisation */ | ||
59 | ci->configure(DSP_SET_SAMPLE_DEPTH, 31); | ||
60 | } | ||
61 | |||
62 | return CODEC_OK; | ||
63 | } | ||
64 | |||
65 | /* this is called for each file to process */ | ||
66 | enum codec_status codec_run(void) | ||
56 | { | 67 | { |
57 | uint32_t elapsedtime; | 68 | uint32_t elapsedtime; |
58 | int retval; | ||
59 | asf_waveformatex_t wfx; /* Holds the stream properties */ | 69 | asf_waveformatex_t wfx; /* Holds the stream properties */ |
60 | size_t resume_offset; | 70 | size_t resume_offset; |
61 | int res; /* Return values from asf_read_packet() and decode_packet() */ | 71 | int res; /* Return values from asf_read_packet() and decode_packet() */ |
@@ -64,27 +74,14 @@ enum codec_status codec_main(void) | |||
64 | int packetlength = 0; /* Logical packet size (minus the header size) */ | 74 | int packetlength = 0; /* Logical packet size (minus the header size) */ |
65 | int outlen = 0; /* Number of bytes written to the output buffer */ | 75 | int outlen = 0; /* Number of bytes written to the output buffer */ |
66 | int pktcnt = 0; /* Count of the packets played */ | 76 | int pktcnt = 0; /* Count of the packets played */ |
67 | 77 | intptr_t param; | |
68 | /* Generic codec initialisation */ | ||
69 | ci->configure(DSP_SET_SAMPLE_DEPTH, 31); | ||
70 | |||
71 | |||
72 | next_track: | ||
73 | retval = CODEC_OK; | ||
74 | |||
75 | /* Wait for the metadata to be read */ | ||
76 | if (codec_wait_taginfo() != 0) | ||
77 | goto done; | ||
78 | 78 | ||
79 | /* Remember the resume position */ | 79 | /* Remember the resume position */ |
80 | resume_offset = ci->id3->offset; | 80 | resume_offset = ci->id3->offset; |
81 | restart_track: | 81 | restart_track: |
82 | retval = CODEC_OK; | ||
83 | |||
84 | if (codec_init()) { | 82 | if (codec_init()) { |
85 | LOGF("(WMA Voice) Error: Error initialising codec\n"); | 83 | LOGF("(WMA Voice) Error: Error initialising codec\n"); |
86 | retval = CODEC_ERROR; | 84 | return CODEC_ERROR; |
87 | goto done; | ||
88 | } | 85 | } |
89 | 86 | ||
90 | /* Copy the format metadata we've stored in the id3 TOC field. This | 87 | /* Copy the format metadata we've stored in the id3 TOC field. This |
@@ -97,14 +94,15 @@ restart_track: | |||
97 | ci->configure(DSP_SET_STEREO_MODE, wfx.channels == 1 ? | 94 | ci->configure(DSP_SET_STEREO_MODE, wfx.channels == 1 ? |
98 | STEREO_MONO : STEREO_INTERLEAVED); | 95 | STEREO_MONO : STEREO_INTERLEAVED); |
99 | codec_set_replaygain(ci->id3); | 96 | codec_set_replaygain(ci->id3); |
97 | |||
98 | ci->seek_buffer(0); | ||
100 | 99 | ||
101 | /* Initialise the AVCodecContext */ | 100 | /* Initialise the AVCodecContext */ |
102 | init_codec_ctx(&avctx, &wfx); | 101 | init_codec_ctx(&avctx, &wfx); |
103 | 102 | ||
104 | if (wmavoice_decode_init(&avctx) < 0) { | 103 | if (wmavoice_decode_init(&avctx) < 0) { |
105 | LOGF("(WMA Voice) Error: Unsupported or corrupt file\n"); | 104 | LOGF("(WMA Voice) Error: Unsupported or corrupt file\n"); |
106 | retval = CODEC_ERROR; | 105 | return CODEC_ERROR; |
107 | goto done; | ||
108 | } | 106 | } |
109 | 107 | ||
110 | /* Now advance the file position to the first frame */ | 108 | /* Now advance the file position to the first frame */ |
@@ -117,21 +115,24 @@ restart_track: | |||
117 | 115 | ||
118 | while (pktcnt < wfx.numpackets) | 116 | while (pktcnt < wfx.numpackets) |
119 | { | 117 | { |
120 | ci->yield(); | 118 | enum codec_command_action action = ci->get_command(¶m); |
121 | if (ci->stop_codec || ci->new_track) { | 119 | |
122 | goto done; | 120 | if (action == CODEC_ACTION_HALT) |
123 | } | 121 | break; |
124 | 122 | ||
125 | /* Deal with any pending seek requests */ | 123 | /* Deal with any pending seek requests */ |
126 | if (ci->seek_time){ | 124 | if (action == CODEC_ACTION_SEEK_TIME) { |
125 | ci->set_elapsed(param); | ||
127 | 126 | ||
128 | if (ci->seek_time == 1) { | 127 | if (param == 0) { |
128 | ci->set_elapsed(0); | ||
129 | ci->seek_complete(); | 129 | ci->seek_complete(); |
130 | goto restart_track; /* Pretend you never saw this... */ | 130 | goto restart_track; /* Pretend you never saw this... */ |
131 | } | 131 | } |
132 | 132 | ||
133 | elapsedtime = asf_seek(ci->seek_time, &wfx); | 133 | elapsedtime = asf_seek(param, &wfx); |
134 | if (elapsedtime < 1){ | 134 | if (elapsedtime < 1){ |
135 | ci->set_elapsed(0); | ||
135 | ci->seek_complete(); | 136 | ci->seek_complete(); |
136 | goto next_track; | 137 | goto next_track; |
137 | } | 138 | } |
@@ -145,7 +146,7 @@ new_packet: | |||
145 | 146 | ||
146 | if (res < 0) { | 147 | if (res < 0) { |
147 | LOGF("(WMA Voice) read_packet error %d\n",res); | 148 | LOGF("(WMA Voice) read_packet error %d\n",res); |
148 | goto done; | 149 | return CODEC_ERROR; |
149 | } else { | 150 | } else { |
150 | avpkt.data = audiobuf; | 151 | avpkt.data = audiobuf; |
151 | avpkt.size = audiobufsize; | 152 | avpkt.size = audiobufsize; |
@@ -165,8 +166,9 @@ new_packet: | |||
165 | ci->advance_buffer(packetlength); | 166 | ci->advance_buffer(packetlength); |
166 | goto new_packet; | 167 | goto new_packet; |
167 | } | 168 | } |
168 | else | 169 | else { |
169 | goto done; | 170 | return CODEC_ERROR; |
171 | } | ||
170 | } | 172 | } |
171 | avpkt.data += res; | 173 | avpkt.data += res; |
172 | avpkt.size -= res; | 174 | avpkt.size -= res; |
@@ -186,10 +188,6 @@ new_packet: | |||
186 | ci->advance_buffer(packetlength); | 188 | ci->advance_buffer(packetlength); |
187 | } | 189 | } |
188 | 190 | ||
189 | done: | 191 | return CODEC_OK; |
190 | if (ci->request_next_track()) | ||
191 | goto next_track; | ||
192 | |||
193 | return retval; | ||
194 | } | 192 | } |
195 | 193 | ||