Esempio n. 1
0
/* Process a buffer (including reencoding or encoding, if desired).
 * Returns: >0 - success
 *           0 - shout error occurred
 *          -1 - no data produced
 *          -2 - fatal error occurred
 */
int process_and_send_buffer(stream_description *sdsc, ref_buffer *buffer)
{
    if(sdsc->reenc)
    {
        unsigned char *buf;
        int buflen,ret;

        ret = reencode_page(sdsc->reenc, buffer, &buf, &buflen);
        if(ret > 0) 
        {
            ret = stream_send_data(sdsc, buf, buflen);
            free(buf);
            return ret;
        }
        else if(ret==0) /* No data produced by reencode */
            return -1;
        else
        {
            LOG_ERROR0("Fatal reencoding error encountered");
            return -2;
        }
    }
    else if (sdsc->enc)
    {
        ogg_page og;
        int be = (sdsc->input->subtype == INPUT_PCM_BE_16)?1:0;
        int ret=1;

        /* We use critical as a flag to say 'start a new stream' */
        if(buffer->critical)
        {
            if(sdsc->resamp) {
                resample_finish(sdsc->resamp);
                encode_data_float(sdsc->enc, sdsc->resamp->buffers,
                        sdsc->resamp->buffill);
                resample_clear(sdsc->resamp);
                sdsc->resamp = resample_initialise (sdsc->stream->channels,
                        sdsc->stream->resampleinrate, sdsc->stream->resampleoutrate);
            }
            encode_finish(sdsc->enc);
            while(encode_flush(sdsc->enc, &og) != 0)
            {
                if ((ret = stream_send_data(sdsc, og.header, og.header_len)) == 0)
                    return 0;
                if ((ret = stream_send_data(sdsc, og.body, og.body_len)) == 0)
                    return 0;
            }
            encode_clear(sdsc->enc);

            if(sdsc->input->metadata_update)
            {
                vorbis_comment_clear(&sdsc->vc);
                vorbis_comment_init(&sdsc->vc);

                sdsc->input->metadata_update(sdsc->input->internal, &sdsc->vc);
            }

            sdsc->enc = encode_initialise(sdsc->stream->channels,
                    sdsc->stream->samplerate, sdsc->stream->managed, 
                    sdsc->stream->min_br, sdsc->stream->nom_br, 
                    sdsc->stream->max_br, sdsc->stream->quality,
                    &sdsc->vc);
            if(!sdsc->enc) {
                LOG_ERROR0("Failed to initialise encoder");
                return -2;
            }
            sdsc->enc->max_samples_ppage = sdsc->stream->max_samples_ppage;
        }

        if(sdsc->downmix) {
            downmix_buffer(sdsc->downmix, (signed char *)buffer->buf, buffer->len, be);
            if(sdsc->resamp) {
                resample_buffer_float(sdsc->resamp, &sdsc->downmix->buffer, 
                        buffer->len/4);
                encode_data_float(sdsc->enc, sdsc->resamp->buffers, 
                        sdsc->resamp->buffill);
            }
            else
                encode_data_float(sdsc->enc, &sdsc->downmix->buffer,
                       buffer->len/4);
        }
        else if(sdsc->resamp) {
            resample_buffer(sdsc->resamp, (signed char *)buffer->buf, 
                    buffer->len, be);
            encode_data_float(sdsc->enc, sdsc->resamp->buffers,
                    sdsc->resamp->buffill);
        }
        else {
            encode_data(sdsc->enc, (signed char *)(buffer->buf), 
                    buffer->len, be);
        }

        while(encode_dataout(sdsc->enc, &og) > 0)
        {
            if ((ret = stream_send_data(sdsc, og.header, og.header_len)) == 0)
                return 0;
            if ((ret = stream_send_data(sdsc, og.body, og.body_len)) == 0)
                return 0;
        }

        return ret;
    }
    else    
        return stream_send_data(sdsc, buffer->buf, buffer->len);
}
/*!
 * \brief Create a new OGG/Vorbis filestream and set it up for reading.
 * \param s File that points to on disk storage of the OGG/Vorbis data.
 * \return The new filestream.
 */
static int ogg_vorbis_open(struct ast_filestream *s)
{
	int i;
	int bytes;
	int result;
	char **ptr;
	char *buffer;
	struct vorbis_desc *tmp = (struct vorbis_desc *)s->_private;

	tmp->writing = 0;

	ogg_sync_init(&tmp->oy);

	buffer = ogg_sync_buffer(&tmp->oy, BLOCK_SIZE);
	bytes = fread(buffer, 1, BLOCK_SIZE, s->f);
	ogg_sync_wrote(&tmp->oy, bytes);

	result = ogg_sync_pageout(&tmp->oy, &tmp->og);
	if (result != 1) {
		if(bytes < BLOCK_SIZE) {
			ast_log(LOG_ERROR, "Run out of data...\n");
		} else {
			ast_log(LOG_ERROR, "Input does not appear to be an Ogg bitstream.\n");
		}
		ogg_sync_clear(&tmp->oy);
		return -1;
	}
	
	ogg_stream_init(&tmp->os, ogg_page_serialno(&tmp->og));
	vorbis_info_init(&tmp->vi);
	vorbis_comment_init(&tmp->vc);

	if (ogg_stream_pagein(&tmp->os, &tmp->og) < 0) { 
		ast_log(LOG_ERROR, "Error reading first page of Ogg bitstream data.\n");
error:
		ogg_stream_clear(&tmp->os);
		vorbis_comment_clear(&tmp->vc);
		vorbis_info_clear(&tmp->vi);
		ogg_sync_clear(&tmp->oy);
		return -1;
	}
	
	if (ogg_stream_packetout(&tmp->os, &tmp->op) != 1) { 
		ast_log(LOG_ERROR, "Error reading initial header packet.\n");
		goto error;
	}
	
	if (vorbis_synthesis_headerin(&tmp->vi, &tmp->vc, &tmp->op) < 0) { 
		ast_log(LOG_ERROR, "This Ogg bitstream does not contain Vorbis audio data.\n");
		goto error;
	}
	
	for (i = 0; i < 2 ; ) {
		while (i < 2) {
			result = ogg_sync_pageout(&tmp->oy, &tmp->og);
			if (result == 0)
				break;
			if (result == 1) {
				ogg_stream_pagein(&tmp->os, &tmp->og);
				while(i < 2) {
					result = ogg_stream_packetout(&tmp->os,&tmp->op);
					if(result == 0)
						break;
					if(result < 0) {
						ast_log(LOG_ERROR, "Corrupt secondary header.  Exiting.\n");
						goto error;
					}
					vorbis_synthesis_headerin(&tmp->vi, &tmp->vc, &tmp->op);
					i++;
				}
			}
		}

		buffer = ogg_sync_buffer(&tmp->oy, BLOCK_SIZE);
		bytes = fread(buffer, 1, BLOCK_SIZE, s->f);
		if (bytes == 0 && i < 2) {
			ast_log(LOG_ERROR, "End of file before finding all Vorbis headers!\n");
			goto error;
		}
		ogg_sync_wrote(&tmp->oy, bytes);
	}
	
	for (ptr = tmp->vc.user_comments; *ptr; ptr++)
		ast_debug(1, "OGG/Vorbis comment: %s\n", *ptr);
		ast_debug(1, "OGG/Vorbis bitstream is %d channel, %ldHz\n", tmp->vi.channels, tmp->vi.rate);
		ast_debug(1, "OGG/Vorbis file encoded by: %s\n", tmp->vc.vendor);

	if (tmp->vi.channels != 1) {
		ast_log(LOG_ERROR, "Only monophonic OGG/Vorbis files are currently supported!\n");
		goto error;
	}
	
	if (tmp->vi.rate != DEFAULT_SAMPLE_RATE) {
		ast_log(LOG_ERROR, "Only 8000Hz OGG/Vorbis files are currently supported!\n");
		vorbis_block_clear(&tmp->vb);
		vorbis_dsp_clear(&tmp->vd);
		goto error;
	}
	
	vorbis_synthesis_init(&tmp->vd, &tmp->vi);
	vorbis_block_init(&tmp->vd, &tmp->vb);

	return 0;
}
Esempio n. 3
0
int main( int argc, char* argv[] ){

  int i,j;
  ogg_packet op;
  SDL_Event event;
  int hasdatatobuffer = 1;
  int playbackdone = 0;
  double now, delay, last_frame_time = 0;

  int frameNum=0;
  int skipNum=0;

  /* takes first argument as file to play */
  /* this works better on Windows and is more convenient
     for drag and drop ogg files over the .exe */

  if( argc != 2 )
  {
    usage();
    exit(0);
  }

  infile  = fopen( argv[1], "rb" );

  /* start up Ogg stream synchronization layer */
  ogg_sync_init(&oy);

  /* init supporting Vorbis structures needed in header parsing */
  vorbis_info_init(&vi);
  vorbis_comment_init(&vc);

  /* init supporting Theora structures needed in header parsing */
  theora_comment_init(&tc);
  theora_info_init(&ti);

  parseHeaders();

  /* force audio off */
  /* vorbis_p = 0; */

  /* initialize decoders */
  if(theora_p){
    theora_decode_init(&td,&ti);
    printf("Ogg logical stream %x is Theora %dx%d %.02f fps video\n"
           "  Frame content is %dx%d with offset (%d,%d).\n",
	   to.serialno,ti.width,ti.height, (double)ti.fps_numerator/ti.fps_denominator,
	   ti.frame_width, ti.frame_height, ti.offset_x, ti.offset_y);
    report_colorspace(&ti);
    dump_comments(&tc);
  }else{
    /* tear down the partial theora setup */
    theora_info_clear(&ti);
    theora_comment_clear(&tc);
  }
  if(vorbis_p){
    vorbis_synthesis_init(&vd,&vi);
    vorbis_block_init(&vd,&vb);  
    printf("Ogg logical stream %x is Vorbis %d channel %d Hz audio.\n",
	   vo.serialno,vi.channels,vi.rate);
  }else{
    /* tear down the partial vorbis setup */
    vorbis_info_clear(&vi);
    vorbis_comment_clear(&vc);
  }
  /* open audio */
  if(vorbis_p)open_audio();
  /* open video */
  if(theora_p)open_video();
  
  /* our main loop */
  while(!playbackdone){

    /* break out on SDL quit event */
    if ( SDL_PollEvent ( &event ) )
    {
      if ( event.type == SDL_QUIT ) break ;
    }

    /* get some audio data */
    while(vorbis_p && !audiobuf_ready){
      int ret;
      float **pcm;
      int count = 0;
      int maxBytesToWrite;

      /* is there pending audio? does it fit our circular buffer without blocking? */
      ret=vorbis_synthesis_pcmout(&vd,&pcm);
      maxBytesToWrite = GetAudioStreamWriteable(aOutStream);

      if (maxBytesToWrite<=FRAMES_PER_BUFFER){
        /* break out until there is a significant amount of
           data to avoid a series of small write operations. */
        break;
      }
      /* if there's pending, decoded audio, grab it */
      if((ret>0)&&(maxBytesToWrite>0)){

	for(i=0;i<ret && i<(maxBytesToWrite/vi.channels);i++)
	  for(j=0;j<vi.channels;j++){
	    int val=(int)(pcm[j][i]*32767.f);
	    if(val>32767)val=32767;
	    if(val<-32768)val=-32768;
	    samples[count]=val;
	    count++;
	  }
	if(WriteAudioStream( aOutStream, samples, i )) {
	  if(count==maxBytesToWrite){
	    audiobuf_ready=1;
	  }
	}
        vorbis_synthesis_read(&vd,i);

	if(vd.granulepos>=0)
	  audiobuf_granulepos=vd.granulepos-ret+i;
	else
	  audiobuf_granulepos+=i;

      }else{
	
	/* no pending audio; is there a pending packet to decode? */
	if(ogg_stream_packetout(&vo,&op)>0){
	  if(vorbis_synthesis(&vb,&op)==0) /* test for success! */
	   vorbis_synthesis_blockin(&vd,&vb);
	}else	/* we need more data; break out to suck in another page */
	  break;
      }
    } /* end audio cycle */

    while(theora_p && !videobuf_ready){
      /* get one video packet... */
      if(ogg_stream_packetout(&to,&op)>0){
      
        theora_decode_packetin(&td,&op);

	  videobuf_granulepos=td.granulepos;
	  videobuf_time=theora_granule_time(&td,videobuf_granulepos);
	  /* update the frame counter */
	  frameNum++;

	  /* check if this frame time has not passed yet.
	     If the frame is late we need to decode additonal
	     ones and keep looping, since theora at this stage
	     needs to decode all frames */
	  now=get_time();
	  delay=videobuf_time-now;
	  if(delay>=0.0){
		/* got a good frame, not late, ready to break out */
		videobuf_ready=1;
	  }else if(now-last_frame_time>=1.0){
		/* display at least one frame per second, regardless */
		videobuf_ready=1;
	  }else{
		fprintf(stderr, "dropping frame %d (%.3fs behind)\n",
			frameNum, -delay);
	   }
      }else{
	/* need more data */
	break;
      }
    }

    if(!hasdatatobuffer && !videobuf_ready && !audiobuf_ready){
      isPlaying = 0;
      playbackdone = 1;
    }

    /* if we're set for the next frame, sleep */
    if((!theora_p || videobuf_ready) && 
       (!vorbis_p || audiobuf_ready)){
        int ticks = 1.0e3*(videobuf_time-get_time());
	if(ticks>0)
          SDL_Delay(ticks);
    }
 
    if(videobuf_ready){
      /* time to write our cached frame */
      video_write();
      videobuf_ready=0;
      last_frame_time=get_time();

      /* if audio has not started (first frame) then start it */
      if ((!isPlaying)&&(vorbis_p)){
        start_audio();
        isPlaying = 1;
      }
    }

    /* HACK: always look for more audio data */
    audiobuf_ready=0;

    /* buffer compressed data every loop */
    if(hasdatatobuffer){
      hasdatatobuffer=buffer_data(&oy);
      if(hasdatatobuffer==0){
        printf("Ogg buffering stopped, end of file reached.\n");
      }
    }
    
    if (ogg_sync_pageout(&oy,&og)>0){
      queue_page(&og);
    }

  } /* playbackdone */

  /* show number of video frames decoded */
  printf( "\n");
  printf( "Frames decoded: %d", frameNum );
  if(skipNum)
    printf( " (only %d shown)", frameNum-skipNum);
  printf( "\n" );

  /* tear it all down */
  fclose( infile );

  if(vorbis_p){
    audio_close();

    ogg_stream_clear(&vo);
    vorbis_block_clear(&vb);
    vorbis_dsp_clear(&vd);
    vorbis_comment_clear(&vc);
    vorbis_info_clear(&vi); 
  }
  if(theora_p){
    ogg_stream_clear(&to);
    theora_clear(&td);
    theora_comment_clear(&tc);
    theora_info_clear(&ti);
  }
  ogg_sync_clear(&oy);

  printf("\r                                                              "
	 "\nDone.\n");
	 
  SDL_Quit();

  return(0);

}
Esempio n. 4
0
/*!
 * \brief Create a new OGG/Vorbis filestream and set it up for writing.
 * \param fd File descriptor that points to on-disk storage.
 * \param comment Comment that should be embedded in the OGG/Vorbis file.
 * \return A new filestream.
 */
static struct cw_filestream *ogg_vorbis_rewrite(FILE *fp, const char *comment)
{
    ogg_packet header;
    ogg_packet header_comm;
    ogg_packet header_code;
    struct cw_filestream *tmp;

