⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 common.c

📁 mpg123 是 MPEG 1.0/2.0/2.5 的实时播放软件
💻 C
📖 第 1 页 / 共 3 页
字号:
/*	common: anything can happen here... frame reading, output, messages	copyright ?-2006 by the mpg123 project - free software under the terms of the LGPL 2.1	see COPYING and AUTHORS files in distribution or http://mpg123.de	initially written by Michael Hipp*/#include <ctype.h>#include <stdlib.h>#include <signal.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/time.h>#include <math.h>#ifdef HAVE_INTTYPES_H#include <inttypes.h>#endif#include <fcntl.h>#include "config.h"#include "mpg123.h"#include "id3.h"#include "icy.h"#include "common.h"#include "debug.h"/* bitrates for [mpeg1/2][layer] */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,} }};long freqs[9] = { 44100, 48000, 32000, 22050, 24000, 16000 , 11025 , 12000 , 8000 };struct bitstream_info bsi;static int fsizeold=0,ssize;static unsigned char bsspace[2][MAXFRAMESIZE+512]; /* MAXFRAMESIZE */static unsigned char *bsbuf=bsspace[1],*bsbufold;static int bsnum=0;static unsigned long oldhead = 0;unsigned long firsthead=0;#define CBR 0#define VBR 1#define ABR 2int vbr = CBR; /* variable bitrate flag */int abr_rate = 0;#ifdef GAPLESS#include "layer3.h"#endifunsigned long track_frames = 0;/* a limit for number of frames in a track; beyond that unsigned long may not be enough to hold byte addresses */#ifdef HAVE_LIMITS_H#include <limits.h>#endif#ifndef ULONG_MAX/* hm, is this portable across preprocessors? */#define ULONG_MAX ((unsigned long)-1)#endif#define TRACK_MAX_FRAMES ULONG_MAX/4/1152/* this could become a struct... */long lastscale = -1; /* last used scale */int rva_level[2] = {-1,-1}; /* significance level of stored rva */float rva_gain[2] = {0,0}; /* mix, album */float rva_peak[2] = {0,0};static double mean_framesize;static unsigned long mean_frames;static int do_recover = 0;struct {	off_t data[INDEX_SIZE];	size_t fill;	unsigned long step;} frame_index;unsigned char *pcm_sample;int pcm_point = 0;int audiobufsize = AUDIOBUFSIZE;#define RESYNC_LIMIT 1024#ifdef VARMODESUPPORT	/*	 *   This is a dirty hack!  It might burn your PC and kill your cat!	 *   When in "varmode", specially formatted layer-3 mpeg files are	 *   expected as input -- it will NOT work with standard mpeg files.	 *   The reason for this:	 *   Varmode mpeg files enable my own GUI player to perform fast	 *   forward and backward functions, and to jump to an arbitrary	 *   timestamp position within the file.  This would be possible	 *   with standard mpeg files, too, but it would be a lot harder to	 *   implement.	 *   A filter for converting standard mpeg to varmode mpeg is	 *   available on request, but it's really not useful on its own.	 *	 *   Oliver Fromme  <oliver.fromme@heim3.tu-clausthal.de>	 *   Mon Mar 24 00:04:24 MET 1997	 */int varmode = FALSE;int playlimit;#endifstatic int decode_header(struct frame *fr,unsigned long newhead);#ifdef GAPLESS/* take into account: channels, bytes per sample, resampling (integer samples!) */unsigned long samples_to_bytes(unsigned long s, struct frame *fr , struct audio_info_struct* ai){	/* rounding positive number... */	double sammy, samf;	sammy = (1.0*s) * (1.0*ai->rate)/freqs[fr->sampling_frequency];	debug4("%lu samples to bytes with freq %li (ai.rate %li); sammy %f", s, freqs[fr->sampling_frequency], ai->rate, sammy);	samf = floor(sammy);	return (unsigned long)		(((ai->format & AUDIO_FORMAT_MASK) == AUDIO_FORMAT_16) ? 2 : 1)		* ai->channels		* (int) (((sammy - samf) < 0.5) ? samf : ( sammy-samf > 0.5 ? samf+1 : ((unsigned long) samf % 2 == 0 ? samf : samf + 1)));}#endifvoid audio_flush(int outmode, struct audio_info_struct *ai){	#ifdef GAPLESS	if(param.gapless) layer3_gapless_buffercheck();	#endif	if(pcm_point)	{		switch(outmode)		{			case DECODE_FILE:				write (OutputDescriptor, pcm_sample, pcm_point);			break;			case DECODE_AUDIO:				audio_play_samples (ai, pcm_sample, pcm_point);			break;			case DECODE_BUFFER:				write (buffer_fd[1], pcm_sample, pcm_point);			break;			case DECODE_WAV:			case DECODE_CDR:			case DECODE_AU:				wav_write(pcm_sample, pcm_point);			break;		}		pcm_point = 0;	}}#if !defined(WIN32) && !defined(GENERIC)void (*catchsignal(int signum, void(*handler)()))(){  struct sigaction new_sa;  struct sigaction old_sa;#ifdef DONT_CATCH_SIGNALS  fprintf (stderr, "Not catching any signals.\n");  return ((void (*)()) -1);#endif  new_sa.sa_handler = handler;  sigemptyset(&new_sa.sa_mask);  new_sa.sa_flags = 0;  if (sigaction(signum, &new_sa, &old_sa) == -1)    return ((void (*)()) -1);  return (old_sa.sa_handler);}#endifvoid read_frame_init (struct frame* fr){	fr->num = 0;	oldhead = 0;	firsthead = 0;	vbr = CBR;	abr_rate = 0;	track_frames = 0;	mean_frames = 0;	mean_framesize = 0;	rva_level[0] = -1;	rva_level[1] = -1;	#ifdef GAPLESS	/* one can at least skip the delay at beginning - though not add it at end since end is unknown */	if(param.gapless) layer3_gapless_init(DECODER_DELAY+GAP_SHIFT, 0);	#endif	frame_index.fill = 0;	frame_index.step = 1;	reset_id3();}#define free_format_header(head) ( ((head & 0xffe00000) == 0xffe00000) && ((head>>17)&3) && (((head>>12)&0xf) == 0x0) && (((head>>10)&0x3) != 0x3 ))/* compiler is smart enought to inline this one or should I really do it as macro...? */int head_check(unsigned long head){	if	(		/* first 11 bits are set to 1 for frame sync */		((head & 0xffe00000) != 0xffe00000)		||		/* layer: 01,10,11 is 1,2,3; 00 is reserved */		(!((head>>17)&3))		||		/* 1111 means bad bitrate */		(((head>>12)&0xf) == 0xf)		||		/* 0000 means free format... */		(((head>>12)&0xf) == 0x0)		||		/* sampling freq: 11 is reserved */		(((head>>10)&0x3) == 0x3 )		/* here used to be a mpeg 2.5 check... re-enabled 2.5 decoding due to lack of evidence that it is really not good */	)	{		return FALSE;	}	/* if no check failed, the header is valid (hopefully)*/	else	{		return TRUE;	}}/* adjust the volume, taking both outscale and rva values into account */void do_rva(){	float rvafact = 1;	float peak = 0;	long newscale;	if(param.rva)	{		int rt = 0;		/* Should one assume a zero RVA as no RVA? */		if(param.rva == 2 && rva_level[1] != -1) rt = 1;		if(rva_level[rt] != -1)		{			rvafact = pow(10,rva_gain[rt]/20);			peak = rva_peak[rt];			if(param.verbose > 1) fprintf(stderr, "Note: doing RVA with gain %f\n", rva_gain[rt]);		}		else		{			warning("no RVA value found");		}	}	newscale = outscale*rvafact;	/* if peak is unknown (== 0) this check won't hurt */	if((peak*newscale) > MAXOUTBURST)	{		newscale = (long) ((float) MAXOUTBURST/peak);		warning2("limiting scale value to %li to prevent clipping with indicated peak factor of %f", newscale, peak);	}	/* first rva setting is forced with lastscale < 0 */	if(newscale != lastscale)	{		debug3("changing scale value from %li to %li (peak estimated to %li)", lastscale != -1 ? lastscale : outscale, newscale, (long) (newscale*peak));		make_decode_tables(newscale); /* the actual work */		lastscale = newscale;	}}int read_frame_recover(struct frame* fr){	int ret;	do_recover = 1;	ret = read_frame(fr);	do_recover = 0;	return ret;}/***************************************************************** * read next frame */int read_frame(struct frame *fr){	/* TODO: rework this thing */  unsigned long newhead;  static unsigned char ssave[34];	off_t framepos;  int give_note = param.verbose > 1 ? 1 : (do_recover ? 0 : 1 );  fsizeold=fr->framesize;       /* for Layer3 */  if (param.halfspeed) {    static int halfphase = 0;    if (halfphase--) {      bsi.bitindex = 0;      bsi.wordpointer = (unsigned char *) bsbuf;      if (fr->lay == 3)        memcpy (bsbuf, ssave, ssize);      return 1;    }    else      halfphase = param.halfspeed - 1;  }read_again:		if(!rd->head_read(rd,&newhead))	{		return FALSE;	}	/* this if wrap looks like dead code... */  if(1 || oldhead != newhead || !oldhead)  {init_resync:    fr->header_change = 2;    if(oldhead) {      if((oldhead & 0xc00) == (newhead & 0xc00)) {        if( (oldhead & 0xc0) == 0 && (newhead & 0xc0) == 0)    	  fr->header_change = 1;         else if( (oldhead & 0xc0) > 0 && (newhead & 0xc0) > 0)	  fr->header_change = 1;      }    }#ifdef SKIP_JUNK	/* watch out for junk/tags on beginning of stream by invalid header */	if(!firsthead && !head_check(newhead) && !free_format_header(newhead)) {		int i;		/* check for id3v2; first three bytes (of 4) are "ID3" */		if((newhead & (unsigned long) 0xffffff00) == (unsigned long) 0x49443300)		{			int id3length = 0;			id3length = parse_new_id3(newhead, rd);			goto read_again;		}		else if(param.verbose > 1) fprintf(stderr,"Note: Junk at the beginning (0x%08lx)\n",newhead);		/* I even saw RIFF headers at the beginning of MPEG streams ;( */		if(newhead == ('R'<<24)+('I'<<16)+('F'<<8)+'F') {			if(param.verbose > 1) fprintf(stderr, "Note: Looks like a RIFF header.\n");			if(!rd->head_read(rd,&newhead))				return 0;			while(newhead != ('d'<<24)+('a'<<16)+('t'<<8)+'a') {				if(!rd->head_shift(rd,&newhead))					return 0;			}			if(!rd->head_read(rd,&newhead))				return 0;			if(param.verbose > 1) fprintf(stderr,"Note: Skipped RIFF header!\n");			goto read_again;		}		/* unhandled junk... just continue search for a header */		/* step in byte steps through next 64K */		for(i=0;i<65536;i++) {			if(!rd->head_shift(rd,&newhead))				return 0;			/* if(head_check(newhead)) */			if(head_check(newhead) && decode_header(fr, newhead))			break;		}		if(i == 65536) {			if(!param.quiet) error("Giving up searching valid MPEG header after 64K of junk.");			return 0;		}		/* 		 * should we additionaly check, whether a new frame starts at		 * the next expected position? (some kind of read ahead)		 * We could implement this easily, at least for files.		 */	}#endif	/* first attempt of read ahead check to find the real first header; cannot believe what junk is out there! */	/* for now, a spurious first free format header screws up here; need free format support for detecting false free format headers... */	if(!firsthead && rd->flags & READER_SEEKABLE && head_check(newhead) && decode_header(fr, newhead))	{		unsigned long nexthead = 0;		int hd = 0;		off_t start = rd->tell(rd);		debug1("doing ahead check with BPF %d", fr->framesize+4);		/* step framesize bytes forward and read next possible header*/		if(rd->back_bytes(rd, -fr->framesize))		{			error("cannot seek!");			return 0;		}		hd = rd->head_read(rd,&nexthead);		if(rd->back_bytes(rd, rd->tell(rd)-start))		{			error("cannot seek!");			return 0;		}		if(!hd)		{			warning("cannot read next header, a one-frame stream? Duh...");		}		else		{			debug2("does next header 0x%08lx match first 0x%08lx?", nexthead, newhead);			/* not allowing free format yet */			if(!head_check(nexthead) || (nexthead & HDRCMPMASK) != (newhead & HDRCMPMASK))			{				debug("No, the header was not valid, start from beginning...");				/* try next byte for valid header */				if(rd->back_bytes(rd, 3))				{					error("cannot seek!");					return 0;				}				goto read_again;			}		}	}    /* why has this head check been avoided here before? */    if(!head_check(newhead))    {      if(!firsthead && free_format_header(newhead))      {        error1("Header 0x%08lx seems to indicate a free format stream; I do not handle that yet", newhead);        goto read_again;        return 0;      }    /* and those ugly ID3 tags */      if((newhead & 0xffffff00) == ('T'<<24)+('A'<<16)+('G'<<8)) {           rd->skip_bytes(rd,124);	   if (param.verbose > 1) fprintf(stderr,"Note: Skipped ID3 Tag!\n");           goto read_again;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -