📄 common.c
字号:
fr->mpeg25 = 0; } else { fr->lsf = 1; fr->mpeg25 = 1; } if (!param.tryresync || !oldhead || (((oldhead>>19)&0x3) ^ ((newhead>>19)&0x3))) { /* If "tryresync" is false, assume that certain parameters do not change within the stream! Force an update if lsf or mpeg25 settings have changed. */ fr->lay = 4-((newhead>>17)&3); if( ((newhead>>10)&0x3) == 0x3) { error("Stream error"); exit(1); } if(fr->mpeg25) { fr->sampling_frequency = 6 + ((newhead>>10)&0x3); } else fr->sampling_frequency = ((newhead>>10)&0x3) + (fr->lsf*3); fr->error_protection = ((newhead>>16)&0x1)^0x1; } fr->bitrate_index = ((newhead>>12)&0xf); fr->padding = ((newhead>>9)&0x1); fr->extension = ((newhead>>8)&0x1); fr->mode = ((newhead>>6)&0x3); fr->mode_ext = ((newhead>>4)&0x3); fr->copyright = ((newhead>>3)&0x1); fr->original = ((newhead>>2)&0x1); fr->emphasis = newhead & 0x3; fr->stereo = (fr->mode == MPG_MD_MONO) ? 1 : 2; oldhead = newhead; if(!fr->bitrate_index) { error1("encountered free format header %08lx in decode_header - not supported yet",newhead); return (0); } switch(fr->lay) { case 1: fr->do_layer = do_layer1;#ifdef VARMODESUPPORT if (varmode) { error("Sorry, layer-1 not supported in varmode."); return (0); }#endif fr->framesize = (long) tabsel_123[fr->lsf][0][fr->bitrate_index] * 12000; fr->framesize /= freqs[fr->sampling_frequency]; fr->framesize = ((fr->framesize+fr->padding)<<2)-4; break; case 2: fr->do_layer = do_layer2;#ifdef VARMODESUPPORT if (varmode) { error("Sorry, layer-2 not supported in varmode."); return (0); }#endif fr->framesize = (long) tabsel_123[fr->lsf][1][fr->bitrate_index] * 144000; fr->framesize /= freqs[fr->sampling_frequency]; fr->framesize += fr->padding - 4; break; case 3: fr->do_layer = do_layer3; if(fr->lsf) ssize = (fr->stereo == 1) ? 9 : 17; else ssize = (fr->stereo == 1) ? 17 : 32; if(fr->error_protection) ssize += 2; 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: error("unknown layer type (!!)"); return (0); } if (fr->framesize > MAXFRAMESIZE) { error1("Frame size too big: %d", fr->framesize+4-fr->padding); return (0); } return 1;}/* concurring to print_rheader... here for control_generic */const char* remote_header_help = "S <mpeg-version> <layer> <sampling freq> <mode(stereo/mono/...)> <mode_ext> <framesize> <stereo> <copyright> <error_protected> <emphasis> <bitrate> <extension> <vbr(0/1=yes/no)>";void make_remote_header(struct frame* fr, char *target){ /* redundancy */ static char *modes[4] = {"Stereo", "Joint-Stereo", "Dual-Channel", "Single-Channel"}; snprintf(target, 1000, "S %s %d %ld %s %d %d %d %d %d %d %d %d %d", fr->mpeg25 ? "2.5" : (fr->lsf ? "2.0" : "1.0"), fr->lay, freqs[fr->sampling_frequency], modes[fr->mode], fr->mode_ext, fr->framesize+4, fr->stereo, fr->copyright ? 1 : 0, fr->error_protection ? 1 : 0, fr->emphasis, tabsel_123[fr->lsf][fr->lay-1][fr->bitrate_index], fr->extension, vbr);}#ifdef MPG123_REMOTEvoid print_rheader(struct frame *fr){ static char *modes[4] = { "Stereo", "Joint-Stereo", "Dual-Channel", "Single-Channel" }; static char *layers[4] = { "Unknown" , "I", "II", "III" }; static char *mpeg_type[2] = { "1.0" , "2.0" }; /* version, layer, freq, mode, channels, bitrate, BPF, VBR*/ fprintf(stderr,"@I %s %s %ld %s %d %d %d %i\n", mpeg_type[fr->lsf],layers[fr->lay],freqs[fr->sampling_frequency], modes[fr->mode],fr->stereo, vbr == ABR ? abr_rate : tabsel_123[fr->lsf][fr->lay-1][fr->bitrate_index], fr->framesize+4, vbr);}#endifvoid print_header(struct frame *fr){ static char *modes[4] = { "Stereo", "Joint-Stereo", "Dual-Channel", "Single-Channel" }; static char *layers[4] = { "Unknown" , "I", "II", "III" }; fprintf(stderr,"MPEG %s, Layer: %s, Freq: %ld, mode: %s, modext: %d, BPF : %d\n", fr->mpeg25 ? "2.5" : (fr->lsf ? "2.0" : "1.0"), layers[fr->lay],freqs[fr->sampling_frequency], modes[fr->mode],fr->mode_ext,fr->framesize+4); fprintf(stderr,"Channels: %d, copyright: %s, original: %s, CRC: %s, emphasis: %d.\n", fr->stereo,fr->copyright?"Yes":"No", fr->original?"Yes":"No",fr->error_protection?"Yes":"No", fr->emphasis); fprintf(stderr,"Bitrate: "); switch(vbr) { case CBR: fprintf(stderr, "%d kbits/s", tabsel_123[fr->lsf][fr->lay-1][fr->bitrate_index]); break; case VBR: fprintf(stderr, "VBR"); break; case ABR: fprintf(stderr, "%d kbit/s ABR", abr_rate); break; default: fprintf(stderr, "???"); } fprintf(stderr, " Extension value: %d\n", fr->extension);}void print_header_compact(struct frame *fr){ static char *modes[4] = { "stereo", "joint-stereo", "dual-channel", "mono" }; static char *layers[4] = { "Unknown" , "I", "II", "III" }; fprintf(stderr,"MPEG %s layer %s, ", fr->mpeg25 ? "2.5" : (fr->lsf ? "2.0" : "1.0"), layers[fr->lay]); switch(vbr) { case CBR: fprintf(stderr, "%d kbits/s", tabsel_123[fr->lsf][fr->lay-1][fr->bitrate_index]); break; case VBR: fprintf(stderr, "VBR"); break; case ABR: fprintf(stderr, "%d kbit/s ABR", abr_rate); break; default: fprintf(stderr, "???"); } fprintf(stderr,", %ld Hz %s\n", freqs[fr->sampling_frequency], modes[fr->mode]);}#if 0/* removed the strndup for better portability *//* * Allocate space for a new string containing the first * "num" characters of "src". The resulting string is * always zero-terminated. Returns NULL if malloc fails. */char *strndup (const char *src, int num){ char *dst; if (!(dst = (char *) malloc(num+1))) return (NULL); dst[num] = '\0'; return (strncpy(dst, src, num));}#endif/* * Split "path" into directory and filename components. * * Return value is 0 if no directory was specified (i.e. * "path" does not contain a '/'), OR if the directory * is the same as on the previous call to this function. * * Return value is 1 if a directory was specified AND it * is different from the previous one (if any). */int split_dir_file (const char *path, char **dname, char **fname){ static char *lastdir = NULL; char *slashpos; if ((slashpos = strrchr(path, '/'))) { *fname = slashpos + 1; *dname = strdup(path); /* , 1 + slashpos - path); */ if(!(*dname)) { perror("memory"); exit(1); } (*dname)[1 + slashpos - path] = 0; if (lastdir && !strcmp(lastdir, *dname)) { /*** same as previous directory ***/ free (*dname); *dname = lastdir; return 0; } else { /*** different directory ***/ if (lastdir) free (lastdir); lastdir = *dname; return 1; } } else { /*** no directory specified ***/ if (lastdir) { free (lastdir); lastdir = NULL; }; *dname = NULL; *fname = (char *)path; return 0; }}void set_pointer(long backstep){ bsi.wordpointer = bsbuf + ssize - backstep; if (backstep) memcpy(bsi.wordpointer,bsbufold+fsizeold-backstep,backstep); bsi.bitindex = 0; }/********************************/double compute_bpf(struct frame *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;}double compute_tpf(struct frame *fr){ static int bs[4] = { 0,384,1152,1152 }; double tpf; tpf = (double) bs[fr->lay]; tpf /= freqs[fr->sampling_frequency] << (fr->lsf); return tpf;}/* * Returns number of frames queued up in output buffer, i.e. * offset between currently played and currently decoded frame. */long compute_buffer_offset(struct frame *fr){ long bufsize; /* * buffermem->buf[0] holds output sampling rate, * buffermem->buf[1] holds number of channels, * buffermem->buf[2] holds audio format of output. */ if(!param.usebuffer || !(bufsize=xfermem_get_usedspace(buffermem)) || !buffermem->buf[0] || !buffermem->buf[1]) return 0; bufsize = (long)((double) bufsize / buffermem->buf[0] / buffermem->buf[1] / compute_tpf(fr)); if((buffermem->buf[2] & AUDIO_FORMAT_MASK) == AUDIO_FORMAT_16) return bufsize/2; else return bufsize;}/* Way too many parameters - heck, this fr and ai is always the same! */int position_info(struct frame* fr, long buffsize, struct audio_info_struct* ai, unsigned long* frames_left, double* current_seconds, double* seconds_left){ double tpf; double dt = 0.0; if(!rd || !fr) { debug("reader troubles!"); return -1; }#ifndef GENERIC { struct timeval t; fd_set serr; int n,errfd = fileno(stderr); t.tv_sec=t.tv_usec=0; FD_ZERO(&serr); FD_SET(errfd,&serr); n = select(errfd+1,NULL,&serr,NULL,&t); if(n <= 0) return -2; }#endif tpf = compute_tpf(fr); if(buffsize > 0 && ai && ai->rate > 0 && ai->channels > 0) { dt = (double) buffsize / ai->rate / ai->channels; if( (ai->format & AUDIO_FORMAT_MASK) == AUDIO_FORMAT_16) dt *= 0.5; } (*frames_left) = 0; if((track_frames != 0) && (track_frames >= fr->num)) (*frames_left) = track_frames - fr->num; else if(rd->filelen >= 0) { double bpf; long t = rd->tell(rd); bpf = mean_framesize ? mean_framesize : compute_bpf(fr); (*frames_left) = (unsigned long)((double)(rd->filelen-t)/bpf); /* I totally don't understand why we should re-estimate the given correct(?) value */ /* fr->num = (unsigned long)((double)t/bpf); */ } /* beginning with 0 or 1?*/ (*current_seconds) = (double) fr->num*tpf-dt; (*seconds_left) = (double)(*frames_left)*tpf+dt;#if 0 (*current_seconds) = (*current_seconds) < 0 ? 0.0 : (*current_seconds);#endif if((*seconds_left) < 0) { warning("seconds_left < 0!"); (*seconds_left) = 0.0; } return 0;}void print_stat(struct frame *fr,unsigned long no,long buffsize,struct audio_info_struct *ai){ double tim1,tim2; unsigned long rno; if(!position_info(fr, buffsize, ai, &rno, &tim1, &tim2)) { /* All these sprintf... only to avoid two writes to stderr in case of using buffer? I guess we can drop that. */ fprintf(stderr, "\rFrame# %5lu [%5lu], Time: %02lu:%02u.%02u [%02u:%02u.%02u], ", no,rno, (unsigned long) tim1/60, (unsigned int)tim1%60, (unsigned int)(tim1*100)%100, (unsigned int)tim2/60, (unsigned int)tim2%60, (unsigned int)(tim2*100)%100 ); if(param.usebuffer) fprintf(stderr,"[%8ld] ",(long)buffsize); }}int get_songlen(struct frame *fr,int no){ double tpf; if(!fr) return 0; if(no < 0) { if(!rd || rd->filelen < 0) return 0; no = (double) rd->filelen / compute_bpf(fr); } tpf = compute_tpf(fr); return no*tpf;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -