示例#1
0
/* public */
static void
vorbis_stream_decode(struct decoder *decoder,
		     struct input_stream *input_stream)
{
	GError *error = NULL;
	OggVorbis_File vf;
	struct vorbis_input_stream vis;
	struct audio_format audio_format;
	float total_time;
	int current_section;
	int prev_section = -1;
	long ret;
	char chunk[OGG_CHUNK_SIZE];
	long bitRate = 0;
	long test;
	const vorbis_info *vi;
	enum decoder_command cmd = DECODE_COMMAND_NONE;

	if (ogg_stream_type_detect(input_stream) != VORBIS)
		return;

	/* rewind the stream, because ogg_stream_type_detect() has
	   moved it */
	input_stream_lock_seek(input_stream, 0, SEEK_SET, NULL);

	if (!vorbis_is_open(&vis, &vf, decoder, input_stream))
		return;

	vi = ov_info(&vf, -1);
	if (vi == NULL) {
		g_warning("ov_info() has failed");
		return;
	}

	if (!audio_format_init_checked(&audio_format, vi->rate,
				       SAMPLE_FORMAT_S16,
				       vi->channels, &error)) {
		g_warning("%s", error->message);
		g_error_free(error);
		return;
	}

	total_time = ov_time_total(&vf, -1);
	if (total_time < 0)
		total_time = 0;

	decoder_initialized(decoder, &audio_format, vis.seekable, total_time);

	do {
		if (cmd == DECODE_COMMAND_SEEK) {
			double seek_where = decoder_seek_where(decoder);
			if (0 == ov_time_seek_page(&vf, seek_where)) {
				decoder_command_finished(decoder);
			} else
				decoder_seek_error(decoder);
		}

		ret = ov_read(&vf, chunk, sizeof(chunk),
			      OGG_DECODE_USE_BIGENDIAN, 2, 1, &current_section);
		if (ret == OV_HOLE) /* bad packet */
			ret = 0;
		else if (ret <= 0)
			/* break on EOF or other error */
			break;

		if (current_section != prev_section) {
			char **comments;

			vi = ov_info(&vf, -1);
			if (vi == NULL) {
				g_warning("ov_info() has failed");
				break;
			}

			if (vi->rate != (long)audio_format.sample_rate ||
			    vi->channels != (int)audio_format.channels) {
				/* we don't support audio format
				   change yet */
				g_warning("audio format change, stopping here");
				break;
			}

			comments = ov_comment(&vf, -1)->user_comments;
			vorbis_send_comments(decoder, input_stream, comments);

			struct replay_gain_info rgi;
			if (vorbis_comments_to_replay_gain(&rgi, comments))
				decoder_replay_gain(decoder, &rgi);

			prev_section = current_section;
		}

		if ((test = ov_bitrate_instant(&vf)) > 0)
			bitRate = test / 1000;

		cmd = decoder_data(decoder, input_stream,
				   chunk, ret,
				   bitRate);
	} while (cmd != DECODE_COMMAND_STOP);

