summaryrefslogtreecommitdiff
path: root/lib/rbcodec/codecs/cook.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rbcodec/codecs/cook.c')
-rw-r--r--lib/rbcodec/codecs/cook.c106
1 files changed, 68 insertions, 38 deletions
diff --git a/lib/rbcodec/codecs/cook.c b/lib/rbcodec/codecs/cook.c
index af1f5e1a87..254e71f576 100644
--- a/lib/rbcodec/codecs/cook.c
+++ b/lib/rbcodec/codecs/cook.c
@@ -21,7 +21,6 @@
21 21
22#include <string.h> 22#include <string.h>
23 23
24#include "logf.h"
25#include "codeclib.h" 24#include "codeclib.h"
26#include "inttypes.h" 25#include "inttypes.h"
27#include "libcook/cook.h" 26#include "libcook/cook.h"
@@ -38,6 +37,22 @@ static void init_rm(RMContext *rmctx)
38 memcpy(rmctx, (void*)(( (intptr_t)ci->id3->id3v2buf + 3 ) &~ 3), sizeof(RMContext)); 37 memcpy(rmctx, (void*)(( (intptr_t)ci->id3->id3v2buf + 3 ) &~ 3), sizeof(RMContext));
39} 38}
40 39
40static int request_packet(int size)
41{
42 int consumed = 0;
43 while (1)
44 {
45 uint8_t *buffer = ci->request_buffer((size_t *)(&consumed), size);
46 if (!consumed)
47 break;
48 consumed = rm_get_packet(&buffer, &rmctx, &pkt);
49 if (consumed < 0 || consumed == size)
50 break;
51 ci->advance_buffer(size);
52 }
53 return consumed;
54}
55
41/* this is the codec entry point */ 56/* this is the codec entry point */
42enum codec_status codec_main(enum codec_entry_call_reason reason) 57enum codec_status codec_main(enum codec_entry_call_reason reason)
43{ 58{
@@ -49,12 +64,10 @@ enum codec_status codec_main(enum codec_entry_call_reason reason)
49/* this is called for each file to process */ 64/* this is called for each file to process */
50enum codec_status codec_run(void) 65enum codec_status codec_run(void)
51{ 66{
52 static size_t buff_size;
53 int datasize, res, consumed, i, time_offset; 67 int datasize, res, consumed, i, time_offset;
54 uint8_t *bit_buffer;
55 uint16_t fs,sps,h; 68 uint16_t fs,sps,h;
56 uint32_t packet_count; 69 uint32_t packet_count;
57 int scrambling_unit_size, num_units; 70 int spn, packet_header_size, scrambling_unit_size, num_units;
58 size_t resume_offset; 71 size_t resume_offset;
59 intptr_t param; 72 intptr_t param;
60 long action; 73 long action;
@@ -84,14 +97,17 @@ enum codec_status codec_run(void)
84 ci->configure(DSP_SET_STEREO_MODE, rmctx.nb_channels == 1 ? 97 ci->configure(DSP_SET_STEREO_MODE, rmctx.nb_channels == 1 ?
85 STEREO_MONO : STEREO_NONINTERLEAVED); 98 STEREO_MONO : STEREO_NONINTERLEAVED);
86 99
100 packet_header_size = PACKET_HEADER_SIZE +
101 ((rmctx.flags & RM_PKT_V1) ? 1 : 0);
87 packet_count = rmctx.nb_packets; 102 packet_count = rmctx.nb_packets;
88 rmctx.audio_framesize = rmctx.block_align; 103 rmctx.audio_framesize = rmctx.block_align;
89 rmctx.block_align = rmctx.sub_packet_size; 104 rmctx.block_align = rmctx.sub_packet_size;
90 fs = rmctx.audio_framesize; 105 fs = rmctx.audio_framesize;
91 sps= rmctx.block_align; 106 sps= rmctx.block_align;
92 h = rmctx.sub_packet_h; 107 h = rmctx.sub_packet_h;
93 scrambling_unit_size = h * (fs + PACKET_HEADER_SIZE); 108 scrambling_unit_size = h * (fs + packet_header_size);
94 109 spn = h * fs / sps;
110
95 res =cook_decode_init(&rmctx, &q); 111 res =cook_decode_init(&rmctx, &q);
96 if(res < 0) { 112 if(res < 0) {
97 DEBUGF("failed to initialize cook decoder\n"); 113 DEBUGF("failed to initialize cook decoder\n");
@@ -101,10 +117,10 @@ enum codec_status codec_run(void)
101 /* check for a mid-track resume and force a seek time accordingly */ 117 /* check for a mid-track resume and force a seek time accordingly */
102 if(resume_offset) { 118 if(resume_offset) {
103 resume_offset -= MIN(resume_offset, rmctx.data_offset + DATA_HEADER_SIZE); 119 resume_offset -= MIN(resume_offset, rmctx.data_offset + DATA_HEADER_SIZE);
104 num_units = (int)resume_offset / scrambling_unit_size; 120 num_units = (int)resume_offset / scrambling_unit_size;
105 /* put number of subpackets to skip in resume_offset */ 121 /* put number of packets to skip in resume_offset */
106 resume_offset /= (sps + PACKET_HEADER_SIZE); 122 resume_offset = num_units * h;
107 param = (int)resume_offset * ((sps * 8 * 1000)/rmctx.bit_rate); 123 param = (int)resume_offset * ((8000LL * fs)/rmctx.bit_rate);
108 } 124 }
109 125
110 if (param) { 126 if (param) {
@@ -120,14 +136,15 @@ enum codec_status codec_run(void)
120seek_start : 136seek_start :
121 while(packet_count) 137 while(packet_count)
122 { 138 {
123 bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size); 139 consumed = request_packet(scrambling_unit_size);
124 consumed = rm_get_packet(&bit_buffer, &rmctx, &pkt); 140 if (!consumed)
141 break;
125 if(consumed < 0) { 142 if(consumed < 0) {
126 DEBUGF("rm_get_packet failed\n"); 143 DEBUGF("rm_get_packet failed\n");
127 return CODEC_ERROR; 144 return CODEC_ERROR;
128 } 145 }
129 146
130 for(i = 0; i < rmctx.audio_pkt_cnt*(fs/sps) ; i++) 147 for (i = 0; i < spn; i++)
131 { 148 {
132 if (action == CODEC_ACTION_NULL) 149 if (action == CODEC_ACTION_NULL)
133 action = ci->get_command(&param); 150 action = ci->get_command(&param);
@@ -155,52 +172,65 @@ seek_start :
155 action = CODEC_ACTION_NULL; 172 action = CODEC_ACTION_NULL;
156 goto seek_start; 173 goto seek_start;
157 } 174 }
158 num_units = (param/(sps*1000*8/rmctx.bit_rate))/(h*(fs/sps)); 175 num_units = (param/(sps*1000*8/rmctx.bit_rate))/spn;
159 ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + consumed * num_units); 176 ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + scrambling_unit_size * num_units);
160 bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size); 177 consumed = request_packet(scrambling_unit_size);
161 consumed = rm_get_packet(&bit_buffer, &rmctx, &pkt); 178 if (!consumed) {
179 ci->seek_complete();
180 return CODEC_OK;
181 }
162 if(consumed < 0) { 182 if(consumed < 0) {
163 DEBUGF("rm_get_packet failed\n"); 183 DEBUGF("rm_get_packet failed\n");
164 ci->seek_complete(); 184 ci->seek_complete();
165 return CODEC_ERROR; 185 return CODEC_ERROR;
166 } 186 }
167 packet_count = rmctx.nb_packets - rmctx.audio_pkt_cnt * num_units; 187
188 packet_count = rmctx.nb_packets - h * num_units;
168 rmctx.frame_number = (param/(sps*1000*8/rmctx.bit_rate)); 189 rmctx.frame_number = (param/(sps*1000*8/rmctx.bit_rate));
169 while(rmctx.audiotimestamp > (unsigned) param) { 190 while(rmctx.audiotimestamp > (unsigned)param && num_units-- > 0) {
170 rmctx.audio_pkt_cnt = 0; 191 rmctx.audio_pkt_cnt = 0;
171 ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + consumed * (num_units-1)); 192 ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + scrambling_unit_size * num_units);
172 bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size); 193 consumed = request_packet(scrambling_unit_size);
173 consumed = rm_get_packet(&bit_buffer, &rmctx, &pkt); 194 if (!consumed) {
174 packet_count += rmctx.audio_pkt_cnt; 195 ci->seek_complete();
175 num_units--; 196 return CODEC_OK;
197 }
198 if(consumed < 0) {
199 ci->seek_complete();
200 DEBUGF("rm_get_packet failed\n");
201 return CODEC_ERROR;
202 }
203
204 packet_count += h;
176 } 205 }
206
207 if (num_units < 0)
208 rmctx.audiotimestamp = 0;
177 time_offset = param - rmctx.audiotimestamp; 209 time_offset = param - rmctx.audiotimestamp;
178 i = (time_offset/((sps * 8 * 1000)/rmctx.bit_rate)); 210 i = (time_offset/((sps * 8 * 1000)/rmctx.bit_rate));
179 ci->set_elapsed(rmctx.audiotimestamp+(1000*8*sps/rmctx.bit_rate)*i); 211 ci->set_elapsed(param);
180 ci->seek_complete(); 212 ci->seek_complete();
181 } 213 }
182 214
183 action = CODEC_ACTION_NULL; 215 action = CODEC_ACTION_NULL;
184 216
185 res = cook_decode_frame(&rmctx,&q, rm_outbuf, &datasize, pkt.frames[i], rmctx.block_align); 217 res = cook_decode_frame(&rmctx,&q, rm_outbuf, &datasize, pkt.frames[i], sps);
186 rmctx.frame_number++;
187
188 /* skip the first two frames; no valid audio */
189 if(rmctx.frame_number < 3) continue;
190 218
191 if(res != rmctx.block_align) { 219 if (res != sps) {
192 DEBUGF("codec error\n"); 220 DEBUGF("codec error\n");
193 return CODEC_ERROR; 221 return CODEC_ERROR;
194 } 222 }
195 223
196 ci->pcmbuf_insert(rm_outbuf, 224 if(datasize)
197 rm_outbuf+q.samples_per_channel, 225 ci->pcmbuf_insert(rm_outbuf,
198 q.samples_per_channel); 226 rm_outbuf+q.samples_per_channel,
227 q.samples_per_channel);
199 ci->set_elapsed(rmctx.audiotimestamp+(1000*8*sps/rmctx.bit_rate)*i); 228 ci->set_elapsed(rmctx.audiotimestamp+(1000*8*sps/rmctx.bit_rate)*i);
229 rmctx.frame_number++;
200 } 230 }
201 packet_count -= rmctx.audio_pkt_cnt; 231 packet_count -= h;
202 rmctx.audio_pkt_cnt = 0; 232 rmctx.audio_pkt_cnt = 0;
203 ci->advance_buffer(consumed); 233 ci->advance_buffer(scrambling_unit_size);
204 } 234 }
205 235
206 return CODEC_OK; 236 return CODEC_OK;