diff options
Diffstat (limited to 'lib/rbcodec/codecs/atrac3_rm.c')
-rw-r--r-- | lib/rbcodec/codecs/atrac3_rm.c | 91 |
1 files changed, 61 insertions, 30 deletions
diff --git a/lib/rbcodec/codecs/atrac3_rm.c b/lib/rbcodec/codecs/atrac3_rm.c index 59dbd29cad..af38b79fc4 100644 --- a/lib/rbcodec/codecs/atrac3_rm.c +++ b/lib/rbcodec/codecs/atrac3_rm.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 "libatrac/atrac3.h" | 26 | #include "libatrac/atrac3.h" |
@@ -37,10 +36,26 @@ static void init_rm(RMContext *rmctx) | |||
37 | /* initialize the RMContext */ | 36 | /* initialize the RMContext */ |
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 | /* and atrac3 expects extadata in id3v2buf, so we shall give it that */ | 39 | /* and atrac3 expects extradata in id3v2buf, so we shall give it that */ |
41 | memcpy(ci->id3->id3v2buf, (char*)rmctx->codec_extradata, rmctx->extradata_size*sizeof(char)); | 40 | memcpy(ci->id3->id3v2buf, (char*)rmctx->codec_extradata, rmctx->extradata_size*sizeof(char)); |
42 | } | 41 | } |
43 | 42 | ||
43 | static int request_packet(int size) | ||
44 | { | ||
45 | int consumed = 0; | ||
46 | while (1) | ||
47 | { | ||
48 | uint8_t *buffer = ci->request_buffer((size_t *)(&consumed), size); | ||
49 | if (!consumed) | ||
50 | break; | ||
51 | consumed = rm_get_packet(&buffer, &rmctx, &pkt); | ||
52 | if (consumed < 0 || consumed == size) | ||
53 | break; | ||
54 | ci->advance_buffer(size); | ||
55 | } | ||
56 | return consumed; | ||
57 | } | ||
58 | |||
44 | /* this is the codec entry point */ | 59 | /* this is the codec entry point */ |
45 | enum codec_status codec_main(enum codec_entry_call_reason reason) | 60 | enum codec_status codec_main(enum codec_entry_call_reason reason) |
46 | { | 61 | { |
@@ -52,12 +67,10 @@ enum codec_status codec_main(enum codec_entry_call_reason reason) | |||
52 | /* this is called for each file to process */ | 67 | /* this is called for each file to process */ |
53 | enum codec_status codec_run(void) | 68 | enum codec_status codec_run(void) |
54 | { | 69 | { |
55 | static size_t buff_size; | ||
56 | int datasize, res, consumed, i, time_offset; | 70 | int datasize, res, consumed, i, time_offset; |
57 | uint8_t *bit_buffer; | ||
58 | uint16_t fs,sps,h; | 71 | uint16_t fs,sps,h; |
59 | uint32_t packet_count; | 72 | uint32_t packet_count; |
60 | int scrambling_unit_size, num_units, elapsed; | 73 | int spn, packet_header_size, scrambling_unit_size, num_units, elapsed; |
61 | int playback_on = -1; | 74 | int playback_on = -1; |
62 | size_t resume_offset; | 75 | size_t resume_offset; |
63 | intptr_t param; | 76 | intptr_t param; |
@@ -85,14 +98,17 @@ enum codec_status codec_run(void) | |||
85 | ci->configure(DSP_SET_STEREO_MODE, rmctx.nb_channels == 1 ? | 98 | ci->configure(DSP_SET_STEREO_MODE, rmctx.nb_channels == 1 ? |
86 | STEREO_MONO : STEREO_NONINTERLEAVED); | 99 | STEREO_MONO : STEREO_NONINTERLEAVED); |
87 | 100 | ||
101 | packet_header_size = PACKET_HEADER_SIZE + | ||
102 | ((rmctx.flags & RM_PKT_V1) ? 1 : 0); | ||
88 | packet_count = rmctx.nb_packets; | 103 | packet_count = rmctx.nb_packets; |
89 | rmctx.audio_framesize = rmctx.block_align; | 104 | rmctx.audio_framesize = rmctx.block_align; |
90 | rmctx.block_align = rmctx.sub_packet_size; | 105 | rmctx.block_align = rmctx.sub_packet_size; |
91 | fs = rmctx.audio_framesize; | 106 | fs = rmctx.audio_framesize; |
92 | sps= rmctx.block_align; | 107 | sps= rmctx.block_align; |
93 | h = rmctx.sub_packet_h; | 108 | h = rmctx.sub_packet_h; |
94 | scrambling_unit_size = h * (fs + PACKET_HEADER_SIZE); | 109 | scrambling_unit_size = h * (fs + packet_header_size); |
95 | 110 | spn = h * fs / sps; | |
111 | |||
96 | res = atrac3_decode_init(&q, ci->id3); | 112 | res = atrac3_decode_init(&q, ci->id3); |
97 | if(res < 0) { | 113 | if(res < 0) { |
98 | DEBUGF("failed to initialize RM atrac decoder\n"); | 114 | DEBUGF("failed to initialize RM atrac decoder\n"); |
@@ -102,10 +118,10 @@ enum codec_status codec_run(void) | |||
102 | /* check for a mid-track resume and force a seek time accordingly */ | 118 | /* check for a mid-track resume and force a seek time accordingly */ |
103 | if(resume_offset) { | 119 | if(resume_offset) { |
104 | resume_offset -= MIN(resume_offset, rmctx.data_offset + DATA_HEADER_SIZE); | 120 | resume_offset -= MIN(resume_offset, rmctx.data_offset + DATA_HEADER_SIZE); |
105 | num_units = (int)resume_offset / scrambling_unit_size; | 121 | num_units = (int)resume_offset / scrambling_unit_size; |
106 | /* put number of subpackets to skip in resume_offset */ | 122 | /* put number of packets to skip in resume_offset */ |
107 | resume_offset /= (sps + PACKET_HEADER_SIZE); | 123 | resume_offset = num_units * h; |
108 | elapsed = (int)resume_offset * ((sps * 8 * 1000)/rmctx.bit_rate); | 124 | elapsed = (int)resume_offset * ((8000LL * fs)/rmctx.bit_rate); |
109 | } | 125 | } |
110 | 126 | ||
111 | if (elapsed > 0) { | 127 | if (elapsed > 0) { |
@@ -123,8 +139,9 @@ enum codec_status codec_run(void) | |||
123 | seek_start : | 139 | seek_start : |
124 | while((unsigned)elapsed < rmctx.duration) | 140 | while((unsigned)elapsed < rmctx.duration) |
125 | { | 141 | { |
126 | bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size); | 142 | consumed = request_packet(scrambling_unit_size); |
127 | consumed = rm_get_packet(&bit_buffer, &rmctx, &pkt); | 143 | if (!consumed) |
144 | break; | ||
128 | if(consumed < 0 && playback_on != 0) { | 145 | if(consumed < 0 && playback_on != 0) { |
129 | if(playback_on == -1) { | 146 | if(playback_on == -1) { |
130 | /* Error only if packet-parsing failed and playback hadn't started */ | 147 | /* Error only if packet-parsing failed and playback hadn't started */ |
@@ -135,7 +152,7 @@ seek_start : | |||
135 | return CODEC_OK; | 152 | return CODEC_OK; |
136 | } | 153 | } |
137 | 154 | ||
138 | for(i = 0; i < rmctx.audio_pkt_cnt*(fs/sps) ; i++) | 155 | for (i = 0; i < spn; i++) |
139 | { | 156 | { |
140 | if (action == CODEC_ACTION_NULL) | 157 | if (action == CODEC_ACTION_NULL) |
141 | action = ci->get_command(¶m); | 158 | action = ci->get_command(¶m); |
@@ -164,10 +181,11 @@ seek_start : | |||
164 | action = CODEC_ACTION_NULL; | 181 | action = CODEC_ACTION_NULL; |
165 | goto seek_start; | 182 | goto seek_start; |
166 | } | 183 | } |
167 | num_units = (param/(sps*1000*8/rmctx.bit_rate))/(h*(fs/sps)); | 184 | num_units = (param/(sps*1000*8/rmctx.bit_rate))/spn; |
168 | ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + consumed * num_units); | 185 | ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + scrambling_unit_size * num_units); |
169 | bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size); | 186 | consumed = request_packet(scrambling_unit_size); |
170 | consumed = rm_get_packet(&bit_buffer, &rmctx, &pkt); | 187 | if (!consumed) |
188 | return CODEC_OK; | ||
171 | if(consumed < 0 && playback_on != 0) { | 189 | if(consumed < 0 && playback_on != 0) { |
172 | if(playback_on == -1) { | 190 | if(playback_on == -1) { |
173 | /* Error only if packet-parsing failed and playback hadn't started */ | 191 | /* Error only if packet-parsing failed and playback hadn't started */ |
@@ -178,19 +196,32 @@ seek_start : | |||
178 | return CODEC_OK; | 196 | return CODEC_OK; |
179 | } | 197 | } |
180 | 198 | ||
181 | packet_count = rmctx.nb_packets - rmctx.audio_pkt_cnt * num_units; | 199 | packet_count = rmctx.nb_packets - h * num_units; |
182 | rmctx.frame_number = (param/(sps*1000*8/rmctx.bit_rate)); | 200 | rmctx.frame_number = (param/(sps*1000*8/rmctx.bit_rate)); |
183 | while(rmctx.audiotimestamp > (unsigned) param) { | 201 | while (rmctx.audiotimestamp > (unsigned)param && num_units-- > 0) { |
184 | rmctx.audio_pkt_cnt = 0; | 202 | rmctx.audio_pkt_cnt = 0; |
185 | ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + consumed * (num_units-1)); | 203 | ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + scrambling_unit_size * num_units); |
186 | bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size); | 204 | consumed = request_packet(scrambling_unit_size); |
187 | consumed = rm_get_packet(&bit_buffer, &rmctx, &pkt); | 205 | if (!consumed) |
188 | packet_count += rmctx.audio_pkt_cnt; | 206 | return CODEC_OK; |
189 | num_units--; | 207 | if(consumed < 0 && playback_on != 0) { |
208 | if(playback_on == -1) { | ||
209 | /* Error only if packet-parsing failed and playback hadn't started */ | ||
210 | DEBUGF("rm_get_packet failed\n"); | ||
211 | return CODEC_ERROR; | ||
212 | } | ||
213 | else | ||
214 | return CODEC_OK; | ||
215 | } | ||
216 | |||
217 | packet_count += h; | ||
190 | } | 218 | } |
219 | |||
220 | if (num_units < 0) | ||
221 | rmctx.audiotimestamp = 0; | ||
191 | time_offset = param - rmctx.audiotimestamp; | 222 | time_offset = param - rmctx.audiotimestamp; |
192 | i = (time_offset/((sps * 8 * 1000)/rmctx.bit_rate)); | 223 | i = (time_offset/((sps * 8 * 1000)/rmctx.bit_rate)); |
193 | elapsed = rmctx.audiotimestamp+(1000*8*sps/rmctx.bit_rate)*i; | 224 | elapsed = param; |
194 | ci->set_elapsed(elapsed); | 225 | ci->set_elapsed(elapsed); |
195 | ci->seek_complete(); | 226 | ci->seek_complete(); |
196 | } | 227 | } |
@@ -198,11 +229,11 @@ seek_start : | |||
198 | action = CODEC_ACTION_NULL; | 229 | action = CODEC_ACTION_NULL; |
199 | 230 | ||
200 | if(pkt.length) | 231 | if(pkt.length) |
201 | res = atrac3_decode_frame(rmctx.block_align, &q, &datasize, pkt.frames[i], rmctx.block_align); | 232 | res = atrac3_decode_frame(sps, &q, &datasize, pkt.frames[i], sps); |
202 | else /* indicates that there are no remaining frames */ | 233 | else /* indicates that there are no remaining frames */ |
203 | return CODEC_OK; | 234 | return CODEC_OK; |
204 | 235 | ||
205 | if(res != rmctx.block_align) { | 236 | if (res != sps) { |
206 | DEBUGF("codec error\n"); | 237 | DEBUGF("codec error\n"); |
207 | return CODEC_ERROR; | 238 | return CODEC_ERROR; |
208 | } | 239 | } |
@@ -214,9 +245,9 @@ seek_start : | |||
214 | ci->set_elapsed(elapsed); | 245 | ci->set_elapsed(elapsed); |
215 | rmctx.frame_number++; | 246 | rmctx.frame_number++; |
216 | } | 247 | } |
217 | packet_count -= rmctx.audio_pkt_cnt; | 248 | packet_count -= h; |
218 | rmctx.audio_pkt_cnt = 0; | 249 | rmctx.audio_pkt_cnt = 0; |
219 | ci->advance_buffer(consumed); | 250 | ci->advance_buffer(scrambling_unit_size); |
220 | } | 251 | } |
221 | 252 | ||
222 | return CODEC_OK; | 253 | return CODEC_OK; |