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

📄 ad_libvorbis.c

📁 自己移植的linux下的流媒体播放器原代码,支持mms协议,支持ftp和http协议.
💻 C
字号:
#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <stdarg.h>#include <math.h>#include "config.h"#include "ad_internal.h"#ifdef HAVE_OGGVORBISstatic ad_info_t info = {	"Ogg/Vorbis audio decoder",	"libvorbis",	"Felix Buenemann, A'rpi",	"libvorbis",	""};LIBAD_EXTERN(libvorbis)#ifdef TREMOR#include <tremor/ivorbiscodec.h>#else#include <vorbis/codec.h>#endif// This struct is also defined in demux_ogg.c => common header ?typedef struct ov_struct_st {  vorbis_info      vi; /* struct that stores all the static vorbis bitstream			  settings */  vorbis_comment   vc; /* struct that stores all the bitstream user comments */  vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */  vorbis_block     vb; /* local working space for packet->PCM decode */  float            rg_scale; /* replaygain scale */#ifdef TREMOR  int              rg_scale_int;#endif} ov_struct_t;static int read_vorbis_comment( char* ptr, char* comment, char* format, ... ) {  va_list va;  int clen, ret;  va_start( va, format );  clen = strlen( comment );  ret = strncasecmp( ptr, comment, clen) == 0 ? vsscanf( ptr+clen, format, va ) : 0;  va_end( va );  return ret;}static int preinit(sh_audio_t *sh){  sh->audio_out_minsize=1024*4; // 1024 samples/frame  return 1;}static int init(sh_audio_t *sh){  ogg_packet op;  vorbis_comment vc;  struct ov_struct_st *ov;#define ERROR() { \    vorbis_comment_clear(&vc); \    vorbis_info_clear(&ov->vi); \    free(ov); \    return 0; \  }  /// Init the decoder with the 3 header packets  ov = (struct ov_struct_st*)malloc(sizeof(struct ov_struct_st));  vorbis_info_init(&ov->vi);  vorbis_comment_init(&vc);  op.bytes = ds_get_packet(sh->ds,&op.packet);  op.b_o_s  = 1;  /// Header  if(vorbis_synthesis_headerin(&ov->vi,&vc,&op) <0) {    mp_msg(MSGT_DECAUDIO,MSGL_ERR,"OggVorbis: initial (identification) header broken!\n");    ERROR();  }  op.bytes = ds_get_packet(sh->ds,&op.packet);  op.b_o_s  = 0;  /// Comments  if(vorbis_synthesis_headerin(&ov->vi,&vc,&op) <0) {    mp_msg(MSGT_DECAUDIO,MSGL_ERR,"OggVorbis: comment header broken!\n");    ERROR();  }  op.bytes = ds_get_packet(sh->ds,&op.packet);  //// Codebook  if(vorbis_synthesis_headerin(&ov->vi,&vc,&op)<0) {    mp_msg(MSGT_DECAUDIO,MSGL_WARN,"OggVorbis: codebook header broken!\n");    ERROR();  } else { /// Print the infos    float rg_gain=0.f, rg_peak=0.f;    char **ptr=vc.user_comments;    while(*ptr){      mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbisComment: %s\n",*ptr);      /* replaygain */      read_vorbis_comment( *ptr, "replaygain_album_gain=", "%f", &rg_gain );      read_vorbis_comment( *ptr, "rg_audiophile=", "%f", &rg_gain );      if( !rg_gain ) {	read_vorbis_comment( *ptr, "replaygain_track_gain=", "%f", &rg_gain );	read_vorbis_comment( *ptr, "rg_radio=", "%f", &rg_gain );      }      read_vorbis_comment( *ptr, "replaygain_album_peak=", "%f", &rg_peak );      if( !rg_peak ) {	read_vorbis_comment( *ptr, "replaygain_track_peak=", "%f", &rg_peak );	read_vorbis_comment( *ptr, "rg_peak=", "%f", &rg_peak );      }      ++ptr;    }    /* replaygain: scale */    if(!rg_gain)      ov->rg_scale = 1.f; /* just in case pow() isn't standard-conformant */    else      ov->rg_scale = pow(10.f, rg_gain/20);    /* replaygain: anticlip */    if(ov->rg_scale * rg_peak > 1.f)      ov->rg_scale = 1.f / rg_peak;    /* replaygain: security */    if(ov->rg_scale > 15.)       ov->rg_scale = 15.;#ifdef TREMOR    ov->rg_scale_int = (int)(ov->rg_scale*64.f);#endif    mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Bitstream is %d channel%s, %dHz, %dbit/s %cBR\n",(int)ov->vi.channels,ov->vi.channels>1?"s":"",(int)ov->vi.rate,(int)ov->vi.bitrate_nominal,	(ov->vi.bitrate_lower!=ov->vi.bitrate_nominal)||(ov->vi.bitrate_upper!=ov->vi.bitrate_nominal)?'V':'C');    if(rg_gain || rg_peak)      mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Gain = %+.2f dB, Peak = %.4f, Scale = %.2f\n", rg_gain, rg_peak, ov->rg_scale);    mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Encoded by: %s\n",vc.vendor);  }  vorbis_comment_clear(&vc);//  printf("lower=%d  upper=%d  \n",(int)ov->vi.bitrate_lower,(int)ov->vi.bitrate_upper);  // Setup the decoder  sh->channels=ov->vi.channels;   sh->samplerate=ov->vi.rate;  sh->samplesize=2;  // assume 128kbit if bitrate not specified in the header  sh->i_bps=((ov->vi.bitrate_nominal>0) ? ov->vi.bitrate_nominal : 128000)/8;  sh->context = ov;  /// Finish the decoder init  vorbis_synthesis_init(&ov->vd,&ov->vi);  vorbis_block_init(&ov->vd,&ov->vb);  mp_msg(MSGT_DECAUDIO,MSGL_V,"OggVorbis: Init OK!\n");  return 1;}static void uninit(sh_audio_t *sh){  struct ov_struct_st *ov = sh->context;  vorbis_dsp_clear(&ov->vd);  vorbis_block_clear(&ov->vb);  vorbis_info_clear(&ov->vi);  free(ov);}static int control(sh_audio_t *sh,int cmd,void* arg, ...){    switch(cmd)    {#if 0            case ADCTRL_RESYNC_STREAM:	  return CONTROL_TRUE;      case ADCTRL_SKIP_FRAME:	  return CONTROL_TRUE;#endif    }  return CONTROL_UNKNOWN;}static int decode_audio(sh_audio_t *sh,unsigned char *buf,int minlen,int maxlen){        int len = 0;        int samples;        float **pcm;        float scale;        struct ov_struct_st *ov = sh->context;	while(len < minlen) {	  while((samples=vorbis_synthesis_pcmout(&ov->vd,&pcm))<=0){	    ogg_packet op;	    memset(&op,0,sizeof(op)); //op.b_o_s = op.e_o_s = 0;	    op.bytes = ds_get_packet(sh->ds,&op.packet);	    if(op.bytes<=0) break;	    if(vorbis_synthesis(&ov->vb,&op)==0) /* test for success! */	      vorbis_synthesis_blockin(&ov->vd,&ov->vb);	  }	  if(samples<=0) break; // error/EOF	  while(samples>0){	    int i,j;	    int clipflag=0;	    int convsize=(maxlen-len)/(2*ov->vi.channels); // max size!	    int bout=((samples<convsize)?samples:convsize);	  	    if(bout<=0) break; // no buffer space	    /* convert floats to 16 bit signed ints (host order) and	       interleave */#ifdef TREMOR           if (ov->rg_scale_int == 64) {	    for(i=0;i<ov->vi.channels;i++){	      ogg_int16_t *convbuffer=(ogg_int16_t *)(&buf[len]);	      ogg_int16_t *ptr=convbuffer+i;	      ogg_int32_t  *mono=pcm[i];	      for(j=0;j<bout;j++){		int val=mono[j]>>9;		/* might as well guard against clipping */		if(val>32767){		  val=32767;		  clipflag=1;		}		if(val<-32768){		  val=-32768;		  clipflag=1;		}		*ptr=val;		ptr+=ov->vi.channels;	      }	    }	   } else#endif /* TREMOR */	   {#ifndef TREMOR            scale = 32767.f * ov->rg_scale;#endif	    for(i=0;i<ov->vi.channels;i++){	      ogg_int16_t *convbuffer=(ogg_int16_t *)(&buf[len]);	      ogg_int16_t *ptr=convbuffer+i;#ifdef TREMOR	      ogg_int32_t  *mono=pcm[i];	      for(j=0;j<bout;j++){		int val=(mono[j]*ov->rg_scale_int)>>(9+6);#else	      float  *mono=pcm[i];	      for(j=0;j<bout;j++){		int val=mono[j]*scale;		/* might as well guard against clipping */		if(val>32767){		  val=32767;		  clipflag=1;		}		if(val<-32768){		  val=-32768;		  clipflag=1;		}#endif    /* TREMOR */		*ptr=val;		ptr+=ov->vi.channels;	      }	    }	   }			    if(clipflag)	      mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"Clipping in frame %ld\n",(long)(ov->vd.sequence));	    len+=2*ov->vi.channels*bout;	    mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"\n[decoded: %d / %d ]\n",bout,samples);	    samples-=bout;	    vorbis_synthesis_read(&ov->vd,bout); /* tell libvorbis how						    many samples we						    actually consumed */	  } //while(samples>0)//          if (!samples) break; // why? how?	}  return len;}#endif /* !HAVE_OGGVORBIS */

⌨️ 快捷键说明

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