summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSolomon Peachy <pizza@shaftnet.org>2018-12-22 20:04:28 -0500
committerSolomon Peachy <pizza@shaftnet.org>2018-12-22 20:12:10 -0500
commit9b9b30bd547c829157f3f83c71378f0bbd43241d (patch)
treed4f1df7303881d197e14ef8db1957705667526df
parenteee3f0ce79eb0b2ae2f272e814e10e6e9524c381 (diff)
downloadrockbox-9b9b30bd547c829157f3f83c71378f0bbd43241d.tar.gz
rockbox-9b9b30bd547c829157f3f83c71378f0bbd43241d.zip
Realmedia related codecs fixes and enhancements
* More tolerance to the file format variations. * AC3 coded files in realaudio format are now playable Full credit to Igor Poretsky Change-Id: Id24e94bc00623e89fb8c80403efa92f69ab1e5d7
-rw-r--r--lib/rbcodec/codecs/a52_rm.c109
-rw-r--r--lib/rbcodec/codecs/atrac3_rm.c91
-rw-r--r--lib/rbcodec/codecs/cook.c106
-rw-r--r--lib/rbcodec/codecs/librm/rm.c59
-rw-r--r--lib/rbcodec/codecs/librm/rm.h5
-rw-r--r--lib/rbcodec/codecs/raac.c3
-rw-r--r--lib/rbcodec/metadata/metadata.c4
-rw-r--r--lib/rbcodec/metadata/rm.c56
8 files changed, 309 insertions, 124 deletions
diff --git a/lib/rbcodec/codecs/a52_rm.c b/lib/rbcodec/codecs/a52_rm.c
index bbfd1c735f..e5204762f4 100644
--- a/lib/rbcodec/codecs/a52_rm.c
+++ b/lib/rbcodec/codecs/a52_rm.c
@@ -44,6 +44,14 @@ static void init_rm(RMContext *rmctx)
44 44
45/* used outside liba52 */ 45/* used outside liba52 */
46static uint8_t buf[3840] IBSS_ATTR; 46static uint8_t buf[3840] IBSS_ATTR;
47static uint8_t *bufptr = buf;
48static uint8_t *bufpos = buf + 7;
49
50static void a52_decoder_reset(void)
51{
52 bufptr = buf;
53 bufpos = buf + 7;
54}
47 55
48/* The following two functions, a52_decode_data and output_audio are taken from a52.c */ 56/* The following two functions, a52_decode_data and output_audio are taken from a52.c */
49static inline void output_audio(sample_t *samples) 57static inline void output_audio(sample_t *samples)
@@ -52,10 +60,8 @@ static inline void output_audio(sample_t *samples)
52 ci->pcmbuf_insert(&samples[0], &samples[256], 256); 60 ci->pcmbuf_insert(&samples[0], &samples[256], 256);
53} 61}
54 62
55static void a52_decode_data(uint8_t *start, uint8_t *end) 63static size_t a52_decode_data(uint8_t *start, uint8_t *end)
56{ 64{
57 static uint8_t *bufptr = buf;
58 static uint8_t *bufpos = buf + 7;
59 /* 65 /*
60 * sample_rate and flags are static because this routine could 66 * sample_rate and flags are static because this routine could
61 * exit between the a52_syncinfo() and the ao_setup(), and we want 67 * exit between the a52_syncinfo() and the ao_setup(), and we want
@@ -65,6 +71,7 @@ static void a52_decode_data(uint8_t *start, uint8_t *end)
65 static int flags; 71 static int flags;
66 int bit_rate; 72 int bit_rate;
67 int len; 73 int len;
74 size_t consumed = 0;
68 75
69 while (1) { 76 while (1) {
70 len = end - start; 77 len = end - start;
@@ -75,6 +82,7 @@ static void a52_decode_data(uint8_t *start, uint8_t *end)
75 memcpy(bufptr, start, len); 82 memcpy(bufptr, start, len);
76 bufptr += len; 83 bufptr += len;
77 start += len; 84 start += len;
85 consumed += len;
78 if (bufptr == bufpos) { 86 if (bufptr == bufpos) {
79 if (bufpos == buf + 7) { 87 if (bufpos == buf + 7) {
80 int length; 88 int length;
@@ -114,7 +122,7 @@ static void a52_decode_data(uint8_t *start, uint8_t *end)
114 ci->set_elapsed(samplesdone/(frequency/1000)); 122 ci->set_elapsed(samplesdone/(frequency/1000));
115 bufptr = buf; 123 bufptr = buf;
116 bufpos = buf + 7; 124 bufpos = buf + 7;
117 continue; 125 break;
118 error: 126 error:
119 //logf("Error decoding A52 stream\n"); 127 //logf("Error decoding A52 stream\n");
120 bufptr = buf; 128 bufptr = buf;
@@ -122,6 +130,7 @@ static void a52_decode_data(uint8_t *start, uint8_t *end)
122 } 130 }
123 } 131 }
124 } 132 }
133 return consumed;
125} 134}
126 135
127/* this is the codec entry point */ 136/* this is the codec entry point */
@@ -143,11 +152,13 @@ enum codec_status codec_main(enum codec_entry_call_reason reason)
143/* this is called for each file to process */ 152/* this is called for each file to process */
144enum codec_status codec_run(void) 153enum codec_status codec_run(void)
145{ 154{
146 size_t n; 155 size_t consumed = 0, n = 0;
147 uint8_t *filebuf; 156 uint8_t *filebuf;
148 int consumed, packet_offset; 157 int packet_offset;
149 int playback_on = -1; 158 int playback_on = -1;
150 size_t resume_offset; 159 size_t resume_offset;
160 size_t data_offset;
161 size_t packet_size;
151 long action; 162 long action;
152 intptr_t param; 163 intptr_t param;
153 164
@@ -162,21 +173,28 @@ enum codec_status codec_run(void)
162 ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency); 173 ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency);
163 codec_set_replaygain(ci->id3); 174 codec_set_replaygain(ci->id3);
164 175
165 ci->seek_buffer(ci->id3->first_frame_offset); 176 ci->seek_buffer(0);
166 177
167 /* Intializations */ 178 /* Initializations */
168 state = a52_init(0); 179 state = a52_init(0);
169 ci->memset(&rmctx,0,sizeof(RMContext)); 180 ci->memset(&rmctx,0,sizeof(RMContext));
170 ci->memset(&pkt,0,sizeof(RMPacket)); 181 ci->memset(&pkt,0,sizeof(RMPacket));
171 init_rm(&rmctx); 182 init_rm(&rmctx);
183 data_offset = rmctx.data_offset +
184 ((rmctx.flags & RM_RAW_DATASTREAM) ? 0 : DATA_HEADER_SIZE);
185 packet_size = rmctx.block_align +
186 ((rmctx.flags & RM_RAW_DATASTREAM) ?
187 0 :
188 (PACKET_HEADER_SIZE +
189 ((rmctx.flags & RM_PKT_V1) ? 1 : 0)));
172 190
173 samplesdone = 0; 191 samplesdone = 0;
174 192
175 /* check for a mid-track resume and force a seek time accordingly */ 193 /* check for a mid-track resume and force a seek time accordingly */
176 if (resume_offset) { 194 if (resume_offset) {
177 resume_offset -= MIN(resume_offset, rmctx.data_offset + DATA_HEADER_SIZE); 195 resume_offset -= MIN(resume_offset, data_offset);
178 /* put number of subpackets to skip in resume_offset */ 196 /* put number of subpackets to skip in resume_offset */
179 resume_offset /= (rmctx.block_align + PACKET_HEADER_SIZE); 197 resume_offset /= packet_size;
180 param = (int)resume_offset * ((rmctx.block_align * 8 * 1000)/rmctx.bit_rate); 198 param = (int)resume_offset * ((rmctx.block_align * 8 * 1000)/rmctx.bit_rate);
181 } 199 }
182 200
@@ -186,11 +204,11 @@ enum codec_status codec_run(void)
186 else { 204 else {
187 /* Seek to the first packet */ 205 /* Seek to the first packet */
188 ci->set_elapsed(0); 206 ci->set_elapsed(0);
189 ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE ); 207 ci->advance_buffer(data_offset);
190 } 208 }
191 209
192 /* The main decoding loop */ 210 /* The main decoding loop */
193 while((unsigned)rmctx.audio_pkt_cnt < rmctx.nb_packets) { 211 while ((rmctx.flags & RM_RAW_DATASTREAM) || (unsigned)rmctx.audio_pkt_cnt < rmctx.nb_packets) {
194 if (action == CODEC_ACTION_NULL) 212 if (action == CODEC_ACTION_NULL)
195 action = ci->get_command(&param); 213 action = ci->get_command(&param);
196 214
@@ -198,34 +216,69 @@ enum codec_status codec_run(void)
198 break; 216 break;
199 217
200 if (action == CODEC_ACTION_SEEK_TIME) { 218 if (action == CODEC_ACTION_SEEK_TIME) {
219 /* Do not allow seeking beyond the file's length */
220 if ((unsigned) param > ci->id3->length) {
221 ci->set_elapsed(ci->id3->length);
222 ci->seek_complete();
223 break;
224 }
225
226 if (n)
227 rm_ac3_swap_bytes(filebuf, (rmctx.flags & RM_RAW_DATASTREAM) ? n : rmctx.block_align);
201 packet_offset = param / ((rmctx.block_align*8*1000)/rmctx.bit_rate); 228 packet_offset = param / ((rmctx.block_align*8*1000)/rmctx.bit_rate);
202 ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + 229 ci->seek_buffer(data_offset + packet_offset * packet_size);
203 packet_offset*(rmctx.block_align + PACKET_HEADER_SIZE));
204 rmctx.audio_pkt_cnt = packet_offset; 230 rmctx.audio_pkt_cnt = packet_offset;
205 samplesdone = (rmctx.sample_rate/1000 * param); 231 samplesdone = packet_offset * A52_SAMPLESPERFRAME;
206 ci->set_elapsed(samplesdone/(frequency/1000)); 232 ci->set_elapsed(samplesdone/(ci->id3->frequency/1000));
207 ci->seek_complete(); 233 ci->seek_complete();
234 a52_decoder_reset();
235 consumed = 0;
236 n = 0;
208 } 237 }
209 238
210 action = CODEC_ACTION_NULL; 239 action = CODEC_ACTION_NULL;
211 240
212 filebuf = ci->request_buffer(&n, rmctx.block_align + PACKET_HEADER_SIZE); 241 if (rmctx.flags & RM_RAW_DATASTREAM) {
213 consumed = rm_get_packet(&filebuf, &rmctx, &pkt); 242 if (n > consumed) {
214 243 consumed += a52_decode_data(filebuf + consumed, filebuf + n);
215 if(consumed < 0 && playback_on != 0) { 244 ci->set_offset(ci->curpos + consumed);
216 if(playback_on == -1) {
217 /* Error only if packet-parsing failed and playback hadn't started */
218 DEBUGF("rm_get_packet failed\n");
219 return CODEC_ERROR;
220 } 245 }
221 else { 246 else {
222 break; 247 if (n) {
248 rm_ac3_swap_bytes(filebuf, n);
249 ci->advance_buffer(n);
250 }
251 filebuf = ci->request_buffer(&n, BUFFER_SIZE);
252 if (n == 0)
253 break;
254 rm_ac3_swap_bytes(filebuf, n);
255 consumed = 0;
223 } 256 }
224 } 257 }
258 else {
259 filebuf = ci->request_buffer(&n, packet_size);
260
261 if (n == 0)
262 break;
263
264 if (rm_get_packet(&filebuf, &rmctx, &pkt) < 0 && playback_on != 0) {
265 if(playback_on == -1) {
266 /* Error only if packet-parsing failed and playback hadn't started */
267 DEBUGF("rm_get_packet failed\n");
268 return CODEC_ERROR;
269 }
270 else {
271 break;
272 }
273 }
225 274
226 playback_on = 1; 275 playback_on = 1;
227 a52_decode_data(filebuf, filebuf + rmctx.block_align); 276 consumed = 0;
228 ci->advance_buffer(pkt.length); 277 while (consumed < rmctx.block_align)
278 consumed += a52_decode_data(filebuf + consumed, filebuf + rmctx.block_align);
279 rm_ac3_swap_bytes(filebuf, rmctx.block_align);
280 ci->advance_buffer(pkt.length);
281 }
229 } 282 }
230 283
231 return CODEC_OK; 284 return CODEC_OK;
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;
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;
diff --git a/lib/rbcodec/codecs/librm/rm.c b/lib/rbcodec/codecs/librm/rm.c
index eabbe5d92a..e499961a7f 100644
--- a/lib/rbcodec/codecs/librm/rm.c
+++ b/lib/rbcodec/codecs/librm/rm.c
@@ -27,8 +27,6 @@
27#include "codeclib.h" 27#include "codeclib.h"
28#endif 28#endif
29 29
30#define SWAP(a, b) do{uint8_t SWAP_tmp= b; b= a; a= SWAP_tmp;}while(0)
31
32#ifdef TEST 30#ifdef TEST
33#include <fcntl.h> 31#include <fcntl.h>
34#include <unistd.h> 32#include <unistd.h>
@@ -500,17 +498,33 @@ void rm_get_packet_fd(int fd,RMContext *rmctx, RMPacket *pkt)
500} 498}
501#endif /*TEST*/ 499#endif /*TEST*/
502 500
501void rm_ac3_swap_bytes(uint8_t *buf, int bufsize)
502{
503 uint8_t *bufptr;
504 for (bufptr = buf; bufptr < buf + bufsize - 1; bufptr += 2)
505 {
506 bufptr[0] ^= bufptr[1];
507 bufptr[1] ^= bufptr[0];
508 bufptr[0] ^= bufptr[1];
509 }
510}
511
503int rm_get_packet(uint8_t **src,RMContext *rmctx, RMPacket *pkt) 512int rm_get_packet(uint8_t **src,RMContext *rmctx, RMPacket *pkt)
504{ 513{
505 int consumed = 0; 514 int consumed = 0;
515 int headerlen;
506 /* rockbox: comment 'set but unused' variables 516 /* rockbox: comment 'set but unused' variables
507 uint8_t unknown; 517 uint8_t unknown;
508 */ 518 */
509 uint16_t x, place; 519 uint16_t x;
510 uint16_t sps = rmctx->sub_packet_size; 520 uint16_t sps = rmctx->sub_packet_size;
511 uint16_t h = rmctx->sub_packet_h; 521 uint16_t h = rmctx->sub_packet_h;
512 uint16_t y = rmctx->sub_packet_cnt; 522 uint16_t y = 0;
513 uint16_t w = rmctx->audio_framesize; 523 uint16_t w = rmctx->audio_framesize;
524
525 rmctx->sub_packet_cnt = 0;
526 rmctx->audio_pkt_cnt = 0;
527
514 do 528 do
515 { 529 {
516 y = rmctx->sub_packet_cnt; 530 y = rmctx->sub_packet_cnt;
@@ -523,6 +537,7 @@ int rm_get_packet(uint8_t **src,RMContext *rmctx, RMPacket *pkt)
523 return -1; 537 return -1;
524 } 538 }
525 539
540 headerlen = PACKET_HEADER_SIZE + (pkt->version ? 1 : 0);
526 pkt->length = rm_get_uint16be(*src+2); 541 pkt->length = rm_get_uint16be(*src+2);
527 pkt->stream_number = rm_get_uint16be(*src+4); 542 pkt->stream_number = rm_get_uint16be(*src+4);
528 pkt->timestamp = rm_get_uint32be(*src+6); 543 pkt->timestamp = rm_get_uint32be(*src+6);
@@ -534,25 +549,27 @@ int rm_get_packet(uint8_t **src,RMContext *rmctx, RMPacket *pkt)
534 pkt->flags = rm_get_uint8(*src+11); 549 pkt->flags = rm_get_uint8(*src+11);
535 550
536 if(pkt->version == 1) 551 if(pkt->version == 1)
537 /* unknown = */ rm_get_uint8(*src+10); 552 /* unknown = */ rm_get_uint8(*src+12);
538 553
539 if (pkt->flags & 2) /* keyframe */ 554 if (pkt->flags & 2) { /* keyframe */
540 y = rmctx->sub_packet_cnt = 0; 555 if (y)
556 return consumed;
557 y = 0;
558 }
541 if (!y) 559 if (!y)
542 rmctx->audiotimestamp = pkt->timestamp; 560 rmctx->audiotimestamp = pkt->timestamp;
543 561
544 /* Skip packet header */ 562 /* Skip packet header */
545 advance_buffer(src, PACKET_HEADER_SIZE); 563 advance_buffer(src, headerlen);
546 consumed += PACKET_HEADER_SIZE; 564 consumed += headerlen;
547 if (rmctx->codec_type == CODEC_COOK || rmctx->codec_type == CODEC_ATRAC) { 565 if (rmctx->codec_type == CODEC_COOK || rmctx->codec_type == CODEC_ATRAC) {
548 for(x = 0 ; x < w/sps; x++) 566 for(x = 0 ; x < w/sps; x++)
549 { 567 {
550 place = sps*(h*x+((h+1)/2)*(y&1)+(y>>1)); 568 pkt->frames[h*x+((h+1)/2)*(y&1)+(y>>1)] = *src;
551 pkt->frames[place/sps] = *src;
552 advance_buffer(src,sps); 569 advance_buffer(src,sps);
553 consumed += sps; 570 consumed += sps;
554 } 571 }
555 } 572 }
556 else if (rmctx->codec_type == CODEC_AAC) { 573 else if (rmctx->codec_type == CODEC_AAC) {
557 rmctx->sub_packet_cnt = (rm_get_uint16be(*src) & 0xf0) >> 4; 574 rmctx->sub_packet_cnt = (rm_get_uint16be(*src) & 0xf0) >> 4;
558 advance_buffer(src, 2); 575 advance_buffer(src, 2);
@@ -563,22 +580,22 @@ int rm_get_packet(uint8_t **src,RMContext *rmctx, RMPacket *pkt)
563 advance_buffer(src, 2); 580 advance_buffer(src, 2);
564 consumed += 2; 581 consumed += 2;
565 } 582 }
566 rmctx->audio_pkt_cnt = --rmctx->sub_packet_cnt; 583 rmctx->audio_pkt_cnt = rmctx->sub_packet_cnt;
567 } 584 }
585 break;
568 } 586 }
569 587
570 else if (rmctx->codec_type == CODEC_AC3) { 588 else if (rmctx->codec_type == CODEC_AC3) {
571 /* The byte order of the data is reversed from standard AC3 */ 589 /* The byte order of the data is reversed from standard AC3 */
572 for(x = 0; x < pkt->length - PACKET_HEADER_SIZE; x+=2) { 590 rm_ac3_swap_bytes(*src, pkt->length - headerlen);
573 SWAP((*src)[0], (*src)[1]); 591 break;
574 *src += 2;
575 }
576 *src -= x;
577 } 592 }
593 else return -1; /* invalid codec type */
594
578 rmctx->audio_pkt_cnt++; 595 rmctx->audio_pkt_cnt++;
579 }while(++(rmctx->sub_packet_cnt) < h); 596 }while(++(rmctx->sub_packet_cnt) < h);
580 597
581return consumed; 598 return consumed;
582} 599}
583 600
584#ifdef DEBUG 601#ifdef DEBUG
@@ -587,6 +604,6 @@ void dump_rm_context(RMContext *rmctx)
587 DEBUGF("block_align = %d\n", rmctx->block_align); 604 DEBUGF("block_align = %d\n", rmctx->block_align);
588 DEBUGF("nb_channels = %d\n", rmctx->nb_channels); 605 DEBUGF("nb_channels = %d\n", rmctx->nb_channels);
589 DEBUGF("sample_rate = %d\n", rmctx->sample_rate); 606 DEBUGF("sample_rate = %d\n", rmctx->sample_rate);
590 DEBUGF("bit_rate = %d\n", rmctx->bit_rate ); 607 DEBUGF("bit_rate = %ld\n", rmctx->bit_rate );
591} 608}
592#endif 609#endif
diff --git a/lib/rbcodec/codecs/librm/rm.h b/lib/rbcodec/codecs/librm/rm.h
index c4a4e3a77e..47ea559f2e 100644
--- a/lib/rbcodec/codecs/librm/rm.h
+++ b/lib/rbcodec/codecs/librm/rm.h
@@ -25,6 +25,9 @@
25#include <inttypes.h> 25#include <inttypes.h>
26#include "bytestream.h" 26#include "bytestream.h"
27 27
28#define RM_RAW_DATASTREAM 0x0100
29#define RM_PKT_V1 0x0200
30
28#define MAX_EXTRADATA_SIZE 16 31#define MAX_EXTRADATA_SIZE 16
29#define DATA_HEADER_SIZE 18 32#define DATA_HEADER_SIZE 18
30#define PACKET_HEADER_SIZE 12 33#define PACKET_HEADER_SIZE 12
@@ -86,6 +89,8 @@ typedef struct rm_context
86 89
87int real_parse_header(int fd, RMContext *rmctx); 90int real_parse_header(int fd, RMContext *rmctx);
88 91
92void rm_ac3_swap_bytes(uint8_t *buf, int bufsize);
93
89/* Get a (sub_packet_h*frames_per_packet) number of audio frames from a memory buffer */ 94/* Get a (sub_packet_h*frames_per_packet) number of audio frames from a memory buffer */
90int rm_get_packet(uint8_t **src,RMContext *rmctx, RMPacket *pkt); 95int rm_get_packet(uint8_t **src,RMContext *rmctx, RMPacket *pkt);
91 96
diff --git a/lib/rbcodec/codecs/raac.c b/lib/rbcodec/codecs/raac.c
index e77d432680..6856afc52e 100644
--- a/lib/rbcodec/codecs/raac.c
+++ b/lib/rbcodec/codecs/raac.c
@@ -109,7 +109,8 @@ enum codec_status codec_run(void)
109 if (resume_offset) { 109 if (resume_offset) {
110 resume_offset -= MIN(resume_offset, rmctx.data_offset + DATA_HEADER_SIZE); 110 resume_offset -= MIN(resume_offset, rmctx.data_offset + DATA_HEADER_SIZE);
111 /* put number of subpackets to skip in resume_offset */ 111 /* put number of subpackets to skip in resume_offset */
112 resume_offset /= (rmctx.block_align + PACKET_HEADER_SIZE); 112 resume_offset /= (rmctx.block_align + PACKET_HEADER_SIZE +
113 ((rmctx.flags & RM_PKT_V1) ? 1 : 0));
113 param = (int)resume_offset * ((rmctx.block_align * 8 * 1000)/rmctx.bit_rate); 114 param = (int)resume_offset * ((rmctx.block_align * 8 * 1000)/rmctx.bit_rate);
114 } 115 }
115 116
diff --git a/lib/rbcodec/metadata/metadata.c b/lib/rbcodec/metadata/metadata.c
index 87ea922788..7ca4b1afd2 100644
--- a/lib/rbcodec/metadata/metadata.c
+++ b/lib/rbcodec/metadata/metadata.c
@@ -444,13 +444,13 @@ bool get_metadata(struct mp3entry* id3, int fd, const char* trackname)
444 /* Load codec specific track tag information and confirm the codec type. */ 444 /* Load codec specific track tag information and confirm the codec type. */
445 if (!entry->parse_func) 445 if (!entry->parse_func)
446 { 446 {
447 DEBUGF("nothing to parse for %s (format %s)", trackname, entry->label); 447 DEBUGF("nothing to parse for %s (format %s)\n", trackname, entry->label);
448 return false; 448 return false;
449 } 449 }
450 450
451 if (!entry->parse_func(fd, id3)) 451 if (!entry->parse_func(fd, id3))
452 { 452 {
453 DEBUGF("parsing %s failed (format: %s)", trackname, entry->label); 453 DEBUGF("parsing %s failed (format: %s)\n", trackname, entry->label);
454 return false; 454 return false;
455 } 455 }
456 456
diff --git a/lib/rbcodec/metadata/rm.c b/lib/rbcodec/metadata/rm.c
index 2a5a2892a3..1e33f0b0ac 100644
--- a/lib/rbcodec/metadata/rm.c
+++ b/lib/rbcodec/metadata/rm.c
@@ -89,7 +89,7 @@ static char* fourcc2str(uint32_t f)
89} 89}
90#endif 90#endif
91 91
92static inline int real_read_audio_stream_info(int fd, RMContext *rmctx) 92static int real_read_audio_stream_info(int fd, RMContext *rmctx)
93{ 93{
94 int skipped = 0; 94 int skipped = 0;
95 uint32_t version; 95 uint32_t version;
@@ -111,6 +111,7 @@ static inline int real_read_audio_stream_info(int fd, RMContext *rmctx)
111 DEBUGF(" version=0x%04lx\n",((version >> 16) & 0xff)); 111 DEBUGF(" version=0x%04lx\n",((version >> 16) & 0xff));
112 if (((version >> 16) & 0xff) == 3) { 112 if (((version >> 16) & 0xff) == 3) {
113 /* Very old version */ 113 /* Very old version */
114 return -1;
114 } else { 115 } else {
115#ifdef SIMULATOR 116#ifdef SIMULATOR
116 real_read_object_header(fd, &obj); 117 real_read_object_header(fd, &obj);
@@ -218,7 +219,7 @@ static inline int real_read_audio_stream_info(int fd, RMContext *rmctx)
218 return skipped; 219 return skipped;
219} 220}
220 221
221static int rm_parse_header(int fd, RMContext *rmctx, struct mp3entry *id3) 222static inline int rm_parse_header(int fd, RMContext *rmctx, struct mp3entry *id3)
222{ 223{
223 struct real_object_t obj; 224 struct real_object_t obj;
224 int res; 225 int res;
@@ -242,6 +243,7 @@ static int rm_parse_header(int fd, RMContext *rmctx, struct mp3entry *id3)
242 uint32_t max_bitrate; 243 uint32_t max_bitrate;
243 uint16_t num_streams; 244 uint16_t num_streams;
244 uint32_t next_data_off; 245 uint32_t next_data_off;
246 uint16_t pkt_version;
245 uint8_t header_end; 247 uint8_t header_end;
246 248
247 memset(&obj,0,sizeof(obj)); 249 memset(&obj,0,sizeof(obj));
@@ -250,6 +252,35 @@ static int rm_parse_header(int fd, RMContext *rmctx, struct mp3entry *id3)
250 252
251 if (obj.fourcc == FOURCC('.','r','a',0xfd)) 253 if (obj.fourcc == FOURCC('.','r','a',0xfd))
252 { 254 {
255 lseek(fd, 4, SEEK_SET);
256 skipped = real_read_audio_stream_info(fd, rmctx);
257 if (skipped > 0 && rmctx->codec_type == CODEC_AC3)
258 {
259 read_uint8(fd,&len);
260 skipped += (int)read_string(fd, id3->id3v1buf[0], sizeof(id3->id3v1buf[0]), '\0', len);
261 read_uint8(fd,&len);
262 skipped += (int)read_string(fd, id3->id3v1buf[1], sizeof(id3->id3v1buf[1]), '\0', len);
263 read_uint8(fd,&len);
264 skipped += (int)read_string(fd, id3->id3v1buf[2], sizeof(id3->id3v1buf[2]), '\0', len);
265 read_uint8(fd,&len);
266 skipped += (int)read_string(fd, id3->id3v1buf[3], sizeof(id3->id3v1buf[3]), '\0', len);
267 rmctx->data_offset = skipped + 8;
268 rmctx->bit_rate = rmctx->block_align * rmctx->sample_rate / 192;
269 if (rmctx->block_align)
270 rmctx->nb_packets = (filesize(fd) - rmctx->data_offset) / rmctx->block_align;
271 if (rmctx->sample_rate)
272 rmctx->duration = (uint32_t)(256LL * 6 * 1000 * rmctx->nb_packets / rmctx->sample_rate);
273 rmctx->flags |= RM_RAW_DATASTREAM;
274
275 DEBUGF(" data_offset = %ld\n",rmctx->data_offset);
276 DEBUGF(" avg_bitrate = %ld\n",rmctx->bit_rate);
277 DEBUGF(" duration = %ld\n",rmctx->duration);
278 DEBUGF(" title=\"%s\"\n",id3->id3v1buf[0]);
279 DEBUGF(" author=\"%s\"\n",id3->id3v1buf[1]);
280 DEBUGF(" copyright=\"%s\"\n",id3->id3v1buf[2]);
281 DEBUGF(" comment=\"%s\"\n",id3->id3v1buf[3]);
282 return 0;
283 }
253 /* Very old .ra format - not yet supported */ 284 /* Very old .ra format - not yet supported */
254 return -1; 285 return -1;
255 } 286 }
@@ -305,6 +336,8 @@ static int rm_parse_header(int fd, RMContext *rmctx, struct mp3entry *id3)
305 DEBUGF(" data_offset = %ld\n",rmctx->data_offset); 336 DEBUGF(" data_offset = %ld\n",rmctx->data_offset);
306 DEBUGF(" num_streams = %d\n",num_streams); 337 DEBUGF(" num_streams = %d\n",num_streams);
307 DEBUGF(" flags=0x%04x\n",rmctx->flags); 338 DEBUGF(" flags=0x%04x\n",rmctx->flags);
339
340 rmctx->flags &= 0x00FF;
308 break; 341 break;
309 342
310 case FOURCC('C','O','N','T'): 343 case FOURCC('C','O','N','T'):
@@ -409,7 +442,22 @@ static int rm_parse_header(int fd, RMContext *rmctx, struct mp3entry *id3)
409 442
410 DEBUGF(" data_nb_packets = %ld\n",rmctx->nb_packets); 443 DEBUGF(" data_nb_packets = %ld\n",rmctx->nb_packets);
411 DEBUGF(" next DATA offset = %ld\n",next_data_off); 444 DEBUGF(" next DATA offset = %ld\n",next_data_off);
412 header_end = 1; 445
446 if (!next_data_off)
447 {
448 if (rmctx->duration == 0 && rmctx->bit_rate != 0)
449 {
450 rmctx->duration = (uint32_t)(8000LL * rmctx->nb_packets * rmctx->block_align / rmctx->bit_rate);
451 DEBUGF(" estimated duration = %ld\n",rmctx->duration);
452 }
453 read_uint16be(fd, &pkt_version);
454 skipped += 2;
455 DEBUGF(" pkt_version=0x%04x\n", pkt_version);
456 if (pkt_version)
457 rmctx->flags |= RM_PKT_V1;
458 rmctx->data_offset = curpos;
459 header_end = 1;
460 }
413 break; 461 break;
414 } 462 }
415 if(header_end) break; 463 if(header_end) break;
@@ -456,7 +504,7 @@ bool get_rm_metadata(int fd, struct mp3entry* id3)
456 504
457 id3->channels = rmctx->nb_channels; 505 id3->channels = rmctx->nb_channels;
458 id3->extradata_size = rmctx->extradata_size; 506 id3->extradata_size = rmctx->extradata_size;
459 id3->bitrate = rmctx->bit_rate / 1000; 507 id3->bitrate = (rmctx->bit_rate + 500) / 1000;
460 id3->frequency = rmctx->sample_rate; 508 id3->frequency = rmctx->sample_rate;
461 id3->length = rmctx->duration; 509 id3->length = rmctx->duration;
462 id3->filesize = filesize(fd); 510 id3->filesize = filesize(fd);