    if ((tmp = malloc(sizeof(struct cw_filestream))))
    {
        memset(tmp, 0, sizeof(struct cw_filestream));

        tmp->writing = 1;
        tmp->fp = fp;

        vorbis_info_init(&tmp->vi);

        if (vorbis_encode_init_vbr(&tmp->vi, 1, 8000, 0.4))
        {
            cw_log(LOG_ERROR, "Unable to initialize Vorbis encoder!\n");
            free(tmp);
            return NULL;
        }

        vorbis_comment_init(&tmp->vc);
        vorbis_comment_add_tag(&tmp->vc, "ENCODER", "CallWeaver");
        if (comment)
            vorbis_comment_add_tag(&tmp->vc, "COMMENT", (char *) comment);

        vorbis_analysis_init(&tmp->vd, &tmp->vi);
        vorbis_block_init(&tmp->vd, &tmp->vb);

        ogg_stream_init(&tmp->os, rand());

        vorbis_analysis_headerout(&tmp->vd, &tmp->vc, &header, &header_comm, &header_code);
        ogg_stream_packetin(&tmp->os, &header);                            
        ogg_stream_packetin(&tmp->os, &header_comm);
        ogg_stream_packetin(&tmp->os, &header_code);

        while (!tmp->eos)
        {
            if (ogg_stream_flush(&tmp->os, &tmp->og) == 0)
                break;
            fwrite(tmp->og.header, 1, tmp->og.header_len, tmp->fp);
            fwrite(tmp->og.body, 1, tmp->og.body_len, tmp->fp);
            if (ogg_page_eos(&tmp->og))
                tmp->eos = 1;
        }

        if (cw_mutex_lock(&ogg_vorbis_lock))
        {
            cw_log(LOG_WARNING, "Unable to lock ogg_vorbis list\n");
            fclose(fp);
            ogg_stream_clear(&tmp->os);
            vorbis_block_clear(&tmp->vb);
            vorbis_dsp_clear(&tmp->vd);
            vorbis_comment_clear(&tmp->vc);
            vorbis_info_clear(&tmp->vi);
            free(tmp);
            return NULL;
        }
        glistcnt++;
        cw_mutex_unlock(&ogg_vorbis_lock);
        cw_update_use_count();
    }
    return tmp;
}
//Method to start encoding
int startEncoding(JNIEnv *env, jclass *cls_ptr, jlong *sampleRate_ptr, jlong *channels_ptr, jfloat *quality_ptr, jlong *bitrate_ptr, jobject *encoderDataFeed_ptr, int type) {
    //Dereference our variables
    jclass cls = (*cls_ptr);
    jlong sampleRate = (*sampleRate_ptr);
    jlong channels = (*channels_ptr);
    jfloat quality = (*quality_ptr);
    jlong bitrate = (*bitrate_ptr);
    jobject encoderDataFeed = (*encoderDataFeed_ptr);

    //Create our PCM data buffer
    signed char readbuffer[READ*4+44];

    //Create a new java byte array to pass to the data feed method
    jbyteArray jByteArrayBuffer = (*env)->NewByteArray(env, READ*4);

    //Create a new java byte buffer to write to
    jbyteArray jByteArrayWriteBuffer = (*env)->NewByteArray(env, READ*8);

    //Find our java classes we'll be calling
    jclass encoderDataFeedClass = (*env)->FindClass(env, "org/xiph/vorbis/encoder/EncodeFeed");

    //Find our java method id's we'll be calling
    jmethodID writeVorbisDataMethodId = (*env)->GetMethodID(env, encoderDataFeedClass, "writeVorbisData", "([BI)I");
    jmethodID readPCMDataMethodId = (*env)->GetMethodID(env, encoderDataFeedClass, "readPCMData", "([BI)J");
    jmethodID startMethodId = (*env)->GetMethodID(env, encoderDataFeedClass, "start", "()V");
    jmethodID stopMethodId = (*env)->GetMethodID(env, encoderDataFeedClass, "stop", "()V");

    ogg_stream_state os; /* take physical pages, weld into a logical
                            stream of packets */
    ogg_page         og; /* one Ogg bitstream page.  Vorbis packets are inside */
    ogg_packet       op; /* one raw packet of data for decode */

    vorbis_info      vi; /* struct that stores all the static vorbis bitstream
                            settings */
    vorbis_comment   vc; /* struct that stores all the user comments */

    vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
    vorbis_block     vb; /* local working space for packet->PCM decode */

    int eos=0,ret;
    int i, founddata;

    /********** Encode setup ************/
    __android_log_print(ANDROID_LOG_INFO, "VorbisEncoder", "Setting up encoding");
    vorbis_info_init(&vi);

    /* choose an encoding mode.  A few possibilities commented out, one
       actually used: */

    /*********************************************************************
     Encoding using a VBR quality mode.  The usable range is -.1
     (lowest quality, smallest file) to 1. (highest quality, largest file).
     Example quality mode .4: 44kHz stereo coupled, roughly 128kbps VBR

     ret = vorbis_encode_init_vbr(&vi,2,44100,.4);

     ---------------------------------------------------------------------

     Encoding using an average bitrate mode (ABR).
     example: 44kHz stereo coupled, average 128kbps VBR

     ret = vorbis_encode_init(&vi,2,44100,-1,128000,-1);

     ---------------------------------------------------------------------

     Encode using a quality mode, but select that quality mode by asking for
     an approximate bitrate.  This is not ABR, it is true VBR, but selected
     using the bitrate interface, and then turning bitrate management off:

     ret = ( vorbis_encode_setup_managed(&vi,2,44100,-1,128000,-1) ||
             vorbis_encode_ctl(&vi,OV_ECTL_RATEMANAGE2_SET,NULL) ||
             vorbis_encode_setup_init(&vi));

     *********************************************************************/
     switch(type) {
        case WITH_BITRATE:
            __android_log_print(ANDROID_LOG_INFO, "VorbisEncoder", "Initializing with %lld channels %lldHz sample rate and %lld bitrate", channels, sampleRate, bitrate);
            ret=vorbis_encode_init(&vi, (long)channels, (long)sampleRate, (long)-1, (long)bitrate, (long)-1);
            break;
        case WITH_QUALITY:
            __android_log_print(ANDROID_LOG_INFO, "VorbisEncoder", "Initializing with %lld channels %lldHz sample rate and %f quality", channels, sampleRate, quality);
            ret=vorbis_encode_init_vbr(&vi, (long)channels, (long)sampleRate, (float)quality);
            break;
        default:
            __android_log_print(ANDROID_LOG_ERROR, "VorbisEncoder", "Failed to initialize");
            stopEncodeFeed(env, &encoderDataFeed, &stopMethodId);
            return ERROR_INITIALIZING;
     }


    /* do not continue if setup failed; this can happen if we ask for a
       mode that libVorbis does not support (eg, too low a bitrate, etc,
       will return 'OV_EIMPL') */

    if(ret) {
      __android_log_print(ANDROID_LOG_ERROR, "VorbisEncoder", "Failed to initialize");
      stopEncodeFeed(env, &encoderDataFeed, &stopMethodId);
      return ERROR_INITIALIZING;
    }

    startEncodeFeed(env, &encoderDataFeed, &startMethodId);

    /* add a comment */
    __android_log_print(ANDROID_LOG_DEBUG, "VorbisEncoder", "Adding comments");
    vorbis_comment_init(&vc);
    vorbis_comment_add_tag(&vc,"ENCODER","JNIVorbisEncoder");

    /* set up the analysis state and auxiliary encoding storage */
    vorbis_analysis_init(&vd,&vi);
    vorbis_block_init(&vd,&vb);

    /* set up our packet->stream encoder */
    /* pick a random serial number; that way we can more likely build
       chained streams just by concatenation */
    srand(time(NULL));
    ogg_stream_init(&os,rand());

    /* Vorbis streams begin with three headers; the initial header (with
       most of the codec setup parameters) which is mandated by the Ogg
       bitstream spec.  The second header holds any comment fields.  The
       third header holds the bitstream codebook.  We merely need to
       make the headers, then pass them to libvorbis one at a time;
       libvorbis handles the additional Ogg bitstream constraints */

    {
      ogg_packet header;
      ogg_packet header_comm;
      ogg_packet header_code;

      vorbis_analysis_headerout(&vd,&vc,&header,&header_comm,&header_code);
      ogg_stream_packetin(&os,&header); /* automatically placed in its own
                                           page */
      ogg_stream_packetin(&os,&header_comm);
      ogg_stream_packetin(&os,&header_code);

      /* This ensures the actual
       * audio data will start on a new page, as per spec
       */
      __android_log_print(ANDROID_LOG_INFO, "VorbisEncoder", "Writting header");
      while(!eos){
        int result=ogg_stream_flush(&os,&og);
        if(result==0)break;
        writeVorbisDataToEncoderDataFeed(env, &encoderDataFeed, &writeVorbisDataMethodId, og.header, og.header_len, &jByteArrayWriteBuffer);
        writeVorbisDataToEncoderDataFeed(env, &encoderDataFeed, &writeVorbisDataMethodId, og.body, og.body_len, &jByteArrayWriteBuffer);
      }

    }

    __android_log_print(ANDROID_LOG_INFO, "VorbisEncoder", "Starting to read from pcm callback");
    while(!eos){
      long i;
      long bytes = readPCMDataFromEncoderDataFeed(env, &encoderDataFeed, &readPCMDataMethodId, readbuffer, READ*4, &jByteArrayBuffer);

      if(bytes==0){
        /* end of file.  this can be done implicitly in the mainline,
           but it's easier to see here in non-clever fashion.
           Tell the library we're at end of stream so that it can handle
           the last frame and mark end of stream in the output properly */
        __android_log_print(ANDROID_LOG_INFO, "VorbisEncoder", "End of file");
        vorbis_analysis_wrote(&vd,0);

      }else{
        /* data to encode */

        /* expose the buffer to submit data */
        float **buffer=vorbis_analysis_buffer(&vd,bytes/(2*channels));

        /* uninterleave samples */
        int channel;
        for(i=0;i<bytes/(2*channels);i++) {
            for(channel = 0; channel < channels; channel++) {
                buffer[channel][i]=((readbuffer[i*(2*channels)+(channel*2+1)]<<8)|
                              (0x00ff&(int)readbuffer[i*(2*channels)+(channel*2)]))/32768.f;
            }
        }

        /* tell the library how much we actually submitted */
        vorbis_analysis_wrote(&vd,i);
      }

      /* vorbis does some data preanalysis, then divvies up blocks for
         more involved (potentially parallel) processing.  Get a single
         block for encoding now */
      while(vorbis_analysis_blockout(&vd,&vb)==1){

        /* analysis, assume we want to use bitrate management */
        vorbis_analysis(&vb,NULL);
        vorbis_bitrate_addblock(&vb);

        while(vorbis_bitrate_flushpacket(&vd,&op)){

          /* weld the packet into the bitstream */
          ogg_stream_packetin(&os,&op);

          /* write out pages (if any) */
          while(!eos){
            int result=ogg_stream_pageout(&os,&og);
            if(result==0)break;
            writeVorbisDataToEncoderDataFeed(env, &encoderDataFeed, &writeVorbisDataMethodId, og.header, og.header_len, &jByteArrayWriteBuffer);
            writeVorbisDataToEncoderDataFeed(env, &encoderDataFeed, &writeVorbisDataMethodId, og.body, og.body_len, &jByteArrayWriteBuffer);

            /* this could be set above, but for illustrative purposes, I do
               it here (to show that vorbis does know where the stream ends) */

            if(ogg_page_eos(&og))eos=1;
          }
        }
      }
    }

    /* clean up and exit.  vorbis_info_clear() must be called last */
    __android_log_print(ANDROID_LOG_INFO, "VorbisEncoder", "Cleaning up encoder");
    ogg_stream_clear(&os);
    vorbis_block_clear(&vb);
    vorbis_dsp_clear(&vd);
    vorbis_comment_clear(&vc);
    vorbis_info_clear(&vi);

    /* ogg_page and ogg_packet structs always point to storage in
       libvorbis.  They're never freed or manipulated directly */
    __android_log_print(ANDROID_LOG_INFO, "VorbisEncoder", "Completed encoding.");
    stopEncodeFeed(env, &encoderDataFeed, &stopMethodId);

    //Clean up encode buffers
    (*env)->DeleteLocalRef(env, jByteArrayBuffer);
    (*env)->DeleteLocalRef(env, jByteArrayWriteBuffer);

    return SUCCESS;
}
Esempio n. 6
0
bool TheoraDecoder::loadStream(Common::SeekableReadStream *stream) {
	close();

	_fileStream = stream;

	// start up Ogg stream synchronization layer
	ogg_sync_init(&_oggSync);

	// init supporting Vorbis structures needed in header parsing
	vorbis_info_init(&_vorbisInfo);
	vorbis_comment vorbisComment;
	vorbis_comment_init(&vorbisComment);

	// init supporting Theora structures needed in header parsing
	th_info theoraInfo;
	th_info_init(&theoraInfo);
	th_comment theoraComment;
	th_comment_init(&theoraComment);
	th_setup_info *theoraSetup = 0;

	uint theoraPackets = 0, vorbisPackets = 0;

	// Ogg file open; parse the headers
	// Only interested in Vorbis/Theora streams
	bool foundHeader = false;
	while (!foundHeader) {
		int ret = bufferData();

		if (ret == 0)
			break; // FIXME: Shouldn't this error out?

		while (ogg_sync_pageout(&_oggSync, &_oggPage) > 0) {
			ogg_stream_state test;

			// is this a mandated initial header? If not, stop parsing
			if (!ogg_page_bos(&_oggPage)) {
				// don't leak the page; get it into the appropriate stream
				queuePage(&_oggPage);
				foundHeader = true;
				break;
			}

			ogg_stream_init(&test, ogg_page_serialno(&_oggPage));
			ogg_stream_pagein(&test, &_oggPage);
			ogg_stream_packetout(&test, &_oggPacket);

			// identify the codec: try theora
			if (theoraPackets == 0 && th_decode_headerin(&theoraInfo, &theoraComment, &theoraSetup, &_oggPacket) >= 0) {
				// it is theora
				memcpy(&_theoraOut, &test, sizeof(test));
				theoraPackets = 1;
				_hasVideo = true;
			} else if (vorbisPackets == 0 && vorbis_synthesis_headerin(&_vorbisInfo, &vorbisComment, &_oggPacket) >= 0) {
				// it is vorbis
				memcpy(&_vorbisOut, &test, sizeof(test));
				vorbisPackets = 1;
				_hasAudio = true;
			} else {
				// whatever it is, we don't care about it
				ogg_stream_clear(&test);
			}
		}
		// fall through to non-bos page parsing
	}

	// we're expecting more header packets.
	while ((theoraPackets && theoraPackets < 3) || (vorbisPackets && vorbisPackets < 3)) {
		int ret;

		// look for further theora headers
		while (theoraPackets && (theoraPackets < 3) && (ret = ogg_stream_packetout(&_theoraOut, &_oggPacket))) {
			if (ret < 0)
				error("Error parsing Theora stream headers; corrupt stream?");

			if (!th_decode_headerin(&theoraInfo, &theoraComment, &theoraSetup, &_oggPacket))
				error("Error parsing Theora stream headers; corrupt stream?");

			theoraPackets++;
		}

		// look for more vorbis header packets
		while (vorbisPackets && (vorbisPackets < 3) && (ret = ogg_stream_packetout(&_vorbisOut, &_oggPacket))) {
			if (ret < 0)
				error("Error parsing Vorbis stream headers; corrupt stream?");

			if (vorbis_synthesis_headerin(&_vorbisInfo, &vorbisComment, &_oggPacket))
				error("Error parsing Vorbis stream headers; corrupt stream?");

			vorbisPackets++;

			if (vorbisPackets == 3)
				break;
		}

		// The header pages/packets will arrive before anything else we
		// care about, or the stream is not obeying spec

		if (ogg_sync_pageout(&_oggSync, &_oggPage) > 0) {
			queuePage(&_oggPage); // demux into the appropriate stream
		} else {
			ret = bufferData(); // someone needs more data

			if (ret == 0)
				error("End of file while searching for codec headers.");
		}
	}

	// And now we have it all. Initialize decoders next
	if (_hasVideo) {
		_videoTrack = new TheoraVideoTrack(getDefaultHighColorFormat(), theoraInfo, theoraSetup);
		addTrack(_videoTrack);
	}

	th_info_clear(&theoraInfo);
	th_comment_clear(&theoraComment);
	th_setup_free(theoraSetup);

	if (_hasAudio) {
		_audioTrack = new VorbisAudioTrack(_soundType, _vorbisInfo);

		// Get enough audio data to start us off
		while (!_audioTrack->hasAudio()) {
			// Queue more data
			bufferData();
			while (ogg_sync_pageout(&_oggSync, &_oggPage) > 0)
				queuePage(&_oggPage);

			queueAudio();
		}

		addTrack(_audioTrack);
	}

	vorbis_comment_clear(&vorbisComment);

	return true;
}
Esempio n. 7
0
vorbis_comment_holder::~vorbis_comment_holder() {
  vorbis_comment_clear(&value);
}
Esempio n. 8
0
int main(){
  ogg_stream_state os; /* take physical pages, weld into a logical
                          stream of packets */
  ogg_page         og; /* one Ogg bitstream page.  Vorbis packets are inside */
  ogg_packet       op; /* one raw packet of data for decode */

  vorbis_info      vi; /* struct that stores all the static vorbis bitstream
                          settings */
  vorbis_comment   vc; /* struct that stores all the user comments */

  vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
  vorbis_block     vb; /* local working space for packet->PCM decode */

  int eos=0,ret;
  int i, founddata;
  int numReads=0;
    
    FILE *outFile = fopen("../test.ogg","wb");

  /* we cheat on the WAV header; we just bypass 44 bytes (simplest WAV
     header is 44 bytes) and assume that the data is 44.1khz, stereo, 16 bit
     little endian pcm samples. This is just an example, after all. */

  /********** Encode setup ************/

  vorbis_info_init(&vi);

  /* choose an encoding mode.  A few possibilities commented out, one
     actually used: */

  /*********************************************************************
   Encoding using a VBR quality mode.  The usable range is -.1
   (lowest quality, smallest file) to 1. (highest quality, largest file).
   Example quality mode .4: 44kHz stereo coupled, roughly 128kbps VBR

   ret = vorbis_encode_init_vbr(&vi,2,44100,.4);

   ---------------------------------------------------------------------

   Encoding using an average bitrate mode (ABR).
   example: 44kHz stereo coupled, average 128kbps VBR

   ret = vorbis_encode_init(&vi,2,44100,-1,128000,-1);

   ---------------------------------------------------------------------

   Encode using a quality mode, but select that quality mode by asking for
   an approximate bitrate.  This is not ABR, it is true VBR, but selected
   using the bitrate interface, and then turning bitrate management off:

   ret = ( vorbis_encode_setup_managed(&vi,2,44100,-1,128000,-1) ||
           vorbis_encode_ctl(&vi,OV_ECTL_RATEMANAGE2_SET,NULL) ||
           vorbis_encode_setup_init(&vi));

   *********************************************************************/

  ret=vorbis_encode_init_vbr(&vi,2,44100,1.0);

  /* do not continue if setup failed; this can happen if we ask for a
     mode that libVorbis does not support (eg, too low a bitrate, etc,
     will return 'OV_EIMPL') */

  if(ret)exit(1);

  /* add a comment */
  vorbis_comment_init(&vc);
  vorbis_comment_add_tag(&vc,"ENCODER","encoder_example.c");

  /* set up the analysis state and auxiliary encoding storage */
  vorbis_analysis_init(&vd,&vi);
  vorbis_block_init(&vd,&vb);

  /* set up our packet->stream encoder */
  /* pick a random serial number; that way we can more likely build
     chained streams just by concatenation */
  srand(time(NULL));
  ogg_stream_init(&os,rand());

  /* Vorbis streams begin with three headers; the initial header (with
     most of the codec setup parameters) which is mandated by the Ogg
     bitstream spec.  The second header holds any comment fields.  The
     third header holds the bitstream codebook.  We merely need to
     make the headers, then pass them to libvorbis one at a time;
     libvorbis handles the additional Ogg bitstream constraints */

  {
    ogg_packet header;
    ogg_packet header_comm;
    ogg_packet header_code;

    vorbis_analysis_headerout(&vd,&vc,&header,&header_comm,&header_code);
    ogg_stream_packetin(&os,&header); /* automatically placed in its own
                                         page */
    ogg_stream_packetin(&os,&header_comm);
    ogg_stream_packetin(&os,&header_code);

    /* This ensures the actual
     * audio data will start on a new page, as per spec
     */
    while(!eos){
      int result=ogg_stream_flush(&os,&og);
      if(result==0)break;
      fwrite(og.header,1,og.header_len,outFile);
      fwrite(og.body,1,og.body_len,outFile);
    }

  }

  while(!eos){
    long i;
    long bytes=READ*4; /* stereo hardwired here */
    numReads++;

    if(numReads>10000) bytes=0;

    if(bytes==0){
      /* end of file.  this can be done implicitly in the mainline,
         but it's easier to see here in non-clever fashion.
         Tell the library we're at end of stream so that it can handle
         the last frame and mark end of stream in the output properly */
      vorbis_analysis_wrote(&vd,0);

    }else{
      /* data to encode */

      /* expose the buffer to submit data */
      float **buffer=vorbis_analysis_buffer(&vd,READ);

      /* uninterleave samples */
      for(i=0;i<bytes/4;i++){
	static float curamp = 0;
	curamp += 0.15f;
	buffer[0][i] = sinf(curamp);
	buffer[1][i] = sinf(curamp);
      }



      /* tell the library how much we actually submitted */
      vorbis_analysis_wrote(&vd,i);
    }

    /* vorbis does some data preanalysis, then divvies up blocks for
       more involved (potentially parallel) processing.  Get a single
       block for encoding now */
    while(vorbis_analysis_blockout(&vd,&vb)==1){

      /* analysis, assume we want to use bitrate management */
      vorbis_analysis(&vb,NULL);
      vorbis_bitrate_addblock(&vb);

      while(vorbis_bitrate_flushpacket(&vd,&op)){

        /* weld the packet into the bitstream */
        ogg_stream_packetin(&os,&op);

        /* write out pages (if any) */
        while(!eos){
          int result=ogg_stream_pageout(&os,&og);
          if(result==0)break;
          fwrite(og.header,1,og.header_len,outFile);
          fwrite(og.body,1,og.body_len,outFile);

          /* this could be set above, but for illustrative purposes, I do
             it here (to show that vorbis does know where the stream ends) */

          if(ogg_page_eos(&og))eos=1;
        }
      }
    }
  }

  /* clean up and exit.  vorbis_info_clear() must be called last */

  ogg_stream_clear(&os);
  vorbis_block_clear(&vb);
  vorbis_dsp_clear(&vd);
  vorbis_comment_clear(&vc);
  vorbis_info_clear(&vi);

  /* ogg_page and ogg_packet structs always point to storage in
     libvorbis.  They're never freed or manipulated directly */

  fprintf(stderr,"Done.\n");
  return(0);
}
Esempio n. 9
0
/* The following function is basically a hacked version of the code in
 * examples/decoder_example.c */
