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

📄 vorbisfile.c

📁 在x86平台上运行不可信任代码的sandbox。
💻 C
📖 第 1 页 / 共 4 页
字号:
    ogg_stream_reset(&work_os); /* eliminate the spurious OV_HOLE                                   return from not necessarily                                   starting from the beginning */    while(1){      if(vf->ready_state>=STREAMSET){	/* snarf/scan a packet if we can */	int result=ogg_stream_packetout(&work_os,&op);      	if(result>0){	  if(vf->vi[vf->current_link].codec_setup){	    thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);	    if(thisblock<0){	      ogg_stream_packetout(&vf->os,NULL);	      thisblock=0;	    }else{	      	      if(eosflag)	      ogg_stream_packetout(&vf->os,NULL);	      else		if(lastblock)accblock+=(lastblock+thisblock)>>2;	    }	    	    if(op.granulepos!=-1){	      int i,link=vf->current_link;	      ogg_int64_t granulepos=op.granulepos-vf->pcmlengths[link*2];	      if(granulepos<0)granulepos=0;	      	      for(i=0;i<link;i++)		granulepos+=vf->pcmlengths[i*2+1];	      vf->pcm_offset=granulepos-accblock;	      break;	    }	    lastblock=thisblock;	    continue;	  }else	    ogg_stream_packetout(&vf->os,NULL);	}      }            if(!lastblock){	if(_get_next_page(vf,&og,-1)<0){	  vf->pcm_offset=ov_pcm_total(vf,-1);	  break;	}      }else{	/* huh?  Bogus stream with packets but no granulepos */	vf->pcm_offset=-1;	break;      }            /* has our decoding just traversed a bitstream boundary? */      if(vf->ready_state>=STREAMSET)	if(vf->current_serialno!=ogg_page_serialno(&og)){	  _decode_clear(vf); /* clear out stream state */	  ogg_stream_clear(&work_os);	}      if(vf->ready_state<STREAMSET){	int link;		vf->current_serialno=ogg_page_serialno(&og);	for(link=0;link<vf->links;link++)	  if(vf->serialnos[link]==vf->current_serialno)break;	if(link==vf->links)goto seek_error; /* sign of a bogus stream.					       error out, leave					       machine uninitialized */	vf->current_link=link;		ogg_stream_reset_serialno(&vf->os,vf->current_serialno);	ogg_stream_reset_serialno(&work_os,vf->current_serialno); 	vf->ready_state=STREAMSET;	      }          ogg_stream_pagein(&vf->os,&og);      ogg_stream_pagein(&work_os,&og);      eosflag=ogg_page_eos(&og);    }  }  ogg_stream_clear(&work_os);  vf->bittrack=0.f;  vf->samptrack=0.f;  return(0); seek_error:  /* dump the machine so we're in a known state */  vf->pcm_offset=-1;  ogg_stream_clear(&work_os);  _decode_clear(vf);  return OV_EBADLINK;}/* Page granularity seek (faster than sample granularity because we   don't do the last bit of decode to find a specific sample).   Seek to the last [granule marked] page preceeding the specified pos   location, such that decoding past the returned point will quickly   arrive at the requested position. */int ov_pcm_seek_page(OggVorbis_File *vf,ogg_int64_t pos){  int link=-1;  ogg_int64_t result=0;  ogg_int64_t total=ov_pcm_total(vf,-1);  if(vf->ready_state<OPENED)return(OV_EINVAL);  if(!vf->seekable)return(OV_ENOSEEK);  if(pos<0 || pos>total)return(OV_EINVAL);   /* which bitstream section does this pcm offset occur in? */  for(link=vf->links-1;link>=0;link--){    total-=vf->pcmlengths[link*2+1];    if(pos>=total)break;  }  /* search within the logical bitstream for the page with the highest     pcm_pos preceeding (or equal to) pos.  There is a danger here;     missing pages or incorrect frame number information in the     bitstream could make our task impossible.  Account for that (it     would be an error condition) */  /* new search algorithm by HB (Nicholas Vinen) */  {    ogg_int64_t end=vf->offsets[link+1];    ogg_int64_t begin=vf->offsets[link];    ogg_int64_t begintime = vf->pcmlengths[link*2];    ogg_int64_t endtime = vf->pcmlengths[link*2+1]+begintime;    ogg_int64_t target=pos-total+begintime;    ogg_int64_t best=begin;        ogg_page og;    while(begin<end){      ogg_int64_t bisect;            if(end-begin<CHUNKSIZE){	bisect=begin;      }else{	/* take a (pretty decent) guess. */	bisect=begin + 	  (target-begintime)*(end-begin)/(endtime-begintime) - CHUNKSIZE;	if(bisect<=begin)	  bisect=begin+1;      }            _seek_helper(vf,bisect);          while(begin<end){	result=_get_next_page(vf,&og,end-vf->offset);	if(result==OV_EREAD) goto seek_error;	if(result<0){	  if(bisect<=begin+1)	    end=begin; /* found it */	  else{	    if(bisect==0) goto seek_error;	    bisect-=CHUNKSIZE;	    if(bisect<=begin)bisect=begin+1;	    _seek_helper(vf,bisect);	  }	}else{	  ogg_int64_t granulepos=ogg_page_granulepos(&og);	  if(granulepos==-1)continue;	  if(granulepos<target){	    best=result;  /* raw offset of packet with granulepos */ 	    begin=vf->offset; /* raw offset of next page */	    begintime=granulepos;	    	    if(target-begintime>44100)break;	    bisect=begin; /* *not* begin + 1 */	  }else{	    if(bisect<=begin+1)	      end=begin;  /* found it */	    else{	      if(end==vf->offset){ /* we're pretty close - we'd be stuck in */		end=result;		bisect-=CHUNKSIZE; /* an endless loop otherwise. */		if(bisect<=begin)bisect=begin+1;		_seek_helper(vf,bisect);	      }else{		end=result;		endtime=granulepos;		break;	      }	    }	  }	}      }    }    /* found our page. seek to it, update pcm offset. Easier case than       raw_seek, don't keep packets preceeding granulepos. */    {      ogg_page og;      ogg_packet op;            /* seek */      _seek_helper(vf,best);      vf->pcm_offset=-1;            if(_get_next_page(vf,&og,-1)<0)return(OV_EOF); /* shouldn't happen */            if(link!=vf->current_link){	/* Different link; dump entire decode machine */	_decode_clear(vf);  		vf->current_link=link;	vf->current_serialno=ogg_page_serialno(&og);	vf->ready_state=STREAMSET;	      }else{	vorbis_synthesis_restart(&vf->vd);      }      ogg_stream_reset_serialno(&vf->os,vf->current_serialno);      ogg_stream_pagein(&vf->os,&og);      /* pull out all but last packet; the one with granulepos */      while(1){	result=ogg_stream_packetpeek(&vf->os,&op);	if(result==0){	  /* !!! the packet finishing this page originated on a             preceeding page. Keep fetching previous pages until we             get one with a granulepos or without the 'continued' flag             set.  Then just use raw_seek for simplicity. */	  	  _seek_helper(vf,best);	  	  while(1){	    result=_get_prev_page(vf,&og);	    if(result<0) goto seek_error;	    if(ogg_page_granulepos(&og)>-1 ||	       !ogg_page_continued(&og)){	      return ov_raw_seek(vf,result);	    }	    vf->offset=result;	  }	}	if(result<0){	  result = OV_EBADPACKET; 	  goto seek_error;	}	if(op.granulepos!=-1){	  vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2];	  if(vf->pcm_offset<0)vf->pcm_offset=0;	  vf->pcm_offset+=total;	  break;	}else	  result=ogg_stream_packetout(&vf->os,NULL);      }    }  }    /* verify result */  if(vf->pcm_offset>pos || pos>ov_pcm_total(vf,-1)){    result=OV_EFAULT;    goto seek_error;  }  vf->bittrack=0.f;  vf->samptrack=0.f;  return(0);   seek_error:  /* dump machine so we're in a known state */  vf->pcm_offset=-1;  _decode_clear(vf);  return (int)result;}/* seek to a sample offset relative to the decompressed pcm stream    returns zero on success, nonzero on failure */int ov_pcm_seek(OggVorbis_File *vf,ogg_int64_t pos){  int thisblock,lastblock=0;  int ret=ov_pcm_seek_page(vf,pos);  if(ret<0)return(ret);  if((ret=_make_decode_ready(vf)))return ret;  /* discard leading packets we don't need for the lapping of the     position we want; don't decode them */  while(1){    ogg_packet op;    ogg_page og;    int ret=ogg_stream_packetpeek(&vf->os,&op);    if(ret>0){      thisblock=vorbis_packet_blocksize(vf->vi+vf->current_link,&op);      if(thisblock<0){	ogg_stream_packetout(&vf->os,NULL);	continue; /* non audio packet */      }      if(lastblock)vf->pcm_offset+=(lastblock+thisblock)>>2;            if(vf->pcm_offset+((thisblock+			  vorbis_info_blocksize(vf->vi,1))>>2)>=pos)break;            /* remove the packet from packet queue and track its granulepos */      ogg_stream_packetout(&vf->os,NULL);      vorbis_synthesis_trackonly(&vf->vb,&op);  /* set up a vb with                                                   only tracking, no                                                   pcm_decode */      vorbis_synthesis_blockin(&vf->vd,&vf->vb);             /* end of logical stream case is hard, especially with exact	 length positioning. */            if(op.granulepos>-1){	int i;	/* always believe the stream markers */	vf->pcm_offset=op.granulepos-vf->pcmlengths[vf->current_link*2];	if(vf->pcm_offset<0)vf->pcm_offset=0;	for(i=0;i<vf->current_link;i++)	  vf->pcm_offset+=vf->pcmlengths[i*2+1];      }	      lastblock=thisblock;          }else{      if(ret<0 && ret!=OV_HOLE)break;            /* suck in a new page */      if(_get_next_page(vf,&og,-1)<0)break;      if(vf->current_serialno!=ogg_page_serialno(&og))_decode_clear(vf);            if(vf->ready_state<STREAMSET){	int link;		vf->current_serialno=ogg_page_serialno(&og);	for(link=0;link<vf->links;link++)	  if(vf->serialnos[link]==vf->current_serialno)break;	if(link==vf->links)return(OV_EBADLINK);	vf->current_link=link;		ogg_stream_reset_serialno(&vf->os,vf->current_serialno); 	vf->ready_state=STREAMSET;      	ret=_make_decode_ready(vf);	if(ret)return ret;	lastblock=0;      }      ogg_stream_pagein(&vf->os,&og);    }  }  vf->bittrack=0.f;  vf->samptrack=0.f;  /* discard samples until we reach the desired position. Crossing a     logical bitstream boundary with abandon is OK. */  while(vf->pcm_offset<pos){    ogg_int64_t target=pos-vf->pcm_offset;    long samples=vorbis_synthesis_pcmout(&vf->vd,NULL);    if(samples>target)samples=target;    vorbis_synthesis_read(&vf->vd,samples);    vf->pcm_offset+=samples;        if(samples<target)      if(_fetch_and_process_packet(vf,NULL,1,1)<=0)	vf->pcm_offset=ov_pcm_total(vf,-1); /* eof */  }  return 0;}/* seek to a playback time relative to the decompressed pcm stream    returns zero on success, nonzero on failure */int ov_time_seek(OggVorbis_File *vf,double seconds){  /* translate time to PCM position and call ov_pcm_seek */  int link=-1;  ogg_int64_t pcm_total=ov_pcm_total(vf,-1);  double time_total=ov_time_total(vf,-1);  if(vf->ready_state<OPENED)return(OV_EINVAL);  if(!vf->seekable)return(OV_ENOSEEK);  if(seconds<0 || seconds>time_total)return(OV_EINVAL);    /* which bitstream section does this time offset occur in? */  for(link=vf->links-1;link>=0;link--){    pcm_total-=vf->pcmlengths[link*2+1];    time_total-=ov_time_total(vf,link);    if(seconds>=time_total)break;  }  /* enough information to convert time offset to pcm offset */  {    ogg_int64_t target=pcm_total+(seconds-time_total)*vf->vi[link].rate;    return(ov_pcm_seek(vf,target));  }}/* page-granularity version of ov_time_seek    returns zero on success, nonzero on failure */int ov_time_seek_page(OggVorbis_File *vf,double seconds){  /* translate time to PCM position and call ov_pcm_seek */  int link=-1;  ogg_int64_t pcm_total=ov_pcm_total(vf,-1);  double time_total=ov_time_total(vf,-1);  if(vf->ready_state<OPENED)return(OV_EINVAL);  if(!vf->seekable)return(OV_ENOSEEK);  if(seconds<0 || seconds>time_total)return(OV_EINVAL);    /* which bitstream section does this time offset occur in? */  for(link=vf->links-1;link>=0;link--){    pcm_total-=vf->pcmlengths[link*2+1];    time_total-=ov_time_total(vf,link);    if(seconds>=time_total)break;  }  /* enough information to convert time offset to pcm offset */  {    ogg_int64_t target=pcm_total+(seconds-time_total)*vf->vi[link].rate;    return(ov_pcm_seek_page(vf,target));  }}/* tell the current stream offset cursor.  Note that seek followed by   tell will likely not give the set offset due to caching */ogg_int64_t ov_raw_tell(OggVorbis_File *vf){  if(vf->ready_state<OPENED)return(OV_EINVAL);  return(vf->offset);}/* return PCM offset (sample) of next PCM sample to be read */ogg_int64_t ov_pcm_tell(OggVorbis_File *vf){  if(vf->ready_state<OPENED)return(OV_EINVAL);  return(vf->pcm_offset);}/* return time offset (seconds) of next PCM sample to be read */double ov_time_tell(OggVorbis_File *vf){  int link=0;  ogg_int64_t pcm_total=0;  double time_total=0.f;    if(vf->ready_state<OPENED)return(OV_EINVAL);  if(vf->seekable){    pcm_total=ov_pcm_total(vf,-1);    time_total=ov_time_total(vf,-1);      /* which bitstream section does this time offset occur in? */    for(link=vf->links-1;link>=0;link--){      pcm_total-=vf->pcmlengths[link*2+1];      time_total-=ov_time_total(vf,link);      if(vf->pcm_offset>=pcm_total)break;    }  }  return((double)time_total+(double)(vf->pcm_offset-pcm_total)/vf->vi[link].rate);}/*  link:   -1) return the vorbis_info struct for the bitstream section                currently being decoded           0-n) to request information for a specific bitstream section        In the case of a non-seekable bitstream, any call returns the    current bitstream.  NULL in the case that the machine is not    initialized */vorbis_info *ov_info(OggVorbis_File *vf,int link){  if(vf->seekable){    if(link<0)      if(vf->ready_state>=STREAMSET)	return vf->vi+vf->current_link;      else      return vf->vi;    else      if(link>=vf->links)	return NULL;      else	return vf->vi+link;  }else{    return vf->vi;  }}/* grr, strong typing, grr, no templates/inheritence, grr */vorbis_comment *ov_comment(OggVorbis_File *vf,int link){  if(vf->seekable){    if(link<0)      if(vf->ready_state>=STREAMSET)	return vf->vc+vf->current_link;      else	return vf->vc;    else      if(link>=vf->links)	return NULL;      else	return vf->vc+link;  }else{    return vf->vc;  }}

⌨️ 快捷键说明

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