	ov_clear(&vf);
}
示例#2
0
CBaseDec::RetCode COggDec::Decoder(FILE *in, const int OutputFd, State* const state, CAudioMetaData* meta_data, time_t* const time_played, unsigned int* const secondsToSkip)
{
  OggVorbis_File vf;
  int bitstream, rval;
  ogg_int64_t jumptime=0;
  Status=OK;
  mOutputFd = OutputFd;
  mState = state;
  mTimePlayed=time_played;

  if (!Open(in, &vf))
  {
	  Status=DATA_ERR;
	  return Status;
  }

  SetMetaData(&vf, meta_data);

#if __BYTE_ORDER == __LITTLE_ENDIAN || USE_TREMOR
  audioDecoder->PrepareClipPlay(ov_info(&vf,0)->channels, ov_info(&vf,0)->rate, 16, 1);
#else
  audioDecoder->PrepareClipPlay(ov_info(&vf,0)->channels, ov_info(&vf,0)->rate, 16, 0);
#endif

  /* up and away ... */
  mSlotSize = MAX_OUTPUT_SAMPLES * 2 * ov_info(&vf,0)->channels;
  for(int i = 0 ; i < DECODE_SLOTS ; i++)
  {
	  if ((mPcmSlots[i] = (char*) malloc(mSlotSize)) == NULL)
	  {
		  for (int j = i - 1; j >= 0; j--)
		  {
			  free(mPcmSlots[j]);
		  }
		  Status=INTERNAL_ERR;
		  return Status;
	  }
	  mSlotTime[i]=0;
  }
  mReadSlot=mWriteSlot=0;

  pthread_t OutputThread;
  if (pthread_create (&OutputThread, 0, OutputDsp, (void *) this) != 0 )
  {
	  for(int i = 0 ; i < DECODE_SLOTS ; i++)
		  free(mPcmSlots[i]);
	  Status=INTERNAL_ERR;
	  return Status;
  }

  int bytes;
  State oldstate=*state;
  do
  {
	  // clear buffer on state change
	  if(oldstate!=*state)
	  {
		  if(*state!=PAUSE && (*state!=PLAY || oldstate!=PAUSE))
		  {
			  mWriteSlot=mReadSlot=0;
			  oldstate=*state;
		  }
	  }
	  while((mWriteSlot+1)%DECODE_SLOTS == mReadSlot)
	  {
		  usleep(10000);
	  }
	  bytes=0;
	  if(mSeekable)
#ifdef USE_TREMOR
		  mSlotTime[mWriteSlot] = ov_time_tell(&vf);
#else
		  mSlotTime[mWriteSlot] = (ogg_int64_t)(1000 * ov_time_tell(&vf));
#endif
	  do
	  {
#ifdef USE_TREMOR
		  rval = ov_read(&vf, mPcmSlots[mWriteSlot]+bytes, mSlotSize-bytes, &bitstream);
#else
		  rval = ov_read(&vf, mPcmSlots[mWriteSlot]+bytes, mSlotSize-bytes, 0, 2, 1, &bitstream);
#endif
		  bytes+=rval;
//printf("Ogg: read buf 0x%x size %d / %d done %d\n", mPcmSlots[mWriteSlot]+bytes, rval, mSlotSize, bytes);
	  } while (rval > 0 && bytes !=mSlotSize);
//printf("\n");
	  int actMSecsToSkip = (*secondsToSkip != 0) ? *secondsToSkip * 1000 : MSECS_TO_SKIP;
	  if((*state==FF || *state==REV) && mSeekable )
	  {
		  if((std::abs((long int)( mSlotTime[mWriteSlot]-jumptime))) > MSECS_TO_PLAY)
		  {
			  if(*state==FF)
			  {
				  ov_time_seek_page(&vf, mSlotTime[mWriteSlot] + actMSecsToSkip);
				  jumptime=mSlotTime[mWriteSlot]+actMSecsToSkip;
			  }
			  else
			  {
				  if(mSlotTime[mWriteSlot] < actMSecsToSkip)
				  {
					  ov_time_seek(&vf, 0);
					  *state=PLAY;
				  }
				  else
				  {
					  ov_time_seek_page(&vf, mSlotTime[mWriteSlot] - actMSecsToSkip);
					  jumptime=mSlotTime[mWriteSlot]-actMSecsToSkip;
				  }
			  }
		  }
		  if (*secondsToSkip != 0) {
			  *state=PLAY;
		  }
	  }
	  if(bytes == mSlotSize)
		  mWriteSlot=(mWriteSlot+1) % DECODE_SLOTS;
  } while (rval != 0 && *state!=STOP_REQ && Status==OK);

  //printf("COggDec::Decoder: read loop stop, rval %d state %d status %d\n", rval, *state, Status);
  // let buffer run dry
  while(rval==0 && *state!=STOP_REQ && Status==OK && mReadSlot != mWriteSlot)
	  usleep(100000);

  //pthread_cancel(OutputThread);
  //printf("COggDec::Decoder: OutputThread join\n");
  Status = WRITE_ERR;
  pthread_join(OutputThread, NULL);
  //printf("COggDec::Decoder: OutputThread join done\n");
  audioDecoder->StopClip();
  for(int i = 0 ; i < DECODE_SLOTS ; i++)
	  free(mPcmSlots[i]);

  /* clean up the junk from the party */
  ov_clear(&vf);

  /* and drive home ;) */
  return Status;
}
示例#3
0
/* public */
static void
vorbis_stream_decode(struct decoder *decoder,
		     struct input_stream *input_stream)
{
	GError *error = NULL;

