summaryrefslogtreecommitdiff
path: root/apps/mp3data.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/mp3data.c')
-rw-r--r--apps/mp3data.c130
1 files changed, 91 insertions, 39 deletions
diff --git a/apps/mp3data.c b/apps/mp3data.c
index bb42c94fc6..89af49849f 100644
--- a/apps/mp3data.c
+++ b/apps/mp3data.c
@@ -39,6 +39,7 @@
39#include "mp3data.h" 39#include "mp3data.h"
40#include "file.h" 40#include "file.h"
41#include "buffer.h" 41#include "buffer.h"
42#include "metadata/metadata_common.h"
42 43
43// #define DEBUG_VERBOSE 44// #define DEBUG_VERBOSE
44 45
@@ -201,39 +202,74 @@ static bool mp3headerinfo(struct mp3info *info, unsigned long header)
201 return true; 202 return true;
202} 203}
203 204
205static bool headers_have_same_type(unsigned long header1,
206 unsigned long header2)
207{
208 /* Compare MPEG version, layer and sampling frequency. If header1 is zero
209 * it is assumed the headers are of same type. */
210 unsigned int mask = 0xfffe0c00;
211 header1 &= mask;
212 header2 &= mask;
213 return header1 ? (header1 == header2) : true;
214}
215
204static unsigned long __find_next_frame(int fd, long *offset, long max_offset, 216static unsigned long __find_next_frame(int fd, long *offset, long max_offset,
205 unsigned long last_header, 217 unsigned long reference_header,
206 int(*getfunc)(int fd, unsigned char *c)) 218 int(*getfunc)(int fd, unsigned char *c),
219 bool single_header)
207{ 220{
208 unsigned long header=0; 221 unsigned long header=0;
209 unsigned char tmp; 222 unsigned char tmp;
210 int i; 223 long pos = 0;
211
212 long pos = 0;
213
214 /* We remember the last header we found, to use as a template to see if
215 the header we find has the same frequency, layer etc */
216 last_header &= 0xffff0c00;
217
218 /* Fill up header with first 24 bits */
219 for(i = 0; i < 3; i++) {
220 header <<= 8;
221 if(!getfunc(fd, &tmp))
222 return 0;
223 header |= tmp;
224 pos++;
225 }
226 224
225 /* We will search until we find two consecutive MPEG frame headers with
226 * the same MPEG version, layer and sampling frequency. The first header
227 * of this pair is assumed to be the first valid MPEG frame header of the
228 * whole stream. */
227 do { 229 do {
230 /* Read 1 new byte. */
228 header <<= 8; 231 header <<= 8;
229 if(!getfunc(fd, &tmp)) 232 if (!getfunc(fd, &tmp))
230 return 0; 233 return 0;
231 header |= tmp; 234 header |= tmp;
232 pos++; 235 pos++;
233 if(max_offset > 0 && pos > max_offset) 236
237 /* Abort if max_offset is reached. Stop parsing. */
238 if (max_offset > 0 && pos > max_offset)
234 return 0; 239 return 0;
235 } while(!is_mp3frameheader(header) || 240
236 (last_header?((header & 0xffff0c00) != last_header):false)); 241 if (is_mp3frameheader(header)) {
242 if (single_header) {
243 /* We search for one _single_ valid header that has the same
244 * type as the reference_header (if reference_header != 0).
245 * In this case we are finished. */
246 if (headers_have_same_type(reference_header, header))
247 break;
248 } else {
249 /* The current header is valid. Now gather the frame size,
250 * seek to this byte position and check if there is another
251 * valid MPEG frame header of the same type. */
252 struct mp3info info;
253
254 /* Gather frame size from given header and seek to next
255 * frame header. */
256 mp3headerinfo(&info, header);
257 lseek(fd, info.frame_size-4, SEEK_CUR);
258
259 /* Read possible next frame header and seek back to last frame
260 * headers byte position. */
261 reference_header = 0;
262 read_uint32be(fd, (uint32_t*)&reference_header);
263 lseek(fd, -info.frame_size, SEEK_CUR);
264
265 /* If the current header is of the same type as the previous
266 * header we are finished. */
267 if (headers_have_same_type(header, reference_header))
268 break;
269 }
270 }
271
272 } while (true);
237 273
238 *offset = pos - 4; 274 *offset = pos - 4;
239 275
@@ -248,9 +284,13 @@ static int fileread(int fd, unsigned char *c)
248 return read(fd, c, 1); 284 return read(fd, c, 1);
249} 285}
250 286
251unsigned long find_next_frame(int fd, long *offset, long max_offset, unsigned long last_header) 287unsigned long find_next_frame(int fd,
288 long *offset,
289 long max_offset,
290 unsigned long reference_header)
252{ 291{
253 return __find_next_frame(fd, offset, max_offset, last_header, fileread); 292 return __find_next_frame(fd, offset, max_offset, reference_header,
293 fileread, true);
254} 294}
255 295
256#ifndef __PCTOOL__ 296#ifndef __PCTOOL__
@@ -312,10 +352,9 @@ static void buf_init(void)
312 fnf_read_index = 0; 352 fnf_read_index = 0;
313} 353}
314 354
315static unsigned long buf_find_next_frame(int fd, long *offset, long max_offset, 355static unsigned long buf_find_next_frame(int fd, long *offset, long max_offset)
316 unsigned long last_header)
317{ 356{
318 return __find_next_frame(fd, offset, max_offset, last_header, buf_getbyte); 357 return __find_next_frame(fd, offset, max_offset, 0, buf_getbyte, true);
319} 358}
320 359
321static int audiobuflen; 360static int audiobuflen;
@@ -337,15 +376,18 @@ static int mem_getbyte(int dummy, unsigned char *c)
337 return 1; 376 return 1;
338} 377}
339 378
340unsigned long mem_find_next_frame(int startpos, long *offset, long max_offset, 379unsigned long mem_find_next_frame(int startpos,
341 unsigned long last_header) 380 long *offset,
381 long max_offset,
382 unsigned long reference_header)
342{ 383{
343 audiobuflen = audiobufend - audiobuf; 384 audiobuflen = audiobufend - audiobuf;
344 mem_pos = startpos; 385 mem_pos = startpos;
345 mem_cnt = 0; 386 mem_cnt = 0;
346 mem_maxlen = max_offset; 387 mem_maxlen = max_offset;
347 388
348 return __find_next_frame(0, offset, max_offset, last_header, mem_getbyte); 389 return __find_next_frame(0, offset, max_offset, reference_header,
390 mem_getbyte, true);
349} 391}
350#endif 392#endif
351 393
@@ -446,17 +488,20 @@ static void get_vbri_info(struct mp3info *info, unsigned char *buf)
446} 488}
447 489
448/* Seek to next mpeg header and extract relevant information. */ 490/* Seek to next mpeg header and extract relevant information. */
449static int get_next_header_info(int fd, long *bytecount, struct mp3info *info) 491static int get_next_header_info(int fd, long *bytecount, struct mp3info *info,
492 bool single_header)
450{ 493{
451 long tmp; 494 long tmp;
452 unsigned long header = find_next_frame(fd, &tmp, 0x20000, 0); 495 unsigned long header = 0;
496
497 header = __find_next_frame(fd, &tmp, 0x20000, 0, fileread, single_header);
453 if(header == 0) 498 if(header == 0)
454 return -1; 499 return -1;
455 500
456 if(!mp3headerinfo(info, header)) 501 if(!mp3headerinfo(info, header))
457 return -2; 502 return -2;
458 503
459 /* Next header is tmp bytes away. */ 504 /* Next frame header is tmp bytes away. */
460 *bytecount += tmp; 505 *bytecount += tmp;
461 506
462 return 0; 507 return 0;
@@ -478,8 +523,8 @@ int get_mp3file_info(int fd, struct mp3info *info)
478 info->enc_padding = -1; 523 info->enc_padding = -1;
479#endif 524#endif
480 525
481 /* Get the very first MPEG frame. */ 526 /* Get the very first single MPEG frame. */
482 result = get_next_header_info(fd, &bytecount, info); 527 result = get_next_header_info(fd, &bytecount, info, true);
483 if(result) 528 if(result)
484 return result; 529 return result;
485 530
@@ -514,7 +559,7 @@ int get_mp3file_info(int fd, struct mp3info *info)
514 bytecount += info->frame_size; 559 bytecount += info->frame_size;
515 560
516 /* Now get the next frame to read the real info about the mp3 stream */ 561 /* Now get the next frame to read the real info about the mp3 stream */
517 result = get_next_header_info(fd, &bytecount, info); 562 result = get_next_header_info(fd, &bytecount, info, false);
518 if(result) 563 if(result)
519 return result; 564 return result;
520 565
@@ -528,7 +573,7 @@ int get_mp3file_info(int fd, struct mp3info *info)
528 bytecount += info->frame_size; 573 bytecount += info->frame_size;
529 574
530 /* Now get the next frame to read the real info about the mp3 stream */ 575 /* Now get the next frame to read the real info about the mp3 stream */
531 result = get_next_header_info(fd, &bytecount, info); 576 result = get_next_header_info(fd, &bytecount, info, false);
532 if(result) 577 if(result)
533 return result; 578 return result;
534 579
@@ -537,6 +582,13 @@ int get_mp3file_info(int fd, struct mp3info *info)
537 else 582 else
538 { 583 {
539 VDEBUGF("-- No VBR header --\n"); 584 VDEBUGF("-- No VBR header --\n");
585
586 /* There was no VBR header found. So, we seek back to beginning and
587 * search for the first MPEG frame header of the mp3 stream. */
588 lseek(fd, -info->frame_size, SEEK_CUR);
589 result = get_next_header_info(fd, &bytecount, info, false);
590 if(result)
591 return result;
540 } 592 }
541 593
542 return bytecount; 594 return bytecount;
@@ -574,7 +626,7 @@ int count_mp3_frames(int fd, int startpos, int filesize,
574 num_frames = 0; 626 num_frames = 0;
575 cnt = 0; 627 cnt = 0;
576 628
577 while((header = buf_find_next_frame(fd, &bytes, -1, header_template))) { 629 while((header = buf_find_next_frame(fd, &bytes, header_template))) {
578 mp3headerinfo(&info, header); 630 mp3headerinfo(&info, header);
579 631
580 if(!header_template) 632 if(!header_template)
@@ -649,7 +701,7 @@ int create_xing_header(int fd, long startpos, long filesize,
649 /* Advance from the last seek point to this one */ 701 /* Advance from the last seek point to this one */
650 for(j = 0;j < pos - last_pos;j++) 702 for(j = 0;j < pos - last_pos;j++)
651 { 703 {
652 header = buf_find_next_frame(fd, &bytes, -1, header_template); 704 header = buf_find_next_frame(fd, &bytes, header_template);
653 filepos += bytes; 705 filepos += bytes;
654 mp3headerinfo(&info, header); 706 mp3headerinfo(&info, header);
655 buf_seek(fd, info.frame_size-4); 707 buf_seek(fd, info.frame_size-4);