void
read_vorbis_data_or_die (const char *filename, int srate, float * data, int count)
{
  ogg_sync_state   oy;
  ogg_stream_state os;
  ogg_page         og;
  ogg_packet       op;

  vorbis_info      vi;
  vorbis_comment   vc;
  vorbis_dsp_state vd;
  vorbis_block     vb;

  FILE *file;
  char *buffer;
  int  bytes;
  int eos = 0;
  int i;
  int read_total = 0 ;

  if ((file = fopen (filename, "rb")) == NULL) {
    printf("\n\nError : fopen failed : %s\n", strerror (errno)) ;
    exit (1) ;
  }

  ogg_sync_init (&oy);

  {
    /* fragile!  Assumes all of our headers will fit in the first 8kB,
       which currently they will */
    buffer = ogg_sync_buffer (&oy,8192);
    bytes = fread (buffer,1,8192,file);
    ogg_sync_wrote (&oy,bytes);

    if(ogg_sync_pageout (&oy,&og) != 1) {
      if(bytes < 8192) {
        printf ("Out of data.\n") ;
          goto done_decode ;
      }

      fprintf (stderr,"Input does not appear to be an Ogg bitstream.\n");
      exit (1);
    }

    ogg_stream_init (&os,ogg_page_serialno(&og));

    vorbis_info_init (&vi);
    vorbis_comment_init (&vc);
    if (ogg_stream_pagein (&os,&og) < 0) {
      fprintf (stderr,"Error reading first page of Ogg bitstream data.\n");
      exit (1);
    }

    if (ogg_stream_packetout(&os,&op) != 1) {
      fprintf (stderr,"Error reading initial header packet.\n");
      exit (1);
    }

    if (vorbis_synthesis_headerin (&vi,&vc,&op) < 0) {
      fprintf (stderr,"This Ogg bitstream does not contain Vorbis "
          "audio data.\n");
      exit (1);
    }

    i = 0;
    while ( i < 2) {
      while (i < 2) {

        int result = ogg_sync_pageout (&oy,&og);
        if(result == 0)
          break;
        if(result==1) {
          ogg_stream_pagein(&os,&og);

          while (i < 2) {
            result = ogg_stream_packetout (&os,&op);
            if (result == 0) break;
            if (result < 0) {
              fprintf (stderr,"Corrupt secondary header.  Exiting.\n");
              exit(1);
            }
            vorbis_synthesis_headerin (&vi,&vc,&op);
            i++;
          }
        }
      }

      buffer = ogg_sync_buffer (&oy,4096);
      bytes = fread (buffer,1,4096,file);
      if (bytes == 0 && i < 2) {
        fprintf (stderr,"End of file before finding all Vorbis headers!\n");
        exit (1);
      }

      ogg_sync_wrote (&oy,bytes);
    }

    if (vi.rate != srate) {
      printf ("\n\nError : File '%s' has sample rate of %ld when it should be %d.\n\n", filename, vi.rate, srate);
      exit (1) ;
    }

    vorbis_synthesis_init (&vd,&vi);
    vorbis_block_init (&vd,&vb);

    while(!eos) {
      while (!eos) {
        int result = ogg_sync_pageout (&oy,&og);
        if (result == 0)
          break;
        if (result < 0) {
          fprintf (stderr,"Corrupt or missing data in bitstream; "
                   "continuing...\n");
        } else {
          ogg_stream_pagein (&os,&og);
          while (1) {
            result = ogg_stream_packetout (&os,&op);

            if (result == 0)
              break;
            if (result < 0) {
              /* no reason to complain; already complained above */
            } else {
              float **pcm;
              int samples;

              if (vorbis_synthesis (&vb,&op) == 0)
                vorbis_synthesis_blockin(&vd,&vb);
              while ((samples = vorbis_synthesis_pcmout (&vd,&pcm)) > 0 && read_total < count) {
                int bout = samples < count ? samples : count;
                bout = read_total + bout > count ? count - read_total : bout;

                memcpy (data + read_total, pcm[0], bout * sizeof (float)) ;

                vorbis_synthesis_read (&vd,bout);
                read_total += bout ;
              }
            }
          }

          if (ogg_page_eos (&og)) eos = 1;
        }
      }

      if (!eos) {
        buffer = ogg_sync_buffer (&oy,4096);
        bytes = fread (buffer,1,4096,file);
        ogg_sync_wrote (&oy,bytes);
        if (bytes == 0) eos = 1;
      }
    }

    ogg_stream_clear (&os);

    vorbis_block_clear (&vb);
    vorbis_dsp_clear (&vd);
    vorbis_comment_clear (&vc);
    vorbis_info_clear (&vi);
  }
done_decode:

  /* OK, clean up the framer */
  ogg_sync_clear (&oy);

  fclose (file) ;
}
Esempio n. 10
0
/* The following function is basically a hacked version of the code in
 * examples/encoder_example.c */