	if (ogg_codec_detect(decoder, input_stream) != OGG_CODEC_VORBIS)
		return;

	/* rewind the stream, because ogg_codec_detect() has
	   moved it */
	input_stream_lock_seek(input_stream, 0, SEEK_SET, NULL);

	struct vorbis_input_stream vis;
	OggVorbis_File vf;
	if (!vorbis_is_open(&vis, &vf, decoder, input_stream))
		return;

	const vorbis_info *vi = ov_info(&vf, -1);
	if (vi == NULL) {
		g_warning("ov_info() has failed");
		return;
	}

	struct audio_format audio_format;
	if (!audio_format_init_checked(&audio_format, vi->rate,
#ifdef HAVE_TREMOR
				       SAMPLE_FORMAT_S16,
#else
				       SAMPLE_FORMAT_FLOAT,
#endif
				       vi->channels, &error)) {
		g_warning("%s", error->message);
		g_error_free(error);
		return;
	}

	float total_time = ov_time_total(&vf, -1);
	if (total_time < 0)
		total_time = 0;

	decoder_initialized(decoder, &audio_format, vis.seekable, total_time);

	enum decoder_command cmd = decoder_get_command(decoder);

#ifdef HAVE_TREMOR
	char buffer[4096];
#else
	float buffer[2048];
	const int frames_per_buffer =
		G_N_ELEMENTS(buffer) / audio_format.channels;
	const unsigned frame_size = sizeof(buffer[0]) * audio_format.channels;
#endif

	int prev_section = -1;
	unsigned kbit_rate = 0;

	do {
		if (cmd == DECODE_COMMAND_SEEK) {
			double seek_where = decoder_seek_where(decoder);
			if (0 == ov_time_seek_page(&vf, seek_where)) {
				decoder_command_finished(decoder);
			} else
				decoder_seek_error(decoder);
		}

		int current_section;

#ifdef HAVE_TREMOR
		long nbytes = ov_read(&vf, buffer, sizeof(buffer),
				      VORBIS_BIG_ENDIAN, 2, 1,
				      &current_section);
#else
		float **per_channel;
		long nframes = ov_read_float(&vf, &per_channel,
					     frames_per_buffer,
					     &current_section);
		long nbytes = nframes;
		if (nframes > 0) {
			vorbis_interleave(buffer,
					  (const float*const*)per_channel,
					  nframes, audio_format.channels);
			nbytes *= frame_size;
		}
#endif

		if (nbytes == OV_HOLE) /* bad packet */
			nbytes = 0;
		else if (nbytes <= 0)
			/* break on EOF or other error */
			break;

		if (current_section != prev_section) {
			vi = ov_info(&vf, -1);
			if (vi == NULL) {
				g_warning("ov_info() has failed");
				break;
			}

			if (vi->rate != (long)audio_format.sample_rate ||
			    vi->channels != (int)audio_format.channels) {
				/* we don't support audio format
				   change yet */
				g_warning("audio format change, stopping here");
				break;
			}

			char **comments = ov_comment(&vf, -1)->user_comments;
			vorbis_send_comments(decoder, input_stream, comments);

			struct replay_gain_info rgi;
			if (vorbis_comments_to_replay_gain(&rgi, comments))
				decoder_replay_gain(decoder, &rgi);

			prev_section = current_section;
		}

		long test = ov_bitrate_instant(&vf);
		if (test > 0)
			kbit_rate = test / 1000;

		cmd = decoder_data(decoder, input_stream,
				   buffer, nbytes,
				   kbit_rate);
	} while (cmd != DECODE_COMMAND_STOP);

