Beispiel #1
0
/* this is void and does not propogate errors up because we want to be
   able to open and use damaged bitstreams as well as we can.  Just
   watch out for missing information for links in the OggVorbis_File
   struct */
static void _prefetch_all_headers(OggVorbis_File *vf, ogg_int64_t dataoffset){
  ogg_page og;
  int i;
  ogg_int64_t ret;
  
  vf->vi=_ogg_realloc(vf->vi,vf->links*sizeof(*vf->vi));
  vf->vc=_ogg_realloc(vf->vc,vf->links*sizeof(*vf->vc));
  vf->dataoffsets=_ogg_malloc(vf->links*sizeof(*vf->dataoffsets));
  vf->pcmlengths=_ogg_malloc(vf->links*2*sizeof(*vf->pcmlengths));
  
  for(i=0;i<vf->links;i++){
    if(i==0){
      /* we already grabbed the initial header earlier.  Just set the offset */
      vf->dataoffsets[i]=dataoffset;
      _seek_helper(vf,dataoffset);

    }else{

      /* seek to the location of the initial header */

      _seek_helper(vf,vf->offsets[i]);
      if(_fetch_headers(vf,vf->vi+i,vf->vc+i,NULL,NULL)<0){
    	vf->dataoffsets[i]=-1;
      }else{
	vf->dataoffsets[i]=vf->offset;
      }
    }

    /* fetch beginning PCM offset */

    if(vf->dataoffsets[i]!=-1){
      ogg_int64_t accumulated=0;
      long        lastblock=-1;
      int         result;

      ogg_stream_reset_serialno(&vf->os,vf->serialnos[i]);

      while(1){
	ogg_packet op;

	ret=_get_next_page(vf,&og,-1);
	if(ret<0)
	  /* this should not be possible unless the file is
             truncated/mangled */
	  break;
       
	if(ogg_page_serialno(&og)!=vf->serialnos[i])
	  break;
	
	/* count blocksizes of all frames in the page */
	ogg_stream_pagein(&vf->os,&og);
	while((result=ogg_stream_packetout(&vf->os,&op))){
	  if(result>0){ /* ignore holes */
	    long thisblock=vorbis_packet_blocksize(vf->vi+i,&op);
	    if(lastblock!=-1)
	      accumulated+=(lastblock+thisblock)>>2;
	    lastblock=thisblock;
	  }
	}

	if(ogg_page_granulepos(&og)!=-1){
	  /* pcm offset of last packet on the first audio page */
	  accumulated= ogg_page_granulepos(&og)-accumulated;
	  break;
	}
      }

      /* less than zero?  This is a stream with samples trimmed off
         the beginning, a normal occurrence; set the offset to zero */
      if(accumulated<0)accumulated=0;

      vf->pcmlengths[i*2]=accumulated;
    }
Beispiel #2
0
static void _os_body_expand(ogg_stream_state *os,int needed){
  if(os->body_storage<=os->body_fill+needed){
    os->body_storage+=(needed+1024);
    os->body_data=_ogg_realloc(os->body_data,os->body_storage);
  }
}
Beispiel #3
0
void oc_enc_rc_resize(oc_enc_ctx *_enc){
  /*If encoding has not yet begun, reset the buffer state.*/
  if(_enc->state.curframe_num<0)oc_enc_rc_reset(_enc);
  else{
    int idt;
    /*Otherwise, update the bounds on the buffer, but not the current
       fullness.*/
    _enc->rc.bits_per_frame=(_enc->state.info.target_bitrate*
     (ogg_int64_t)_enc->state.info.fps_denominator)/
     _enc->state.info.fps_numerator;
    /*Insane framerates or frame sizes mean insane bitrates.
      Let's not get carried away.*/
    if(_enc->rc.bits_per_frame>0x400000000000LL){
      _enc->rc.bits_per_frame=(ogg_int64_t)0x400000000000LL;
    }
    else if(_enc->rc.bits_per_frame<32)_enc->rc.bits_per_frame=32;
    _enc->rc.buf_delay=OC_MAXI(_enc->rc.buf_delay,12);
    _enc->rc.max=_enc->rc.bits_per_frame*_enc->rc.buf_delay;
    _enc->rc.target=(_enc->rc.max+1>>1)+(_enc->rc.bits_per_frame+2>>2)*
     OC_MINI(_enc->keyframe_frequency_force,_enc->rc.buf_delay);
    /*Update the INTER-frame scale filter delay.
      We jump to it immediately if we've already seen enough frames; otherwise
       it is simply set as the new target.*/
    _enc->rc.inter_delay_target=idt=OC_MAXI(_enc->rc.buf_delay>>1,10);
    if(idt<OC_MINI(_enc->rc.inter_delay,_enc->rc.inter_count)){
      oc_iir_filter_init(&_enc->rc.scalefilter[1],idt,
       _enc->rc.scalefilter[1].y[0]);
      _enc->rc.inter_delay=idt;
    }
  }
  /*If we're in pass-2 mode, make sure the frame metrics array is big enough
     to hold frame statistics for the full buffer.*/
  if(_enc->rc.twopass==2){
    int cfm;
    int buf_delay;
    int reset_window;
    buf_delay=_enc->rc.buf_delay;
    reset_window=_enc->rc.frame_metrics==NULL&&(_enc->rc.frames_total[0]==0||
     buf_delay<_enc->rc.frames_total[0]+_enc->rc.frames_total[1]
     +_enc->rc.frames_total[2]);
    cfm=_enc->rc.cframe_metrics;
    /*Only try to resize the frame metrics buffer if a) it's too small and
       b) we were using a finite buffer, or are about to start.*/
    if(cfm<buf_delay&&(_enc->rc.frame_metrics!=NULL||reset_window)){
      oc_frame_metrics *fm;
      int               nfm;
      int               fmh;
      fm=(oc_frame_metrics *)_ogg_realloc(_enc->rc.frame_metrics,
       buf_delay*sizeof(*_enc->rc.frame_metrics));
      if(fm==NULL){
        /*We failed to allocate a finite buffer.*/
        /*If we don't have a valid 2-pass header yet, just return; we'll reset
           the buffer size when we read the header.*/
        if(_enc->rc.frames_total[0]==0)return;
        /*Otherwise revert to the largest finite buffer previously set, or to
           whole-file buffering if we were still using that.*/
        _enc->rc.buf_delay=_enc->rc.frame_metrics!=NULL?
         cfm:_enc->rc.frames_total[0]+_enc->rc.frames_total[1]
         +_enc->rc.frames_total[2];
        oc_enc_rc_resize(_enc);
        return;
      }
      _enc->rc.frame_metrics=fm;
      _enc->rc.cframe_metrics=buf_delay;
      /*Re-organize the circular buffer.*/
      fmh=_enc->rc.frame_metrics_head;
      nfm=_enc->rc.nframe_metrics;
      if(fmh+nfm>cfm){
        int shift;
        shift=OC_MINI(fmh+nfm-cfm,buf_delay-cfm);
        memcpy(fm+cfm,fm,OC_MINI(fmh+nfm-cfm,buf_delay-cfm)*sizeof(*fm));
        if(fmh+nfm>buf_delay)memmove(fm,fm+shift,fmh+nfm-buf_delay);
      }
    }
    /*We were using whole-file buffering; now we're not.*/
    if(reset_window){
      _enc->rc.nframes[0]=_enc->rc.nframes[1]=_enc->rc.nframes[2]=0;
      _enc->rc.scale_sum[0]=_enc->rc.scale_sum[1]=0;
      _enc->rc.scale_window_end=_enc->rc.scale_window0=
       _enc->state.curframe_num+_enc->prev_dup_count+1;
      if(_enc->rc.twopass_buffer_bytes){
        int qti;
        /*We already read the metrics for the first frame in the window.*/
        *(_enc->rc.frame_metrics)=*&_enc->rc.cur_metrics;
        _enc->rc.nframe_metrics++;
        qti=_enc->rc.cur_metrics.frame_type;
        _enc->rc.nframes[qti]++;
        _enc->rc.nframes[2]+=_enc->rc.cur_metrics.dup_count;
        _enc->rc.scale_sum[qti]+=oc_bexp_q24(_enc->rc.cur_metrics.log_scale);
        _enc->rc.scale_window_end+=_enc->rc.cur_metrics.dup_count+1;
        if(_enc->rc.scale_window_end-_enc->rc.scale_window0<buf_delay){
          /*We need more frame data.*/
          _enc->rc.twopass_buffer_bytes=0;
        }
      }
    }
    /*Otherwise, we could shrink the size of the current window, if necessary,
       but leaving it like it is lets us adapt to the new buffer size more
       gracefully.*/
  }
}
Beispiel #4
0
int main(int argc,char *argv[]){
  char *basename;
  codebook **b=_ogg_calloc(1,sizeof(codebook *));
  int *addmul=_ogg_calloc(1,sizeof(int));
  int books=0;
  int input=0;
  int interleave=0;
  int j;
  int start=0;
  int num=-1;
  argv++;

  if(*argv==NULL){
    process_usage();
    exit(1);
  }

  /* yes, this is evil.  However, it's very convenient to parse file
     extentions */

  while(*argv){
    if(*argv[0]=='-'){
      /* option */
      if(argv[0][1]=='s'){
	/* subvector */
	if(sscanf(argv[1],"%d,%d",&start,&num)!=2){
	  num= -1;
	  if(sscanf(argv[1],"%d",&start)!=1){
	    fprintf(stderr,"Syntax error using -s\n");
	    exit(1);
	  }
	}
	argv+=2;
      }
      if(argv[0][1]=='i'){
	/* interleave */
	interleave=1;
	argv+=1;
      }
    }else{
      /* input file.  What kind? */
      char *dot;
      char *ext=NULL;
      char *name=strdup(*argv++);
      dot=strrchr(name,'.');
      if(dot)
	ext=dot+1;
      else
	ext="";

      /* codebook */
      if(!strcmp(ext,"vqh")){
	int multp=0;
	if(input){
	  fprintf(stderr,"specify all input data (.vqd) files following\n"
		  "codebook header (.vqh) files\n");
	  exit(1);
	}
	/* is it additive or multiplicative? */
	if(name[0]=='*'){
	  multp=1;
	  name++;
	}
	if(name[0]=='+')name++;

	basename=strrchr(name,'/');
	if(basename)
	  basename=strdup(basename)+1;
	else
	  basename=strdup(name);
	dot=strrchr(basename,'.');
	if(dot)*dot='\0';

	b=_ogg_realloc(b,sizeof(codebook *)*(books+2));
	b[books]=codebook_load(name);
	addmul=_ogg_realloc(addmul,sizeof(int)*(books+1));
	addmul[books++]=multp;
	b[books]=NULL;
      }

      /* data file */
      if(!strcmp(ext,"vqd")){
	int cols;
	long lines=0;
	char *line;
	float *vec;
	FILE *in=fopen(name,"r");
	if(!in){
	  fprintf(stderr,"Could not open input file %s\n",name);
	  exit(1);
	}

	if(!input){
	  process_preprocess(b,basename);
	  input++;
	}

	reset_next_value();
	line=setup_line(in);
	/* count cols before we start reading */
	{
	  char *temp=line;
	  while(*temp==' ')temp++;
	  for(cols=0;*temp;cols++){
	    while(*temp>32)temp++;
	    while(*temp==' ')temp++;
	  }
	}
	vec=alloca(cols*sizeof(float));
	while(line){
	  lines++;
	  for(j=0;j<cols;j++)
	    if(get_line_value(in,vec+j)){
	      fprintf(stderr,"Too few columns on line %ld in data file\n",lines);
	      exit(1);
	    }
	  /* ignores -s for now */
	  process_vector(b,addmul,interleave,vec,cols);

	  line=setup_line(in);
	}
	fclose(in);
      }
    }
  }

  /* take any data from stdin */
  {
    struct stat st;
    if(fstat(STDIN_FILENO,&st)==-1){
      fprintf(stderr,"Could not stat STDIN\n");
      exit(1);
    }
    if((S_IFIFO|S_IFREG|S_IFSOCK)&st.st_mode){
      int cols;
      char *line;
      long lines=0;
      float *vec;
      if(!input){
	process_preprocess(b,basename);
	input++;
      }
      
      line=setup_line(stdin);
      /* count cols before we start reading */
      {
	char *temp=line;
	while(*temp==' ')temp++;
	for(cols=0;*temp;cols++){
	  while(*temp>32)temp++;
	  while(*temp==' ')temp++;
	}
      }
      vec=alloca(cols*sizeof(float));
      while(line){
	lines++;
	for(j=0;j<cols;j++)
	  if(get_line_value(stdin,vec+j)){
	    fprintf(stderr,"Too few columns on line %ld in data file\n",lines);
	    exit(1);
	  }
	/* ignores -s for now */
	process_vector(b,addmul,interleave,vec,cols);
	
	line=setup_line(stdin);
      }
    }
  }

  process_postprocess(b,basename);

  return 0;
}
Beispiel #5
0
int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){
  vorbis_info *vi=v->vi;
  codec_setup_info *ci=vi->codec_setup;

  /* Shift out any PCM that we returned previously */
  /* centerW is currently the center of the last block added */

  if(v->centerW>ci->blocksizes[1]/2 &&
  /* Quick additional hack; to avoid *alot* of shifts, use an
     oversized buffer.  This increases memory usage, but doesn't make
     much difference wrt L1/L2 cache pressure. */
     v->pcm_returned>8192){

    /* don't shift too much; we need to have a minimum PCM buffer of
       1/2 long block */

    int shiftPCM=v->centerW-ci->blocksizes[1]/2;
    shiftPCM=(v->pcm_returned<shiftPCM?v->pcm_returned:shiftPCM);

    v->pcm_current-=shiftPCM;
    v->centerW-=shiftPCM;
    v->pcm_returned-=shiftPCM;
    
    if(shiftPCM){
      int i;
      for(i=0;i<vi->channels;i++)
	memmove(v->pcm[i],v->pcm[i]+shiftPCM,
		v->pcm_current*sizeof(*v->pcm[i]));
    }
  }

  v->lW=v->W;
  v->W=vb->W;
  v->nW=-1;

  v->glue_bits+=vb->glue_bits;
  v->time_bits+=vb->time_bits;
  v->floor_bits+=vb->floor_bits;
  v->res_bits+=vb->res_bits;

  if(v->sequence+1 != vb->sequence)v->granulepos=-1; /* out of sequence;
                                                     lose count */

  v->sequence=vb->sequence;

  {
    int sizeW=ci->blocksizes[v->W];
    int centerW=v->centerW+ci->blocksizes[v->lW]/4+sizeW/4;
    int beginW=centerW-sizeW/2;
    int endW=beginW+sizeW;
    int beginSl;
    int endSl;
    int i,j;

    /* Do we have enough PCM/mult storage for the block? */
    if(endW>v->pcm_storage){
      /* expand the storage */
      v->pcm_storage=endW+ci->blocksizes[1];
   
      for(i=0;i<vi->channels;i++)
	v->pcm[i]=_ogg_realloc(v->pcm[i],v->pcm_storage*sizeof(*v->pcm[i])); 
    }

    /* overlap/add PCM */

    switch((int)v->W){
    case 0:
      beginSl=0;
      endSl=ci->blocksizes[0]/2;
      break;
    case 1:
      beginSl=ci->blocksizes[1]/4-ci->blocksizes[v->lW]/4;
      endSl=beginSl+ci->blocksizes[v->lW]/2;
      break;
    default:
      return(-1);
    }

    for(j=0;j<vi->channels;j++){
      float *pcm=v->pcm[j]+beginW;
      float *p=vb->pcm[j];

      /* the overlap/add section */
      for(i=beginSl;i<endSl;i++)
	pcm[i]+=p[i];
      /* the remaining section */
      for(;i<sizeW;i++)
	pcm[i]=p[i];

    }

    /* deal with initial packet state; we do this using the explicit
       pcm_returned==-1 flag otherwise we're sensitive to first block
       being short or long */

    if(v->pcm_returned==-1)
      v->pcm_returned=centerW;

    /* track the frame number... This is for convenience, but also
       making sure our last packet doesn't end with added padding.  If
       the last packet is partial, the number of samples we'll have to
       return will be past the vb->granulepos.
       
       This is not foolproof!  It will be confused if we begin
       decoding at the last page after a seek or hole.  In that case,
       we don't have a starting point to judge where the last frame
       is.  For this reason, vorbisfile will always try to make sure
       it reads the last two marked pages in proper sequence */

    if(v->granulepos==-1)
      if(vb->granulepos==-1){
	v->granulepos=0;
      }else{
	v->granulepos=vb->granulepos;
      }
    else{
      v->granulepos+=(centerW-v->centerW);
      if(vb->granulepos!=-1 && v->granulepos!=vb->granulepos){

	if(v->granulepos>vb->granulepos){
	  long extra=v->granulepos-vb->granulepos;

	  if(vb->eofflag){
	    /* partial last frame.  Strip the extra samples off */
	    centerW-=extra;
	  }else if(vb->sequence == 1){
	    /* ^^^ argh, this can be 1 from seeking! */


	    /* partial first frame.  Discard extra leading samples */
	    v->pcm_returned+=extra;
	    if(v->pcm_returned>centerW)v->pcm_returned=centerW;
	    
	  }
	  
	}/* else{ Shouldn't happen *unless* the bitstream is out of
	    spec.  Either way, believe the bitstream } */
	v->granulepos=vb->granulepos;
      }
    }

    /* Update, cleanup */

    v->centerW=centerW;
    v->pcm_current=endW;

    if(vb->eofflag)v->eofflag=1;
  }

  return(0);
}
Beispiel #6
0
long _ve_envelope_search(vorbis_dsp_state *v){
  vorbis_info *vi=v->vi;
  codec_setup_info *ci=vi->codec_setup;
  vorbis_info_psy_global *gi=&ci->psy_g_param;
  envelope_lookup *ve=((backend_lookup_state *)(v->backend_state))->ve;
  long i,j;

  int first=ve->current/ve->searchstep;
  int last=v->pcm_current/ve->searchstep-VE_WIN;
  if(first<0)first=0;

  /* make sure we have enough storage to match the PCM */
  if(last+VE_WIN+VE_POST>ve->storage){
    ve->storage=last+VE_WIN+VE_POST; /* be sure */
    ve->mark=_ogg_realloc(ve->mark,ve->storage*sizeof(*ve->mark));
  }

  for(j=first;j<last;j++){
    int ret=0;

    ve->stretch++;
    if(ve->stretch>VE_MAXSTRETCH*2)
      ve->stretch=VE_MAXSTRETCH*2;
    
    for(i=0;i<ve->ch;i++){
      float *pcm=v->pcm[i]+ve->searchstep*(j);
      ret|=_ve_amp(ve,gi,pcm,ve->band,ve->filter+i*VE_BANDS,j);
    }

    ve->mark[j+VE_POST]=0;
    if(ret&1){
      ve->mark[j]=1;
      ve->mark[j+1]=1;
    }

    if(ret&2){
      ve->mark[j]=1;
      if(j>0)ve->mark[j-1]=1;
    }

    if(ret&4)ve->stretch=-1;
  }

  ve->current=last*ve->searchstep;

  {
    long centerW=v->centerW;
    long testW=
      centerW+
      ci->blocksizes[v->W]/4+
      ci->blocksizes[1]/2+
      ci->blocksizes[0]/4;
    
    j=ve->cursor;
    
    while(j<ve->current-(ve->searchstep)){/* account for postecho
                                             working back one window */
      if(j>=testW)return(1);
 
      ve->cursor=j;

      if(ve->mark[j/ve->searchstep]){
	if(j>centerW){

	  #if 0
	  if(j>ve->curmark){
	    float *marker=alloca(v->pcm_current*sizeof(*marker));
	    int l,m;
	    memset(marker,0,sizeof(*marker)*v->pcm_current);
	    fprintf(stderr,"mark! seq=%d, cursor:%fs time:%fs\n",
		    seq,
		    (totalshift+ve->cursor)/44100.,
		    (totalshift+j)/44100.);
	    _analysis_output_always("pcmL",seq,v->pcm[0],v->pcm_current,0,0,totalshift);
	    _analysis_output_always("pcmR",seq,v->pcm[1],v->pcm_current,0,0,totalshift);

	    _analysis_output_always("markL",seq,v->pcm[0],j,0,0,totalshift);
	    _analysis_output_always("markR",seq,v->pcm[1],j,0,0,totalshift);
	    
	    for(m=0;m<VE_BANDS;m++){
	      char buf[80];
	      sprintf(buf,"delL%d",m);
	      for(l=0;l<last;l++)marker[l*ve->searchstep]=ve->filter[m].markers[l]*.1;
	      _analysis_output_always(buf,seq,marker,v->pcm_current,0,0,totalshift);
	    }

	    for(m=0;m<VE_BANDS;m++){
	      char buf[80];
	      sprintf(buf,"delR%d",m);
	      for(l=0;l<last;l++)marker[l*ve->searchstep]=ve->filter[m+VE_BANDS].markers[l]*.1;
	      _analysis_output_always(buf,seq,marker,v->pcm_current,0,0,totalshift);
	    }

	    for(l=0;l<last;l++)marker[l*ve->searchstep]=ve->mark[l]*.4;
	    _analysis_output_always("mark",seq,marker,v->pcm_current,0,0,totalshift);
	   
	    
	    seq++;
	    
	  }
#endif

	  ve->curmark=j;
	  if(j>=testW)return(1);
	  return(0);
	}
      }
      j+=ve->searchstep;
    }
  }
  
  return(-1);
}
Beispiel #7
0
static void _os_body_expand(ogg_stream_state *os,int needed){
  if(os->body_storage<=os->body_fill+needed){
    os->body_storage+=(needed+1024);
    os->body_data=(unsigned char*) _ogg_realloc(os->body_data,os->body_storage*sizeof(*os->body_data));
  }
}