void
write_vorbis_data_or_die (const char *filename, int srate, float q, const float * data, int count, int ch)
{
  FILE * file ;
  ogg_stream_state os;
  ogg_page         og;
  ogg_packet       op;
  vorbis_info      vi;
  vorbis_comment   vc;
  vorbis_dsp_state vd;
  vorbis_block     vb;

  int eos = 0, ret;

  if ((file = fopen (filename, "wb")) == NULL) {
    printf("\n\nError : fopen failed : %s\n", strerror (errno)) ;
    exit (1) ;
  }

  /********** Encode setup ************/

  vorbis_info_init (&vi);

  ret = vorbis_encode_init_vbr (&vi,ch,srate,q);
  if (ret) {
    printf ("vorbis_encode_init_vbr return %d\n", ret) ;
    exit (1) ;
  }

  vorbis_comment_init (&vc);
  vorbis_comment_add_tag (&vc,"ENCODER","test/util.c");
  vorbis_analysis_init (&vd,&vi);
  vorbis_block_init (&vd,&vb);

  ogg_stream_init (&os,12345678);

  {
    ogg_packet header;
    ogg_packet header_comm;
    ogg_packet header_code;

    vorbis_analysis_headerout (&vd,&vc,&header,&header_comm,&header_code);
    ogg_stream_packetin (&os,&header);
    ogg_stream_packetin (&os,&header_comm);
    ogg_stream_packetin (&os,&header_code);

    /* Ensures the audio data will start on a new page. */
    while (!eos){
        int result = ogg_stream_flush (&os,&og);
        if (result == 0)
            break;
        fwrite (og.header,1,og.header_len,file);
        fwrite (og.body,1,og.body_len,file);
    }

  }

  {
    /* expose the buffer to submit data */
    float **buffer = vorbis_analysis_buffer (&vd,count);
    int i;

    for(i=0;i<ch;i++)
      memcpy (buffer [i], data, count * sizeof (float)) ;

    /* tell the library how much we actually submitted */
    vorbis_analysis_wrote (&vd,count);
    vorbis_analysis_wrote (&vd,0);
  }

  while (vorbis_analysis_blockout (&vd,&vb) == 1) {
    vorbis_analysis (&vb,NULL);
    vorbis_bitrate_addblock (&vb);

    while (vorbis_bitrate_flushpacket (&vd,&op)) {
      ogg_stream_packetin (&os,&op);

      while (!eos) {
          int result = ogg_stream_pageout (&os,&og);
          if (result == 0)
              break;
          fwrite (og.header,1,og.header_len,file);
          fwrite (og.body,1,og.body_len,file);

          if (ogg_page_eos (&og))
              eos = 1;
      }
    }
  }

  ogg_stream_clear (&os);
  vorbis_block_clear (&vb);
  vorbis_dsp_clear (&vd);
  vorbis_comment_clear (&vc);
  vorbis_info_clear (&vi);

 fclose (file) ;
}
Esempio n. 11
0
static void
vorbis_end (stream_processor *stream, sf_count_t * len)
{	*len += stream->lastgranulepos ;
	vorbis_comment_clear (&stream->vcomment) ;
	vorbis_info_clear (&stream->vinfo) ;
} /* vorbis_end */
Esempio n. 12
0
static int
vorbis_read_header (SF_PRIVATE *psf, int log_data)
{
	OGG_PRIVATE *odata = (OGG_PRIVATE *) psf->container_data ;
	VORBIS_PRIVATE *vdata = (VORBIS_PRIVATE *) psf->codec_data ;
	char *buffer ;
	int	bytes ;
	int i, nn ;

	odata->eos = 0 ;

	/* Weird stuff happens if these aren't called. */
	ogg_stream_reset (&odata->ostream) ;
	ogg_sync_reset (&odata->osync) ;

	/*
	**	Grab some data at the head of the stream.  We want the first page
	**	(which is guaranteed to be small and only contain the Vorbis
	**	stream initial header) We need the first page to get the stream
	**	serialno.
	*/

	/* Expose the buffer */
	buffer = ogg_sync_buffer (&odata->osync, 4096L) ;

	/* Grab the part of the header that has already been read. */
	memcpy (buffer, psf->header, psf->headindex) ;
	bytes = psf->headindex ;

	/* Submit a 4k block to libvorbis' Ogg layer */
	bytes += psf_fread (buffer + psf->headindex, 1, 4096 - psf->headindex, psf) ;
	ogg_sync_wrote (&odata->osync, bytes) ;

	/* Get the first page. */
	if ((nn = ogg_sync_pageout (&odata->osync, &odata->opage)) != 1)
	{
		/* Have we simply run out of data?  If so, we're done. */
		if (bytes < 4096)
			return 0 ;

		/* Error case.  Must not be Vorbis data */
		psf_log_printf (psf, "Input does not appear to be an Ogg bitstream.\n") ;
		return SFE_MALFORMED_FILE ;
		} ;

	/*
	**	Get the serial number and set up the rest of decode.
	**	Serialno first ; use it to set up a logical stream.
	*/
	ogg_stream_clear (&odata->ostream) ;
	ogg_stream_init (&odata->ostream, ogg_page_serialno (&odata->opage)) ;

	if (ogg_stream_pagein (&odata->ostream, &odata->opage) < 0)
	{	/* Error ; stream version mismatch perhaps. */
		psf_log_printf (psf, "Error reading first page of Ogg bitstream data\n") ;
		return SFE_MALFORMED_FILE ;
		} ;

	if (ogg_stream_packetout (&odata->ostream, &odata->opacket) != 1)
	{	/* No page? must not be vorbis. */
		psf_log_printf (psf, "Error reading initial header packet.\n") ;
		return SFE_MALFORMED_FILE ;
		} ;

	/*
	**	This function (vorbis_read_header) gets called multiple times, so the OGG
	**	and vorbis structs have to be cleared every time we pass through to
	**	prevent memory leaks.
	*/
	vorbis_block_clear (&vdata->vblock) ;
	vorbis_dsp_clear (&vdata->vdsp) ;
	vorbis_comment_clear (&vdata->vcomment) ;
	vorbis_info_clear (&vdata->vinfo) ;

	/*
	**	Extract the initial header from the first page and verify that the
	**	Ogg bitstream is in fact Vorbis data.
	**
	**	I handle the initial header first instead of just having the code
	**	read all three Vorbis headers at once because reading the initial
	**	header is an easy way to identify a Vorbis bitstream and it's
	**	useful to see that functionality seperated out.
	*/
	vorbis_info_init (&vdata->vinfo) ;
	vorbis_comment_init (&vdata->vcomment) ;

	if (vorbis_synthesis_headerin (&vdata->vinfo, &vdata->vcomment, &odata->opacket) < 0)
	{	/* Error case ; not a vorbis header. */
		psf_log_printf (psf, "Found Vorbis in stream header, but vorbis_synthesis_headerin failed.\n") ;
		return SFE_MALFORMED_FILE ;
		} ;

	/*
	**	Common Ogg metadata fields?
	**	TITLE, VERSION, ALBUM, TRACKNUMBER, ARTIST, PERFORMER, COPYRIGHT, LICENSE,
	**	ORGANIZATION, DESCRIPTION, GENRE, DATE, LOCATION, CONTACT, ISRC,
	*/

	if (log_data)
	{	int k ;

		for (k = 0 ; k < ARRAY_LEN (vorbis_metatypes) ; k++)
		{	char *dd ;

			dd = vorbis_comment_query (&vdata->vcomment, vorbis_metatypes [k].name, 0) ;
			if (dd == NULL)
				continue ;
			psf_store_string (psf, vorbis_metatypes [k].id, dd) ;
			} ;
		} ;

	/*
	**	At this point, we're sure we're Vorbis.	We've set up the logical (Ogg)
	**	bitstream decoder. Get the comment and codebook headers and set up the
	**	Vorbis decoder.
	**
	**	The next two packets in order are the comment and codebook headers.
	**	They're likely large and may span multiple pages.  Thus we reead
	**	and submit data until we get our two pacakets, watching that no
	**	pages are missing.  If a page is missing, error out ; losing a
	**	header page is the only place where missing data is fatal.
	*/

	i = 0 ;			/* Count of number of packets read */
	while (i < 2)
	{	int result = ogg_sync_pageout (&odata->osync, &odata->opage) ;
		if (result == 0)
		{	/* Need more data */
			buffer = ogg_sync_buffer (&odata->osync, 4096) ;
			bytes = psf_fread (buffer, 1, 4096, psf) ;

			if (bytes == 0 && i < 2)
			{	psf_log_printf (psf, "End of file before finding all Vorbis headers!\n") ;
				return SFE_MALFORMED_FILE ;
				} ;
			nn = ogg_sync_wrote (&odata->osync, bytes) ;
			}
		else if (result == 1)
		{	/*
			**	Don't complain about missing or corrupt data yet. We'll
			**	catch it at the packet output phase.
			**
			**	We can ignore any errors here as they'll also become apparent
			**	at packetout.
			*/
			nn = ogg_stream_pagein (&odata->ostream, &odata->opage) ;
			while (i < 2)
			{	result = ogg_stream_packetout (&odata->ostream, &odata->opacket) ;
				if (result == 0)
					break ;
				if (result < 0)
				{	/*	Uh oh ; data at some point was corrupted or missing!
					**	We can't tolerate that in a header. Die. */
					psf_log_printf (psf, "Corrupt secondary header.	Exiting.\n") ;
					return SFE_MALFORMED_FILE ;
					} ;

				vorbis_synthesis_headerin (&vdata->vinfo, &vdata->vcomment, &odata->opacket) ;
				i++ ;
				} ;
			} ;
		} ;

	if (log_data)
	{	int printed_metadata_msg = 0 ;
		int k ;

		psf_log_printf (psf, "Bitstream is %d channel, %D Hz\n", vdata->vinfo.channels, vdata->vinfo.rate) ;
		psf_log_printf (psf, "Encoded by : %s\n", vdata->vcomment.vendor) ;

		/* Throw the comments plus a few lines about the bitstream we're decoding. */
		for (k = 0 ; k < ARRAY_LEN (vorbis_metatypes) ; k++)
		{	char *dd ;

			dd = vorbis_comment_query (&vdata->vcomment, vorbis_metatypes [k].name, 0) ;
			if (dd == NULL)
				continue ;

			if (printed_metadata_msg == 0)
			{	psf_log_printf (psf, "Metadata :\n") ;
				printed_metadata_msg = 1 ;
				} ;

			psf_store_string (psf, vorbis_metatypes [k].id, dd) ;
			psf_log_printf (psf, "  %-10s : %s\n", vorbis_metatypes [k].name, dd) ;
			} ;

		psf_log_printf (psf, "End\n") ;
		} ;

	psf->sf.samplerate	= vdata->vinfo.rate ;
	psf->sf.channels	= vdata->vinfo.channels ;
	psf->sf.format		= SF_FORMAT_OGG | SF_FORMAT_VORBIS ;

	/*	OK, got and parsed all three headers. Initialize the Vorbis
	**	packet->PCM decoder.
	**	Central decode state. */
	vorbis_synthesis_init (&vdata->vdsp, &vdata->vinfo) ;

	/*	Local state for most of the decode so multiple block decodes can
	**	proceed in parallel. We could init multiple vorbis_block structures
	**	for vd here. */
	vorbis_block_init (&vdata->vdsp, &vdata->vblock) ;

	vdata->loc = 0 ;

	return 0 ;
} /* vorbis_read_header */
Esempio n. 13
0
int main(int argc, char **argv)
{
    /* Default values */
    oe_options opt = {
              NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0,
              NULL, 0, NULL, 0, NULL, 0, NULL, 0, NULL, 0,
              1, 0, 0, 0,
              16,44100,2, 0,
              NULL, DEFAULT_NAMEFMT_REMOVE, DEFAULT_NAMEFMT_REPLACE,
              NULL,
              0, -1,-1,-1,
              .3,-1,
              0,0,0.f,
              0, 0, 0, 0, 0};

    int i;

    char **infiles;
    int numfiles;
    int errors=0;

    get_args_from_ucs16(&argc, &argv);

    setlocale(LC_ALL, "");
    bindtextdomain(PACKAGE, LOCALEDIR);
    textdomain(PACKAGE);

    parse_options(argc, argv, &opt);

    if(optind >= argc)
    {
        fprintf(stderr, _("ERROR: No input files specified. Use -h for help.\n"));
        return 1;
    }
    else
    {
        infiles = argv + optind;
        numfiles = argc - optind;
    }

    /* Now, do some checking for illegal argument combinations */

    for(i = 0; i < numfiles; i++)
    {
        if(!strcmp(infiles[i], "-") && numfiles > 1)
        {
            fprintf(stderr, _("ERROR: Multiple files specified when using stdin\n"));
            exit(1);
        }
    }

    if(numfiles > 1 && opt.outfile)
    {
        fprintf(stderr, _("ERROR: Multiple input files with specified output filename: suggest using -n\n"));
        exit(1);
    }

    if(!opt.fixedserial)
    {
                /* We randomly pick a serial number. This is then incremented for each
                   file. The random seed includes the PID so two copies of oggenc that
                   start in the same second will generate different serial numbers. */
                srand(time(NULL) ^ getpid());
        opt.serial = rand();
    }
    opt.skeleton_serial = opt.serial + numfiles;
    opt.kate_serial = opt.skeleton_serial + numfiles;

    for(i = 0; i < numfiles; i++)
    {
        /* Once through the loop for each file */

        oe_enc_opt      enc_opts;
        vorbis_comment  vc;
        char *out_fn = NULL;
        FILE *in, *out = NULL;
        int foundformat = 0;
        int closeout = 0, closein = 0;
        char *artist=NULL, *album=NULL, *title=NULL, *track=NULL;
        char *date=NULL, *genre=NULL;
        char *lyrics=NULL, *lyrics_language=NULL;
        input_format *format;
        int resampled = 0;

        /* Set various encoding defaults */

        enc_opts.serialno = opt.serial++;
        enc_opts.skeleton_serialno = opt.skeleton_serial++;
        enc_opts.kate_serialno = opt.kate_serial++;
        enc_opts.progress_update = update_statistics_full;
        enc_opts.start_encode = start_encode_full;
        enc_opts.end_encode = final_statistics;
        enc_opts.error = encode_error;
        enc_opts.comments = &vc;
        enc_opts.copy_comments = opt.copy_comments;
        enc_opts.with_skeleton = opt.with_skeleton;
        enc_opts.ignorelength = opt.ignorelength;

        /* OK, let's build the vorbis_comments structure */
        build_comments(&vc, &opt, i, &artist, &album, &title, &track,
                &date, &genre);

        if(opt.lyrics_count)
        {
            if(i >= opt.lyrics_count)
            {
                lyrics = NULL;
            }
            else
                lyrics = opt.lyrics[i];
        }

        if(opt.lyrics_language_count)
        {
            if(i >= opt.lyrics_language_count)
            {
                if(!opt.quiet)
                    fprintf(stderr, _("WARNING: Insufficient lyrics languages specified, defaulting to final lyrics language.\n"));
                lyrics_language = opt.lyrics_language[opt.lyrics_language_count-1];
            }
            else
                lyrics_language = opt.lyrics_language[i];
        }

        if(!strcmp(infiles[i], "-"))
        {
            setbinmode(stdin);
            in = stdin;
            infiles[i] = NULL;
            if(!opt.outfile)
            {
                setbinmode(stdout);
                out = stdout;
            }
        }
        else
        {
            in = oggenc_fopen(infiles[i], "rb", opt.isutf8);

            if(in == NULL)
            {
                fprintf(stderr, _("ERROR: Cannot open input file \"%s\": %s\n"), infiles[i], strerror(errno));
                free(out_fn);
                errors++;
                continue;
            }

            closein = 1;
        }

        /* Now, we need to select an input audio format - we do this before opening
           the output file so that we don't end up with a 0-byte file if the input
           file can't be read */

        if(opt.rawmode)
        {
            input_format raw_format = {NULL, 0, raw_open, wav_close, "raw", 
                N_("RAW file reader")};

            enc_opts.rate=opt.raw_samplerate;
            enc_opts.channels=opt.raw_channels;
            enc_opts.samplesize=opt.raw_samplesize;
            enc_opts.endianness=opt.raw_endianness;

            format = &raw_format;
            format->open_func(in, &enc_opts, NULL, 0);
            foundformat=1;
        }
        else
        {
            format = open_audio_file(in, &enc_opts);
            if(format)
            {
                if(!opt.quiet)
                    fprintf(stderr, _("Opening with %s module: %s\n"),
                            format->format, format->description);
                foundformat=1;
            }

        }

        if(!foundformat)
        {
            fprintf(stderr, _("ERROR: Input file \"%s\" is not a supported format\n"), infiles[i]?infiles[i]:"(stdin)");
            if(closein)
                fclose(in);
            errors++;
            continue;
        }

        /* Ok. We can read the file - so now open the output file */

        if(opt.outfile && !strcmp(opt.outfile, "-"))
        {
            setbinmode(stdout);
            out = stdout;
        }
        else if(out == NULL)
        {
            if(opt.outfile)
            {
                out_fn = strdup(opt.outfile);
            }
            else if(opt.namefmt)
            {
                out_fn = generate_name_string(opt.namefmt, opt.namefmt_remove, 
                        opt.namefmt_replace, artist, title, album, track,date,
                        genre);
            }
            /* This bit was widely derided in mid-2002, so it's been removed */
            /*
            else if(opt.title)
            {
                out_fn = malloc(strlen(title) + 5);
                strcpy(out_fn, title);
                strcat(out_fn, ".ogg");
            }
            */
            else if(infiles[i])
            {
                /* Create a filename from existing filename, replacing extension with .ogg or .oga */
                char *start, *end;
                char *extension;

                /* if adding Skeleton or Kate, we're not Vorbis I anymore */
                extension = (opt.with_skeleton || opt.lyrics_count>0) ? ".oga" : ".ogg";

                start = infiles[i];
                end = strrchr(infiles[i], '.');
                end = end?end:(start + strlen(infiles[i])+1);

                out_fn = malloc(end - start + 5);
                strncpy(out_fn, start, end-start);
                out_fn[end-start] = 0;
                strcat(out_fn, extension);
            }
            else {
                /* if adding skeleton or kate, we're not Vorbis I anymore */
                if (opt.with_skeleton || opt.lyrics_count>0)
                    out_fn = strdup("default.oga");
                else
                    out_fn = strdup("default.ogg");
                fprintf(stderr, _("WARNING: No filename, defaulting to \"%s\"\n"), out_fn);
            }

            /* Create any missing subdirectories, if possible */
            if(create_directories(out_fn, opt.isutf8)) {
                if(closein)
                    fclose(in);
                fprintf(stderr, _("ERROR: Could not create required subdirectories for output filename \"%s\"\n"), out_fn);
                errors++;
                free(out_fn);
                continue;
            }

            if(infiles[i] && !strcmp(infiles[i], out_fn)) {
                fprintf(stderr, _("ERROR: Input filename is the same as output filename \"%s\"\n"), out_fn);
                errors++;
                free(out_fn);
                continue;
            }

            out = oggenc_fopen(out_fn, "wb", opt.isutf8);
            if(out == NULL)
            {
                if(closein)
                    fclose(in);
                fprintf(stderr, _("ERROR: Cannot open output file \"%s\": %s\n"), out_fn, strerror(errno));
                errors++;
                free(out_fn);
                continue;
            }
            closeout = 1;
        }

        /* Now, set the rest of the options */
        enc_opts.out = out;
        enc_opts.comments = &vc;
#ifdef _WIN32
        if (opt.isutf8) {
            enc_opts.filename = NULL;
            enc_opts.infilename = NULL;
            utf8_decode(out_fn, &enc_opts.filename);
            utf8_decode(infiles[i], &enc_opts.infilename);
        } else {
            enc_opts.filename = strdup(out_fn);
            enc_opts.infilename = strdup(infiles[i]);
        }
#else
        enc_opts.filename = out_fn;
        enc_opts.infilename = infiles[i];
#endif
        enc_opts.managed = opt.managed;
        enc_opts.bitrate = opt.nominal_bitrate; 
        enc_opts.min_bitrate = opt.min_bitrate;
        enc_opts.max_bitrate = opt.max_bitrate;
        enc_opts.quality = opt.quality;
        enc_opts.quality_set = opt.quality_set;
        enc_opts.advopt = opt.advopt;
        enc_opts.advopt_count = opt.advopt_count;
        enc_opts.lyrics = lyrics;
        enc_opts.lyrics_language = lyrics_language;

        if(opt.resamplefreq && opt.resamplefreq != enc_opts.rate) {
            int fromrate = enc_opts.rate;

            resampled = 1;
            enc_opts.resamplefreq = opt.resamplefreq;
            if(setup_resample(&enc_opts)) {
                errors++;
                goto clear_all;
            }
            else if(!opt.quiet)
                fprintf(stderr, _("Resampling input from %d Hz to %d Hz\n"), fromrate, opt.resamplefreq);
        }

        if(opt.downmix) {
            if(enc_opts.channels == 2) {
                setup_downmix(&enc_opts);
                if(!opt.quiet)
                    fprintf(stderr, _("Downmixing stereo to mono\n"));
            }
            else {
                fprintf(stderr, _("WARNING: Can't downmix except from stereo to mono\n"));
                opt.downmix = 0;
            }
        }

        if(opt.scale > 0.f) {
            setup_scaler(&enc_opts, opt.scale);
            if(!opt.quiet)
                fprintf(stderr, _("Scaling input to %f\n"), opt.scale);
        }


        if(!enc_opts.total_samples_per_channel)
            enc_opts.progress_update = update_statistics_notime;

        if(opt.quiet)
        {
            enc_opts.start_encode = start_encode_null;
            enc_opts.progress_update = update_statistics_null;
            enc_opts.end_encode = final_statistics_null;
        }

        if(oe_encode(&enc_opts))
            errors++;

        if(opt.scale > 0)
            clear_scaler(&enc_opts);
        if(opt.downmix)
            clear_downmix(&enc_opts);
        if(resampled)
            clear_resample(&enc_opts);
clear_all:

        if(out_fn) free(out_fn);
        if(opt.outfile) free(opt.outfile);
#ifdef _WIN32
        if(enc_opts.filename) free(enc_opts.filename);
        if(enc_opts.infilename) free(enc_opts.infilename);
#endif
        vorbis_comment_clear(&vc);
        format->close_func(enc_opts.readdata);

        if(closein)
            fclose(in);
        if(closeout)
            fclose(out);
    }/* Finished this file, loop around to next... */

    return errors?1:0;

}
//---------------------------Start Destructor--------------------------------------//
VorbisPropertyHandler::~VorbisPropertyHandler(void) {
   // Delete Vorbis structures
   vorbis_info_clear (&m_oInfo);
   vorbis_comment_clear (&m_oComment);
}
MyVorbisExtractor::~MyVorbisExtractor() {
    vorbis_comment_clear(&mVc);
    vorbis_info_clear(&mVi);
}
Esempio n. 16
0
G_MODULE_EXPORT gboolean
tracker_extract_get_metadata (TrackerExtractInfo *info)
{
	TrackerSparqlBuilder *preupdate, *metadata;
	VorbisData vd = { 0 };
	MergeData md = { 0 };
	FILE *f;
	gchar *filename, *uri;
	OggVorbis_File vf;
	vorbis_comment *comment;
	vorbis_info *vi;
	unsigned int bitrate;
	gint time;
	GFile *file;
	const gchar *graph;

	file = tracker_extract_info_get_file (info);
	filename = g_file_get_path (file);
	f = tracker_file_open (filename);
	g_free (filename);

	preupdate = tracker_extract_info_get_preupdate_builder (info);
	metadata = tracker_extract_info_get_metadata_builder (info);
	graph = tracker_extract_info_get_graph (info);

	if (!f) {
		return FALSE;
	}

	if (ov_open (f, &vf, NULL, 0) < 0) {
		tracker_file_close (f, FALSE);
		return FALSE;
	}

	tracker_sparql_builder_predicate (metadata, "a");
	tracker_sparql_builder_object (metadata, "nmm:MusicPiece");
	tracker_sparql_builder_object (metadata, "nfo:Audio");

	if ((comment = ov_comment (&vf, -1)) != NULL) {
		gchar *date;

		vd.title = ogg_get_comment (comment, "title");
		vd.artist = ogg_get_comment (comment, "artist");
		vd.album = ogg_get_comment (comment, "album");
		vd.album_artist = ogg_get_comment (comment, "albumartist");
		vd.track_count = ogg_get_comment (comment, "trackcount");
		vd.track_number = ogg_get_comment (comment, "tracknumber");
		vd.disc_number = ogg_get_comment (comment, "DiscNo");
		vd.performer = ogg_get_comment (comment, "Performer");
		vd.track_gain = ogg_get_comment (comment, "TrackGain");
		vd.track_peak_gain = ogg_get_comment (comment, "TrackPeakGain");
		vd.album_gain = ogg_get_comment (comment, "AlbumGain");
		vd.album_peak_gain = ogg_get_comment (comment, "AlbumPeakGain");

		date = ogg_get_comment (comment, "date");
		vd.date = tracker_date_guess (date);
		g_free (date);

		vd.comment = ogg_get_comment (comment, "comment");
		vd.genre = ogg_get_comment (comment, "genre");
		vd.codec = ogg_get_comment (comment, "Codec");
		vd.codec_version = ogg_get_comment (comment, "CodecVersion");
		vd.sample_rate = ogg_get_comment (comment, "SampleRate");
		vd.channels = ogg_get_comment (comment, "Channels");
		vd.mb_album_id = ogg_get_comment (comment, "MBAlbumID");
		vd.mb_artist_id = ogg_get_comment (comment, "MBArtistID");
		vd.mb_album_artist_id = ogg_get_comment (comment, "MBAlbumArtistID");
		vd.mb_track_id = ogg_get_comment (comment, "MBTrackID");
		vd.lyrics = ogg_get_comment (comment, "Lyrics");
		vd.copyright = ogg_get_comment (comment, "Copyright");
		vd.license = ogg_get_comment (comment, "License");
		vd.organization = ogg_get_comment (comment, "Organization");
		vd.location = ogg_get_comment (comment, "Location");
		vd.publisher = ogg_get_comment (comment, "Publisher");

		vorbis_comment_clear (comment);
	}

	md.creator = tracker_coalesce_strip (3, vd.artist, vd.album_artist, vd.performer);

	if (md.creator) {
		/* NOTE: This must be created before vd.album is evaluated */
		md.creator_uri = tracker_sparql_escape_uri_printf ("urn:artist:%s", md.creator);

		tracker_sparql_builder_insert_open (preupdate, NULL);
		if (graph) {
			tracker_sparql_builder_graph_open (preupdate, graph);
		}

		tracker_sparql_builder_subject_iri (preupdate, md.creator_uri);
		tracker_sparql_builder_predicate (preupdate, "a");
		tracker_sparql_builder_object (preupdate, "nmm:Artist");
		tracker_sparql_builder_predicate (preupdate, "nmm:artistName");
		tracker_sparql_builder_object_unvalidated (preupdate, md.creator);

		if (graph) {
			tracker_sparql_builder_graph_close (preupdate);
		}
		tracker_sparql_builder_insert_close (preupdate);

		tracker_sparql_builder_predicate (metadata, "nmm:performer");
		tracker_sparql_builder_object_iri (metadata, md.creator_uri);
	}

	if (vd.album) {
		gchar *uri = tracker_sparql_escape_uri_printf ("urn:album:%s", vd.album);
		gchar *album_disc_uri;

		tracker_sparql_builder_insert_open (preupdate, NULL);
		if (graph) {
			tracker_sparql_builder_graph_open (preupdate, graph);
		}

		tracker_sparql_builder_subject_iri (preupdate, uri);
		tracker_sparql_builder_predicate (preupdate, "a");
		tracker_sparql_builder_object (preupdate, "nmm:MusicAlbum");
		/* FIXME: nmm:albumTitle is now deprecated
		 * tracker_sparql_builder_predicate (preupdate, "nie:title");
		 */
		tracker_sparql_builder_predicate (preupdate, "nmm:albumTitle");
		tracker_sparql_builder_object_unvalidated (preupdate, vd.album);

		if (md.creator_uri) {
			tracker_sparql_builder_predicate (preupdate, "nmm:albumArtist");
			tracker_sparql_builder_object_iri (preupdate, md.creator_uri);
		}

		if (graph) {
			tracker_sparql_builder_graph_close (preupdate);
		}
		tracker_sparql_builder_insert_close (preupdate);

		if (vd.track_count) {
			tracker_sparql_builder_delete_open (preupdate, NULL);
			tracker_sparql_builder_subject_iri (preupdate, uri);
			tracker_sparql_builder_predicate (preupdate, "nmm:albumTrackCount");
			tracker_sparql_builder_object_variable (preupdate, "unknown");
			tracker_sparql_builder_delete_close (preupdate);

			tracker_sparql_builder_where_open (preupdate);
			tracker_sparql_builder_subject_iri (preupdate, uri);
			tracker_sparql_builder_predicate (preupdate, "nmm:albumTrackCount");
			tracker_sparql_builder_object_variable (preupdate, "unknown");
			tracker_sparql_builder_where_close (preupdate);

			tracker_sparql_builder_insert_open (preupdate, NULL);
			if (graph) {
				tracker_sparql_builder_graph_open (preupdate, graph);
			}

			tracker_sparql_builder_subject_iri (preupdate, uri);
			tracker_sparql_builder_predicate (preupdate, "nmm:albumTrackCount");
			tracker_sparql_builder_object_unvalidated (preupdate, vd.track_count);

			if (graph) {
				tracker_sparql_builder_graph_close (preupdate);
			}
			tracker_sparql_builder_insert_close (preupdate);
		}

		if (vd.album_gain) {
			tracker_sparql_builder_delete_open (preupdate, NULL);
			tracker_sparql_builder_subject_iri (preupdate, uri);
			tracker_sparql_builder_predicate (preupdate, "nmm:albumGain");
			tracker_sparql_builder_object_variable (preupdate, "unknown");
			tracker_sparql_builder_delete_close (preupdate);

			tracker_sparql_builder_where_open (preupdate);
			tracker_sparql_builder_subject_iri (preupdate, uri);
			tracker_sparql_builder_predicate (preupdate, "nmm:albumGain");
			tracker_sparql_builder_object_variable (preupdate, "unknown");
			tracker_sparql_builder_where_close (preupdate);

			tracker_sparql_builder_insert_open (preupdate, NULL);
			if (graph) {
				tracker_sparql_builder_graph_open (preupdate, graph);
			}

			tracker_sparql_builder_subject_iri (preupdate, uri);
			tracker_sparql_builder_predicate (preupdate, "nmm:albumGain");
			tracker_sparql_builder_object_double (preupdate, atof (vd.album_gain));

			if (graph) {
				tracker_sparql_builder_graph_close (preupdate);
			}
			tracker_sparql_builder_insert_close (preupdate);
		}

		if (vd.album_peak_gain) {
			tracker_sparql_builder_delete_open (preupdate, NULL);
			tracker_sparql_builder_subject_iri (preupdate, uri);
			tracker_sparql_builder_predicate (preupdate, "nmm:albumPeakGain");
			tracker_sparql_builder_object_variable (preupdate, "unknown");
			tracker_sparql_builder_delete_close (preupdate);

			tracker_sparql_builder_where_open (preupdate);
			tracker_sparql_builder_subject_iri (preupdate, uri);
			tracker_sparql_builder_predicate (preupdate, "nmm:albumPeakGain");
			tracker_sparql_builder_object_variable (preupdate, "unknown");
			tracker_sparql_builder_where_close (preupdate);

			tracker_sparql_builder_insert_open (preupdate, NULL);
			if (graph) {
				tracker_sparql_builder_graph_open (preupdate, graph);
			}

			tracker_sparql_builder_subject_iri (preupdate, uri);
			tracker_sparql_builder_predicate (preupdate, "nmm:albumPeakGain");
			tracker_sparql_builder_object_double (preupdate, atof (vd.album_peak_gain));

			if (graph) {
				tracker_sparql_builder_graph_close (preupdate);
			}
			tracker_sparql_builder_insert_close (preupdate);
		}

		album_disc_uri = tracker_sparql_escape_uri_printf ("urn:album-disc:%s:Disc%d",
		                                                   vd.album,
		                                                   vd.disc_number ? atoi(vd.disc_number) : 1);

		tracker_sparql_builder_delete_open (preupdate, NULL);
		tracker_sparql_builder_subject_iri (preupdate, album_disc_uri);
		tracker_sparql_builder_predicate (preupdate, "nmm:setNumber");
		tracker_sparql_builder_object_variable (preupdate, "unknown");
		tracker_sparql_builder_delete_close (preupdate);
		tracker_sparql_builder_where_open (preupdate);
		tracker_sparql_builder_subject_iri (preupdate, album_disc_uri);
		tracker_sparql_builder_predicate (preupdate, "nmm:setNumber");
		tracker_sparql_builder_object_variable (preupdate, "unknown");
		tracker_sparql_builder_where_close (preupdate);

		tracker_sparql_builder_delete_open (preupdate, NULL);
		tracker_sparql_builder_subject_iri (preupdate, album_disc_uri);
		tracker_sparql_builder_predicate (preupdate, "nmm:albumDiscAlbum");
		tracker_sparql_builder_object_variable (preupdate, "unknown");
		tracker_sparql_builder_delete_close (preupdate);
		tracker_sparql_builder_where_open (preupdate);
		tracker_sparql_builder_subject_iri (preupdate, album_disc_uri);
		tracker_sparql_builder_predicate (preupdate, "nmm:albumDiscAlbum");
		tracker_sparql_builder_object_variable (preupdate, "unknown");
		tracker_sparql_builder_where_close (preupdate);

		tracker_sparql_builder_insert_open (preupdate, NULL);
		if (graph) {
			tracker_sparql_builder_graph_open (preupdate, graph);
		}

		tracker_sparql_builder_subject_iri (preupdate, album_disc_uri);
		tracker_sparql_builder_predicate (preupdate, "a");
		tracker_sparql_builder_object (preupdate, "nmm:MusicAlbumDisc");
		tracker_sparql_builder_predicate (preupdate, "nmm:setNumber");
		tracker_sparql_builder_object_int64 (preupdate, vd.disc_number ? atoi (vd.disc_number) : 1);
		tracker_sparql_builder_predicate (preupdate, "nmm:albumDiscAlbum");
		tracker_sparql_builder_object_iri (preupdate, uri);

		if (graph) {
			tracker_sparql_builder_graph_close (preupdate);
		}
		tracker_sparql_builder_insert_close (preupdate);

		tracker_sparql_builder_predicate (metadata, "nmm:musicAlbumDisc");
		tracker_sparql_builder_object_iri (metadata, album_disc_uri);

	        g_free (album_disc_uri);

		tracker_sparql_builder_predicate (metadata, "nmm:musicAlbum");
		tracker_sparql_builder_object_iri (metadata, uri);
		g_free (uri);
	}

	g_free (vd.track_count);
	g_free (vd.album_peak_gain);
	g_free (vd.album_gain);
	g_free (vd.disc_number);

	if (vd.title) {
		tracker_sparql_builder_predicate (metadata, "nie:title");
		tracker_sparql_builder_object_unvalidated (metadata, vd.title);
		g_free (vd.title);
	}

	if (vd.track_number) {
		tracker_sparql_builder_predicate (metadata, "nmm:trackNumber");
		tracker_sparql_builder_object_unvalidated (metadata, vd.track_number);
		g_free (vd.track_number);
	}

	if (vd.track_gain) {
		/* TODO */
		g_free (vd.track_gain);
	}

	if (vd.track_peak_gain) {
		/* TODO */
		g_free (vd.track_peak_gain);
	}

	if (vd.comment) {
		tracker_sparql_builder_predicate (metadata, "nie:comment");
		tracker_sparql_builder_object_unvalidated (metadata, vd.comment);
		g_free (vd.comment);
	}

	if (vd.date) {
		tracker_sparql_builder_predicate (metadata, "nie:contentCreated");
		tracker_sparql_builder_object_unvalidated (metadata, vd.date);
		g_free (vd.date);
	}

	if (vd.genre) {
		tracker_sparql_builder_predicate (metadata, "nfo:genre");
		tracker_sparql_builder_object_unvalidated (metadata, vd.genre);
		g_free (vd.genre);
	}

	if (vd.codec) {
		tracker_sparql_builder_predicate (metadata, "nfo:codec");
		tracker_sparql_builder_object_unvalidated (metadata, vd.codec);
		g_free (vd.codec);
	}

	if (vd.codec_version) {
		/* TODO */
		g_free (vd.codec_version);
	}

	if (vd.sample_rate) {
		tracker_sparql_builder_predicate (metadata, "nfo:sampleRate");
		tracker_sparql_builder_object_unvalidated (metadata, vd.sample_rate);
		g_free (vd.sample_rate);
	}

	if (vd.channels) {
		tracker_sparql_builder_predicate (metadata, "nfo:channels");
		tracker_sparql_builder_object_unvalidated (metadata, vd.channels);
		g_free (vd.channels);
	}

	if (vd.mb_album_id) {
		/* TODO */
		g_free (vd.mb_album_id);
	}

	if (vd.mb_artist_id) {
		/* TODO */
		g_free (vd.mb_artist_id);
	}

	if (vd.mb_album_artist_id) {
		/* TODO */
		g_free (vd.mb_album_artist_id);
	}

	if (vd.mb_track_id) {
		/* TODO */
		g_free (vd.mb_track_id);
	}

	if (vd.lyrics) {
		tracker_sparql_builder_predicate (metadata, "nie:plainTextContent");
		tracker_sparql_builder_object_unvalidated (metadata, vd.lyrics);
		g_free (vd.lyrics);
	}

	if (vd.copyright) {
		tracker_sparql_builder_predicate (metadata, "nie:copyright");
		tracker_sparql_builder_object_unvalidated (metadata, vd.copyright);
		g_free (vd.copyright);
	}

	if (vd.license) {
		tracker_sparql_builder_predicate (metadata, "nie:license");
		tracker_sparql_builder_object_unvalidated (metadata, vd.license);
		g_free (vd.license);
	}

	if (vd.organization) {
		/* TODO */
		g_free (vd.organization);
	}

	if (vd.location) {
		/* TODO */
		g_free (vd.location);
	}

	if (vd.publisher) {
		tracker_sparql_builder_predicate (metadata, "dc:publisher");

		tracker_sparql_builder_object_blank_open (metadata);
		tracker_sparql_builder_predicate (metadata, "a");
		tracker_sparql_builder_object (metadata, "nco:Contact");

		tracker_sparql_builder_predicate (metadata, "nco:fullname");
		tracker_sparql_builder_object_unvalidated (metadata, vd.publisher);
		tracker_sparql_builder_object_blank_close (metadata);
		g_free (vd.publisher);
	}

	if ((vi = ov_info (&vf, 0)) != NULL ) {
		bitrate = vi->bitrate_nominal / 1000;

		tracker_sparql_builder_predicate (metadata, "nfo:averageBitrate");
		tracker_sparql_builder_object_int64 (metadata, (gint64) bitrate);
	}

	/* Duration */
	if ((time = ov_time_total (&vf, -1)) != OV_EINVAL) {
		tracker_sparql_builder_predicate (metadata, "nfo:duration");
		tracker_sparql_builder_object_int64 (metadata, (gint64) time);
	}

	uri = g_file_get_uri (file);
	tracker_media_art_process (NULL,
				0,
				NULL,
				TRACKER_MEDIA_ART_ALBUM,
				vd.album_artist ? vd.album_artist : vd.artist,
				vd.album,
				uri);
	g_free (uri);

	g_free (vd.artist);
	g_free (vd.album);
	g_free (vd.album_artist);
	g_free (vd.performer);

	g_free (md.creator_uri);

#ifdef HAVE_POSIX_FADVISE
	posix_fadvise (fileno (f), 0, 0, POSIX_FADV_DONTNEED);
#endif /* HAVE_POSIX_FADVISE */

	/* NOTE: This calls fclose on the file */
	ov_clear (&vf);

	return TRUE;
}
Esempio n. 17
0
int ExportOGG::Export(AudacityProject *project,
                       int numChannels,
                       wxString fName,
                       bool selectionOnly,
                       double t0,
                       double t1,
                       MixerSpec *mixerSpec,
                       Tags *metadata,
                       int WXUNUSED(subformat))
{
   double    rate    = project->GetRate();
   TrackList *tracks = project->GetTracks();
   double    quality = (gPrefs->Read(wxT("/FileFormats/OggExportQuality"), 50)/(float)100.0);

   wxLogNull logNo;            // temporarily disable wxWidgets error messages
   int updateResult = eProgressSuccess;
   int       eos = 0;

   FileIO outFile(fName, FileIO::Output);

   if (!outFile.IsOpened()) {
      wxMessageBox(_("Unable to open target file for writing"));
      return false;
   }

   // All the Ogg and Vorbis encoding data
   ogg_stream_state stream;
   ogg_page         page;
   ogg_packet       packet;

   vorbis_info      info;
   vorbis_comment   comment;
   vorbis_dsp_state dsp;
   vorbis_block     block;

   // Encoding setup
   vorbis_info_init(&info);
   vorbis_encode_init_vbr(&info, numChannels, int(rate + 0.5), quality);

   // Retrieve tags
   if (!FillComment(project, &comment, metadata)) {
      return false;
   }

   // Set up analysis state and auxiliary encoding storage
   vorbis_analysis_init(&dsp, &info);
   vorbis_block_init(&dsp, &block);

   // Set up packet->stream encoder.  According to encoder example,
   // a random serial number makes it more likely that you can make
   // chained streams with concatenation.
   srand(time(NULL));
   ogg_stream_init(&stream, rand());

   // First we need to write the required headers:
   //    1. The Ogg bitstream header, which contains codec setup params
   //    2. The Vorbis comment header
   //    3. The bitstream codebook.
   //
   // After we create those our responsibility is complete, libvorbis will
   // take care of any other ogg bistream constraints (again, according
   // to the example encoder source)
   ogg_packet bitstream_header;
   ogg_packet comment_header;
   ogg_packet codebook_header;

   vorbis_analysis_headerout(&dsp, &comment, &bitstream_header, &comment_header,
         &codebook_header);

   // Place these headers into the stream
   ogg_stream_packetin(&stream, &bitstream_header);
   ogg_stream_packetin(&stream, &comment_header);
   ogg_stream_packetin(&stream, &codebook_header);

   // Flushing these headers now guarentees that audio data will
   // start on a new page, which apparently makes streaming easier
   while (ogg_stream_flush(&stream, &page)) {
      outFile.Write(page.header, page.header_len);
      outFile.Write(page.body, page.body_len);
   }

   int numWaveTracks;
   WaveTrack **waveTracks;
   tracks->GetWaveTracks(selectionOnly, &numWaveTracks, &waveTracks);
   Mixer *mixer = CreateMixer(numWaveTracks, waveTracks,
                            tracks->GetTimeTrack(),
                            t0, t1,
                            numChannels, SAMPLES_PER_RUN, false,
                            rate, floatSample, true, mixerSpec);
   delete [] waveTracks;

   ProgressDialog *progress = new ProgressDialog(wxFileName(fName).GetName(),
      selectionOnly ?
      _("Exporting the selected audio as Ogg Vorbis") :
      _("Exporting the entire project as Ogg Vorbis"));

   while (updateResult == eProgressSuccess && !eos) {
      float **vorbis_buffer = vorbis_analysis_buffer(&dsp, SAMPLES_PER_RUN);
      sampleCount samplesThisRun = mixer->Process(SAMPLES_PER_RUN);

      if (samplesThisRun == 0) {
         // Tell the library that we wrote 0 bytes - signalling the end.
         vorbis_analysis_wrote(&dsp, 0);
      }
      else {

         for (int i = 0; i < numChannels; i++) {
            float *temp = (float *)mixer->GetBuffer(i);
            memcpy(vorbis_buffer[i], temp, sizeof(float)*SAMPLES_PER_RUN);
         }

         // tell the encoder how many samples we have
         vorbis_analysis_wrote(&dsp, samplesThisRun);
      }

      // I don't understand what this call does, so here is the comment
      // from the example, verbatim:
      //
      //    vorbis does some data preanalysis, then divvies up blocks
      //    for more involved (potentially parallel) processing. Get
      //    a single block for encoding now
      while (vorbis_analysis_blockout(&dsp, &block) == 1) {

         // analysis, assume we want to use bitrate management
         vorbis_analysis(&block, NULL);
         vorbis_bitrate_addblock(&block);

         while (vorbis_bitrate_flushpacket(&dsp, &packet)) {

            // add the packet to the bitstream
            ogg_stream_packetin(&stream, &packet);

            // From vorbis-tools-1.0/oggenc/encode.c:
            //   If we've gone over a page boundary, we can do actual output,
            //   so do so (for however many pages are available).

            while (!eos) {
               int result = ogg_stream_pageout(&stream, &page);
               if (!result) {
                  break;
               }

               outFile.Write(page.header, page.header_len);
               outFile.Write(page.body, page.body_len);

               if (ogg_page_eos(&page)) {
                  eos = 1;
               }
            }
         }
      }

      updateResult = progress->Update(mixer->MixGetCurrentTime()-t0, t1-t0);
   }

   delete progress;;

   delete mixer;

   ogg_stream_clear(&stream);

   vorbis_block_clear(&block);
   vorbis_dsp_clear(&dsp);
   vorbis_info_clear(&info);
   vorbis_comment_clear(&comment);

   outFile.Close();

   return updateResult;
}
Esempio n. 18
0
xtr_oggvorbis_c::~xtr_oggvorbis_c() {
  vorbis_info_clear(&m_vorbis_info);
  vorbis_comment_clear(&m_vorbis_comment);
}
Esempio n. 19
0
int OggDec::DecodeOGG(char *inmemory,int inmemsize,
                char *outmemory,int outmemsize,int *done)
{
	char	*buffer;
	int		i;

	*done = 0;
	if(leakSize){
		if(outmemsize >= leakSize){
			memcpy(outmemory,leak_mem,leakSize);
			*done = leakSize;
			free(leak_mem);
			leak_mem = NULL;
			leakSize = 0;
			allocMemSize = 0;
		}else{
			memcpy(outmemory,leak_mem,outmemsize);
			*done = outmemsize;
			memmove(leak_mem,leak_mem+outmemsize,leakSize-outmemsize);
			leakSize -= outmemsize;
		}
		if(inmemsize==0) return (OGG_DEC_CONTINUE);
	}
	if(0==decStep){
		eos = 0;
		buffer=ogg_sync_buffer(&oy,4096);
		memcpy(buffer,inmemory,inmemsize);
		ogg_sync_wrote(&oy,inmemsize);
		if(ogg_sync_pageout(&oy,&og)!=1){
			if(inmemsize<4096){
				Clear_ogg();
				return(OGG_DEC_END);
			}
			return(OGG_DEC_ERR);
		}
		ogg_stream_init(&os,ogg_page_serialno(&og));
		vorbis_info_init(&vi);
		vorbis_comment_init(&vc);
		if(ogg_stream_pagein(&os,&og)<0){ 
			return(OGG_DEC_ERR);
		}
		if(ogg_stream_packetout(&os,&op)!=1){ 
			return(OGG_DEC_ERR);
		}
		if(vorbis_synthesis_headerin(&vi,&vc,&op)<0){ 
			return(OGG_DEC_ERR);
		}
		wfmt.wFormatTag = WAVE_FORMAT_PCM;
		wfmt.nChannels = vi.channels;
		wfmt.wBitsPerSample = 16;
		wfmt.nSamplesPerSec = vi.rate;
		wfmt.nBlockAlign = wfmt.nChannels * (wfmt.wBitsPerSample/8);
		wfmt.nAvgBytesPerSec = wfmt.nSamplesPerSec * wfmt.nBlockAlign;
		wfmt.cbSize = 0;
		bWaveGet = TRUE;
		decStep = 1;
		d1loop=0;
		return (OGG_DEC_CONTINUE);
	}
	if(1==decStep){
		while(d1loop<2){
			while(d1loop<2){
				int result=ogg_sync_pageout(&oy,&og);
				if(result==0)break;
				if(result==1){
					ogg_stream_pagein(&os,&og);
					while(d1loop<2){
						result=ogg_stream_packetout(&os,&op);
						if(result==0)break;
						if(result<0){
							return(OGG_DEC_ERR);
						}
						vorbis_synthesis_headerin(&vi,&vc,&op);
						d1loop++;
					}
				}
			}
			buffer=ogg_sync_buffer(&oy,4096);
			memcpy(buffer,inmemory,inmemsize);
			if(inmemsize==0 && d1loop<2){
				return(OGG_DEC_ERR);
			}
			ogg_sync_wrote(&oy,inmemsize);
			if(d1loop<2)
				return (OGG_DEC_CONTINUE);
		}
		decStep = 2;
		convsize=4096/vi.channels;
		vorbis_synthesis_init(&vd,&vi);
		vorbis_block_init(&vd,&vb);
		return (OGG_DEC_CONTINUE);
	}
	while(!eos){
	  while(!eos){
		int result=ogg_sync_pageout(&oy,&og);
		if(result==0)break;
		if(result<0){
		}else{
			ogg_stream_pagein(&os,&og);
			while(1){
				result=ogg_stream_packetout(&os,&op);
				if(result==0)break;
				if(result<0){
				}else{
					float **pcm;
					int samples;
		  
					if(vorbis_synthesis(&vb,&op)==0)
						vorbis_synthesis_blockin(&vd,&vb);
					while((samples=vorbis_synthesis_pcmout(&vd,&pcm))>0){
						int j;
						int clipflag=0;
						int bout=(samples<convsize?samples:convsize);
		
						for(i=0;i<vi.channels;i++){
							ogg_int16_t *ptr=convbuffer+i;
							float  *mono=pcm[i];
							for(j=0;j<bout;j++){
#if 1
								int val=int(mono[j]*32767.f);
#else
								int val=mono[j]*32767.f+drand48()-0.5f;
#endif
								if(val>32767){
								  val=32767;
								  clipflag=1;
								}
								if(val<-32768){
								  val=-32768;
								  clipflag=1;
								}
								*ptr=val;
								ptr+=(vi.channels);
							}
						}
						if(NULL==leak_mem){
							if(outmemsize >= (*done +2*vi.channels*bout)){
								memcpy(outmemory+(*done),convbuffer,2*vi.channels*bout);
								*done += 2*vi.channels*bout;
							}else{
								allocMemSize = 0x100000;
								leak_mem = (char *)malloc(allocMemSize);
							}
						}
						if(leak_mem){
							if(allocMemSize < (leakSize + 2*vi.channels*bout)){
								allocMemSize += 0x100000;
								realloc(leak_mem,allocMemSize);
							}
							memcpy(leak_mem+leakSize,convbuffer,2*vi.channels*bout);
							leakSize += 2*vi.channels*bout;
						}
						vorbis_synthesis_read(&vd,bout);
					}	    
				}
			}
			if(ogg_page_eos(&og))eos=1;
		}
	  }
	  if(!eos){
		buffer=ogg_sync_buffer(&oy,4096);
		memcpy(buffer,inmemory,inmemsize);
		ogg_sync_wrote(&oy,inmemsize);
		if(inmemsize==0) eos=1;
		return (OGG_DEC_CONTINUE);
	  }
	}
	if(bLoop){
		eos = 0;
		return OGG_DEC_REPLAY;
	}
	ogg_stream_clear(&os);
	vorbis_block_clear(&vb);
	vorbis_dsp_clear(&vd);
	vorbis_comment_clear(&vc);
	vorbis_info_clear(&vi);
	decStep = 0;

	return (OGG_DEC_CONTINUE);
}
Esempio n. 20
0
void VideoStreamPlaybackTheora::set_file(const String& p_file) {

	ERR_FAIL_COND(playing);
	ogg_packet op;
	th_setup_info    *ts = NULL;

	file_name = p_file;
	if (file) {
		memdelete(file);
	}
	file = FileAccess::open(p_file, FileAccess::READ);
	ERR_FAIL_COND(!file);

#ifdef THEORA_USE_THREAD_STREAMING
	thread_exit=false;
	thread_eof=false;
	//pre-fill buffer
	int to_read = ring_buffer.space_left();
	int read = file->get_buffer(read_buffer.ptr(),to_read);
	ring_buffer.write(read_buffer.ptr(),read);

	thread=Thread::create(_streaming_thread,this);

#endif

	ogg_sync_init(&oy);

	/* init supporting Vorbis structures needed in header parsing */
	vorbis_info_init(&vi);
	vorbis_comment_init(&vc);

	/* init supporting Theora structures needed in header parsing */
	th_comment_init(&tc);
	th_info_init(&ti);

	theora_eos=false;
	vorbis_eos=false;

	/* Ogg file open; parse the headers */
	/* Only interested in Vorbis/Theora streams */
	int stateflag = 0;

	int audio_track_skip=audio_track;


	while(!stateflag){
		int ret=buffer_data();
		if(ret==0)break;
		while(ogg_sync_pageout(&oy,&og)>0){
			ogg_stream_state test;

			/* is this a mandated initial header? If not, stop parsing */
			if(!ogg_page_bos(&og)){
				/* don't leak the page; get it into the appropriate stream */
				queue_page(&og);
				stateflag=1;
				break;
			}

			ogg_stream_init(&test,ogg_page_serialno(&og));
			ogg_stream_pagein(&test,&og);
			ogg_stream_packetout(&test,&op);


			/* identify the codec: try theora */
			if(!theora_p && th_decode_headerin(&ti,&tc,&ts,&op)>=0){
				/* it is theora */
				copymem(&to,&test,sizeof(test));
				theora_p=1;
			}else if(!vorbis_p && vorbis_synthesis_headerin(&vi,&vc,&op)>=0){


				/* it is vorbis */
				if (audio_track_skip) {
					vorbis_info_clear(&vi);
					vorbis_comment_clear(&vc);
					ogg_stream_clear(&test);
					vorbis_info_init(&vi);
					vorbis_comment_init(&vc);

					audio_track_skip--;
				} else {
                                        copymem(&vo,&test,sizeof(test));
					vorbis_p=1;
				}
			}else{
				/* whatever it is, we don't care about it */
				ogg_stream_clear(&test);
			}
		}
		/* fall through to non-bos page parsing */
	}

	/* we're expecting more header packets. */
	while((theora_p && theora_p<3) || (vorbis_p && vorbis_p<3)){
		int ret;

		/* look for further theora headers */
		while(theora_p && (theora_p<3) && (ret=ogg_stream_packetout(&to,&op))){
			if(ret<0){
				fprintf(stderr,"Error parsing Theora stream headers; "
						"corrupt stream?\n");
				clear();
				return;
			}
			if(!th_decode_headerin(&ti,&tc,&ts,&op)){
				fprintf(stderr,"Error parsing Theora stream headers; "
						"corrupt stream?\n");
				clear();
				return;
			}
			theora_p++;
		}

		/* look for more vorbis header packets */
		while(vorbis_p && (vorbis_p<3) && (ret=ogg_stream_packetout(&vo,&op))){
			if(ret<0){
				fprintf(stderr,"Error parsing Vorbis stream headers; corrupt stream?\n");
				clear();
				return;
			}
			ret = vorbis_synthesis_headerin(&vi,&vc,&op);
			if(ret){
				fprintf(stderr,"Error parsing Vorbis stream headers; corrupt stream?\n");
				clear();
				return;
			}
			vorbis_p++;
			if(vorbis_p==3)break;
		}

		/* The header pages/packets will arrive before anything else we
		care about, or the stream is not obeying spec */

		if(ogg_sync_pageout(&oy,&og)>0){
			queue_page(&og); /* demux into the appropriate stream */
		}else{
			int ret=buffer_data(); /* someone needs more data */
			if(ret==0){
				fprintf(stderr,"End of file while searching for codec headers.\n");
				clear();
				return;
			}
		}
	}

	/* and now we have it all.  initialize decoders */
	if(theora_p){
		td=th_decode_alloc(&ti,ts);
		printf("Ogg logical stream %lx is Theora %dx%d %.02f fps",
			   to.serialno,ti.pic_width,ti.pic_height,
			   (double)ti.fps_numerator/ti.fps_denominator);
		px_fmt=ti.pixel_fmt;
		switch(ti.pixel_fmt){
		case TH_PF_420: printf(" 4:2:0 video\n"); break;
		case TH_PF_422: printf(" 4:2:2 video\n"); break;
		case TH_PF_444: printf(" 4:4:4 video\n"); break;
		case TH_PF_RSVD:
		default:
			printf(" video\n  (UNKNOWN Chroma sampling!)\n");
			break;
		}
		if(ti.pic_width!=ti.frame_width || ti.pic_height!=ti.frame_height)
			printf("  Frame content is %dx%d with offset (%d,%d).\n",
				   ti.frame_width, ti.frame_height, ti.pic_x, ti.pic_y);
		th_decode_ctl(td,TH_DECCTL_GET_PPLEVEL_MAX,&pp_level_max,
					  sizeof(pp_level_max));
		pp_level=pp_level_max;
		pp_level=0;
		th_decode_ctl(td,TH_DECCTL_SET_PPLEVEL,&pp_level,sizeof(pp_level));
		pp_inc=0;

		/*{
		int arg = 0xffff;
		th_decode_ctl(td,TH_DECCTL_SET_TELEMETRY_MBMODE,&arg,sizeof(arg));
		th_decode_ctl(td,TH_DECCTL_SET_TELEMETRY_MV,&arg,sizeof(arg));
		th_decode_ctl(td,TH_DECCTL_SET_TELEMETRY_QI,&arg,sizeof(arg));
		arg=10;
		th_decode_ctl(td,TH_DECCTL_SET_TELEMETRY_BITS,&arg,sizeof(arg));
		}*/

		int w;
		int h;
		w=(ti.pic_x+ti.frame_width+1&~1)-(ti.pic_x&~1);
		h=(ti.pic_y+ti.frame_height+1&~1)-(ti.pic_y&~1);
		size.x = w;
		size.y = h;

		texture->create(w,h,Image::FORMAT_RGBA,Texture::FLAG_FILTER|Texture::FLAG_VIDEO_SURFACE);

	}else{
		/* tear down the partial theora setup */
		th_info_clear(&ti);
		th_comment_clear(&tc);
	}

	th_setup_free(ts);

	if(vorbis_p){
		vorbis_synthesis_init(&vd,&vi);
		vorbis_block_init(&vd,&vb);
		fprintf(stderr,"Ogg logical stream %lx is Vorbis %d channel %ld Hz audio.\n",
				vo.serialno,vi.channels,vi.rate);
		//_setup(vi.channels, vi.rate);

	}else{
		/* tear down the partial vorbis setup */
		vorbis_info_clear(&vi);
		vorbis_comment_clear(&vc);
	}

	playing = false;
	buffering=true;
	time=0;
	audio_frames_wrote=0;


};
Esempio n. 21
0
/*!
 * \brief Create a new OGG/Vorbis filestream and set it up for reading.
 * \param fd Descriptor that points to on disk storage of the OGG/Vorbis data.
 * \return The new filestream.
 */