	ov_clear(&vf);
}
示例#4
0
int main(){
  OggVorbis_File ov;
  int i,ret;
  ogg_int64_t pcmlength;
  double timelength;
  char *bigassbuffer;
  int dummy;
  int hs=0;

#ifdef _WIN32 /* We need to set stdin/stdout to binary mode. Damn windows. */
  _setmode( _fileno( stdin ), _O_BINARY );
#endif


  /* open the file/pipe on stdin */
  if(ov_open_callbacks(stdin,&ov,NULL,-1,OV_CALLBACKS_NOCLOSE)<0){
    fprintf(stderr,"Could not open input as an OggVorbis file.\n\n");
    exit(1);
  }

#if 0 /*enable this code to test seeking with halfrate decode */
  if(ov_halfrate(&ov,1)){
    fprintf(stderr,"Sorry; unable to set half-rate decode.\n\n");
    exit(1);
  }else
    hs=1;
#endif

  if(ov_seekable(&ov)){

    /* to simplify our own lives, we want to assume the whole file is
       stereo.  Verify this to avoid potentially mystifying users
       (pissing them off is OK, just don't confuse them) */
    for(i=0;i<ov.links;i++){
      vorbis_info *vi=ov_info(&ov,i);
      if(vi->channels!=2){
        fprintf(stderr,"Sorry; right now seeking_test can only use Vorbis files\n"
               "that are entirely stereo.\n\n");
        exit(1);
      }
    }

    /* because we want to do sample-level verification that the seek
       does what it claimed, decode the entire file into memory */
    pcmlength=ov_pcm_total(&ov,-1);
    timelength=ov_time_total(&ov,-1);
    bigassbuffer=malloc((pcmlength>>hs)*2); /* w00t */
    i=0;
    while(i<(pcmlength>>hs)*2){
      int ret=ov_read(&ov,bigassbuffer+i,((pcmlength>>hs)*2)-i,1,1,1,&dummy);
      if(ret<0){
        fprintf(stderr,"Error reading file.\n");
        exit(1);
      }
      if(ret){
        i+=ret;
      }else{
        pcmlength=(i/2)<<hs;
      }
      fprintf(stderr,"\rloading.... [%ld left]              ",
              (long)((pcmlength>>hs)*2-i));
    }

    {
      ogg_int64_t length=ov.end;
      fprintf(stderr,"\rtesting raw seeking to random places in %ld bytes....\n",
             (long)length);

      for(i=0;i<1000;i++){
        ogg_int64_t val=(double)rand()/RAND_MAX*length;
        fprintf(stderr,"\r\t%d [raw position %ld]...     ",i,(long)val);
        ret=ov_raw_seek(&ov,val);
        if(ret<0){
          fprintf(stderr,"seek failed: %d\n",ret);
          exit(1);
        }

        _verify(&ov,val,-1,-1.,pcmlength,bigassbuffer);

      }
    }

    fprintf(stderr,"\r");
    {
      fprintf(stderr,"testing pcm page seeking to random places in %ld samples....\n",
             (long)pcmlength);

      for(i=0;i<1000;i++){
        ogg_int64_t val= i==0?(ogg_int64_t)0:(double)rand()/RAND_MAX*pcmlength;
        fprintf(stderr,"\r\t%d [pcm position %ld]...     ",i,(long)val);
        ret=ov_pcm_seek_page(&ov,val);
        if(ret<0){
          fprintf(stderr,"seek failed: %d\n",ret);
          exit(1);
        }

        _verify(&ov,-1,val,-1.,pcmlength,bigassbuffer);

      }
    }

    fprintf(stderr,"\r");
    {
      fprintf(stderr,"testing pcm exact seeking to random places in %f seconds....\n",
             timelength);
      for(i=0;i<1000;i++){
        ogg_int64_t val= i==0?(ogg_int64_t)0:(double)rand()/RAND_MAX*pcmlength;
        fprintf(stderr,"\r\t%d [pcm position %ld]...     ",i,(long)val);
        ret=ov_pcm_seek(&ov,val);
        if(ret<0){
          fprintf(stderr,"seek failed: %d\n",ret);
          exit(1);
        }
        if(ov_pcm_tell(&ov)!=((val>>hs)<<hs)){
          fprintf(stderr,"Declared position didn't perfectly match request: %ld != %ld\n",
                 (long)val,(long)ov_pcm_tell(&ov));
          exit(1);
        }

        _verify(&ov,-1,val,-1.,pcmlength,bigassbuffer);

      }
    }

    fprintf(stderr,"\r");
    {
      fprintf(stderr,"testing time page seeking to random places in %f seconds....\n",
             timelength);
    
      for(i=0;i<1000;i++){
        double val=(double)rand()/RAND_MAX*timelength;
        fprintf(stderr,"\r\t%d [time position %f]...     ",i,val);
        ret=ov_time_seek_page(&ov,val);
        if(ret<0){
          fprintf(stderr,"seek failed: %d\n",ret);
          exit(1);
        }

        _verify(&ov,-1,-1,val,pcmlength,bigassbuffer);

      }
    }

    fprintf(stderr,"\r");
    {
      fprintf(stderr,"testing time exact seeking to random places in %f seconds....\n",
             timelength);
    
      for(i=0;i<1000;i++){
        double val=(double)rand()/RAND_MAX*timelength;
        fprintf(stderr,"\r\t%d [time position %f]...     ",i,val);
        ret=ov_time_seek(&ov,val);
        if(ret<0){
          fprintf(stderr,"seek failed: %d\n",ret);
          exit(1);
        }
        if(ov_time_tell(&ov)<val-1 || ov_time_tell(&ov)>val+1){
          fprintf(stderr,"Declared position didn't perfectly match request: %f != %f\n",
                 val,ov_time_tell(&ov));
          exit(1);
        }

        _verify(&ov,-1,-1,val,pcmlength,bigassbuffer);

      }
    }
    
    fprintf(stderr,"\r                                           \nOK.\n\n");


  }else{
示例#5
0
int main(){
  OggVorbis_File ov;
  int i,ret;
  ogg_int64_t pcmlength;
  ogg_int64_t timelength;
  char *bigassbuffer;
  int dummy;

#ifdef _WIN32 /* We need to set stdin/stdout to binary mode. Damn windows. */
  _setmode( _fileno( stdin ), _O_BINARY );
#endif


  /* open the file/pipe on stdin */
  if(ov_open(stdin, &ov, NULL, 0) < 0) {
    fprintf(stderr,"Could not open input as an OggVorbis file.\n\n");
    exit(1);
  }

  if(ov_seekable(&ov)){

    /* to simplify our own lives, we want to assume the whole file is
       stereo.  Verify this to avoid potentially mystifying users
       (pissing them off is OK, just don't confuse them) */
    for(i=0;i<ov.links;i++){
      vorbis_info *vi=ov_info(&ov,i);
      if(vi->channels!=2){
        fprintf(stderr,"Sorry; right now seeking_test can only use Vorbis files\n"
               "that are entirely stereo.\n\n");
        exit(1);
      }
    }
    
    /* because we want to do sample-level verification that the seek
       does what it claimed, decode the entire file into memory */
    pcmlength=ov_pcm_total(&ov,-1);
    timelength=ov_time_total(&ov,-1);
    bigassbuffer=malloc(pcmlength*4); /* w00t */
    if(bigassbuffer){
      i=0;
      while(i<pcmlength*4){
	int ret=ov_read(&ov,bigassbuffer+i,pcmlength*4-i,&dummy);
	if(ret<0)continue;
	if(ret){
	  i+=ret;
	}else{
	  pcmlength=i/4;
	}
	fprintf(stderr,"\rloading.... [%ld left]              ",
		(long)(pcmlength*4-i));
      }
    }else{
      fprintf(stderr,"\rfile too large to load into memory for read tests;\n\tonly verifying seek positioning...\n");
    }
    
    {
      ogg_int64_t length=ov.end;
      fprintf(stderr,"\rtesting raw seeking to random places in %ld bytes....\n",
             (long)length);
    
      for(i=0;i<1000;i++){
        ogg_int64_t val=rand()*length/RAND_MAX;
        fprintf(stderr,"\r\t%d [raw position %ld]...     ",i,(long)val);
        ret=ov_raw_seek(&ov,val);
        if(ret<0){
          fprintf(stderr,"seek failed: %d\n",ret);
          exit(1);
        }

        _verify(&ov,val,-1,-1.,pcmlength,bigassbuffer);

      }
    }

    fprintf(stderr,"\r");
    {
      fprintf(stderr,"testing pcm page seeking to random places in %ld samples....\n",
             (long)pcmlength);
    
      for(i=0;i<1000;i++){
        ogg_int64_t val=(double)rand()*pcmlength/RAND_MAX;
        fprintf(stderr,"\r\t%d [pcm position %ld]...     ",i,(long)val);
        ret=ov_pcm_seek_page(&ov,val);
        if(ret<0){
          fprintf(stderr,"seek failed: %d\n",ret);
          exit(1);
        }

        _verify(&ov,-1,val,-1.,pcmlength,bigassbuffer);

      }
    }
    
    fprintf(stderr,"\r");
    {
      fprintf(stderr,"testing pcm exact seeking to random places in %ld samples....\n",
             (long)pcmlength);
    
      for(i=0;i<1000;i++){
        ogg_int64_t val=(double)rand()*pcmlength/RAND_MAX;
        fprintf(stderr,"\r\t%d [pcm position %ld]...     ",i,(long)val);
        ret=ov_pcm_seek(&ov,val);
        if(ret<0){
          fprintf(stderr,"seek failed: %d\n",ret);
          exit(1);
        }
        if(ov_pcm_tell(&ov)!=val){
          fprintf(stderr,"Declared position didn't perfectly match request: %ld != %ld\n",
                 (long)val,(long)ov_pcm_tell(&ov));
          exit(1);
        }

        _verify(&ov,-1,val,-1.,pcmlength,bigassbuffer);

      }
    }

    fprintf(stderr,"\r");
    {
      fprintf(stderr,"testing time page seeking to random places in %ld milliseconds....\n",
              (long)timelength);
    
      for(i=0;i<1000;i++){
        ogg_int64_t val=(double)rand()*timelength/RAND_MAX;
        fprintf(stderr,"\r\t%d [time position %ld]...     ",i,(long)val);
        ret=ov_time_seek_page(&ov,val);
        if(ret<0){
          fprintf(stderr,"seek failed: %d\n",ret);
          exit(1);
        }

        _verify(&ov,-1,-1,val,pcmlength,bigassbuffer);

      }
    }

    fprintf(stderr,"\r");
    {
      fprintf(stderr,"testing time exact seeking to random places in %ld milliseconds....\n",
              (long)timelength);
    
      for(i=0;i<1000;i++){
        ogg_int64_t val=(double)rand()*timelength/RAND_MAX;
        fprintf(stderr,"\r\t%d [time position %ld]...     ",i,(long)val);
        ret=ov_time_seek(&ov,val);
        if(ret<0){
          fprintf(stderr,"seek failed: %d\n",ret);
          exit(1);
        }
        if(ov_time_tell(&ov)<val-1 || ov_time_tell(&ov)>val+1){
          fprintf(stderr,"Declared position didn't perfectly match request: %ld != %ld\n",
                  (long)val,(long)ov_time_tell(&ov));
          exit(1);
        }

        _verify(&ov,-1,-1,val,pcmlength,bigassbuffer);

      }
    }
    
    fprintf(stderr,"\r                                           \nOK.\n\n");


  }else{
    fprintf(stderr,"Standard input was not seekable.\n");
  }

  ov_clear(&ov);
  return 0;
}