/* parse.c - compact version of famous library mpg123 Copyright (C) 2017 Uncle Mike This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ #include "mpeghead.h" #include "mpg123.h" #include "getbits.h" #include <limits.h> #define TRACK_MAX_FRAMES (ULONG_MAX / 4 / 1152) #define FORGET_INTERVAL 1024 // used by callers to set forget flag each <n> bytes. // use 4 bytes from buf to construct 28bit uint value and return 1; return 0 if bytes are not synchsafe #define synchsafe_to_long( buf, res ) \ ((((buf)[0]|(buf)[1]|(buf)[2]|(buf)[3]) & 0x80) ? \ 0 : (res = (((ulong)(buf)[0]) << 21) | (((ulong)(buf)[1]) << 14)|(((ulong)(buf)[2]) << 7)|((ulong)(buf)[3]), 1 )) #define check_bytes_left( n ) if( fr->framesize < lame_offset + n ) \ goto check_lame_tag_yes // PARSE_GOOD and PARSE_BAD have to be 1 and 0 (TRUE and FALSE), others can vary. enum parse_codes { PARSE_MORE = MPG123_NEED_MORE, PARSE_ERR = MPG123_ERR, PARSE_END = 10, /* No more audio data to find. */ PARSE_GOOD = 1, /* Everything's fine. */ PARSE_BAD = 0, /* Not fine (invalid data). */ PARSE_RESYNC = 2, /* Header not good, go into resync. */ PARSE_AGAIN = 3, /* Really start over, throw away and read a new header, again. */ }; // bitrates for [mpeg1/2][layer] static const int tabsel_123[2][3][16] = { { {0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,}, {0,32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384,}, {0,32,40,48, 56, 64, 80, 96,112,128,160,192,224,256,320,} }, { {0,32,48,56,64,80,96,112,128,144,160,176,192,224,256,}, {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,}, {0,8,16,24,32,40,48,56,64,80,96,112,128,144,160,} } }; static const long freqs[9] = { 44100, 48000, 32000, 22050, 24000, 16000 , 11025 , 12000 , 8000 }; void set_pointer( mpg123_handle_t *fr, long backstep ) { fr->wordpointer = fr->bsbuf + fr->ssize - backstep; if( backstep ) memcpy( fr->wordpointer, fr->bsbufold + fr->fsizeold - backstep, backstep ); fr->bitindex = 0; } int frame_bitrate( mpg123_handle_t *fr ) { return tabsel_123[fr->lsf][fr->lay-1][fr->bitrate_index]; } long frame_freq( mpg123_handle_t *fr ) { return freqs[fr->sampling_frequency]; } double compute_bpf( mpg123_handle_t *fr ) { double bpf; switch( fr->lay ) { case 1: bpf = tabsel_123[fr->lsf][0][fr->bitrate_index]; bpf *= 12000.0 * 4.0; bpf /= freqs[fr->sampling_frequency] << (fr->lsf); break; case 2: case 3: bpf = tabsel_123[fr->lsf][fr->lay-1][fr->bitrate_index]; bpf *= 144000; bpf /= freqs[fr->sampling_frequency] << (fr->lsf); break; default: bpf = 1.0; } return bpf; } int mpg123_spf( mpg123_handle_t *mh ) { if( mh == NULL ) return MPG123_ERR; return mh->firsthead ? mh->spf : MPG123_ERR; } double mpg123_tpf( mpg123_handle_t *fr ) { static int bs[4] = { 0,384, 1152, 1152 }; double tpf; if( fr == NULL || !fr->firsthead ) return MPG123_ERR; tpf = (double)bs[fr->lay]; tpf /= freqs[fr->sampling_frequency] << (fr->lsf); return tpf; } int get_songlen( mpg123_handle_t *fr, int no ) { double tpf; if( !fr ) return 0; if( no < 0 ) { if( !fr->rd || fr->rdat.filelen < 0 ) return 0; no = (int)((double)fr->rdat.filelen / compute_bpf( fr )); } tpf = mpg123_tpf( fr ); return (int)(no * tpf); } // just tell if the header is some mono. static int header_mono( ulong newhead ) { return HDR_CHANNEL_VAL( newhead ) == MPG_MD_MONO ? TRUE : FALSE; } static int head_check(ulong head) { if((( head & HDR_SYNC ) != HDR_SYNC ) || (!(HDR_LAYER_VAL(head))) || (HDR_BITRATE_VAL(head) == 0xf) || (HDR_SAMPLERATE_VAL(head) == 0x3 )) return FALSE; return TRUE; } // true if the two headers will work with the same decoding routines static int head_compatible( ulong fred, ulong bret ) { return (( fred & HDR_CMPMASK ) == ( bret & HDR_CMPMASK ) && header_mono( fred ) == header_mono( bret )); } // this is moderately sized buffers. Int offset is enough. static ulong bit_read_long( byte *buf, int *offset ) { ulong val = (((ulong)buf[*offset]) << 24) | (((ulong) buf[*offset+1]) << 16) | (((ulong) buf[*offset+2]) << 8) | ((ulong)buf[*offset+3]); *offset += 4; return val; } static word bit_read_short( byte *buf, int *offset ) { word val = (((word) buf[*offset] ) << 8) | ((word) buf[*offset+1]); *offset += 2; return val; } static int check_lame_tag( mpg123_handle_t *fr ) { int lame_offset = (fr->stereo == 2) ? (fr->lsf ? 17 : 32) : (fr->lsf ? 9 : 17); ulong xing_flags; ulong long_tmp; int i; // going to look for Xing or Info at some position after the header // MPEG 1 MPEG 2/2.5 (LSF) // Stereo, Joint Stereo, Dual Channel 32 17 // Mono 17 9 if( fr->p.flags & MPG123_IGNORE_INFOFRAME ) goto check_lame_tag_no; // note: CRC or not, that does not matter here. // but, there is any combination of Xing flags in the wild. There are headers // without the search index table! I cannot assume a reasonable minimal size // for the actual data, have to check if each byte of information is present. // but: 4 B Info/Xing + 4 B flags is bare minimum. if( fr->framesize < lame_offset + 8 ) goto check_lame_tag_no; // only search for tag when all zero before it (apart from checksum) for( i = 2; i < lame_offset; ++i ) { if( fr->bsbuf[i] != 0 ) goto check_lame_tag_no; } if((fr->bsbuf[lame_offset] == 'I') && (fr->bsbuf[lame_offset+1] == 'n') && (fr->bsbuf[lame_offset+2] == 'f') && (fr->bsbuf[lame_offset+3] == 'o')) { // we still have to see what there is } else if((fr->bsbuf[lame_offset] == 'X') && (fr->bsbuf[lame_offset+1] == 'i') && (fr->bsbuf[lame_offset+2] == 'n') && (fr->bsbuf[lame_offset+3] == 'g')) { // Xing header means always VBR fr->vbr = MPG123_VBR; } else goto check_lame_tag_no; lame_offset += 4; xing_flags = bit_read_long( fr->bsbuf, &lame_offset ); // from now on, I have to carefully check if the announced data is actually // there! I'm always returning 'yes', though. if( xing_flags & 1 ) { // total bitstream frames check_bytes_left( 4 ); long_tmp = bit_read_long( fr->bsbuf, &lame_offset ); if( fr->p.flags & MPG123_IGNORE_STREAMLENGTH ) { } else { // check for endless stream, but: TRACK_MAX_FRAMES sensible at all? fr->track_frames = long_tmp > TRACK_MAX_FRAMES ? 0 : (mpg_off_t)long_tmp; // all or nothing: Only if encoder delay/padding is known, we'll cut // samples for gapless. if( fr->p.flags & MPG123_GAPLESS ) frame_gapless_init( fr, fr->track_frames, 0, 0 ); } } if( xing_flags & 0x2 ) { // total bitstream bytes check_bytes_left( 4 ); long_tmp = bit_read_long( fr->bsbuf, &lame_offset ); if( fr->p.flags & MPG123_IGNORE_STREAMLENGTH ) { } else { // the Xing bitstream length, at least as interpreted by the Lame // encoder, encompasses all data from the Xing header frame on, // ignoring leading ID3v2 data. Trailing tags (ID3v1) seem to be // included, though. if( fr->rdat.filelen < 1 ) { fr->rdat.filelen = (mpg_off_t)long_tmp + fr->audio_start; // Overflow? } } } if( xing_flags & 0x4 ) // TOC { check_bytes_left( 100 ); frame_fill_toc( fr, fr->bsbuf + lame_offset ); lame_offset += 100; } // VBR quality if( xing_flags & 0x8 ) { check_bytes_left( 4 ); long_tmp = bit_read_long( fr->bsbuf, &lame_offset ); } // either zeros/nothing, or: // 0-8: LAME3.90a // 9: revision/VBR method // 10: lowpass // 11-18: ReplayGain // 19: encoder flags // 20: ABR // 21-23: encoder delays check_bytes_left( 24 ); // I'm interested in 24 B of extra info. if( fr->bsbuf[lame_offset] != 0 ) { byte lame_vbr; float replay_gain[2] = { 0, 0 }; float peak = 0; float gain_offset = 0; // going to be +6 for old lame that used 83dB char nb[10]; mpg_off_t pad_in; mpg_off_t pad_out; memcpy( nb, fr->bsbuf + lame_offset, 9 ); nb[9] = 0; if(!strncmp( "LAME", nb, 4 )) { uint major, minor; char rest[6]; rest[0] = 0; // Lame versions before 3.95.1 used 83 dB reference level, later // versions 89 dB. We stick with 89 dB as being "normal", adding 6 dB. if( sscanf( nb + 4, "%u.%u%s", &major, &minor, rest ) >= 2 ) { // We cannot detect LAME 3.95 reliably (same version string as // 3.95.1), so this is a blind spot. Everything < 3.95 is safe, though. if( major < 3 || ( major == 3 && minor < 95 )) gain_offset = 6; } } lame_offset += 9; // 9 in // the 4 big bits are tag revision, the small bits vbr method. lame_vbr = fr->bsbuf[lame_offset] & 15; lame_offset += 1; // 10 in // from rev1 proposal... not sure if all good in practice switch( lame_vbr ) { case 1: case 8: fr->vbr = MPG123_CBR; break; case 2: case 9: fr->vbr = MPG123_ABR; break; default: fr->vbr = MPG123_VBR; break; // 00 ==unknown is taken as VBR } lame_offset += 1; // 11 in, skipping lowpass filter value peak = 0; // until better times arrived lame_offset += 4; // 15 in // ReplayGain values - lame only writes radio mode gain... // 16bit gain, 3 bits name, 3 bits originator, sign (1=-, 0=+), // dB value * 10 in 9 bits (fixed point) ignore the setting if name or // originator == 000! // radio 0 0 1 0 1 1 1 0 0 1 1 1 1 1 0 1 // audiophile 0 1 0 0 1 0 0 0 0 0 0 1 0 1 0 0 for( i = 0; i < 2; ++i ) { byte gt = fr->bsbuf[lame_offset] >> 5; byte origin = (fr->bsbuf[lame_offset] >> 2) & 0x7; float factor = (fr->bsbuf[lame_offset] & 0x2) ? -0.1f : 0.1f; word gain = bit_read_short( fr->bsbuf, &lame_offset ) & 0x1ff; // 19 in (2 cycles) if( origin == 0 || gt < 1 || gt > 2 ) continue; gt--; replay_gain[gt] = factor * (float)gain; // apply gain offset for automatic origin. if( origin == 3 ) replay_gain[gt] += gain_offset; } for( i = 0; i < 2; ++i ) { if( fr->rva.level[i] <= 0 ) { fr->rva.peak[i] = 0; // TODO: use parsed peak? fr->rva.gain[i] = replay_gain[i]; fr->rva.level[i] = 0; } } lame_offset += 1; // 20 in, skipping encoding flags byte // ABR rate if( fr->vbr == MPG123_ABR ) fr->abr_rate = fr->bsbuf[lame_offset]; lame_offset += 1; // 21 in // Encoder delay and padding, two 12 bit values // ... lame does write them from int. pad_in = ((((int) fr->bsbuf[lame_offset]) << 4) | (((int) fr->bsbuf[lame_offset+1]) >> 4)); pad_out = ((((int) fr->bsbuf[lame_offset+1]) << 8) | ((int) fr->bsbuf[lame_offset+2])) & 0xfff; lame_offset += 3; // 24 in if( fr->p.flags & MPG123_GAPLESS ) frame_gapless_init( fr, fr->track_frames, pad_in, pad_out ); // final: 24 B LAME data } check_lame_tag_yes: // switch buffer back ... fr->bsbuf = fr->bsspace[fr->bsnum] + 512; fr->bsnum = (fr->bsnum + 1) & 1; return 1; check_lame_tag_no: return 0; } // first attempt of read ahead check to find the real first header; cannot believe what junk is out there! static int do_readahead( mpg123_handle_t *fr, ulong newhead ) { ulong nexthead = 0; int hd = 0; mpg_off_t start, oret; int ret; if(!( !fr->firsthead && fr->rdat.flags & ( READER_SEEKABLE|READER_BUFFERED ))) return PARSE_GOOD; start = fr->rd->tell( fr ); // step framesize bytes forward and read next possible header if((oret = fr->rd->skip_bytes( fr, fr->framesize )) < 0 ) return oret == MPG123_NEED_MORE ? PARSE_MORE : PARSE_ERR; // read header, seek back. hd = fr->rd->head_read( fr, &nexthead ); if( fr->rd->back_bytes( fr, fr->rd->tell( fr ) - start ) < 0 ) return PARSE_ERR; if( hd == MPG123_NEED_MORE ) return PARSE_MORE; if( !hd ) return PARSE_END; if( !head_check( nexthead ) || !head_compatible( newhead, nexthead )) { fr->oldhead = 0; // start over // try next byte for valid header if(( ret = fr->rd->back_bytes( fr, 3 )) < 0 ) return PARSE_ERR; return PARSE_AGAIN; } return PARSE_GOOD; } static void halfspeed_prepare( mpg123_handle_t *fr ) { if( fr->p.halfspeed && fr->lay == 3 ) memcpy( fr->ssave, fr->bsbuf, fr->ssize ); } // if this returns 1, the next frame is the repetition. static int halfspeed_do( mpg123_handle_t *fr ) { // speed-down hack: Play it again, Sam (the frame, I mean). if( fr->p.halfspeed ) { if( fr->halfphase ) // repeat last frame { fr->to_decode = fr->to_ignore = TRUE; fr->halfphase--; fr->bitindex = 0; fr->wordpointer = (byte *)fr->bsbuf; if( fr->lay == 3 ) memcpy( fr->bsbuf, fr->ssave, fr->ssize ); if( fr->error_protection ) fr->crc = getbits( fr, 16 ); // skip crc return 1; } else { fr->halfphase = fr->p.halfspeed - 1; } } return 0; } // read ahead and find the next MPEG header, to guess framesize // return value: success code // PARSE_GOOD: found a valid frame size (stored in the handle). // < 0: error codes, possibly from feeder buffer (NEED_MORE) // PARSE_BAD: cannot get the framesize for some reason and shall silentry try the next possible header (if this is no free format stream after all...) static int guess_freeformat_framesize( mpg123_handle_t *fr, ulong oldhead ) { ulong head; int ret; long i; if(!( fr->rdat.flags & ( READER_SEEKABLE|READER_BUFFERED ))) return PARSE_BAD; if(( ret = fr->rd->head_read( fr, &head )) <= 0 ) return ret; // we are already 4 bytes into it for( i = 4; i < MAXFRAMESIZE + 4; i++ ) { if(( ret = fr->rd->head_shift( fr, &head )) <= 0 ) return ret; // no head_check needed, the mask contains all relevant bits. if(( head & HDR_SAMEMASK ) == ( oldhead & HDR_SAMEMASK )) { fr->rd->back_bytes( fr, i + 1 ); fr->framesize = i - 3; return PARSE_GOOD; // success! } } fr->rd->back_bytes( fr, i ); return PARSE_BAD; } // decode a header and write the information // into the frame structure // return values are compatible with those of read_frame, namely: // 1: success // 0: no valid header // <0: some error // you are required to do a head_check() before calling! static int decode_header( mpg123_handle_t *fr, ulong newhead, int *freeformat_count ) { // for some reason, the layer and sampling freq settings used to be wrapped // in a weird conditional including MPG123_NO_RESYNC. what was I thinking? // this information has to be consistent. fr->lay = 4 - HDR_LAYER_VAL( newhead ); if( HDR_VERSION_VAL( newhead ) & 0x2 ) { fr->lsf = (HDR_VERSION_VAL( newhead ) & 0x1 ) ? 0 : 1; fr->sampling_frequency = HDR_SAMPLERATE_VAL( newhead ) + (fr->lsf * 3); fr->mpeg25 = 0; } else { fr->sampling_frequency = 6 + HDR_SAMPLERATE_VAL( newhead ); fr->mpeg25 = 1; fr->lsf = 1; } fr->error_protection = HDR_CRC_VAL( newhead ) ^ 0x1; fr->bitrate_index = HDR_BITRATE_VAL( newhead ); fr->padding = HDR_PADDING_VAL( newhead ); fr->extension = HDR_PRIVATE_VAL( newhead ); fr->mode = HDR_CHANNEL_VAL( newhead ); fr->mode_ext = HDR_CHANEX_VAL( newhead ); fr->copyright = HDR_COPYRIGHT_VAL( newhead ); fr->original = HDR_ORIGINAL_VAL( newhead ); fr->emphasis = HDR_EMPHASIS_VAL( newhead ); fr->freeformat = !( newhead & HDR_BITRATE ); fr->stereo = (fr->mode == MPG_MD_MONO) ? 1 : 2; // we can't use tabsel_123 for freeformat, so trying to guess framesize... if( fr->freeformat ) { // when we first encounter the frame with freeformat, guess framesize if( fr->freeformat_framesize < 0 ) { int ret; *freeformat_count += 1; if( *freeformat_count > 5 ) return PARSE_BAD; ret = guess_freeformat_framesize( fr, newhead ); if( ret == PARSE_GOOD ) { fr->freeformat_framesize = fr->framesize - fr->padding; } else { return ret; } } else { // freeformat should be CBR, so the same framesize can be used at the 2nd reading or later fr->framesize = fr->freeformat_framesize + fr->padding; } } switch( fr->lay ) { case 3: fr->spf = fr->lsf ? 576 : 1152; /* MPEG 2.5 implies LSF.*/ fr->do_layer = do_layer3; if( fr->lsf ) fr->ssize = (fr->stereo == 1) ? 9 : 17; else fr->ssize = (fr->stereo == 1) ? 17 : 32; if( fr->error_protection ) fr->ssize += 2; if( !fr->freeformat ) { fr->framesize = (long)tabsel_123[fr->lsf][2][fr->bitrate_index] * 144000; fr->framesize /= freqs[fr->sampling_frequency]<<(fr->lsf); fr->framesize = fr->framesize + fr->padding - 4; } break; default: return PARSE_BAD; } if( fr->framesize > MAXFRAMESIZE ) return PARSE_BAD; return PARSE_GOOD; } // advance a byte in stream to get next possible header and forget // buffered data if possible (for feed reader). static int forget_head_shift( mpg123_handle_t *fr, ulong *newheadp, int forget ) { int ret; if(( ret = fr->rd->head_shift( fr, newheadp )) <= 0 ) return ret; // try to forget buffered data as early as possible to speed up parsing where // new data needs to be added for resync (and things would be re-parsed again // and again because of the start from beginning after hitting end). if( forget && fr->rd->forget != NULL ) { // ensure that the last 4 bytes stay in buffers for reading the header anew. if(!fr->rd->back_bytes( fr, 4 )) { fr->rd->forget( fr ); fr->rd->back_bytes( fr, -4 ); } } return ret; // No surprise here, error already triggered early return. } // trying to parse ID3v2.3 and ID3v2.4 tags... // returns: 0: bad or just unparseable tag // 1: good, (possibly) new tag info // <0: reader error (may need more data feed, try again) int parse_new_id3( mpg123_handle_t *fr, ulong first4bytes ) { byte buf[6]; ulong length=0; byte flags = 0; int ret = 1; int ret2; byte major = (byte)(first4bytes & 0xff); if( major == 0xff ) return 0; if(( ret2 = fr->rd->read_frame_body( fr, buf, 6 )) < 0 ) // read more header information return ret2; if( buf[0] == 0xff ) return 0; // revision, will never be 0xff. // second new byte are some nice flags, if these are invalid skip the whole thing flags = buf[1]; // length-10 or length-20 (footer present); 4 synchsafe integers == 28 bit number // we have already read 10 bytes, so left are length or length+10 bytes belonging to tag if( !synchsafe_to_long( buf + 2, length )) return 0; if(( ret2 = fr->rd->skip_bytes( fr, length )) < 0 ) // will not store data in backbuff! ret = ret2; // skip footer if present if(( ret > 0 ) && ( flags & 16 ) && (( ret2 = fr->rd->skip_bytes( fr, length )) < 0 )) ret = ret2; return ret; } static int handle_id3v2( mpg123_handle_t *fr, ulong newhead ) { int ret; fr->oldhead = 0; // think about that. Used to be present only for skipping of junk, not resync-style wetwork. ret = parse_new_id3( fr, newhead ); if( ret < 0 ) return ret; return PARSE_AGAIN; } // watch out for junk/tags on beginning of stream by invalid header static int skip_junk( mpg123_handle_t *fr, ulong *newheadp, long *headcount ) { int ret; int freeformat_count = 0; ulong newhead = *newheadp; uint forgetcount = 0; long limit = 65536; // check for id3v2; first three bytes (of 4) are "ID3" if(( newhead & (ulong)0xffffff00 ) == (ulong)0x49443300 ) { return handle_id3v2( fr, newhead ); } // I even saw RIFF headers at the beginning of MPEG streams ;( if( newhead == ('R'<<24)+('I'<<16)+('F'<<8)+'F' ) { if(( ret = fr->rd->head_read( fr, &newhead )) <= 0 ) return ret; while( newhead != ('d'<<24)+('a'<<16)+('t'<<8)+'a' ) { if( ++forgetcount > FORGET_INTERVAL ) forgetcount = 0; if(( ret = forget_head_shift( fr, &newhead, !forgetcount )) <= 0 ) return ret; } if(( ret = fr->rd->head_read( fr, &newhead )) <= 0 ) return ret; fr->oldhead = 0; *newheadp = newhead; return PARSE_AGAIN; } // unhandled junk... just continue search for a header, stepping in single bytes through next 64K. // this is rather identical to the resync loop. *newheadp = 0; // invalidate the external value. ret = 0; // we will check the value after the loop. // we prepare for at least the 64K bytes as usual, unless // user explicitly wanted more (even infinity). Never less. if( fr->p.resync_limit < 0 || fr->p.resync_limit > limit ) limit = fr->p.resync_limit; do { ++(*headcount); if( limit >= 0 && *headcount >= limit ) break; if( ++forgetcount > FORGET_INTERVAL ) forgetcount = 0; if(( ret = forget_head_shift( fr, &newhead, !forgetcount )) <= 0 ) return ret; if( head_check( newhead ) && (ret = decode_header( fr, newhead, &freeformat_count ))) break; } while( 1 ); if( ret < 0 ) return ret; if( limit >= 0 && *headcount >= limit ) return PARSE_END; // If the new header ist good, it is already decoded. *newheadp = newhead; return PARSE_GOOD; } // the newhead is bad, so let's check if it is something special, otherwise just resync. static int wetwork( mpg123_handle_t *fr, ulong *newheadp ) { int ret = PARSE_ERR; ulong newhead = *newheadp; *newheadp = 0; // classic ID3 tags. Read, then start parsing again. if(( newhead & 0xffffff00 ) == ( 'T'<<24 )+( 'A'<<16 )+( 'G'<<8 )) { fr->id3buf[0] = (byte)((newhead >> 24) & 0xff); fr->id3buf[1] = (byte)((newhead >> 16) & 0xff); fr->id3buf[2] = (byte)((newhead >> 8) & 0xff); fr->id3buf[3] = (byte)( newhead & 0xff); if(( ret = fr->rd->fullread( fr, fr->id3buf + 4, 124 )) < 0 ) return ret; fr->metaflags |= MPG123_NEW_ID3|MPG123_ID3; fr->rdat.flags |= READER_ID3TAG; // that marks id3v1 return PARSE_AGAIN; } // this is similar to initial junk skipping code... // check for id3v2; first three bytes (of 4) are "ID3" if(( newhead & (ulong)0xffffff00 ) == (ulong)0x49443300 ) { return handle_id3v2( fr, newhead ); } // now we got something bad at hand, try to recover. if( !( fr->p.flags & MPG123_NO_RESYNC )) { long try = 0; long limit = fr->p.resync_limit; uint forgetcount = 0; // if a resync is needed the bitreservoir of previous frames is no longer valid fr->bitreservoir = 0; do // ... shift the header with additional single bytes until be found something that could be a header. { try++; if( limit >= 0 && try >= limit ) break; if( ++forgetcount > FORGET_INTERVAL ) forgetcount = 0; if(( ret = forget_head_shift( fr, &newhead, !forgetcount )) <= 0 ) { *newheadp = newhead; return ret ? ret : PARSE_END; } } while( !head_check( newhead )); *newheadp = newhead; // now we either got something that could be a header, or we gave up. if( limit >= 0 && try >= limit ) { fr->err = MPG123_RESYNC_FAIL; return PARSE_ERR; } else { fr->oldhead = 0; return PARSE_RESYNC; } } else { fr->err = MPG123_OUT_OF_SYNC; return PARSE_ERR; } } // that's a big one: read the next frame. 1 is success, <= 0 is some error // special error READER_MORE means: Please feed more data and try again. int read_frame( mpg123_handle_t *fr ) { // TODO: rework this thing int freeformat_count = 0; int oldsize = fr->framesize; int oldphase = fr->halfphase; long headcount = 0; byte *newbuf; ulong newhead; mpg_off_t framepos; int ret; fr->fsizeold = fr->framesize; // for Layer3 if( halfspeed_do( fr ) == 1 ) return 1; read_again: // in case we are looping to find a valid frame, discard any buffered data before the current position. // this is essential to prevent endless looping, always going back to the beginning when feeder buffer is exhausted. if( fr->rd->forget != NULL ) fr->rd->forget( fr ); if(( ret = fr->rd->head_read( fr, &newhead )) <= 0 ) goto read_frame_bad; init_resync: if( !fr->firsthead && !head_check( newhead )) { ret = skip_junk(fr, &newhead, &headcount); if( ret < 0 ) goto read_frame_bad; else if( ret == PARSE_AGAIN ) goto read_again; else if( ret == PARSE_RESYNC ) goto init_resync; else if( ret == PARSE_END ) { ret = 0; goto read_frame_bad; } } ret = head_check( newhead ); if( ret ) ret = decode_header( fr, newhead, &freeformat_count ); if( ret < 0 ) goto read_frame_bad; else if( ret == PARSE_AGAIN ) goto read_again; else if( ret == PARSE_RESYNC ) goto init_resync; else if( ret == PARSE_END ) { ret = 0; goto read_frame_bad; } if( ret == PARSE_BAD ) { // header was not good. ret = wetwork( fr, &newhead ); // Messy stuff, handle junk, resync ... if( ret < 0 ) goto read_frame_bad; else if( ret == PARSE_AGAIN ) goto read_again; else if( ret == PARSE_RESYNC ) goto init_resync; else if( ret == PARSE_END ) { ret = 0; goto read_frame_bad; } // normally, we jumped already. // if for some reason everything's fine to continue, do continue. if( ret != PARSE_GOOD ) goto read_frame_bad; } if( !fr->firsthead ) { ret = do_readahead( fr, newhead ); // readahead can fail mit NEED_MORE, in which case we must also make // the just read header available again for next go if( ret < 0 ) fr->rd->back_bytes( fr, 4 ); if( ret < 0 ) goto read_frame_bad; else if( ret == PARSE_AGAIN ) goto read_again; else if( ret == PARSE_RESYNC ) goto init_resync; else if( ret == PARSE_END ) { ret = 0; goto read_frame_bad; } } // now we should have our valid header and proceed to reading the frame. // if filepos is invalid, so is framepos framepos = fr->rd->tell( fr ) - 4; // flip/init buffer for Layer 3 newbuf = fr->bsspace[fr->bsnum] + 512; // read main data into memory if(( ret = fr->rd->read_frame_body( fr, newbuf, fr->framesize )) < 0 ) { // if failed: flip back goto read_frame_bad; } fr->bsbufold = fr->bsbuf; fr->bsbuf = newbuf; fr->bsnum = (fr->bsnum + 1) & 1; if( !fr->firsthead ) { fr->firsthead = newhead; // _now_ it's time to store it... the first real header */ // this is the first header of our current stream segment. // it is only the actual first header of the whole stream when fr->num is still below zero! // think of resyncs where firsthead has been reset for format flexibility. if( fr->num < 0 ) { fr->audio_start = framepos; // only check for LAME tag at beginning of whole stream // ... when there indeed is one in between, it's the user's problem. if( fr->lay == 3 && check_lame_tag( fr ) == 1 ) { // ...in practice, Xing/LAME tags are layer 3 only. if( fr->rd->forget != NULL ) fr->rd->forget( fr ); fr->oldhead = 0; goto read_again; } // now adjust volume do_rva( fr ); } } fr->bitindex = 0; fr->wordpointer = (byte *)fr->bsbuf; // question: How bad does the floating point value get with repeated recomputation? // also, considering that we can play the file or parts of many times. if( ++fr->mean_frames != 0 ) fr->mean_framesize = ((fr->mean_frames - 1) * fr->mean_framesize + compute_bpf( fr )) / fr->mean_frames ; fr->num++; // 0 for first frame! if(!( fr->state_flags & FRAME_FRANKENSTEIN ) && (( fr->track_frames > 0 && fr->num >= fr->track_frames ) || ( fr->gapless_frames > 0 && fr->num >= fr->gapless_frames ))) fr->state_flags |= FRAME_FRANKENSTEIN; halfspeed_prepare( fr ); // index the position fr->input_offset = framepos; // keep track of true frame positions in our frame index. // but only do so when we are sure that the frame number is accurate... if(( fr->state_flags & FRAME_ACCURATE ) && FI_NEXT( fr->index, fr->num )) fi_add( &fr->index, framepos ); if( fr->silent_resync > 0 ) fr->silent_resync--; if( fr->rd->forget != NULL ) fr->rd->forget( fr ); fr->to_decode = fr->to_ignore = TRUE; if( fr->error_protection ) fr->crc = getbits( fr, 16 ); // skip crc // let's check for header change after deciding that the new one is good // and actually having read a frame. // header_change > 1: decoder structure has to be updated // preserve header_change value from previous runs if it is serious. // If we still have a big change pending, it should be dealt with outside, // fr->header_change set to zero afterwards. if( fr->header_change < 2 ) { fr->header_change = 2; // output format change is possible... if( fr->oldhead ) // check a following header for change { if( fr->oldhead == newhead ) { fr->header_change = 0; } else if( head_compatible( fr->oldhead, newhead )) { // headers that match in this test behave the same for the outside world. // namely: same decoding routines, same amount of decoded data. fr->header_change = 1; } else { fr->state_flags |= FRAME_FRANKENSTEIN; } } else if( fr->firsthead && !head_compatible( fr->firsthead, newhead )) { fr->state_flags |= FRAME_FRANKENSTEIN; } } fr->oldhead = newhead; return 1; read_frame_bad: // also if we searched for valid data in vein, we can forget skipped data. // otherwise, the feeder would hold every dead old byte in memory until the first valid frame! if( fr->rd->forget != NULL ) fr->rd->forget( fr ); fr->silent_resync = 0; if( fr->err == MPG123_OK ) fr->err = MPG123_ERR_READER; fr->framesize = oldsize; fr->halfphase = oldphase; // that return code might be inherited from some feeder action, or reader error. return ret; }