static struct cw_filestream *ogg_vorbis_open(FILE *fp)
{
    int i;
    int bytes;
    int result;
    char **ptr;
    char *buffer;

    struct cw_filestream *tmp;

    if ((tmp = malloc(sizeof(struct cw_filestream))))
    {
        memset(tmp, 0, sizeof(struct cw_filestream));

        tmp->writing = 0;
        tmp->fp = fp;

        ogg_sync_init(&tmp->oy);

        buffer = ogg_sync_buffer(&tmp->oy, BLOCK_SIZE);
        bytes = fread(buffer, 1, BLOCK_SIZE, tmp->fp);

        ogg_sync_wrote(&tmp->oy, bytes);

        result = ogg_sync_pageout(&tmp->oy, &tmp->og);
        if (result != 1)
        {
            if (bytes < BLOCK_SIZE)
                cw_log(LOG_ERROR, "Run out of data... %d %s\n", errno, strerror(errno));
            else
                cw_log(LOG_ERROR, "Input does not appear to be an Ogg bitstream.\n");
            fclose(fp);
            ogg_sync_clear(&tmp->oy);
            free(tmp);
            return NULL;
        }
        
        ogg_stream_init(&tmp->os, ogg_page_serialno(&tmp->og));
        vorbis_info_init(&tmp->vi);
        vorbis_comment_init(&tmp->vc);

        if (ogg_stream_pagein(&tmp->os, &tmp->og) < 0)
        {
            cw_log(LOG_ERROR, "Error reading first page of Ogg bitstream data.\n");
            fclose(fp);
            ogg_stream_clear(&tmp->os);
            vorbis_comment_clear(&tmp->vc);
            vorbis_info_clear(&tmp->vi);
            ogg_sync_clear(&tmp->oy);
            free(tmp);
            return NULL;
        }
        
        if (ogg_stream_packetout(&tmp->os, &tmp->op) != 1)
        { 
            cw_log(LOG_ERROR, "Error reading initial header packet.\n");
            fclose(fp);
            ogg_stream_clear(&tmp->os);
            vorbis_comment_clear(&tmp->vc);
            vorbis_info_clear(&tmp->vi);
            ogg_sync_clear(&tmp->oy);
            free(tmp);
            return NULL;
        }
        
        if (vorbis_synthesis_headerin(&tmp->vi, &tmp->vc, &tmp->op) < 0)
        { 
            cw_log(LOG_ERROR, "This Ogg bitstream does not contain Vorbis audio data.\n");
            fclose(fp);
            ogg_stream_clear(&tmp->os);
            vorbis_comment_clear(&tmp->vc);
            vorbis_info_clear(&tmp->vi);
            ogg_sync_clear(&tmp->oy);
            free(tmp);
            return NULL;
        }
        
        i = 0;
        while (i < 2)
        {
            while (i < 2)
            {
                result = ogg_sync_pageout(&tmp->oy, &tmp->og);
                if (result == 0)
                    break;
                if (result == 1)
                {
                    ogg_stream_pagein(&tmp->os, &tmp->og);
                    while (i < 2)
                    {
                        result = ogg_stream_packetout(&tmp->os,&tmp->op);
                        if (result == 0)
                            break;
                        if (result < 0)
                        {
                            cw_log(LOG_ERROR, "Corrupt secondary header.  Exiting.\n");
                            fclose(fp);
                            ogg_stream_clear(&tmp->os);
                            vorbis_comment_clear(&tmp->vc);
                            vorbis_info_clear(&tmp->vi);
                            ogg_sync_clear(&tmp->oy);
                            free(tmp);
                            return NULL;
                        }
                        vorbis_synthesis_headerin(&tmp->vi, &tmp->vc, &tmp->op);
                        i++;
                    }
                }
            }

            buffer = ogg_sync_buffer(&tmp->oy, BLOCK_SIZE);
            bytes = fread(buffer, 1, BLOCK_SIZE, tmp->fp);
            if (bytes == 0  &&  i < 2)
            {
                cw_log(LOG_ERROR, "End of file before finding all Vorbis headers!\n");
                fclose(fp);
                ogg_stream_clear(&tmp->os);
                vorbis_comment_clear(&tmp->vc);
                vorbis_info_clear(&tmp->vi);
                ogg_sync_clear(&tmp->oy);
                free(tmp);
                return NULL;
            }
            ogg_sync_wrote(&tmp->oy, bytes);
        }
        
        ptr = tmp->vc.user_comments;
        while (*ptr)
        {
            cw_log(LOG_DEBUG, "OGG/Vorbis comment: %s\n", *ptr);
            ++ptr;
        }
        cw_log(LOG_DEBUG, "OGG/Vorbis bitstream is %d channel, %ldHz\n", tmp->vi.channels, tmp->vi.rate);
        cw_log(LOG_DEBUG, "OGG/Vorbis file encoded by: %s\n", tmp->vc.vendor);

        if (tmp->vi.channels != 1)
        {
            cw_log(LOG_ERROR, "Only monophonic OGG/Vorbis files are currently supported!\n");
            ogg_stream_clear(&tmp->os);
            vorbis_comment_clear(&tmp->vc);
            vorbis_info_clear(&tmp->vi);
            ogg_sync_clear(&tmp->oy);
            free(tmp);
            return NULL;
        }
        

        if (tmp->vi.rate != 8000)
        {
            cw_log(LOG_ERROR, "Only 8000Hz OGG/Vorbis files are currently supported!\n");
            fclose(fp);
            ogg_stream_clear(&tmp->os);
            vorbis_block_clear(&tmp->vb);
            vorbis_dsp_clear(&tmp->vd);
            vorbis_comment_clear(&tmp->vc);
            vorbis_info_clear(&tmp->vi);
            ogg_sync_clear(&tmp->oy);
            free(tmp);
            return NULL;
        }
        
        vorbis_synthesis_init(&tmp->vd, &tmp->vi);
        vorbis_block_init(&tmp->vd, &tmp->vb);

        if (cw_mutex_lock(&ogg_vorbis_lock))
        {
            cw_log(LOG_WARNING, "Unable to lock ogg_vorbis list\n");
            fclose(fp);
            ogg_stream_clear(&tmp->os);
            vorbis_block_clear(&tmp->vb);
            vorbis_dsp_clear(&tmp->vd);
            vorbis_comment_clear(&tmp->vc);
            vorbis_info_clear(&tmp->vi);
            ogg_sync_clear(&tmp->oy);
            free(tmp);
            return NULL;
        }
        glistcnt++;
        cw_mutex_unlock(&ogg_vorbis_lock);
        cw_update_use_count();
    }
    return tmp;
}
/**
    \fn initialize

*/
uint8_t AUDMEncoder_Vorbis::initialize(void)
{
  int ret;
  VORBIS_encoderParam *vorbisConf=&vorbisParam;
  

  ogg_packet header1,header2,header3;
  int err;

  
  
  vorbis_info_init(&VI) ;

  switch(vorbisConf->mode)
  {
    
    case ADM_VORBIS_VBR:
                      err=vorbis_encode_init(&VI,
                              _wavheader->channels,
                              _wavheader->frequency,
                              -1, // Max bitrate      
                              vorbisConf->bitrate*1000, //long nominal_bitrate,
                              -1 //long min_bitrate))
                            );
                      break;
    case  ADM_VORBIS_QUALITY :
                    err=vorbis_encode_init_vbr(&VI,
                                _wavheader->channels,
                                _wavheader->frequency,
                                vorbisConf->quality/10
                              );
                    break;
      
    default:
      ADM_assert(0);
  }
  if (err!=0) 
  {
	  delete (vorbisStruct*)_handle;
	  _handle = NULL;

    printf("[vorbis] init error %d\n",err);
    return 0;
  }
  vorbis_analysis_init(&VD, &VI) ;
  vorbis_block_init(&VD, &VB);
  vorbis_comment_init(&VC);
  vorbis_comment_add_tag(&VC, "encoder", "AVIDEMUX2") ;

  vorbis_analysis_headerout(&VD, &VC, &header1,
                             &header2, &header3);


// Store all headers as extra data
// see ogg vorbis decode for details
// we need 3 packets

  _extraSize=header1.bytes+header2.bytes+header3.bytes+3*sizeof(uint32_t);
  _extraData=new uint8_t[_extraSize];

  uint32_t *ex=(uint32_t *)_extraData;
  uint8_t *d;
  d=_extraData+sizeof(uint32_t)*3;
  ex[0]=header1.bytes;
  ex[1]=header2.bytes;
  ex[2]=header3.bytes;
  memcpy(d,header1.packet,ex[0]);
  d+=ex[0];
  memcpy(d,header2.packet,ex[1]);
  d+=ex[1];
  memcpy(d,header3.packet,ex[2]);
  vorbis_comment_clear(&VC);
			
  printf("\n[Vorbis]Vorbis encoder initialized\n");
  switch(vorbisConf->mode)
  {
    case ADM_VORBIS_VBR:
      printf("[Vorbis]CBR Bitrate:%lu\n",vorbisConf->bitrate);
      break;
    case ADM_VORBIS_QUALITY: //FIXME FIXME FIXME
      printf("[Vorbis]VBR Quality:%.1f\n",vorbisConf->quality);
    break;
    default:
      ADM_assert(0);
  }
   
  printf("[Vorbis]Channels  :%lu\n",_wavheader->channels);
  printf("[Vorbis]Frequency :%lu\n",_wavheader->frequency);
  return 1;
}
Esempio n. 23
0
int main(int argc,char *argv[]){
  int c,long_option_index,ret;

  ogg_stream_state to; /* take physical pages, weld into a logical
                           stream of packets */
  ogg_stream_state vo; /* take physical pages, weld into a logical
                           stream of packets */
  ogg_page         og; /* one Ogg bitstream page.  Vorbis packets are inside */
  ogg_packet       op; /* one raw packet of data for decode */

  theora_state     td;
  theora_info      ti;
  theora_comment   tc;

  vorbis_info      vi; /* struct that stores all the static vorbis bitstream
                          settings */
  vorbis_comment   vc; /* struct that stores all the user comments */

  vorbis_dsp_state vd; /* central working state for the packet->PCM decoder */
  vorbis_block     vb; /* local working space for packet->PCM decode */

  int audioflag=0;
  int videoflag=0;
  int akbps=0;
  int vkbps=0;

  ogg_int64_t audio_bytesout=0;
  ogg_int64_t video_bytesout=0;
  double timebase;


  FILE* outfile = stdout;

#ifdef _WIN32 
# ifdef THEORA_PERF_DATA
    LARGE_INTEGER start_time;
    LARGE_INTEGER final_time;

    LONGLONG elapsed_ticks;
    LARGE_INTEGER ticks_per_second;
    
    LONGLONG elapsed_secs;
    LONGLONG elapsed_sec_mod;
    double elapsed_secs_dbl ;
# endif
  /* We need to set stdin/stdout to binary mode. Damn windows. */
  /* if we were reading/writing a file, it would also need to in
     binary mode, eg, fopen("file.wav","wb"); */
  /* Beware the evil ifdef. We avoid these where we can, but this one we
     cannot. Don't add any more, you'll probably go to hell if you do. */
  _setmode( _fileno( stdin ), _O_BINARY );
  _setmode( _fileno( stdout ), _O_BINARY );


#endif

  while((c=getopt_long(argc,argv,optstring,options,&long_option_index))!=EOF){
    switch(c){
    case 'o':
      outfile=fopen(optarg,"wb");
      if(outfile==NULL){
        fprintf(stderr,"Unable to open output file '%s'\n", optarg);
        exit(1);
      }
      break;;

    case 'a':
      audio_q=atof(optarg)*.099;
      if(audio_q<-.1 || audio_q>1){
        fprintf(stderr,"Illegal audio quality (choose -1 through 10)\n");
        exit(1);
      }
      audio_r=-1;
      break;

    case 'v':
      video_q=rint(atof(optarg)*6.3);
      if(video_q<0 || video_q>63){
        fprintf(stderr,"Illegal video quality (choose 0 through 10)\n");
        exit(1);
      }
      video_r=0;
      break;

    case 'A':
      audio_r=atof(optarg)*1000;
      if(audio_q<0){
        fprintf(stderr,"Illegal audio quality (choose > 0 please)\n");
        exit(1);
      }
      audio_q=-99;
      break;

    case 'V':
      video_r=rint(atof(optarg)*1000);
      if(video_r<45000 || video_r>2000000){
        fprintf(stderr,"Illegal video bitrate (choose 45kbps through 2000kbps)\n");
        exit(1);
      }
      video_q=0;
     break;

    case 's':
      video_an=rint(atof(optarg));
      break;

    case 'S':
      video_ad=rint(atof(optarg));
      break;

    case 'f':
      video_hzn=rint(atof(optarg));
      break;

    case 'F':
      video_hzd=rint(atof(optarg));
      break;

    default:
      usage();
    }
  }

  while(optind<argc){
    /* assume that anything following the options must be a filename */
    id_file(argv[optind]);
    optind++;
  }



#ifdef THEORA_PERF_DATA
# ifdef WIN32
    QueryPerformanceCounter(&start_time);
# endif
#endif


  /* yayness.  Set up Ogg output stream */
  srand(time(NULL));
  {
    /* need two inequal serial numbers */
    int serial1, serial2;
    serial1 = rand();
    serial2 = rand();
    if (serial1 == serial2) serial2++;
    ogg_stream_init(&to,serial1);
    ogg_stream_init(&vo,serial2);
  }

  /* Set up Theora encoder */
  if(!video){
    fprintf(stderr,"No video files submitted for compression?\n");
    exit(1);
  }
  /* Theora has a divisible-by-sixteen restriction for the encoded video size */
  /* scale the frame size up to the nearest /16 and calculate offsets */
  video_x=((frame_x + 15) >>4)<<4;
  video_y=((frame_y + 15) >>4)<<4;
  /* We force the offset to be even.
     This ensures that the chroma samples align properly with the luma
      samples. */
  frame_x_offset=((video_x-frame_x)/2)&~1;
  frame_y_offset=((video_y-frame_y)/2)&~1;

  theora_info_init(&ti);
  ti.width=video_x;
  ti.height=video_y;
  ti.frame_width=frame_x;
  ti.frame_height=frame_y;
  ti.offset_x=frame_x_offset;
  ti.offset_y=frame_y_offset;
  ti.fps_numerator=video_hzn;
  ti.fps_denominator=video_hzd;
  ti.aspect_numerator=video_an;
  ti.aspect_denominator=video_ad;
  ti.colorspace=OC_CS_UNSPECIFIED;
  ti.pixelformat=OC_PF_420;
  ti.target_bitrate=video_r;
  ti.quality=video_q;

  ti.dropframes_p=0;
  ti.quick_p=1;
  ti.keyframe_auto_p=1;
  ti.keyframe_frequency=64;
  ti.keyframe_frequency_force=64;
  ti.keyframe_data_target_bitrate=video_r*1.5;
  ti.keyframe_auto_threshold=80;
  ti.keyframe_mindistance=8;
  ti.noise_sensitivity=1;

  theora_encode_init(&td,&ti);
  theora_info_clear(&ti);

  /* initialize Vorbis too, assuming we have audio to compress. */
  if(audio){
    vorbis_info_init(&vi);
    if(audio_q>-99)
      ret = vorbis_encode_init_vbr(&vi,audio_ch,audio_hz,audio_q);
    else
      ret = vorbis_encode_init(&vi,audio_ch,audio_hz,-1,audio_r,-1);
    if(ret){
      fprintf(stderr,"The Vorbis encoder could not set up a mode according to\n"
              "the requested quality or bitrate.\n\n");
      exit(1);
    }

    vorbis_comment_init(&vc);
    vorbis_analysis_init(&vd,&vi);
    vorbis_block_init(&vd,&vb);
  }

  /* write the bitstream header packets with proper page interleave */

  /* first packet will get its own page automatically */
  theora_encode_header(&td,&op);
  ogg_stream_packetin(&to,&op);
  if(ogg_stream_pageout(&to,&og)!=1){
    fprintf(stderr,"Internal Ogg library error.\n");
    exit(1);
  }
  fwrite(og.header,1,og.header_len,outfile);
  fwrite(og.body,1,og.body_len,outfile);

  /* create the remaining theora headers */
  theora_comment_init(&tc);
  theora_encode_comment(&tc,&op);
  ogg_stream_packetin(&to,&op);
  /*theora_encode_comment() doesn't take a theora_state parameter, so it has to
     allocate its own buffer to pass back the packet data.
    If we don't free it here, we'll leak.
    libogg2 makes this much cleaner: the stream owns the buffer after you call
     packetin in libogg2, but this is not true in libogg1.*/
  free(op.packet);
  theora_encode_tables(&td,&op);
  ogg_stream_packetin(&to,&op);

  if(audio){
    ogg_packet header;
    ogg_packet header_comm;
    ogg_packet header_code;

    vorbis_analysis_headerout(&vd,&vc,&header,&header_comm,&header_code);
    ogg_stream_packetin(&vo,&header); /* automatically placed in its own
                                         page */
    if(ogg_stream_pageout(&vo,&og)!=1){
      fprintf(stderr,"Internal Ogg library error.\n");
      exit(1);
    }
    fwrite(og.header,1,og.header_len,outfile);
    fwrite(og.body,1,og.body_len,outfile);

    /* remaining vorbis header packets */
    ogg_stream_packetin(&vo,&header_comm);
    ogg_stream_packetin(&vo,&header_code);
  }

  /* Flush the rest of our headers. This ensures
     the actual data in each stream will start
     on a new page, as per spec. */
  while(1){
    int result = ogg_stream_flush(&to,&og);
      if(result<0){
        /* can't get here */
        fprintf(stderr,"Internal Ogg library error.\n");
        exit(1);
      }
    if(result==0)break;
    fwrite(og.header,1,og.header_len,outfile);
    fwrite(og.body,1,og.body_len,outfile);
  }
  if(audio){
    while(1){
      int result=ogg_stream_flush(&vo,&og);
      if(result<0){
        /* can't get here */
        fprintf(stderr,"Internal Ogg library error.\n");
        exit(1);
      }
      if(result==0)break;
      fwrite(og.header,1,og.header_len,outfile);
      fwrite(og.body,1,og.body_len,outfile);
    }
  }

  /* setup complete.  Raw processing loop */
  fprintf(stderr,"Compressing....\n");
  while(1){
    ogg_page audiopage;
    ogg_page videopage;

    /* is there an audio page flushed?  If not, fetch one if possible */
    audioflag=fetch_and_process_audio(audio,&audiopage,&vo,&vd,&vb,audioflag);

    /* is there a video page flushed?  If not, fetch one if possible */
    videoflag=fetch_and_process_video(video,&videopage,&to,&td,videoflag);

    /* no pages of either?  Must be end of stream. */
    if(!audioflag && !videoflag)break;

    /* which is earlier; the end of the audio page or the end of the
       video page? Flush the earlier to stream */
    {
      int audio_or_video=-1;
      double audiotime=
        audioflag?vorbis_granule_time(&vd,ogg_page_granulepos(&audiopage)):-1;
      double videotime=
        videoflag?theora_granule_time(&td,ogg_page_granulepos(&videopage)):-1;

      if(!audioflag){
        audio_or_video=1;
      } else if(!videoflag) {
        audio_or_video=0;
      } else {
        if(audiotime<videotime)
          audio_or_video=0;
        else
          audio_or_video=1;
      }

      if(audio_or_video==1){
        /* flush a video page */
        video_bytesout+=fwrite(videopage.header,1,videopage.header_len,outfile);
        video_bytesout+=fwrite(videopage.body,1,videopage.body_len,outfile);
        videoflag=0;
        timebase=videotime;
        
      }else{
        /* flush an audio page */
        audio_bytesout+=fwrite(audiopage.header,1,audiopage.header_len,outfile);
        audio_bytesout+=fwrite(audiopage.body,1,audiopage.body_len,outfile);
        audioflag=0;
        timebase=audiotime;
      }
      {
        int hundredths=timebase*100-(long)timebase*100;
        int seconds=(long)timebase%60;
        int minutes=((long)timebase/60)%60;
        int hours=(long)timebase/3600;
        
        if(audio_or_video)
          vkbps=rint(video_bytesout*8./timebase*.001);
        else
          akbps=rint(audio_bytesout*8./timebase*.001);
        
        fprintf(stderr,
                "\r      %d:%02d:%02d.%02d audio: %dkbps video: %dkbps                 ",
                hours,minutes,seconds,hundredths,akbps,vkbps);
      }
    }

  }

  /* clear out state */

  if(audio){
    ogg_stream_clear(&vo);
    vorbis_block_clear(&vb);
    vorbis_dsp_clear(&vd);
    vorbis_comment_clear(&vc);
    vorbis_info_clear(&vi);
  }
  if(video){
    ogg_stream_clear(&to);
    theora_clear(&td);
  }

  if(outfile && outfile!=stdout)fclose(outfile);

  fprintf(stderr,"\r   \ndone.\n\n");

#ifdef THEORA_PERF_DATA
# ifdef WIN32
    QueryPerformanceCounter(&final_time);
    elapsed_ticks = final_time.QuadPart - start_time.QuadPart;
    ticks_per_second;
    QueryPerformanceFrequency(&ticks_per_second);
    elapsed_secs = elapsed_ticks / ticks_per_second.QuadPart;
    elapsed_sec_mod = elapsed_ticks % ticks_per_second.QuadPart;
    elapsed_secs_dbl = elapsed_secs;
    elapsed_secs_dbl += ((double)elapsed_sec_mod / (double)ticks_per_second.QuadPart);
    printf("Encode time = %lld ticks\n", elapsed_ticks);
    printf("~%lld and %lld / %lld seconds\n", elapsed_secs, elapsed_sec_mod, ticks_per_second.QuadPart);
    printf("~%Lf seconds\n", elapsed_secs_dbl);
# endif

#endif 

  return(0);

}