summaryrefslogtreecommitdiff
path: root/lib/rbcodec/codecs/atrac3_rm.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/rbcodec/codecs/atrac3_rm.c')
-rw-r--r--lib/rbcodec/codecs/atrac3_rm.c91
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
43static 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 */
45enum codec_status codec_main(enum codec_entry_call_reason reason) 60enum 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 */
53enum codec_status codec_run(void) 68enum 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)
123seek_start : 139seek_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(&param); 158 action = ci->get_command(&param);
@@ -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;